[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v4 5/6] efi: implement LoadFile2 initrd loading protocol for
From: |
Daniel Kiper |
Subject: |
Re: [PATCH v4 5/6] efi: implement LoadFile2 initrd loading protocol for Linux |
Date: |
Mon, 17 Oct 2022 17:07:38 +0200 |
User-agent: |
NeoMutt/20170113 (1.7.2) |
On Thu, Sep 08, 2022 at 03:30:16PM +0200, Ard Biesheuvel wrote:
> Recent Linux kernels will invoke the LoadFile2 protocol installed on
> a well-known vendor media path to load the initrd if it is exposed by
> the firmware. Using this method is preferred for two reasons:
> - the Linux kernel is in charge of allocating the memory, and so it can
> implement any placement policy it wants (given that these tend to
> change between kernel versions),
> - it is no longer necessary to modify the device tree provided by the
> firmware.
>
> So let's install this protocol when handling the 'initrd' command if
> such a recent kernel was detected (based on the PE/COFF image version),
> and defer loading the initrd contents until the point where the kernel
> invokes the LoadFile2 protocol.
>
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> Reviewed-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
> Tested-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
> ---
> grub-core/commands/efi/lsefi.c | 1 +
> grub-core/loader/arm64/linux.c | 123 +++++++++++++++++++-
> include/grub/efi/api.h | 40 +++++++
> 3 files changed, 163 insertions(+), 1 deletion(-)
>
> diff --git a/grub-core/commands/efi/lsefi.c b/grub-core/commands/efi/lsefi.c
> index f46ba3b49384..c304d25ccdd6 100644
> --- a/grub-core/commands/efi/lsefi.c
> +++ b/grub-core/commands/efi/lsefi.c
> @@ -55,6 +55,7 @@ struct known_protocol
> { GRUB_EFI_ABSOLUTE_POINTER_PROTOCOL_GUID, "absolute pointer" },
> { GRUB_EFI_DRIVER_BINDING_PROTOCOL_GUID, "EFI driver binding" },
> { GRUB_EFI_LOAD_FILE_PROTOCOL_GUID, "load file" },
> + { GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID, "load file2" },
> { GRUB_EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "simple FS" },
> { GRUB_EFI_TAPE_IO_PROTOCOL_GUID, "tape I/O" },
> { GRUB_EFI_UNICODE_COLLATION_PROTOCOL_GUID, "unicode collation" },
> diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c
> index 56ba8d0a6ea3..8b7fbb35fb72 100644
> --- a/grub-core/loader/arm64/linux.c
> +++ b/grub-core/loader/arm64/linux.c
> @@ -48,6 +48,39 @@ static grub_uint32_t cmdline_size;
> static grub_addr_t initrd_start;
> static grub_addr_t initrd_end;
>
> +static struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
Please drop redundant spaces after "{" and before "}".
> +static grub_efi_handle_t initrd_lf2_handle = NULL;
> +static int initrd_use_loadfile2 = 0;
I think you can use bool here.
> +static grub_efi_guid_t load_file2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID;
> +static grub_efi_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 grub_efi_status_t __grub_efi_api
> +grub_efi_initrd_load_file2(grub_efi_load_file2_t *this,
Missing space before "(".
> + grub_efi_device_path_t *device_path,
> + grub_efi_boolean_t boot_policy,
> + grub_efi_uintn_t *buffer_size,
> + void *buffer);
> +
> +static grub_efi_load_file2_t initrd_lf2 = {
> + grub_efi_initrd_load_file2
> +};
> +
> grub_err_t
> grub_arch_efi_linux_load_image_header (grub_file_t file,
> struct linux_arch_kernel_header * lh)
> @@ -78,6 +111,18 @@ grub_arch_efi_linux_load_image_header (grub_file_t file,
> return grub_error(GRUB_ERR_FILE_READ_ERROR, "failed to read COFF
> image header");
> }
>
> + /*
> + * Linux kernels built for any architecture are guaranteed to support the
> + * LoadFile2 based initrd loading protocol if the image version is >= 1.
> + */
> + if (lh->coff_image_header.optional_header.major_image_version >= 1)
> + initrd_use_loadfile2 = 1;
> + else
> + initrd_use_loadfile2 = 0;
> +
> + grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n",
> + initrd_use_loadfile2 ? "en" : "dis");
> +
> return GRUB_ERR_NONE;
> }
>
> @@ -197,6 +242,8 @@ grub_linux_boot (void)
> static grub_err_t
> grub_linux_unload (void)
> {
> + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
> +
> grub_dl_unref (my_mod);
> loaded = 0;
> if (initrd_start)
> @@ -208,6 +255,18 @@ grub_linux_unload (void)
> grub_efi_free_pages ((grub_addr_t) kernel_addr,
> GRUB_EFI_BYTES_TO_PAGES (kernel_size));
> grub_fdt_unload ();
> +
> + if (initrd_lf2_handle)
initrd_lf2_handle != NULL
> + {
> + b->uninstall_multiple_protocol_interfaces (initrd_lf2_handle,
> + &load_file2_guid,
> + &initrd_lf2,
> + &device_path_guid,
> + &initrd_lf2_device_path,
> + NULL);
> + initrd_lf2_handle = NULL;
> + initrd_use_loadfile2 = 0;
> + }
> return GRUB_ERR_NONE;
> }
>
> @@ -247,13 +306,50 @@ allocate_initrd_mem (int initrd_pages)
> GRUB_EFI_LOADER_DATA);
> }
>
> +static grub_efi_status_t __grub_efi_api
> +grub_efi_initrd_load_file2(grub_efi_load_file2_t *this,
Missing space before "(".
> + grub_efi_device_path_t *device_path,
> + grub_efi_boolean_t boot_policy,
> + grub_efi_uintn_t *buffer_size,
> + void *buffer)
> +{
> + grub_efi_status_t status = GRUB_EFI_SUCCESS;
> + grub_efi_uintn_t initrd_size;
> +
> + if (this != &initrd_lf2 || 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;
> +
> + initrd_size = grub_get_initrd_size (&initrd_ctx);
> + if (buffer == NULL || *buffer_size < initrd_size)
> + {
> + *buffer_size = initrd_size;
> + return GRUB_EFI_BUFFER_TOO_SMALL;
> + }
> +
> + grub_dprintf ("linux", "Providing initrd via EFI_LOAD_FILE2_PROTOCOL\n");
> +
> + if (grub_initrd_load (&initrd_ctx, buffer))
> + status = GRUB_EFI_DEVICE_ERROR;
> +
> + grub_initrd_close (&initrd_ctx);
> + return status;
> +}
> +
> static grub_err_t
> grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
> int argc, char *argv[])
> {
> - struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 };
> int initrd_size, initrd_pages;
> void *initrd_mem = NULL;
> + grub_efi_boot_services_t *b = grub_efi_system_table->boot_services;
> + grub_efi_status_t status;
>
> if (argc == 0)
> {
> @@ -271,6 +367,31 @@ grub_cmd_initrd (grub_command_t cmd __attribute__
> ((unused)),
> if (grub_initrd_init (argc, argv, &initrd_ctx))
> goto fail;
>
> + if (initrd_use_loadfile2)
> + {
> + if (!initrd_lf2_handle)
initrd_lf2_handle = NULL
Daniel
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [PATCH v4 5/6] efi: implement LoadFile2 initrd loading protocol for Linux,
Daniel Kiper <=