Move the parser for cmos.layout text files to accessors
authorPatrick Georgi <patrick.georgi@secunet.com>
Fri, 28 Jan 2011 07:50:33 +0000 (07:50 +0000)
committerPatrick Georgi <patrick.georgi@coresystems.de>
Fri, 28 Jan 2011 07:50:33 +0000 (07:50 +0000)
Signed-off-by: Patrick Georgi <patrick.georgi@secunet.com>
Acked-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6312 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

util/nvramtool/Makefile
util/nvramtool/accessors/layout-text.c [new file with mode: 0644]
util/nvramtool/accessors/layout-text.h [new file with mode: 0644]
util/nvramtool/cli/nvramtool.c
util/nvramtool/layout_file.c [deleted file]
util/nvramtool/layout_file.h [deleted file]

index 673b394455c48c0dd40d374def151106e741c375..ff9072e2b64093f854e58a9a2cb7fe47cab196ac 100644 (file)
@@ -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 (file)
index 0000000..5f7cade
--- /dev/null
@@ -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 <dsp@llnl.gov> <dave_peterson@pobox.com>.
+ *  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 (file)
index 0000000..21997e9
--- /dev/null
@@ -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 <dsp@llnl.gov> <dave_peterson@pobox.com>.
+ *  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 */
index e3e7e8875ad0cf097d7060cf229b98d2be5a99b7..23de093fa086c739c0b32fe22351dc1a9f8b2bab 100644 (file)
@@ -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 (file)
index 535554f..0000000
+++ /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 <dsp@llnl.gov> <dave_peterson@pobox.com>.
- *  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 (file)
index 21997e9..0000000
+++ /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 <dsp@llnl.gov> <dave_peterson@pobox.com>.
- *  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 */