Re: [PATCH 4/6] test: dm: part: Check the GPT layout for large sector sizes

Heinrich Schuchardt <[email protected]>
Newsgroups org.u-boot-project.lists.u-boot
Message-ID <[email protected]>
On 7/31/26 14:40, Alexey Charkov wrote:
> Add a test that runs gpt_fill_header() and gpt_fill_pte() over a range of
> block sizes and checks that the partition entry array is sized and placed
> consistently, in particular that the backup array ends exactly where the
> backup GPT header begins.
> 
> Neither function performs any block I/O, so the test builds a synthetic
> struct blk_desc rather than needing a block device with a configurable
> block size. The expected array size is taken from the GPT header fields
> rather than from GPT_ENTRY_NUMBERS, so the test still holds for builds
> with a non-default CONFIG_EFI_PARTITION_ENTRIES_NUMBERS, such as
> ARCH_SUNXI with 56 entries.
> 
> Without the preceding fixes this fails on the first block size other than
> 512:
> 
>    test/dm/part.c:313, dm_test_part_gpt_blksz():
>        entry_lba + pte_blks == first_lba: Expected 0x12 (18), got 0x22 (34)
> 
> Signed-off-by: Alexey Charkov <[email protected]>

Thank you for providing the new test.

test/dm/part.c is never tested in the CI on big-endian systems as it is 
restricted to the sandbox.

The sandbox restriction arises because test/dm/part.c relies on MMC 
drives emulated on the sandbox. We should instead create memory backed 
BLKMAP devices. Then we can run the partition table tests on QEMU and on 
real hardware.

For your new test I would suggest to simply move it to a new file in 
test/lib/ as it does not rely on the presence of block devices.

Heinrich

> ---
>   test/dm/part.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 100 insertions(+)
> 
> diff --git a/test/dm/part.c b/test/dm/part.c
> index ad37d7f406f4..4b48322fb807 100644
> --- a/test/dm/part.c
> +++ b/test/dm/part.c
> @@ -5,6 +5,8 @@
>   
>   #include <dm.h>
>   #include <env.h>
> +#include <malloc.h>
> +#include <memalign.h>
>   #include <mmc.h>
>   #include <part.h>
>   #include <part_efi.h>
> @@ -248,3 +250,101 @@ static int dm_test_part_get_info_by_uuid(struct unit_test_state *uts)
>   	return 0;
>   }
>   DM_TEST(dm_test_part_get_info_by_uuid, UTF_SCAN_PDATA | UTF_SCAN_FDT);
> +
> +/*
> + * Check that the GPT layout adapts to the block size of the device. Neither
> + * gpt_fill_header() nor gpt_fill_pte() does any block I/O, so a synthetic
> + * descriptor is enough here; partition_entries_offset() reads the device tree
> + * '/config' node, which is available without scanning for devices.
> + */
> +static int dm_test_part_gpt_blksz(struct unit_test_state *uts)
> +{
> +	static const struct {
> +		unsigned long blksz;
> +		lbaint_t lba;
> +	} cases[] = {
> +		{   512, 0x2000 },	/* 4MB, the traditional 34-block layout */
> +		{  1024, 0x1000 },
> +		{  2048,  0x800 },
> +		{  4096,  0x400 },	/* 4K native media, e.g. UFS */
> +		{  8192,  0x200 },
> +		{ 16384,  0x100 },	/* the array fits in a single block... */
> +		{ 32768,   0x40 },	/* ...on a device smaller than 34 blocks */
> +	};
> +
> +	char str_disk_guid[UUID_STR_LEN + 1] =
> +		"8d60b397-1bb6-4d33-80ee-b1587d24c2f8";
> +	struct disk_partition part;
> +	struct blk_desc desc;
> +	gpt_header gpt_h;
> +	gpt_entry *gpt_e;
> +	int i;
> +
> +	gpt_e = calloc(GPT_ENTRY_NUMBERS, sizeof(gpt_entry));
> +	ut_assertnonnull(gpt_e);
> +
> +	for (i = 0; i < ARRAY_SIZE(cases); i++) {
> +		u64 entry_lba, first_lba, last_lba;
> +		u32 pte_blks;
> +
> +		memset(&desc, '\0', sizeof(desc));
> +		memset(&gpt_h, '\0', sizeof(gpt_h));
> +		desc.blksz = cases[i].blksz;
> +		desc.log2blksz = LOG2(desc.blksz);
> +		desc.lba = cases[i].lba;
> +
> +		ut_assertok(gpt_fill_header(&desc, &gpt_h, str_disk_guid, 1));
> +
> +		/*
> +		 * Size the array with BLOCK_CNT() rather than the
> +		 * DIV_ROUND_UP() that gpt_pte_blocks() uses, so that this
> +		 * checks the layout instead of restating the implementation.
> +		 */
> +		pte_blks = BLOCK_CNT(le32_to_cpu(gpt_h.num_partition_entries) *
> +				     le32_to_cpu(gpt_h.sizeof_partition_entry),
> +				     (&desc));
> +		entry_lba = le64_to_cpu(gpt_h.partition_entry_lba);
> +		first_lba = le64_to_cpu(gpt_h.first_usable_lba);
> +		last_lba = le64_to_cpu(gpt_h.last_usable_lba);
> +
> +		ut_asserteq_64(1, le64_to_cpu(gpt_h.my_lba));
> +		ut_asserteq_64(desc.lba - 1, le64_to_cpu(gpt_h.alternate_lba));
> +
> +		/* the primary array ends where the usable area begins */
> +		ut_assert(entry_lba >= 2);
> +		ut_asserteq_64(entry_lba + pte_blks, first_lba);
> +		ut_assert(first_lba < last_lba);
> +
> +		/*
> +		 * write_gpt_table() puts the backup array at
> +		 * last_usable_lba + 1, so it has to end exactly where the
> +		 * backup header begins
> +		 */
> +		ut_asserteq_64(le64_to_cpu(gpt_h.alternate_lba),
> +			       last_lba + 1 + pte_blks);
> +
> +		/* a partition with no start and no size fills the disk */
> +		memset(&part, '\0', sizeof(part));
> +		disk_partition_set_uuid(&part, str_disk_guid);
> +		ut_assertok(gpt_fill_pte(&desc, &gpt_h, gpt_e, &part, 1));
> +		ut_asserteq_64(first_lba, le64_to_cpu(gpt_e[0].starting_lba));
> +		ut_asserteq_64(last_lba, le64_to_cpu(gpt_e[0].ending_lba));
> +
> +		/* a partition overlapping the entry array is rejected */
> +		part.start = entry_lba;
> +		part.size = 1;
> +		ut_asserteq(-ENOSPC,
> +			    gpt_fill_pte(&desc, &gpt_h, gpt_e, &part, 1));
> +
> +		/* so is one running past the end of the usable area */
> +		part.start = first_lba;
> +		part.size = last_lba - first_lba + 2;
> +		ut_asserteq(-E2BIG,
> +			    gpt_fill_pte(&desc, &gpt_h, gpt_e, &part, 1));
> +	}
> +
> +	free(gpt_e);
> +
> +	return 0;
> +}
> +DM_TEST(dm_test_part_gpt_blksz, 0);
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.