[syslinux] [PULL 1/8] Move partiter from com32/chain to com32/lib/syslinux
Paulo Alcantara
pcacjr at gmail.com
Wed Jul 22 16:27:23 PDT 2015
From: "Raphael S. Carvalho" <raphael.scarv at gmail.com>
MultiFS depends on the availability of partiter to find a partition.
Cc: Gene Cumm <gene.cumm at gmail.com>
Signed-off-by: Raphael S. Carvalho <raphael.scarv at gmail.com>
Signed-off-by: Paulo Alcantara <pcacjr at zytor.com>
---
com32/chain/Makefile | 2 +-
com32/chain/chain.c | 4 +-
com32/chain/mangle.c | 4 +-
com32/chain/mangle.h | 2 +-
com32/chain/options.c | 4 +-
com32/chain/partiter.c | 726 --------------------------------------
com32/chain/partiter.h | 119 -------
com32/chain/utility.c | 256 --------------
com32/chain/utility.h | 75 ----
com32/include/syslinux/partiter.h | 119 +++++++
com32/include/syslinux/utility.h | 76 ++++
com32/lib/syslinux/partiter.c | 726 ++++++++++++++++++++++++++++++++++++++
com32/lib/syslinux/utility.c | 256 ++++++++++++++
mk/lib.mk | 2 +-
14 files changed, 1186 insertions(+), 1185 deletions(-)
delete mode 100644 com32/chain/partiter.c
delete mode 100644 com32/chain/partiter.h
delete mode 100644 com32/chain/utility.c
delete mode 100644 com32/chain/utility.h
create mode 100644 com32/include/syslinux/partiter.h
create mode 100644 com32/include/syslinux/utility.h
create mode 100644 com32/lib/syslinux/partiter.c
create mode 100644 com32/lib/syslinux/utility.c
diff --git a/com32/chain/Makefile b/com32/chain/Makefile
index d7b5aa8..a7d1f66 100644
--- a/com32/chain/Makefile
+++ b/com32/chain/Makefile
@@ -16,7 +16,7 @@
VPATH = $(SRC)
include $(MAKEDIR)/elf.mk
-OBJS = chain.o partiter.o utility.o options.o mangle.o
+OBJS = chain.o options.o mangle.o
CFLAGS += -fno-strict-aliasing
all: chain.c32
diff --git a/com32/chain/chain.c b/com32/chain/chain.c
index 4e9e32d..f9fe07e 100644
--- a/com32/chain/chain.c
+++ b/com32/chain/chain.c
@@ -35,9 +35,9 @@
#include <syslinux/disk.h>
#include <syslinux/video.h>
#include "chain.h"
-#include "utility.h"
+#include <syslinux/utility.h>
#include "options.h"
-#include "partiter.h"
+#include <syslinux/partiter.h>
#include "mangle.h"
static int fixed_cnt = 128; /* see comments in main() */
diff --git a/com32/chain/mangle.c b/com32/chain/mangle.c
index 275d0aa..64d9c19 100644
--- a/com32/chain/mangle.c
+++ b/com32/chain/mangle.c
@@ -37,8 +37,8 @@
#include <syslinux/config.h>
#include "chain.h"
#include "options.h"
-#include "utility.h"
-#include "partiter.h"
+#include <syslinux/utility.h>
+#include <syslinux/partiter.h>
#include "mangle.h"
static const char cmldr_signature[8] = "cmdcons";
diff --git a/com32/chain/mangle.h b/com32/chain/mangle.h
index 42f6c5b..98b2f2c 100644
--- a/com32/chain/mangle.h
+++ b/com32/chain/mangle.h
@@ -32,7 +32,7 @@
#define COM32_CHAIN_MANGLE_H
#include "chain.h"
-#include "partiter.h"
+#include <syslinux/partiter.h>
/* file's manglers */
int manglef_isolinux(struct data_area *data);
diff --git a/com32/chain/options.c b/com32/chain/options.c
index 2b51939..b3c986e 100644
--- a/com32/chain/options.c
+++ b/com32/chain/options.c
@@ -33,8 +33,8 @@
#include <stdlib.h>
#include <string.h>
#include "chain.h"
-#include "partiter.h"
-#include "utility.h"
+#include <syslinux/partiter.h>
+#include <syslinux/utility.h>
#include "options.h"
struct options opt;
diff --git a/com32/chain/partiter.c b/com32/chain/partiter.c
deleted file mode 100644
index 4937f0c..0000000
--- a/com32/chain/partiter.c
+++ /dev/null
@@ -1,726 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
- * Copyright 2010 Shao Miller
- * Copyright 2010-2015 Michal Soltys
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall
- * be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * partiter.c
- *
- * Provides disk / partition iteration.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdarg.h>
-#include <zlib.h>
-#include <syslinux/disk.h>
-#include "partiter.h"
-#include "utility.h"
-
-#define ost_is_ext(type) ((type) == 0x05 || (type) == 0x0F || (type) == 0x85)
-#define ost_is_nondata(type) (ost_is_ext(type) || (type) == 0x00)
-#define sane(s,l) ((s)+(l) > (s))
-
-/* virtual forwards */
-
-static void pi_dtor_(struct part_iter *);
-static int pi_next_(struct part_iter *);
-static int pi_dos_next(struct part_iter *);
-static int pi_gpt_next(struct part_iter *);
-
-/* vtab and types */
-
-static struct itertype types[] = {
- [0] = {
- .dtor = &pi_dtor_,
- .next = &pi_dos_next,
-}, [1] = {
- .dtor = &pi_dtor_,
- .next = &pi_gpt_next,
-}, [2] = {
- .dtor = &pi_dtor_,
- .next = &pi_next_,
-}};
-
-const struct itertype * const typedos = types;
-const struct itertype * const typegpt = types+1;
-const struct itertype * const typeraw = types+2;
-
-/* pi_dtor_() - common/raw iterator cleanup */
-static void pi_dtor_(struct part_iter *iter)
-{
- /* syslinux's free is null resilient */
- free(iter->data);
-}
-
-/* pi_ctor() - common/raw iterator initialization */
-static int pi_ctor(struct part_iter *iter,
- const struct disk_info *di, int flags
-)
-{
- memcpy(&iter->di, di, sizeof *di);
- iter->flags = flags;
- iter->index0 = -1;
- iter->length = di->lbacnt;
-
- iter->type = typeraw;
- return 0;
-}
-
-/* pi_dos_ctor() - MBR/EBR iterator specific initialization */
-static int pi_dos_ctor(struct part_iter *iter,
- const struct disk_info *di, int flags,
- const struct disk_dos_mbr *mbr
-)
-{
- if (pi_ctor(iter, di, flags))
- return -1;
-
- if (!(iter->data = malloc(sizeof *mbr))) {
- critm();
- goto bail;
- }
-
- memcpy(iter->data, mbr, sizeof *mbr);
-
- iter->dos.bebr_index0 = -1;
- iter->dos.disk_sig = mbr->disk_sig;
-
- iter->type = typedos;
- return 0;
-bail:
- pi_dtor_(iter);
- return -1;
-}
-
-/* pi_gpt_ctor() - GPT iterator specific initialization */
-static int pi_gpt_ctor(struct part_iter *iter,
- const struct disk_info *di, int flags,
- const struct disk_gpt_header *gpth, const struct disk_gpt_part_entry *gptl
-)
-{
- uint64_t siz;
-
- if (pi_ctor(iter, di, flags))
- return -1;
-
- siz = (uint64_t)gpth->part_count * gpth->part_size;
-
- if (!(iter->data = malloc((size_t)siz))) {
- critm();
- goto bail;
- }
-
- memcpy(iter->data, gptl, (size_t)siz);
-
- iter->gpt.pe_count = (int)gpth->part_count;
- iter->gpt.pe_size = (int)gpth->part_size;
- iter->gpt.ufirst = gpth->lba_first_usable;
- iter->gpt.ulast = gpth->lba_last_usable;
-
- memcpy(&iter->gpt.disk_guid, &gpth->disk_guid, sizeof gpth->disk_guid);
- memcpy(&iter->gpt.part_guid, &gpth->disk_guid, sizeof gpth->disk_guid);
-
- iter->type = typegpt;
- return 0;
-bail:
- pi_dtor_(iter);
- return -1;
-}
-
-/* Logical partition must be sane, meaning:
- * - must be data or empty
- * - must have non-0 start and length
- * - values must not wrap around 32bit
- * - must be inside current EBR frame
- */
-
-static int notsane_logical(const struct part_iter *iter)
-{
- const struct disk_dos_part_entry *dp;
- uint32_t end_log;
-
- dp = ((struct disk_dos_mbr *)iter->data)->table;
-
- if (!dp[0].ostype)
- return 0;
-
- if (ost_is_ext(dp[0].ostype)) {
- error("The 1st EBR entry must be data or empty.");
- return -1;
- }
-
- if (!(iter->flags & PIF_STRICT))
- return 0;
-
- end_log = dp[0].start_lba + dp[0].length;
-
- if (!dp[0].start_lba ||
- !dp[0].length ||
- !sane(dp[0].start_lba, dp[0].length) ||
- end_log > iter->dos.nebr_siz) {
-
- error("Logical partition (in EBR) with invalid offset and/or length.");
- return -1;
- }
-
- return 0;
-}
-
-/* Extended partition must be sane, meaning:
- * - must be extended or empty
- * - must have non-0 start and length
- * - values must not wrap around 32bit
- * - must be inside base EBR frame
- */
-
-static int notsane_extended(const struct part_iter *iter)
-{
- const struct disk_dos_part_entry *dp;
- uint32_t end_ebr;
-
- dp = ((struct disk_dos_mbr *)iter->data)->table;
-
- if (!dp[1].ostype)
- return 0;
-
- if (!ost_is_nondata(dp[1].ostype)) {
- error("The 2nd EBR entry must be extended or empty.");
- return -1;
- }
-
- if (!(iter->flags & PIF_STRICT))
- return 0;
-
- end_ebr = dp[1].start_lba + dp[1].length;
-
- if (!dp[1].start_lba ||
- !dp[1].length ||
- !sane(dp[1].start_lba, dp[1].length) ||
- end_ebr > iter->dos.bebr_siz) {
-
- error("Extended partition (EBR) with invalid offset and/or length.");
- return -1;
- }
-
- return 0;
-}
-
-/* Primary partition must be sane, meaning:
- * - must have non-0 start and length
- * - values must not wrap around 32bit
- */
-
-static int notsane_primary(const struct part_iter *iter)
-{
- const struct disk_dos_part_entry *dp;
- dp = ((struct disk_dos_mbr *)iter->data)->table + iter->index0;
-
- if (!dp->ostype)
- return 0;
-
- if (!(iter->flags & PIF_STRICT))
- return 0;
-
- if (!dp->start_lba ||
- !dp->length ||
- !sane(dp->start_lba, dp->length) ||
- ((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;
- }
-
- return 0;
-}
-
-static int notsane_gpt(const struct part_iter *iter)
-{
- const struct disk_gpt_part_entry *gp;
- gp = (const struct disk_gpt_part_entry *)
- (iter->data + iter->index0 * iter->gpt.pe_size);
-
- if (guid_is0(&gp->type))
- return 0;
-
- if (!(iter->flags & PIF_STRICT))
- 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.");
- return -1;
- }
-
- return 0;
-}
-
-static int dos_next_mbr(struct part_iter *iter, uint32_t *lba,
- struct disk_dos_part_entry **_dp)
-{
- struct disk_dos_part_entry *dp;
-
- while (++iter->index0 < 4) {
- dp = ((struct disk_dos_mbr *)iter->data)->table + iter->index0;
-
- if (notsane_primary(iter)) {
- iter->status = PI_INSANE;
- return -1;
- }
-
- if (ost_is_ext(dp->ostype)) {
- if (iter->dos.bebr_index0 >= 0) {
- error("More than 1 extended partition.");
- iter->status = PI_INSANE;
- return -1;
- }
- /* record base EBR index */
- iter->dos.bebr_index0 = iter->index0;
- }
- if (!ost_is_nondata(dp->ostype) || (iter->flags & PIF_STEPALL)) {
- *lba = dp->start_lba;
- *_dp = dp;
- break;
- }
- }
-
- return 0;
-}
-
-static int prep_base_ebr(struct part_iter *iter)
-{
- struct disk_dos_part_entry *dp;
-
- if (iter->dos.bebr_index0 < 0) /* if we don't have base extended partition at all */
- return -1;
- else if (!iter->dos.bebr_lba) { /* if not initialized yet */
- dp = ((struct disk_dos_mbr *)iter->data)->table + iter->dos.bebr_index0;
-
- iter->dos.bebr_lba = dp->start_lba;
- iter->dos.bebr_siz = dp->length;
-
- iter->dos.nebr_lba = dp->start_lba;
- iter->dos.nebr_siz = dp->length;
-
- iter->index0--;
- }
- return 0;
-}
-
-static int dos_next_ebr(struct part_iter *iter, uint32_t *lba,
- struct disk_dos_part_entry **_dp)
-{
- struct disk_dos_part_entry *dp;
-
- if (prep_base_ebr(iter) < 0) {
- iter->status = PI_DONE;
- return -1;
- }
-
- while (++iter->index0 < 1024 && iter->dos.nebr_lba) {
- free(iter->data);
- if (!(iter->data =
- disk_read_sectors(&iter->di, iter->dos.nebr_lba, 1))) {
- error("Couldn't load EBR.");
- iter->status = PI_ERRLOAD;
- return -1;
- }
-
- /* check sanity of loaded data */
- if (notsane_logical(iter) || notsane_extended(iter)) {
- iter->status = PI_INSANE;
- return -1;
- }
-
- dp = ((struct disk_dos_mbr *)iter->data)->table;
-
- iter->dos.cebr_lba = iter->dos.nebr_lba;
- iter->dos.cebr_siz = iter->dos.nebr_siz;
-
- /* setup next frame values */
- if (dp[1].ostype) {
- iter->dos.nebr_lba = iter->dos.bebr_lba + dp[1].start_lba;
- iter->dos.nebr_siz = dp[1].length;
- } else {
- iter->dos.nebr_lba = 0;
- iter->dos.nebr_siz = 0;
- }
-
- if (!dp[0].ostype)
- iter->dos.logskipcnt++;
-
- if (dp[0].ostype || (iter->flags & PIF_STEPALL)) {
- *lba = dp[0].start_lba ? iter->dos.cebr_lba + dp[0].start_lba : 0;
- *_dp = dp;
- return 0;
- }
- /*
- * This way it's possible to continue, if some crazy soft left a "hole"
- * - EBR with a valid extended partition without a logical one. In
- * such case, linux will not reserve a number for such hole - so we
- * don't increase index0. If PIF_STEPALL flag is set, we will never
- * reach this place.
- */
- }
- iter->status = PI_DONE;
- return -1;
-}
-
-static void gpt_conv_label(struct part_iter *iter)
-{
- const struct disk_gpt_part_entry *gp;
- const int16_t *orig_lab;
-
- gp = (const struct disk_gpt_part_entry *)
- (iter->data + iter->index0 * iter->gpt.pe_size);
- orig_lab = (const int16_t *)gp->name;
-
- /* caveat: this is very crude conversion */
- for (int i = 0; i < PI_GPTLABSIZE/2; i++) {
- iter->gpt.part_label[i] = (char)orig_lab[i];
- }
- iter->gpt.part_label[PI_GPTLABSIZE/2] = 0;
-}
-
-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_gpth(struct disk_gpt_header *gh, int flags)
-{
- uint32_t crc, crcc;
-
- if (!(flags & PIF_GPTHCRC))
- return 1;
-
- crc = gh->chksum;
- gh->chksum = 0;
- crcc = crc32(crc32(0, NULL, 0), (const uint8_t *)gh, gh->hdr_size);
- gh->chksum = crc;
- 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)
-{
- iter->status = PI_DONE;
- return iter->status;
-}
-
-static int pi_dos_next(struct part_iter *iter)
-{
- uint32_t abs_lba = 0;
- struct disk_dos_part_entry *dos_part = NULL;
-
- if (iter->status)
- return iter->status;
-
- /* look for primary partitions */
- if (iter->index0 < 4 &&
- dos_next_mbr(iter, &abs_lba, &dos_part) < 0)
- return iter->status;
-
- /* look for logical partitions */
- if (iter->index0 >= 4 &&
- dos_next_ebr(iter, &abs_lba, &dos_part) < 0)
- return iter->status;
-
- /*
- * note special index handling:
- * in case PIF_STEPALL is set - this makes the index consistent with
- * non-PIF_STEPALL iterators
- */
-
- if (!dos_part->ostype)
- iter->index = -1;
- else
- iter->index = iter->index0 + 1 - iter->dos.logskipcnt;
- iter->abs_lba = abs_lba;
- iter->length = dos_part->length;
- iter->record = (char *)dos_part;
-
-#ifdef DEBUG
- disk_dos_part_dump(dos_part);
-#endif
-
- return iter->status;
-}
-
-static int pi_gpt_next(struct part_iter *iter)
-{
- const struct disk_gpt_part_entry *gpt_part = NULL;
-
- if (iter->status)
- return iter->status;
-
- while (++iter->index0 < iter->gpt.pe_count) {
- gpt_part = (const struct disk_gpt_part_entry *)
- (iter->data + iter->index0 * iter->gpt.pe_size);
-
- if (notsane_gpt(iter)) {
- iter->status = PI_INSANE;
- return iter->status;
- }
-
- if (!guid_is0(&gpt_part->type) || (iter->flags & PIF_STEPALL))
- break;
- }
- /* no more partitions ? */
- if (iter->index0 == iter->gpt.pe_count) {
- iter->status = PI_DONE;
- return iter->status;
- }
- /* gpt_part is guaranteed to be valid here */
- iter->index = iter->index0 + 1;
- iter->abs_lba = gpt_part->lba_first;
- iter->length = gpt_part->lba_last - gpt_part->lba_first + 1;
- iter->record = (char *)gpt_part;
- memcpy(&iter->gpt.part_guid, &gpt_part->uid, sizeof(struct guid));
- gpt_conv_label(iter);
-
-#ifdef DEBUG
- disk_gpt_part_dump(gpt_part);
-#endif
-
- return iter->status;
-}
-
-static struct part_iter *pi_alloc(void)
-{
- struct part_iter *iter;
- if (!(iter = malloc(sizeof *iter)))
- critm();
- else
- memset(iter, 0, sizeof *iter);
- return iter;
-}
-
-/* pi_del() - delete iterator */
-void pi_del(struct part_iter **_iter)
-{
- if(!_iter || !*_iter)
- return;
- pi_dtor(*_iter);
- free(*_iter);
- *_iter = NULL;
-}
-
-static int notsane_gpt_hdr(const struct disk_info *di, const struct disk_gpt_header *gpth, int flags)
-{
- uint64_t gpt_loff; /* offset to GPT partition list in sectors */
- uint64_t gpt_lsiz; /* size of GPT partition list in bytes */
- uint64_t gpt_lcnt; /* size of GPT partition in sectors */
- uint64_t gpt_sec; /* secondary gpt header */
-
- if (!(flags & PIF_STRICT))
- return 0;
-
- if (gpth->lba_alt < gpth->lba_cur)
- gpt_sec = gpth->lba_cur;
- else
- gpt_sec = gpth->lba_alt;
- gpt_loff = gpth->lba_table;
- gpt_lsiz = (uint64_t)gpth->part_size * gpth->part_count;
- gpt_lcnt = (gpt_lsiz + di->bps - 1) / di->bps;
-
- /*
- * disk_read_sectors allows reading of max 255 sectors, so we use
- * it as a sanity check base. EFI doesn't specify max (AFAIK).
- */
- if (gpt_loff < 2 || !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 && gpt_loff <= gpth->lba_last_usable) ||
- gpt_loff + gpt_lcnt > gpt_sec ||
- ((flags & PIF_STRICTER) && (gpt_sec >= di->lbacnt)) ||
- gpth->part_size < sizeof(struct disk_gpt_part_entry))
- return -1;
-
- return 0;
-}
-
-static void try_gpt_we(const char *str, int sec)
-{
- if (sec)
- error(str);
- else
- warn(str);
-}
-
-static struct disk_gpt_header *try_gpt_hdr(const struct disk_info *di, int sec, int flags)
-{
- const char *desc = sec ? "backup" : "primary";
- uint64_t gpt_cur = sec ? di->lbacnt - 1 : 1;
- struct disk_gpt_header *gpth;
- char errbuf[96];
-
- gpth = disk_read_sectors(di, gpt_cur, 1);
- if (!gpth) {
- sprintf(errbuf, "Unable to read %s GPT header.", desc);
- goto out;
- }
- if(!valid_crc_gpth(gpth, flags)) {
- sprintf(errbuf, "Invalid checksum of %s GPT header.", desc);
- goto out;
- }
- if(notsane_gpt_hdr(di, gpth, flags)) {
- sprintf(errbuf, "Checksum of %s GPT header is valid, but values fail sanity checks.", desc);
- goto out;
- }
- return gpth;
-out:
- try_gpt_we(errbuf, sec);
- free(gpth);
- return NULL;
-}
-
-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];
- uint32_t gpt_lcnt; /* size of GPT partition in sectors */
- uint64_t gpt_loff; /* offset to GPT partition list in sectors */
-
- 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;
- } else {
- /* try to read alternative, we have to calculate its position */
- if (!pri)
- gpt_loff = gpth->lba_alt + 1;
- else
- gpt_loff = gpth->lba_alt - gpt_lcnt;
- }
-
- gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt);
- if (!gptl) {
- sprintf(errbuf, "Unable to read %s GPT partition list.", desc);
- goto out;
- }
- if (!valid_crc_gptl(gpth, gptl, flags)) {
- sprintf(errbuf, "Invalid checksum of %s GPT partition list.", desc);
- 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 */
-struct part_iter *pi_begin(const struct disk_info *di, int flags)
-{
- int isgpt = 0, ret = -1;
- struct part_iter *iter;
- struct disk_dos_mbr *mbr = NULL;
- struct disk_gpt_header *gpth = NULL;
- struct disk_gpt_part_entry *gptl = NULL;
-
- /* Preallocate iterator */
- if (!(iter = pi_alloc()))
- goto out;
-
- /* Read MBR */
- if (!(mbr = disk_read_sectors(di, 0, 1))) {
- error("Unable to read the first disk sector.");
- goto out;
- }
-
- /* Check for MBR magic */
- if (mbr->sig != disk_mbr_sig_magic) {
- warn("No MBR magic, treating disk as raw.");
- /* looks like RAW */
- ret = pi_ctor(iter, di, flags);
- goto out;
- }
-
- /* Check for GPT protective MBR */
- for (size_t i = 0; i < 4; i++)
- isgpt |= (mbr->table[i].ostype == 0xEE);
- isgpt = isgpt && !(flags & PIF_PREFMBR);
-
- /* Try to read GPT header */
- if (isgpt) {
- gpth = try_gpt_hdr(di, 0, flags);
- if (!gpth)
- /*
- * this read might fail if bios reports different disk size (different vm/pc)
- * not much we can do here to avoid it
- */
- gpth = try_gpt_hdr(di, 1, flags);
- if (!gpth)
- goto out;
- }
-
- if (gpth && gpth->rev.uint32 == 0x00010000 &&
- !memcmp(gpth->sig, disk_gpt_sig_magic, sizeof gpth->sig)) {
- /* looks like GPT v1.0 */
-#ifdef DEBUG
- dprintf("Looks like a GPT v1.0 disk.\n");
- disk_gpt_header_dump(gpth);
-#endif
- gptl = try_gpt_list(di, gpth, 0, flags);
- if (!gptl)
- gptl = try_gpt_list(di, gpth, 1, flags);
- if (!gptl)
- goto out;
-
- /* looks like GPT */
- ret = pi_gpt_ctor(iter, di, flags, gpth, gptl);
- } else {
- /* looks like MBR */
- ret = pi_dos_ctor(iter, di, flags, mbr);
- }
-out:
- if (ret < 0) {
- free(iter);
- iter = NULL;
- }
- free(mbr);
- free(gpth);
- free(gptl);
-
- return iter;
-}
-
-/* vim: set ts=8 sts=4 sw=4 noet: */
diff --git a/com32/chain/partiter.h b/com32/chain/partiter.h
deleted file mode 100644
index a48f8d6..0000000
--- a/com32/chain/partiter.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
- * Copyright 2010 Shao Miller
- * Copyright 2010-2015 Michal Soltys
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall
- * be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * partiter.h
- *
- * Provides disk / partition iteration.
- */
-
-#ifndef COM32_CHAIN_PARTITER_H
-#define COM32_CHAIN_PARTITER_H
-
-#include <stdint.h>
-#include <syslinux/disk.h>
-
-/* status */
-
-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, PIF_GPTHCRC = 16, PIF_GPTLCRC = 32};
-
-struct itertype;
-struct part_iter;
-
-struct itertype {
- void (*dtor)(struct part_iter *);
- int (*next)(struct part_iter *);
-};
-
-#define PI_GPTLABSIZE ((int)sizeof(((struct disk_gpt_part_entry *)0)->name))
-
-struct part_iter {
- const struct itertype *type;
- char *data;
- char *record;
- uint64_t abs_lba;
- uint64_t length;
- int index0; /* including holes, from -1 (disk, then parts from 0) */
- int index; /* excluding holes, from 0 (disk, then parts from 1), -1 means hole, if PIF_STEPALL is set */
- int flags; /* flags, see #defines above */
- int status; /* current status, see enums above */
- struct disk_info di;
- union {
- struct {
- uint32_t disk_sig; /* 32bit disk signature as stored in MBR */
-
- uint32_t bebr_lba; /* absolute lba of base extended partition */
- uint32_t bebr_siz; /* size of base extended partition */
-
- uint32_t cebr_lba; /* absolute lba of curr ext. partition */
- uint32_t cebr_siz; /* size of curr ext. partition */
- uint32_t nebr_lba; /* absolute lba of next ext. partition */
- uint32_t nebr_siz; /* size of next ext. partition */
-
- int bebr_index0; /* index of (0-3) of base ext. part., -1 if not present in MBR */
- int logskipcnt; /* how many logical holes were skipped */
- } dos;
- struct {
- struct guid disk_guid;
- struct guid part_guid;
- char part_label[PI_GPTLABSIZE/2+1];
- int pe_count;
- int pe_size;
- uint64_t ufirst;
- uint64_t ulast;
- } gpt;
- };
-};
-
-extern const struct itertype * const typedos;
-extern const struct itertype * const typegpt;
-extern const struct itertype * const typeraw;
-
-struct part_iter *pi_begin(const struct disk_info *, int flags);
-void pi_del(struct part_iter **);
-
-/* inline virtuals */
-static inline int pi_next(struct part_iter *iter)
-{
- return iter->type->next(iter);
-}
-
-static inline void pi_dtor(struct part_iter *iter)
-{
- iter->type->dtor(iter);
-}
-
-#endif
-
-/* vim: set ts=8 sts=4 sw=4 noet: */
diff --git a/com32/chain/utility.c b/com32/chain/utility.c
deleted file mode 100644
index 180749e..0000000
--- a/com32/chain/utility.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
- * Copyright 2010 Shao Miller
- * Copyright 2010-2015 Michal Soltys
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall
- * be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * ----------------------------------------------------------------------- */
-
-#include <com32.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <string.h>
-#include <fs.h>
-#include <syslinux/disk.h>
-#include <syslinux/pmapi.h>
-#include "utility.h"
-
-static const char *bpbtypes[] = {
- [0] = "unknown",
- [1] = "2.0",
- [2] = "3.0",
- [3] = "3.2",
- [4] = "3.4",
- [5] = "4.0",
- [6] = "8.0 (NT+)",
- [7] = "7.0",
- [8] = "exFAT",
-};
-
-void wait_key(void)
-{
- int cnt;
- char junk;
-
- /* drain */
- do {
- errno = 0;
- cnt = read(0, &junk, 1);
- } while (cnt > 0 || (cnt < 0 && errno == EAGAIN));
-
- /* wait */
- do {
- errno = 0;
- cnt = read(0, &junk, 1);
- } while (!cnt || (cnt < 0 && errno == EAGAIN));
-}
-
-int guid_is0(const struct guid *guid)
-{
- return
- !(guid->data1 ||
- guid->data2 ||
- guid->data3 ||
- guid->data4);
-}
-
-/*
- * mode explanation:
- *
- * cnul - "strict" mode, never returning higher value than obtained from cbios
- * cadd - if the disk is larger than reported geometry /and/ if the geometry has
- * less cylinders than 1024 - it means that the total size is somewhere
- * between cs and cs+1; in this particular case, we bump the cs to be able
- * to return matching chs triplet
- * cmax - assume we can use any cylinder value
- *
- * by default cadd seems most reasonable, giving consistent results with e.g.
- * sfdisk's behavior
- */
-void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, int mode)
-{
- uint32_t c, h, s, t;
- uint32_t cs, hs, ss;
-
- /*
- * Not much reason here, but if we have no valid CHS geometry, we assume
- * "typical" ones to have something to return.
- */
- if (di->cbios) {
- cs = di->cyl;
- hs = di->head;
- ss = di->spt;
- if (mode == L2C_CADD) {
- if (cs < 1024 && di->lbacnt > cs*hs*ss)
- cs++;
- } else if (mode == L2C_CMAX)
- cs = 1024;
- } else {
- if (di->disk & 0x80) {
- cs = 1024;
- hs = 255;
- ss = 63;
- } else {
- cs = 80;
- hs = 2;
- ss = 18;
- }
- }
-
- if (lba >= cs*hs*ss) {
- s = ss;
- h = hs - 1;
- c = cs - 1;
- } else {
- s = (lba % ss) + 1;
- t = lba / ss;
- h = t % hs;
- c = t / hs;
- }
-
- (*dst)[0] = h;
- (*dst)[1] = s | ((c & 0x300) >> 2);
- (*dst)[2] = c;
-}
-
-uint32_t get_file_lba(const char *filename)
-{
- struct com32_filedata fd;
- uint32_t lba = 0;
- int size = 65536;
- char *buf;
-
- buf = lmalloc(size);
- if (!buf)
- return 0;
-
- /* Put the filename in the bounce buffer */
- strlcpy(buf, filename, size);
-
- if (open_file(buf, O_RDONLY, &fd) <= 0) {
- goto fail; /* Filename not found */
- }
-
- /* Since the first member is the LBA, we simply cast */
- lba = *((uint32_t *) MK_PTR(0, fd.handle));
-
- /* Call comapi_close() to free the structure */
- close_file(fd.handle);
-
-fail:
- lfree(buf);
- return lba;
-}
-
-/* drive offset detection */
-int drvoff_detect(int type)
-{
- if (bpbV40 <= type && type <= bpbVNT) {
- return 0x24;
- } else if (type == bpbV70) {
- return 0x40;
- } else if (type == bpbEXF) {
- return 0x6F;
- }
-
- return -1;
-}
-
-/*
- * heuristics could certainly be improved
- */
-int bpb_detect(const uint8_t *sec, const char *tag)
-{
- int a, b, c, jmp = -1, rev = 0;
-
- /* exFAT mess first (media descriptor is 0 here) */
- if (!memcmp(sec + 0x03, "EXFAT ", 8)) {
- rev = bpbEXF;
- goto out;
- }
-
- /* media descriptor check */
- if ((sec[0x15] & 0xF0) != 0xF0)
- goto out;
-
- if (sec[0] == 0xEB) /* jump short */
- jmp = 2 + *(int8_t *)(sec + 1);
- else if (sec[0] == 0xE9) /* jump near */
- jmp = 3 + *(int16_t *)(sec + 1);
-
- if (jmp < 0) /* no boot code at all ? */
- goto nocode;
-
- /* sanity */
- if (jmp < 0x18 || jmp > 0x1F0)
- goto out;
-
- /* detect by jump */
- if (jmp >= 0x18 && jmp < 0x1E)
- rev = bpbV20;
- else if (jmp >= 0x1E && jmp < 0x20)
- rev = bpbV30;
- else if (jmp >= 0x20 && jmp < 0x24)
- rev = bpbV32;
- else if (jmp >= 0x24 && jmp < 0x46)
- rev = bpbV34;
-
- /* TODO: some better V2 - V3.4 checks ? */
-
- if (rev)
- goto out;
- /*
- * BPB info:
- * 2.0 == 0x0B - 0x17
- * 3.0 == 2.0 + 0x18 - 0x1D
- * 3.2 == 3.0 + 0x1E - 0x1F
- * 3.4 ==!2.0 + 0x18 - 0x23
- * 4.0 == 3.4 + 0x24 - 0x45
- * NT ==~3.4 + 0x24 - 0x53
- * 7.0 == 3.4 + 0x24 - 0x59
- */
-
-nocode:
- a = memcmp(sec + 0x03, "NTFS", 4);
- b = memcmp(sec + 0x36, "FAT", 3);
- c = memcmp(sec + 0x52, "FAT", 3); /* ext. DOS 7+ bs */
-
- if ((sec[0x26] & 0xFE) == 0x28 && !b) {
- rev = bpbV40;
- } else if (sec[0x26] == 0x80 && !a) {
- rev = bpbVNT;
- } else if ((sec[0x42] & 0xFE) == 0x28 && !c) {
- rev = bpbV70;
- }
-
-out:
- printf("BPB detection (%s): %s\n", tag, bpbtypes[rev]);
- return rev;
-}
-
-/* vim: set ts=8 sts=4 sw=4 noet: */
diff --git a/com32/chain/utility.h b/com32/chain/utility.h
deleted file mode 100644
index f8e9c61..0000000
--- a/com32/chain/utility.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* ----------------------------------------------------------------------- *
- *
- * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
- * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
- * Copyright 2010 Shao Miller
- * Copyright 2010-2015 Michal Soltys
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom
- * the Software is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice shall
- * be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * ----------------------------------------------------------------------- */
-
-#ifndef COM32_CHAIN_UTILITY_H
-#define COM32_CHAIN_UTILITY_H
-
-#include <stdint.h>
-#include <stdio.h>
-#include <syslinux/disk.h>
-#include <syslinux/movebits.h>
-
-/* most (all ?) bpb "types" known to humankind as of 2012 */
-enum {bpbUNK, bpbV20, bpbV30, bpbV32, bpbV34, bpbV40, bpbVNT, bpbV70, bpbEXF};
-
-/* see utility.c for details */
-enum {L2C_CNUL, L2C_CADD, L2C_CMAX};
-
-/* first usable and first unusable offsets */
-#define dosmin ((addr_t)0x500u)
-#define dosmax ((addr_t)(*(uint16_t *) 0x413 << 10))
-
-void wait_key(void);
-void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, int mode);
-uint32_t get_file_lba(const char *filename);
-int drvoff_detect(int type);
-int bpb_detect(const uint8_t *bpb, const char *tag);
-int guid_is0(const struct guid *guid);
-
-static inline int warn(const char *x)
-{
- return fprintf(stderr, "WARN: %s\n", x);
-}
-
-static inline int error(const char *x)
-{
- return fprintf(stderr, "ERR: %s\n", x);
-}
-
-static inline int crit(const char *x)
-{
- return fprintf(stderr, "CRIT: %s @%s:%d\n", x, __FILE__, __LINE__);
-}
-
-#define critm() crit("Malloc failure.")
-
-#endif
-
-/* vim: set ts=8 sts=4 sw=4 noet: */
diff --git a/com32/include/syslinux/partiter.h b/com32/include/syslinux/partiter.h
new file mode 100644
index 0000000..a48f8d6
--- /dev/null
+++ b/com32/include/syslinux/partiter.h
@@ -0,0 +1,119 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2010 Shao Miller
+ * Copyright 2010-2015 Michal Soltys
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * partiter.h
+ *
+ * Provides disk / partition iteration.
+ */
+
+#ifndef COM32_CHAIN_PARTITER_H
+#define COM32_CHAIN_PARTITER_H
+
+#include <stdint.h>
+#include <syslinux/disk.h>
+
+/* status */
+
+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, PIF_GPTHCRC = 16, PIF_GPTLCRC = 32};
+
+struct itertype;
+struct part_iter;
+
+struct itertype {
+ void (*dtor)(struct part_iter *);
+ int (*next)(struct part_iter *);
+};
+
+#define PI_GPTLABSIZE ((int)sizeof(((struct disk_gpt_part_entry *)0)->name))
+
+struct part_iter {
+ const struct itertype *type;
+ char *data;
+ char *record;
+ uint64_t abs_lba;
+ uint64_t length;
+ int index0; /* including holes, from -1 (disk, then parts from 0) */
+ int index; /* excluding holes, from 0 (disk, then parts from 1), -1 means hole, if PIF_STEPALL is set */
+ int flags; /* flags, see #defines above */
+ int status; /* current status, see enums above */
+ struct disk_info di;
+ union {
+ struct {
+ uint32_t disk_sig; /* 32bit disk signature as stored in MBR */
+
+ uint32_t bebr_lba; /* absolute lba of base extended partition */
+ uint32_t bebr_siz; /* size of base extended partition */
+
+ uint32_t cebr_lba; /* absolute lba of curr ext. partition */
+ uint32_t cebr_siz; /* size of curr ext. partition */
+ uint32_t nebr_lba; /* absolute lba of next ext. partition */
+ uint32_t nebr_siz; /* size of next ext. partition */
+
+ int bebr_index0; /* index of (0-3) of base ext. part., -1 if not present in MBR */
+ int logskipcnt; /* how many logical holes were skipped */
+ } dos;
+ struct {
+ struct guid disk_guid;
+ struct guid part_guid;
+ char part_label[PI_GPTLABSIZE/2+1];
+ int pe_count;
+ int pe_size;
+ uint64_t ufirst;
+ uint64_t ulast;
+ } gpt;
+ };
+};
+
+extern const struct itertype * const typedos;
+extern const struct itertype * const typegpt;
+extern const struct itertype * const typeraw;
+
+struct part_iter *pi_begin(const struct disk_info *, int flags);
+void pi_del(struct part_iter **);
+
+/* inline virtuals */
+static inline int pi_next(struct part_iter *iter)
+{
+ return iter->type->next(iter);
+}
+
+static inline void pi_dtor(struct part_iter *iter)
+{
+ iter->type->dtor(iter);
+}
+
+#endif
+
+/* vim: set ts=8 sts=4 sw=4 noet: */
diff --git a/com32/include/syslinux/utility.h b/com32/include/syslinux/utility.h
new file mode 100644
index 0000000..e2667a0
--- /dev/null
+++ b/com32/include/syslinux/utility.h
@@ -0,0 +1,76 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2010 Shao Miller
+ * Copyright 2010-2015 Michal Soltys
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#ifndef COM32_CHAIN_UTILITY_H
+#define COM32_CHAIN_UTILITY_H
+
+#include <stdint.h>
+#include <stdio.h>
+#include <syslinux/disk.h>
+#include <syslinux/movebits.h>
+#include <klibc/compiler.h>
+
+/* most (all ?) bpb "types" known to humankind as of 2012 */
+enum {bpbUNK, bpbV20, bpbV30, bpbV32, bpbV34, bpbV40, bpbVNT, bpbV70, bpbEXF};
+
+/* see utility.c for details */
+enum {L2C_CNUL, L2C_CADD, L2C_CMAX};
+
+/* first usable and first unusable offsets */
+#define dosmin ((addr_t)0x500u)
+#define dosmax ((addr_t)(*(uint16_t *) 0x413 << 10))
+
+void wait_key(void);
+void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, int mode);
+uint32_t get_file_lba(const char *filename);
+int drvoff_detect(int type);
+int bpb_detect(const uint8_t *bpb, const char *tag);
+int guid_is0(const struct guid *guid);
+
+static inline int warn(const char *x)
+{
+ return fprintf(stderr, "WARN: %s\n", x);
+}
+
+static __unusedfunc int error(const char *x)
+{
+ return fprintf(stderr, "ERR: %s\n", x);
+}
+
+static inline int crit(const char *x)
+{
+ return fprintf(stderr, "CRIT: %s @%s:%d\n", x, __FILE__, __LINE__);
+}
+
+#define critm() crit("Malloc failure.")
+
+#endif
+
+/* vim: set ts=8 sts=4 sw=4 noet: */
diff --git a/com32/lib/syslinux/partiter.c b/com32/lib/syslinux/partiter.c
new file mode 100644
index 0000000..3ae2583
--- /dev/null
+++ b/com32/lib/syslinux/partiter.c
@@ -0,0 +1,726 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2010 Shao Miller
+ * Copyright 2010-2015 Michal Soltys
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * partiter.c
+ *
+ * Provides disk / partition iteration.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <zlib.h>
+#include <syslinux/disk.h>
+#include <syslinux/partiter.h>
+#include <syslinux/utility.h>
+
+#define ost_is_ext(type) ((type) == 0x05 || (type) == 0x0F || (type) == 0x85)
+#define ost_is_nondata(type) (ost_is_ext(type) || (type) == 0x00)
+#define sane(s,l) ((s)+(l) > (s))
+
+/* virtual forwards */
+
+static void pi_dtor_(struct part_iter *);
+static int pi_next_(struct part_iter *);
+static int pi_dos_next(struct part_iter *);
+static int pi_gpt_next(struct part_iter *);
+
+/* vtab and types */
+
+static struct itertype types[] = {
+ [0] = {
+ .dtor = &pi_dtor_,
+ .next = &pi_dos_next,
+}, [1] = {
+ .dtor = &pi_dtor_,
+ .next = &pi_gpt_next,
+}, [2] = {
+ .dtor = &pi_dtor_,
+ .next = &pi_next_,
+}};
+
+const struct itertype * const typedos = types;
+const struct itertype * const typegpt = types+1;
+const struct itertype * const typeraw = types+2;
+
+/* pi_dtor_() - common/raw iterator cleanup */
+static void pi_dtor_(struct part_iter *iter)
+{
+ /* syslinux's free is null resilient */
+ free(iter->data);
+}
+
+/* pi_ctor() - common/raw iterator initialization */
+static int pi_ctor(struct part_iter *iter,
+ const struct disk_info *di, int flags
+)
+{
+ memcpy(&iter->di, di, sizeof *di);
+ iter->flags = flags;
+ iter->index0 = -1;
+ iter->length = di->lbacnt;
+
+ iter->type = typeraw;
+ return 0;
+}
+
+/* pi_dos_ctor() - MBR/EBR iterator specific initialization */
+static int pi_dos_ctor(struct part_iter *iter,
+ const struct disk_info *di, int flags,
+ const struct disk_dos_mbr *mbr
+)
+{
+ if (pi_ctor(iter, di, flags))
+ return -1;
+
+ if (!(iter->data = malloc(sizeof *mbr))) {
+ critm();
+ goto bail;
+ }
+
+ memcpy(iter->data, mbr, sizeof *mbr);
+
+ iter->dos.bebr_index0 = -1;
+ iter->dos.disk_sig = mbr->disk_sig;
+
+ iter->type = typedos;
+ return 0;
+bail:
+ pi_dtor_(iter);
+ return -1;
+}
+
+/* pi_gpt_ctor() - GPT iterator specific initialization */
+static int pi_gpt_ctor(struct part_iter *iter,
+ const struct disk_info *di, int flags,
+ const struct disk_gpt_header *gpth, const struct disk_gpt_part_entry *gptl
+)
+{
+ uint64_t siz;
+
+ if (pi_ctor(iter, di, flags))
+ return -1;
+
+ siz = (uint64_t)gpth->part_count * gpth->part_size;
+
+ if (!(iter->data = malloc((size_t)siz))) {
+ critm();
+ goto bail;
+ }
+
+ memcpy(iter->data, gptl, (size_t)siz);
+
+ iter->gpt.pe_count = (int)gpth->part_count;
+ iter->gpt.pe_size = (int)gpth->part_size;
+ iter->gpt.ufirst = gpth->lba_first_usable;
+ iter->gpt.ulast = gpth->lba_last_usable;
+
+ memcpy(&iter->gpt.disk_guid, &gpth->disk_guid, sizeof gpth->disk_guid);
+ memcpy(&iter->gpt.part_guid, &gpth->disk_guid, sizeof gpth->disk_guid);
+
+ iter->type = typegpt;
+ return 0;
+bail:
+ pi_dtor_(iter);
+ return -1;
+}
+
+/* Logical partition must be sane, meaning:
+ * - must be data or empty
+ * - must have non-0 start and length
+ * - values must not wrap around 32bit
+ * - must be inside current EBR frame
+ */
+
+static int notsane_logical(const struct part_iter *iter)
+{
+ const struct disk_dos_part_entry *dp;
+ uint32_t end_log;
+
+ dp = ((struct disk_dos_mbr *)iter->data)->table;
+
+ if (!dp[0].ostype)
+ return 0;
+
+ if (ost_is_ext(dp[0].ostype)) {
+ error("The 1st EBR entry must be data or empty.");
+ return -1;
+ }
+
+ if (!(iter->flags & PIF_STRICT))
+ return 0;
+
+ end_log = dp[0].start_lba + dp[0].length;
+
+ if (!dp[0].start_lba ||
+ !dp[0].length ||
+ !sane(dp[0].start_lba, dp[0].length) ||
+ end_log > iter->dos.nebr_siz) {
+
+ error("Logical partition (in EBR) with invalid offset and/or length.");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Extended partition must be sane, meaning:
+ * - must be extended or empty
+ * - must have non-0 start and length
+ * - values must not wrap around 32bit
+ * - must be inside base EBR frame
+ */
+
+static int notsane_extended(const struct part_iter *iter)
+{
+ const struct disk_dos_part_entry *dp;
+ uint32_t end_ebr;
+
+ dp = ((struct disk_dos_mbr *)iter->data)->table;
+
+ if (!dp[1].ostype)
+ return 0;
+
+ if (!ost_is_nondata(dp[1].ostype)) {
+ error("The 2nd EBR entry must be extended or empty.");
+ return -1;
+ }
+
+ if (!(iter->flags & PIF_STRICT))
+ return 0;
+
+ end_ebr = dp[1].start_lba + dp[1].length;
+
+ if (!dp[1].start_lba ||
+ !dp[1].length ||
+ !sane(dp[1].start_lba, dp[1].length) ||
+ end_ebr > iter->dos.bebr_siz) {
+
+ error("Extended partition (EBR) with invalid offset and/or length.");
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Primary partition must be sane, meaning:
+ * - must have non-0 start and length
+ * - values must not wrap around 32bit
+ */
+
+static int notsane_primary(const struct part_iter *iter)
+{
+ const struct disk_dos_part_entry *dp;
+ dp = ((struct disk_dos_mbr *)iter->data)->table + iter->index0;
+
+ if (!dp->ostype)
+ return 0;
+
+ if (!(iter->flags & PIF_STRICT))
+ return 0;
+
+ if (!dp->start_lba ||
+ !dp->length ||
+ !sane(dp->start_lba, dp->length) ||
+ ((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;
+ }
+
+ return 0;
+}
+
+static int notsane_gpt(const struct part_iter *iter)
+{
+ const struct disk_gpt_part_entry *gp;
+ gp = (const struct disk_gpt_part_entry *)
+ (iter->data + iter->index0 * iter->gpt.pe_size);
+
+ if (guid_is0(&gp->type))
+ return 0;
+
+ if (!(iter->flags & PIF_STRICT))
+ 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.");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int dos_next_mbr(struct part_iter *iter, uint32_t *lba,
+ struct disk_dos_part_entry **_dp)
+{
+ struct disk_dos_part_entry *dp;
+
+ while (++iter->index0 < 4) {
+ dp = ((struct disk_dos_mbr *)iter->data)->table + iter->index0;
+
+ if (notsane_primary(iter)) {
+ iter->status = PI_INSANE;
+ return -1;
+ }
+
+ if (ost_is_ext(dp->ostype)) {
+ if (iter->dos.bebr_index0 >= 0) {
+ error("More than 1 extended partition.");
+ iter->status = PI_INSANE;
+ return -1;
+ }
+ /* record base EBR index */
+ iter->dos.bebr_index0 = iter->index0;
+ }
+ if (!ost_is_nondata(dp->ostype) || (iter->flags & PIF_STEPALL)) {
+ *lba = dp->start_lba;
+ *_dp = dp;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int prep_base_ebr(struct part_iter *iter)
+{
+ struct disk_dos_part_entry *dp;
+
+ if (iter->dos.bebr_index0 < 0) /* if we don't have base extended partition at all */
+ return -1;
+ else if (!iter->dos.bebr_lba) { /* if not initialized yet */
+ dp = ((struct disk_dos_mbr *)iter->data)->table + iter->dos.bebr_index0;
+
+ iter->dos.bebr_lba = dp->start_lba;
+ iter->dos.bebr_siz = dp->length;
+
+ iter->dos.nebr_lba = dp->start_lba;
+ iter->dos.nebr_siz = dp->length;
+
+ iter->index0--;
+ }
+ return 0;
+}
+
+static int dos_next_ebr(struct part_iter *iter, uint32_t *lba,
+ struct disk_dos_part_entry **_dp)
+{
+ struct disk_dos_part_entry *dp;
+
+ if (prep_base_ebr(iter) < 0) {
+ iter->status = PI_DONE;
+ return -1;
+ }
+
+ while (++iter->index0 < 1024 && iter->dos.nebr_lba) {
+ free(iter->data);
+ if (!(iter->data =
+ disk_read_sectors(&iter->di, iter->dos.nebr_lba, 1))) {
+ error("Couldn't load EBR.");
+ iter->status = PI_ERRLOAD;
+ return -1;
+ }
+
+ /* check sanity of loaded data */
+ if (notsane_logical(iter) || notsane_extended(iter)) {
+ iter->status = PI_INSANE;
+ return -1;
+ }
+
+ dp = ((struct disk_dos_mbr *)iter->data)->table;
+
+ iter->dos.cebr_lba = iter->dos.nebr_lba;
+ iter->dos.cebr_siz = iter->dos.nebr_siz;
+
+ /* setup next frame values */
+ if (dp[1].ostype) {
+ iter->dos.nebr_lba = iter->dos.bebr_lba + dp[1].start_lba;
+ iter->dos.nebr_siz = dp[1].length;
+ } else {
+ iter->dos.nebr_lba = 0;
+ iter->dos.nebr_siz = 0;
+ }
+
+ if (!dp[0].ostype)
+ iter->dos.logskipcnt++;
+
+ if (dp[0].ostype || (iter->flags & PIF_STEPALL)) {
+ *lba = dp[0].start_lba ? iter->dos.cebr_lba + dp[0].start_lba : 0;
+ *_dp = dp;
+ return 0;
+ }
+ /*
+ * This way it's possible to continue, if some crazy soft left a "hole"
+ * - EBR with a valid extended partition without a logical one. In
+ * such case, linux will not reserve a number for such hole - so we
+ * don't increase index0. If PIF_STEPALL flag is set, we will never
+ * reach this place.
+ */
+ }
+ iter->status = PI_DONE;
+ return -1;
+}
+
+static void gpt_conv_label(struct part_iter *iter)
+{
+ const struct disk_gpt_part_entry *gp;
+ const int16_t *orig_lab;
+
+ gp = (const struct disk_gpt_part_entry *)
+ (iter->data + iter->index0 * iter->gpt.pe_size);
+ orig_lab = (const int16_t *)gp->name;
+
+ /* caveat: this is very crude conversion */
+ for (int i = 0; i < PI_GPTLABSIZE/2; i++) {
+ iter->gpt.part_label[i] = (char)orig_lab[i];
+ }
+ iter->gpt.part_label[PI_GPTLABSIZE/2] = 0;
+}
+
+static 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_gpth(struct disk_gpt_header *gh, int flags)
+{
+ uint32_t crc, crcc;
+
+ if (!(flags & PIF_GPTHCRC))
+ return 1;
+
+ crc = gh->chksum;
+ gh->chksum = 0;
+ crcc = crc32(crc32(0, NULL, 0), (const uint8_t *)gh, gh->hdr_size);
+ gh->chksum = crc;
+ 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)
+{
+ iter->status = PI_DONE;
+ return iter->status;
+}
+
+static int pi_dos_next(struct part_iter *iter)
+{
+ uint32_t abs_lba = 0;
+ struct disk_dos_part_entry *dos_part = NULL;
+
+ if (iter->status)
+ return iter->status;
+
+ /* look for primary partitions */
+ if (iter->index0 < 4 &&
+ dos_next_mbr(iter, &abs_lba, &dos_part) < 0)
+ return iter->status;
+
+ /* look for logical partitions */
+ if (iter->index0 >= 4 &&
+ dos_next_ebr(iter, &abs_lba, &dos_part) < 0)
+ return iter->status;
+
+ /*
+ * note special index handling:
+ * in case PIF_STEPALL is set - this makes the index consistent with
+ * non-PIF_STEPALL iterators
+ */
+
+ if (!dos_part->ostype)
+ iter->index = -1;
+ else
+ iter->index = iter->index0 + 1 - iter->dos.logskipcnt;
+ iter->abs_lba = abs_lba;
+ iter->length = dos_part->length;
+ iter->record = (char *)dos_part;
+
+#ifdef DEBUG
+ disk_dos_part_dump(dos_part);
+#endif
+
+ return iter->status;
+}
+
+static int pi_gpt_next(struct part_iter *iter)
+{
+ const struct disk_gpt_part_entry *gpt_part = NULL;
+
+ if (iter->status)
+ return iter->status;
+
+ while (++iter->index0 < iter->gpt.pe_count) {
+ gpt_part = (const struct disk_gpt_part_entry *)
+ (iter->data + iter->index0 * iter->gpt.pe_size);
+
+ if (notsane_gpt(iter)) {
+ iter->status = PI_INSANE;
+ return iter->status;
+ }
+
+ if (!guid_is0(&gpt_part->type) || (iter->flags & PIF_STEPALL))
+ break;
+ }
+ /* no more partitions ? */
+ if (iter->index0 == iter->gpt.pe_count) {
+ iter->status = PI_DONE;
+ return iter->status;
+ }
+ /* gpt_part is guaranteed to be valid here */
+ iter->index = iter->index0 + 1;
+ iter->abs_lba = gpt_part->lba_first;
+ iter->length = gpt_part->lba_last - gpt_part->lba_first + 1;
+ iter->record = (char *)gpt_part;
+ memcpy(&iter->gpt.part_guid, &gpt_part->uid, sizeof(struct guid));
+ gpt_conv_label(iter);
+
+#ifdef DEBUG
+ disk_gpt_part_dump(gpt_part);
+#endif
+
+ return iter->status;
+}
+
+static struct part_iter *pi_alloc(void)
+{
+ struct part_iter *iter;
+ if (!(iter = malloc(sizeof *iter)))
+ critm();
+ else
+ memset(iter, 0, sizeof *iter);
+ return iter;
+}
+
+/* pi_del() - delete iterator */
+void pi_del(struct part_iter **_iter)
+{
+ if(!_iter || !*_iter)
+ return;
+ pi_dtor(*_iter);
+ free(*_iter);
+ *_iter = NULL;
+}
+
+static int notsane_gpt_hdr(const struct disk_info *di, const struct disk_gpt_header *gpth, int flags)
+{
+ uint64_t gpt_loff; /* offset to GPT partition list in sectors */
+ uint64_t gpt_lsiz; /* size of GPT partition list in bytes */
+ uint64_t gpt_lcnt; /* size of GPT partition in sectors */
+ uint64_t gpt_sec; /* secondary gpt header */
+
+ if (!(flags & PIF_STRICT))
+ return 0;
+
+ if (gpth->lba_alt < gpth->lba_cur)
+ gpt_sec = gpth->lba_cur;
+ else
+ gpt_sec = gpth->lba_alt;
+ gpt_loff = gpth->lba_table;
+ gpt_lsiz = (uint64_t)gpth->part_size * gpth->part_count;
+ gpt_lcnt = (gpt_lsiz + di->bps - 1) / di->bps;
+
+ /*
+ * disk_read_sectors allows reading of max 255 sectors, so we use
+ * it as a sanity check base. EFI doesn't specify max (AFAIK).
+ */
+ if (gpt_loff < 2 || !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 && gpt_loff <= gpth->lba_last_usable) ||
+ gpt_loff + gpt_lcnt > gpt_sec ||
+ ((flags & PIF_STRICTER) && (gpt_sec >= di->lbacnt)) ||
+ gpth->part_size < sizeof(struct disk_gpt_part_entry))
+ return -1;
+
+ return 0;
+}
+
+static void try_gpt_we(const char *str, int sec)
+{
+ if (sec)
+ error(str);
+ else
+ warn(str);
+}
+
+static struct disk_gpt_header *try_gpt_hdr(const struct disk_info *di, int sec, int flags)
+{
+ const char *desc = sec ? "backup" : "primary";
+ uint64_t gpt_cur = sec ? di->lbacnt - 1 : 1;
+ struct disk_gpt_header *gpth;
+ char errbuf[96];
+
+ gpth = disk_read_sectors(di, gpt_cur, 1);
+ if (!gpth) {
+ sprintf(errbuf, "Unable to read %s GPT header.", desc);
+ goto out;
+ }
+ if(!valid_crc_gpth(gpth, flags)) {
+ sprintf(errbuf, "Invalid checksum of %s GPT header.", desc);
+ goto out;
+ }
+ if(notsane_gpt_hdr(di, gpth, flags)) {
+ sprintf(errbuf, "Checksum of %s GPT header is valid, but values fail sanity checks.", desc);
+ goto out;
+ }
+ return gpth;
+out:
+ try_gpt_we(errbuf, sec);
+ free(gpth);
+ return NULL;
+}
+
+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];
+ uint32_t gpt_lcnt; /* size of GPT partition in sectors */
+ uint64_t gpt_loff; /* offset to GPT partition list in sectors */
+
+ 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;
+ } else {
+ /* try to read alternative, we have to calculate its position */
+ if (!pri)
+ gpt_loff = gpth->lba_alt + 1;
+ else
+ gpt_loff = gpth->lba_alt - gpt_lcnt;
+ }
+
+ gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt);
+ if (!gptl) {
+ sprintf(errbuf, "Unable to read %s GPT partition list.", desc);
+ goto out;
+ }
+ if (!valid_crc_gptl(gpth, gptl, flags)) {
+ sprintf(errbuf, "Invalid checksum of %s GPT partition list.", desc);
+ 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 */
+struct part_iter *pi_begin(const struct disk_info *di, int flags)
+{
+ int isgpt = 0, ret = -1;
+ struct part_iter *iter;
+ struct disk_dos_mbr *mbr = NULL;
+ struct disk_gpt_header *gpth = NULL;
+ struct disk_gpt_part_entry *gptl = NULL;
+
+ /* Preallocate iterator */
+ if (!(iter = pi_alloc()))
+ goto out;
+
+ /* Read MBR */
+ if (!(mbr = disk_read_sectors(di, 0, 1))) {
+ error("Unable to read the first disk sector.");
+ goto out;
+ }
+
+ /* Check for MBR magic */
+ if (mbr->sig != disk_mbr_sig_magic) {
+ warn("No MBR magic, treating disk as raw.");
+ /* looks like RAW */
+ ret = pi_ctor(iter, di, flags);
+ goto out;
+ }
+
+ /* Check for GPT protective MBR */
+ for (size_t i = 0; i < 4; i++)
+ isgpt |= (mbr->table[i].ostype == 0xEE);
+ isgpt = isgpt && !(flags & PIF_PREFMBR);
+
+ /* Try to read GPT header */
+ if (isgpt) {
+ gpth = try_gpt_hdr(di, 0, flags);
+ if (!gpth)
+ /*
+ * this read might fail if bios reports different disk size (different vm/pc)
+ * not much we can do here to avoid it
+ */
+ gpth = try_gpt_hdr(di, 1, flags);
+ if (!gpth)
+ goto out;
+ }
+
+ if (gpth && gpth->rev.uint32 == 0x00010000 &&
+ !memcmp(gpth->sig, disk_gpt_sig_magic, sizeof gpth->sig)) {
+ /* looks like GPT v1.0 */
+#ifdef DEBUG
+ dprintf("Looks like a GPT v1.0 disk.\n");
+ disk_gpt_header_dump(gpth);
+#endif
+ gptl = try_gpt_list(di, gpth, 0, flags);
+ if (!gptl)
+ gptl = try_gpt_list(di, gpth, 1, flags);
+ if (!gptl)
+ goto out;
+
+ /* looks like GPT */
+ ret = pi_gpt_ctor(iter, di, flags, gpth, gptl);
+ } else {
+ /* looks like MBR */
+ ret = pi_dos_ctor(iter, di, flags, mbr);
+ }
+out:
+ if (ret < 0) {
+ free(iter);
+ iter = NULL;
+ }
+ free(mbr);
+ free(gpth);
+ free(gptl);
+
+ return iter;
+}
+
+/* vim: set ts=8 sts=4 sw=4 noet: */
diff --git a/com32/lib/syslinux/utility.c b/com32/lib/syslinux/utility.c
new file mode 100644
index 0000000..ecf5a37
--- /dev/null
+++ b/com32/lib/syslinux/utility.c
@@ -0,0 +1,256 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved
+ * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin
+ * Copyright 2010 Shao Miller
+ * Copyright 2010-2015 Michal Soltys
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+#include <com32.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <fs.h>
+#include <syslinux/disk.h>
+#include <syslinux/pmapi.h>
+#include <syslinux/utility.h>
+
+static const char *bpbtypes[] = {
+ [0] = "unknown",
+ [1] = "2.0",
+ [2] = "3.0",
+ [3] = "3.2",
+ [4] = "3.4",
+ [5] = "4.0",
+ [6] = "8.0 (NT+)",
+ [7] = "7.0",
+ [8] = "exFAT",
+};
+
+void wait_key(void)
+{
+ int cnt;
+ char junk;
+
+ /* drain */
+ do {
+ errno = 0;
+ cnt = read(0, &junk, 1);
+ } while (cnt > 0 || (cnt < 0 && errno == EAGAIN));
+
+ /* wait */
+ do {
+ errno = 0;
+ cnt = read(0, &junk, 1);
+ } while (!cnt || (cnt < 0 && errno == EAGAIN));
+}
+
+int guid_is0(const struct guid *guid)
+{
+ return
+ !(guid->data1 ||
+ guid->data2 ||
+ guid->data3 ||
+ guid->data4);
+}
+
+/*
+ * mode explanation:
+ *
+ * cnul - "strict" mode, never returning higher value than obtained from cbios
+ * cadd - if the disk is larger than reported geometry /and/ if the geometry has
+ * less cylinders than 1024 - it means that the total size is somewhere
+ * between cs and cs+1; in this particular case, we bump the cs to be able
+ * to return matching chs triplet
+ * cmax - assume we can use any cylinder value
+ *
+ * by default cadd seems most reasonable, giving consistent results with e.g.
+ * sfdisk's behavior
+ */
+void lba2chs(disk_chs *dst, const struct disk_info *di, uint64_t lba, int mode)
+{
+ uint32_t c, h, s, t;
+ uint32_t cs, hs, ss;
+
+ /*
+ * Not much reason here, but if we have no valid CHS geometry, we assume
+ * "typical" ones to have something to return.
+ */
+ if (di->cbios) {
+ cs = di->cyl;
+ hs = di->head;
+ ss = di->spt;
+ if (mode == L2C_CADD) {
+ if (cs < 1024 && di->lbacnt > cs*hs*ss)
+ cs++;
+ } else if (mode == L2C_CMAX)
+ cs = 1024;
+ } else {
+ if (di->disk & 0x80) {
+ cs = 1024;
+ hs = 255;
+ ss = 63;
+ } else {
+ cs = 80;
+ hs = 2;
+ ss = 18;
+ }
+ }
+
+ if (lba >= cs*hs*ss) {
+ s = ss;
+ h = hs - 1;
+ c = cs - 1;
+ } else {
+ s = (lba % ss) + 1;
+ t = lba / ss;
+ h = t % hs;
+ c = t / hs;
+ }
+
+ (*dst)[0] = h;
+ (*dst)[1] = s | ((c & 0x300) >> 2);
+ (*dst)[2] = c;
+}
+
+uint32_t get_file_lba(const char *filename)
+{
+ struct com32_filedata fd;
+ uint32_t lba = 0;
+ int size = 65536;
+ char *buf;
+
+ buf = lmalloc(size);
+ if (!buf)
+ return 0;
+
+ /* Put the filename in the bounce buffer */
+ strlcpy(buf, filename, size);
+
+ if (open_file(buf, O_RDONLY, &fd) <= 0) {
+ goto fail; /* Filename not found */
+ }
+
+ /* Since the first member is the LBA, we simply cast */
+ lba = *((uint32_t *) MK_PTR(0, fd.handle));
+
+ /* Call comapi_close() to free the structure */
+ close_file(fd.handle);
+
+fail:
+ lfree(buf);
+ return lba;
+}
+
+/* drive offset detection */
+int drvoff_detect(int type)
+{
+ if (bpbV40 <= type && type <= bpbVNT) {
+ return 0x24;
+ } else if (type == bpbV70) {
+ return 0x40;
+ } else if (type == bpbEXF) {
+ return 0x6F;
+ }
+
+ return -1;
+}
+
+/*
+ * heuristics could certainly be improved
+ */
+int bpb_detect(const uint8_t *sec, const char *tag)
+{
+ int a, b, c, jmp = -1, rev = 0;
+
+ /* exFAT mess first (media descriptor is 0 here) */
+ if (!memcmp(sec + 0x03, "EXFAT ", 8)) {
+ rev = bpbEXF;
+ goto out;
+ }
+
+ /* media descriptor check */
+ if ((sec[0x15] & 0xF0) != 0xF0)
+ goto out;
+
+ if (sec[0] == 0xEB) /* jump short */
+ jmp = 2 + *(int8_t *)(sec + 1);
+ else if (sec[0] == 0xE9) /* jump near */
+ jmp = 3 + *(int16_t *)(sec + 1);
+
+ if (jmp < 0) /* no boot code at all ? */
+ goto nocode;
+
+ /* sanity */
+ if (jmp < 0x18 || jmp > 0x1F0)
+ goto out;
+
+ /* detect by jump */
+ if (jmp >= 0x18 && jmp < 0x1E)
+ rev = bpbV20;
+ else if (jmp >= 0x1E && jmp < 0x20)
+ rev = bpbV30;
+ else if (jmp >= 0x20 && jmp < 0x24)
+ rev = bpbV32;
+ else if (jmp >= 0x24 && jmp < 0x46)
+ rev = bpbV34;
+
+ /* TODO: some better V2 - V3.4 checks ? */
+
+ if (rev)
+ goto out;
+ /*
+ * BPB info:
+ * 2.0 == 0x0B - 0x17
+ * 3.0 == 2.0 + 0x18 - 0x1D
+ * 3.2 == 3.0 + 0x1E - 0x1F
+ * 3.4 ==!2.0 + 0x18 - 0x23
+ * 4.0 == 3.4 + 0x24 - 0x45
+ * NT ==~3.4 + 0x24 - 0x53
+ * 7.0 == 3.4 + 0x24 - 0x59
+ */
+
+nocode:
+ a = memcmp(sec + 0x03, "NTFS", 4);
+ b = memcmp(sec + 0x36, "FAT", 3);
+ c = memcmp(sec + 0x52, "FAT", 3); /* ext. DOS 7+ bs */
+
+ if ((sec[0x26] & 0xFE) == 0x28 && !b) {
+ rev = bpbV40;
+ } else if (sec[0x26] == 0x80 && !a) {
+ rev = bpbVNT;
+ } else if ((sec[0x42] & 0xFE) == 0x28 && !c) {
+ rev = bpbV70;
+ }
+
+out:
+ printf("BPB detection (%s): %s\n", tag, bpbtypes[rev]);
+ return rev;
+}
+
+/* vim: set ts=8 sts=4 sw=4 noet: */
diff --git a/mk/lib.mk b/mk/lib.mk
index ceb95bd..c56d3e3 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -106,7 +106,7 @@ LIBOTHER_OBJS = \
pci/writeb.o pci/writew.o pci/writel.o \
\
sys/x86_init_fpu.o math/pow.o math/strtod.o \
- syslinux/disk.o \
+ syslinux/disk.o syslinux/utility.o syslinux/partiter.o \
\
syslinux/setup_data.o
--
2.1.0
More information about the Syslinux
mailing list