/**************************************************************************** * 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); }
void write_cmos_layout_header(const char *header_filename) { FILE *fp; const cmos_entry_t *cmos_entry; cmos_checksum_layout_t layout; if ((fp = fopen(header_filename, "w+")) == NULL) { fprintf(stderr, "%s: Can't open file %s for writing: %s\n", prog_name, header_filename, strerror(errno)); exit(1); } fprintf(fp, "/**\n * This is an autogenerated file. Do not EDIT.\n" " * All changes made to this file will be lost.\n" " * See mainboard's cmos.layout file.\n */\n" "\n#ifndef __OPTION_TABLE_H\n" "#define __OPTION_TABLE_H\n\n"); for (cmos_entry = first_cmos_entry(); cmos_entry != NULL; cmos_entry = next_cmos_entry(cmos_entry)) { if (!is_ident((char *)cmos_entry->name)) { fprintf(stderr, "Error - Name %s is an invalid identifier\n", cmos_entry->name); fclose(fp); exit(1); } fprintf(fp, "#define CMOS_VSTART_%s\t%d\n", cmos_entry->name, cmos_entry->bit); fprintf(fp, "#define CMOS_VLEN_%s\t%d\n", cmos_entry->name, cmos_entry->length); } 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(fp, "\n#define LB_CKS_RANGE_START %d\n", layout.summed_area_start / 8); fprintf(fp, "#define LB_CKS_RANGE_END %d\n", layout.summed_area_end / 8); fprintf(fp, "#define LB_CKS_LOC %d\n", layout.checksum_at / 8); fprintf(fp, "\n#endif /* __OPTION_TABLE_H */\n"); fclose(fp); }
/**************************************************************************** * list_all_params * * Attempt to list all CMOS parameters. Return 1 if error was encountered. * Else return OK. ****************************************************************************/ static int list_all_params(void) { const cmos_entry_t *e; int result; result = OK; for (e = first_cmos_entry(); e != NULL; e = next_cmos_entry(e)) { if ((e->config == CMOS_ENTRY_RESERVED) || is_checksum_name(e->name)) continue; if (list_cmos_entry(e, TRUE)) result = 1; } return result; }
int write_cmos_layout_bin(FILE *f) { const cmos_entry_t *cmos_entry; const cmos_enum_t *cmos_enum; cmos_checksum_layout_t layout; struct cmos_option_table table; struct cmos_entries entry; struct cmos_enums cenum; struct cmos_checksum csum; size_t sum = 0; int len; for (cmos_entry = first_cmos_entry(); cmos_entry != NULL; cmos_entry = next_cmos_entry(cmos_entry)) { if (cmos_entry == first_cmos_entry()) { sum += sizeof(table); table.header_length = sizeof(table); table.tag = LB_TAG_CMOS_OPTION_TABLE; table.size = 0; if (fwrite((char *)&table, sizeof(table), 1, f) != 1) { perror("Error writing image file"); goto err; } } memset(&entry, 0, sizeof(entry)); entry.tag = LB_TAG_OPTION; entry.config = cmos_entry->config; entry.config_id = (uint32_t)cmos_entry->config_id; entry.bit = cmos_entry->bit; entry.length = cmos_entry->length; if (!is_ident((char *)cmos_entry->name)) { fprintf(stderr, "Error - Name %s is an invalid identifier\n", cmos_entry->name); goto err; } memcpy(entry.name, cmos_entry->name, strlen(cmos_entry->name)); entry.name[strlen(cmos_entry->name)] = '\0'; len = strlen(cmos_entry->name) + 1; if (len % 4) ROUNDUP4(len); entry.size = sizeof(entry) - CMOS_MAX_NAME_LENGTH + len; sum += entry.size; if (fwrite((char *)&entry, entry.size, 1, f) != 1) { perror("Error writing image file"); goto err; } } for (cmos_enum = first_cmos_enum(); cmos_enum != NULL; cmos_enum = next_cmos_enum(cmos_enum)) { memset(&cenum, 0, sizeof(cenum)); cenum.tag = LB_TAG_OPTION_ENUM; memcpy(cenum.text, cmos_enum->text, strlen(cmos_enum->text)); cenum.text[strlen(cmos_enum->text)] = '\0'; len = strlen((char *)cenum.text) + 1; if (len % 4) ROUNDUP4(len); cenum.config_id = cmos_enum->config_id; cenum.value = cmos_enum->value; cenum.size = sizeof(cenum) - CMOS_MAX_TEXT_LENGTH + len; sum += cenum.size; if (fwrite((char *)&cenum, cenum.size, 1, f) != 1) { perror("Error writing image file"); goto err; } } 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); csum.tag = LB_TAG_OPTION_CHECKSUM; csum.size = sizeof(csum); csum.range_start = layout.summed_area_start; csum.range_end = layout.summed_area_end; csum.location = layout.checksum_at; csum.type = CHECKSUM_PCBIOS; sum += csum.size; if (fwrite((char *)&csum, csum.size, 1, f) != 1) { perror("Error writing image file"); goto err; } if (fseek(f, 0, SEEK_SET) != 0) { perror("Error while seeking"); goto err; } table.size = sum; if (fwrite((char *)&table, sizeof(table), 1, f) != 1) { perror("Error writing image file"); goto err; } return sum; err: fclose(f); exit(1); }
int main() { int ch, done; ITEM *cur; /* coreboot data structures */ lib_get_sysinfo(); struct cb_cmos_option_table *opttbl = get_system_option_table(); if (opttbl == NULL) { printf("Could not find coreboot option table\n"); halt(); } /* display initialization */ initscr(); keypad(stdscr, TRUE); cbreak(); noecho(); start_color(); leaveok(stdscr, TRUE); curs_set(1); erase(); box(stdscr, 0, 0); mvaddstr(0, 2, "coreboot configuration utility"); /* prep CMOS layout into libcurses data structures */ /* determine number of options, and maximum option name length */ int numopts=0; int maxlength=0; struct cb_cmos_entries *option = first_cmos_entry(opttbl); while (option) { if ((option->config != 'r') && (strcmp("check_sum", option->name) != 0)) { maxlength = max(maxlength, strlen(option->name)); numopts++; } option = next_cmos_entry(option); } if (numopts == 0) { printf("NO CMOS OPTIONS FOUND. EXITING!!!"); return 1; } FIELD **fields = malloc(sizeof(FIELD*)*(2*numopts+1)); int i; /* walk over options, fetch details */ option = first_cmos_entry(opttbl); for (i=0;i<numopts;i++) { while ((option->config == 'r') || (strcmp("check_sum", option->name) == 0)) { option = next_cmos_entry(option); } fields[2*i] = new_field(1, strlen(option->name), i*2, 1, 0, 0); set_field_buffer(fields[2*i], 0, option->name); field_opts_off(fields[2*i], O_ACTIVE); fields[2*i+1] = new_field(1, 40, i*2, maxlength+2, 0, 0); char *buf = NULL; int fail = get_option_as_string(use_nvram, opttbl, &buf, option->name); switch (option->config) { case 'h': { set_field_type(fields[2*i+1], TYPE_INTEGER, 0, 0, (1<<option->length)-1); field_opts_on(fields[2*i+1], O_BLANK); break; } case 's': { set_max_field(fields[2*i+1], option->length/8); field_opts_off(fields[2*i+1], O_STATIC); break; } case 'e': { int numvals = 0; struct cb_cmos_enums *cmos_enum = first_cmos_enum_of_id(opttbl, option->config_id); /* if invalid data in CMOS, set buf to first enum */ if (fail && cmos_enum) { buf = cmos_enum->text; } while (cmos_enum) { numvals++; cmos_enum = next_cmos_enum_of_id(cmos_enum, option->config_id); } char **values = malloc(sizeof(char*)*numvals + 1); int cnt = 0; cmos_enum = first_cmos_enum_of_id(opttbl, option->config_id); while (cmos_enum) { values[cnt] = cmos_enum->text; cnt++; cmos_enum = next_cmos_enum_of_id(cmos_enum, option->config_id); } values[cnt] = NULL; field_opts_off(fields[2*i+1], O_EDIT); set_field_type(fields[2*i+1], TYPE_ENUM, values, 1, 1); free(values); // copied by set_field_type break; } default: break; } if (buf) set_field_buffer(fields[2*i+1], 0, buf); #if HOSTED // underline is non-trivial on VGA text set_field_back(fields[2*i+1], A_UNDERLINE); #endif field_opts_off(fields[2*i+1], O_BLANK | O_AUTOSKIP | O_NULLOK); option = next_cmos_entry(option); } fields[2*numopts]=NULL; FORM *form = new_form(fields); int numlines = min(numopts*2, 16); WINDOW *w = newwin(numlines+2, 70, 2, 1); WINDOW *inner_w = newpad(numopts*2, 68); box(w, 0, 0); mvwaddstr(w, 0, 2, "Press F1 when done"); set_form_win(form, w); set_form_sub(form, inner_w); post_form(form); done = 0; while(!done) { ch=getch(); if (ch == ERR) continue; switch (ch) { case KEY_DOWN: form_driver(form, REQ_NEXT_FIELD); break; case KEY_UP: form_driver(form, REQ_PREV_FIELD); break; case KEY_LEFT: if (field_type(current_field(form)) == TYPE_ENUM) { form_driver(form, REQ_PREV_CHOICE); } else { form_driver(form, REQ_LEFT_CHAR); } break; case KEY_RIGHT: if (field_type(current_field(form)) == TYPE_ENUM) { form_driver(form, REQ_NEXT_CHOICE); } else { form_driver(form, REQ_RIGHT_CHAR); } break; case KEY_BACKSPACE: case '\b': form_driver(form, REQ_DEL_PREV); break; case KEY_DC: form_driver(form, REQ_DEL_CHAR); break; case KEY_F(1): done=1; break; default: form_driver(form, ch); break; } render_form(form); } for (i = 0; i < numopts; i++) { char *name = field_buffer(fields[2*i], 0); char *value = field_buffer(fields[2*i+1], 0); char *ptr; for (ptr = value + strlen (value) - 1; ptr >= value && *ptr == ' '; ptr--); ptr[1] = '\0'; set_option_from_string(use_nvram, opttbl, value, name); } unpost_form(form); free_form(form); touchwin(stdscr); refresh(); endwin(); /* TODO: reboot */ halt(); }