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]>
