From: Pali Rohár Date: Fri, 30 Jul 2021 09:01:36 +0000 (+0200) Subject: libfdisk: (dos) Add function dos_partition_sync_chs() for updating CHS values X-Git-Tag: v2.38-rc1~327^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e63d9ab1d604c786f3bc84f0206407433c241951;p=thirdparty%2Futil-linux.git libfdisk: (dos) Add function dos_partition_sync_chs() for updating CHS values Call this function everytime after changing either relative LBA partition offset or LBA partition size to ensure that CHS values are in sync with LBA. This should fix partition CHS values after moving or deleting partition. Signed-off-by: Pali Rohár --- diff --git a/include/pt-mbr.h b/include/pt-mbr.h index 1a38246f19..0f014cd88b 100644 --- a/include/pt-mbr.h +++ b/include/pt-mbr.h @@ -58,6 +58,28 @@ static inline void dos_partition_set_size(struct dos_partition *p, unsigned int __dos_store_4le(p->nr_sects, n); } +static inline void dos_partition_sync_chs(struct dos_partition *p, unsigned long long int part_offset, unsigned int geom_sectors, unsigned int geom_heads) +{ + unsigned long long int start = part_offset + dos_partition_get_start(p); + unsigned long long int stop = start + dos_partition_get_size(p) - 1; + unsigned int spc = geom_heads * geom_sectors; + + if (start / spc > 1023) + start = spc * 1024 - 1; + if (stop / spc > 1023) + stop = spc * 1024 - 1; + + p->bc = (start / spc) & 0xff; + p->bh = (start / geom_sectors) % geom_heads; + p->bs = ((start % geom_sectors + 1) & 0x3f) | + (((start / spc) >> 2) & 0xc0); + + p->ec = (stop / spc) & 0xff; + p->eh = (stop / geom_sectors) % geom_heads; + p->es = ((stop % geom_sectors + 1) & 0x3f) | + (((stop / spc) >> 2) & 0xc0); +} + static inline int mbr_is_valid_magic(const unsigned char *mbr) { return mbr[510] == 0x55 && mbr[511] == 0xaa ? 1 : 0; diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c index 475a2265dd..0ace22666f 100644 --- a/libfdisk/src/dos.c +++ b/libfdisk/src/dos.c @@ -83,15 +83,6 @@ static const struct fdisk_shortcut dos_parttype_cuts[] = { .shortcut = "X", .alias = "linuxex", .data = "85" } /* Linux extended */ }; -#define set_hsc(h,s,c,sector) { \ - s = sector % cxt->geom.sectors + 1; \ - sector /= cxt->geom.sectors; \ - h = sector % cxt->geom.heads; \ - sector /= cxt->geom.heads; \ - c = sector & 0xff; \ - s |= (sector >> 2) & 0xc0; \ - } - #define sector(s) ((s) & 0x3f) #define cylinder(s, c) ((c) | (((s) & 0xc0) << 2)) @@ -471,6 +462,7 @@ static int delete_partition(struct fdisk_context *cxt, size_t partnum) *p = *q; dos_partition_set_start(p, dos_partition_get_start(q)); dos_partition_set_size(p, dos_partition_get_size(q)); + dos_partition_sync_chs(p, pe->offset, cxt->geom.sectors, cxt->geom.heads); partition_set_changed(cxt, partnum - 1, 1); } else if (cxt->label->nparts_max > 5) { @@ -482,6 +474,7 @@ static int delete_partition(struct fdisk_context *cxt, size_t partnum) get_abs_partition_start(pe) - l->ext_offset); pe->offset = l->ext_offset; + dos_partition_sync_chs(p, pe->offset, cxt->geom.sectors, cxt->geom.heads); partition_set_changed(cxt, 5, 1); } @@ -1024,13 +1017,7 @@ static void set_partition(struct fdisk_context *cxt, p->sys_ind = sysid; dos_partition_set_start(p, start - offset); dos_partition_set_size(p, stop - start + 1); - - if (start/(cxt->geom.sectors*cxt->geom.heads) > 1023) - start = cxt->geom.heads*cxt->geom.sectors*1024 - 1; - set_hsc(p->bh, p->bs, p->bc, start); - if (stop/(cxt->geom.sectors*cxt->geom.heads) > 1023) - stop = cxt->geom.heads*cxt->geom.sectors*1024 - 1; - set_hsc(p->eh, p->es, p->ec, stop); + dos_partition_sync_chs(p, offset, cxt->geom.sectors, cxt->geom.heads); partition_set_changed(cxt, i, 1); } @@ -2517,7 +2504,9 @@ again: /* Recount starts according to EBR offsets, the absolute * address still has to be the same! */ dos_partition_set_start(cur->pt_entry, nxt_start - cur->offset); + dos_partition_sync_chs(cur->pt_entry, cur->offset, cxt->geom.sectors, cxt->geom.heads); dos_partition_set_start(nxt->pt_entry, cur_start - nxt->offset); + dos_partition_sync_chs(nxt->pt_entry, nxt->offset, cxt->geom.sectors, cxt->geom.heads); partition_set_changed(cxt, i, 1); partition_set_changed(cxt, i + 1, 1); @@ -2662,6 +2651,7 @@ int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i) dos_partition_set_size(p, sects); dos_partition_set_start(p, new); + dos_partition_sync_chs(p, pe->offset, cxt->geom.sectors, cxt->geom.heads); partition_set_changed(cxt, i, 1); }