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 has grown since v1. It started as a big-endian correctness fix
noticed while auditing the file, and once the new test in patch 4 could
drive a real block device on a big-endian target it turned up two more
problems in the same family, both of which make a table written on
big-endian useless.

Patch 3 from v1 was dropped in favor of outright removal of the old MAC
partition label support, as suggested by Heinrich (already in next).

Patches 3 and 4 add the C tests, which are complementary rather than
alternatives. Patch 3 drives gpt_fill_header()/gpt_fill_pte() with a
synthetic descriptor, which is the only practical way to sweep block
sizes from 512 to 32768, but it can never reach anything that touches the
medium. Patch 5 backs a blkmap device with plain memory and does a full
write/verify/parse round trip, covering set_protective_mbr(),
is_pmbr_valid(), gpt_verify_headers(), is_gpt_valid() and
part_get_info_efi(). Both live in the lib suite rather than test/dm/,
because UT_DM depends on SANDBOX and test/dm/part.c is built for sandbox
only, whereas test/lib/ is built for every board with CONFIG_UNIT_TEST.

Patch 5 enables EFI_PARTITION and BLKMAP on malta64 so both tests are
actually built and run on a big-endian target. malta64 already sets
CONFIG_UNIT_TEST and already runs the full pytest suite in CI as the
qemu_malta64 job, and ut subtests are collected from u-boot.sym, so no CI
change is needed. malta64 rather than malta because hdr_start/pte_start
in gpt_fill_pte() are size_t: on a 32-bit big-endian target an
unconverted __le64 truncates to zero and the overlap check still happens
to reject an overlap, while on MIPS64 it does not.

Patches 6 and 7 add the sandbox-side python test. Patch 6 is a
prerequisite: 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.

Still not covered: gpt_verify_partitions() and friends now have
big-endian coverage against a device U-Boot wrote itself, but nothing
checks that U-Boot parses a spec-conformant table produced by someone
else on big-endian. That needs a real disk image attached to the QEMU
target, which means teaching u-boot-test-hooks to pass one and, for the
4Kn case, using virtio-blk rather than IDE, since drivers/block/ide.c
hardcodes ATA_BLOCKSIZE. I am happy to look at that separately if it is
wanted.

Tested by building sandbox (default, flattree, sandbox64, spl, vpl, gcc
and clang), generic-rk3576, sonoff-ihost-rv1126,
A20-OLinuXino_MICRO-eMMC, turris_mox, boston64r2, qemu-ppce500 and all
four malta variants, with no new warnings on any commit of the series,
and by running the full sandbox pytest suite plus 'ut lib' on malta64
under qemu-system-mips64.

CI passes all green: 
https://git.u-boot-project.org/u-boot/contributors/alchark/u-boot/-/pipelines/1326

Signed-off-by: Alexey Charkov <[email protected]>
---
Changes in v2:
- Rebased onto next
- Patch 1: reword the commit message only. The entry array is sized from
  num_partition_entries and sizeof_partition_entry rather than a fixed
  128-byte entry, and the two counts that could disagree are now named.
  No code change.
- Patch 2: also convert the protective MBR fields and the GPT partition
  names, and fix print_efiname() to match. Both were found by running the
  new patch 4 test on big-endian, and both make a table written on
  big-endian unreadable. Dropped the v1 Reviewed-by tags from this patch,
  since it grew three hunks nobody has seen.
- Patch 3 (old): superseded by the removal of part_mac
- Patch 3: moved out of test/dm/part.c into test/lib/, so it is built and
  run on boards other than sandbox.
- Patch 4 is new: a GPT write/verify/parse round trip against a
  memory-backed blkmap device, which covers the paths a synthetic
  descriptor cannot reach.
- Patch 5 is new: enable EFI_PARTITION and BLKMAP on malta64 so both C
  tests run on a big-endian target in CI.
- Patch 6: unbind the 4096-byte device at the end of the new test, so it
  does not leak into whatever runs next.
- Link to v1: 
https://patch.msgid.link/[email protected]

To: [email protected]
To: Patrice Chotard <[email protected]>
To: Patrick Delaunay <[email protected]>
Cc: Tom Rini <[email protected]>
Cc: Alexey Charkov <[email protected]>
Cc: Ilias Apalodimas <[email protected]>
Cc: Denis Mukhin <[email protected]>
Cc: Simon Glass <[email protected]>
Cc: Paul Burton <[email protected]>
Cc: Heinrich Schuchardt <[email protected]>

---
Alexey Charkov (7):
      disk: part_efi: Size the partition entry array from the block size
      disk: part_efi: Add missing endianness conversions
      test: lib: Check the GPT layout for large sector sizes
      test: lib: Check the GPT round trip against a real block device
      configs: malta64: Enable EFI_PARTITION and BLKMAP for big-endian tests
      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

 configs/malta64_defconfig |   2 +
 disk/part_efi.c           |  66 ++++++++----
 test/lib/Makefile         |   1 +
 test/lib/part_efi.c       | 257 ++++++++++++++++++++++++++++++++++++++++++++++
 test/py/tests/test_gpt.py | 120 ++++++++++++++++++++++
 5 files changed, 425 insertions(+), 21 deletions(-)
---
base-commit: b8e0086b585791a771416ce51b58ce0097bc0b28
change-id: 20260731-gpt-4k-f8b9e3fad474

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

Reply via email to