All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ilias Apalodimas <ilias.apalodimas@linaro.org>
To: Masahisa Kojima <masahisa.kojima@linaro.org>
Cc: u-boot@lists.denx.de, Heinrich Schuchardt <xypron.glpk@gmx.de>,
	Simon Glass <sjg@chromium.org>,
	Takahiro Akashi <takahiro.akashi@linaro.org>,
	Mark Kettenis <mark.kettenis@xs4all.nl>
Subject: Re: [PATCH v13 5/9] bootmenu: add removable media entries
Date: Thu, 25 Aug 2022 11:03:06 +0300	[thread overview]
Message-ID: <Ywcsuj8KpQQXAa3T@hades> (raw)
In-Reply-To: <CADQ0-X_n5SuCQ+rcZyR3xy4FyHbJqWhz7HgtMH0oCwjE9=-S+w@mail.gmail.com>

[...]

> > > media devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL,
> > > add it as new UEFI boot option(BOOT####) and update BootOrder
> > > variable. This automatically generated UEFI boot option
> > > has the dedicated guid in the optional_data to distinguish it from
> > > the UEFI boot option user adds manually. This optional_data is
> > > removed when the efi bootmgr loads the selected UEFI boot option.
> > >
> > > This commit also provides the BOOT#### variable maintenance feature.
> > > Depending on the system hardware setup, some devices
> > > may not exist at a later system boot, so bootmenu checks the
> > > available device in each bootmenu invocation and automatically
> > > removes the BOOT#### variable corrensponding to the non-existent
> > > media device.
> > >
> >
> > Maybe I am doing something wrong here and this has been discussed in the
> > past, but here's what I get by testing this.
> >
> > - The automatic scanning of boot options seems to be happening only when
> >   "Change boot order" menu is selected.  Isn't it better to do it on
> >   eficonfig startup ?
> 
> In current design, we can not edit/delete the auto-generated boot options.
> I can move automatic scanning of boot options into the eficonfig startup, but
> it does not affect edit/delete boot options.
> I just do automatic scanning of boot options just before it is used in
> "Change Boot Order".

Fair enough.  Isn't it better to still scan on startup ?
If we ever fix the automatic detected boot options to show up, that would
make sense I guess

> 
> > - Although I can see a variable Boot0000 which holds the device path of the
> >   virtio disk that has the BOOTAA64.EFI file, I can't see that option in
> >   the edit/delete menus
> 
> Is it the auto-generated boot option?
> The auto-generate boot option is not listed in the edit/delete menu,
> discussed with
> Heinrich before[1].

Ok thanks!

Regards
/Ilias
> 
> [1] https://lore.kernel.org/u-boot/2d19f001-a3cb-735e-d615-2f23cb5b254b@gmx.de/
> 
> Thanks,
> Masahisa Kojima
> 
> >
> > Thanks
> > /Ilias
> > > Signed-off-by: Masahisa Kojima <masahisa.kojima@linaro.org>
> > > ---
> > > Changes in v13:
> > > - remove BootOrder variable dependency
> > >
> > > Changes in v12:
> > > - move generate_media_device_boot_option into cmd/eficonfig.c and expose it
> > > - remove unnecessary include file
> > >
> > > Changes in v11:
> > > - update delete_boot_option() parameter
> > >
> > > Changes in v10:
> > > - add function comment
> > > - devname dynamic allocation removes, allocate in stack
> > > - delete BOOT#### when updating BootOrder fails
> > >
> > > Changes in v9:
> > > - update efi_disk_get_device_name() parameter to pass efi_handle_t
> > > - add function comment
> > >
> > > Changes in v8:
> > > - function and structure prefix is changed to "eficonfig"
> > >
> > > Changes in v7:
> > > - rename prepare_media_device_entry() to generate_media_device_boot_option()
> > >
> > > Changes in v6:
> > > - optional_data size is changed to 16bytes
> > > - check the load option size before comparison
> > > - remove guid included in optional_data of auto generated
> > >   entry when loading
> > >
> > > Changes in v5:
> > > - Return EFI_SUCCESS if there is no BootOrder defined
> > > - correctly handle the case if no removable device found
> > > - use guid to identify the automatically generated entry by bootmenu
> > >
> > >  cmd/bootmenu.c               |  22 +++-
> > >  cmd/eficonfig.c              | 209 +++++++++++++++++++++++++++++++++++
> > >  include/efi_config.h         |   1 +
> > >  include/efi_loader.h         |  16 +++
> > >  lib/efi_loader/efi_bootmgr.c |   4 +
> > >  5 files changed, 246 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c
> > > index 704d36debe..3340be1632 100644
> > > --- a/cmd/bootmenu.c
> > > +++ b/cmd/bootmenu.c
> > > @@ -7,7 +7,7 @@
> > >  #include <common.h>
> > >  #include <command.h>
> > >  #include <ansi.h>
> > > -#include <efi_loader.h>
> > > +#include <efi_config.h>
> > >  #include <efi_variable.h>
> > >  #include <env.h>
> > >  #include <log.h>
> > > @@ -220,7 +220,7 @@ static int prepare_bootmenu_entry(struct bootmenu_data *menu,
> > >       return 1;
> > >  }
> > >
> > > -#if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR))
> > > +#if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR)) && (CONFIG_IS_ENABLED(CMD_EFICONFIG))
> > >  /**
> > >   * prepare_uefi_bootorder_entry() - generate the uefi bootmenu entries
> > >   *
> > > @@ -340,11 +340,21 @@ static struct bootmenu_data *bootmenu_create(int delay)
> > >       if (ret < 0)
> > >               goto cleanup;
> > >
> > > -#if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR))
> > > +#if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR)) && (CONFIG_IS_ENABLED(CMD_EFICONFIG))
> > >       if (i < MAX_COUNT - 1) {
> > > -                     ret = prepare_uefi_bootorder_entry(menu, &iter, &i);
> > > -                     if (ret < 0 && ret != -ENOENT)
> > > -                             goto cleanup;
> > > +             efi_status_t efi_ret;
> > > +
> > > +             /*
> > > +              * UEFI specification requires booting from removal media using
> > > +              * a architecture-specific default image name such as BOOTAA64.EFI.
> > > +              */
> > > +             efi_ret = eficonfig_generate_media_device_boot_option();
> > > +             if (efi_ret != EFI_SUCCESS && efi_ret != EFI_NOT_FOUND)
> > > +                     goto cleanup;
> > > +
> > > +             ret = prepare_uefi_bootorder_entry(menu, &iter, &i);
> > > +             if (ret < 0 && ret != -ENOENT)
> > > +                     goto cleanup;
> > >       }
> > >  #endif
> > >
> > > diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c
> > > index 537f3f2bbc..92171c4894 100644
> > > --- a/cmd/eficonfig.c
> > > +++ b/cmd/eficonfig.c
> > > @@ -1786,6 +1786,215 @@ static efi_status_t eficonfig_process_delete_boot_option(void *data)
> > >       return ret;
> > >  }
> > >
> > > +/**
> > > + * eficonfig_enumerate_boot_option() - enumerate the possible bootable media
> > > + *
> > > + * @opt:             pointer to the media boot option structure
> > > + * @volume_handles:  pointer to the efi handles
> > > + * @count:           number of efi handle
> > > + * Return:           status code
> > > + */
> > > +efi_status_t eficonfig_enumerate_boot_option(struct eficonfig_media_boot_option *opt,
> > > +                                          efi_handle_t *volume_handles, efi_status_t count)
> > > +{
> > > +     u32 i;
> > > +     struct efi_handler *handler;
> > > +     efi_status_t ret = EFI_SUCCESS;
> > > +
> > > +     for (i = 0; i < count; i++) {
> > > +             u16 *p;
> > > +             u16 dev_name[BOOTMENU_DEVICE_NAME_MAX];
> > > +             char *optional_data;
> > > +             struct efi_load_option lo;
> > > +             char buf[BOOTMENU_DEVICE_NAME_MAX];
> > > +             struct efi_device_path *device_path;
> > > +
> > > +             ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler);
> > > +             if (ret != EFI_SUCCESS)
> > > +                     continue;
> > > +             ret = efi_protocol_open(handler, (void **)&device_path,
> > > +                                     efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> > > +             if (ret != EFI_SUCCESS)
> > > +                     continue;
> > > +
> > > +             ret = efi_disk_get_device_name(volume_handles[i], buf, BOOTMENU_DEVICE_NAME_MAX);
> > > +             if (ret != EFI_SUCCESS)
> > > +                     continue;
> > > +
> > > +             p = dev_name;
> > > +             utf8_utf16_strncpy(&p, buf, strlen(buf));
> > > +
> > > +             lo.label = dev_name;
> > > +             lo.attributes = LOAD_OPTION_ACTIVE;
> > > +             lo.file_path = device_path;
> > > +             lo.file_path_length = efi_dp_size(device_path) + sizeof(END);
> > > +             /*
> > > +              * Set the dedicated guid to optional_data, it is used to identify
> > > +              * the boot option that automatically generated by the bootmenu.
> > > +              * efi_serialize_load_option() expects optional_data is null-terminated
> > > +              * utf8 string, so set the "1234567" string to allocate enough space
> > > +              * 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) {
> > > +                     ret = EFI_OUT_OF_RESOURCES;
> > > +                     free(dev_name);
> > > +                     goto out;
> > > +             }
> > > +             /* set the guid */
> > > +             optional_data = (char *)opt[i].lo + (opt[i].size - u16_strsize(u"1234567"));
> > > +             memcpy(optional_data, &efi_guid_bootmenu_auto_generated, sizeof(efi_guid_t));
> > > +     }
> > > +
> > > +out:
> > > +     return ret;
> > > +}
> > > +
> > > +/**
> > > + * eficonfig_delete_invalid_boot_option() - delete non-existing boot option
> > > + *
> > > + * @opt:             pointer to the media boot option structure
> > > + * @count:           number of media boot option structure
> > > + * Return:           status code
> > > + */
> > > +efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_option *opt,
> > > +                                               efi_status_t count)
> > > +{
> > > +     u32 i, j;
> > > +     efi_uintn_t size;
> > > +     efi_status_t ret;
> > > +     void *load_option;
> > > +     struct efi_load_option lo;
> > > +     u16 varname[] = u"Boot####";
> > > +
> > > +     for (i = 0; i <= 0xFFFF; i++) {
> > > +             efi_uintn_t tmp;
> > > +
> > > +             efi_create_indexed_name(varname, sizeof(varname), "Boot", i);
> > > +             load_option = efi_get_var(varname, &efi_global_variable_guid, &size);
> > > +             if (!load_option)
> > > +                     continue;
> > > +
> > > +             tmp = size;
> > > +             ret = efi_deserialize_load_option(&lo, load_option, &size);
> > > +             if (ret != EFI_SUCCESS)
> > > +                     goto next;
> > > +
> > > +             if (size >= sizeof(efi_guid_bootmenu_auto_generated)) {
> > > +                     if (guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated) == 0) {
> > > +                             for (j = 0; j < count; j++) {
> > > +                                     if (opt[j].size == tmp &&
> > > +                                         memcmp(opt[j].lo, load_option, tmp) == 0) {
> > > +                                             opt[j].exist = true;
> > > +                                             break;
> > > +                                     }
> > > +                             }
> > > +
> > > +                             if (j == count) {
> > > +                                     ret = delete_boot_option(i);
> > > +                                     if (ret != EFI_SUCCESS) {
> > > +                                             free(load_option);
> > > +                                             goto out;
> > > +                                     }
> > > +                             }
> > > +                     }
> > > +             }
> > > +next:
> > > +             free(load_option);
> > > +     }
> > > +
> > > +out:
> > > +     return ret;
> > > +}
> > > +
> > > +/**
> > > + * eficonfig_generate_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 also provide the BOOT#### variable maintenance for
> > > + * the media device entries.
> > > + *   - Automatically create the BOOT#### variable for the newly detected device,
> > > + *     this BOOT#### variable is distinguished by the special GUID
> > > + *     stored in the EFI_LOAD_OPTION.optional_data
> > > + *   - If the device is not attached to the system, the associated BOOT#### variable
> > > + *     is automatically deleted.
> > > + *
> > > + * Return:   status code
> > > + */
> > > +efi_status_t eficonfig_generate_media_device_boot_option(void)
> > > +{
> > > +     u32 i;
> > > +     efi_status_t ret;
> > > +     efi_uintn_t count;
> > > +     efi_handle_t *volume_handles = NULL;
> > > +     struct eficonfig_media_boot_option *opt = NULL;
> > > +
> > > +     ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid,
> > > +                                        NULL, &count, (efi_handle_t **)&volume_handles);
> > > +     if (ret != EFI_SUCCESS)
> > > +             return ret;
> > > +
> > > +     opt = calloc(count, sizeof(struct eficonfig_media_boot_option));
> > > +     if (!opt)
> > > +             goto out;
> > > +
> > > +     /* enumerate all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */
> > > +     ret = eficonfig_enumerate_boot_option(opt, volume_handles, count);
> > > +     if (ret != EFI_SUCCESS)
> > > +             goto out;
> > > +
> > > +     /*
> > > +      * System hardware configuration may vary depending on the user setup.
> > > +      * The boot option is automatically added by the bootmenu.
> > > +      * If the device is not attached to the system, the boot option needs
> > > +      * to be deleted.
> > > +      */
> > > +     ret = eficonfig_delete_invalid_boot_option(opt, count);
> > > +     if (ret != EFI_SUCCESS)
> > > +             goto out;
> > > +
> > > +     /* add non-existent boot option */
> > > +     for (i = 0; i < count; i++) {
> > > +             u32 boot_index;
> > > +             u16 var_name[9];
> > > +
> > > +             if (!opt[i].exist) {
> > > +                     ret = eficonfig_get_unused_bootoption(var_name, sizeof(var_name),
> > > +                                                           &boot_index);
> > > +                     if (ret != EFI_SUCCESS)
> > > +                             goto out;
> > > +
> > > +                     ret = efi_set_variable_int(var_name, &efi_global_variable_guid,
> > > +                                                EFI_VARIABLE_NON_VOLATILE |
> > > +                                                EFI_VARIABLE_BOOTSERVICE_ACCESS |
> > > +                                                EFI_VARIABLE_RUNTIME_ACCESS,
> > > +                                                opt[i].size, opt[i].lo, false);
> > > +                     if (ret != EFI_SUCCESS)
> > > +                             goto out;
> > > +
> > > +                     ret = eficonfig_append_bootorder(boot_index);
> > > +                     if (ret != EFI_SUCCESS) {
> > > +                             efi_set_variable_int(var_name, &efi_global_variable_guid,
> > > +                                                  0, 0, NULL, false);
> > > +                             goto out;
> > > +                     }
> > > +             }
> > > +     }
> > > +
> > > +out:
> > > +     if (opt) {
> > > +             for (i = 0; i < count; i++)
> > > +                     free(opt[i].lo);
> > > +     }
> > > +     free(opt);
> > > +     efi_free_pool(volume_handles);
> > > +
> > > +     return ret;
> > > +}
> > > +
> > > +
> > >  /**
> > >   * eficonfig_init() - do required initialization for eficonfig command
> > >   *
> > > diff --git a/include/efi_config.h b/include/efi_config.h
> > > index 974d8ce1ee..55ace89e4a 100644
> > > --- a/include/efi_config.h
> > > +++ b/include/efi_config.h
> > > @@ -92,5 +92,6 @@ efi_status_t eficonfig_select_file_handler(void *data);
> > >  efi_status_t eficonfig_get_unused_bootoption(u16 *buf,
> > >                                            efi_uintn_t buf_size, u32 *index);
> > >  efi_status_t eficonfig_append_bootorder(u16 index);
> > > +efi_status_t eficonfig_generate_media_device_boot_option(void);
> > >
> > >  #endif
> > > diff --git a/include/efi_loader.h b/include/efi_loader.h
> > > index 4461f721e0..6b63ae8dde 100644
> > > --- a/include/efi_loader.h
> > > +++ b/include/efi_loader.h
> > > @@ -953,6 +953,22 @@ struct efi_signature_store {
> > >  struct x509_certificate;
> > >  struct pkcs7_message;
> > >
> > > +/**
> > > + * struct eficonfig_media_boot_option - boot option for (removable) media device
> > > + *
> > > + * This structure is used to enumerate possible boot option
> > > + *
> > > + * @lo:              Serialized load option data
> > > + * @size:    Size of serialized load option data
> > > + * @exist:   Flag to indicate the load option already exists
> > > + *           in Non-volatile load option
> > > + */
> > > +struct eficonfig_media_boot_option {
> > > +     void *lo;
> > > +     efi_uintn_t size;
> > > +     bool exist;
> > > +};
> > > +
> > >  bool efi_hash_regions(struct image_region *regs, int count,
> > >                     void **hash, const char *hash_algo, int *len);
> > >  bool efi_signature_lookup_digest(struct efi_image_regions *regs,
> > > diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c
> > > index ede9116b3c..4b24b41047 100644
> > > --- a/lib/efi_loader/efi_bootmgr.c
> > > +++ b/lib/efi_loader/efi_bootmgr.c
> > > @@ -246,6 +246,10 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle,
> > >       }
> > >
> > >       /* Set load options */
> > > +     if (size >= sizeof(efi_guid_t) &&
> > > +         !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated))
> > > +             size = 0;
> > > +
> > >       if (size) {
> > >               *load_options = malloc(size);
> > >               if (!*load_options) {
> > > --
> > > 2.17.1
> > >

  reply	other threads:[~2022-08-25  8:03 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-24  6:37 [PATCH v13 0/9] enable menu-driven UEFI variable maintenance Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 1/9] eficonfig: menu-driven addition of UEFI boot option Masahisa Kojima
2022-08-24 11:15   ` Ilias Apalodimas
2022-08-25  3:16     ` Masahisa Kojima
2022-08-24 14:19   ` Ilias Apalodimas
2022-08-25  3:17     ` Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 2/9] eficonfig: add "Edit Boot Option" menu entry Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 3/9] menu: add KEY_PLUS, KEY_MINUS and KEY_SPACE handling Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 4/9] eficonfig: add "Delete Boot Option" menu entry Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 5/9] bootmenu: add removable media entries Masahisa Kojima
2022-08-24 13:25   ` Ilias Apalodimas
2022-08-25  3:25     ` Masahisa Kojima
2022-08-25  8:03       ` Ilias Apalodimas [this message]
2022-08-25  8:26         ` Masahisa Kojima
2022-08-24 14:17   ` Ilias Apalodimas
2022-08-25  3:27     ` Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 6/9] eficonfig: add "Change Boot Order" menu entry Masahisa Kojima
2022-08-25  0:11   ` Takahiro Akashi
2022-08-25  2:36     ` Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 7/9] doc:bootmenu: add description for UEFI boot support Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 8/9] doc:eficonfig: add documentation for eficonfig command Masahisa Kojima
2022-08-24  9:13   ` Ilias Apalodimas
2022-08-25  2:11     ` Masahisa Kojima
2022-08-24  6:37 ` [PATCH v13 9/9] test: unit test for eficonfig Masahisa Kojima
2022-08-24  9:09   ` Ilias Apalodimas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Ywcsuj8KpQQXAa3T@hades \
    --to=ilias.apalodimas@linaro.org \
    --cc=mark.kettenis@xs4all.nl \
    --cc=masahisa.kojima@linaro.org \
    --cc=sjg@chromium.org \
    --cc=takahiro.akashi@linaro.org \
    --cc=u-boot@lists.denx.de \
    --cc=xypron.glpk@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.