Message ID | 20240528144252.179247-4-heinrich.schuchardt@canonical.com |
---|---|
State | Superseded |
Delegated to: | Heinrich Schuchardt |
Headers | show |
Series | efi_loader: improve device-tree loading | expand |
On Tue, 28 May 2024 at 17:43, Heinrich Schuchardt <heinrich.schuchardt@canonical.com> wrote: > > We already support creating a load option where the device-path > field contains the concatenation of the binary device-path and > optionally the device path of the initrd which we expose via the > EFI_LOAD_FILE2_PROTOCOL. > > Allow to append another device-path pointing to the device-tree > identified by the device-tree GUID. > > Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> > --- > v2: > Rename create_initrd_dp() to create_lo_dp_part(). > Use enum as parameter for create_lo_dp_part(). > Use function efi_load_option_dp_join() to avoid code duplication. > --- > cmd/efidebug.c | 130 +++++++++++++++++++++++++++++++++++-------------- > 1 file changed, 93 insertions(+), 37 deletions(-) > > diff --git a/cmd/efidebug.c b/cmd/efidebug.c > index 762027daf8a..966b4b83361 100644 > --- a/cmd/efidebug.c > +++ b/cmd/efidebug.c > @@ -654,38 +654,80 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag, > } > > /** > - * create_initrd_dp() - create a special device for our Boot### option > + * enum efi_lo_dp_part - part of device path in load option > + */ > +enum efi_lo_dp_part { > + /** @EFI_LO_DP_PART_BINARY: binary */ > + EFI_LO_DP_PART_BINARY, > + /** @EFI_LO_DP_PART_INITRD: initial RAM disk */ > + EFI_LO_DP_PART_INITRD, > + /** EFI_LP_DP_PART_FDT: device-tree */ > + EFI_LP_DP_PART_FDT, > +}; > + > +/** > + * create_lo_dp() - create a special device path for our Boot### option > * > * @dev: device > * @part: disk partition > * @file: filename > * @shortform: create short form device path > + * @type: part of device path to be created > * Return: pointer to the device path or ERR_PTR > */ > static > -struct efi_device_path *create_initrd_dp(const char *dev, const char *part, > - const char *file, int shortform) > +struct efi_device_path *create_lo_dp_part(const char *dev, const char *part, > + const char *file, bool shortform, > + enum efi_lo_dp_part type) > > { > struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL, *short_fp = NULL; > - struct efi_device_path *initrd_dp = NULL; > + struct efi_device_path *dp = NULL; > + const struct efi_device_path *dp_prefix; > efi_status_t ret; > - const struct efi_initrd_dp id_dp = { > + const struct efi_initrd_dp fdt_dp = { > + .vendor = { > + { > + DEVICE_PATH_TYPE_MEDIA_DEVICE, > + DEVICE_PATH_SUB_TYPE_VENDOR_PATH, > + sizeof(fdt_dp.vendor), > + }, > + EFI_FDT_GUID, > + }, > + .end = { > + DEVICE_PATH_TYPE_END, > + DEVICE_PATH_SUB_TYPE_END, > + sizeof(fdt_dp.end), > + } > + }; > + const struct efi_initrd_dp initrd_dp = { > .vendor = { > { > DEVICE_PATH_TYPE_MEDIA_DEVICE, > DEVICE_PATH_SUB_TYPE_VENDOR_PATH, > - sizeof(id_dp.vendor), > + sizeof(initrd_dp.vendor), > }, > EFI_INITRD_MEDIA_GUID, > }, > .end = { > DEVICE_PATH_TYPE_END, > DEVICE_PATH_SUB_TYPE_END, > - sizeof(id_dp.end), > + sizeof(initrd_dp.end), > } > }; > > + switch (type) { > + case EFI_LO_DP_PART_INITRD: > + dp_prefix = &initrd_dp.vendor.dp; > + break; > + case EFI_LP_DP_PART_FDT: > + dp_prefix = &fdt_dp.vendor.dp; > + break; > + default: > + dp_prefix = NULL; > + break; > + } > + > ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp); > if (ret != EFI_SUCCESS) { > printf("Cannot create device path for \"%s %s\"\n", part, file); > @@ -696,13 +739,12 @@ struct efi_device_path *create_initrd_dp(const char *dev, const char *part, > if (!short_fp) > short_fp = tmp_fp; > > - initrd_dp = efi_dp_concat((const struct efi_device_path *)&id_dp, > - short_fp, 0); > + dp = efi_dp_concat(dp_prefix, short_fp, 0); > > out: > efi_free_pool(tmp_dp); > efi_free_pool(tmp_fp); > - return initrd_dp; > + return dp; > } > > /** > @@ -793,9 +835,8 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, > efi_guid_t guid; > u16 *label; > struct efi_device_path *file_path = NULL; > - struct efi_device_path *fp_free = NULL; > - struct efi_device_path *final_fp = NULL; > struct efi_device_path *initrd_dp = NULL; > + struct efi_device_path *fdt_dp = NULL; > struct efi_load_option lo; > void *data = NULL; > efi_uintn_t size; > @@ -843,22 +884,31 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, > lo.label = label; /* label will be changed below */ > > /* file path */ > - ret = efi_dp_from_name(argv[3], argv[4], argv[5], > - NULL, &fp_free); > - if (ret != EFI_SUCCESS) { > - printf("Cannot create device path for \"%s %s\"\n", > - argv[3], argv[4]); > + file_path = create_lo_dp_part(argv[3], argv[4], argv[5], > + shortform, > + EFI_LO_DP_PART_BINARY); > + argc -= 5; > + argv += 5; > + break; > + case 'd': > + shortform = 1; > + fallthrough; > + case 'D': > + if (argc < 3 || fdt_dp) { > + r = CMD_RET_USAGE; > + goto out; > + } > + > + fdt_dp = create_lo_dp_part(argv[1], argv[2], argv[3], > + shortform, > + EFI_LP_DP_PART_FDT); > + if (!fdt_dp) { > + printf("Cannot add a device-tree\n"); > r = CMD_RET_FAILURE; > goto out; > } > - if (shortform) > - file_path = efi_dp_shorten(fp_free); > - if (!file_path) > - file_path = fp_free; > - fp_size += efi_dp_size(file_path) + > - sizeof(struct efi_device_path); > - argc -= 5; > - argv += 5; > + argc -= 3; > + argv += 3; > break; > case 'i': > shortform = 1; > @@ -869,8 +919,9 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, > goto out; > } > > - initrd_dp = create_initrd_dp(argv[1], argv[2], argv[3], > - shortform); > + initrd_dp = create_lo_dp_part(argv[1], argv[2], argv[3], > + shortform, > + EFI_LO_DP_PART_INITRD); > if (!initrd_dp) { > printf("Cannot add an initrd\n"); > r = CMD_RET_FAILURE; > @@ -878,8 +929,6 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, > } > argc -= 3; > argv += 3; > - fp_size += efi_dp_size(initrd_dp) + > - sizeof(struct efi_device_path); > break; > case 's': > if (argc < 1 || lo.optional_data) { > @@ -897,7 +946,6 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, > &file_path, &fp_size); > if (r != CMD_RET_SUCCESS) > goto out; > - fp_free = file_path; > argc -= 3; > argv += 3; > } else{ > @@ -917,14 +965,14 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, > goto out; > } > > - final_fp = efi_dp_concat(file_path, initrd_dp, 1); > - if (!final_fp) { > + ret = efi_load_option_dp_join(&file_path, &fp_size, initrd_dp, fdt_dp); > + if (ret != EFI_SUCCESS) { > printf("Cannot create final device path\n"); > r = CMD_RET_FAILURE; > goto out; > } > > - lo.file_path = final_fp; > + lo.file_path = file_path; > lo.file_path_length = fp_size; > > size = efi_serialize_load_option(&lo, (u8 **)&data); > @@ -945,9 +993,9 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, > > out: > free(data); > - efi_free_pool(final_fp); > efi_free_pool(initrd_dp); > - efi_free_pool(fp_free); > + efi_free_pool(fdt_dp); > + efi_free_pool(file_path); > free(lo.label); > > return r; > @@ -1009,7 +1057,8 @@ static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag, > */ > static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) > { > - struct efi_device_path *initrd_path = NULL; > + struct efi_device_path *fdt_path; > + struct efi_device_path *initrd_path; > struct efi_load_option lo; > efi_status_t ret; > > @@ -1038,6 +1087,12 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) > efi_free_pool(initrd_path); > } > > + fdt_path = efi_dp_from_lo(&lo, &efi_guid_fdt); > + if (fdt_path) { > + printf(" device-tree path: %pD\n", fdt_path); > + efi_free_pool(fdt_path); > + } > + > printf(" data:\n"); > print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, > lo.optional_data, *size, true); > @@ -1565,8 +1620,9 @@ U_BOOT_LONGHELP(efidebug, > "\n" > "efidebug boot add - set UEFI BootXXXX variable\n" > " -b|-B <bootid> <label> <interface> <devnum>[:<part>] <file path>\n" > + " -d|-D <interface> <devnum>[:<part>] <device-tree file path>\n" > " -i|-I <interface> <devnum>[:<part>] <initrd file path>\n" > - " (-b, -i for short form device path)\n" > + " (-b, -d, -i for short form device path)\n" > #if (IS_ENABLED(CONFIG_EFI_HTTP_BOOT)) > " -u <bootid> <label> <uri>\n" > #endif > -- > 2.43.0 > Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
diff --git a/cmd/efidebug.c b/cmd/efidebug.c index 762027daf8a..966b4b83361 100644 --- a/cmd/efidebug.c +++ b/cmd/efidebug.c @@ -654,38 +654,80 @@ static int do_efi_show_tables(struct cmd_tbl *cmdtp, int flag, } /** - * create_initrd_dp() - create a special device for our Boot### option + * enum efi_lo_dp_part - part of device path in load option + */ +enum efi_lo_dp_part { + /** @EFI_LO_DP_PART_BINARY: binary */ + EFI_LO_DP_PART_BINARY, + /** @EFI_LO_DP_PART_INITRD: initial RAM disk */ + EFI_LO_DP_PART_INITRD, + /** EFI_LP_DP_PART_FDT: device-tree */ + EFI_LP_DP_PART_FDT, +}; + +/** + * create_lo_dp() - create a special device path for our Boot### option * * @dev: device * @part: disk partition * @file: filename * @shortform: create short form device path + * @type: part of device path to be created * Return: pointer to the device path or ERR_PTR */ static -struct efi_device_path *create_initrd_dp(const char *dev, const char *part, - const char *file, int shortform) +struct efi_device_path *create_lo_dp_part(const char *dev, const char *part, + const char *file, bool shortform, + enum efi_lo_dp_part type) { struct efi_device_path *tmp_dp = NULL, *tmp_fp = NULL, *short_fp = NULL; - struct efi_device_path *initrd_dp = NULL; + struct efi_device_path *dp = NULL; + const struct efi_device_path *dp_prefix; efi_status_t ret; - const struct efi_initrd_dp id_dp = { + const struct efi_initrd_dp fdt_dp = { + .vendor = { + { + DEVICE_PATH_TYPE_MEDIA_DEVICE, + DEVICE_PATH_SUB_TYPE_VENDOR_PATH, + sizeof(fdt_dp.vendor), + }, + EFI_FDT_GUID, + }, + .end = { + DEVICE_PATH_TYPE_END, + DEVICE_PATH_SUB_TYPE_END, + sizeof(fdt_dp.end), + } + }; + const struct efi_initrd_dp initrd_dp = { .vendor = { { DEVICE_PATH_TYPE_MEDIA_DEVICE, DEVICE_PATH_SUB_TYPE_VENDOR_PATH, - sizeof(id_dp.vendor), + sizeof(initrd_dp.vendor), }, EFI_INITRD_MEDIA_GUID, }, .end = { DEVICE_PATH_TYPE_END, DEVICE_PATH_SUB_TYPE_END, - sizeof(id_dp.end), + sizeof(initrd_dp.end), } }; + switch (type) { + case EFI_LO_DP_PART_INITRD: + dp_prefix = &initrd_dp.vendor.dp; + break; + case EFI_LP_DP_PART_FDT: + dp_prefix = &fdt_dp.vendor.dp; + break; + default: + dp_prefix = NULL; + break; + } + ret = efi_dp_from_name(dev, part, file, &tmp_dp, &tmp_fp); if (ret != EFI_SUCCESS) { printf("Cannot create device path for \"%s %s\"\n", part, file); @@ -696,13 +739,12 @@ struct efi_device_path *create_initrd_dp(const char *dev, const char *part, if (!short_fp) short_fp = tmp_fp; - initrd_dp = efi_dp_concat((const struct efi_device_path *)&id_dp, - short_fp, 0); + dp = efi_dp_concat(dp_prefix, short_fp, 0); out: efi_free_pool(tmp_dp); efi_free_pool(tmp_fp); - return initrd_dp; + return dp; } /** @@ -793,9 +835,8 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, efi_guid_t guid; u16 *label; struct efi_device_path *file_path = NULL; - struct efi_device_path *fp_free = NULL; - struct efi_device_path *final_fp = NULL; struct efi_device_path *initrd_dp = NULL; + struct efi_device_path *fdt_dp = NULL; struct efi_load_option lo; void *data = NULL; efi_uintn_t size; @@ -843,22 +884,31 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, lo.label = label; /* label will be changed below */ /* file path */ - ret = efi_dp_from_name(argv[3], argv[4], argv[5], - NULL, &fp_free); - if (ret != EFI_SUCCESS) { - printf("Cannot create device path for \"%s %s\"\n", - argv[3], argv[4]); + file_path = create_lo_dp_part(argv[3], argv[4], argv[5], + shortform, + EFI_LO_DP_PART_BINARY); + argc -= 5; + argv += 5; + break; + case 'd': + shortform = 1; + fallthrough; + case 'D': + if (argc < 3 || fdt_dp) { + r = CMD_RET_USAGE; + goto out; + } + + fdt_dp = create_lo_dp_part(argv[1], argv[2], argv[3], + shortform, + EFI_LP_DP_PART_FDT); + if (!fdt_dp) { + printf("Cannot add a device-tree\n"); r = CMD_RET_FAILURE; goto out; } - if (shortform) - file_path = efi_dp_shorten(fp_free); - if (!file_path) - file_path = fp_free; - fp_size += efi_dp_size(file_path) + - sizeof(struct efi_device_path); - argc -= 5; - argv += 5; + argc -= 3; + argv += 3; break; case 'i': shortform = 1; @@ -869,8 +919,9 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, goto out; } - initrd_dp = create_initrd_dp(argv[1], argv[2], argv[3], - shortform); + initrd_dp = create_lo_dp_part(argv[1], argv[2], argv[3], + shortform, + EFI_LO_DP_PART_INITRD); if (!initrd_dp) { printf("Cannot add an initrd\n"); r = CMD_RET_FAILURE; @@ -878,8 +929,6 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, } argc -= 3; argv += 3; - fp_size += efi_dp_size(initrd_dp) + - sizeof(struct efi_device_path); break; case 's': if (argc < 1 || lo.optional_data) { @@ -897,7 +946,6 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, &file_path, &fp_size); if (r != CMD_RET_SUCCESS) goto out; - fp_free = file_path; argc -= 3; argv += 3; } else{ @@ -917,14 +965,14 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, goto out; } - final_fp = efi_dp_concat(file_path, initrd_dp, 1); - if (!final_fp) { + ret = efi_load_option_dp_join(&file_path, &fp_size, initrd_dp, fdt_dp); + if (ret != EFI_SUCCESS) { printf("Cannot create final device path\n"); r = CMD_RET_FAILURE; goto out; } - lo.file_path = final_fp; + lo.file_path = file_path; lo.file_path_length = fp_size; size = efi_serialize_load_option(&lo, (u8 **)&data); @@ -945,9 +993,9 @@ static int do_efi_boot_add(struct cmd_tbl *cmdtp, int flag, out: free(data); - efi_free_pool(final_fp); efi_free_pool(initrd_dp); - efi_free_pool(fp_free); + efi_free_pool(fdt_dp); + efi_free_pool(file_path); free(lo.label); return r; @@ -1009,7 +1057,8 @@ static int do_efi_boot_rm(struct cmd_tbl *cmdtp, int flag, */ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) { - struct efi_device_path *initrd_path = NULL; + struct efi_device_path *fdt_path; + struct efi_device_path *initrd_path; struct efi_load_option lo; efi_status_t ret; @@ -1038,6 +1087,12 @@ static void show_efi_boot_opt_data(u16 *varname16, void *data, size_t *size) efi_free_pool(initrd_path); } + fdt_path = efi_dp_from_lo(&lo, &efi_guid_fdt); + if (fdt_path) { + printf(" device-tree path: %pD\n", fdt_path); + efi_free_pool(fdt_path); + } + printf(" data:\n"); print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, lo.optional_data, *size, true); @@ -1565,8 +1620,9 @@ U_BOOT_LONGHELP(efidebug, "\n" "efidebug boot add - set UEFI BootXXXX variable\n" " -b|-B <bootid> <label> <interface> <devnum>[:<part>] <file path>\n" + " -d|-D <interface> <devnum>[:<part>] <device-tree file path>\n" " -i|-I <interface> <devnum>[:<part>] <initrd file path>\n" - " (-b, -i for short form device path)\n" + " (-b, -d, -i for short form device path)\n" #if (IS_ENABLED(CONFIG_EFI_HTTP_BOOT)) " -u <bootid> <label> <uri>\n" #endif
We already support creating a load option where the device-path field contains the concatenation of the binary device-path and optionally the device path of the initrd which we expose via the EFI_LOAD_FILE2_PROTOCOL. Allow to append another device-path pointing to the device-tree identified by the device-tree GUID. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> --- v2: Rename create_initrd_dp() to create_lo_dp_part(). Use enum as parameter for create_lo_dp_part(). Use function efi_load_option_dp_join() to avoid code duplication. --- cmd/efidebug.c | 130 +++++++++++++++++++++++++++++++++++-------------- 1 file changed, 93 insertions(+), 37 deletions(-)