Raphael S.Carvalho
2013-Oct-18 05:39 UTC
[syslinux] [RFC/PATCH 1/3] Move partiter from com32/chain to com32/lib/syslinux
From: Raphael S. Carvalho <raphael.scarv at gmail.com> MultiFS depends on the availability of partiter to find a partition. Signed-off-by: Raphael S. Carvalho <raphael.scarv at gmail.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 | 656 ------------------------------------- com32/chain/partiter.h | 124 ------- com32/chain/utility.c | 256 --------------- com32/chain/utility.h | 75 ----- com32/include/syslinux/partiter.h | 124 +++++++ com32/include/syslinux/utility.h | 76 +++++ com32/lib/syslinux/partiter.c | 656 +++++++++++++++++++++++++++++++++++++ com32/lib/syslinux/utility.c | 256 +++++++++++++++ mk/lib.mk | 2 +- 14 files changed, 1121 insertions(+), 1120 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 4a5af91..dcc60f5 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 ae95d45..dce44df 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 ffdaab8..72eafde 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 d4a5b75..df5c568 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 4e722a0..4211c2f 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 1eb5350..0000000 --- a/com32/chain/partiter.c +++ /dev/null @@ -1,656 +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-2012 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_RELAX) - 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_RELAX) - 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_RELAX) - return 0; - - if (!dp->start_lba || - !dp->length || - !sane(dp->start_lba, dp->length) || - 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_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."); - 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 gpt_check_hdr_crc(const struct disk_info * const diskinfo, struct disk_gpt_header **_gh) -{ - struct disk_gpt_header *gh = *_gh; - uint64_t lba_alt; - uint32_t hold_crc32; - - hold_crc32 = gh->chksum; - gh->chksum = 0; - if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { - warn("Primary GPT header checksum invalid."); - /* retry with backup */ - lba_alt = gh->lba_alt; - free(gh); - if (!(gh = *_gh = disk_read_sectors(diskinfo, lba_alt, 1))) { - error("Couldn't read backup GPT header."); - return -1; - } - hold_crc32 = gh->chksum; - gh->chksum = 0; - if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { - error("Secondary GPT header checksum invalid."); - return -1; - } - } - /* restore old checksum */ - gh->chksum = hold_crc32; - - return 0; -} - -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; -} - -/* 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 gptprot, 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 bail; - - /* Read MBR */ - if (!(mbr = disk_read_sectors(di, 0, 1))) { - error("Couldn't read the first disk sector."); - goto bail; - } - - /* 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 bail; - } - - /* Check for GPT protective MBR */ - 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; - } - } - - if (gpth && gpth->rev.uint32 == 0x00010000 && - !memcmp(gpth->sig, disk_gpt_sig_magic, sizeof gpth->sig)) { - /* looks like GPT v1.0 */ - 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 */ -#ifdef DEBUG - dprintf("Looks like a GPT v1.0 disk.\n"); - disk_gpt_header_dump(gpth); -#endif - /* Verify checksum, fallback to backup, then bail if invalid */ - if (gpt_check_hdr_crc(di, &gpth)) - goto bail; - - 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). - * Apart from that, some extensive sanity checks. - */ - 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 *gptl)) { - error("Invalid GPT header's values."); - goto bail; - } - if (!(gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt))) { - error("Couldn't read GPT partition list."); - goto bail; - } - /* Check array checksum(s). */ - if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) { - warn("Checksum of the main GPT partition list is invalid, trying backup."); - free(gptl); - /* secondary array directly precedes secondary header */ - if (!(gptl = disk_read_sectors(di, gpth->lba_alt - gpt_lcnt, gpt_lcnt))) { - error("Couldn't read backup GPT partition list."); - goto bail; - } - if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) { - error("Checksum of the backup GPT partition list is invalid, giving up."); - goto bail; - } - } - /* looks like GPT */ - ret = pi_gpt_ctor(iter, di, flags, gpth, gptl); - } else { - /* looks like MBR */ - ret = pi_dos_ctor(iter, di, flags, mbr); - } -bail: - if (ret < 0) - free(iter); - 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 13dec84..0000000 --- a/com32/chain/partiter.h +++ /dev/null @@ -1,124 +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-2012 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_OK, PI_DONE, PI_INSANE, PI_ERRLOAD}; - -/* flags */ - -enum {PIF_STEPALL = 1, PIF_RELAX = 2, PIF_PREFMBR = 4}; - -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 **); - -static inline int pi_errored(struct part_iter *iter) -{ - return iter->status > PI_DONE; -} - -/* 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 b17997f..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-2012 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 596017b..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-2012 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..13dec84 --- /dev/null +++ b/com32/include/syslinux/partiter.h @@ -0,0 +1,124 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * Copyright 2010 Shao Miller + * Copyright 2010-2012 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_OK, PI_DONE, PI_INSANE, PI_ERRLOAD}; + +/* flags */ + +enum {PIF_STEPALL = 1, PIF_RELAX = 2, PIF_PREFMBR = 4}; + +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 **); + +static inline int pi_errored(struct part_iter *iter) +{ + return iter->status > PI_DONE; +} + +/* 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..a9347dd --- /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-2012 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..ca3f2fe --- /dev/null +++ b/com32/lib/syslinux/partiter.c @@ -0,0 +1,656 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2003-2009 H. Peter Anvin - All Rights Reserved + * Copyright 2009-2010 Intel Corporation; author: H. Peter Anvin + * Copyright 2010 Shao Miller + * Copyright 2010-2012 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_RELAX) + 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_RELAX) + 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_RELAX) + return 0; + + if (!dp->start_lba || + !dp->length || + !sane(dp->start_lba, dp->length) || + 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_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."); + 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 gpt_check_hdr_crc(const struct disk_info * const diskinfo, struct disk_gpt_header **_gh) +{ + struct disk_gpt_header *gh = *_gh; + uint64_t lba_alt; + uint32_t hold_crc32; + + hold_crc32 = gh->chksum; + gh->chksum = 0; + if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { + warn("Primary GPT header checksum invalid."); + /* retry with backup */ + lba_alt = gh->lba_alt; + free(gh); + if (!(gh = *_gh = disk_read_sectors(diskinfo, lba_alt, 1))) { + error("Couldn't read backup GPT header."); + return -1; + } + hold_crc32 = gh->chksum; + gh->chksum = 0; + if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { + error("Secondary GPT header checksum invalid."); + return -1; + } + } + /* restore old checksum */ + gh->chksum = hold_crc32; + + return 0; +} + +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; +} + +/* 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 gptprot, 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 bail; + + /* Read MBR */ + if (!(mbr = disk_read_sectors(di, 0, 1))) { + error("Couldn't read the first disk sector."); + goto bail; + } + + /* 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 bail; + } + + /* Check for GPT protective MBR */ + 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; + } + } + + if (gpth && gpth->rev.uint32 == 0x00010000 && + !memcmp(gpth->sig, disk_gpt_sig_magic, sizeof gpth->sig)) { + /* looks like GPT v1.0 */ + 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 */ +#ifdef DEBUG + dprintf("Looks like a GPT v1.0 disk.\n"); + disk_gpt_header_dump(gpth); +#endif + /* Verify checksum, fallback to backup, then bail if invalid */ + if (gpt_check_hdr_crc(di, &gpth)) + goto bail; + + 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). + * Apart from that, some extensive sanity checks. + */ + 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 *gptl)) { + error("Invalid GPT header's values."); + goto bail; + } + if (!(gptl = disk_read_sectors(di, gpt_loff, gpt_lcnt))) { + error("Couldn't read GPT partition list."); + goto bail; + } + /* Check array checksum(s). */ + if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) { + warn("Checksum of the main GPT partition list is invalid, trying backup."); + free(gptl); + /* secondary array directly precedes secondary header */ + if (!(gptl = disk_read_sectors(di, gpth->lba_alt - gpt_lcnt, gpt_lcnt))) { + error("Couldn't read backup GPT partition list."); + goto bail; + } + if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) { + error("Checksum of the backup GPT partition list is invalid, giving up."); + goto bail; + } + } + /* looks like GPT */ + ret = pi_gpt_ctor(iter, di, flags, gpth, gptl); + } else { + /* looks like MBR */ + ret = pi_dos_ctor(iter, di, flags, mbr); + } +bail: + if (ret < 0) + free(iter); + 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..e58df5e --- /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-2012 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 bc516c2..861daf8 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 -- 1.7.2.5
Apparently Analagous Threads
- [PULL 1/8] Move partiter from com32/chain to com32/lib/syslinux
- [PATCH 1/6] chain/partiter: fix and improve gpt handling in buggy cases
- chain.c32 (and partiter) updates v2
- PATCH/RFC chain.c: update iterator code, yank from chain.c, move both to separate directory
- [PULL 0/8] MultiFS suppport for BIOS and EFI