On Wed, Jul 9, 2025 at 2:08 PM Ross Lagerwall <ross.lagerw...@citrix.com> wrote:
>
> On Tue, Jul 8, 2025 at 9:02 PM Frediano Ziglio via Grub-devel
> <grub-devel@gnu.org> wrote:
> >
> > Allows to load modules using LoadFile2 protocol.
> > Add and use a new GUID for kernel media device.
> > This will allow Xen to pick up additional modules using
> > EFI interface instead of using multiboot2 interface (not
> > available on x86_64).
> >
> > Signed-off-by: Frediano Ziglio <frediano.zig...@cloud.com>
> > ---
> >  grub-core/loader/arm64/xen_boot.c | 172 +++++++++++++++++++++++++++++-
> >  include/grub/efi/api.h            |   5 +
> >  2 files changed, 176 insertions(+), 1 deletion(-)
> >
> > diff --git a/grub-core/loader/arm64/xen_boot.c 
> > b/grub-core/loader/arm64/xen_boot.c
> > index 2975a546e..64f685de6 100644
> > --- a/grub-core/loader/arm64/xen_boot.c
> > +++ b/grub-core/loader/arm64/xen_boot.c
> > @@ -68,6 +68,56 @@ enum module_type
> >  };
> >  typedef enum module_type module_type_t;
> >
> > +static grub_guid_t load_file2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID;
> > +static grub_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID;
> > +
> > +static initrd_media_device_path_t initrd_lf2_device_path = {
> > +  {
> > +    {
> > +      GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
> > +      GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE,
> > +      sizeof(grub_efi_vendor_media_device_path_t),
> > +    },
> > +    LINUX_EFI_INITRD_MEDIA_GUID
> > +  }, {
> > +    GRUB_EFI_END_DEVICE_PATH_TYPE,
> > +    GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
> > +    sizeof(grub_efi_device_path_t)
> > +  }
> > +};
> > +
> > +static initrd_media_device_path_t kernel_lf2_device_path = {
> > +  {
> > +    {
> > +      GRUB_EFI_MEDIA_DEVICE_PATH_TYPE,
> > +      GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE,
> > +      sizeof(grub_efi_vendor_media_device_path_t),
> > +    },
> > +    XEN_EFI_KERNEL_MEDIA_GUID
> > +  }, {
> > +    GRUB_EFI_END_DEVICE_PATH_TYPE,
> > +    GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE,
> > +    sizeof(grub_efi_device_path_t)
> > +  }
> > +};
> > +
> > +typedef struct lf2
> > +{
> > +  grub_efi_load_file2_t lf2;
> > +  grub_efi_handle_t handle;
> > +  initrd_media_device_path_t *media;
> > +} lf2_t;
> > +
> > +static grub_efi_status_t __grub_efi_api
> > +grub_efi_load_file2 (grub_efi_load_file2_t *this,
> > +                     grub_efi_device_path_t *device_path,
> > +                     grub_efi_boolean_t boot_policy,
> > +                     grub_efi_uintn_t *buffer_size,
> > +                     void *buffer);
> > +static void lf2_init(lf2_t *lf2, initrd_media_device_path_t *media);
> > +static grub_err_t lf2_start(lf2_t *lf2);
> > +static void lf2_done(lf2_t *lf2);
> > +
> >  struct xen_boot_binary
> >  {
> >    struct xen_boot_binary *next;
> > @@ -80,6 +130,8 @@ struct xen_boot_binary
> >
> >    char *cmdline;
> >    int cmdline_size;
> > +
> > +  lf2_t lf2;
> >  };
> >
> >  static grub_dl_t my_mod;
> > @@ -289,6 +341,8 @@ single_binary_unload (struct xen_boot_binary *binary)
> >                     binary->cmdline, binary->cmdline_size);
> >      }
> >
> > +  lf2_done (&binary->lf2);
> > +
> >    if (!binary->is_hypervisor)
> >      grub_list_remove (GRUB_AS_LIST (binary));
> >
> > @@ -393,6 +447,7 @@ grub_cmd_xen_module (grub_command_t cmd 
> > __attribute__((unused)),
> >    struct xen_boot_binary *module = NULL;
> >    grub_file_t file = 0;
> >    int nounzip = 0;
> > +  initrd_media_device_path_t *media;
> >
> >    if (!argc)
> >      {
> > @@ -427,6 +482,19 @@ grub_cmd_xen_module (grub_command_t cmd 
> > __attribute__((unused)),
> >
> >    module->is_hypervisor = false;
> >    module->align = 4096;
> > +  switch (grub_list_length (GRUB_AS_LIST (module_head)))
> > +    {
> > +    case MODULE_IMAGE:
> > +      media = &kernel_lf2_device_path;
> > +      break;
> > +    case MODULE_INITRD:
> > +      media = &initrd_lf2_device_path;
> > +      break;
> > +    default:
> > +      media = NULL;
> > +      break;
> > +    }
> > +  lf2_init(&module->lf2, media);
> >
> >    grub_dprintf ("xen_loader", "Init module and node info\n");
> >
> > @@ -438,7 +506,10 @@ grub_cmd_xen_module (grub_command_t cmd 
> > __attribute__((unused)),
> >
> >    xen_boot_binary_load (module, file, argc, argv);
> >    if (grub_errno == GRUB_ERR_NONE)
> > -    grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST (module));
> > +    {
> > +      grub_list_push (GRUB_AS_LIST_P (&module_head), GRUB_AS_LIST 
> > (module));
> > +      lf2_start (&module->lf2);
> > +    }
> >
> >   fail:
> >    if (file)
> > @@ -505,6 +576,105 @@ fail:
> >    return grub_errno;
> >  }
> >
> > +static void
> > +lf2_init(lf2_t *lf2, initrd_media_device_path_t *media)
> > +{
> > +  lf2->lf2.load_file = grub_efi_load_file2;
> > +  lf2->handle = NULL;
> > +  lf2->media = media;
> > +}
> > +
> > +static grub_err_t
> > +lf2_start(lf2_t *lf2)
> > +{
> > +  grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
> > +  grub_efi_status_t status;
> > +
> > +  if (lf2->handle)
> > +    return GRUB_ERR_NONE;
> > +
> > +  status = b->install_multiple_protocol_interfaces (&lf2->handle,
> > +                                                   &load_file2_guid,
> > +                                                   &lf2->lf2,
> > +                                                   &device_path_guid,
> > +                                                   lf2->media,
> > +                                                   NULL);
> > +  if (status == GRUB_EFI_OUT_OF_RESOURCES)
> > +    {
> > +      grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory"));
> > +      return grub_errno;
> > +    }
> > +  else if (status != GRUB_EFI_SUCCESS)
> > +    {
> > +      grub_error (GRUB_ERR_BAD_ARGUMENT, N_("failed to install 
> > protocols"));
> > +      return grub_errno;
> > +    }
> > +
> > +  return GRUB_ERR_NONE;
> > +}
> > +
> > +static void
> > +lf2_done(lf2_t *lf2)
> > +{
> > +  grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
> > +
> > +  if (!lf2->handle)
> > +    return;
> > +
> > +  b->uninstall_multiple_protocol_interfaces (lf2->handle,
> > +                                            &load_file2_guid,
> > +                                            &lf2->lf2,
> > +                                            &device_path_guid,
> > +                                            lf2->media,
> > +                                            NULL);
> > +  lf2->handle = NULL;
> > +}
> > +
> > +
> > +static grub_efi_status_t __grub_efi_api
> > +grub_efi_load_file2 (grub_efi_load_file2_t *this,
> > +                     grub_efi_device_path_t *device_path,
> > +                     grub_efi_boolean_t boot_policy,
> > +                     grub_efi_uintn_t *buffer_size,
> > +                     void *buffer)
> > +{
> > +  grub_efi_uintn_t size;
> > +  struct xen_boot_binary *binary, *module;
> > +  const void *src;
> > +
> > +  binary = NULL;
> > +  FOR_LIST_ELEMENTS (module, module_head)
> > +    if (this == &module->lf2.lf2)
> > +      {
> > +        binary = module;
> > +        break;
> > +      }
> > +
> > +  if (!binary || buffer_size == NULL)
> > +    return GRUB_EFI_INVALID_PARAMETER;
> > +
> > +  if (device_path->type != GRUB_EFI_END_DEVICE_PATH_TYPE ||
> > +      device_path->subtype != GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE)
> > +    return GRUB_EFI_NOT_FOUND;
> > +
> > +  if (boot_policy)
> > +    return GRUB_EFI_UNSUPPORTED;
> > +
> > +  size = binary->size;
> > +  if (buffer == NULL || *buffer_size < size)
> > +    {
> > +      *buffer_size = size;
> > +      return GRUB_EFI_BUFFER_TOO_SMALL;
> > +    }
> > +
>
> This is not compliant with the spec:
>
> > BufferSize ... On output with a return code of EFI_SUCCESS, the amount of
> > data transferred to Buffer.
>

From 
https://uefi.org/specs/UEFI/2.10/13_Protocols_Media_Access.html#efi-load-file-protocol-loadfile

BufferSize On input the size of Buffer in bytes. On output with a
return code of EFI_SUCCESS, the amount of data transferred to Buffer.
On output with a return code of EFI_BUFFER_TOO_SMALL, the size of
Buffer required to retrieve the requested file.

It's coherent with the second sentence. Otherwise how does Linux get
the size of the file?

> It looks like you copied this from the EFI Linux loader which has the same
> issue.
>
> Ross

Frediano

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to