diff options
author | Rasmus Villemoes <rasmus.villemoes@prevas.dk> | 2021-03-18 12:39:08 +0100 |
---|---|---|
committer | Rasmus Villemoes <rasmus.villemoes@prevas.dk> | 2021-04-21 12:29:16 +0200 |
commit | 44d5346ae6c8d566199a56076c36f114f524c560 (patch) | |
tree | 708fbbb3ed16c15af50366c2303273e87882dda5 /image-hd.c | |
parent | cd3ceacef26c4d462583c607cf7f58aace9d030b (diff) | |
download | genimage-44d5346ae6c8d566199a56076c36f114f524c560.tar.gz genimage-44d5346ae6c8d566199a56076c36f114f524c560.tar.xz |
image-hd.c: allow partitions to appear out-of-order
GPT partitions, and primary partitions when using MBR, do not need to
appear in order. This can be useful to add new partitions to the
partition table (e.g. including an explicit bootloader partition,
instead of relying on writing it to a raw offset on the block device),
without altering the numbers of previously existing partitions.
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Diffstat (limited to 'image-hd.c')
-rw-r--r-- | image-hd.c | 36 |
1 files changed, 34 insertions, 2 deletions
@@ -482,6 +482,33 @@ static unsigned long long rounddown(unsigned long long value, unsigned long long return value - (value % align); } +static int check_overlap(struct image *image, struct partition *p) +{ + struct partition *q; + + list_for_each_entry(q, &image->partitions, list) { + /* Stop iterating when we reach p. */ + if (p == q) + return 0; + /* We must have that p starts beyond where q ends... */ + if (p->offset >= q->offset + q->size) + continue; + /* ...or vice versa. */ + if (q->offset >= p->offset + p->size) + continue; + + image_error(image, + "partition %s (offset 0x%llx, size 0x%llx) overlaps previous " + "partition %s (offset 0x%llx, size 0x%llx)\n", + p->name, p->offset, p->size, + q->name, q->offset, q->size); + return -EINVAL; + } + /* This should not be reached. */ + image_error(image, "linked list corruption???"); + return -EIO; +} + static int hdimage_setup(struct image *image, cfg_t *cfg) { struct partition *part; @@ -667,7 +694,11 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) return -EINVAL; } if (part->offset && part->in_partition_table) { - if (now > part->offset) { + if (!part->extended) { + int ret = check_overlap(image, part); + if (ret) + return ret; + } else if (now > part->offset) { image_error(image, "part %s overlaps with previous partition\n", part->name); return -EINVAL; @@ -679,7 +710,8 @@ static int hdimage_setup(struct image *image, cfg_t *cfg) part->name, part->size); return -EINVAL; } - now = part->offset + part->size; + if (part->offset + part->size > now) + now = part->offset + part->size; } if (hd->gpt) |