/**************************************************************************** * parse_assignment * * Parse the string 'arg' (which supposedly represents an assignment) into a * NAME and a VALUE. If 'arg' does not conform to the proper assignment * syntax, exit with a usage message. Otherwise, on return, 'arg' is broken * into substrings representing NAME and VALUE, and *name and *value are set * to point to these two substrings. ****************************************************************************/ static void parse_assignment(char arg[], const char **name, const char **value) { static const size_t N_MATCHES = 4; regmatch_t match[N_MATCHES]; regex_t assignment; compile_reg_expr(REG_EXTENDED | REG_NEWLINE, assignment_regex, &assignment); /* Does 'arg' conform to proper assignment syntax? If not, exit with a * usage message. */ if (regexec(&assignment, arg, N_MATCHES, match, 0)) usage(stderr); /* Ok, we found a valid assignment. Break it into two strings * representing NAME and VALUE. */ arg[match[1].rm_eo] = '\0'; arg[match[2].rm_eo] = '\0'; *name = &arg[match[1].rm_so]; *value = &arg[match[2].rm_so]; regfree(&assignment); }
/**************************************************************************** * process_input_file * * Read the contents of file 'f' and return a pointer to a list of pending * write operations. Perform sanity checking on all write operations and * exit with an error message if there is a problem. ****************************************************************************/ cmos_write_t *process_input_file(FILE * f) { static const int LINE_BUF_SIZE = 256; static const size_t N_MATCHES = 4; char line[LINE_BUF_SIZE]; const char *name, *value; cmos_write_t *list, *item, **p; regex_t blank_or_comment, assignment; regmatch_t match[N_MATCHES]; const cmos_entry_t *e; list = NULL; p = &list; compile_reg_expr(REG_EXTENDED | REG_NEWLINE, blank_or_comment_regex, &blank_or_comment); compile_reg_expr(REG_EXTENDED | REG_NEWLINE, assignment_regex, &assignment); /* each iteration processes one line from input file */ for (line_num = 1; get_input_file_line(f, line, LINE_BUF_SIZE) == OK; line_num++) { /* skip comments and blank lines */ if (!regexec(&blank_or_comment, line, 0, NULL, 0)) continue; /* Is this a valid assignment line? If not, then it's a syntax * error. */ if (regexec(&assignment, line, N_MATCHES, match, 0)) { fprintf(stderr, "%s: Syntax error on line %d of input file.\n", prog_name, line_num); exit(1); } /* OK, we found an assignment. Break the line into substrings * representing the lefthand and righthand sides of the assignment. */ line[match[1].rm_eo] = '\0'; line[match[2].rm_eo] = '\0'; name = &line[match[1].rm_so]; value = &line[match[2].rm_so]; /* now look up the coreboot parameter name */ if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL) { fprintf(stderr, "%s: Error on line %d of input file: CMOS parameter " "%s not found.\n", prog_name, line_num, name); exit(1); } /* At this point, we figure out what numeric value needs to be written * to which location. At the same time, we perform sanity checking on * the write operation. */ if ((item = (cmos_write_t *) malloc(sizeof(*item))) == NULL) out_of_memory(); item->bit = e->bit; item->length = e->length; item->config = e->config; item->value = try_prepare_cmos_write(e, value); /* Append write operation to pending write list. */ item->next = NULL; *p = item; p = &item->next; } regfree(&blank_or_comment); regfree(&assignment); return list; }
/**************************************************************************** * 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); }