Skip to content

Commit

Permalink
image-hd: fix CHS addresses in EBR
Browse files Browse the repository at this point in the history
All CHS addresses in the EBR should point to absolute address in the
image instead of the relative addresses, currently they are only
LBA-to-CHS conversion of the relative offsets. If correct, output of
`sfdisk -d` of the genimage-produced disk image piped back to `sfdisk
file.img` should produce binary identical (see note below) output.
However, it is not true, because the CHS addresses differ. Even though
the extended partition uses the 0xf type (LBA addressing) and CHS
addressing is limited to 1023 sectors, the generated output should be
comparable to other tools for easier debugging.

With this change the calculation of CHS addresses of the next EBRs and
logical partitions within the extended partition adds the proper offset,
so the addresses are absolute within the image.

Note: At least with the version of sfdisk I have tested with (from
util-linux 2.37.2), the image is not completely identical - there are
one byte differences in the MBR and each MBR. This is because even if
the partition type is set as 0xf, sfdisk produces the extended partition
and all the logical partition with 0x5 type.

Signed-off-by: Jan Čermák <[email protected]>
  • Loading branch information
sairon authored and michaelolbrich committed Jun 21, 2024
1 parent b3eac8e commit 86d9a34
Showing 1 changed file with 13 additions and 7 deletions.
20 changes: 13 additions & 7 deletions image-hd.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,12 @@ static void lba_to_chs(unsigned int lba, unsigned char *chs)
chs[2] = (c & 0xff);
}

static void hdimage_setup_chs(struct mbr_partition_entry *entry)
static void hdimage_setup_chs(struct mbr_partition_entry *entry,
unsigned long long offset_sectors)
{
lba_to_chs(entry->relative_sectors, entry->first_chs);
lba_to_chs(entry->relative_sectors + entry->total_sectors - 1,
lba_to_chs(entry->relative_sectors + offset_sectors,
entry->first_chs);
lba_to_chs(entry->relative_sectors + entry->total_sectors - 1 + offset_sectors,
entry->last_chs);
}

Expand Down Expand Up @@ -173,7 +175,7 @@ static int hdimage_insert_mbr(struct image *image, struct list_head *partitions)
entry->relative_sectors = (hd->extended_lba)/512;
entry->total_sectors = (image->size - hd->extended_lba)/512;
}
hdimage_setup_chs(entry);
hdimage_setup_chs(entry, 0);

if (part->extended)
break;
Expand All @@ -191,7 +193,7 @@ static int hdimage_insert_mbr(struct image *image, struct list_head *partitions)
entry->relative_sectors = 1;
entry->total_sectors = hd->gpt_location / 512 + GPT_SECTORS - 2;

hdimage_setup_chs(entry);
hdimage_setup_chs(entry, 0);
}

mbr.boot_signature = htole16(0xaa55);
Expand Down Expand Up @@ -226,7 +228,9 @@ static int hdimage_insert_ebr(struct image *image, struct partition *part)
entry->partition_type = part->partition_type;
entry->relative_sectors = hd->align/512;
entry->total_sectors = part->size/512;
hdimage_setup_chs(entry);
// absolute CHS address of the logical partition
// equals to absolute partition offset
hdimage_setup_chs(entry, (part->offset - hd->align) / 512);
struct partition *p = part;
list_for_each_entry_continue(p, &image->partitions, list) {
if (!p->extended)
Expand All @@ -236,7 +240,9 @@ static int hdimage_insert_ebr(struct image *image, struct partition *part)
entry->partition_type = 0x0F;
entry->relative_sectors = (p->offset - hd->align - hd->extended_lba)/512;
entry->total_sectors = (p->size + hd->align)/512;
hdimage_setup_chs(entry);
// absolute CHS address of the next EBR
// equals to relative address within extended partition + partition start
hdimage_setup_chs(entry, hd->extended_lba / 512);
break;
}

Expand Down

0 comments on commit 86d9a34

Please sign in to comment.