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; + } + + grub_dprintf ("xen_loader", "Providing Xen module via EFI_LOAD_FILE2_PROTOCOL\n"); + + src = (void *) xen_boot_address_align (binary->start, binary->align); + grub_memcpy(buffer, src, size); + + return GRUB_EFI_SUCCESS; +} + static grub_command_t cmd_xen_hypervisor; static grub_command_t cmd_xen_module; diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index b686e8afe..7d0641ade 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -374,6 +374,11 @@ { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \ } +#define XEN_EFI_KERNEL_MEDIA_GUID \ + { 0x2a4847d3, 0x990b, 0x4cf2, \ + { 0x6b, 0xb5, 0x55, 0x71, 0xb4, 0x72, 0x17, 0x21 } \ + } + #define GRUB_EFI_VENDOR_BOOT_LOADER_INTERFACE_GUID \ { 0x4a67b082, 0x0a4c, 0x41cf, \ {0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f } \ -- 2.43.0 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel