efi_loader: use event callback for initrd deregistration

Currently efi_initrd_deregister() is called in bootefi.c
when the image started from bootefi command returns.
Since efi_guid_event_group_return_to_efibootmgr event is
implemented, so let's use this event for invoking
initrd deregistration.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Tested-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c
index 58761fa..6918fd5 100644
--- a/lib/efi_loader/efi_helper.c
+++ b/lib/efi_loader/efi_helper.c
@@ -549,11 +549,6 @@
 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 2b467b5..67d1f75 100644
--- a/lib/efi_loader/efi_load_initrd.c
+++ b/lib/efi_loader/efi_load_initrd.c
@@ -184,6 +184,50 @@
 }
 
 /**
+ * efi_initrd_deregister() - delete the handle for loading initial RAM disk
+ *
+ * This will delete the handle containing the Linux specific vendor device
+ * path and EFI_LOAD_FILE2_PROTOCOL for loading an initrd
+ *
+ * Return:	status code
+ */
+efi_status_t efi_initrd_deregister(void)
+{
+	efi_status_t ret;
+
+	if (!efi_initrd_handle)
+		return EFI_SUCCESS;
+
+	ret = efi_uninstall_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);
+	efi_initrd_handle = NULL;
+
+	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
@@ -196,6 +240,7 @@
 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
@@ -214,34 +259,17 @@
 						       &efi_guid_load_file2_protocol,
 						       &efi_lf2_protocol,
 						       NULL);
-
-	return ret;
-}
-
-/**
- * efi_initrd_deregister() - delete the handle for loading initial RAM disk
- *
- * This will delete the handle containing the Linux specific vendor device
- * path and EFI_LOAD_FILE2_PROTOCOL for loading an initrd
- *
- * Return:	status code
- */
-efi_status_t efi_initrd_deregister(void)
-{
-	efi_status_t ret;
-
-	if (!efi_initrd_handle)
-		return EFI_SUCCESS;
+	if (ret != EFI_SUCCESS) {
+		log_err("installing EFI_LOAD_FILE2_PROTOCOL failed\n");
+		return ret;
+	}
 
-	ret = efi_uninstall_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);
-	efi_initrd_handle = NULL;
+	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;
 }