diff mbox series

[v6,4/9] efi_loader: create default file boot option

Message ID 20231015234907.2362717-5-masahisa.kojima@linaro.org
State New
Headers show
Series Add EFI HTTP boot support | expand

Commit Message

Masahisa Kojima Oct. 15, 2023, 11:49 p.m. UTC
Current efibootmgr automatically creates the
boot options of all disks and partitions installing
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.
Some of the automatically created boot options are
useless if the disk and partition does not have
the default file(e.g. EFI/BOOT/BOOTAA64.EFI).

This commit only creates the boot option if the disk and
partition have the default file so that system can directly
boot from it.

Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
---
 lib/efi_loader/efi_bootmgr.c | 53 +++++++++++++++++++++++-------------
 1 file changed, 34 insertions(+), 19 deletions(-)
diff mbox series

Patch

diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
index a40762c74c..a197127cdd 100644
--- a/lib/efi_loader/efi_bootmgr.c
+++ b/lib/efi_loader/efi_bootmgr.c
@@ -355,20 +355,21 @@  error:
  */
 static efi_status_t efi_bootmgr_enumerate_boot_option(struct eficonfig_media_boot_option *opt,
 						      efi_handle_t *volume_handles,
-						      efi_status_t count)
+						      efi_uintn_t *count)
 {
-	u32 i;
+	u32 i, num = 0;
 	struct efi_handler *handler;
 	efi_status_t ret = EFI_SUCCESS;
 
-	for (i = 0; i < count; i++) {
+	for (i = 0; i < *count; i++) {
 		u16 *p;
 		u16 dev_name[BOOTMENU_DEVICE_NAME_MAX];
 		char *optional_data;
 		struct efi_load_option lo;
 		char buf[BOOTMENU_DEVICE_NAME_MAX];
-		struct efi_device_path *device_path;
+		struct efi_device_path *device_path, *full_path;
 		struct efi_device_path *short_dp;
+		efi_handle_t image_handle;
 
 		ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler);
 		if (ret != EFI_SUCCESS)
@@ -378,17 +379,27 @@  static efi_status_t efi_bootmgr_enumerate_boot_option(struct eficonfig_media_boo
 		if (ret != EFI_SUCCESS)
 			continue;
 
+		/* check whether the partition or disk have the default file */
+		full_path = efi_dp_from_file(device_path,
+					     "/EFI/BOOT/" BOOTEFI_NAME);
+		ret = EFI_CALL(efi_load_image(true, efi_root, full_path, NULL,
+					      0, &image_handle));
+		if (ret != EFI_SUCCESS)
+			goto next;
+		ret = EFI_CALL(efi_unload_image(image_handle));
+		if (ret != EFI_SUCCESS)
+			goto next;
+
 		ret = efi_disk_get_device_name(volume_handles[i], buf, BOOTMENU_DEVICE_NAME_MAX);
 		if (ret != EFI_SUCCESS)
-			continue;
+			goto next;
 
 		p = dev_name;
 		utf8_utf16_strncpy(&p, buf, strlen(buf));
 
 		/* prefer to short form device path */
-		short_dp = efi_dp_shorten(device_path);
-		if (short_dp)
-			device_path = short_dp;
+		short_dp = efi_dp_shorten(full_path);
+		device_path = short_dp ? short_dp : full_path;
 
 		lo.label = dev_name;
 		lo.attributes = LOAD_OPTION_ACTIVE;
@@ -396,24 +407,29 @@  static efi_status_t efi_bootmgr_enumerate_boot_option(struct eficonfig_media_boo
 		lo.file_path_length = efi_dp_size(device_path) + sizeof(END);
 		/*
 		 * Set the dedicated guid to optional_data, it is used to identify
-		 * the boot option that automatically generated by the bootmenu.
+		 * the boot option that automatically generated by the efibootmgr.
 		 * efi_serialize_load_option() expects optional_data is null-terminated
 		 * utf8 string, so set the "1234567" string to allocate enough space
 		 * to store guid, instead of realloc the load_option.
 		 */
 		lo.optional_data = "1234567";
-		opt[i].size = efi_serialize_load_option(&lo, (u8 **)&opt[i].lo);
-		if (!opt[i].size) {
-			ret = EFI_OUT_OF_RESOURCES;
-			goto out;
+		opt[num].size = efi_serialize_load_option(&lo, (u8 **)&opt[num].lo);
+		if (!opt[num].size) {
+			efi_free_pool(full_path);
+			return EFI_OUT_OF_RESOURCES;
 		}
 		/* set the guid */
-		optional_data = (char *)opt[i].lo + (opt[i].size - u16_strsize(u"1234567"));
+		optional_data = (char *)opt[num].lo + (opt[num].size - u16_strsize(u"1234567"));
 		memcpy(optional_data, &efi_guid_bootmenu_auto_generated, sizeof(efi_guid_t));
+		num++;
+
+next:
+		efi_free_pool(full_path);
 	}
 
-out:
-	return ret;
+	*count = num;
+
+	return EFI_SUCCESS;
 }
 
 /**
@@ -642,7 +658,7 @@  efi_status_t efi_bootmgr_delete_boot_option(u16 boot_index)
  * efi_bootmgr_update_media_device_boot_option() - generate the media device boot option
  *
  * This function enumerates all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
- * and generate the bootmenu entries.
+ * and create the boot option with default file if the file exists.
  * This function also provide the BOOT#### variable maintenance for
  * the media device entries.
  * - Automatically create the BOOT#### variable for the newly detected device,
@@ -674,8 +690,7 @@  efi_status_t efi_bootmgr_update_media_device_boot_option(void)
 		goto out;
 	}
 
-	/* enumerate all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */
-	ret = efi_bootmgr_enumerate_boot_option(opt, volume_handles, count);
+	ret = efi_bootmgr_enumerate_boot_option(opt, volume_handles, &count);
 	if (ret != EFI_SUCCESS)
 		goto out;