diff options
author | Michal Soltys <soltys@ziu.info> | 2013-02-14 16:51:46 +0100 |
---|---|---|
committer | Michal Soltys <soltys@ziu.info> | 2013-02-14 16:53:05 +0100 |
commit | ed26fef5f0f0deb56abc68857b139c93e5486813 (patch) | |
tree | 8bae4ad4b10fd1c309d144b730d91983561b7e32 | |
parent | b5849a4d28bec1616ac4d2aa67b4ca5b3de55144 (diff) | |
download | syslinux-ed26fef5f0f0deb56abc68857b139c93e5486813.tar.gz |
com32/chain: manglepe_fixchs() correction
We have to be more careful, when in-entry start/length values are 0 (one
or both). Firstly they are relative to the disk or the [B]EBR (while CHS
are absolute). Secondly, length 0 would imply the end CHS being lower
than the start CHS.
Under normal circumstances, partiter would complain about corrupt layout
(unless relax flag is set) and value 0 in any of those fields generally
imply a hole, so the adjustments were harmless - nontheless they made
everything look silly and not really correct.
Adjusted approach is:
- for start entry - if the os entry is 0 /and/ the beginning is 0 -
reset to 0, otherwise calculate chs
- for end entry - as above /or/ length is 0 - reset to 0, otherwise
calculate chs
Signed-off-by: Michal Soltys <soltys@ziu.info>
-rw-r--r-- | com32/chain/mangle.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/com32/chain/mangle.c b/com32/chain/mangle.c index 215ca410..a506e797 100644 --- a/com32/chain/mangle.c +++ b/com32/chain/mangle.c @@ -578,17 +578,47 @@ bail: return 0; } -static int updchs(const struct disk_info *di, - struct disk_dos_part_entry *dp, - uint32_t lba1) +static int updchs(struct part_iter *iter, int ext) { - uint32_t ochs1, ochs2; + struct disk_dos_part_entry *dp; + uint32_t ochs1, ochs2, lba; + dp = (struct disk_dos_part_entry *)iter->record; + if (!ext) { + /* primary or logical */ + lba = (uint32_t)iter->start_lba; + } else { + /* extended */ + dp += 1; + lba = iter->dos.nebr_lba; + } ochs1 = *(uint32_t *)dp->start; ochs2 = *(uint32_t *)dp->end; - lba2chs(&dp->start, di, lba1, L2C_CADD); - lba2chs(&dp->end, di, lba1 + dp->length - 1, L2C_CADD); + /* + * We have to be a bit more careful here in case of 0 start and/or length; + * start = 0 would be converted to the beginning of the disk (C/H/S = + * 0/0/1) or the [B]EBR, length = 0 would actually set the end CHS to be + * lower than the start CHS. + * + * Both are harmless in case of a hole (and in non-hole case will make + * partiter complain about corrupt layout unless PIF_RELAX is set), but it + * makes everything look silly and not really correct. + * + * Thus the approach as seen below. + */ + + if (dp->start_lba || iter->index != -1) { + lba2chs(&dp->start, &iter->di, lba, L2C_CADD); + } else { + memset(&dp->start, 0, sizeof dp->start); + } + + if ((dp->start_lba || iter->index != -1) && dp->length) { + lba2chs(&dp->end, &iter->di, lba + dp->length - 1, L2C_CADD); + } else { + memset(&dp->end, 0, sizeof dp->end); + } return *(uint32_t *)dp->start != ochs1 || @@ -602,7 +632,6 @@ int manglepe_fixchs(struct part_iter *miter) { int wb = 0, werr = 0; struct part_iter *iter = NULL; - struct disk_dos_part_entry *dp; int ridx; if (!opt.fixchs) @@ -618,11 +647,10 @@ int manglepe_fixchs(struct part_iter *miter) while (!pi_next(iter) && !werr) { ridx = iter->index0; - dp = (struct disk_dos_part_entry *)iter->record; - wb |= updchs(&iter->di, dp, iter->start_lba); + wb |= updchs(iter, 0); if (ridx > 3) - wb |= updchs(&iter->di, dp + 1, iter->dos.nebr_lba); + wb |= updchs(iter, 1); /* * we have to update mbr and each extended partition, but only if |