[syslinux:elflink] com32/chain: implement relax flag

syslinux-bot for Michal Soltys soltys at ziu.info
Sat Feb 16 01:48:12 PST 2013


Commit-ID:  c3e12b67d34fbf0efaae33c8b0867ccceb7c5949
Gitweb:     http://www.syslinux.org/commit/c3e12b67d34fbf0efaae33c8b0867ccceb7c5949
Author:     Michal Soltys <soltys at ziu.info>
AuthorDate: Thu, 14 Feb 2013 16:51:46 +0100
Committer:  Michal Soltys <soltys at ziu.info>
CommitDate: Thu, 14 Feb 2013 16:53:05 +0100

com32/chain: implement relax flag

This flag tones down sanity checks during partition iteration.
This is useful in situations such as:

- inconsistent layouts, but with some partition still in sane bootable state
- usb sticks/disks moved between different PCs might return different
  size, which might cause problems if the partitions span the whole disk

Signed-off-by: Michal Soltys <soltys at ziu.info>

---
 com32/chain/chain.c    | 10 +++++-----
 com32/chain/mangle.c   |  4 ++--
 com32/chain/options.c  |  6 ++++++
 com32/chain/options.h  |  1 +
 com32/chain/partiter.c | 17 +++++++++++++++--
 com32/chain/partiter.h |  1 +
 doc/chain.txt          | 14 ++++++++++++--
 7 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/com32/chain/chain.c b/com32/chain/chain.c
