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

Sughosh Ganu sughosh.ganu at linaro.org
Thu Jun 26 11:28:52 CEST 2025


On Thu, 26 Jun 2025 at 13:52, Heinrich Schuchardt <xypron.glpk at gmx.de> wrote:
>
> On 24.06.25 14:07, Sughosh Ganu 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>
> > ---
> > Changes since V1:
> > * Move the option for entering the URI under the boot file.
> > * All corresponding changes needed for the above change.
> >
> >   cmd/eficonfig.c      | 113 ++++++++++++++++++++++++++++++++++++++++---
> >   include/efi_config.h |   4 ++
> >   2 files changed, 109 insertions(+), 8 deletions(-)
> >
> > diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> > index 6e14d34a6bd..917d79b8023 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
>
> I am not aware of as standard setting a limit on URI sizes.
>
> https://www.rfc-editor.org/rfc/rfc9110#section-4.1-5 has this
> recommendation:
>
> It is RECOMMENDED that all senders and recipients support, at a minimum,
> URIs with lengths of 8000 octets in protocol elements.
>
> We should determine the length of the URI when the user makes his input.

I had checked the corresponding RFC to check if there was a mention of
size limit on the URI, and there is none. There is a mention about
some applications using 2K as a limit for the URI length. But in
U-Boot's context, I think that 512 bytes is a good enough limit, given
that we are using the URI primarily for specifying distro installation
image's path.

Also, the handle_user_input() function in the eficonfig tool expects a
size limit to be provided for all the user input, and I think this is
a sane thing to do rather than allowing the user to input random
strings. Do you see a realistic use-case where a URI of more than 512
characters might be expected for a boot option?

>
> >   #define EFICONFIG_MENU_HEADER_ROW_NUM 3
> >   #define EFICONFIG_MENU_DESC_ROW_NUM 5
> >
> > @@ -538,6 +539,31 @@ struct efi_device_path *eficonfig_create_device_path(struct efi_device_path *dp_
> >       return dp;
> >   }
> >
> > +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 +1009,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 +1040,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;
> > @@ -1027,6 +1070,13 @@ efi_status_t eficonfig_process_clear_file_selection(void *data)
> >       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,20 +1092,35 @@ 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->boot_file_option ? select_boot_file_menu_items :
> > +             select_file_menu_items;
> > +
> > +     menu_count = file_info->boot_file_option ?
> > +             ARRAY_SIZE(select_boot_file_menu_items) :
> > +             ARRAY_SIZE(select_file_menu_items);
> >
> > -     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));
> > +     menu_items[0].data = data;
> > +     menu_items[1].data = data;
> > +     menu_items[2].data = data;
> > +
> > +     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->boot_file_option ?
> > +                                    "  ** Update File/URI **" :
> > +                                    "  ** Update File **",
> >                                      eficonfig_menu_desc,
> >                                      eficonfig_display_statusline,
> >                                      eficonfig_print_entry,
> >                                      eficonfig_choice_entry);
> > +
> >       if (ret != EFI_SUCCESS) /* User selects "Clear" or "Quit" */
> >               ret = EFI_NOT_READY;
> >
> > @@ -1268,6 +1333,7 @@ static efi_status_t prepare_file_selection_entry(struct efimenu *efi_menu, char
> >       u16_strlcat(file_name, file_info->current_path, len);
> >       ret = create_boot_option_entry(efi_menu, title, file_name,
> >                                      eficonfig_process_show_file_option, file_info);
> > +
> >   out:
> >       free(devname);
> >       free(file_name);
> > @@ -1340,6 +1406,16 @@ out:
> >       return ret;
> >   }
> >
>
> Please, document all functions according to
> https://docs.kernel.org/doc-guide/kernel-doc.html#function-documentation

So I have had this comment from you on my other patches as well. I am
not adding any API in my patch. What exactly is the rule for adding
function documentation? I can understand if some static function
happens to be doing a lot of work, and then it would be easier to
understand its functionality through comments. But I don't think any
function being added in this patch qualifies for such documentation
being needed.

>
> > +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 +1468,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 +1543,14 @@ 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));
>
> Where is the matching free()?

There is one being added below.

>
> Best regards
>
> Heinrich
>
> > +     if (!bo->file_info.uri) {
> > +             ret =  EFI_OUT_OF_RESOURCES;
> > +             goto out;
> > +     }
> > +
> > +     bo->file_info.boot_file_option = true;
> > +
> >       /* copy the preset value */
> >       if (load_option) {
> >               ret = efi_deserialize_load_option(&lo, load_option, &size);
> > @@ -1481,7 +1568,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
> >                       fill_file_info(lo.file_path, &bo->file_info, device_dp);
> >
> >               /* Initrd file path (optional) is placed at second instance. */
> > @@ -1512,6 +1602,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 +1629,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 +1656,7 @@ out:
> >       free(tmp);
> >       free(bo->optional_data);
> >       free(bo->description);
> > +     free(bo->file_info.uri);

This is the matching free.

-sughosh

> >       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..4438933db6a 100644
> > --- a/include/efi_config.h
> > +++ b/include/efi_config.h
> > @@ -82,15 +82,19 @@ 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
> > + * @boot_file_option:        flag indicating if option is for boot file
> >    */
> >   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;
> > +     bool boot_file_option;
> >   };
> >
> >   void eficonfig_print_msg(char *msg);
>


More information about the U-Boot mailing list