From 66ca24a9a05aa094bcdcf0784d8cc5911dc2f725 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 2 Jun 2019 01:43:33 +0200 Subject: efi_loader: DisconnectController() with no driver If DisconnectController() is called and no driver is managing ControllerHandle, return EFI_SUCCESS. UEFI SCT II 2017, 3.3.12 DisconnectController(), 5.1.3.12.4 - 5.1.3.12.6 Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 54fff85e64e..027bd6d4d32 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1134,11 +1134,15 @@ static efi_status_t efi_get_drivers(efi_handle_t handle, ++count; } } + *number_of_drivers = 0; + if (!count) { + *driver_handle_buffer = NULL; + return EFI_SUCCESS; + } /* * Create buffer. In case of duplicate driver assignments the buffer * will be too large. But that does not harm. */ - *number_of_drivers = 0; *driver_handle_buffer = calloc(count, sizeof(efi_handle_t)); if (!*driver_handle_buffer) return EFI_OUT_OF_RESOURCES; @@ -1194,7 +1198,8 @@ static efi_status_t efi_disconnect_all_drivers &driver_handle_buffer); if (ret != EFI_SUCCESS) return ret; - + if (!number_of_drivers) + return EFI_SUCCESS; ret = EFI_NOT_FOUND; while (number_of_drivers) { r = EFI_CALL(efi_disconnect_controller( -- cgit v1.2.3 From 6a853dbcc02ba26d8b85d26be9763464c6bfe63e Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 2 Jun 2019 21:02:10 +0200 Subject: lib: time: export usec_to_tick() In the UEFI Stall() boottime service we need access to usec_to_tick(). Export the function. Remove redundant implementation in arch/arm/mach-rockchip/rk_timer.c. Signed-off-by: Heinrich Schuchardt --- lib/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/time.c b/lib/time.c index 9c55da6f1b3..f5751ab162b 100644 --- a/lib/time.c +++ b/lib/time.c @@ -139,7 +139,7 @@ unsigned long __weak notrace timer_get_us(void) return tick_to_time(get_ticks() * 1000); } -static uint64_t usec_to_tick(unsigned long usec) +uint64_t usec_to_tick(unsigned long usec) { uint64_t tick = usec; tick *= get_tbclk(); -- cgit v1.2.3 From 22f23db428b8ee14ff04a9128431e719ef2a387c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 2 Jun 2019 21:12:17 +0200 Subject: efi_loader: check timer events in Stall() During a call to Stall() we should periodically check for timer events. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 027bd6d4d32..fed8d47adec 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1947,8 +1947,14 @@ out: */ static efi_status_t EFIAPI efi_stall(unsigned long microseconds) { + u64 end_tick; + EFI_ENTRY("%ld", microseconds); - udelay(microseconds); + + end_tick = get_ticks() + usec_to_tick(microseconds); + while (get_ticks() < end_tick) + efi_timer_check(); + return EFI_EXIT(EFI_SUCCESS); } -- cgit v1.2.3 From 25e6fb5e93194d84c4b93fb3ab9d93d2157923dd Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 2 Jun 2019 22:54:28 +0200 Subject: efi_loader: fix EnableCursor() The EnableCursor() service of the simple text output protocol must update the the CursorVisible field of the output mode. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_console.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index b2cb18e6d67..3b7578f3aa4 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -430,6 +430,7 @@ static efi_status_t EFIAPI efi_cout_enable_cursor( EFI_ENTRY("%p, %d", this, enable); printf(ESC"[?25%c", enable ? 'h' : 'l'); + efi_con_mode.cursor_visible = !!enable; return EFI_EXIT(EFI_SUCCESS); } -- cgit v1.2.3 From 120ff7ba68df265a8b96c5c6131b579ce722a7a5 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 2 Jun 2019 20:02:32 +0200 Subject: efi_loader: close protocols in UnloadImage() When UnloadImage() is called all protocols opened by the image have to be closed. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_boottime.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index fed8d47adec..78c6076e28c 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2791,12 +2791,46 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, * @image_obj: handle of the loaded image * @loaded_image_protocol: loaded image protocol */ -static void efi_delete_image(struct efi_loaded_image_obj *image_obj, - struct efi_loaded_image *loaded_image_protocol) +static efi_status_t efi_delete_image + (struct efi_loaded_image_obj *image_obj, + struct efi_loaded_image *loaded_image_protocol) { + struct efi_object *efiobj; + efi_status_t r, ret = EFI_SUCCESS; + +close_next: + list_for_each_entry(efiobj, &efi_obj_list, link) { + struct efi_handler *protocol; + + list_for_each_entry(protocol, &efiobj->protocols, link) { + struct efi_open_protocol_info_item *info; + + list_for_each_entry(info, &protocol->open_infos, link) { + if (info->info.agent_handle != + (efi_handle_t)image_obj) + continue; + r = EFI_CALL(efi_close_protocol + (efiobj, protocol->guid, + info->info.agent_handle, + info->info.controller_handle + )); + if (r != EFI_SUCCESS) + ret = r; + /* + * Closing protocols may results in further + * items being deleted. To play it safe loop + * over all elements again. + */ + goto close_next; + } + } + } + efi_free_pages((uintptr_t)loaded_image_protocol->image_base, efi_size_in_pages(loaded_image_protocol->image_size)); efi_delete_handle(&image_obj->header); + + return ret; } /** -- cgit v1.2.3 From 94e6e5505310be3bec4392f24ac13b75dbbaca2b Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Wed, 29 May 2019 20:54:25 +0200 Subject: efi_loader: bootmgr: print a message when loading from BootNext failed If a user defines BootNext but not BootOrder and loading from BootNext fails, you will see only a message like this: BootOrder not defined This may confuse a user. Adding an error message will be helpful. An example output looks like this: => efidebug boot add 0001 label1 scsi 0:1 "\path1\file1.efi" "--option foo" => efidebug boot add 0002 label2 scsi 0:1 "\path2\file2.efi" "--option bar" => efidebug boot add 0003 label3 scsi 0:1 "\path3\file3.efi" "--option no" => efidebug boot order 0001 0002 => efidebug boot next 0003 => bootefi bootmgr Loading from Boot0003 'label3' failed Loading from BootNext failed, falling back to BootOrder Loading from Boot0001 'label1' failed Loading from Boot0002 'label2' failed EFI boot manager: Cannot load any image Signed-off-by: AKASHI Takahiro Adjust messages. Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_bootmgr.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 7bf51874c1c..43791422c81 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -149,8 +149,11 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path, NULL, 0, handle)); - if (ret != EFI_SUCCESS) + if (ret != EFI_SUCCESS) { + printf("Loading from Boot%04X '%ls' failed\n", n, + lo.label); goto error; + } attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS; @@ -215,6 +218,7 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle) ret = try_load_entry(bootnext, handle); if (ret == EFI_SUCCESS) return ret; + printf("Loading from BootNext failed, falling back to BootOrder\n"); } } else { printf("Deleting BootNext failed\n"); -- cgit v1.2.3 From e80474ad39d1f348cda3837bef1b7baf600fae47 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 4 Jun 2019 20:55:12 +0200 Subject: efi_loader: notify memory map changes When the memory map is changed signal events of the EFI_EVENT_GROUP_MEMORY_MAP_CHANGE event group. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_memory.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'lib') diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 76dcaa48f49..386cf924fe2 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -230,6 +230,7 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, struct efi_mem_list *newlist; bool carve_again; uint64_t carved_pages = 0; + struct efi_event *evt; EFI_PRINT("%s: 0x%llx 0x%llx %d %s\n", __func__, start, pages, memory_type, overlap_only_ram ? "yes" : "no"); @@ -315,6 +316,16 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, /* And make sure memory is listed in descending order */ efi_mem_sort(); + /* Notify that the memory map was changed */ + list_for_each_entry(evt, &efi_events, link) { + if (evt->group && + !guidcmp(evt->group, + &efi_guid_event_group_memory_map_change)) { + efi_signal_event(evt, false); + break; + } + } + return start; } -- cgit v1.2.3 From cee2cbc73173a871a5c65e9e55f3d98a6fd71325 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 4 Jun 2019 15:52:06 +0900 Subject: efi_loader: variable: support non-volatile attribute The attribute, EFI_VARIABLE_NON_VOLATILE, should be encoded as "nv" flag in U-Boot variable if specified. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_variable.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 50bc10537f4..e56053194da 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -125,6 +125,8 @@ static const char *parse_attr(const char *str, u32 *attrp) if ((s = prefix(str, "ro"))) { attr |= READ_ONLY; + } else if ((s = prefix(str, "nv"))) { + attr |= EFI_VARIABLE_NON_VOLATILE; } else if ((s = prefix(str, "boot"))) { attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS; } else if ((s = prefix(str, "run"))) { @@ -468,7 +470,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, } } - val = malloc(2 * data_size + strlen("{ro,run,boot}(blob)") + 1); + val = malloc(2 * data_size + strlen("{ro,run,boot,nv}(blob)") + 1); if (!val) { ret = EFI_OUT_OF_RESOURCES; goto out; @@ -480,12 +482,16 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name, * store attributes * TODO: several attributes are not supported */ - attributes &= (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS); + attributes &= (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS); s += sprintf(s, "{"); while (attributes) { u32 attr = 1 << (ffs(attributes) - 1); - if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) + if (attr == EFI_VARIABLE_NON_VOLATILE) + s += sprintf(s, "nv"); + else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) s += sprintf(s, "boot"); else if (attr == EFI_VARIABLE_RUNTIME_ACCESS) s += sprintf(s, "run"); -- cgit v1.2.3 From 366161cf976c41f2cfabbb896c8f9a94c31886ce Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 4 Jun 2019 15:52:09 +0900 Subject: efi_loader: bootmgr: make BootNext non-volatile Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- lib/efi_loader/efi_bootmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 43791422c81..b2102c5b5af 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -210,7 +210,8 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle) ret = EFI_CALL(efi_set_variable( L"BootNext", (efi_guid_t *)&efi_global_variable_guid, - 0, 0, &bootnext)); + EFI_VARIABLE_NON_VOLATILE, 0, + &bootnext)); /* load BootNext */ if (ret == EFI_SUCCESS) { -- cgit v1.2.3