index ccfeefa..f1120d9 100644
--- a/com32/chain/chain.c
+++ b/com32/chain/chain.c
@@ -72,7 +72,7 @@ static int find_by_sig(uint32_t mbr_sig,
     for (drive = 0x80; drive < 0x80 + fixed_cnt; drive++) {
 	if (disk_get_params(drive, &diskinfo))
 	    continue;		/* Drive doesn't exist */
-	if (!(boot_part = pi_begin(&diskinfo, 0)))
+	if (!(boot_part = pi_begin(&diskinfo, opt.relax)))
 	    continue;
 	/* Check for a MBR disk */
 	if (boot_part->type != typedos) {
@@ -103,7 +103,7 @@ static int find_by_guid(const struct guid *gpt_guid,
     for (drive = 0x80; drive < 0x80 + fixed_cnt; drive++) {
 	if (disk_get_params(drive, &diskinfo))
 	    continue;		/* Drive doesn't exist */
-	if (!(boot_part = pi_begin(&diskinfo, 0)))
+	if (!(boot_part = pi_begin(&diskinfo, opt.relax)))
 	    continue;
 	/* Check for a GPT disk */
 	if (boot_part->type != typegpt) {
@@ -135,7 +135,7 @@ static int find_by_label(const char *label, struct part_iter **_boot_part)
     for (drive = 0x80; drive < 0x80 + fixed_cnt; drive++) {
 	if (disk_get_params(drive, &diskinfo))
 	    continue;		/* Drive doesn't exist */
-	if (!(boot_part = pi_begin(&diskinfo, 0)))
+	if (!(boot_part = pi_begin(&diskinfo, opt.relax)))
 	    continue;
 	/* Check for a GPT disk */
 	if (!(boot_part->type == typegpt)) {
@@ -324,7 +324,7 @@ int find_dp(struct part_iter **_iter)
 	if (disk_get_params(drive, &diskinfo))
 	    goto bail;
 	/* this will start iteration over FDD, possibly raw */
-	if (!(iter = pi_begin(&diskinfo, 0)))
+	if (!(iter = pi_begin(&diskinfo, opt.relax)))
 	    goto bail;
 
     } else if (!strcmp(opt.drivename, "boot") || !strcmp(opt.drivename, "fs")) {
@@ -344,7 +344,7 @@ int find_dp(struct part_iter **_iter)
 	if (disk_get_params(drive, &diskinfo))
 	    goto bail;
 	/* this will start iteration over disk emulation, possibly raw */
-	if (!(iter = pi_begin(&diskinfo, 0)))
+	if (!(iter = pi_begin(&diskinfo, opt.relax)))
 	    goto bail;
 
 	/* 'fs' => we should lookup the syslinux partition number and use it */
diff --git a/com32/chain/mangle.c b/com32/chain/mangle.c
index b252a66..252128d 100644
--- a/com32/chain/mangle.c
+++ b/com32/chain/mangle.c
@@ -537,7 +537,7 @@ int manglepe_hide(struct part_iter *miter)
     if (miter->index > 4 && !(opt.hide & HIDE_EXT))
 	warn("Specified partition is logical, so it can't be unhidden without 'unhideall'.");
 
-    if (!(iter = pi_begin(&miter->di, PIF_STEPALL)))
+    if (!(iter = pi_begin(&miter->di, PIF_STEPALL | opt.relax)))
 	return -1;
 
     while (!pi_next(iter) && !werr) {
@@ -611,7 +611,7 @@ int manglepe_fixchs(struct part_iter *miter)
 	return -1;
     }
 
-    if (!(iter = pi_begin(&miter->di, PIF_STEPALL)))
+    if (!(iter = pi_begin(&miter->di, PIF_STEPALL | opt.relax)))
 	return -1;
 
     while (!pi_next(iter) && !werr) {
diff --git a/com32/chain/options.c b/com32/chain/options.c
index 93f14f7..209ad01 100644
--- a/com32/chain/options.c
+++ b/com32/chain/options.c
@@ -33,6 +33,7 @@
 #include <string.h>
 #include "common.h"
 #include "chain.h"
+#include "partiter.h"
 #include "utility.h"
 #include "options.h"
 
@@ -123,6 +124,7 @@ 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",
 "",
 "  file=<file>          Load and execute <file>",
 "  seg=<s[:o[:i]]>      Load file at <s:o>, jump to <s:i>",
@@ -324,6 +326,10 @@ int opt_parse_args(int argc, char *argv[])
 	    opt.fixchs = true;
 	} else if (!strcmp(argv[i], "nofixchs")) {
 	    opt.fixchs = false;
+	} else if (!strcmp(argv[i], "relax")) {
+	    opt.relax = PIF_RELAX;
+	} else if (!strcmp(argv[i], "norelax")) {
+	    opt.relax = 0;
 	} else if (!strcmp(argv[i], "warn")) {
 	    opt.warn = true;
 	} else if (!strcmp(argv[i], "nowarn")) {
diff --git a/com32/chain/options.h b/com32/chain/options.h
index ea6e470..ac8f356 100644
--- a/com32/chain/options.h
+++ b/com32/chain/options.h
@@ -64,6 +64,7 @@ struct options {
     bool filebpb;
     bool fixchs;
     bool warn;
+    int relax;
     bool brkchain;
     uint16_t keeppxe;
     struct syslinux_rm_regs regs;
diff --git a/com32/chain/partiter.c b/com32/chain/partiter.c
index 6535719..967769f 100644
--- a/com32/chain/partiter.c
+++ b/com32/chain/partiter.c
@@ -177,6 +177,9 @@ static int notsane_logical(const struct part_iter *iter)
 	return -1;
     }
 
+    if (iter->flags & PIF_RELAX)
+	return 0;
+
     end_log = dp[0].start_lba + dp[0].length;
 
     if (!dp[0].start_lba ||
@@ -213,6 +216,9 @@ static int notsane_extended(const struct part_iter *iter)
 	return -1;
     }
 
+    if (iter->flags & PIF_RELAX)
+	return 0;
+
     end_ebr = dp[1].start_lba + dp[1].length;
 
     if (!dp[1].start_lba ||
@@ -240,6 +246,9 @@ static int notsane_primary(const struct part_iter *iter)
     if (!dp->ostype)
 	return 0;
 
+    if (iter->flags & PIF_RELAX)
+	return 0;
+
     if (!dp->start_lba ||
 	!dp->length ||
 	!sane(dp->start_lba, dp->length) ||
@@ -260,6 +269,9 @@ static int notsane_gpt(const struct part_iter *iter)
     if (guid_is0(&gp->type))
 	return 0;
 
+    if (iter->flags & PIF_RELAX)
+	return 0;
+
     if (gp->lba_first < iter->gpt.ufirst ||
 	gp->lba_last > iter->gpt.ulast) {
 	error("LBA sectors of GPT partition are beyond the range allowed in GPT header.");
@@ -592,14 +604,15 @@ struct part_iter *pi_begin(const struct disk_info *di, int flags)
 	 * it as a sanity check base. EFI doesn't specify max (AFAIK).
 	 * Apart from that, some extensive sanity checks.
 	 */
-	if (!gpt_loff || !gpt_lsiz || gpt_lcnt > 255u ||
+	if (!(flags & PIF_RELAX) && (
+		!gpt_loff || !gpt_lsiz || gpt_lcnt > 255u ||
 		gpth->lba_first_usable > gpth->lba_last_usable ||
 		!sane(gpt_loff, gpt_lcnt) ||
 		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 ||
-		gpth->part_size < sizeof(struct disk_gpt_part_entry)) {
+		gpth->part_size < sizeof(struct disk_gpt_part_entry))) {
 	    error("Invalid GPT header's values.");
 	    goto bail;
 	}
diff --git a/com32/chain/partiter.h b/com32/chain/partiter.h
index 63dc6da..a737584 100644
--- a/com32/chain/partiter.h
+++ b/com32/chain/partiter.h
@@ -47,6 +47,7 @@ enum {PI_OK, PI_DONE, PI_INSANE, PI_ERRLOAD};
 /* flags */
 
 #define PIF_STEPALL 0x01
+#define PIF_RELAX   0x02
 
 struct itertype;
 struct part_iter;
diff --git a/doc/chain.txt b/doc/chain.txt
index e71b1c0..d3c012c 100644
--- a/doc/chain.txt
+++ b/doc/chain.txt
@@ -110,8 +110,8 @@ The defaults, if option is not specified, are 0:0x7c00:0x7c00
 If any of the fields are omitted (e.g. 0x2000::), they default to 0.
 
 	sect=<segment>:<offset>:<ip>
-	nosect
 	*sect=0:0x7c00:0x7c00
+	nosect
 	nosect sets: nomaps
 
 This triplet lets you alter the addresses a sector will use. It's loaded at
@@ -226,8 +226,18 @@ stacks in memory (pxelinux only).
 This option will wait for a keypress right before continuing the chainloading.
 Useful to see warnings emited by the chain module.
 
-	*nobreak
+	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.
+
 	break
+	*nobreak
 	break sets: nofile nomaps nohand
 
 It is possible to trigger a "service-only" run - The chain module will do


More information about the Syslinux-commits mailing list