aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Soltys <soltys@ziu.info>2014-06-29 21:41:42 +0200
committerH. Peter Anvin <hpa@zytor.com>2014-08-26 18:07:19 -0700
commitd31b445735d186cec01df71c6db2c32c103e9835 (patch)
tree262828c6e13b554367efdc64fc649d290c186256
parent68e8acb564a1b0e591d73edb912aa703c54ba2df (diff)
downloadsyslinux-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.c2
-rw-r--r--com32/chain/options.c30
-rw-r--r--com32/chain/partiter.c14
-rw-r--r--com32/chain/partiter.h2
-rw-r--r--doc/chain.txt27
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