diff options
author | Michal Soltys <soltys@ziu.info> | 2013-02-14 16:51:45 +0100 |
---|---|---|
committer | Michal Soltys <soltys@ziu.info> | 2013-02-14 16:53:04 +0100 |
commit | 4f46f2e8713dddfc73d4a5e229201302254b988c (patch) | |
tree | 575bc9c1ee3292a903f9d1c8ddc9fe8e28f5b107 | |
parent | c5d41b402f31849690a18ff682422ac7e691bebe (diff) | |
download | syslinux-4f46f2e8713dddfc73d4a5e229201302254b988c.tar.gz syslinux-4f46f2e8713dddfc73d4a5e229201302254b988c.tar.xz syslinux-4f46f2e8713dddfc73d4a5e229201302254b988c.zip |
com32/chain: partiter - simplifications and updates
The code uses more abstractions than it's really worth or necessary, so
these patches simplify the code a bit. Partially suggested by Shao as
well.
Additionally, there're some added comments and more consistent naming
used.
Signed-off-by: Michal Soltys <soltys@ziu.info>
-rw-r--r-- | com32/chain/chain.c | 8 | ||||
-rw-r--r-- | com32/chain/mangle.c | 4 | ||||
-rw-r--r-- | com32/chain/partiter.c | 350 | ||||
-rw-r--r-- | com32/chain/partiter.h | 36 |
4 files changed, 119 insertions, 279 deletions
diff --git a/com32/chain/chain.c b/com32/chain/chain.c index d76c6690..bb249555 100644 --- a/com32/chain/chain.c +++ b/com32/chain/chain.c @@ -115,7 +115,7 @@ static int find_by_guid(const struct guid *gpt_guid, goto ok; } /* disk guid doesn't match, maybe partition guid will */ - while (!pi_next(&boot_part)) { + while (!pi_next(boot_part)) { if (!memcmp(&boot_part->gpt.part_guid, gpt_guid, sizeof(*gpt_guid))) goto ok; } @@ -147,7 +147,7 @@ static int find_by_label(const char *label, struct part_iter **_boot_part) continue; } /* Check for a matching partition */ - while (!pi_next(&boot_part)) { + while (!pi_next(boot_part)) { if (!strcmp(label, boot_part->gpt.part_label)) goto ok; } @@ -353,7 +353,7 @@ int find_dp(struct part_iter **_iter) /* 'fs' => we should lookup the syslinux partition number and use it */ if (!strcmp(opt.drivename, "fs")) { - while (!pi_next(&iter)) { + while (!pi_next(iter)) { if (iter->start_lba == fs_lba) break; } @@ -377,7 +377,7 @@ int find_dp(struct part_iter **_iter) do { if (iter->index == partition) break; - } while (!pi_next(&iter)); + } while (!pi_next(iter)); if (iter->status) { error("Requested disk / partition combination not found.\n"); goto bail; diff --git a/com32/chain/mangle.c b/com32/chain/mangle.c index fbb5d57e..7fe77eed 100644 --- a/com32/chain/mangle.c +++ b/com32/chain/mangle.c @@ -543,7 +543,7 @@ int manglepe_hide(struct part_iter *miter) if (!(iter = pi_begin(&miter->di, PIF_STEPALL))) return -1; - while (!pi_next(&iter) && !werr) { + while (!pi_next(iter) && !werr) { ridx = iter->rawindex; if (!(opt.hide & 2) && ridx > 4) break; /* skip when we're constrained to pri only */ @@ -613,7 +613,7 @@ int manglepe_fixchs(struct part_iter *miter) if (!(iter = pi_begin(&miter->di, PIF_STEPALL))) return -1; - while (!pi_next(&iter) && !werr) { + while (!pi_next(iter) && !werr) { ridx = iter->rawindex; dp = (struct disk_dos_part_entry *)iter->record; diff --git a/com32/chain/partiter.c b/com32/chain/partiter.c index 8fdb3590..23cbf903 100644 --- a/com32/chain/partiter.c +++ b/com32/chain/partiter.c @@ -48,108 +48,61 @@ #define ost_is_nondata(type) (ost_is_ext(type) || (type) == 0x00) #define sane(s,l) ((s)+(l) > (s)) -/* forwards */ +/* virtual forwards */ -static int iter_ctor(struct part_iter *, va_list *); -static int iter_dos_ctor(struct part_iter *, va_list *); -static int iter_gpt_ctor(struct part_iter *, va_list *); -static void iter_dtor(struct part_iter *); -static struct part_iter *pi_dos_next(struct part_iter *); -static struct part_iter *pi_gpt_next(struct part_iter *); -static struct part_iter *pi_raw_next(struct part_iter *); +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] = { - .ctor = &iter_dos_ctor, - .dtor = &iter_dtor, + .dtor = &pi_dtor_, .next = &pi_dos_next, }, [1] = { - .ctor = &iter_gpt_ctor, - .dtor = &iter_dtor, + .dtor = &pi_dtor_, .next = &pi_gpt_next, }, [2] = { - .ctor = &iter_ctor, - .dtor = &iter_dtor, - .next = &pi_raw_next, + .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; -#ifdef DEBUG -static int inv_type(const void *type) +/* pi_dtor_() - common/raw iterator cleanup */ +static void pi_dtor_(struct part_iter *iter) { - int i, cnt = sizeof(types)/sizeof(types[0]); - for (i = 0; i < cnt; i++) { - if (type == types + i) - return 0; - } - return -1; + /* syslinux's free is null resilient */ + free(iter->data); } -#endif -/** - * iter_ctor() - common iterator initialization - * @iter: iterator pointer - * @args(0): disk_info structure used for disk functions - * @args(1): flags modifier - * - * Second and further arguments are passed as a pointer to va_list - **/ -static int iter_ctor(struct part_iter *iter, va_list *args) +/* pi_ctor() - common/raw iterator initialization */ +static int pi_ctor(struct part_iter *iter, + const struct disk_info *di, int flags +) { - const struct disk_info *di = va_arg(*args, const struct disk_info *); - int flags = va_arg(*args, int); - -#ifdef DEBUG - if (!di) - return -1; -#endif - memcpy(&iter->di, di, sizeof(struct disk_info)); iter->flags = flags; iter->index0 = -1; iter->length = di->lbacnt; + iter->type = typeraw; return 0; } -/** - * iter_dtor() - common iterator cleanup - * @iter: iterator pointer - * - **/ -static void iter_dtor(struct part_iter *iter) +/* 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 +) { - free(iter->data); -} - -/** - * iter_dos_ctor() - MBR/EBR iterator specific initialization - * @iter: iterator pointer - * @args(0): disk_info structure used for disk functions - * @args(1): pointer to buffer with loaded valid MBR - * - * Second and further arguments are passed as a pointer to va_list. - * This function only makes rudimentary checks. If user uses - * pi_new(), he/she is responsible for doing proper sanity checks. - **/ -static int iter_dos_ctor(struct part_iter *iter, va_list *args) -{ - const struct disk_dos_mbr *mbr; - - /* uses args(0) */ - if (iter_ctor(iter, args)) + if (pi_ctor(iter, di, flags)) return -1; - mbr = va_arg(*args, const struct disk_dos_mbr *); - -#ifdef DEBUG - if (!mbr) - goto bail; -#endif - if (!(iter->data = malloc(sizeof(struct disk_dos_mbr)))) goto bail; @@ -158,50 +111,26 @@ static int iter_dos_ctor(struct part_iter *iter, va_list *args) iter->dos.bebr_index0 = -1; iter->dos.disk_sig = mbr->disk_sig; + iter->type = typedos; return 0; bail: - iter->type->dtor(iter); + pi_dtor_(iter); return -1; } -/** - * iter_gpt_ctor() - GPT iterator specific initialization - * @iter: iterator pointer - * @args(0): ptr to disk_info structure - * @args(1): ptr to buffer with GPT header - * @args(2): ptr to buffer with GPT partition list - * - * Second and further arguments are passed as a pointer to va_list. - * This function only makes rudimentary checks. If user uses - * pi_new(), he/she is responsible for doing proper sanity checks. - **/ -static int iter_gpt_ctor(struct part_iter *iter, va_list *args) +/* 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; - const struct disk_gpt_header *gpth; - const struct disk_gpt_part_entry *gptl; - /* uses args(0) */ - if (iter_ctor(iter, args)) + if (pi_ctor(iter, di, flags)) return -1; - gpth = va_arg(*args, const struct disk_gpt_header *); - gptl = va_arg(*args, const struct disk_gpt_part_entry *); - -#ifdef DEBUG - if (!gpth || !gptl) - goto bail; -#endif - siz = (uint64_t)gpth->part_count * gpth->part_size; -#ifdef DEBUG - if (!siz || (siz + iter->di.bps - 1) / iter->di.bps > 255u || - gpth->part_size < sizeof(struct disk_gpt_part_entry)) { - goto bail; - } -#endif - if (!(iter->data = malloc((size_t)siz))) goto bail; @@ -214,9 +143,10 @@ static int iter_gpt_ctor(struct part_iter *iter, va_list *args) memcpy(&iter->gpt.disk_guid, &gpth->disk_guid, sizeof(struct guid)); + iter->type = typegpt; return 0; bail: - iter->type->dtor(iter); + pi_dtor_(iter); return -1; } @@ -309,7 +239,7 @@ static int notsane_primary(const struct part_iter *iter) !dp->length || !sane(dp->start_lba, dp->length) || dp->start_lba + dp->length > iter->di.lbacnt) { - error("Insane primary (MBR) partition.\n"); + error("Primary (MBR) with invalid offset and/or length.\n"); return -1; } @@ -327,14 +257,14 @@ static int notsane_gpt(const struct part_iter *iter) if (gp->lba_first < iter->gpt.ufirst || gp->lba_last > iter->gpt.ulast) { - error("Insane GPT partition.\n"); + error("LBA sectors of GPT partition are beyond the range allowed in GPT header.\n"); return -1; } return 0; } -static int pi_dos_next_mbr(struct part_iter *iter, uint32_t *lba, +static int dos_next_mbr(struct part_iter *iter, uint32_t *lba, struct disk_dos_part_entry **_dp) { struct disk_dos_part_entry *dp; @@ -344,14 +274,14 @@ static int pi_dos_next_mbr(struct part_iter *iter, uint32_t *lba, if (notsane_primary(iter)) { iter->status = PI_INSANE; - goto bail; + return -1; } if (ost_is_ext(dp->ostype)) { if (iter->dos.bebr_index0 >= 0) { error("You have more than 1 extended partition.\n"); iter->status = PI_INSANE; - goto bail; + return -1; } /* record base EBR index */ iter->dos.bebr_index0 = iter->index0; @@ -364,8 +294,6 @@ static int pi_dos_next_mbr(struct part_iter *iter, uint32_t *lba, } return 0; -bail: - return -1; } static int prep_base_ebr(struct part_iter *iter) @@ -391,12 +319,12 @@ static int prep_base_ebr(struct part_iter *iter) return 0; } -static int pi_dos_next_ebr(struct part_iter *iter, uint32_t *lba, +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)) { + if (prep_base_ebr(iter) < 0) { iter->status = PI_DONE; return -1; } @@ -442,8 +370,8 @@ static int pi_dos_next_ebr(struct part_iter *iter, uint32_t *lba, * 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 stepall flag is set, we will never reach - * this place. + * don't increase index0. If PIF_STEPALL flag is set, we will never + * reach this place. */ } iter->status = PI_DONE; @@ -466,14 +394,9 @@ static void gpt_conv_label(struct part_iter *iter) iter->gpt.part_label[PI_GPTLABSIZE/2] = 0; } -static int check_crc(uint32_t crc_match, const uint8_t *buf, unsigned int siz) +static inline int valid_crc(uint32_t crc, const uint8_t *buf, unsigned int siz) { - uint32_t crc; - - crc = crc32(0, NULL, 0); - crc = crc32(crc, buf, siz); - - return crc_match != crc; + 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) @@ -484,7 +407,7 @@ static int gpt_check_hdr_crc(const struct disk_info * const diskinfo, struct dis hold_crc32 = gh->chksum; gh->chksum = 0; - if (check_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { + if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { error("WARNING: Primary GPT header checksum invalid.\n"); /* retry with backup */ lba_alt = gh->lba_alt; @@ -495,7 +418,7 @@ static int gpt_check_hdr_crc(const struct disk_info * const diskinfo, struct dis } hold_crc32 = gh->chksum; gh->chksum = 0; - if (check_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { + if (!valid_crc(hold_crc32, (const uint8_t *)gh, gh->hdr_size)) { error("Secondary GPT header checksum invalid.\n"); return -1; } @@ -506,34 +429,33 @@ static int gpt_check_hdr_crc(const struct disk_info * const diskinfo, struct dis return 0; } -static struct part_iter *pi_raw_next(struct part_iter *iter) +static int pi_next_(struct part_iter *iter) { iter->status = PI_DONE; - return NULL; + return iter->status; } -static struct part_iter *pi_dos_next(struct part_iter *iter) +static int pi_dos_next(struct part_iter *iter) { uint32_t start_lba = 0; struct disk_dos_part_entry *dos_part = NULL; if (iter->status) - goto bail; + return iter->status; /* look for primary partitions */ if (iter->index0 < 4 && - pi_dos_next_mbr(iter, &start_lba, &dos_part)) - goto bail; + dos_next_mbr(iter, &start_lba, &dos_part) < 0) + return iter->status; /* look for logical partitions */ if (iter->index0 >= 4 && - pi_dos_next_ebr(iter, &start_lba, &dos_part)) - goto bail; + dos_next_ebr(iter, &start_lba, &dos_part) < 0) + return iter->status; /* - * note special index handling, if we have stepall set - - * this is made to keep index consistent with non-stepall - * iterators + * note special index handling, if we have PIF_STEPALL set - this is made + * to keep index consistent with non-PIF_STEPALL iterators */ if (iter->index0 >= 4 && !dos_part->ostype) @@ -549,17 +471,15 @@ static struct part_iter *pi_dos_next(struct part_iter *iter) disk_dos_part_dump(dos_part); #endif - return iter; -bail: - return NULL; + return iter->status; } -static struct part_iter *pi_gpt_next(struct part_iter *iter) +static int pi_gpt_next(struct part_iter *iter) { const struct disk_gpt_part_entry *gpt_part = NULL; if (iter->status) - goto bail; + return iter->status; while (++iter->index0 < iter->gpt.pe_count) { gpt_part = (const struct disk_gpt_part_entry *) @@ -567,7 +487,7 @@ static struct part_iter *pi_gpt_next(struct part_iter *iter) if (notsane_gpt(iter)) { iter->status = PI_INSANE; - goto bail; + return iter->status; } if (!guid_is0(&gpt_part->type) || (iter->flags & PIF_STEPALL)) @@ -576,7 +496,7 @@ static struct part_iter *pi_gpt_next(struct part_iter *iter) /* no more partitions ? */ if (iter->index0 == iter->gpt.pe_count) { iter->status = PI_DONE; - goto bail; + return iter->status; } /* gpt_part is guaranteed to be valid here */ iter->index = iter->index0 + 1; @@ -591,135 +511,53 @@ static struct part_iter *pi_gpt_next(struct part_iter *iter) disk_gpt_part_dump(gpt_part); #endif - return iter; -bail: - return NULL; + return iter->status; } -/* - * ---------------------------------------------------------------------------- - * Following functions are for users to call. - * ---------------------------------------------------------------------------- - */ - - -int pi_next(struct part_iter **_iter) +static struct part_iter *pi_alloc(void) { struct part_iter *iter; - - if(!_iter || !*_iter) - return 0; - iter = *_iter; -#ifdef DEBUG - if (inv_type(iter->type)) { - error("This is not a valid iterator.\n"); - return 0; - } -#endif - if ((iter = iter->type->next(iter))) { - *_iter = iter; - } - return (*_iter)->status; -} - -/** - * pi_new() - get new iterator - * @itertype: iterator type - * @...: variable arguments passed to ctors - * - * Variable arguments depend on the type. Please see functions: - * iter_gpt_ctor() and iter_dos_ctor() for details. - **/ -struct part_iter *pi_new(const struct itertype *type, ...) -{ - int badctor = 0; - struct part_iter *iter = NULL; - va_list ap; - - va_start(ap, type); - -#ifdef DEBUG - if (inv_type(type)) { - error("Unknown iterator requested.\n"); - goto bail; - } -#endif - - if (!(iter = malloc(sizeof(struct part_iter)))) { + if (!(iter = malloc(sizeof(struct part_iter)))) error("Couldn't allocate memory for the iterator.\n"); - goto bail; - } - - memset(iter, 0, sizeof(struct part_iter)); - iter->type = type; - - if (type->ctor(iter, &ap)) { - badctor = -1; - error("Cannot initialize the iterator.\n"); - goto bail; - } - -bail: - va_end(ap); - if (badctor) { - free(iter); - iter = NULL; - } + else + memset(iter, 0, sizeof(struct part_iter)); return iter; } -/** - * pi_del() - delete iterator - * @iter: iterator double pointer - * - **/ - +/* pi_del() - delete iterator */ void pi_del(struct part_iter **_iter) { - struct part_iter *iter; - if(!_iter || !*_iter) return; - iter = *_iter; - -#ifdef DEBUG - if (inv_type(iter->type)) { - error("This is not a valid iterator.\n"); - return; - } -#endif - - iter->type->dtor(iter); - free(iter); + pi_dtor(*_iter); + free(*_iter); *_iter = NULL; } -/** - * pi_begin() - check disk, validate, and get proper iterator - * @di: diskinfo struct pointer - * - * This function checks the disk for GPT or legacy partition table and allocates - * an appropriate iterator. - **/ +/* 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 setraw = 0; - struct part_iter *iter = NULL; + int 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 first disk sector.\n"); goto bail; } - setraw = -1; - - /* Check for MBR magic*/ + /* Check for MBR magic */ if (mbr->sig != disk_mbr_sig_magic) { - error("No MBR magic.\n"); + error("WARNING: no MBR magic, treating disk as raw.\n"); + /* looks like RAW */ + ret = pi_ctor(iter, di, flags); goto bail; } @@ -770,32 +608,28 @@ struct part_iter *pi_begin(const struct disk_info *di, int flags) goto bail; } /* Check array checksum(s). */ - if (check_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) { - error("WARNING: GPT partition list checksum invalid, trying backup.\n"); + if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, (unsigned int)gpt_lsiz)) { + error("Main GPT partition list's checksum invalid, trying backup.\n"); 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.\n"); goto bail; } - if (check_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) { - error("Backup GPT partition list checksum invalid.\n"); + if (!valid_crc(gpth->table_chksum, (const uint8_t *)gptl, gpt_lsiz)) { + error("Backup GPT partition list's checksum invalid.\n"); goto bail; } } - /* allocate iterator and exit */ - iter = pi_new(typegpt, di, flags, gpth, gptl); + /* looks like GPT */ + ret = pi_gpt_ctor(iter, di, flags, gpth, gptl); } else { /* looks like MBR */ - iter = pi_new(typedos, di, flags, mbr); + ret = pi_dos_ctor(iter, di, flags, mbr); } - - setraw = 0; bail: - if (setraw) { - error("WARNING: treating disk as raw.\n"); - iter = pi_new(typeraw, di, flags); - } + if (ret < 0) + free(iter); free(mbr); free(gpth); free(gptl); diff --git a/com32/chain/partiter.h b/com32/chain/partiter.h index ac15de63..821d4481 100644 --- a/com32/chain/partiter.h +++ b/com32/chain/partiter.h @@ -40,12 +40,11 @@ #include <stdint.h> #include <syslinux/disk.h> -#define PI_ERRLOAD 3 -#define PI_INSANE 2 -#define PI_DONE 1 -#define PI_OK 0 +/* status */ -/* behaviour flags */ +enum {PI_OK, PI_DONE, PI_INSANE, PI_ERRLOAD}; + +/* flags */ #define PIF_STEPALL 0x01 @@ -53,9 +52,8 @@ struct itertype; struct part_iter; struct itertype { - int (*ctor)(struct part_iter *, va_list *); void (*dtor)(struct part_iter *); - struct part_iter *(*next) (struct part_iter *); + int (*next)(struct part_iter *); }; #define PI_GPTLABSIZE ((int)sizeof(((struct disk_gpt_part_entry *)0)->name)) @@ -66,13 +64,12 @@ struct part_iter { char *record; uint64_t start_lba; uint64_t length; - int index; - int rawindex; + int index0; /* including holes, from -1 (disk, then parts from 0) */ + int rawindex; /* including holes, from 0 (disk, then parts from 1) */ + int index; /* excluding holes, from 0 (disk) (-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; - int flags; - int status; - /* internal */ - int index0; union { struct { uint32_t disk_sig; @@ -103,9 +100,18 @@ extern const struct itertype * const typegpt; extern const struct itertype * const typeraw; struct part_iter *pi_begin(const struct disk_info *, int flags); -struct part_iter *pi_new(const struct itertype *, ...); void pi_del(struct part_iter **); -int pi_next(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 |