74 lines
3.0 KiB
Diff
74 lines
3.0 KiB
Diff
From 7eaacdbf00ec29931553384f914c229c6078582e Mon Sep 17 00:00:00 2001
|
|
Message-Id: <7eaacdbf00ec29931553384f914c229c6078582e.1652945863.git.stefan@agner.ch>
|
|
In-Reply-To: <184b6a054e04bb4c7fb4885a30d62314229dc551.1652945863.git.stefan@agner.ch>
|
|
References: <184b6a054e04bb4c7fb4885a30d62314229dc551.1652945863.git.stefan@agner.ch>
|
|
From: Stefan Agner <stefan@agner.ch>
|
|
Date: Thu, 5 May 2022 15:46:51 +0200
|
|
Subject: [PATCH] efidisk: pass buffers with higher alignment
|
|
|
|
Some devices report a IoAlign value of 2, however seem to require a
|
|
buffer with higher alignment.
|
|
|
|
The UEFI specification is saying: "IoAlign values of 0 and 1 mean that
|
|
the buffer can be placed anywhere in memory. Otherwise, IoAlign must
|
|
be a power of 2, and the requirement is that the start address of a
|
|
buffer must be evenly divisible by IoAlign with no remainder."
|
|
|
|
It seems that this got misinterpreted by some vendors assuming IoAlign
|
|
is 2^IoAlign. There is also such a hint in an example in earlier
|
|
versions of the Driver Writer's Guide:
|
|
ScsiPassThruMode.IoAlign = 2; // Data must be alligned on 4-byte boundary
|
|
|
|
However, it is unsafe to just blindly align buffers by 2^IoAlign, as
|
|
this would lead to an overflow for systems which use block size
|
|
alignment (e.g. 512 bytes, for example U-Boot).
|
|
|
|
Ontop of that, some devices seem to report no alignment requirements
|
|
but seem to read corrupt data or report read errors if the buffer is
|
|
not aligned.
|
|
|
|
Work around by using an alignment of at least BlockSize (typically 512
|
|
bytes) in any casea. 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.
|
|
|
|
Acked-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
|
|
Signed-off-by: Stefan Agner <stefan@agner.ch>
|
|
---
|
|
grub-core/disk/efi/efidisk.c | 15 +++++++++++++--
|
|
1 file changed, 13 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
|
|
index 9e20af70e..c6e37f131 100644
|
|
--- a/grub-core/disk/efi/efidisk.c
|
|
+++ b/grub-core/disk/efi/efidisk.c
|
|
@@ -553,8 +553,19 @@ 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 should represent the required alignment. However,
|
|
+ * some UEFI implementation on Intel NUC systems seem to use IoAlign=2 but
|
|
+ * require 2^IoAlign. Some implementation seem to require alignment despite
|
|
+ * not reporting any requirements.
|
|
+ *
|
|
+ * Make sure to align to at least block size in any case.
|
|
+ */
|
|
+ if (bio->media->io_align < bio->media->block_size)
|
|
+ io_align = bio->media->block_size;
|
|
+ else
|
|
+ io_align = bio->media->io_align;
|
|
+
|
|
num_bytes = size << disk->log_sector_size;
|
|
|
|
if ((grub_addr_t) buf & (io_align - 1))
|
|
--
|
|
2.36.1
|
|
|