aboutsummaryrefslogtreecommitdiffstats
path: root/sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch
diff options
context:
space:
mode:
authorPA4WDH2021-08-25 12:02:32 +0200
committerPA4WDH2021-08-25 12:02:32 +0200
commit38be1b3221b1e85cac1af8a67c733752265425d7 (patch)
tree62805f905167039e00378ede54f5dd41203bc577 /sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch
parentAdd patch to sys-boot/u-boot-2021.07 to make it work (diff)
downloadunmatched-patchwork-38be1b3221b1e85cac1af8a67c733752265425d7.tar.gz
unmatched-patchwork-38be1b3221b1e85cac1af8a67c733752265425d7.tar.bz2
unmatched-patchwork-38be1b3221b1e85cac1af8a67c733752265425d7.zip
Add sys-boot/grub-2.06-r1
Diffstat (limited to 'sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch')
-rw-r--r--sys-boot/grub/files/grub-2.06-003-efi-implemented-loadfile2-initrd-loading.patch180
1 files changed, 180 insertions, 0 deletions
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 <ard.biesheuvel@arm.com>
+Signed-off-by: Nikita Ermakov <arei@altlinux.org>
+---
+ 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