summaryrefslogtreecommitdiffstats
path: root/image-hd.c
diff options
context:
space:
mode:
authorRasmus Villemoes <rasmus.villemoes@prevas.dk>2021-03-18 12:39:08 +0100
committerRasmus Villemoes <rasmus.villemoes@prevas.dk>2021-04-21 12:29:16 +0200
commit44d5346ae6c8d566199a56076c36f114f524c560 (patch)
tree708fbbb3ed16c15af50366c2303273e87882dda5 /image-hd.c
parentcd3ceacef26c4d462583c607cf7f58aace9d030b (diff)
downloadgenimage-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.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/image-hd.c b/image-hd.c
index b773419..766fdde 100644
--- a/image-hd.c
+++ b/image-hd.c
@@ -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)