[PATCH v5 1/2] cmd: eficonfig: add support for URI device path based boot options

Ilias Apalodimas ilias.apalodimas at linaro.org
Thu Jul 3 10:31:25 CEST 2025


Thanks Sughosh


Heinrich the code compared to the one you sent your r-b has minor
fixes. Do you want me to preserve that ?

On Thu, 3 Jul 2025 at 09:43, Sughosh Ganu <sughosh.ganu at linaro.org> wrote:
>
> The eficonfig command provides a menu based interface for maintenance
> of the EFI boot options. Add support for adding a URI based boot
> option. This boot option can then be used for HTTP boot.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu at linaro.org>

Reviewed-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>
Tested-by: Ilias Apalodimas <ilias.apalodimas at linaro.org>

> ---
> Changes since V4:
> * Clear out the URI string in eficonfig_process_clear_file_selection()
>   when user selects the 'Clear' menu.
> * Display the URI string as part of editing the boot option by putting
>   a check in prepare_file_selection_entry().
> * Clear out the URI string in eficonfig_process_select_file() if a
>   file is being selected from one of the disk volumes.
>
>
>  cmd/eficonfig.c      | 146 ++++++++++++++++++++++++++++++++++++++++---
>  include/efi_config.h |   2 +
>  2 files changed, 140 insertions(+), 8 deletions(-)
>
> diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> index 6e14d34a6bd..8ac0fb98e02 100644
> --- a/cmd/eficonfig.c
> +++ b/cmd/eficonfig.c
> @@ -35,6 +35,7 @@ static int avail_row;
>
>  #define EFICONFIG_DESCRIPTION_MAX 32
>  #define EFICONFIG_OPTIONAL_DATA_MAX 64
> +#define EFICONFIG_URI_MAX 512
>  #define EFICONFIG_MENU_HEADER_ROW_NUM 3
>  #define EFICONFIG_MENU_DESC_ROW_NUM 5
>
> @@ -538,6 +539,40 @@ struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_
>         return dp;
>  }
>
> +/**
> + * eficonfig_create_uri_device_path() - Create an URI based device path
> + * @uri_str:   URI string to be added to the device path
> + *
> + * Take the u16 string, convert it to a u8 string, and create a URI
> + * device path. This will be used for the EFI HTTP boot.
> + *
> + * Return: pointer to the URI device path on success, NULL on failure
> + */
> +static struct efi_device_path *eficonfig_create_uri_device_path(u16 *uri_str)
> +{
> +       char *pos, *p;
> +       u32 len = 0;
> +       efi_uintn_t uridp_len;
> +       struct efi_device_path_uri *uridp;
> +
> +       len = utf16_utf8_strlen(uri_str);
> +
> +       uridp_len = sizeof(struct efi_device_path) + len + 1;
> +       uridp = efi_alloc(uridp_len + sizeof(EFI_DP_END));
> +       if (!uridp)
> +               return NULL;
> +
> +       uridp->dp.type = DEVICE_PATH_TYPE_MESSAGING_DEVICE;
> +       uridp->dp.sub_type = DEVICE_PATH_SUB_TYPE_MSG_URI;
> +       uridp->dp.length = uridp_len;
> +       p = (char *)&uridp->uri;
> +       utf16_utf8_strcpy(&p, uri_str);
> +       pos = (char *)uridp + uridp_len;
> +       memcpy(pos, &EFI_DP_END, sizeof(EFI_DP_END));
> +
> +       return &uridp->dp;
> +}
> +
>  /**
>   * eficonfig_file_selected() - handler of file selection
>   *
> @@ -983,6 +1018,22 @@ static efi_status_t eficonfig_boot_add_optional_data(void *data)
>                                  "  enter optional data:");
>  }
>
> +/**
> + * eficonfig_boot_add_uri() - handle user input for HTTP Boot URI
> + *
> + * @data:      pointer to the internal boot option structure
> + * Return:     status code
> + */
> +static efi_status_t eficonfig_boot_add_uri(void *data)
> +{
> +       struct eficonfig_select_file_info *file_info = data;
> +
> +       return handle_user_input(file_info->uri, EFICONFIG_URI_MAX, 24,
> +                                "\n  ** Edit URI **\n"
> +                                "\n"
> +                                "  enter HTTP Boot URI:");
> +}
> +
>  /**
>   * eficonfig_boot_edit_save() - handler to save the boot option
>   *
> @@ -998,7 +1049,8 @@ static efi_status_t eficonfig_boot_edit_save(void *data)
>                 bo->edit_completed = false;
>                 return EFI_NOT_READY;
>         }
> -       if (u16_strlen(bo->file_info.current_path) == 0) {
> +       if (u16_strlen(bo->file_info.current_path) == 0 &&
> +           u16_strlen(bo->file_info.uri) == 0) {
>                 eficonfig_print_msg("File is not selected!");
>                 bo->edit_completed = false;
>                 return EFI_NOT_READY;
> @@ -1024,9 +1076,19 @@ efi_status_t eficonfig_process_clear_file_selection(void *data)
>         file_info->current_path[0] = u'\0';
>         file_info->dp_volume = NULL;
>
> +       if (file_info->uri)
> +               file_info->uri[0] = u'\0';
> +
>         return EFI_ABORTED;
>  }
>
> +static struct eficonfig_item select_boot_file_menu_items[] = {
> +       {"Select File", eficonfig_process_select_file},
> +       {"Enter URI", eficonfig_boot_add_uri},
> +       {"Clear", eficonfig_process_clear_file_selection},
> +       {"Quit", eficonfig_process_quit},
> +};
> +
>  static struct eficonfig_item select_file_menu_items[] = {
>         {"Select File", eficonfig_process_select_file},
>         {"Clear", eficonfig_process_clear_file_selection},
> @@ -1042,16 +1104,30 @@ static struct eficonfig_item select_file_menu_items[] = {
>  efi_status_t eficonfig_process_show_file_option(void *data)
>  {
>         efi_status_t ret;
> +       unsigned int menu_count;
>         struct efimenu *efi_menu;
> +       struct eficonfig_item *menu_items;
> +       struct eficonfig_select_file_info *file_info = data;
> +
> +       menu_items = file_info->uri ? select_boot_file_menu_items :
> +               select_file_menu_items;
> +
> +       menu_count = file_info->uri ?
> +               ARRAY_SIZE(select_boot_file_menu_items) :
> +               ARRAY_SIZE(select_file_menu_items);
> +
> +       menu_items[0].data = data;
> +       menu_items[1].data = data;
> +       menu_items[2].data = data;
>
> -       select_file_menu_items[0].data = data;
> -       select_file_menu_items[1].data = data;
> -       efi_menu = eficonfig_create_fixed_menu(select_file_menu_items,
> -                                              ARRAY_SIZE(select_file_menu_items));
> +       efi_menu = eficonfig_create_fixed_menu(menu_items, menu_count);
>         if (!efi_menu)
>                 return EFI_OUT_OF_RESOURCES;
>
> -       ret = eficonfig_process_common(efi_menu, "  ** Update File **",
> +       ret = eficonfig_process_common(efi_menu,
> +                                      file_info->uri ?
> +                                      "  ** Update File/URI **" :
> +                                      "  ** Update File **",
>                                        eficonfig_menu_desc,
>                                        eficonfig_display_statusline,
>                                        eficonfig_print_entry,
> @@ -1121,6 +1197,14 @@ out:
>                 file_info->current_path[len] = u'\0';
>                 file_info->current_volume = tmp->current_volume;
>                 file_info->dp_volume = tmp->dp_volume;
> +
> +               /*
> +                * File being selected, set the URI string to
> +                * null so that the file gets picked as the
> +                * boot image.
> +                */
> +               if (file_info->uri)
> +                       file_info->uri[0] = u'\0';
>         }
>
>         list_for_each_safe(pos, n, &tmp->filepath_list) {
> @@ -1224,6 +1308,12 @@ static efi_status_t prepare_file_selection_entry(struct efimenu *efi_menu, char
>         efi_handle_t handle;
>         char *devname;
>
> +       /* Check for URI based boot file */
> +       if (file_info->uri && utf16_utf8_strlen(file_info->uri))
> +               return create_boot_option_entry(efi_menu, title, file_info->uri,
> +                                               eficonfig_process_show_file_option,
> +                                               file_info);
> +
>         devname = calloc(1, EFICONFIG_VOLUME_PATH_MAX + 1);
>         if (!devname)
>                 return EFI_OUT_OF_RESOURCES;
> @@ -1340,6 +1430,27 @@ out:
>         return ret;
>  }
>
> +/**
> + * fill_dp_uri() - copy the URI string in the device path
> + * @dp:                pointer to the URI device path
> + * @uri_str:   URI string to be copied
> + *
> + * Copy the passed URI string to the URI device path. This
> + * requires utf8_utf16_strcpy() to copy the u16 string to
> + * the u8 array in the device path structure.
> + *
> + * Return: None
> + */
> +static void fill_dp_uri(struct efi_device_path *dp, u16 **uri_str)
> +{
> +       u16 *p = *uri_str;
> +       struct efi_device_path_uri *uridp;
> +
> +       uridp = (struct efi_device_path_uri *)dp;
> +
> +       utf8_utf16_strcpy(&p, uridp->uri);
> +}
> +
>  /**
>   * fill_file_info() - fill the file info from efi_device_path structure
>   *
> @@ -1392,10 +1503,13 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
>         size_t len;
>         efi_status_t ret;
>         char *tmp = NULL, *p;
> +       u16 *current_path = NULL;
>         struct efi_load_option lo = {0};
>         efi_uintn_t dp_size;
>         struct efi_device_path *dp = NULL;
>         efi_uintn_t size = load_option_size;
> +       struct efi_device_path *dp_volume = NULL;
> +       struct efi_device_path *uri_dp = NULL;
>         struct efi_device_path *device_dp = NULL;
>         struct efi_device_path *initrd_dp = NULL;
>         struct efi_device_path *fdt_dp = NULL;
> @@ -1464,6 +1578,12 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
>                 goto out;
>         }
>
> +       bo->file_info.uri = calloc(1, EFICONFIG_URI_MAX * sizeof(u16));
> +       if (!bo->file_info.uri) {
> +               ret =  EFI_OUT_OF_RESOURCES;
> +               goto out;
> +       }
> +
>         /* copy the preset value */
>         if (load_option) {
>                 ret = efi_deserialize_load_option(&lo, load_option, &size);
> @@ -1481,7 +1601,10 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
>                 u16_strcpy(bo->description, lo.label);
>
>                 /* EFI image file path is a first instance */
> -               if (lo.file_path)
> +               if (lo.file_path && EFI_DP_TYPE(lo.file_path, MESSAGING_DEVICE,
> +                                               MSG_URI))
> +                       fill_dp_uri(lo.file_path, &bo->file_info.uri);
> +               else if (lo.file_path)
>                         fill_file_info(lo.file_path, &bo->file_info, device_dp);
>
>                 /* Initrd file path (optional) is placed at second instance. */
> @@ -1512,6 +1635,9 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
>                         goto out;
>         }
>
> +       if (utf16_utf8_strlen(bo->file_info.uri))
> +               uri_dp = eficonfig_create_uri_device_path(bo->file_info.uri);
> +
>         if (bo->initrd_info.dp_volume) {
>                 dp = eficonfig_create_device_path(bo->initrd_info.dp_volume,
>                                                  bo->initrd_info.current_path);
> @@ -1536,7 +1662,10 @@ static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_bo
>                 efi_free_pool(dp);
>         }
>
> -       dp = eficonfig_create_device_path(bo->file_info.dp_volume, bo->file_info.current_path);
> +       dp_volume = bo->file_info.dp_volume;
> +       current_path = bo->file_info.current_path;
> +       dp = uri_dp ?
> +               uri_dp : eficonfig_create_device_path(dp_volume, current_path);
>         if (!dp) {
>                 ret = EFI_OUT_OF_RESOURCES;
>                 goto out;
> @@ -1560,6 +1689,7 @@ out:
>         free(tmp);
>         free(bo->optional_data);
>         free(bo->description);
> +       free(bo->file_info.uri);
>         free(bo->file_info.current_path);
>         free(bo->initrd_info.current_path);
>         free(bo->fdt_info.current_path);
> diff --git a/include/efi_config.h b/include/efi_config.h
> index d7c1601137e..23211e799fc 100644
> --- a/include/efi_config.h
> +++ b/include/efi_config.h
> @@ -82,6 +82,7 @@ struct eficonfig_item {
>   * @current_volume:    pointer to the efi_simple_file_system_protocol
>   * @dp_volume:         pointer to device path of the selected device
>   * @current_path:      pointer to the selected file path string
> + * @uri:               URI for HTTP Boot
>   * @filepath_list:     list_head structure for file path list
>   * @file_selectred:    flag indicates file selecting status
>   */
> @@ -89,6 +90,7 @@ struct eficonfig_select_file_info {
>         struct efi_simple_file_system_protocol *current_volume;
>         struct efi_device_path *dp_volume;
>         u16 *current_path;
> +       u16 *uri;
>         struct list_head filepath_list;
>         bool file_selected;
>  };
> --
> 2.34.1
>


More information about the U-Boot mailing list