aboutsummaryrefslogtreecommitdiffstats
path: root/com32
diff options
context:
space:
mode:
Diffstat (limited to 'com32')
-rw-r--r--com32/chain/options.c13
-rw-r--r--com32/chain/partiter.c52
-rw-r--r--com32/chain/partiter.h2
3 files changed, 45 insertions, 22 deletions
diff --git a/com32/chain/options.c b/com32/chain/options.c
index a99e0d7b..3eecebde 100644
--- a/com32/chain/options.c
+++ b/com32/chain/options.c
@@ -132,6 +132,8 @@ 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",
+" gpthcrc Perform gpt header crc check",
+" gptlcrc Perform gpt list crc check",
" 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",
@@ -174,7 +176,8 @@ 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 */
+ /* strict but ignore disk size, do all gpt crc checks */
+ opt.piflags = PIF_STRICT | PIF_GPTHCRC | PIF_GPTLCRC;
opt.foff = opt.soff = opt.fip = opt.sip = 0x7C00;
opt.drivename = "boot";
#ifdef DEBUG
@@ -359,6 +362,14 @@ int opt_parse_args(int argc, char *argv[])
case '1': opt.piflags |= PIF_STRICT; break;
default:;
}
+ } else if (!strcmp(argv[i], "gpthcrc")) {
+ opt.piflags |= PIF_GPTHCRC;
+ } else if (!strcmp(argv[i], "nogpthcrc")) {
+ opt.piflags &= ~PIF_GPTHCRC;
+ } else if (!strcmp(argv[i], "gptlcrc")) {
+ opt.piflags |= PIF_GPTLCRC;
+ } else if (!strcmp(argv[i], "nogptlcrc")) {
+ opt.piflags &= ~PIF_GPTLCRC;
} 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 287205f7..3e678aa3 100644
--- a/com32/chain/partiter.c
+++ b/com32/chain/partiter.c
@@ -412,16 +412,29 @@ static inline int valid_crc(uint32_t crc, const uint8_t *buf, unsigned int siz)
return crc == crc32(crc32(0, NULL, 0), buf, siz);
}
-static int valid_crc_hdr(void *buf)
+static int valid_crc_gpth(struct disk_gpt_header *gh, int flags)
{
- struct disk_gpt_header *gh = buf;
- uint32_t crc = gh->chksum;
- int valid;
+ uint32_t crc, crcc;
+ if (!(flags & PIF_GPTHCRC))
+ return 1;
+
+ crc = gh->chksum;
gh->chksum = 0;
- valid = crc == crc32(crc32(0, NULL, 0), buf, gh->hdr_size);
+ crcc = crc32(crc32(0, NULL, 0), (const uint8_t *)gh, gh->hdr_size);
gh->chksum = crc;
- return valid;
+ return crc == crcc;
+}
+
+static int valid_crc_gptl(const struct disk_gpt_header *gh, const struct disk_gpt_part_entry *gl, int flags)
+{
+ uint32_t crcc;
+
+ if (!(flags & PIF_GPTLCRC))
+ return 1;
+
+ crcc = crc32(crc32(0, NULL, 0), (const uint8_t *)gl, gh->part_size * gh->part_count);
+ return gh->table_chksum == crcc;
}
static int pi_next_(struct part_iter *iter)
@@ -582,7 +595,7 @@ static struct disk_gpt_header *try_gpt_hdr(const struct disk_info *di, int sec,
sprintf(errbuf, "Unable to read %s GPT header.", desc);
goto out;
}
- if(!valid_crc_hdr(gpth)) {
+ if(!valid_crc_gpth(gpth, flags)) {
sprintf(errbuf, "Invalid checksum of %s GPT header.", desc);
goto out;
}
@@ -597,18 +610,16 @@ out:
return NULL;
}
-static struct disk_gpt_part_entry *try_gpt_list(const struct disk_info *di, const struct disk_gpt_header *gpth, int alt)
+static struct disk_gpt_part_entry *try_gpt_list(const struct disk_info *di, const struct disk_gpt_header *gpth, int alt, int flags)
{
int pri = gpth->lba_cur < gpth->lba_alt;
const char *desc = alt ? "alternative" : "main";
struct disk_gpt_part_entry *gptl;
char errbuf[64];
- uint64_t gpt_lsiz; /* size of GPT partition list in bytes */
- uint64_t gpt_lcnt; /* size of GPT partition in sectors */
+ uint32_t gpt_lcnt; /* size of GPT partition in sectors */
uint64_t gpt_loff; /* offset to GPT partition list in sectors */
- gpt_lsiz = (uint64_t)gpth->part_size * gpth->part_count;
- gpt_lcnt = (gpt_lsiz + di->bps - 1) / di->bps;
+ gpt_lcnt = (gpth->part_size * gpth->part_count + di->bps - 1) / di->bps;
if (!alt) {
/* prefer header value for partition table if not asking for alternative */
gpt_loff = gpth->lba_table;
@@ -623,16 +634,17 @@ static struct disk_gpt_part_entry *try_gpt_list(const struct disk_info *di, cons
gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt);
if (!gptl) {
sprintf(errbuf, "Unable to read %s GPT partition list.", desc);
- try_gpt_we(errbuf, alt);
- return NULL;
+ goto out;
}
- if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) {
+ if (!valid_crc_gptl(gpth, gptl, flags)) {
sprintf(errbuf, "Invalid checksum of %s GPT partition list.", desc);
- try_gpt_we(errbuf, alt);
- free(gptl);
- return NULL;
+ goto out;
}
return gptl;
+out:
+ try_gpt_we(errbuf, alt);
+ free(gptl);
+ return NULL;
}
/* pi_begin() - validate and and get proper iterator for a disk described by di */
@@ -687,9 +699,9 @@ struct part_iter *pi_begin(const struct disk_info *di, int flags)
dprintf("Looks like a GPT v1.0 disk.\n");
disk_gpt_header_dump(gpth);
#endif
- gptl = try_gpt_list(di, gpth, 0);
+ gptl = try_gpt_list(di, gpth, 0, flags);
if (!gptl)
- gptl = try_gpt_list(di, gpth, 1);
+ gptl = try_gpt_list(di, gpth, 1, flags);
if (!gptl)
goto out;
diff --git a/com32/chain/partiter.h b/com32/chain/partiter.h
index 22c0e42f..6d4fdb63 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_PREFMBR = 2, PIF_STRICT = 4, PIF_STRICTER = 8};
+enum {PIF_STEPALL = 1, PIF_PREFMBR = 2, PIF_STRICT = 4, PIF_STRICTER = 8, PIF_GPTHCRC = 16, PIF_GPTLCRC = 32};
struct itertype;
struct part_iter;