@@ -932,6 +932,7 @@ struct efi_device_path *efi_dp_from_lo(struct efi_load_option *lo,
struct efi_device_path *efi_dp_concat(const struct efi_device_path *dp1,
const struct efi_device_path *dp2);
struct efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path);
+struct efi_device_path *efi_search_file_path_dp_node(struct efi_device_path *device_path);
efi_status_t efi_deserialize_load_option(struct efi_load_option *lo, u8 *data,
efi_uintn_t *size);
unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data);
@@ -387,7 +387,6 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
}
if (lo.attributes & LOAD_OPTION_ACTIVE) {
- struct efi_device_path *file_path;
u32 attributes;
log_debug("trying to load \"%ls\" from %pD\n", lo.label,
@@ -405,11 +404,14 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
lo.file_path,
lo.label, handle);
}
- } else {
- file_path = expand_media_path(lo.file_path);
- ret = EFI_CALL(efi_load_image(true, efi_root, file_path,
+ } else if (efi_search_file_path_dp_node(lo.file_path)) {
+ ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path,
NULL, 0, handle));
- efi_free_pool(file_path);
+ } else {
+ efi_handle_t h;
+
+ h = efi_dp_find_obj(lo.file_path, &efi_block_io_guid, NULL);
+ ret = load_default_file_from_blk_dev(h->dev, handle);
}
if (ret != EFI_SUCCESS) {
log_warning("Loading %ls '%ls' failed\n",
@@ -549,13 +551,13 @@ 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;
@@ -563,6 +565,16 @@ static efi_status_t efi_bootmgr_enumerate_boot_option(struct eficonfig_media_boo
char buf[BOOTMENU_DEVICE_NAME_MAX];
struct efi_device_path *device_path;
struct efi_device_path *short_dp;
+ struct efi_block_io *blkio;
+
+ ret = efi_search_protocol(volume_handles[i], &efi_block_io_guid, &handler);
+ blkio = handler->protocol_interface;
+ /*
+ * The logical partition is excluded since the bootmgr tries to
+ * boot with the default file by scanning the default file on the fly.
+ */
+ if (blkio->media->logical_partition)
+ continue;
ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler);
if (ret != EFI_SUCCESS)
@@ -596,16 +608,18 @@ static efi_status_t efi_bootmgr_enumerate_boot_option(struct eficonfig_media_boo
* 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) {
+ opt[num].size = efi_serialize_load_option(&lo, (u8 **)&opt[num].lo);
+ if (!opt[num].size) {
ret = EFI_OUT_OF_RESOURCES;
goto out;
}
/* 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++;
}
+ *count = num;
out:
return ret;
}
@@ -835,8 +849,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.
+ * This function enumerates all BlockIo devices and add the boot option for it.
* This function also provide the BOOT#### variable maintenance for
* the media device entries.
* - Automatically create the BOOT#### variable for the newly detected device,
@@ -856,7 +869,7 @@ efi_status_t efi_bootmgr_update_media_device_boot_option(void)
struct eficonfig_media_boot_option *opt = NULL;
ret = efi_locate_handle_buffer_int(BY_PROTOCOL,
- &efi_simple_file_system_protocol_guid,
+ &efi_block_io_guid,
NULL, &count,
(efi_handle_t **)&volume_handles);
if (ret != EFI_SUCCESS)
@@ -868,8 +881,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;
@@ -888,6 +900,9 @@ efi_status_t efi_bootmgr_update_media_device_boot_option(void)
u32 boot_index;
u16 var_name[9];
+ if (!opt[i].size)
+ continue;
+
if (!opt[i].exist) {
ret = efi_bootmgr_get_unused_bootoption(var_name, sizeof(var_name),
&boot_index);
@@ -1219,3 +1219,23 @@ struct efi_device_path *search_gpt_dp_node(struct efi_device_path *device_path)
return NULL;
}
+
+/**
+ * efi_search_file_path_dp_node() - search file_path device path node
+ *
+ * @device_path: device path
+ *
+ * Return: pointer to the DEVICE_PATH_SUB_TYPE_FILE_PATH device path node
+ */
+struct efi_device_path *efi_search_file_path_dp_node(struct efi_device_path *device_path)
+{
+ struct efi_device_path *dp = device_path;
+
+ while (dp) {
+ if (EFI_DP_TYPE(dp, MEDIA_DEVICE, FILE_PATH))
+ return dp;
+ dp = efi_dp_next(dp);
+ }
+
+ return NULL;
+}
Current efibootmgr automatically creates the boot options of all the disks and partitions installing SIMPLE_FILE_SYSTEM_PROTOCOL. These boot options are created to load and start the default file(e.g. EFI/BOOT/BOOTAA64.EFI). Now efibootmgr can scan the BlockIo device and try to boot with the default file on the fly, this commit creates the boot options only for the BlockIo devices exluding the logical partition. Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org> --- include/efi_loader.h | 1 + lib/efi_loader/efi_bootmgr.c | 47 +++++++++++++++++++++----------- lib/efi_loader/efi_device_path.c | 20 ++++++++++++++ 3 files changed, 52 insertions(+), 16 deletions(-)