The GPT partition entry array is sized in bytes by the spec, so the
number of blocks it takes up depends on the block size of the device.
U-Boot got that wrong in gpt_fill_header(), which reserved a fixed 34
blocks at each end of the disk. On a device with 4096-byte native
sectors, such as UFS flash, the backup entry array ended up 28 blocks
short of the backup GPT header instead of immediately before it, and
roughly 114 KiB was wasted at each end of the disk.

Patch 1 calculates the count from the block size and makes the four
places that need it share one helper, since they disagreed with each
other in different ways. Note that it also changes the 512-byte layout
for boards that do not use the default entry count:
CONFIG_EFI_PARTITION_ENTRIES_NUMBERS is "default 56 if ARCH_SUNXI" and
is set to 64 by a number of Rockchip defconfigs, and on those
first_usable_lba moves from 34 to 16 and 18 respectively. Existing
tables stay readable, since the entry array is always located from the
on-disk partition_entry_lba, and only newly written tables are
affected. Partitions given without an explicit start= will be placed
lower, though, and on sunxi first_usable_lba lands exactly on the 8 KiB
SPL offset, so sunxi and Rockchip folks may want to look at patch 1
specifically (none of the devices I have override the default).

Patch 2 is an unrelated big-endian correctness fix in the same file,
noticed while auditing it: a few header fields are read without
converting from little-endian, and one already-converted value is
swapped a second time.

Patch 3 is another unrelated bug that has to be fixed before any of this
can be tested: part_test_mac() reads one block into a 512-byte on-stack
buffer, so it corrupts the stack on any device with larger blocks. Since
it runs during partition probing on every device, sandbox crashes on any
access at all to a device bound with a 4096-byte block size.

Patches 4 and 6 add the tests. The C test sweeps block sizes from 512 to
32768 against gpt_fill_header()/gpt_fill_pte() with a synthetic
descriptor, and the Python test writes a real GPT to a host device with
4096-byte blocks and checks the resulting on-disk headers. Both fail
without patch 1.

Patch 5 is a prerequisite for patch 6: test_gpt_write_part_type() never
binds its own disk image and has only worked because an earlier test
left host 0 bound, so it breaks as soon as a test binding a different
image is added above it.

One known gap: test_gpt_write and test_gpt_write_part_type hardcode the
128-entry 512-byte layout, so they fail if sandbox is configured with a
different CONFIG_EFI_PARTITION_ENTRIES_NUMBERS. The new tests derive
their expectations instead, and pass at 56 and 64 entries. No sandbox
defconfig upstream uses anything but 128, so I have left the old tests
alone.

Tested by building sandbox (default, flattree, sandbox64, gcc and
clang), generic-rk3576 (gcc and clang), sonoff-ihost-rv1126 and
A20-OLinuXino_MICRO-eMMC on armv7, and boston32r2 and boston64r2 for
MIPS32/MIPS64 big-endian, which is what patch 2 is there for.

Signed-off-by: Alexey Charkov <[email protected]>
---
Alexey Charkov (6):
      disk: part_efi: Size the partition entry array from the block size
      disk: part_efi: Add missing endianness conversions
      disk: part_mac: Fix stack corruption on devices with large blocks
      test: dm: part: Check the GPT layout for large sector sizes
      test: py: gpt: Bind the disk image in test_gpt_write_part_type()
      test: py: gpt: Test the GPT layout on a device with 4096-byte blocks

 disk/part_efi.c           |  55 +++++++++++++++-------
 disk/part_mac.c           |  12 ++---
 test/dm/part.c            | 100 +++++++++++++++++++++++++++++++++++++++
 test/py/tests/test_gpt.py | 116 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 261 insertions(+), 22 deletions(-)
---
base-commit: 100e12ea78c73071b9710f08b32fd4590019266f
change-id: 20260731-gpt-4k-f8b9e3fad474

Best regards,
--  
Alexey Charkov <[email protected]>

Reply via email to