grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] efidisk: pass buffers with higher alignment


From: Heinrich Schuchardt
Subject: Re: [PATCH] efidisk: pass buffers with higher alignment
Date: Mon, 9 May 2022 21:19:30 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.1

On 5/5/22 15:54, Stefan Agner wrote:
Despite the UEFI specification saying "the requirement is that the
start address of a buffer must be evenly divisible by IoAlign with
no remainder.", it seems that a higher alignment requirement is
neecssary on some system (e.g. a Intel NUC system with NVMe SSD).
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:
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.

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 <stefan@agner.ch>
---
  grub-core/disk/efi/efidisk.c | 12 ++++++++++--
  1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c
index f077b5f55..0fc2f0826 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,
    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

The UEFI specification unambiguously says:

"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."

For instance U-Boot will set this value to the sector size (typically
512). As

  0 == (int)(1 << 512)

with your code below you would set the alignment to 0 for U-Boot which
is obviously wrong.

There may be UEFI implementations that are broken. To support these you
might want to set the alignment value to the maximum of sector size and
media->io_align.

Best regards

Heinrich

+   * 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 (bio->media->io_align > 1)
+    io_align = 1 << bio->media->io_align;
+  else
+    io_align = 1;
    num_bytes = size << disk->log_sector_size;

    if ((grub_addr_t) buf & (io_align - 1))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]