From 925984c09f01119f3ff19cd40f6d559894234d82 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Wed, 11 May 2022 01:51:30 +0200 Subject: [PATCH] Improve GRUB2 boot to also adhere UEFI spec (#1830) (#1893) --- ...k-pass-buffers-with-higher-alignment.patch | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/buildroot-external/patches/grub2/0003-efidisk-pass-buffers-with-higher-alignment.patch b/buildroot-external/patches/grub2/0003-efidisk-pass-buffers-with-higher-alignment.patch index 2d3be553cb0..51205cfec51 100644 --- a/buildroot-external/patches/grub2/0003-efidisk-pass-buffers-with-higher-alignment.patch +++ b/buildroot-external/patches/grub2/0003-efidisk-pass-buffers-with-higher-alignment.patch @@ -1,7 +1,7 @@ -From 74d815143bb9b504fb54d3eaf0ed3e382b26000a Mon Sep 17 00:00:00 2001 -Message-Id: <74d815143bb9b504fb54d3eaf0ed3e382b26000a.1651759401.git.stefan@agner.ch> -In-Reply-To: <184b6a054e04bb4c7fb4885a30d62314229dc551.1651759401.git.stefan@agner.ch> -References: <184b6a054e04bb4c7fb4885a30d62314229dc551.1651759401.git.stefan@agner.ch> +From e3c27254802e1d7ebaa64df8edb93b0a899f1678 Mon Sep 17 00:00:00 2001 +Message-Id: +In-Reply-To: <184b6a054e04bb4c7fb4885a30d62314229dc551.1652212828.git.stefan@agner.ch> +References: <184b6a054e04bb4c7fb4885a30d62314229dc551.1652212828.git.stefan@agner.ch> From: Stefan Agner Date: Thu, 5 May 2022 15:46:51 +0200 Subject: [PATCH] efidisk: pass buffers with higher alignment @@ -14,12 +14,18 @@ That particular system has IoAlign set to 2, and sometimes returns status 7 when buffers with alignment of 2 are passed. Things seem to work fine with buffers aligned to 4 bytes. -It seems that IoAlign > 1 means 2 ^ IoAlign. There is also such a hint -in an example printed in the Driver Writer's Guide: +It seems that some system interpret IoAlign > 1 to mean 2 ^ IoAlign. +There is also such a hint in an example printed in the Driver Writer's +Guide: ScsiPassThruMode.IoAlign = 2; // Data must be alligned on 4-byte boundary -Pass 2 ^ IoAlign aligned buffers to make sure GRUB2 works properly on -all systems. +However, some systems (e.g. U-Boot and some drivers in EDK II) do follow +the UEFI specification. + +Work around by using an alignment of at least 512 bytes in case +alignment is requested. Also make sure that IoAlign is still respected +as per UEFI specification if a higher alignment than block size is +requested. Note: The problem has only noticed with compressed squashfs. It seems that ext4 (and presumably other file system drivers) pass buffers with @@ -27,32 +33,38 @@ a higher alignment already. Signed-off-by: Stefan Agner --- - grub-core/disk/efi/efidisk.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) + grub-core/disk/efi/efidisk.c | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c -index 9e20af70e..eaf22367f 100644 +index 9e20af70e..c4eb4f4e7 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c -@@ -553,8 +553,16 @@ grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector, +@@ -553,8 +553,22 @@ grub_efidisk_readwrite (struct grub_disk *disk, grub_disk_addr_t sector, d = disk->data; bio = d->block_io; - /* Set alignment to 1 if 0 specified */ - io_align = bio->media->io_align ? bio->media->io_align : 1; + /* -+ * If IoAlign is > 1, it means alignment by 2^IoAlign -+ * Note: UEFI spec claims alignment by IoAlign. But there are systems -+ * with IoAlign=2 which return status 7 if 2 bytes aligned buffers are -+ * passed. ++ * If IoAlign is > 1, it should represent the required alignment. However, ++ * some UEFI implementation on Intel NUC systems seem to use IoAlign=2 but ++ * require 2^IoAlign. ++ * Make sure to align to at least block size if IO alignment is required. + */ + if (bio->media->io_align > 1) -+ io_align = 1 << bio->media->io_align; ++ { ++ if (bio->media->io_align < bio->media->block_size) ++ io_align = bio->media->block_size; ++ else ++ io_align = bio->media->io_align; ++ } + else + io_align = 1; ++ num_bytes = size << disk->log_sector_size; if ((grub_addr_t) buf & (io_align - 1)) -- -2.36.0 +2.36.1