diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 58761fae784..6918fd5e48a 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -549,11 +549,6 @@ efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options) out: free(load_options); - if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) { - if (efi_initrd_deregister() != EFI_SUCCESS) - log_err("Failed to remove loadfile2 for initrd\n"); - } - /* Notify EFI_EVENT_GROUP_RETURN_TO_EFIBOOTMGR event group. */ list_for_each_entry(evt, &efi_events, link) { if (evt->group && diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index 2b467b55481..67d1f75d525 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -183,41 +183,6 @@ out: return ret; } -/** - * efi_initrd_register() - create handle for loading initial RAM disk - * - * This function creates a new handle and installs a Linux specific vendor - * device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path - * to identify the handle and then calls the LoadFile service of the - * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk. - * - * Return: status code - */ -efi_status_t efi_initrd_register(void) -{ - efi_status_t ret; - - /* - * Allow the user to continue if Boot#### file path is not set for - * an initrd - */ - ret = check_initrd(); - if (ret == EFI_INVALID_PARAMETER) - return EFI_SUCCESS; - if (ret != EFI_SUCCESS) - return ret; - - ret = efi_install_multiple_protocol_interfaces(&efi_initrd_handle, - /* initramfs */ - &efi_guid_device_path, &dp_lf2_handle, - /* LOAD_FILE2 */ - &efi_guid_load_file2_protocol, - &efi_lf2_protocol, - NULL); - - return ret; -} - /** * efi_initrd_deregister() - delete the handle for loading initial RAM disk * @@ -245,3 +210,66 @@ efi_status_t efi_initrd_deregister(void) return ret; } + +/** + * efi_initrd_return_notify() - return to efibootmgr callback + * + * @event: the event for which this notification function is registered + * @context: event context + */ +static void EFIAPI efi_initrd_return_notify(struct efi_event *event, + void *context) +{ + efi_status_t ret; + + EFI_ENTRY("%p, %p", event, context); + ret = efi_initrd_deregister(); + EFI_EXIT(ret); +} + +/** + * efi_initrd_register() - create handle for loading initial RAM disk + * + * This function creates a new handle and installs a Linux specific vendor + * device path and an EFI_LOAD_FILE2_PROTOCOL. Linux uses the device path + * to identify the handle and then calls the LoadFile service of the + * EFI_LOAD_FILE2_PROTOCOL to read the initial RAM disk. + * + * Return: status code + */ +efi_status_t efi_initrd_register(void) +{ + efi_status_t ret; + struct efi_event *event; + + /* + * Allow the user to continue if Boot#### file path is not set for + * an initrd + */ + ret = check_initrd(); + if (ret == EFI_INVALID_PARAMETER) + return EFI_SUCCESS; + if (ret != EFI_SUCCESS) + return ret; + + ret = efi_install_multiple_protocol_interfaces(&efi_initrd_handle, + /* initramfs */ + &efi_guid_device_path, &dp_lf2_handle, + /* LOAD_FILE2 */ + &efi_guid_load_file2_protocol, + &efi_lf2_protocol, + NULL); + if (ret != EFI_SUCCESS) { + log_err("installing EFI_LOAD_FILE2_PROTOCOL failed\n"); + return ret; + } + + ret = efi_create_event(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, + efi_initrd_return_notify, NULL, + &efi_guid_event_group_return_to_efibootmgr, + &event); + if (ret != EFI_SUCCESS) + log_err("Creating event failed\n"); + + return ret; +}