Skip to content

Commit

Permalink
Improve GRUB2 boot to also adhere UEFI spec (home-assistant#1830)
Browse files Browse the repository at this point in the history
  • Loading branch information
agners committed May 10, 2022
1 parent e98edce commit c809071
Showing 1 changed file with 30 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
From 74d815143bb9b504fb54d3eaf0ed3e382b26000a Mon Sep 17 00:00:00 2001
Message-Id: <74d815143bb9b504fb54d3eaf0ed3e382b26000a.1651759401[email protected]>
In-Reply-To: <184b6a054e04bb4c7fb4885a30d62314229dc551.1651759401[email protected]>
References: <184b6a054e04bb4c7fb4885a30d62314229dc551.1651759401[email protected]>
From e3c27254802e1d7ebaa64df8edb93b0a899f1678 Mon Sep 17 00:00:00 2001
Message-Id: <e3c27254802e1d7ebaa64df8edb93b0a899f1678.1652212828[email protected]>
In-Reply-To: <184b6a054e04bb4c7fb4885a30d62314229dc551.1652212828[email protected]>
References: <184b6a054e04bb4c7fb4885a30d62314229dc551.1652212828[email protected]>
From: Stefan Agner <[email protected]>
Date: Thu, 5 May 2022 15:46:51 +0200
Subject: [PATCH] efidisk: pass buffers with higher alignment
Expand All @@ -14,45 +14,57 @@ 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
a higher alignment already.

Signed-off-by: Stefan Agner <[email protected]>
---
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

0 comments on commit c809071

Please sign in to comment.