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 | d4ce5b911628423adeb53db8a3cb796f8de2016d (patch) | |
tree | a3c00a9e5fd52d6b1682ce93a64a9ac8d506e211 | |
parent | c3e12b67d34fbf0efaae33c8b0867ccceb7c5949 (diff) | |
download | syslinux-d4ce5b911628423adeb53db8a3cb796f8de2016d.tar.gz syslinux-d4ce5b911628423adeb53db8a3cb796f8de2016d.tar.xz syslinux-d4ce5b911628423adeb53db8a3cb796f8de2016d.zip |
com32/chain: implement handling of non-standard hybrid GPT+MBR layouts
We also take a bit relaxed approach - so we check for presence of 0xEE
at any place, then attempt to read GPT header only if prefmbr is not
set.
Signed-off-by: Michal Soltys <soltys@ziu.info>
-rw-r--r-- | com32/chain/chain.c | 10 | ||||
-rw-r--r-- | com32/chain/mangle.c | 4 | ||||
-rw-r--r-- | com32/chain/options.c | 5 | ||||
-rw-r--r-- | com32/chain/options.h | 15 | ||||
-rw-r--r-- | com32/chain/partiter.c | 7 | ||||
-rw-r--r-- | com32/chain/partiter.h | 5 | ||||
-rw-r--r-- | doc/chain.txt | 6 |
7 files changed, 34 insertions, 18 deletions
diff --git a/com32/chain/chain.c b/com32/chain/chain.c index f1120d93..d6eab7ce 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, opt.relax))) + if (!(boot_part = pi_begin(&diskinfo, opt.relax | opt.prefmbr))) 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, opt.relax))) + if (!(boot_part = pi_begin(&diskinfo, opt.relax | opt.prefmbr))) 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, opt.relax))) + if (!(boot_part = pi_begin(&diskinfo, opt.relax | opt.prefmbr))) 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, opt.relax))) + if (!(iter = pi_begin(&diskinfo, opt.relax | opt.prefmbr))) 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, opt.relax))) + if (!(iter = pi_begin(&diskinfo, opt.relax | opt.prefmbr))) 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 252128da..94e6e90f 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 | opt.relax))) + if (!(iter = pi_begin(&miter->di, PIF_STEPALL | opt.relax | opt.prefmbr))) 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 | opt.relax))) + if (!(iter = pi_begin(&miter->di, PIF_STEPALL | opt.relax | opt.prefmbr))) return -1; while (!pi_next(iter) && !werr) { diff --git a/com32/chain/options.c b/com32/chain/options.c index 209ad017..4044520b 100644 --- a/com32/chain/options.c +++ b/com32/chain/options.c @@ -125,6 +125,7 @@ static void usage(void) " warn Wait for a keypress to continue chainloading", " break Don't chainload", " relax Relax sanity checks", +" prefmbr On hybrid MBR/GPT disks, prefer legacy layout", "", " file=<file> Load and execute <file>", " seg=<s[:o[:i]]> Load file at <s:o>, jump to <s:i>", @@ -334,6 +335,10 @@ int opt_parse_args(int argc, char *argv[]) opt.warn = true; } else if (!strcmp(argv[i], "nowarn")) { opt.warn = false; + } else if (!strcmp(argv[i], "prefmbr")) { + opt.prefmbr = PIF_PREFMBR; + } else if (!strcmp(argv[i], "noprefmbr")) { + opt.prefmbr = 0; } else if (!strcmp(argv[i], "nobreak")) { opt.brkchain = false; } else if (!strcmp(argv[i], "break")) { diff --git a/com32/chain/options.h b/com32/chain/options.h index ac8f356b..5ae41090 100644 --- a/com32/chain/options.h +++ b/com32/chain/options.h @@ -37,16 +37,20 @@ enum {HIDE_OFF = 0, HIDE_ON = 1, HIDE_EXT = 2, HIDE_REV = 4}; struct options { + const char *drivename; + const char *partition; + const char *file; + const char *grubcfg; unsigned int fseg; unsigned int foff; unsigned int fip; unsigned int sseg; unsigned int soff; unsigned int sip; - const char *drivename; - const char *partition; - const char *file; - const char *grubcfg; + int hide; + int relax; + int prefmbr; + uint16_t keeppxe; bool isolinux; bool cmldr; bool drmk; @@ -56,7 +60,6 @@ struct options { bool hand; bool hptr; bool swap; - int hide; bool sect; bool save; bool bss; @@ -64,9 +67,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 967769f6..3c7670d6 100644 --- a/com32/chain/partiter.c +++ b/com32/chain/partiter.c @@ -549,7 +549,7 @@ void pi_del(struct part_iter **_iter) /* pi_begin() - validate and and get proper iterator for a disk described by di */ struct part_iter *pi_begin(const struct disk_info *di, int flags) { - int ret = -1; + int gptprot, ret = -1; struct part_iter *iter; struct disk_dos_mbr *mbr = NULL; struct disk_gpt_header *gpth = NULL; @@ -574,7 +574,10 @@ struct part_iter *pi_begin(const struct disk_info *di, int flags) } /* Check for GPT protective MBR */ - if (mbr->table[0].ostype == 0xEE) { + gptprot = 0; + for (size_t i = 0; i < 4; i++) + gptprot |= (mbr->table[i].ostype == 0xEE); + if (gptprot && !(flags & PIF_PREFMBR)) { if (!(gpth = disk_read_sectors(di, 1, 1))) { error("Couldn't read potential GPT header."); goto bail; diff --git a/com32/chain/partiter.h b/com32/chain/partiter.h index a737584e..4004ef9e 100644 --- a/com32/chain/partiter.h +++ b/com32/chain/partiter.h @@ -46,8 +46,9 @@ enum {PI_OK, PI_DONE, PI_INSANE, PI_ERRLOAD}; /* flags */ -#define PIF_STEPALL 0x01 -#define PIF_RELAX 0x02 +#define PIF_STEPALL 0b001 +#define PIF_RELAX 0b010 +#define PIF_PREFMBR 0b100 struct itertype; struct part_iter; diff --git a/doc/chain.txt b/doc/chain.txt index d3c012c0..2321c102 100644 --- a/doc/chain.txt +++ b/doc/chain.txt @@ -226,6 +226,12 @@ 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. + prefmbr + *noprefmbr + +In the case of presence of non-standard hybrid MBR/GPT layout, this flag makes +chain module prefer MBR layout over GPT. + relax *norelax |