diff options
author | Michal Soltys <soltys@ziu.info> | 2014-06-29 21:41:42 +0200 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2014-08-26 18:07:19 -0700 |
commit | d31b445735d186cec01df71c6db2c32c103e9835 (patch) | |
tree | 262828c6e13b554367efdc64fc649d290c186256 | |
parent | 68e8acb564a1b0e591d73edb912aa703c54ba2df (diff) | |
download | syslinux-d31b445735d186cec01df71c6db2c32c103e9835.tar.gz syslinux-d31b445735d186cec01df71c6db2c32c103e9835.tar.xz syslinux-d31b445735d186cec01df71c6db2c32c103e9835.zip |
chain: implement strict=<0|1|2>
This provides more fine grained control than single relax flag. to cover
case with wrong disk sizes.
relax and nostrict are equivalent to strict=0
norelax and strict are equivalent to strict=2
strict=1 does the same as strict=2, but ignores checks against disk size
The current default is strict=1. Options: 'fixchs', '[un]hide[all]' and
'save' will forcibly enable strict=2 (can be overridden by the user).
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | com32/chain/mangle.c | 2 | ||||
-rw-r--r-- | com32/chain/options.c | 30 | ||||
-rw-r--r-- | com32/chain/partiter.c | 14 | ||||
-rw-r--r-- | com32/chain/partiter.h | 2 | ||||
-rw-r--r-- | doc/chain.txt | 27 |
5 files changed, 53 insertions, 22 deletions
diff --git a/com32/chain/mangle.c b/com32/chain/mangle.c index 6963574f..3231e512 100644 --- a/com32/chain/mangle.c +++ b/com32/chain/mangle.c @@ -602,7 +602,7 @@ static int updchs(struct part_iter *iter, int ext) * 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 + * partiter complain about corrupt layout if PIF_STRICT is set), but it * makes everything look silly and not really correct. * * Thus the approach as seen below. diff --git a/com32/chain/options.c b/com32/chain/options.c index 4e722a01..a99e0d7b 100644 --- a/com32/chain/options.c +++ b/com32/chain/options.c @@ -132,7 +132,9 @@ static void usage(void) " keeppxe Keep the PXE and UNDI stacks in memory (PXELINUX)", " warn Wait for a keypress to continue chainloading", " break Don't chainload", -" relax Relax sanity checks", +" strict[=<0|1|2>] Set the level of strictness in sanity checks", +" - strict w/o any value is the same as strict=2", +" relax The same as strict=0", " prefmbr On hybrid MBR/GPT disks, prefer legacy layout", "", " file=<file> Load and execute <file>", @@ -172,6 +174,7 @@ void opt_set_defs(void) opt.maps = true; /* by def. map sector */ opt.hand = true; /* by def. prepare handover */ opt.brkchain = false; /* by def. do chainload */ + opt.piflags = PIF_STRICT; /* by def. be strict, but ignore disk sizes */ opt.foff = opt.soff = opt.fip = opt.sip = 0x7C00; opt.drivename = "boot"; #ifdef DEBUG @@ -303,12 +306,16 @@ int opt_parse_args(int argc, char *argv[]) opt.hide = HIDE_OFF; } else if (!strcmp(argv[i], "hide")) { opt.hide = HIDE_ON; + opt.piflags |= PIF_STRICT | PIF_STRICTER; } else if (!strcmp(argv[i], "hideall")) { opt.hide = HIDE_ON | HIDE_EXT; + opt.piflags |= PIF_STRICT | PIF_STRICTER; } else if (!strcmp(argv[i], "unhide")) { opt.hide = HIDE_ON | HIDE_REV; + opt.piflags |= PIF_STRICT | PIF_STRICTER; } else if (!strcmp(argv[i], "unhideall")) { opt.hide = HIDE_ON | HIDE_EXT | HIDE_REV; + opt.piflags |= PIF_STRICT | PIF_STRICTER; } else if (!strcmp(argv[i], "setbpb")) { opt.setbpb = true; } else if (!strcmp(argv[i], "nosetbpb")) { @@ -329,16 +336,29 @@ int opt_parse_args(int argc, char *argv[]) opt.maps = false; } else if (!strcmp(argv[i], "save")) { opt.save = true; + opt.piflags |= PIF_STRICT | PIF_STRICTER; } else if (!strcmp(argv[i], "nosave")) { opt.save = false; } else if (!strcmp(argv[i], "fixchs")) { opt.fixchs = true; + opt.piflags |= PIF_STRICT | PIF_STRICTER; } else if (!strcmp(argv[i], "nofixchs")) { opt.fixchs = false; - } else if (!strcmp(argv[i], "relax")) { - opt.piflags |= PIF_RELAX; - } else if (!strcmp(argv[i], "norelax")) { - opt.piflags &= ~PIF_RELAX; + } else if (!strcmp(argv[i], "relax") || !strcmp(argv[i], "nostrict")) { + opt.piflags &= ~(PIF_STRICT | PIF_STRICTER); + } else if (!strcmp(argv[i], "norelax") || !strcmp(argv[i], "strict")) { + opt.piflags |= PIF_STRICT | PIF_STRICTER; + } else if (!strncmp(argv[i], "strict=", 7)) { + if (argv[i][7] < '0' || argv[i][7] > '2' || !argv[i][8]) { + error("Strict level must be 0, 1 or 2."); + goto bail; + } + opt.piflags &= ~(PIF_STRICT | PIF_STRICTER); + switch (argv[i][7]) { + case '2': opt.piflags |= PIF_STRICTER; + case '1': opt.piflags |= PIF_STRICT; break; + default:; + } } else if (!strcmp(argv[i], "warn")) { opt.warn = true; } else if (!strcmp(argv[i], "nowarn")) { diff --git a/com32/chain/partiter.c b/com32/chain/partiter.c index 5c5b015b..beeb1bd2 100644 --- a/com32/chain/partiter.c +++ b/com32/chain/partiter.c @@ -176,7 +176,7 @@ static int notsane_logical(const struct part_iter *iter) return -1; } - if (iter->flags & PIF_RELAX) + if (!(iter->flags & PIF_STRICT)) return 0; end_log = dp[0].start_lba + dp[0].length; @@ -215,7 +215,7 @@ static int notsane_extended(const struct part_iter *iter) return -1; } - if (iter->flags & PIF_RELAX) + if (!(iter->flags & PIF_STRICT)) return 0; end_ebr = dp[1].start_lba + dp[1].length; @@ -245,13 +245,13 @@ static int notsane_primary(const struct part_iter *iter) if (!dp->ostype) return 0; - if (iter->flags & PIF_RELAX) + if (!(iter->flags & PIF_STRICT)) return 0; if (!dp->start_lba || !dp->length || !sane(dp->start_lba, dp->length) || - dp->start_lba + dp->length > iter->di.lbacnt) { + ((iter->flags & PIF_STRICTER) && (dp->start_lba + dp->length > iter->di.lbacnt))) { error("Primary partition (in MBR) with invalid offset and/or length."); return -1; } @@ -268,7 +268,7 @@ static int notsane_gpt(const struct part_iter *iter) if (guid_is0(&gp->type)) return 0; - if (iter->flags & PIF_RELAX) + if (!(iter->flags & PIF_STRICT)) return 0; if (gp->lba_first < iter->gpt.ufirst || @@ -602,7 +602,7 @@ static int notsane_gpt_hdr(const struct disk_info *di, const struct disk_gpt_hea uint64_t gpt_lsiz; /* size of GPT partition list in bytes */ uint64_t gpt_lcnt; /* size of GPT partition in sectors */ - if (flags & PIF_RELAX) + if (!(flags & PIF_STRICT)) return 0; gpt_loff = gpth->lba_table; @@ -619,7 +619,7 @@ static int notsane_gpt_hdr(const struct disk_info *di, const struct disk_gpt_hea gpt_loff + gpt_lcnt > gpth->lba_first_usable || !sane(gpth->lba_last_usable, gpt_lcnt) || gpth->lba_last_usable + gpt_lcnt >= gpth->lba_alt || - gpth->lba_alt >= di->lbacnt || + ((flags & PIF_STRICTER) && (gpth->lba_alt >= di->lbacnt)) || gpth->part_size < sizeof(struct disk_gpt_part_entry)) return -1; diff --git a/com32/chain/partiter.h b/com32/chain/partiter.h index d01a6500..22c0e42f 100644 --- a/com32/chain/partiter.h +++ b/com32/chain/partiter.h @@ -46,7 +46,7 @@ enum {PI_ERRLOAD = -31, PI_INSANE, PI_OK = 0, PI_DONE}; /* flags */ -enum {PIF_STEPALL = 1, PIF_RELAX = 2, PIF_PREFMBR = 4}; +enum {PIF_STEPALL = 1, PIF_PREFMBR = 2, PIF_STRICT = 4, PIF_STRICTER = 8}; struct itertype; struct part_iter; diff --git a/doc/chain.txt b/doc/chain.txt index 2321c102..effd508e 100644 --- a/doc/chain.txt +++ b/doc/chain.txt @@ -160,6 +160,7 @@ useful to also fix its BPB values. save *nosave + save sets: strict=2 Fixing BPB values only in memory might not be enough. This option allows writing of the corrected sector. You will probably want to use this option @@ -195,6 +196,7 @@ drive we use during chainloading is not fd0 or hd0. hide[all] unhide[all] *nohide + [un]hide[all] sets: strict=2 In certain situations it's useful to hide partitions - for example to make sure DOS gets C:. 'hide' will hide hidable primary partitions, except the one we're @@ -205,6 +207,7 @@ Writing is only performed, if the os type values actually changed. fixchs *nofixchs + fixchs sets: strict=2 If you want to make a drive you're booting from totally compatible with current BIOS, you can use this to fix all partitions' CHS numbers. Good to silence e.g. @@ -232,15 +235,23 @@ Useful to see warnings emited by the chain module. In the case of presence of non-standard hybrid MBR/GPT layout, this flag makes chain module prefer MBR layout over GPT. + strict[=<0|1|2>] + *strict=1 relax - *norelax - -This option inhibits sanity checks during the traversal of the partition table. -This is potentially useful in corner cases, when for example an usb stick moved -to some different computer would report smaller size than previously with -partitions spanning the whole space. Normally partition iterator would report -an error and abort in such case. Another case scenario is disk corruption in -some later EMBR partition. + +Those options control the level of sanity checks used during the traversal of +partition table(s). This is useful in buggy corner cases, when the disk size is +reported differently across different computers or virtual machines (if it +happens at all, the size usually differs by 1 sector). Normally the partition +iterator would report an error and abort in such case. Another case scenario is +disk corruption in some later EMBR partition. + +- strict=0 inhibits any checks +- strict=1 enables checks, but ignores those that involve disk size +- strict=2 enables all checks +- relax and nostrict are equivalent to strict=0 +- norelax and strict are equivalent to strict=2 + break *nobreak |