efi_loader: Pass file path to payload

The payload gets information on where it got loaded from. This includes
the device as well as file path.

So far we've treated both as the same thing and always gave it the device
name. However, in some situations grub2 actually wants to find its loading
path to find its configuration file.

So let's split the two semantically separte bits into separate structs and
pass the loaded file name into our payload when we load it using "load".

Signed-off-by: Alexander Graf <agraf@suse.de>
diff --git a/cmd/bootefi.c b/cmd/bootefi.c
index 0d09aa1..adcf645 100644
--- a/cmd/bootefi.c
+++ b/cmd/bootefi.c
@@ -34,17 +34,30 @@
 	}
 };
 
+static struct efi_device_path_file_path bootefi_device_path[] = {
+	{
+		.dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE,
+		.dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH,
+		.dp.length = sizeof(bootefi_image_path[0]),
+		.str = { 'b','o','o','t','e','f','i' },
+	}, {
+		.dp.type = DEVICE_PATH_TYPE_END,
+		.dp.sub_type = DEVICE_PATH_SUB_TYPE_END,
+		.dp.length = sizeof(bootefi_image_path[0]),
+	}
+};
+
 static efi_status_t bootefi_open_dp(void *handle, efi_guid_t *protocol,
 			void **protocol_interface, void *agent_handle,
 			void *controller_handle, uint32_t attributes)
 {
-	*protocol_interface = bootefi_image_path;
+	*protocol_interface = bootefi_device_path;
 	return EFI_SUCCESS;
 }
 
 /* The EFI loaded_image interface for the image executed via "bootefi" */
 static struct efi_loaded_image loaded_image_info = {
-	.device_handle = bootefi_image_path,
+	.device_handle = bootefi_device_path,
 	.file_path = bootefi_image_path,
 };
 
@@ -63,7 +76,7 @@
 		{
 			/*
 			 * When asking for the device path interface, return
-			 * bootefi_image_path
+			 * bootefi_device_path
 			 */
 			.guid = &efi_guid_device_path,
 			.open = &bootefi_open_dp,
@@ -73,11 +86,11 @@
 
 /* The EFI object struct for the device the "bootefi" image was loaded from */
 static struct efi_object bootefi_device_obj = {
-	.handle = bootefi_image_path,
+	.handle = bootefi_device_path,
 	.protocols = {
 		{
 			/* When asking for the device path interface, return
-			 * bootefi_image_path */
+			 * bootefi_device_path */
 			.guid = &efi_guid_device_path,
 			.open = &bootefi_open_dp,
 		}
@@ -192,7 +205,7 @@
 	bootefi_help_text
 );
 
-void efi_set_bootdev(const char *dev, const char *devnr)
+void efi_set_bootdev(const char *dev, const char *devnr, const char *path)
 {
 	__maybe_unused struct blk_desc *desc;
 	char devname[16] = { 0 }; /* dp->str is u16[16] long */
@@ -217,7 +230,12 @@
 	if (colon)
 		*colon = '\0';
 
-	/* Patch the bootefi_image_path to the target device */
+	/* Patch bootefi_device_path to the target device */
+	memset(bootefi_device_path[0].str, 0, sizeof(bootefi_device_path[0].str));
+	ascii2unicode(bootefi_device_path[0].str, devname);
+
+	/* Patch bootefi_image_path to the target file path */
 	memset(bootefi_image_path[0].str, 0, sizeof(bootefi_image_path[0].str));
+	snprintf(devname, sizeof(devname), "%s", path);
 	ascii2unicode(bootefi_image_path[0].str, devname);
 }