From d1cf56c24d55921d580cb6d698707bd69fa08500 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Fri, 8 Nov 2024 16:29:40 +0100 Subject: [PATCH 1/2] image-hd: move some helper function to the top of the file Signed-off-by: Michael Olbrich --- image-hd.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/image-hd.c b/image-hd.c index 5839154..3d14262 100644 --- a/image-hd.c +++ b/image-hd.c @@ -109,6 +109,26 @@ ct_assert(sizeof(struct gpt_partition_entry) == 128); #define GPT_PE_FLAG_HIDDEN (1ULL << 62) #define GPT_PE_FLAG_NO_AUTO (1ULL << 63) +static unsigned long long roundup(unsigned long long value, unsigned long long align) +{ + return ((value - 1)/align + 1) * align; +} + +static unsigned long long rounddown(unsigned long long value, unsigned long long align) +{ + return value - (value % align); +} + +static unsigned long long min_ull(unsigned long long x, unsigned long long y) +{ + return x < y ? x : y; +} + +static unsigned long long max_ull(unsigned long long x, unsigned long long y) +{ + return x > y ? x : y; +} + static unsigned long long partition_end(const struct partition *part) { return part->offset + part->size; @@ -659,26 +679,6 @@ static int hdimage_generate(struct image *image) return 0; } -static unsigned long long roundup(unsigned long long value, unsigned long long align) -{ - return ((value - 1)/align + 1) * align; -} - -static unsigned long long rounddown(unsigned long long value, unsigned long long align) -{ - return value - (value % align); -} - -static unsigned long long min_ull(unsigned long long x, unsigned long long y) -{ - return x < y ? x : y; -} - -static unsigned long long max_ull(unsigned long long x, unsigned long long y) -{ - return x > y ? x : y; -} - static bool image_has_hole_covering(const char *image, unsigned long long start, unsigned long long end) { From 1ccb8c342281d51792a6a79cf2049214703d316a Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Fri, 8 Nov 2024 16:30:56 +0100 Subject: [PATCH 2/2] image-hd: set the first usable lba correctly Before this, the begining of the first partition was used. This leaves some unusable space between the partition table and the first partition and causes some Windows versions to alter the GPT. So set the first usable lba correctly: Set it to the first lba after the last non-partition data before the first partition. This will either be directly behind the GPT entry array or, for example after a bootloader that is placed between the partition table and the first partition. Signed-off-by: Michael Olbrich --- image-hd.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/image-hd.c b/image-hd.c index 3d14262..51d2d4f 100644 --- a/image-hd.c +++ b/image-hd.c @@ -483,7 +483,7 @@ static int hdimage_insert_gpt(struct image *image, struct list_head *partitions) const char *outfile = imageoutfile(image); struct gpt_header header; struct gpt_partition_entry table[GPT_ENTRIES]; - unsigned long long smallest_offset = ~0ULL; + unsigned long long smallest_offset = ~0ULL, first_usable_offset = 0; struct partition *part; unsigned i, j; int ret; @@ -526,10 +526,25 @@ static int hdimage_insert_gpt(struct image *image, struct list_head *partitions) i++; } - if (smallest_offset == ~0ULL) - smallest_offset = hd->gpt_location + (GPT_SECTORS - 1)*512; - header.first_usable_lba = htole64(smallest_offset / 512); + /* + * Find the last non-partition data before the first partition. + * This can be a bootloader or the GPT partition table. + */ + list_for_each_entry(part, partitions, list) { + unsigned long long end; + + if (part->in_partition_table) + continue; + + /* ignore the backup partition table at the end of the disk */ + if (strstr(part->name, "GPT backup")) + continue; + end = part->offset + part->size; + if (end <= smallest_offset && end > first_usable_offset) + first_usable_offset = end; + } + header.first_usable_lba = htole64(roundup(first_usable_offset, 512) / 512); header.table_crc = htole32(crc32(table, sizeof(table)));