summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile2
-rw-r--r--lib/efi_loader/efi_boottime.c174
-rw-r--r--lib/efi_loader/efi_console.c63
-rw-r--r--lib/efi_loader/efi_file.c10
-rw-r--r--lib/efi_loader/efi_gop.c89
-rw-r--r--lib/efi_loader/efi_hii.c49
-rw-r--r--lib/efi_loader/efi_memory.c8
-rw-r--r--lib/efi_loader/efi_runtime.c29
-rw-r--r--lib/efi_loader/efi_setup.c5
-rw-r--r--lib/efi_loader/efi_unicode_collation.c69
-rw-r--r--lib/efi_loader/efi_variable.c8
-rw-r--r--lib/efi_selftest/efi_selftest_event_groups.c9
-rw-r--r--lib/efi_selftest/efi_selftest_gop.c5
13 files changed, 318 insertions, 202 deletions
diff --git a/lib/Makefile b/lib/Makefile
index 09c45b81229..2fffd68f943 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -88,7 +88,7 @@ obj-y += crc32.o
obj-$(CONFIG_CRC32C) += crc32c.o
obj-y += ctype.o
obj-y += div64.o
-obj-$(CONFIG_OF_LIBFDT) += fdtdec.o
+obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdtdec.o fdtdec_common.o
obj-y += hang.o
obj-y += linux_compat.o
obj-y += linux_string.o
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 7d1d6e92138..d104cc6b316 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -27,6 +27,12 @@ LIST_HEAD(efi_obj_list);
/* List of all events */
LIST_HEAD(efi_events);
+/* List of queued events */
+LIST_HEAD(efi_event_queue);
+
+/* Flag to disable timer activity in ExitBootServices() */
+static bool timers_enabled = true;
+
/* List of all events registered by RegisterProtocolNotify() */
LIST_HEAD(efi_register_notify_events);
@@ -161,32 +167,75 @@ const char *__efi_nesting_dec(void)
}
/**
+ * efi_event_is_queued() - check if an event is queued
+ *
+ * @event: event
+ * Return: true if event is queued
+ */
+static bool efi_event_is_queued(struct efi_event *event)
+{
+ return !!event->queue_link.next;
+}
+
+/**
+ * efi_process_event_queue() - process event queue
+ */
+static void efi_process_event_queue(void)
+{
+ while (!list_empty(&efi_event_queue)) {
+ struct efi_event *event;
+ efi_uintn_t old_tpl;
+
+ event = list_first_entry(&efi_event_queue, struct efi_event,
+ queue_link);
+ if (efi_tpl >= event->notify_tpl)
+ return;
+ list_del(&event->queue_link);
+ event->queue_link.next = NULL;
+ event->queue_link.prev = NULL;
+ /* Events must be executed at the event's TPL */
+ old_tpl = efi_tpl;
+ efi_tpl = event->notify_tpl;
+ EFI_CALL_VOID(event->notify_function(event,
+ event->notify_context));
+ efi_tpl = old_tpl;
+ if (event->type == EVT_NOTIFY_SIGNAL)
+ event->is_signaled = 0;
+ }
+}
+
+/**
* efi_queue_event() - queue an EFI event
* @event: event to signal
- * @check_tpl: check the TPL level
*
* This function queues the notification function of the event for future
* execution.
*
- * The notification function is called if the task priority level of the event
- * is higher than the current task priority level.
- *
- * For the SignalEvent service see efi_signal_event_ext.
- *
*/
-static void efi_queue_event(struct efi_event *event, bool check_tpl)
+static void efi_queue_event(struct efi_event *event)
{
- if (event->notify_function) {
- event->is_queued = true;
- /* Check TPL */
- if (check_tpl && efi_tpl >= event->notify_tpl)
- return;
- event->is_queued = false;
- EFI_CALL_VOID(event->notify_function(event,
- event->notify_context));
- } else {
- event->is_queued = false;
+ struct efi_event *item = NULL;
+
+ if (!event->notify_function)
+ return;
+
+ if (!efi_event_is_queued(event)) {
+ /*
+ * Events must be notified in order of decreasing task priority
+ * level. Insert the new event accordingly.
+ */
+ list_for_each_entry(item, &efi_event_queue, queue_link) {
+ if (item->notify_tpl < event->notify_tpl) {
+ list_add_tail(&event->queue_link,
+ &item->queue_link);
+ event = NULL;
+ break;
+ }
+ }
+ if (event)
+ list_add_tail(&event->queue_link, &efi_event_queue);
}
+ efi_process_event_queue();
}
/**
@@ -211,7 +260,6 @@ efi_status_t is_valid_tpl(efi_uintn_t tpl)
/**
* efi_signal_event() - signal an EFI event
* @event: event to signal
- * @check_tpl: check the TPL level
*
* This function signals an event. If the event belongs to an event group all
* events of the group are signaled. If they are of type EVT_NOTIFY_SIGNAL
@@ -219,8 +267,10 @@ efi_status_t is_valid_tpl(efi_uintn_t tpl)
*
* For the SignalEvent service see efi_signal_event_ext.
*/
-void efi_signal_event(struct efi_event *event, bool check_tpl)
+void efi_signal_event(struct efi_event *event)
{
+ if (event->is_signaled)
+ return;
if (event->group) {
struct efi_event *evt;
@@ -234,20 +284,15 @@ void efi_signal_event(struct efi_event *event, bool check_tpl)
if (evt->is_signaled)
continue;
evt->is_signaled = true;
- if (evt->type & EVT_NOTIFY_SIGNAL &&
- evt->notify_function)
- evt->is_queued = true;
}
list_for_each_entry(evt, &efi_events, link) {
if (!evt->group || guidcmp(evt->group, event->group))
continue;
- if (evt->is_queued)
- efi_queue_event(evt, check_tpl);
+ efi_queue_event(evt);
}
} else {
event->is_signaled = true;
- if (event->type & EVT_NOTIFY_SIGNAL)
- efi_queue_event(event, check_tpl);
+ efi_queue_event(event);
}
}
@@ -637,8 +682,6 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
evt->group = group;
/* Disable timers on boot up */
evt->trigger_next = -1ULL;
- evt->is_queued = false;
- evt->is_signaled = false;
list_add_tail(&evt->link, &efi_events);
*event = evt;
return EFI_SUCCESS;
@@ -733,8 +776,8 @@ void efi_timer_check(void)
u64 now = timer_get_us();
list_for_each_entry(evt, &efi_events, link) {
- if (evt->is_queued)
- efi_queue_event(evt, true);
+ if (!timers_enabled)
+ continue;
if (!(evt->type & EVT_TIMER) || now < evt->trigger_next)
continue;
switch (evt->trigger_type) {
@@ -748,8 +791,9 @@ void efi_timer_check(void)
continue;
}
evt->is_signaled = false;
- efi_signal_event(evt, true);
+ efi_signal_event(evt);
}
+ efi_process_event_queue();
WATCHDOG_RESET();
}
@@ -850,7 +894,7 @@ static efi_status_t EFIAPI efi_wait_for_event(efi_uintn_t num_events,
if (!event[i]->type || event[i]->type & EVT_NOTIFY_SIGNAL)
return EFI_EXIT(EFI_INVALID_PARAMETER);
if (!event[i]->is_signaled)
- efi_queue_event(event[i], true);
+ efi_queue_event(event[i]);
}
/* Wait for signal */
@@ -894,7 +938,7 @@ static efi_status_t EFIAPI efi_signal_event_ext(struct efi_event *event)
EFI_ENTRY("%p", event);
if (efi_is_event(event) != EFI_SUCCESS)
return EFI_EXIT(EFI_INVALID_PARAMETER);
- efi_signal_event(event, true);
+ efi_signal_event(event);
return EFI_EXIT(EFI_SUCCESS);
}
@@ -933,6 +977,9 @@ static efi_status_t EFIAPI efi_close_event(struct efi_event *event)
free(item);
}
}
+ /* Remove event from queue */
+ if (efi_event_is_queued(event))
+ list_del(&event->queue_link);
list_del(&event->link);
free(event);
@@ -961,7 +1008,7 @@ static efi_status_t EFIAPI efi_check_event(struct efi_event *event)
event->type & EVT_NOTIFY_SIGNAL)
return EFI_EXIT(EFI_INVALID_PARAMETER);
if (!event->is_signaled)
- efi_queue_event(event, true);
+ efi_queue_event(event);
if (event->is_signaled) {
event->is_signaled = false;
return EFI_EXIT(EFI_SUCCESS);
@@ -1068,7 +1115,8 @@ efi_status_t efi_add_protocol(const efi_handle_t handle,
}
notif->handle = handle;
list_add_tail(&notif->link, &event->handles);
- efi_signal_event(event->event, true);
+ event->event->is_signaled = false;
+ efi_signal_event(event->event);
}
}
@@ -1593,7 +1641,7 @@ out:
/* Notify that the configuration table was changed */
list_for_each_entry(evt, &efi_events, link) {
if (evt->group && !guidcmp(evt->group, guid)) {
- efi_signal_event(evt, false);
+ efi_signal_event(evt);
break;
}
}
@@ -1731,7 +1779,7 @@ efi_status_t efi_load_image_from_path(struct efi_device_path *file_path,
/* Open file */
f = efi_file_from_path(file_path);
if (!f)
- return EFI_DEVICE_ERROR;
+ return EFI_NOT_FOUND;
/* Get file size */
bs = 0;
@@ -1808,17 +1856,10 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy,
EFI_ENTRY("%d, %p, %pD, %p, %zd, %p", boot_policy, parent_image,
file_path, source_buffer, source_size, image_handle);
- if (!image_handle || !efi_search_obj(parent_image)) {
- ret = EFI_INVALID_PARAMETER;
- goto error;
- }
-
- if (!source_buffer && !file_path) {
- ret = EFI_NOT_FOUND;
- goto error;
- }
- /* The parent image handle must refer to a loaded image */
- if (!parent_image->type) {
+ if (!image_handle || (!source_buffer && !file_path) ||
+ !efi_search_obj(parent_image) ||
+ /* The parent image handle must refer to a loaded image */
+ !parent_image->type) {
ret = EFI_INVALID_PARAMETER;
goto error;
}
@@ -1892,19 +1933,22 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
efi_uintn_t map_key)
{
struct efi_event *evt;
+ efi_status_t ret = EFI_SUCCESS;
EFI_ENTRY("%p, %zx", image_handle, map_key);
/* Check that the caller has read the current memory map */
- if (map_key != efi_memory_map_key)
- return EFI_INVALID_PARAMETER;
-
- /* Make sure that notification functions are not called anymore */
- efi_tpl = TPL_HIGH_LEVEL;
+ if (map_key != efi_memory_map_key) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
/* Check if ExitBootServices has already been called */
if (!systab.boottime)
- return EFI_EXIT(EFI_SUCCESS);
+ goto out;
+
+ /* Stop all timer related activities */
+ timers_enabled = false;
/* Add related events to the event group */
list_for_each_entry(evt, &efi_events, link) {
@@ -1916,11 +1960,14 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
if (evt->group &&
!guidcmp(evt->group,
&efi_guid_event_group_exit_boot_services)) {
- efi_signal_event(evt, false);
+ efi_signal_event(evt);
break;
}
}
+ /* Make sure that notification functions are not called anymore */
+ efi_tpl = TPL_HIGH_LEVEL;
+
/* TODO: Should persist EFI variables here */
board_quiesce_devices();
@@ -1946,8 +1993,8 @@ static efi_status_t EFIAPI efi_exit_boot_services(efi_handle_t image_handle,
/* Give the payload some time to boot */
efi_set_watchdog(0);
WATCHDOG_RESET();
-
- return EFI_EXIT(EFI_SUCCESS);
+out:
+ return EFI_EXIT(ret);
}
/**
@@ -2819,6 +2866,9 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
EFI_ENTRY("%p, %p, %p", image_handle, exit_data_size, exit_data);
/* Check parameters */
+ if (image_obj->header.type != EFI_OBJECT_TYPE_LOADED_IMAGE)
+ return EFI_EXIT(EFI_INVALID_PARAMETER);
+
ret = EFI_CALL(efi_open_protocol(image_handle, &efi_guid_loaded_image,
&info, NULL, NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL));
@@ -3570,11 +3620,11 @@ struct efi_system_table __efi_runtime_data systab = {
},
.fw_vendor = firmware_vendor,
.fw_revision = FW_VERSION << 16 | FW_PATCHLEVEL << 8,
- .con_in = (void *)&efi_con_in,
- .con_out = (void *)&efi_con_out,
- .std_err = (void *)&efi_con_out,
- .runtime = (void *)&efi_runtime_services,
- .boottime = (void *)&efi_boot_services,
+ .con_in = &efi_con_in,
+ .con_out = &efi_con_out,
+ .std_err = &efi_con_out,
+ .runtime = &efi_runtime_services,
+ .boottime = &efi_boot_services,
.nr_tables = 0,
.tables = NULL,
};
diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c
index 3b7578f3aa4..6c8229da42a 100644
--- a/lib/efi_loader/efi_console.c
+++ b/lib/efi_loader/efi_console.c
@@ -316,23 +316,6 @@ static efi_status_t EFIAPI efi_cout_query_mode(
return EFI_EXIT(EFI_SUCCESS);
}
-static efi_status_t EFIAPI efi_cout_set_mode(
- struct efi_simple_text_output_protocol *this,
- unsigned long mode_number)
-{
- EFI_ENTRY("%p, %ld", this, mode_number);
-
-
- if (mode_number > efi_con_mode.max_mode)
- return EFI_EXIT(EFI_UNSUPPORTED);
-
- efi_con_mode.mode = mode_number;
- efi_con_mode.cursor_column = 0;
- efi_con_mode.cursor_row = 0;
-
- return EFI_EXIT(EFI_SUCCESS);
-}
-
static const struct {
unsigned int fg;
unsigned int bg;
@@ -358,6 +341,7 @@ static efi_status_t EFIAPI efi_cout_set_attribute(
EFI_ENTRY("%p, %lx", this, attribute);
+ efi_con_mode.attribute = attribute;
if (attribute)
printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg);
else
@@ -378,6 +362,20 @@ static efi_status_t EFIAPI efi_cout_clear_screen(
return EFI_EXIT(EFI_SUCCESS);
}
+static efi_status_t EFIAPI efi_cout_set_mode(
+ struct efi_simple_text_output_protocol *this,
+ unsigned long mode_number)
+{
+ EFI_ENTRY("%p, %ld", this, mode_number);
+
+ if (mode_number >= efi_con_mode.max_mode)
+ return EFI_EXIT(EFI_UNSUPPORTED);
+ efi_con_mode.mode = mode_number;
+ EFI_CALL(efi_cout_clear_screen(this));
+
+ return EFI_EXIT(EFI_SUCCESS);
+}
+
static efi_status_t EFIAPI efi_cout_reset(
struct efi_simple_text_output_protocol *this,
char extended_verification)
@@ -387,6 +385,7 @@ static efi_status_t EFIAPI efi_cout_reset(
/* Clear screen */
EFI_CALL(efi_cout_clear_screen(this));
/* Set default colors */
+ efi_con_mode.attribute = 0x07;
printf(ESC "[0;37;40m");
return EFI_EXIT(EFI_SUCCESS);
@@ -482,10 +481,8 @@ void set_shift_mask(int mod, struct efi_key_state *key_state)
key_state->key_shift_state |= EFI_LEFT_ALT_PRESSED;
if (mod & 4)
key_state->key_shift_state |= EFI_LEFT_CONTROL_PRESSED;
- if (mod & 8)
+ if (!mod || (mod & 8))
key_state->key_shift_state |= EFI_LEFT_LOGO_PRESSED;
- } else {
- key_state->key_shift_state |= EFI_LEFT_LOGO_PRESSED;
}
}
@@ -564,10 +561,13 @@ static efi_status_t efi_cin_read_key(struct efi_key_data *key)
case cESC: /* ESC */
pressed_key.scan_code = 23;
break;
- case 'O': /* F1 - F4 */
+ case 'O': /* F1 - F4, End */
ch = getc();
/* consider modifiers */
- if (ch < 'P') {
+ if (ch == 'F') { /* End */
+ pressed_key.scan_code = 6;
+ break;
+ } else if (ch < 'P') {
set_shift_mask(ch - '0', &key->key_state);
ch = getc();
}
@@ -591,17 +591,20 @@ static efi_status_t efi_cin_read_key(struct efi_key_data *key)
case '1'...'5': /* F1 - F5 */
pressed_key.scan_code = ch - '1' + 11;
break;
- case '7'...'9': /* F6 - F8 */
- pressed_key.scan_code = ch - '7' + 16;
+ case '6'...'9': /* F5 - F8 */
+ pressed_key.scan_code = ch - '6' + 15;
break;
case 'A'...'D': /* up, down right, left */
pressed_key.scan_code = ch - 'A' + 1;
break;
- case 'F':
- pressed_key.scan_code = 6; /* End */
+ case 'F': /* End */
+ pressed_key.scan_code = 6;
+ break;
+ case 'H': /* Home */
+ pressed_key.scan_code = 5;
break;
- case 'H':
- pressed_key.scan_code = 5; /* Home */
+ case '~': /* Home */
+ pressed_key.scan_code = 5;
break;
}
break;
@@ -704,7 +707,7 @@ static void efi_cin_check(void)
efi_status_t ret;
if (key_available) {
- efi_signal_event(efi_con_in.wait_for_key, true);
+ efi_signal_event(efi_con_in.wait_for_key);
return;
}
@@ -718,7 +721,7 @@ static void efi_cin_check(void)
/* Queue the wait for key event */
if (key_available)
- efi_signal_event(efi_con_in.wait_for_key, true);
+ efi_signal_event(efi_con_in.wait_for_key);
}
}
}
diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c
index 182d735e6bc..36ca719a82f 100644
--- a/lib/efi_loader/efi_file.c
+++ b/lib/efi_loader/efi_file.c
@@ -307,16 +307,10 @@ static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file)
EFI_ENTRY("%p", file);
- if (set_blk_dev(fh)) {
- ret = EFI_DEVICE_ERROR;
- goto error;
- }
+ if (set_blk_dev(fh) || fs_unlink(fh->path))
+ ret = EFI_WARN_DELETE_FAILURE;
- if (fs_unlink(fh->path))
- ret = EFI_DEVICE_ERROR;
file_close(fh);
-
-error:
return EFI_EXIT(ret);
}
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index e003823b606..cad509bfea0 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -41,24 +41,25 @@ static efi_status_t EFIAPI gop_query_mode(struct efi_gop *this, u32 mode_number,
struct efi_gop_mode_info **info)
{
struct efi_gop_obj *gopobj;
+ efi_status_t ret = EFI_SUCCESS;
EFI_ENTRY("%p, %x, %p, %p", this, mode_number, size_of_info, info);
+ if (!this || !size_of_info || !info || mode_number) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+
gopobj = container_of(this, struct efi_gop_obj, ops);
+ ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, sizeof(gopobj->info),
+ (void **)info);
+ if (ret != EFI_SUCCESS)
+ goto out;
*size_of_info = sizeof(gopobj->info);
- *info = &gopobj->info;
-
- return EFI_EXIT(EFI_SUCCESS);
-}
-
-static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number)
-{
- EFI_ENTRY("%p, %x", this, mode_number);
-
- if (mode_number != 0)
- return EFI_EXIT(EFI_INVALID_PARAMETER);
+ memcpy(*info, &gopobj->info, sizeof(gopobj->info));
- return EFI_EXIT(EFI_SUCCESS);
+out:
+ return EFI_EXIT(ret);
}
static __always_inline struct efi_gop_pixel efi_vid16_to_blt_col(u16 vid)
@@ -309,6 +310,44 @@ static efi_status_t gop_blt_vid_to_buf(struct efi_gop *this,
dx, dy, width, height, delta, vid_bpp);
}
+/**
+ * gop_set_mode() - set graphical output mode
+ *
+ * This function implements the SetMode() service.
+ *
+ * See the Unified Extensible Firmware Interface (UEFI) specification for
+ * details.
+ *
+ * @this: the graphical output protocol
+ * @model_number: the mode to be set
+ * Return: status code
+ */
+static efi_status_t EFIAPI gop_set_mode(struct efi_gop *this, u32 mode_number)
+{
+ struct efi_gop_obj *gopobj;
+ struct efi_gop_pixel buffer = {0, 0, 0, 0};
+ efi_uintn_t vid_bpp;
+ efi_status_t ret = EFI_SUCCESS;
+
+ EFI_ENTRY("%p, %x", this, mode_number);
+
+ if (!this) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
+ if (mode_number) {
+ ret = EFI_UNSUPPORTED;
+ goto out;
+ }
+ gopobj = container_of(this, struct efi_gop_obj, ops);
+ vid_bpp = gop_get_bpp(this);
+ ret = gop_blt_video_fill(this, &buffer, EFI_BLT_VIDEO_FILL, 0, 0, 0, 0,
+ gopobj->info.width, gopobj->info.height, 0,
+ vid_bpp);
+out:
+ return EFI_EXIT(ret);
+}
+
/*
* Copy rectangle.
*
@@ -367,7 +406,7 @@ efi_status_t EFIAPI gop_blt(struct efi_gop *this, struct efi_gop_pixel *buffer,
dy, width, height, delta, vid_bpp);
break;
default:
- ret = EFI_UNSUPPORTED;
+ ret = EFI_INVALID_PARAMETER;
}
if (ret != EFI_SUCCESS)
@@ -464,26 +503,26 @@ efi_status_t efi_gop_register(void)
gopobj->mode.info = &gopobj->info;
gopobj->mode.info_size = sizeof(gopobj->info);
+ gopobj->mode.fb_base = fb_base;
+ gopobj->mode.fb_size = fb_size;
+
+ gopobj->info.version = 0;
+ gopobj->info.width = col;
+ gopobj->info.height = row;
#ifdef CONFIG_DM_VIDEO
if (bpix == VIDEO_BPP32)
#else
if (bpix == LCD_COLOR32)
#endif
{
- /*
- * With 32bit color space we can directly expose the frame
- * buffer
- */
- gopobj->mode.fb_base = fb_base;
- gopobj->mode.fb_size = fb_size;
+ gopobj->info.pixel_format = EFI_GOT_BGRA8;
+ } else {
+ gopobj->info.pixel_format = EFI_GOT_BITMASK;
+ gopobj->info.pixel_bitmask[0] = 0xf800; /* red */
+ gopobj->info.pixel_bitmask[1] = 0x07e0; /* green */
+ gopobj->info.pixel_bitmask[2] = 0x001f; /* blue */
}
-
- gopobj->info.version = 0;
- gopobj->info.width = col;
- gopobj->info.height = row;
- gopobj->info.pixel_format = EFI_GOT_BGRA8;
gopobj->info.pixels_per_scanline = col;
-
gopobj->bpix = bpix;
gopobj->fb = fb;
diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c
index 61b71dec621..77e330285a7 100644
--- a/lib/efi_loader/efi_hii.c
+++ b/lib/efi_loader/efi_hii.c
@@ -581,18 +581,22 @@ list_package_lists(const struct efi_hii_database_protocol *this,
struct efi_hii_packagelist *hii =
(struct efi_hii_packagelist *)handle;
int package_cnt, package_max;
- efi_status_t ret = EFI_SUCCESS;
+ efi_status_t ret = EFI_NOT_FOUND;
EFI_ENTRY("%p, %u, %pUl, %p, %p", this, package_type, package_guid,
handle_buffer_length, handle);
if (!handle_buffer_length ||
- (*handle_buffer_length && !handle))
- return EFI_EXIT(EFI_INVALID_PARAMETER);
+ (*handle_buffer_length && !handle)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
if ((package_type != EFI_HII_PACKAGE_TYPE_GUID && package_guid) ||
- (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid))
- return EFI_EXIT(EFI_INVALID_PARAMETER);
+ (package_type == EFI_HII_PACKAGE_TYPE_GUID && !package_guid)) {
+ ret = EFI_INVALID_PARAMETER;
+ goto out;
+ }
EFI_PRINT("package type=%x, guid=%pUl, length=%zu\n", (int)package_type,
package_guid, *handle_buffer_length);
@@ -607,53 +611,28 @@ list_package_lists(const struct efi_hii_database_protocol *this,
if (!list_empty(&hii->guid_list))
break;
continue;
- case EFI_HII_PACKAGE_FORMS:
- EFI_PRINT("Form package not supported\n");
- ret = EFI_INVALID_PARAMETER;
- continue;
case EFI_HII_PACKAGE_STRINGS:
if (!list_empty(&hii->string_tables))
break;
continue;
- case EFI_HII_PACKAGE_FONTS:
- EFI_PRINT("Font package not supported\n");
- ret = EFI_INVALID_PARAMETER;
- continue;
- case EFI_HII_PACKAGE_IMAGES:
- EFI_PRINT("Image package not supported\n");
- ret = EFI_INVALID_PARAMETER;
- continue;
- case EFI_HII_PACKAGE_SIMPLE_FONTS:
- EFI_PRINT("Simple font package not supported\n");
- ret = EFI_INVALID_PARAMETER;
- continue;
- case EFI_HII_PACKAGE_DEVICE_PATH:
- EFI_PRINT("Device path package not supported\n");
- ret = EFI_INVALID_PARAMETER;
- continue;
case EFI_HII_PACKAGE_KEYBOARD_LAYOUT:
if (!list_empty(&hii->keyboard_packages))
break;
continue;
- case EFI_HII_PACKAGE_ANIMATIONS:
- EFI_PRINT("Animation package not supported\n");
- ret = EFI_INVALID_PARAMETER;
- continue;
- case EFI_HII_PACKAGE_END:
- case EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN:
- case EFI_HII_PACKAGE_TYPE_SYSTEM_END:
default:
continue;
}
package_cnt++;
- if (package_cnt <= package_max)
+ if (package_cnt <= package_max) {
*handle++ = hii;
- else
+ ret = EFI_SUCCESS;
+ } else {
ret = EFI_BUFFER_TOO_SMALL;
+ }
}
*handle_buffer_length = package_cnt * sizeof(*handle);
-
+out:
return EFI_EXIT(ret);
}
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 386cf924fe2..27379381e87 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -321,7 +321,7 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
if (evt->group &&
!guidcmp(evt->group,
&efi_guid_event_group_memory_map_change)) {
- efi_signal_event(evt, false);
+ efi_signal_event(evt);
break;
}
}
@@ -334,7 +334,6 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type,
*
* Check that the address is within allocated memory:
*
- * * The address cannot be NULL.
* * The address must be in a range of the memory map.
* * The address may not point to EFI_CONVENTIONAL_MEMORY.
*
@@ -349,8 +348,6 @@ static efi_status_t efi_check_allocated(u64 addr, bool must_be_allocated)
{
struct efi_mem_list *item;
- if (!addr)
- return EFI_INVALID_PARAMETER;
list_for_each_entry(item, &efi_mem, link) {
u64 start = item->desc.physical_start;
u64 end = start + (item->desc.num_pages << EFI_PAGE_SHIFT);
@@ -560,6 +557,9 @@ efi_status_t efi_free_pool(void *buffer)
efi_status_t ret;
struct efi_pool_allocation *alloc;
+ if (!buffer)
+ return EFI_INVALID_PARAMETER;
+
ret = efi_check_allocated((uintptr_t)buffer, true);
if (ret != EFI_SUCCESS)
return ret;
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 9c50955c9bd..40fdc0ea928 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -89,6 +89,30 @@ struct elf_rela {
* handle a good number of runtime callbacks
*/
+efi_status_t efi_init_runtime_supported(void)
+{
+ u16 efi_runtime_services_supported = 0;
+
+ /*
+ * This value must be synced with efi_runtime_detach_list
+ * as well as efi_runtime_services.
+ */
+#if CONFIG_IS_ENABLED(ARCH_BCM283X) || \
+ CONFIG_IS_ENABLED(FSL_LAYERSCAPE) || \
+ CONFIG_IS_ENABLED(SYSRESET_X86) || \
+ CONFIG_IS_ENABLED(PSCI_RESET)
+ efi_runtime_services_supported |= EFI_RT_SUPPORTED_RESET_SYSTEM;
+#endif
+ efi_runtime_services_supported |=
+ EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP;
+ return EFI_CALL(efi_set_variable(L"RuntimeServicesSupported",
+ &efi_global_variable_guid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(efi_runtime_services_supported),
+ &efi_runtime_services_supported));
+}
+
/**
* efi_update_table_header_crc32() - Update crc32 in table header
*
@@ -130,7 +154,7 @@ static void EFIAPI efi_reset_system_boottime(
if (evt->group &&
!guidcmp(evt->group,
&efi_guid_event_group_reset_system)) {
- efi_signal_event(evt, false);
+ efi_signal_event(evt);
break;
}
}
@@ -342,8 +366,7 @@ efi_status_t __weak __efi_runtime EFIAPI efi_get_time(
struct efi_time *time,
struct efi_time_cap *capabilities)
{
- /* Nothing we can do */
- return EFI_DEVICE_ERROR;
+ return EFI_UNSUPPORTED;
}
/**
diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index 8691d686d29..bfb57836fa9 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -117,6 +117,11 @@ efi_status_t efi_init_obj_list(void)
if (ret != EFI_SUCCESS)
goto out;
+ /* Indicate supported runtime services */
+ ret = efi_init_runtime_supported();
+ if (ret != EFI_SUCCESS)
+ goto out;
+
/* Initialize system table */
ret = efi_initialize_system_table();
if (ret != EFI_SUCCESS)
diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c
index f293b423975..243c51a8dbe 100644
--- a/lib/efi_loader/efi_unicode_collation.c
+++ b/lib/efi_loader/efi_unicode_collation.c
@@ -11,8 +11,8 @@
#include <cp437.h>
#include <efi_loader.h>
-/* Characters that may not be used in file names */
-static const char illegal[] = "<>:\"/\\|?*\x7f";
+/* Characters that may not be used in FAT 8.3 file names */
+static const char illegal[] = "+,<=>:;\"/\\|?*[]\x7f";
/*
* EDK2 assumes codepage 1250 when creating FAT 8.3 file names.
@@ -74,10 +74,21 @@ out:
}
/**
+ * next_lower() - get next codepoint converted to lower case
+ *
+ * @string: pointer to u16 string, on return advanced by one codepoint
+ * Return: first codepoint of string converted to lower case
+ */
+static s32 next_lower(const u16 **string)
+{
+ return utf_to_lower(utf16_get(string));
+}
+
+/**
* metai_match() - compare utf-16 string with a pattern string case-insenitively
*
- * @s: string to compare
- * @p: pattern string
+ * @string: string to compare
+ * @pattern: pattern string
*
* The pattern string may use these:
* - * matches >= 0 characters
@@ -93,61 +104,67 @@ out:
*
* Return: true if the string is matched.
*/
-static bool metai_match(const u16 *s, const u16 *p)
+static bool metai_match(const u16 *string, const u16 *pattern)
{
- u16 first;
+ s32 first, s, p;
+
+ for (; *string && *pattern;) {
+ const u16 *string_old = string;
+
+ s = next_lower(&string);
+ p = next_lower(&pattern);
- for (; *s && *p; ++s, ++p) {
- switch (*p) {
+ switch (p) {
case '*':
/* Match 0 or more characters */
- ++p;
- for (;; ++s) {
- if (metai_match(s, p))
+ for (;; s = next_lower(&string)) {
+ if (metai_match(string_old, pattern))
return true;
- if (!*s)
+ if (!s)
return false;
+ string_old = string;
}
case '?':
/* Match any one character */
break;
case '[':
/* Match any character in the set */
- ++p;
- first = *p;
+ p = next_lower(&pattern);
+ first = p;
if (first == ']')
/* Empty set */
return false;
- ++p;
- if (*p == '-') {
+ p = next_lower(&pattern);
+ if (p == '-') {
/* Range */
- ++p;
- if (*s < first || *s > *p)
+ p = next_lower(&pattern);
+ if (s < first || s > p)
return false;
- ++p;
- if (*p != ']')
+ p = next_lower(&pattern);
+ if (p != ']')
return false;
} else {
/* Set */
bool hit = false;
- if (*s == first)
+ if (s == first)
hit = true;
- for (; *p && *p != ']'; ++p) {
- if (*p == *s)
+ for (; p && p != ']';
+ p = next_lower(&pattern)) {
+ if (p == s)
hit = true;
}
- if (!hit || *p != ']')
+ if (!hit || p != ']')
return false;
}
break;
default:
/* Match one character */
- if (*p != *s)
+ if (p != s)
return false;
}
}
- if (!*p && !*s)
+ if (!*pattern && !*string)
return true;
return false;
}
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index e56053194da..d6b75ca02e4 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -148,7 +148,7 @@ static const char *parse_attr(const char *str, u32 *attrp)
}
/**
- * efi_efi_get_variable() - retrieve value of a UEFI variable
+ * efi_get_variable() - retrieve value of a UEFI variable
*
* This function implements the GetVariable runtime service.
*
@@ -404,7 +404,7 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size,
}
/**
- * efi_efi_set_variable() - set value of a UEFI variable
+ * efi_set_variable() - set value of a UEFI variable
*
* This function implements the SetVariable runtime service.
*
@@ -430,7 +430,9 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
data_size, data);
/* TODO: implement APPEND_WRITE */
- if (!variable_name || !vendor ||
+ if (!variable_name || !*variable_name || !vendor ||
+ ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
+ !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) ||
(attributes & EFI_VARIABLE_APPEND_WRITE)) {
ret = EFI_INVALID_PARAMETER;
goto out;
diff --git a/lib/efi_selftest/efi_selftest_event_groups.c b/lib/efi_selftest/efi_selftest_event_groups.c
index 5a7980c5d0b..6dcde50648b 100644
--- a/lib/efi_selftest/efi_selftest_event_groups.c
+++ b/lib/efi_selftest/efi_selftest_event_groups.c
@@ -80,12 +80,11 @@ static int execute(void)
return EFI_ST_FAILURE;
}
for (j = 0; j < GROUP_SIZE; ++j) {
- if (counter[j] != i) {
+ if (counter[j] != 2 * i + 1) {
efi_st_printf("i %u, j %u, count %u\n",
(unsigned int)i, (unsigned int)j,
(unsigned int)counter[j]);
- efi_st_error(
- "Notification function was called\n");
+ efi_st_error("Notification function was not called\n");
return EFI_ST_FAILURE;
}
/* Clear signaled state */
@@ -94,7 +93,7 @@ static int execute(void)
efi_st_error("Event was not signaled\n");
return EFI_ST_FAILURE;
}
- if (counter[j] != i) {
+ if (counter[j] != 2 * i + 1) {
efi_st_printf("i %u, j %u, count %u\n",
(unsigned int)i, (unsigned int)j,
(unsigned int)counter[j]);
@@ -109,7 +108,7 @@ static int execute(void)
"Signaled state not cleared\n");
return EFI_ST_FAILURE;
}
- if (counter[j] != i + 1) {
+ if (counter[j] != 2 * i + 2) {
efi_st_printf("i %u, j %u, count %u\n",
(unsigned int)i, (unsigned int)j,
(unsigned int)counter[j]);
diff --git a/lib/efi_selftest/efi_selftest_gop.c b/lib/efi_selftest/efi_selftest_gop.c
index 4ad043c5974..d64294ac79d 100644
--- a/lib/efi_selftest/efi_selftest_gop.c
+++ b/lib/efi_selftest/efi_selftest_gop.c
@@ -80,6 +80,11 @@ static int execute(void)
}
efi_st_printf("Mode %u: %u x %u\n",
i, info->width, info->height);
+ ret = boottime->free_pool(info);
+ if (ret != EFI_SUCCESS) {
+ efi_st_printf("FreePool failed");
+ return EFI_ST_FAILURE;
+ }
}
return EFI_ST_SUCCESS;