libfdisk: (dos) Add function fdisk_dos_fix_chs() for fixing CHS values for all partitions
This function fixes beginning and ending CHS values for every partition according to LBA relative offset, relative beginning and size and fdisk idea of disk geometry (sectors per track and number of heads). This function may be used for repairing existing partitions to be compatible with CHS addressing. Signed-off-by: Pali Rohár <pali.rohar@gmail.com>
This commit is contained in:
parent
e63d9ab1d6
commit
dac364addb
|
@ -220,6 +220,7 @@ DOS_FLAG_ACTIVE
|
|||
fdisk_dos_enable_compatible
|
||||
fdisk_dos_is_compatible
|
||||
fdisk_dos_move_begin
|
||||
fdisk_dos_fix_chs
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
|
|
@ -780,10 +780,10 @@ static inline int chs_overflowed(unsigned int c, unsigned int h, unsigned int s)
|
|||
return (c == 1023 && (h == 254 || h == 255) && s == 63);
|
||||
}
|
||||
|
||||
static inline int lba_overflowed(unsigned int start, unsigned int sects)
|
||||
static inline int lba_overflowed(fdisk_sector_t start, fdisk_sector_t sects)
|
||||
{
|
||||
/* Check if the last LBA sector can be represented by unsigned int */
|
||||
return (start + (sects-1) < start);
|
||||
/* Check if the last LBA sector can be represented by unsigned 32bit int */
|
||||
return (start + (sects-1) > UINT32_MAX);
|
||||
}
|
||||
|
||||
static void get_partition_table_geometry(struct fdisk_context *cxt,
|
||||
|
@ -2586,6 +2586,87 @@ static int dos_reorder(struct fdisk_context *cxt)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* fdisk_dos_fix_chs:
|
||||
* @cxt: fdisk context
|
||||
*
|
||||
* Fix beginning and ending C/H/S values for every partition
|
||||
* according to LBA relative offset, relative beginning and
|
||||
* size and fdisk idea of disk geometry (sectors per track
|
||||
* and number of heads).
|
||||
*
|
||||
* Returns: number of fixed (changed) partitions.
|
||||
*/
|
||||
int fdisk_dos_fix_chs(struct fdisk_context *cxt)
|
||||
{
|
||||
unsigned int obc, obh, obs; /* old beginning c, h, s */
|
||||
unsigned int oec, oeh, oes; /* old ending c, h, s */
|
||||
unsigned int nbc, nbh, nbs; /* new beginning c, h, s */
|
||||
unsigned int nec, neh, nes; /* new ending c, h, s */
|
||||
fdisk_sector_t l, sects; /* lba beginning and size */
|
||||
struct dos_partition *p;
|
||||
struct pte *pe;
|
||||
int changed = 0;
|
||||
size_t i;
|
||||
|
||||
assert(fdisk_is_label(cxt, DOS));
|
||||
|
||||
for (i = 0; i < cxt->label->nparts_max; i++) {
|
||||
p = self_partition(cxt, i);
|
||||
if (!p || !is_used_partition(p))
|
||||
continue;
|
||||
|
||||
pe = self_pte(cxt, i);
|
||||
|
||||
/* old beginning c, h, s */
|
||||
obc = cylinder(p->bs, p->bc);
|
||||
obh = p->bh;
|
||||
obs = sector(p->bs);
|
||||
|
||||
/* old ending c, h, s */
|
||||
oec = cylinder(p->es, p->ec);
|
||||
oeh = p->eh;
|
||||
oes = sector(p->es);
|
||||
|
||||
/* new beginning c, h, s */
|
||||
l = get_abs_partition_start(pe);
|
||||
long2chs(cxt, l, &nbc, &nbh, &nbs);
|
||||
if (l > UINT32_MAX || nbc >= 1024) {
|
||||
nbc = 1023;
|
||||
nbh = cxt->geom.heads-1;
|
||||
nbs = cxt->geom.sectors;
|
||||
}
|
||||
|
||||
/* new ending c, h, s */
|
||||
sects = dos_partition_get_size(p);
|
||||
long2chs(cxt, l + sects - 1, &nec, &neh, &nes);
|
||||
if (lba_overflowed(l, sects) || nec >= 1024) {
|
||||
nec = 1023;
|
||||
neh = cxt->geom.heads-1;
|
||||
nes = cxt->geom.sectors;
|
||||
}
|
||||
|
||||
if (obc != nbc || obh != nbh || obs != nbs ||
|
||||
oec != nec || oeh != neh || oes != nes) {
|
||||
DBG(LABEL, ul_debug("DOS: changing %zu partition CHS "
|
||||
"from (%d, %d, %d)-(%d, %d, %d) "
|
||||
"to (%d, %d, %d)-(%d, %d, %d)",
|
||||
i+1, obc, obh, obs, oec, oeh, oes,
|
||||
nbc, nbh, nbs, nec, neh, nes));
|
||||
p->bc = nbc & 0xff;
|
||||
p->bh = nbh;
|
||||
p->bs = nbs | ((nbc >> 2) & 0xc0);
|
||||
p->ec = nec & 0xff;
|
||||
p->eh = neh;
|
||||
p->es = nes | ((nec >> 2) & 0xc0);
|
||||
partition_set_changed(cxt, i, 1);
|
||||
changed++;
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
/* TODO: use fdisk_set_partition() API */
|
||||
int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i)
|
||||
{
|
||||
|
|
|
@ -619,6 +619,7 @@ extern int fdisk_iter_get_direction(struct fdisk_iter *itr);
|
|||
/* dos.c */
|
||||
#define DOS_FLAG_ACTIVE 1
|
||||
|
||||
extern int fdisk_dos_fix_chs(struct fdisk_context *cxt);
|
||||
extern int fdisk_dos_move_begin(struct fdisk_context *cxt, size_t i);
|
||||
extern int fdisk_dos_enable_compatible(struct fdisk_label *lb, int enable);
|
||||
extern int fdisk_dos_is_compatible(struct fdisk_label *lb);
|
||||
|
|
|
@ -316,3 +316,7 @@ FDISK_2.36 {
|
|||
fdisk_label_advparse_parttype;
|
||||
fdisk_label_get_parttype_shortcut;
|
||||
} FDISK_2.35;
|
||||
|
||||
FDISK_2.38 {
|
||||
fdisk_dos_fix_chs;
|
||||
} FDISK_2.36;
|
||||
|
|
Loading…
Reference in New Issue