From 86d9a340280a6303f09264a76d13a22d5c77e425 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= Date: Thu, 30 May 2024 16:26:37 +0200 Subject: [PATCH] image-hd: fix CHS addresses in EBR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- image-hd.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/image-hd.c b/image-hd.c index d1fe303..7651def 100644 --- a/image-hd.c +++ b/image-hd.c @@ -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); } @@ -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; @@ -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); @@ -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) @@ -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; }