From 38be1b3221b1e85cac1af8a67c733752265425d7 Mon Sep 17 00:00:00 2001 From: PA4WDH Date: Wed, 25 Aug 2021 12:02:32 +0200 Subject: Add sys-boot/grub-2.06-r1 --- ...-efi-implemented-loadfile2-initrd-loading.patch | 180 +++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch (limited to 'sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch') diff --git a/sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch b/sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch new file mode 100644 index 0000000..65fdf2e --- /dev/null +++ b/sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch @@ -0,0 +1,180 @@ +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 +Signed-off-by: Nikita Ermakov +--- + grub-core/loader/arm64/linux.c | 117 ++++++++++++++++++++++++++++++++- + 1 file changed, 116 insertions(+), 1 deletion(-) + +diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c +index aed7a200b..6b03455d1 100644 +--- a/grub-core/loader/arm64/linux.c ++++ b/grub-core/loader/arm64/linux.c +@@ -48,9 +48,18 @@ 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 }; ++static grub_efi_handle_t initrd_lf2_handle; ++static int initrd_use_loadfile2; ++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; ++ + grub_err_t + grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) + { ++ struct grub_pe32_coff_header *coff_header; ++ struct grub_pe32_optional_header *optional_header; ++ + if (lh->magic != GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) + return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); + +@@ -61,6 +70,21 @@ grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) + grub_dprintf ("linux", "UEFI stub kernel:\n"); + grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset); + ++ coff_header = (struct grub_pe32_coff_header *)((unsigned long)lh + lh->hdr_offset); ++ optional_header = (struct grub_pe32_optional_header *)(coff_header + 1); ++ ++ /* ++ * Linux kernels built for any architecture are guaranteed to support the ++ * LoadFile2 based initrd loading protocol if the image version is >= 1. ++ */ ++ if (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; + } + +@@ -230,13 +254,86 @@ allocate_initrd_mem (int initrd_pages) + GRUB_EFI_LOADER_DATA); + } + ++struct initrd_media_device_path { ++ grub_efi_vendor_media_device_path_t vendor; ++ grub_efi_device_path_t end; ++} GRUB_PACKED; ++ ++#define LINUX_EFI_INITRD_MEDIA_GUID \ ++ { 0x5568e427, 0x68fc, 0x4f3d, \ ++ { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \ ++ } ++ ++static struct initrd_media_device_path 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_initrd_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 grub_efi_load_file2_t initrd_lf2 = { ++ grub_efi_initrd_load_file2 ++}; ++ ++static grub_efi_status_t ++grub_efi_initrd_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_status_t status = GRUB_EFI_SUCCESS; ++ grub_efi_uintn_t initrd_size; ++ ++ if (!this || this != &initrd_lf2 || !buffer_size) ++ 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 || *buffer_size < initrd_size) ++ { ++ *buffer_size = initrd_size; ++ return GRUB_EFI_BUFFER_TOO_SMALL; ++ } ++ ++ grub_dprintf ("linux", "Providing initrd via LOAD_FILE2_PROTOCOL\n"); ++ ++ if (grub_initrd_load (&initrd_ctx, buffer)) ++ status = GRUB_EFI_LOAD_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_status_t status; + + if (argc == 0) + { +@@ -254,6 +351,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + if (grub_initrd_init (argc, argv, &initrd_ctx)) + goto fail; + ++ if (initrd_use_loadfile2 && !initrd_lf2_handle) ++ { ++ b = grub_efi_system_table->boot_services; ++ status = b->install_multiple_protocol_interfaces (&initrd_lf2_handle, ++ &load_file2_guid, ++ &initrd_lf2, ++ &device_path_guid, ++ &initrd_lf2_device_path, ++ NULL); ++ if (status == GRUB_EFI_OUT_OF_RESOURCES) ++ { ++ grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); ++ return grub_errno; ++ } ++ grub_dprintf ("linux", "LoadFile2 initrd loading protocol installed\n"); ++ return GRUB_ERR_NONE; ++ } ++ + initrd_size = grub_get_initrd_size (&initrd_ctx); + grub_dprintf ("linux", "Loading initrd\n"); + +-- +2.29.3 -- cgit v1.2.3