On 27.06.25 13:25, 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.g...@linaro.org>

Reviwwed-by: Heinrich Schuchardt <xypron.g...@gmx.de>

---
Changes since V2:
* Added comments for eficonfig_create_uri_device_path()
* Added comments for fill_dp_uri()
* Remove some superfluous newlines added

  cmd/eficonfig.c      | 131 ++++++++++++++++++++++++++++++++++++++++---
  include/efi_config.h |   4 ++
  2 files changed, 127 insertions(+), 8 deletions(-)

diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
index 6e14d34a6bd..602d31dca2d 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;
@@ -1027,6 +1079,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,16 +1101,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->boot_file_option ? select_boot_file_menu_items :
+               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_count = file_info->boot_file_option ?
+               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;
+
+       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,
@@ -1340,6 +1413,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 +1486,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 +1561,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));
+       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 +1586,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 +1620,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 +1647,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 +1674,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..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);

Reply via email to