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/efi_loader/efi_boottime.c') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 54fff85e64..027bd6d4d3 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 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/efi_loader/efi_boottime.c') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 027bd6d4d3..fed8d47ade 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 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/efi_loader/efi_boottime.c') diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index fed8d47ade..78c6076e28 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