diff --git a/util/nvramtool/Makefile b/util/nvramtool/Makefile index a705494468..520655dbb5 100644 --- a/util/nvramtool/Makefile +++ b/util/nvramtool/Makefile @@ -30,7 +30,7 @@ CFLAGS = -O2 -g -Wall -W -I. CLI_OBJS = cli/nvramtool.o cli/opts.o OBJS = cmos_lowlevel.o cmos_ops.o common.o compute_ip_checksum.o \ - hexdump.o input_file.o layout.o accessors/layout-text.o lbtable.o \ + hexdump.o input_file.o layout.o accessors/layout-text.o accessors/layout-bin.o lbtable.o \ reg_expr.o cbfs.o accessors/cmos-hw-unix.o accessors/cmos-mem.o OBJS += $(CLI_OBJS) diff --git a/util/nvramtool/accessors/layout-bin.c b/util/nvramtool/accessors/layout-bin.c new file mode 100644 index 0000000000..53f0530c40 --- /dev/null +++ b/util/nvramtool/accessors/layout-bin.c @@ -0,0 +1,460 @@ +/*****************************************************************************\ + * lbtable.c + ***************************************************************************** + * Copyright (C) 2002-2005 The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Dave Peterson + * and Stefan Reinauer . + * UCRL-CODE-2003-012 + * All rights reserved. + * + * This file is part of nvramtool, a utility for reading/writing coreboot + * parameters and displaying information from the coreboot table. + * For details, see http://coreboot.org/nvramtool. + * + * Please also read the file DISCLAIMER which is included in this software + * distribution. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License (as published by the + * Free Software Foundation) version 2, dated June 1991. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and + * conditions of the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +\*****************************************************************************/ + +#include +#include +#include +#include "common.h" +#include "coreboot_tables.h" +#include "ip_checksum.h" +#include "lbtable.h" +#include "layout.h" +#include "cmos_lowlevel.h" +#include "hexdump.h" +#include "cbfs.h" + +static void process_cmos_table(void); +static void get_cmos_checksum_info(void); +static void try_convert_checksum_layout(cmos_checksum_layout_t * layout); +static void try_add_cmos_table_enum(cmos_enum_t * cmos_enum); +static void try_add_cmos_table_entry(cmos_entry_t * cmos_entry); +static const struct cmos_entries *first_cmos_table_entry(void); +static const struct cmos_entries *next_cmos_table_entry(const struct + cmos_entries *last); +static const struct cmos_enums *first_cmos_table_enum(void); +static const struct cmos_enums *next_cmos_table_enum + (const struct cmos_enums *last); +static const struct lb_record *first_cmos_rec(uint32_t tag); +static const struct lb_record *next_cmos_rec(const struct lb_record *last, + uint32_t tag); + +/* The CMOS option table is located within the coreboot table. It tells us + * where the CMOS parameters are located in the nonvolatile RAM. + */ +static const struct cmos_option_table *cmos_table = NULL; + +void process_layout(void) +{ + if ((cmos_table) == NULL) { + fprintf(stderr, + "%s: CMOS option table not found in coreboot table. " + "Apparently, the coreboot installed on this system was " + "built without specifying CONFIG_HAVE_OPTION_TABLE.\n", + prog_name); + exit(1); + } + + process_cmos_table(); + get_cmos_checksum_info(); +} + +void get_layout_from_cbfs_file(void) +{ + uint32_t len; + cmos_table = cbfs_find_file("cmos_layout.bin", CBFS_COMPONENT_CMOS_LAYOUT, &len); + process_layout(); +} + +/**************************************************************************** + * process_cmos_table + * + * Extract layout information from the CMOS option table and store it in our + * internal repository. + ****************************************************************************/ +static void process_cmos_table(void) +{ + const struct cmos_enums *p; + const struct cmos_entries *q; + cmos_enum_t cmos_enum; + cmos_entry_t cmos_entry; + + /* First add the enums. */ + for (p = first_cmos_table_enum(); p != NULL; + p = next_cmos_table_enum(p)) { + cmos_enum.config_id = p->config_id; + cmos_enum.value = p->value; + strncpy(cmos_enum.text, (char *)p->text, CMOS_MAX_TEXT_LENGTH); + cmos_enum.text[CMOS_MAX_TEXT_LENGTH] = '\0'; + try_add_cmos_table_enum(&cmos_enum); + } + + /* Now add the entries. We must add the entries after the enums because + * the entries are sanity checked against the enums as they are added. + */ + for (q = first_cmos_table_entry(); q != NULL; + q = next_cmos_table_entry(q)) { + cmos_entry.bit = q->bit; + cmos_entry.length = q->length; + + switch (q->config) { + case 'e': + cmos_entry.config = CMOS_ENTRY_ENUM; + break; + + case 'h': + cmos_entry.config = CMOS_ENTRY_HEX; + break; + + case 'r': + cmos_entry.config = CMOS_ENTRY_RESERVED; + break; + + case 's': + cmos_entry.config = CMOS_ENTRY_STRING; + break; + + default: + fprintf(stderr, + "%s: Entry in CMOS option table has unknown config " + "value.\n", prog_name); + exit(1); + } + + cmos_entry.config_id = q->config_id; + strncpy(cmos_entry.name, (char *)q->name, CMOS_MAX_NAME_LENGTH); + cmos_entry.name[CMOS_MAX_NAME_LENGTH] = '\0'; + try_add_cmos_table_entry(&cmos_entry); + } +} + +/**************************************************************************** + * get_cmos_checksum_info + * + * Get layout information for CMOS checksum. + ****************************************************************************/ +static void get_cmos_checksum_info(void) +{ + const cmos_entry_t *e; + struct cmos_checksum *checksum; + cmos_checksum_layout_t layout; + unsigned index, index2; + + checksum = (struct cmos_checksum *)next_cmos_rec((const struct lb_record *)first_cmos_table_enum(), LB_TAG_OPTION_CHECKSUM); + + if (checksum != NULL) { /* We are lucky. The coreboot table hints us to the checksum. + * We might have to check the type field here though. + */ + layout.summed_area_start = checksum->range_start; + layout.summed_area_end = checksum->range_end; + layout.checksum_at = checksum->location; + try_convert_checksum_layout(&layout); + cmos_checksum_start = layout.summed_area_start; + cmos_checksum_end = layout.summed_area_end; + cmos_checksum_index = layout.checksum_at; + return; + } + + if ((e = find_cmos_entry(checksum_param_name)) == NULL) + return; + + /* If we get here, we are unlucky. The CMOS option table contains the + * location of the CMOS checksum. However, there is no information + * regarding which bytes of the CMOS area the checksum is computed over. + * Thus we have to hope our presets will be fine. + */ + + if (e->bit % 8) { + fprintf(stderr, + "%s: Error: CMOS checksum is not byte-aligned.\n", + prog_name); + exit(1); + } + + index = e->bit / 8; + index2 = index + 1; /* The CMOS checksum occupies 16 bits. */ + + if (verify_cmos_byte_index(index) || verify_cmos_byte_index(index2)) { + fprintf(stderr, + "%s: Error: CMOS checksum location out of range.\n", + prog_name); + exit(1); + } + + if (((index >= cmos_checksum_start) && (index <= cmos_checksum_end)) || + (((index2) >= cmos_checksum_start) + && ((index2) <= cmos_checksum_end))) { + fprintf(stderr, + "%s: Error: CMOS checksum overlaps checksummed area.\n", + prog_name); + exit(1); + } + + cmos_checksum_index = index; +} + +/**************************************************************************** + * try_convert_checksum_layout + * + * Perform sanity checking on CMOS checksum layout information and attempt to + * convert information from bit positions to byte positions. Return OK on + * success or an error code on failure. + ****************************************************************************/ +static void try_convert_checksum_layout(cmos_checksum_layout_t * layout) +{ + switch (checksum_layout_to_bytes(layout)) { + case OK: + return; + + case LAYOUT_SUMMED_AREA_START_NOT_ALIGNED: + fprintf(stderr, + "%s: CMOS checksummed area start is not byte-aligned.\n", + prog_name); + break; + + case LAYOUT_SUMMED_AREA_END_NOT_ALIGNED: + fprintf(stderr, + "%s: CMOS checksummed area end is not byte-aligned.\n", + prog_name); + break; + + case LAYOUT_CHECKSUM_LOCATION_NOT_ALIGNED: + fprintf(stderr, + "%s: CMOS checksum location is not byte-aligned.\n", + prog_name); + break; + + case LAYOUT_INVALID_SUMMED_AREA: + fprintf(stderr, + "%s: CMOS checksummed area end must be greater than " + "CMOS checksummed area start.\n", prog_name); + break; + + case LAYOUT_CHECKSUM_OVERLAPS_SUMMED_AREA: + fprintf(stderr, + "%s: CMOS checksum overlaps checksummed area.\n", + prog_name); + break; + + case LAYOUT_SUMMED_AREA_OUT_OF_RANGE: + fprintf(stderr, + "%s: CMOS checksummed area out of range.\n", prog_name); + break; + + case LAYOUT_CHECKSUM_LOCATION_OUT_OF_RANGE: + fprintf(stderr, + "%s: CMOS checksum location out of range.\n", + prog_name); + break; + + default: + BUG(); + } + + exit(1); +} + +/**************************************************************************** + * try_add_cmos_table_enum + * + * Attempt to add a CMOS enum to our internal repository. Exit with an error + * message on failure. + ****************************************************************************/ +static void try_add_cmos_table_enum(cmos_enum_t * cmos_enum) +{ + switch (add_cmos_enum(cmos_enum)) { + case OK: + return; + + case LAYOUT_DUPLICATE_ENUM: + fprintf(stderr, "%s: Duplicate enum %s found in CMOS option " + "table.\n", prog_name, cmos_enum->text); + break; + + default: + BUG(); + } + + exit(1); +} + +/**************************************************************************** + * try_add_cmos_table_entry + * + * Attempt to add a CMOS entry to our internal repository. Exit with an + * error message on failure. + ****************************************************************************/ +static void try_add_cmos_table_entry(cmos_entry_t * cmos_entry) +{ + const cmos_entry_t *conflict; + + switch (add_cmos_entry(cmos_entry, &conflict)) { + case OK: + return; + + case CMOS_AREA_OUT_OF_RANGE: + fprintf(stderr, + "%s: Bad CMOS option layout in CMOS option table entry " + "%s.\n", prog_name, cmos_entry->name); + break; + + case CMOS_AREA_TOO_WIDE: + fprintf(stderr, + "%s: Area too wide for CMOS option table entry %s.\n", + prog_name, cmos_entry->name); + break; + + case LAYOUT_ENTRY_OVERLAP: + fprintf(stderr, + "%s: CMOS option table entries %s and %s have overlapping " + "layouts.\n", prog_name, cmos_entry->name, + conflict->name); + break; + + case LAYOUT_ENTRY_BAD_LENGTH: + /* Silently ignore entries with zero length. Although this should + * never happen in practice, we should handle the case in a + * reasonable manner just to be safe. + */ + return; + + default: + BUG(); + } + + exit(1); +} + +/**************************************************************************** + * first_cmos_table_entry + * + * Return a pointer to the first entry in the CMOS table that represents a + * CMOS parameter. Return NULL if CMOS table is empty. + ****************************************************************************/ +static const struct cmos_entries *first_cmos_table_entry(void) +{ + return (const struct cmos_entries *)first_cmos_rec(LB_TAG_OPTION); +} + +/**************************************************************************** + * next_cmos_table_entry + * + * Return a pointer to the next entry after 'last' in the CMOS table that + * represents a CMOS parameter. Return NULL if there are no more parameters. + ****************************************************************************/ +static const struct cmos_entries *next_cmos_table_entry(const struct + cmos_entries *last) +{ + return (const struct cmos_entries *) + next_cmos_rec((const struct lb_record *)last, LB_TAG_OPTION); +} + +/**************************************************************************** + * first_cmos_table_enum + * + * Return a pointer to the first entry in the CMOS table that represents a + * possible CMOS parameter value. Return NULL if the table does not contain + * any such entries. + ****************************************************************************/ +static const struct cmos_enums *first_cmos_table_enum(void) +{ + return (const struct cmos_enums *)first_cmos_rec(LB_TAG_OPTION_ENUM); +} + +/**************************************************************************** + * next_cmos_table_enum + * + * Return a pointer to the next entry after 'last' in the CMOS table that + * represents a possible CMOS parameter value. Return NULL if there are no + * more parameter values. + ****************************************************************************/ +static const struct cmos_enums *next_cmos_table_enum + (const struct cmos_enums *last) { + return (const struct cmos_enums *) + next_cmos_rec((const struct lb_record *)last, LB_TAG_OPTION_ENUM); +} + +/**************************************************************************** + * first_cmos_rec + * + * Return a pointer to the first entry in the CMOS table whose type matches + * 'tag'. Return NULL if CMOS table contains no such entry. + * + * Possible values for 'tag' are as follows: + * + * LB_TAG_OPTION: The entry represents a CMOS parameter. + * LB_TAG_OPTION_ENUM: The entry represents a possible value for a CMOS + * parameter of type 'enum'. + * + * The CMOS table tells us where in the nonvolatile RAM to look for CMOS + * parameter values and specifies their types as 'enum', 'hex', or + * 'reserved'. + ****************************************************************************/ +static const struct lb_record *first_cmos_rec(uint32_t tag) +{ + const char *p; + uint32_t bytes_processed, bytes_for_entries; + const struct lb_record *lbrec; + + p = ((const char *)cmos_table) + cmos_table->header_length; + bytes_for_entries = cmos_table->size - cmos_table->header_length; + + for (bytes_processed = 0; + bytes_processed < bytes_for_entries; + bytes_processed += lbrec->size) { + lbrec = (const struct lb_record *)&p[bytes_processed]; + + if (lbrec->tag == tag) + return lbrec; + } + + return NULL; +} + +/**************************************************************************** + * next_cmos_rec + * + * Return a pointer to the next entry after 'last' in the CMOS table whose + * type matches 'tag'. Return NULL if the table contains no more entries of + * this type. + ****************************************************************************/ +static const struct lb_record *next_cmos_rec(const struct lb_record *last, + uint32_t tag) +{ + const char *p; + uint32_t bytes_processed, bytes_for_entries, last_offset; + const struct lb_record *lbrec; + + p = ((const char *)cmos_table) + cmos_table->header_length; + bytes_for_entries = cmos_table->size - cmos_table->header_length; + last_offset = ((const char *)last) - p; + + for (bytes_processed = last_offset + last->size; + bytes_processed < bytes_for_entries; + bytes_processed += lbrec->size) { + lbrec = (const struct lb_record *)&p[bytes_processed]; + + if (lbrec->tag == tag) + return lbrec; + } + + return NULL; +} + diff --git a/util/nvramtool/lbtable.c b/util/nvramtool/lbtable.c index 0ec25f8317..2ce43c50f9 100644 --- a/util/nvramtool/lbtable.c +++ b/util/nvramtool/lbtable.c @@ -63,22 +63,8 @@ static const struct lb_header *lbtable_scan(unsigned long start, unsigned long end, int *bad_header_count, int *bad_table_count); -static void process_cmos_table(void); -static void get_cmos_checksum_info(void); -static void try_convert_checksum_layout(cmos_checksum_layout_t * layout); -static void try_add_cmos_table_enum(cmos_enum_t * cmos_enum); -static void try_add_cmos_table_entry(cmos_entry_t * cmos_entry); static const struct lb_record *find_lbrec(uint32_t tag); static const char *lbrec_tag_to_str(uint32_t tag); -static const struct cmos_entries *first_cmos_table_entry(void); -static const struct cmos_entries *next_cmos_table_entry(const struct - cmos_entries *last); -static const struct cmos_enums *first_cmos_table_enum(void); -static const struct cmos_enums *next_cmos_table_enum - (const struct cmos_enums *last); -static const struct lb_record *first_cmos_rec(uint32_t tag); -static const struct lb_record *next_cmos_rec(const struct lb_record *last, - uint32_t tag); static void memory_print_fn(const struct lb_record *rec); static void mainboard_print_fn(const struct lb_record *rec); static void cmos_opt_table_print_fn(const struct lb_record *rec); @@ -316,21 +302,6 @@ void get_lbtable(void) exit(1); } -static void process_layout(void) -{ - if ((cmos_table) == NULL) { - fprintf(stderr, - "%s: CMOS option table not found in coreboot table. " - "Apparently, the coreboot installed on this system was " - "built without specifying CONFIG_HAVE_OPTION_TABLE.\n", - prog_name); - exit(1); - } - - process_cmos_table(); - get_cmos_checksum_info(); -} - /**************************************************************************** * get_layout_from_cmos_table * @@ -346,17 +317,6 @@ void get_layout_from_cmos_table(void) process_layout(); } -void get_layout_from_cbfs_file(void) -{ - static struct lb_header header; - u32 len; - cmos_table = cbfs_find_file("cmos_layout.bin", CBFS_COMPONENT_CMOS_LAYOUT, &len); - lbtable = &header; - header.header_bytes = (u32)cmos_table-(u32)lbtable; - header.table_bytes = ntohl(len); - process_layout(); -} - /**************************************************************************** * dump_lbtable * @@ -572,269 +532,6 @@ static const struct lb_header *lbtable_scan(unsigned long start, return NULL; } -/**************************************************************************** - * process_cmos_table - * - * Extract layout information from the CMOS option table and store it in our - * internal repository. - ****************************************************************************/ -static void process_cmos_table(void) -{ - const struct cmos_enums *p; - const struct cmos_entries *q; - cmos_enum_t cmos_enum; - cmos_entry_t cmos_entry; - - /* First add the enums. */ - for (p = first_cmos_table_enum(); p != NULL; - p = next_cmos_table_enum(p)) { - cmos_enum.config_id = p->config_id; - cmos_enum.value = p->value; - strncpy(cmos_enum.text, (char *)p->text, CMOS_MAX_TEXT_LENGTH); - cmos_enum.text[CMOS_MAX_TEXT_LENGTH] = '\0'; - try_add_cmos_table_enum(&cmos_enum); - } - - /* Now add the entries. We must add the entries after the enums because - * the entries are sanity checked against the enums as they are added. - */ - for (q = first_cmos_table_entry(); q != NULL; - q = next_cmos_table_entry(q)) { - cmos_entry.bit = q->bit; - cmos_entry.length = q->length; - - switch (q->config) { - case 'e': - cmos_entry.config = CMOS_ENTRY_ENUM; - break; - - case 'h': - cmos_entry.config = CMOS_ENTRY_HEX; - break; - - case 'r': - cmos_entry.config = CMOS_ENTRY_RESERVED; - break; - - case 's': - cmos_entry.config = CMOS_ENTRY_STRING; - break; - - default: - fprintf(stderr, - "%s: Entry in CMOS option table has unknown config " - "value.\n", prog_name); - exit(1); - } - - cmos_entry.config_id = q->config_id; - strncpy(cmos_entry.name, (char *)q->name, CMOS_MAX_NAME_LENGTH); - cmos_entry.name[CMOS_MAX_NAME_LENGTH] = '\0'; - try_add_cmos_table_entry(&cmos_entry); - } -} - -/**************************************************************************** - * get_cmos_checksum_info - * - * Get layout information for CMOS checksum. - ****************************************************************************/ -static void get_cmos_checksum_info(void) -{ - const cmos_entry_t *e; - struct cmos_checksum *checksum; - cmos_checksum_layout_t layout; - unsigned index, index2; - - checksum = (struct cmos_checksum *)find_lbrec(LB_TAG_OPTION_CHECKSUM); - - if (checksum == NULL) { - checksum = (struct cmos_checksum *)next_cmos_rec((const struct lb_record *)first_cmos_table_enum(), LB_TAG_OPTION_CHECKSUM); - } - - if (checksum != NULL) { /* We are lucky. The coreboot table hints us to the checksum. - * We might have to check the type field here though. - */ - layout.summed_area_start = checksum->range_start; - layout.summed_area_end = checksum->range_end; - layout.checksum_at = checksum->location; - try_convert_checksum_layout(&layout); - cmos_checksum_start = layout.summed_area_start; - cmos_checksum_end = layout.summed_area_end; - cmos_checksum_index = layout.checksum_at; - return; - } - - if ((e = find_cmos_entry(checksum_param_name)) == NULL) - return; - - /* If we get here, we are unlucky. The CMOS option table contains the - * location of the CMOS checksum. However, there is no information - * regarding which bytes of the CMOS area the checksum is computed over. - * Thus we have to hope our presets will be fine. - */ - - if (e->bit % 8) { - fprintf(stderr, - "%s: Error: CMOS checksum is not byte-aligned.\n", - prog_name); - exit(1); - } - - index = e->bit / 8; - index2 = index + 1; /* The CMOS checksum occupies 16 bits. */ - - if (verify_cmos_byte_index(index) || verify_cmos_byte_index(index2)) { - fprintf(stderr, - "%s: Error: CMOS checksum location out of range.\n", - prog_name); - exit(1); - } - - if (((index >= cmos_checksum_start) && (index <= cmos_checksum_end)) || - (((index2) >= cmos_checksum_start) - && ((index2) <= cmos_checksum_end))) { - fprintf(stderr, - "%s: Error: CMOS checksum overlaps checksummed area.\n", - prog_name); - exit(1); - } - - cmos_checksum_index = index; -} - -/**************************************************************************** - * try_convert_checksum_layout - * - * Perform sanity checking on CMOS checksum layout information and attempt to - * convert information from bit positions to byte positions. Return OK on - * success or an error code on failure. - ****************************************************************************/ -static void try_convert_checksum_layout(cmos_checksum_layout_t * layout) -{ - switch (checksum_layout_to_bytes(layout)) { - case OK: - return; - - case LAYOUT_SUMMED_AREA_START_NOT_ALIGNED: - fprintf(stderr, - "%s: CMOS checksummed area start is not byte-aligned.\n", - prog_name); - break; - - case LAYOUT_SUMMED_AREA_END_NOT_ALIGNED: - fprintf(stderr, - "%s: CMOS checksummed area end is not byte-aligned.\n", - prog_name); - break; - - case LAYOUT_CHECKSUM_LOCATION_NOT_ALIGNED: - fprintf(stderr, - "%s: CMOS checksum location is not byte-aligned.\n", - prog_name); - break; - - case LAYOUT_INVALID_SUMMED_AREA: - fprintf(stderr, - "%s: CMOS checksummed area end must be greater than " - "CMOS checksummed area start.\n", prog_name); - break; - - case LAYOUT_CHECKSUM_OVERLAPS_SUMMED_AREA: - fprintf(stderr, - "%s: CMOS checksum overlaps checksummed area.\n", - prog_name); - break; - - case LAYOUT_SUMMED_AREA_OUT_OF_RANGE: - fprintf(stderr, - "%s: CMOS checksummed area out of range.\n", prog_name); - break; - - case LAYOUT_CHECKSUM_LOCATION_OUT_OF_RANGE: - fprintf(stderr, - "%s: CMOS checksum location out of range.\n", - prog_name); - break; - - default: - BUG(); - } - - exit(1); -} - -/**************************************************************************** - * try_add_cmos_table_enum - * - * Attempt to add a CMOS enum to our internal repository. Exit with an error - * message on failure. - ****************************************************************************/ -static void try_add_cmos_table_enum(cmos_enum_t * cmos_enum) -{ - switch (add_cmos_enum(cmos_enum)) { - case OK: - return; - - case LAYOUT_DUPLICATE_ENUM: - fprintf(stderr, "%s: Duplicate enum %s found in CMOS option " - "table.\n", prog_name, cmos_enum->text); - break; - - default: - BUG(); - } - - exit(1); -} - -/**************************************************************************** - * try_add_cmos_table_entry - * - * Attempt to add a CMOS entry to our internal repository. Exit with an - * error message on failure. - ****************************************************************************/ -static void try_add_cmos_table_entry(cmos_entry_t * cmos_entry) -{ - const cmos_entry_t *conflict; - - switch (add_cmos_entry(cmos_entry, &conflict)) { - case OK: - return; - - case CMOS_AREA_OUT_OF_RANGE: - fprintf(stderr, - "%s: Bad CMOS option layout in CMOS option table entry " - "%s.\n", prog_name, cmos_entry->name); - break; - - case CMOS_AREA_TOO_WIDE: - fprintf(stderr, - "%s: Area too wide for CMOS option table entry %s.\n", - prog_name, cmos_entry->name); - break; - - case LAYOUT_ENTRY_OVERLAP: - fprintf(stderr, - "%s: CMOS option table entries %s and %s have overlapping " - "layouts.\n", prog_name, cmos_entry->name, - conflict->name); - break; - - case LAYOUT_ENTRY_BAD_LENGTH: - /* Silently ignore entries with zero length. Although this should - * never happen in practice, we should handle the case in a - * reasonable manner just to be safe. - */ - return; - - default: - BUG(); - } - - exit(1); -} - /**************************************************************************** * find_lbrec * @@ -934,122 +631,6 @@ static const char *lbrec_tag_to_str(uint32_t tag) return "UNKNOWN"; } -/**************************************************************************** - * first_cmos_table_entry - * - * Return a pointer to the first entry in the CMOS table that represents a - * CMOS parameter. Return NULL if CMOS table is empty. - ****************************************************************************/ -static const struct cmos_entries *first_cmos_table_entry(void) -{ - return (const struct cmos_entries *)first_cmos_rec(LB_TAG_OPTION); -} - -/**************************************************************************** - * next_cmos_table_entry - * - * Return a pointer to the next entry after 'last' in the CMOS table that - * represents a CMOS parameter. Return NULL if there are no more parameters. - ****************************************************************************/ -static const struct cmos_entries *next_cmos_table_entry(const struct - cmos_entries *last) -{ - return (const struct cmos_entries *) - next_cmos_rec((const struct lb_record *)last, LB_TAG_OPTION); -} - -/**************************************************************************** - * first_cmos_table_enum - * - * Return a pointer to the first entry in the CMOS table that represents a - * possible CMOS parameter value. Return NULL if the table does not contain - * any such entries. - ****************************************************************************/ -static const struct cmos_enums *first_cmos_table_enum(void) -{ - return (const struct cmos_enums *)first_cmos_rec(LB_TAG_OPTION_ENUM); -} - -/**************************************************************************** - * next_cmos_table_enum - * - * Return a pointer to the next entry after 'last' in the CMOS table that - * represents a possible CMOS parameter value. Return NULL if there are no - * more parameter values. - ****************************************************************************/ -static const struct cmos_enums *next_cmos_table_enum - (const struct cmos_enums *last) { - return (const struct cmos_enums *) - next_cmos_rec((const struct lb_record *)last, LB_TAG_OPTION_ENUM); -} - -/**************************************************************************** - * first_cmos_rec - * - * Return a pointer to the first entry in the CMOS table whose type matches - * 'tag'. Return NULL if CMOS table contains no such entry. - * - * Possible values for 'tag' are as follows: - * - * LB_TAG_OPTION: The entry represents a CMOS parameter. - * LB_TAG_OPTION_ENUM: The entry represents a possible value for a CMOS - * parameter of type 'enum'. - * - * The CMOS table tells us where in the nonvolatile RAM to look for CMOS - * parameter values and specifies their types as 'enum', 'hex', or - * 'reserved'. - ****************************************************************************/ -static const struct lb_record *first_cmos_rec(uint32_t tag) -{ - const char *p; - uint32_t bytes_processed, bytes_for_entries; - const struct lb_record *lbrec; - - p = ((const char *)cmos_table) + cmos_table->header_length; - bytes_for_entries = cmos_table->size - cmos_table->header_length; - - for (bytes_processed = 0; - bytes_processed < bytes_for_entries; - bytes_processed += lbrec->size) { - lbrec = (const struct lb_record *)&p[bytes_processed]; - - if (lbrec->tag == tag) - return lbrec; - } - - return NULL; -} - -/**************************************************************************** - * next_cmos_rec - * - * Return a pointer to the next entry after 'last' in the CMOS table whose - * type matches 'tag'. Return NULL if the table contains no more entries of - * this type. - ****************************************************************************/ -static const struct lb_record *next_cmos_rec(const struct lb_record *last, - uint32_t tag) -{ - const char *p; - uint32_t bytes_processed, bytes_for_entries, last_offset; - const struct lb_record *lbrec; - - p = ((const char *)cmos_table) + cmos_table->header_length; - bytes_for_entries = cmos_table->size - cmos_table->header_length; - last_offset = ((const char *)last) - p; - - for (bytes_processed = last_offset + last->size; - bytes_processed < bytes_for_entries; - bytes_processed += lbrec->size) { - lbrec = (const struct lb_record *)&p[bytes_processed]; - - if (lbrec->tag == tag) - return lbrec; - } - - return NULL; -} - /**************************************************************************** * memory_print_fn * diff --git a/util/nvramtool/lbtable.h b/util/nvramtool/lbtable.h index c9276b6d04..319557e24a 100644 --- a/util/nvramtool/lbtable.h +++ b/util/nvramtool/lbtable.h @@ -40,4 +40,5 @@ void dump_lbtable(void); void list_lbtable_choices(void); void list_lbtable_item(const char item[]); +void process_layout(void); #endif /* LBTABLE_H */