Improve GRUB2 boot to also adhere UEFI spec (#1830) (#1893)

This commit is contained in:
Stefan Agner 2022-05-11 01:51:30 +02:00 committed by GitHub
parent ba8bda73fa
commit 925984c09f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,7 +1,7 @@
From 74d815143bb9b504fb54d3eaf0ed3e382b26000a Mon Sep 17 00:00:00 2001 From e3c27254802e1d7ebaa64df8edb93b0a899f1678 Mon Sep 17 00:00:00 2001
Message-Id: <74d815143bb9b504fb54d3eaf0ed3e382b26000a.1651759401.git.stefan@agner.ch> Message-Id: <e3c27254802e1d7ebaa64df8edb93b0a899f1678.1652212828.git.stefan@agner.ch>
In-Reply-To: <184b6a054e04bb4c7fb4885a30d62314229dc551.1651759401.git.stefan@agner.ch> In-Reply-To: <184b6a054e04bb4c7fb4885a30d62314229dc551.1652212828.git.stefan@agner.ch>
References: <184b6a054e04bb4c7fb4885a30d62314229dc551.1651759401.git.stefan@agner.ch> References: <184b6a054e04bb4c7fb4885a30d62314229dc551.1652212828.git.stefan@agner.ch>
From: Stefan Agner <stefan@agner.ch> From: Stefan Agner <stefan@agner.ch>
Date: Thu, 5 May 2022 15:46:51 +0200 Date: Thu, 5 May 2022 15:46:51 +0200
Subject: [PATCH] efidisk: pass buffers with higher alignment 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 status 7 when buffers with alignment of 2 are passed. Things seem
to work fine with buffers aligned to 4 bytes. to work fine with buffers aligned to 4 bytes.
It seems that IoAlign > 1 means 2 ^ IoAlign. There is also such a hint It seems that some system interpret IoAlign > 1 to mean 2 ^ IoAlign.
in an example printed in the Driver Writer's Guide: 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 ScsiPassThruMode.IoAlign = 2; // Data must be alligned on 4-byte boundary
Pass 2 ^ IoAlign aligned buffers to make sure GRUB2 works properly on However, some systems (e.g. U-Boot and some drivers in EDK II) do follow
all systems. 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 Note: The problem has only noticed with compressed squashfs. It seems
that ext4 (and presumably other file system drivers) pass buffers with that ext4 (and presumably other file system drivers) pass buffers with
@ -27,32 +33,38 @@ a higher alignment already.
Signed-off-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Stefan Agner <stefan@agner.ch>
--- ---
grub-core/disk/efi/efidisk.c | 12 ++++++++++-- grub-core/disk/efi/efidisk.c | 18 ++++++++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-) 1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c 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 --- a/grub-core/disk/efi/efidisk.c
+++ b/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; d = disk->data;
bio = d->block_io; bio = d->block_io;
- /* Set alignment to 1 if 0 specified */ - /* Set alignment to 1 if 0 specified */
- io_align = bio->media->io_align ? bio->media->io_align : 1; - io_align = bio->media->io_align ? bio->media->io_align : 1;
+ /* + /*
+ * If IoAlign is > 1, it means alignment by 2^IoAlign + * If IoAlign is > 1, it should represent the required alignment. However,
+ * Note: UEFI spec claims alignment by IoAlign. But there are systems + * some UEFI implementation on Intel NUC systems seem to use IoAlign=2 but
+ * with IoAlign=2 which return status 7 if 2 bytes aligned buffers are + * require 2^IoAlign.
+ * passed. + * Make sure to align to at least block size if IO alignment is required.
+ */ + */
+ if (bio->media->io_align > 1) + 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 + else
+ io_align = 1; + io_align = 1;
+
num_bytes = size << disk->log_sector_size; num_bytes = size << disk->log_sector_size;
if ((grub_addr_t) buf & (io_align - 1)) if ((grub_addr_t) buf & (io_align - 1))
-- --
2.36.0 2.36.1