From 49a74437aab0c253243e62aca20966cf22f864e6 Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Fri, 28 Jan 2011 07:50:33 +0000 Subject: Move the parser for cmos.layout text files to accessors Signed-off-by: Patrick Georgi Acked-by: Stefan Reinauer git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6312 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- util/nvramtool/Makefile | 2 +- util/nvramtool/accessors/layout-text.c | 900 +++++++++++++++++++++++++++++++++ util/nvramtool/accessors/layout-text.h | 41 ++ util/nvramtool/cli/nvramtool.c | 2 +- util/nvramtool/layout_file.c | 900 --------------------------------- util/nvramtool/layout_file.h | 41 -- 6 files changed, 943 insertions(+), 943 deletions(-) create mode 100644 util/nvramtool/accessors/layout-text.c create mode 100644 util/nvramtool/accessors/layout-text.h delete mode 100644 util/nvramtool/layout_file.c delete mode 100644 util/nvramtool/layout_file.h (limited to 'util/nvramtool') diff --git a/util/nvramtool/Makefile b/util/nvramtool/Makefile index 673b394455..ff9072e2b6 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 layout_file.o lbtable.o \ + hexdump.o input_file.o layout.o accessors/layout-text.o lbtable.o \ reg_expr.o cbfs.o OBJS += $(CLI_OBJS) diff --git a/util/nvramtool/accessors/layout-text.c b/util/nvramtool/accessors/layout-text.c new file mode 100644 index 0000000000..5f7cadea97 --- /dev/null +++ b/util/nvramtool/accessors/layout-text.c @@ -0,0 +1,900 @@ +/*****************************************************************************\ + * layout-text.c + ***************************************************************************** + * Copyright (C) 2002-2005 The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Dave Peterson . + * 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 "common.h" +#include "layout-text.h" +#include "layout.h" +#include "cmos_lowlevel.h" +#include "reg_expr.h" + +static void process_layout_file(FILE * f); +static void skip_past_start(FILE * f); +static int process_entry(FILE * f, int skip_add); +static int process_enum(FILE * f, int skip_add); +static void process_checksum_info(FILE * f); +static void skip_remaining_lines(FILE * f); +static void create_entry(cmos_entry_t * cmos_entry, + const char start_bit_str[], const char length_str[], + const char config_str[], const char config_id_str[], + const char name_str[]); +static void try_add_layout_file_entry(const cmos_entry_t * cmos_entry); +static void create_enum(cmos_enum_t * cmos_enum, const char id_str[], + const char value_str[], const char text_str[]); +static void try_add_cmos_enum(const cmos_enum_t * cmos_enum); +static void set_checksum_info(const char start_str[], const char end_str[], + const char index_str[]); +static char cmos_entry_char_value(cmos_entry_config_t config); +static int get_layout_file_line(FILE * f, char line[], int line_buf_size); +static unsigned string_to_unsigned(const char str[], const char str_name[]); +static unsigned long string_to_unsigned_long(const char str[], + const char str_name[]); +static unsigned long do_string_to_unsigned_long(const char str[], + const char str_name[], + const char blurb[]); + +/* matches either a blank line or a comment line */ +static const char blank_or_comment_regex[] = + /* a blank line */ + "(^[[:space:]]+$)" "|" /* or ... */ + /* a line consisting of: optional whitespace followed by */ + "(^[[:space:]]*" + /* a '#' character and optionally, additional characters */ + "#.*$)"; + +static regex_t blank_or_comment_expr; + +/* matches the line in a CMOS layout file indicating the start of the + * "entries" section. + */ +static const char start_entries_regex[] = + /* optional whitespace */ + "^[[:space:]]*" + /* followed by "entries" */ + "entries" + /* followed by optional whitespace */ + "[[:space:]]*$"; + +static regex_t start_entries_expr; + +/* matches the line in a CMOS layout file indicating the start of the + * "enumerations" section + */ +static const char start_enums_regex[] = + /* optional whitespace */ + "^[[:space:]]*" + /* followed by "enumerations" */ + "enumerations" + /* followed by optional whitespace */ + "[[:space:]]*$"; + +static regex_t start_enums_expr; + +/* matches the line in a CMOS layout file indicating the start of the + * "checksums" section + */ +static const char start_checksums_regex[] = + /* optional whitespace */ + "^[[:space:]]*" + /* followed by "checksums" */ + "checksums" + /* followed by optional whitespace */ + "[[:space:]]*$"; + +static regex_t start_checksums_expr; + +/* matches a line in a CMOS layout file specifying a CMOS entry */ +static const char entries_line_regex[] = + /* optional whitespace */ + "^[[:space:]]*" + /* followed by a chunk of nonwhitespace for start-bit field */ + "([^[:space:]]+)" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for length field */ + "([^[:space:]]+)" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for config field */ + "([^[:space:]]+)" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for config-ID field */ + "([^[:space:]]+)" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for name field */ + "([^[:space:]]+)" + /* followed by optional whitespace */ + "[[:space:]]*$"; + +static regex_t entries_line_expr; + +/* matches a line in a CMOS layout file specifying a CMOS enumeration */ +static const char enums_line_regex[] = + /* optional whitespace */ + "^[[:space:]]*" + /* followed by a chunk of nonwhitespace for ID field */ + "([^[:space:]]+)" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for value field */ + "([^[:space:]]+)" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for text field */ + "([^[:space:]]+)" + /* followed by optional whitespace */ + "[[:space:]]*$"; + +static regex_t enums_line_expr; + +/* matches the line in a CMOS layout file specifying CMOS checksum + * information + */ +static const char checksum_line_regex[] = + /* optional whitespace */ + "^[[:space:]]*" + /* followed by "checksum" */ + "checksum" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for first bit of summed area */ + "([^[:space:]]+)" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for last bit of summed area */ + "([^[:space:]]+)" + /* followed by one or more whitespace characters */ + "[[:space:]]+" + /* followed by a chunk of nonwhitespace for checksum location bit */ + "([^[:space:]]+)" + /* followed by optional whitespace */ + "[[:space:]]*$"; + +static regex_t checksum_line_expr; + +static const int LINE_BUF_SIZE = 256; + +static int line_num; + +static const char *layout_filename = NULL; + +/**************************************************************************** + * set_layout_filename + * + * Set the name of the file we will obtain CMOS layout information from. + ****************************************************************************/ +void set_layout_filename(const char filename[]) +{ + layout_filename = filename; +} + +/**************************************************************************** + * get_layout_from_file + * + * Read CMOS layout information from the user-specified CMOS layout file. + ****************************************************************************/ +void get_layout_from_file(void) +{ + FILE *f; + + assert(layout_filename != NULL); + + if ((f = fopen(layout_filename, "r")) == NULL) { + fprintf(stderr, + "%s: Can not open CMOS layout file %s for reading: " + "%s\n", prog_name, layout_filename, strerror(errno)); + exit(1); + } + + process_layout_file(f); + fclose(f); +} + +/**************************************************************************** + * write_cmos_layout + * + * Write CMOS layout information to file 'f'. The output is written in the + * format that CMOS layout files adhere to. + ****************************************************************************/ +void write_cmos_layout(FILE * f) +{ + const cmos_entry_t *cmos_entry; + const cmos_enum_t *cmos_enum; + cmos_checksum_layout_t layout; + + fprintf(f, "entries\n"); + + for (cmos_entry = first_cmos_entry(); + cmos_entry != NULL; cmos_entry = next_cmos_entry(cmos_entry)) + fprintf(f, "%u %u %c %u %s\n", cmos_entry->bit, + cmos_entry->length, + cmos_entry_char_value(cmos_entry->config), + cmos_entry->config_id, cmos_entry->name); + + fprintf(f, "\nenumerations\n"); + + for (cmos_enum = first_cmos_enum(); + cmos_enum != NULL; cmos_enum = next_cmos_enum(cmos_enum)) + fprintf(f, "%u %llu %s\n", cmos_enum->config_id, + cmos_enum->value, cmos_enum->text); + + layout.summed_area_start = cmos_checksum_start; + layout.summed_area_end = cmos_checksum_end; + layout.checksum_at = cmos_checksum_index; + checksum_layout_to_bits(&layout); + fprintf(f, "\nchecksums\nchecksum %u %u %u\n", layout.summed_area_start, + layout.summed_area_end, layout.checksum_at); +} + +/**************************************************************************** + * process_layout_file + * + * Read CMOS layout information from file 'f' and add it to our internal + * repository. + ****************************************************************************/ +static void process_layout_file(FILE * f) +{ + compile_reg_expr(REG_EXTENDED | REG_NEWLINE, blank_or_comment_regex, &blank_or_comment_expr); + compile_reg_expr(REG_EXTENDED | REG_NEWLINE, start_entries_regex, &start_entries_expr); + compile_reg_expr(REG_EXTENDED | REG_NEWLINE, entries_line_regex, &entries_line_expr); + compile_reg_expr(REG_EXTENDED | REG_NEWLINE, start_enums_regex, &start_enums_expr); + compile_reg_expr(REG_EXTENDED | REG_NEWLINE, enums_line_regex, &enums_line_expr); + compile_reg_expr(REG_EXTENDED | REG_NEWLINE, start_checksums_regex, &start_checksums_expr); + compile_reg_expr(REG_EXTENDED | REG_NEWLINE, checksum_line_regex, &checksum_line_expr); + line_num = 1; + skip_past_start(f); + + /* Skip past all entries. We will process these later when we + * make a second pass through the file. + */ + while (!process_entry(f, 1)) ; + + /* Process all enums, adding them to our internal repository as + * we go. */ + + if (process_enum(f, 0)) { + fprintf(stderr, "%s: Error: CMOS layout file contains no " + "enumerations.\n", prog_name); + exit(1); + } + + while (!process_enum(f, 0)) ; + + /* Go back to start of file. */ + line_num = 1; + fseek(f, 0, SEEK_SET); + + skip_past_start(f); + + /* Process all entries, adding them to the repository as we go. + * We must add the entries after the enums, even though they + * appear in the layout file before the enums. This is because + * the entries are sanity checked against the enums as they are + * added. + */ + + if (process_entry(f, 0)) { + fprintf(stderr, + "%s: Error: CMOS layout file contains no entries.\n", + prog_name); + exit(1); + } + + while (!process_entry(f, 0)) ; + + /* Skip past all enums. They have already been processed. */ + while (!process_enum(f, 1)) ; + + /* Process CMOS checksum info. */ + process_checksum_info(f); + + /* See if there are any lines left to process. If so, verify + * that they are all either blank lines or comments. + */ + skip_remaining_lines(f); + + regfree(&blank_or_comment_expr); + regfree(&start_entries_expr); + regfree(&entries_line_expr); + regfree(&start_enums_expr); + regfree(&enums_line_expr); + regfree(&start_checksums_expr); + regfree(&checksum_line_expr); +} + +/**************************************************************************** + * skip_past_start + * + * Skip past the line that marks the start of the "entries" section. + ****************************************************************************/ +static void skip_past_start(FILE * f) +{ + char line[LINE_BUF_SIZE]; + + for (;; line_num++) { + if (get_layout_file_line(f, line, LINE_BUF_SIZE)) { + fprintf(stderr, + "%s: \"entries\" line not found in CMOS layout file.\n", + prog_name); + exit(1); + } + + if (!regexec(&blank_or_comment_expr, line, 0, NULL, 0)) + continue; + + if (!regexec(&start_entries_expr, line, 0, NULL, 0)) + break; + + fprintf(stderr, + "%s: Syntax error on line %d of CMOS layout file. " + "\"entries\" line expected.\n", prog_name, line_num); + exit(1); + } + + line_num++; +} + +/**************************************************************************** + * process_entry + * + * Get an entry from "entries" section of file and add it to our repository + * of layout information. Return 0 if an entry was found and processed. + * Return 1 if there are no more entries. + ****************************************************************************/ +static int process_entry(FILE * f, int skip_add) +{ + static const size_t N_MATCHES = 6; + char line[LINE_BUF_SIZE]; + regmatch_t match[N_MATCHES]; + cmos_entry_t cmos_entry; + int result; + + result = 1; + + for (;; line_num++) { + if (get_layout_file_line(f, line, LINE_BUF_SIZE)) { + fprintf(stderr, + "%s: Unexpected end of CMOS layout file reached while " + "reading \"entries\" section.\n", prog_name); + exit(1); + } + + if (!regexec(&blank_or_comment_expr, line, 0, NULL, 0)) + continue; + + if (regexec(&entries_line_expr, line, N_MATCHES, match, 0)) { + if (regexec(&start_enums_expr, line, 0, NULL, 0)) { + fprintf(stderr, + "%s: Syntax error on line %d of CMOS layout " + "file.\n", prog_name, line_num); + exit(1); + } + + break; /* start of enumerations reached: no more entries */ + } + + result = 0; /* next layout entry found */ + + if (skip_add) + break; + + line[match[1].rm_eo] = '\0'; + line[match[2].rm_eo] = '\0'; + line[match[3].rm_eo] = '\0'; + line[match[4].rm_eo] = '\0'; + line[match[5].rm_eo] = '\0'; + create_entry(&cmos_entry, &line[match[1].rm_so], + &line[match[2].rm_so], &line[match[3].rm_so], + &line[match[4].rm_so], &line[match[5].rm_so]); + try_add_layout_file_entry(&cmos_entry); + break; + } + + line_num++; + return result; +} + +/**************************************************************************** + * process_enum + * + * Get an enuneration from "enumerations" section of file and add it to our + * repository of layout information. Return 0 if an enumeration was found + * and processed. Return 1 if there are no more enumerations. + ****************************************************************************/ +static int process_enum(FILE * f, int skip_add) +{ + static const size_t N_MATCHES = 4; + char line[LINE_BUF_SIZE]; + regmatch_t match[N_MATCHES]; + cmos_enum_t cmos_enum; + int result; + + result = 1; + + for (;; line_num++) { + if (get_layout_file_line(f, line, LINE_BUF_SIZE)) { + fprintf(stderr, + "%s: Unexpected end of CMOS layout file reached while " + "reading \"enumerations\" section.\n", + prog_name); + exit(1); + } + + if (!regexec(&blank_or_comment_expr, line, 0, NULL, 0)) + continue; + + if (regexec(&enums_line_expr, line, N_MATCHES, match, 0)) { + if (regexec(&start_checksums_expr, line, 0, NULL, 0)) { + fprintf(stderr, + "%s: Syntax error on line %d of CMOS layout " + "file.\n", prog_name, line_num); + exit(1); + } + + break; /* start of checksums reached: no more enumerations */ + } + + result = 0; /* next layout enumeration found */ + + if (skip_add) + break; + + line[match[1].rm_eo] = '\0'; + line[match[2].rm_eo] = '\0'; + line[match[3].rm_eo] = '\0'; + create_enum(&cmos_enum, &line[match[1].rm_so], + &line[match[2].rm_so], &line[match[3].rm_so]); + try_add_cmos_enum(&cmos_enum); + break; + } + + line_num++; + return result; +} + +/**************************************************************************** + * process_checksum_info + * + * Get line conatining CMOS checksum information. + ****************************************************************************/ +static void process_checksum_info(FILE * f) +{ + static const size_t N_MATCHES = 4; + char line[LINE_BUF_SIZE]; + regmatch_t match[N_MATCHES]; + + for (;; line_num++) { + if (get_layout_file_line(f, line, LINE_BUF_SIZE)) { + fprintf(stderr, + "%s: Unexpected end of CMOS layout file reached while " + "reading \"checksums\" section.\n", prog_name); + exit(1); + } + + if (!regexec(&blank_or_comment_expr, line, 0, NULL, 0)) + continue; + + if (regexec(&checksum_line_expr, line, N_MATCHES, match, 0)) { + fprintf(stderr, + "%s: Syntax error on line %d of CMOS layout " + "file. \"checksum\" line expected.\n", + prog_name, line_num); + exit(1); + } + + /* checksum line found */ + line[match[1].rm_eo] = '\0'; + line[match[2].rm_eo] = '\0'; + line[match[3].rm_eo] = '\0'; + set_checksum_info(&line[match[1].rm_so], &line[match[2].rm_so], + &line[match[3].rm_so]); + break; + } +} + +/**************************************************************************** + * skip_remaining_lines + * + * Get any remaining lines of unprocessed input. Complain if we find a line + * that contains anything other than comments and whitespace. + ****************************************************************************/ +static void skip_remaining_lines(FILE * f) +{ + char line[LINE_BUF_SIZE]; + + for (line_num++; + get_layout_file_line(f, line, LINE_BUF_SIZE) == OK; line_num++) { + if (regexec(&blank_or_comment_expr, line, 0, NULL, 0)) { + fprintf(stderr, + "%s: Syntax error on line %d of CMOS layout file: " + "Only comments and/or whitespace allowed after " + "\"checksum\" line.\n", prog_name, line_num); + exit(1); + } + } +} + +/**************************************************************************** + * create_entry + * + * Create a CMOS entry structure representing the given information. Perform + * sanity checking on input parameters. + ****************************************************************************/ +static void create_entry(cmos_entry_t * cmos_entry, + const char start_bit_str[], const char length_str[], + const char config_str[], const char config_id_str[], + const char name_str[]) +{ + cmos_entry->bit = string_to_unsigned(start_bit_str, "start-bit"); + cmos_entry->length = string_to_unsigned(length_str, "length"); + + if (config_str[1] != '\0') + goto bad_config_str; + + switch (config_str[0]) { + case 'e': + cmos_entry->config = CMOS_ENTRY_ENUM; + break; + + case 'h': + cmos_entry->config = CMOS_ENTRY_HEX; + break; + + case 's': + cmos_entry->config = CMOS_ENTRY_STRING; + break; + + case 'r': + cmos_entry->config = CMOS_ENTRY_RESERVED; + break; + + default: + goto bad_config_str; + } + + cmos_entry->config_id = string_to_unsigned(config_id_str, "config-ID"); + + if (strlen(name_str) >= CMOS_MAX_NAME_LENGTH) { + fprintf(stderr, + "%s: Error on line %d of CMOS layout file: name too " + "long (max length is %d).\n", prog_name, line_num, + CMOS_MAX_NAME_LENGTH - 1); + exit(1); + } + + strcpy(cmos_entry->name, name_str); + return; + + bad_config_str: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file: 'e', 'h', or " + "'r' expected for config value.\n", prog_name, line_num); + exit(1); +} + +/**************************************************************************** + * try_add_layout_file_entry + * + * Attempt to add the given CMOS entry to our internal repository. Exit with + * an error message on failure. + ****************************************************************************/ +static void try_add_layout_file_entry(const 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: Error on line %d of CMOS layout file. Area " + "covered by entry %s is out of range.\n", prog_name, + line_num, cmos_entry->name); + break; + + case CMOS_AREA_TOO_WIDE: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. Area " + "covered by entry %s is too wide.\n", prog_name, + line_num, cmos_entry->name); + break; + + case LAYOUT_ENTRY_OVERLAP: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. Layouts " + "overlap for entries %s and %s.\n", prog_name, line_num, + 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); +} + +/**************************************************************************** + * create_enum + * + * Create a CMOS enumeration structure representing the given information. + * Perform sanity checking on input parameters. + ****************************************************************************/ +static void create_enum(cmos_enum_t * cmos_enum, const char id_str[], + const char value_str[], const char text_str[]) +{ + cmos_enum->config_id = string_to_unsigned(id_str, "ID"); + cmos_enum->value = string_to_unsigned_long(value_str, "value"); + + if (strlen(text_str) >= CMOS_MAX_TEXT_LENGTH) { + fprintf(stderr, + "%s: Error on line %d of CMOS layout file: text too " + "long (max length is %d).\n", prog_name, line_num, + CMOS_MAX_TEXT_LENGTH - 1); + exit(1); + } + + strcpy(cmos_enum->text, text_str); +} + +/**************************************************************************** + * try_add_cmos_enum + * + * Attempt to add the given CMOS enum to our internal repository. Exit with + * an error message on failure. + ****************************************************************************/ +static void try_add_cmos_enum(const cmos_enum_t * cmos_enum) +{ + switch (add_cmos_enum(cmos_enum)) { + case OK: + return; + + case LAYOUT_DUPLICATE_ENUM: + fprintf(stderr, "%s: Error on line %d of CMOS layout file: " + "Enumeration found with duplicate ID/value combination.\n", + prog_name, line_num); + break; + + default: + BUG(); + } + + exit(1); +} + +/**************************************************************************** + * set_checksum_info + * + * Set CMOS checksum information according to input parameters and perform + * sanity checking on input parameters. + ****************************************************************************/ +static void set_checksum_info(const char start_str[], const char end_str[], + const char index_str[]) +{ + cmos_checksum_layout_t layout; + + /* These are bit positions that we want to convert to byte positions. */ + layout.summed_area_start = + string_to_unsigned(start_str, "CMOS checksummed area start"); + layout.summed_area_end = + string_to_unsigned(end_str, "CMOS checksummed area end"); + layout.checksum_at = + string_to_unsigned(index_str, "CMOS checksum location"); + + switch (checksum_layout_to_bytes(&layout)) { + case OK: + break; + + case LAYOUT_SUMMED_AREA_START_NOT_ALIGNED: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. CMOS " + "checksummed area start is not byte-aligned.\n", + prog_name, line_num); + goto fail; + + case LAYOUT_SUMMED_AREA_END_NOT_ALIGNED: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. CMOS " + "checksummed area end is not byte-aligned.\n", + prog_name, line_num); + goto fail; + + case LAYOUT_CHECKSUM_LOCATION_NOT_ALIGNED: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. CMOS " + "checksum location is not byte-aligned.\n", prog_name, + line_num); + goto fail; + + case LAYOUT_INVALID_SUMMED_AREA: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. CMOS " + "checksummed area end must be greater than CMOS checksummed " + "area start.\n", prog_name, line_num); + goto fail; + + case LAYOUT_CHECKSUM_OVERLAPS_SUMMED_AREA: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. CMOS " + "checksum overlaps checksummed area.\n", prog_name, + line_num); + goto fail; + + case LAYOUT_SUMMED_AREA_OUT_OF_RANGE: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. CMOS " + "checksummed area out of range.\n", prog_name, + line_num); + goto fail; + + case LAYOUT_CHECKSUM_LOCATION_OUT_OF_RANGE: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file. CMOS " + "checksum location out of range.\n", prog_name, + line_num); + goto fail; + + default: + BUG(); + } + + cmos_checksum_start = layout.summed_area_start; + cmos_checksum_end = layout.summed_area_end; + cmos_checksum_index = layout.checksum_at; + return; + + fail: + exit(1); +} + +/**************************************************************************** + * cmos_entry_char_value + * + * Return the character representation of 'config'. + ****************************************************************************/ +static char cmos_entry_char_value(cmos_entry_config_t config) +{ + switch (config) { + case CMOS_ENTRY_ENUM: + return 'e'; + + case CMOS_ENTRY_HEX: + return 'h'; + + case CMOS_ENTRY_RESERVED: + return 'r'; + + case CMOS_ENTRY_STRING: + return 's'; + + default: + BUG(); + } + + return 0; /* not reached */ +} + +/**************************************************************************** + * get_layout_file_line + * + * Get a line of input from file 'f'. Store result in 'line' which is an + * array of 'line_buf_size' bytes. Return OK on success or an error code on + * failure. + ****************************************************************************/ +static int get_layout_file_line(FILE * f, char line[], int line_buf_size) +{ + switch (get_line_from_file(f, line, line_buf_size)) { + case OK: + return OK; + + case LINE_EOF: + return LINE_EOF; + + case LINE_TOO_LONG: + fprintf(stderr, + "%s: Error on line %d of CMOS layout file: Maximum " + "line length exceeded. Max is %d characters.\n", + prog_name, line_num, line_buf_size - 2); + break; + } + + exit(1); + return 1; /* keep compiler happy */ +} + +/**************************************************************************** + * string_to_unsigned + * + * Convert the string 'str' to an unsigned and return the result. + ****************************************************************************/ +static unsigned string_to_unsigned(const char str[], const char str_name[]) +{ + unsigned long n; + unsigned z; + + n = do_string_to_unsigned_long(str, str_name, ""); + + if ((z = (unsigned)n) != n) { + /* This could happen on an architecture in which + * sizeof(unsigned) < sizeof(unsigned long). + */ + fprintf(stderr, + "%s: Error on line %d of CMOS layout file: %s value is " + "out of range.\n", prog_name, line_num, str_name); + exit(1); + } + + return z; +} + +/**************************************************************************** + * string_to_unsigned_long + * + * Convert the string 'str' to an unsigned long and return the result. + ****************************************************************************/ +static unsigned long string_to_unsigned_long(const char str[], + const char str_name[]) +{ + return do_string_to_unsigned_long(str, str_name, " long"); +} + +/**************************************************************************** + * do_string_to_unsigned_long + * + * Convert the string 'str' to an unsigned long and return the result. Exit + * with an appropriate error message on failure. + ****************************************************************************/ +static unsigned long do_string_to_unsigned_long(const char str[], + const char str_name[], + const char blurb[]) +{ + unsigned long n; + char *p; + + n = strtoul(str, &p, 0); + + if (*p != '\0') { + fprintf(stderr, + "%s: Error on line %d of CMOS layout file: %s is not a " + "valid unsigned%s integer.\n", prog_name, line_num, + str_name, blurb); + exit(1); + } + + return n; +} diff --git a/util/nvramtool/accessors/layout-text.h b/util/nvramtool/accessors/layout-text.h new file mode 100644 index 0000000000..21997e9a46 --- /dev/null +++ b/util/nvramtool/accessors/layout-text.h @@ -0,0 +1,41 @@ +/*****************************************************************************\ + * layout_file.h + ***************************************************************************** + * Copyright (C) 2002-2005 The Regents of the University of California. + * Produced at the Lawrence Livermore National Laboratory. + * Written by Dave Peterson . + * 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. +\*****************************************************************************/ + +#ifndef LAYOUT_FILE_H +#define LAYOUT_FILE_H + +#include "common.h" +#include "coreboot_tables.h" + +void set_layout_filename(const char filename[]); +void get_layout_from_file(void); +void write_cmos_layout(FILE * f); + +#endif /* LAYOUT_FILE_H */ diff --git a/util/nvramtool/cli/nvramtool.c b/util/nvramtool/cli/nvramtool.c index e3e7e8875a..23de093fa0 100644 --- a/util/nvramtool/cli/nvramtool.c +++ b/util/nvramtool/cli/nvramtool.c @@ -36,7 +36,7 @@ #include "opts.h" #include "lbtable.h" #include "layout.h" -#include "layout_file.h" +#include "accessors/layout-text.h" #include "input_file.h" #include "cmos_ops.h" #include "cmos_lowlevel.h" diff --git a/util/nvramtool/layout_file.c b/util/nvramtool/layout_file.c deleted file mode 100644 index 535554f704..0000000000 --- a/util/nvramtool/layout_file.c +++ /dev/null @@ -1,900 +0,0 @@ -/*****************************************************************************\ - * layout_file.c - ***************************************************************************** - * Copyright (C) 2002-2005 The Regents of the University of California. - * Produced at the Lawrence Livermore National Laboratory. - * Written by Dave Peterson . - * 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 "common.h" -#include "layout_file.h" -#include "layout.h" -#include "cmos_lowlevel.h" -#include "reg_expr.h" - -static void process_layout_file(FILE * f); -static void skip_past_start(FILE * f); -static int process_entry(FILE * f, int skip_add); -static int process_enum(FILE * f, int skip_add); -static void process_checksum_info(FILE * f); -static void skip_remaining_lines(FILE * f); -static void create_entry(cmos_entry_t * cmos_entry, - const char start_bit_str[], const char length_str[], - const char config_str[], const char config_id_str[], - const char name_str[]); -static void try_add_layout_file_entry(const cmos_entry_t * cmos_entry); -static void create_enum(cmos_enum_t * cmos_enum, const char id_str[], - const char value_str[], const char text_str[]); -static void try_add_cmos_enum(const cmos_enum_t * cmos_enum); -static void set_checksum_info(const char start_str[], const char end_str[], - const char index_str[]); -static char cmos_entry_char_value(cmos_entry_config_t config); -static int get_layout_file_line(FILE * f, char line[], int line_buf_size); -static unsigned string_to_unsigned(const char str[], const char str_name[]); -static unsigned long string_to_unsigned_long(const char str[], - const char str_name[]); -static unsigned long do_string_to_unsigned_long(const char str[], - const char str_name[], - const char blurb[]); - -/* matches either a blank line or a comment line */ -static const char blank_or_comment_regex[] = - /* a blank line */ - "(^[[:space:]]+$)" "|" /* or ... */ - /* a line consisting of: optional whitespace followed by */ - "(^[[:space:]]*" - /* a '#' character and optionally, additional characters */ - "#.*$)"; - -static regex_t blank_or_comment_expr; - -/* matches the line in a CMOS layout file indicating the start of the - * "entries" section. - */ -static const char start_entries_regex[] = - /* optional whitespace */ - "^[[:space:]]*" - /* followed by "entries" */ - "entries" - /* followed by optional whitespace */ - "[[:space:]]*$"; - -static regex_t start_entries_expr; - -/* matches the line in a CMOS layout file indicating the start of the - * "enumerations" section - */ -static const char start_enums_regex[] = - /* optional whitespace */ - "^[[:space:]]*" - /* followed by "enumerations" */ - "enumerations" - /* followed by optional whitespace */ - "[[:space:]]*$"; - -static regex_t start_enums_expr; - -/* matches the line in a CMOS layout file indicating the start of the - * "checksums" section - */ -static const char start_checksums_regex[] = - /* optional whitespace */ - "^[[:space:]]*" - /* followed by "checksums" */ - "checksums" - /* followed by optional whitespace */ - "[[:space:]]*$"; - -static regex_t start_checksums_expr; - -/* matches a line in a CMOS layout file specifying a CMOS entry */ -static const char entries_line_regex[] = - /* optional whitespace */ - "^[[:space:]]*" - /* followed by a chunk of nonwhitespace for start-bit field */ - "([^[:space:]]+)" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for length field */ - "([^[:space:]]+)" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for config field */ - "([^[:space:]]+)" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for config-ID field */ - "([^[:space:]]+)" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for name field */ - "([^[:space:]]+)" - /* followed by optional whitespace */ - "[[:space:]]*$"; - -static regex_t entries_line_expr; - -/* matches a line in a CMOS layout file specifying a CMOS enumeration */ -static const char enums_line_regex[] = - /* optional whitespace */ - "^[[:space:]]*" - /* followed by a chunk of nonwhitespace for ID field */ - "([^[:space:]]+)" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for value field */ - "([^[:space:]]+)" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for text field */ - "([^[:space:]]+)" - /* followed by optional whitespace */ - "[[:space:]]*$"; - -static regex_t enums_line_expr; - -/* matches the line in a CMOS layout file specifying CMOS checksum - * information - */ -static const char checksum_line_regex[] = - /* optional whitespace */ - "^[[:space:]]*" - /* followed by "checksum" */ - "checksum" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for first bit of summed area */ - "([^[:space:]]+)" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for last bit of summed area */ - "([^[:space:]]+)" - /* followed by one or more whitespace characters */ - "[[:space:]]+" - /* followed by a chunk of nonwhitespace for checksum location bit */ - "([^[:space:]]+)" - /* followed by optional whitespace */ - "[[:space:]]*$"; - -static regex_t checksum_line_expr; - -static const int LINE_BUF_SIZE = 256; - -static int line_num; - -static const char *layout_filename = NULL; - -/**************************************************************************** - * set_layout_filename - * - * Set the name of the file we will obtain CMOS layout information from. - ****************************************************************************/ -void set_layout_filename(const char filename[]) -{ - layout_filename = filename; -} - -/**************************************************************************** - * get_layout_from_file - * - * Read CMOS layout information from the user-specified CMOS layout file. - ****************************************************************************/ -void get_layout_from_file(void) -{ - FILE *f; - - assert(layout_filename != NULL); - - if ((f = fopen(layout_filename, "r")) == NULL) { - fprintf(stderr, - "%s: Can not open CMOS layout file %s for reading: " - "%s\n", prog_name, layout_filename, strerror(errno)); - exit(1); - } - - process_layout_file(f); - fclose(f); -} - -/**************************************************************************** - * write_cmos_layout - * - * Write CMOS layout information to file 'f'. The output is written in the - * format that CMOS layout files adhere to. - ****************************************************************************/ -void write_cmos_layout(FILE * f) -{ - const cmos_entry_t *cmos_entry; - const cmos_enum_t *cmos_enum; - cmos_checksum_layout_t layout; - - fprintf(f, "entries\n"); - - for (cmos_entry = first_cmos_entry(); - cmos_entry != NULL; cmos_entry = next_cmos_entry(cmos_entry)) - fprintf(f, "%u %u %c %u %s\n", cmos_entry->bit, - cmos_entry->length, - cmos_entry_char_value(cmos_entry->config), - cmos_entry->config_id, cmos_entry->name); - - fprintf(f, "\nenumerations\n"); - - for (cmos_enum = first_cmos_enum(); - cmos_enum != NULL; cmos_enum = next_cmos_enum(cmos_enum)) - fprintf(f, "%u %llu %s\n", cmos_enum->config_id, - cmos_enum->value, cmos_enum->text); - - layout.summed_area_start = cmos_checksum_start; - layout.summed_area_end = cmos_checksum_end; - layout.checksum_at = cmos_checksum_index; - checksum_layout_to_bits(&layout); - fprintf(f, "\nchecksums\nchecksum %u %u %u\n", layout.summed_area_start, - layout.summed_area_end, layout.checksum_at); -} - -/**************************************************************************** - * process_layout_file - * - * Read CMOS layout information from file 'f' and add it to our internal - * repository. - ****************************************************************************/ -static void process_layout_file(FILE * f) -{ - compile_reg_expr(REG_EXTENDED | REG_NEWLINE, blank_or_comment_regex, &blank_or_comment_expr); - compile_reg_expr(REG_EXTENDED | REG_NEWLINE, start_entries_regex, &start_entries_expr); - compile_reg_expr(REG_EXTENDED | REG_NEWLINE, entries_line_regex, &entries_line_expr); - compile_reg_expr(REG_EXTENDED | REG_NEWLINE, start_enums_regex, &start_enums_expr); - compile_reg_expr(REG_EXTENDED | REG_NEWLINE, enums_line_regex, &enums_line_expr); - compile_reg_expr(REG_EXTENDED | REG_NEWLINE, start_checksums_regex, &start_checksums_expr); - compile_reg_expr(REG_EXTENDED | REG_NEWLINE, checksum_line_regex, &checksum_line_expr); - line_num = 1; - skip_past_start(f); - - /* Skip past all entries. We will process these later when we - * make a second pass through the file. - */ - while (!process_entry(f, 1)) ; - - /* Process all enums, adding them to our internal repository as - * we go. */ - - if (process_enum(f, 0)) { - fprintf(stderr, "%s: Error: CMOS layout file contains no " - "enumerations.\n", prog_name); - exit(1); - } - - while (!process_enum(f, 0)) ; - - /* Go back to start of file. */ - line_num = 1; - fseek(f, 0, SEEK_SET); - - skip_past_start(f); - - /* Process all entries, adding them to the repository as we go. - * We must add the entries after the enums, even though they - * appear in the layout file before the enums. This is because - * the entries are sanity checked against the enums as they are - * added. - */ - - if (process_entry(f, 0)) { - fprintf(stderr, - "%s: Error: CMOS layout file contains no entries.\n", - prog_name); - exit(1); - } - - while (!process_entry(f, 0)) ; - - /* Skip past all enums. They have already been processed. */ - while (!process_enum(f, 1)) ; - - /* Process CMOS checksum info. */ - process_checksum_info(f); - - /* See if there are any lines left to process. If so, verify - * that they are all either blank lines or comments. - */ - skip_remaining_lines(f); - - regfree(&blank_or_comment_expr); - regfree(&start_entries_expr); - regfree(&entries_line_expr); - regfree(&start_enums_expr); - regfree(&enums_line_expr); - regfree(&start_checksums_expr); - regfree(&checksum_line_expr); -} - -/**************************************************************************** - * skip_past_start - * - * Skip past the line that marks the start of the "entries" section. - ****************************************************************************/ -static void skip_past_start(FILE * f) -{ - char line[LINE_BUF_SIZE]; - - for (;; line_num++) { - if (get_layout_file_line(f, line, LINE_BUF_SIZE)) { - fprintf(stderr, - "%s: \"entries\" line not found in CMOS layout file.\n", - prog_name); - exit(1); - } - - if (!regexec(&blank_or_comment_expr, line, 0, NULL, 0)) - continue; - - if (!regexec(&start_entries_expr, line, 0, NULL, 0)) - break; - - fprintf(stderr, - "%s: Syntax error on line %d of CMOS layout file. " - "\"entries\" line expected.\n", prog_name, line_num); - exit(1); - } - - line_num++; -} - -/**************************************************************************** - * process_entry - * - * Get an entry from "entries" section of file and add it to our repository - * of layout information. Return 0 if an entry was found and processed. - * Return 1 if there are no more entries. - ****************************************************************************/ -static int process_entry(FILE * f, int skip_add) -{ - static const size_t N_MATCHES = 6; - char line[LINE_BUF_SIZE]; - regmatch_t match[N_MATCHES]; - cmos_entry_t cmos_entry; - int result; - - result = 1; - - for (;; line_num++) { - if (get_layout_file_line(f, line, LINE_BUF_SIZE)) { - fprintf(stderr, - "%s: Unexpected end of CMOS layout file reached while " - "reading \"entries\" section.\n", prog_name); - exit(1); - } - - if (!regexec(&blank_or_comment_expr, line, 0, NULL, 0)) - continue; - - if (regexec(&entries_line_expr, line, N_MATCHES, match, 0)) { - if (regexec(&start_enums_expr, line, 0, NULL, 0)) { - fprintf(stderr, - "%s: Syntax error on line %d of CMOS layout " - "file.\n", prog_name, line_num); - exit(1); - } - - break; /* start of enumerations reached: no more entries */ - } - - result = 0; /* next layout entry found */ - - if (skip_add) - break; - - line[match[1].rm_eo] = '\0'; - line[match[2].rm_eo] = '\0'; - line[match[3].rm_eo] = '\0'; - line[match[4].rm_eo] = '\0'; - line[match[5].rm_eo] = '\0'; - create_entry(&cmos_entry, &line[match[1].rm_so], - &line[match[2].rm_so], &line[match[3].rm_so], - &line[match[4].rm_so], &line[match[5].rm_so]); - try_add_layout_file_entry(&cmos_entry); - break; - } - - line_num++; - return result; -} - -/**************************************************************************** - * process_enum - * - * Get an enuneration from "enumerations" section of file and add it to our - * repository of layout information. Return 0 if an enumeration was found - * and processed. Return 1 if there are no more enumerations. - ****************************************************************************/ -static int process_enum(FILE * f, int skip_add) -{ - static const size_t N_MATCHES = 4; - char line[LINE_BUF_SIZE]; - regmatch_t match[N_MATCHES]; - cmos_enum_t cmos_enum; - int result; - - result = 1; - - for (;; line_num++) { - if (get_layout_file_line(f, line, LINE_BUF_SIZE)) { - fprintf(stderr, - "%s: Unexpected end of CMOS layout file reached while " - "reading \"enumerations\" section.\n", - prog_name); - exit(1); - } - - if (!regexec(&blank_or_comment_expr, line, 0, NULL, 0)) - continue; - - if (regexec(&enums_line_expr, line, N_MATCHES, match, 0)) { - if (regexec(&start_checksums_expr, line, 0, NULL, 0)) { - fprintf(stderr, - "%s: Syntax error on line %d of CMOS layout " - "file.\n", prog_name, line_num); - exit(1); - } - - break; /* start of checksums reached: no more enumerations */ - } - - result = 0; /* next layout enumeration found */ - - if (skip_add) - break; - - line[match[1].rm_eo] = '\0'; - line[match[2].rm_eo] = '\0'; - line[match[3].rm_eo] = '\0'; - create_enum(&cmos_enum, &line[match[1].rm_so], - &line[match[2].rm_so], &line[match[3].rm_so]); - try_add_cmos_enum(&cmos_enum); - break; - } - - line_num++; - return result; -} - -/**************************************************************************** - * process_checksum_info - * - * Get line conatining CMOS checksum information. - ****************************************************************************/ -static void process_checksum_info(FILE * f) -{ - static const size_t N_MATCHES = 4; - char line[LINE_BUF_SIZE]; - regmatch_t match[N_MATCHES]; - - for (;; line_num++) { - if (get_layout_file_line(f, line, LINE_BUF_SIZE)) { - fprintf(stderr, - "%s: Unexpected end of CMOS layout file reached while " - "reading \"checksums\" section.\n", prog_name); - exit(1); - } - - if (!regexec(&blank_or_comment_expr, line, 0, NULL, 0)) - continue; - - if (regexec(&checksum_line_expr, line, N_MATCHES, match, 0)) { - fprintf(stderr, - "%s: Syntax error on line %d of CMOS layout " - "file. \"checksum\" line expected.\n", - prog_name, line_num); - exit(1); - } - - /* checksum line found */ - line[match[1].rm_eo] = '\0'; - line[match[2].rm_eo] = '\0'; - line[match[3].rm_eo] = '\0'; - set_checksum_info(&line[match[1].rm_so], &line[match[2].rm_so], - &line[match[3].rm_so]); - break; - } -} - -/**************************************************************************** - * skip_remaining_lines - * - * Get any remaining lines of unprocessed input. Complain if we find a line - * that contains anything other than comments and whitespace. - ****************************************************************************/ -static void skip_remaining_lines(FILE * f) -{ - char line[LINE_BUF_SIZE]; - - for (line_num++; - get_layout_file_line(f, line, LINE_BUF_SIZE) == OK; line_num++) { - if (regexec(&blank_or_comment_expr, line, 0, NULL, 0)) { - fprintf(stderr, - "%s: Syntax error on line %d of CMOS layout file: " - "Only comments and/or whitespace allowed after " - "\"checksum\" line.\n", prog_name, line_num); - exit(1); - } - } -} - -/**************************************************************************** - * create_entry - * - * Create a CMOS entry structure representing the given information. Perform - * sanity checking on input parameters. - ****************************************************************************/ -static void create_entry(cmos_entry_t * cmos_entry, - const char start_bit_str[], const char length_str[], - const char config_str[], const char config_id_str[], - const char name_str[]) -{ - cmos_entry->bit = string_to_unsigned(start_bit_str, "start-bit"); - cmos_entry->length = string_to_unsigned(length_str, "length"); - - if (config_str[1] != '\0') - goto bad_config_str; - - switch (config_str[0]) { - case 'e': - cmos_entry->config = CMOS_ENTRY_ENUM; - break; - - case 'h': - cmos_entry->config = CMOS_ENTRY_HEX; - break; - - case 's': - cmos_entry->config = CMOS_ENTRY_STRING; - break; - - case 'r': - cmos_entry->config = CMOS_ENTRY_RESERVED; - break; - - default: - goto bad_config_str; - } - - cmos_entry->config_id = string_to_unsigned(config_id_str, "config-ID"); - - if (strlen(name_str) >= CMOS_MAX_NAME_LENGTH) { - fprintf(stderr, - "%s: Error on line %d of CMOS layout file: name too " - "long (max length is %d).\n", prog_name, line_num, - CMOS_MAX_NAME_LENGTH - 1); - exit(1); - } - - strcpy(cmos_entry->name, name_str); - return; - - bad_config_str: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file: 'e', 'h', or " - "'r' expected for config value.\n", prog_name, line_num); - exit(1); -} - -/**************************************************************************** - * try_add_layout_file_entry - * - * Attempt to add the given CMOS entry to our internal repository. Exit with - * an error message on failure. - ****************************************************************************/ -static void try_add_layout_file_entry(const 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: Error on line %d of CMOS layout file. Area " - "covered by entry %s is out of range.\n", prog_name, - line_num, cmos_entry->name); - break; - - case CMOS_AREA_TOO_WIDE: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. Area " - "covered by entry %s is too wide.\n", prog_name, - line_num, cmos_entry->name); - break; - - case LAYOUT_ENTRY_OVERLAP: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. Layouts " - "overlap for entries %s and %s.\n", prog_name, line_num, - 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); -} - -/**************************************************************************** - * create_enum - * - * Create a CMOS enumeration structure representing the given information. - * Perform sanity checking on input parameters. - ****************************************************************************/ -static void create_enum(cmos_enum_t * cmos_enum, const char id_str[], - const char value_str[], const char text_str[]) -{ - cmos_enum->config_id = string_to_unsigned(id_str, "ID"); - cmos_enum->value = string_to_unsigned_long(value_str, "value"); - - if (strlen(text_str) >= CMOS_MAX_TEXT_LENGTH) { - fprintf(stderr, - "%s: Error on line %d of CMOS layout file: text too " - "long (max length is %d).\n", prog_name, line_num, - CMOS_MAX_TEXT_LENGTH - 1); - exit(1); - } - - strcpy(cmos_enum->text, text_str); -} - -/**************************************************************************** - * try_add_cmos_enum - * - * Attempt to add the given CMOS enum to our internal repository. Exit with - * an error message on failure. - ****************************************************************************/ -static void try_add_cmos_enum(const cmos_enum_t * cmos_enum) -{ - switch (add_cmos_enum(cmos_enum)) { - case OK: - return; - - case LAYOUT_DUPLICATE_ENUM: - fprintf(stderr, "%s: Error on line %d of CMOS layout file: " - "Enumeration found with duplicate ID/value combination.\n", - prog_name, line_num); - break; - - default: - BUG(); - } - - exit(1); -} - -/**************************************************************************** - * set_checksum_info - * - * Set CMOS checksum information according to input parameters and perform - * sanity checking on input parameters. - ****************************************************************************/ -static void set_checksum_info(const char start_str[], const char end_str[], - const char index_str[]) -{ - cmos_checksum_layout_t layout; - - /* These are bit positions that we want to convert to byte positions. */ - layout.summed_area_start = - string_to_unsigned(start_str, "CMOS checksummed area start"); - layout.summed_area_end = - string_to_unsigned(end_str, "CMOS checksummed area end"); - layout.checksum_at = - string_to_unsigned(index_str, "CMOS checksum location"); - - switch (checksum_layout_to_bytes(&layout)) { - case OK: - break; - - case LAYOUT_SUMMED_AREA_START_NOT_ALIGNED: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. CMOS " - "checksummed area start is not byte-aligned.\n", - prog_name, line_num); - goto fail; - - case LAYOUT_SUMMED_AREA_END_NOT_ALIGNED: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. CMOS " - "checksummed area end is not byte-aligned.\n", - prog_name, line_num); - goto fail; - - case LAYOUT_CHECKSUM_LOCATION_NOT_ALIGNED: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. CMOS " - "checksum location is not byte-aligned.\n", prog_name, - line_num); - goto fail; - - case LAYOUT_INVALID_SUMMED_AREA: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. CMOS " - "checksummed area end must be greater than CMOS checksummed " - "area start.\n", prog_name, line_num); - goto fail; - - case LAYOUT_CHECKSUM_OVERLAPS_SUMMED_AREA: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. CMOS " - "checksum overlaps checksummed area.\n", prog_name, - line_num); - goto fail; - - case LAYOUT_SUMMED_AREA_OUT_OF_RANGE: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. CMOS " - "checksummed area out of range.\n", prog_name, - line_num); - goto fail; - - case LAYOUT_CHECKSUM_LOCATION_OUT_OF_RANGE: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file. CMOS " - "checksum location out of range.\n", prog_name, - line_num); - goto fail; - - default: - BUG(); - } - - cmos_checksum_start = layout.summed_area_start; - cmos_checksum_end = layout.summed_area_end; - cmos_checksum_index = layout.checksum_at; - return; - - fail: - exit(1); -} - -/**************************************************************************** - * cmos_entry_char_value - * - * Return the character representation of 'config'. - ****************************************************************************/ -static char cmos_entry_char_value(cmos_entry_config_t config) -{ - switch (config) { - case CMOS_ENTRY_ENUM: - return 'e'; - - case CMOS_ENTRY_HEX: - return 'h'; - - case CMOS_ENTRY_RESERVED: - return 'r'; - - case CMOS_ENTRY_STRING: - return 's'; - - default: - BUG(); - } - - return 0; /* not reached */ -} - -/**************************************************************************** - * get_layout_file_line - * - * Get a line of input from file 'f'. Store result in 'line' which is an - * array of 'line_buf_size' bytes. Return OK on success or an error code on - * failure. - ****************************************************************************/ -static int get_layout_file_line(FILE * f, char line[], int line_buf_size) -{ - switch (get_line_from_file(f, line, line_buf_size)) { - case OK: - return OK; - - case LINE_EOF: - return LINE_EOF; - - case LINE_TOO_LONG: - fprintf(stderr, - "%s: Error on line %d of CMOS layout file: Maximum " - "line length exceeded. Max is %d characters.\n", - prog_name, line_num, line_buf_size - 2); - break; - } - - exit(1); - return 1; /* keep compiler happy */ -} - -/**************************************************************************** - * string_to_unsigned - * - * Convert the string 'str' to an unsigned and return the result. - ****************************************************************************/ -static unsigned string_to_unsigned(const char str[], const char str_name[]) -{ - unsigned long n; - unsigned z; - - n = do_string_to_unsigned_long(str, str_name, ""); - - if ((z = (unsigned)n) != n) { - /* This could happen on an architecture in which - * sizeof(unsigned) < sizeof(unsigned long). - */ - fprintf(stderr, - "%s: Error on line %d of CMOS layout file: %s value is " - "out of range.\n", prog_name, line_num, str_name); - exit(1); - } - - return z; -} - -/**************************************************************************** - * string_to_unsigned_long - * - * Convert the string 'str' to an unsigned long and return the result. - ****************************************************************************/ -static unsigned long string_to_unsigned_long(const char str[], - const char str_name[]) -{ - return do_string_to_unsigned_long(str, str_name, " long"); -} - -/**************************************************************************** - * do_string_to_unsigned_long - * - * Convert the string 'str' to an unsigned long and return the result. Exit - * with an appropriate error message on failure. - ****************************************************************************/ -static unsigned long do_string_to_unsigned_long(const char str[], - const char str_name[], - const char blurb[]) -{ - unsigned long n; - char *p; - - n = strtoul(str, &p, 0); - - if (*p != '\0') { - fprintf(stderr, - "%s: Error on line %d of CMOS layout file: %s is not a " - "valid unsigned%s integer.\n", prog_name, line_num, - str_name, blurb); - exit(1); - } - - return n; -} diff --git a/util/nvramtool/layout_file.h b/util/nvramtool/layout_file.h deleted file mode 100644 index 21997e9a46..0000000000 --- a/util/nvramtool/layout_file.h +++ /dev/null @@ -1,41 +0,0 @@ -/*****************************************************************************\ - * layout_file.h - ***************************************************************************** - * Copyright (C) 2002-2005 The Regents of the University of California. - * Produced at the Lawrence Livermore National Laboratory. - * Written by Dave Peterson . - * 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. -\*****************************************************************************/ - -#ifndef LAYOUT_FILE_H -#define LAYOUT_FILE_H - -#include "common.h" -#include "coreboot_tables.h" - -void set_layout_filename(const char filename[]); -void get_layout_from_file(void); -void write_cmos_layout(FILE * f); - -#endif /* LAYOUT_FILE_H */ -- cgit v1.2.3