/**************************************************************************** * op_read_cmos_dump * * -B INPUT_FILE * * Read binary data from a file and write the data to CMOS memory. ****************************************************************************/ static void op_read_cmos_dump(void) { unsigned char data[CMOS_SIZE]; size_t nr_bytes; FILE *f; if ((f = fopen(nvramtool_op.param, "rb")) == NULL) { fprintf(stderr, "%s: Can not open file %s for reading: %s\n", prog_name, nvramtool_op.param, strerror(errno)); exit(1); } if ((nr_bytes = fread(data, 1, CMOS_SIZE, f)) != CMOS_SIZE) { fprintf(stderr, "%s: Error: Only able to read %d bytes of CMOS data " "from file %s. CMOS data is unchanged.\n", prog_name, (int)nr_bytes, nvramtool_op.param); exit(1); } fclose(f); set_iopl(3); cmos_write_all(data); set_iopl(0); }
/**************************************************************************** * op_show_cmos_hex_dump * * -x * * Write a hex dump of CMOS memory to standard output. ****************************************************************************/ static void op_show_cmos_hex_dump(void) { unsigned char data[CMOS_SIZE]; set_iopl(3); cmos_read_all(data); set_iopl(0); hexdump(data, CMOS_SIZE, 0, stdout, &cmos_dump_format); }
/**************************************************************************** * op_cmos_checksum * * -c [VALUE] * * If VALUE is present, set coreboot CMOS checksum to VALUE. Else show * checksum value. ****************************************************************************/ static void op_cmos_checksum(void) { uint16_t checksum; get_cmos_layout(); if (nvramtool_op.param == NULL) { set_iopl(3); checksum = cmos_checksum_read(); set_iopl(0); printf("0x%x\n", checksum); } else { checksum = convert_checksum_value(nvramtool_op.param); set_iopl(3); cmos_checksum_write(checksum); set_iopl(0); } }
/**************************************************************************** * do_cmos_writes * * 'list' is a linked list of pending CMOS write operations that have passed * all sanity checks. Perform all write operations, destroying the list as * we go. ****************************************************************************/ void do_cmos_writes(cmos_write_t * list) { cmos_write_t *item; set_iopl(3); while (list != NULL) { cmos_entry_t e; item = list; e.bit = item->bit; e.length = item->length; e.config = item->config; list = item->next; cmos_write(&e, item->value); free(item); } cmos_checksum_write(cmos_checksum_compute()); set_iopl(0); }
/**************************************************************************** * op_write_cmos_dump * * -b OUTPUT_FILE * * Write the contents of CMOS memory to a binary file. ****************************************************************************/ static void op_write_cmos_dump(void) { unsigned char data[CMOS_SIZE]; FILE *f; if ((f = fopen(nvramtool_op.param, "wb")) == NULL) { fprintf(stderr, "%s: Can not open file %s for writing: %s\n", prog_name, nvramtool_op.param, strerror(errno)); exit(1); } set_iopl(3); cmos_read_all(data); set_iopl(0); if (fwrite(data, 1, CMOS_SIZE, f) != CMOS_SIZE) { fprintf(stderr, "%s: Error writing CMOS data to file %s: %s\n", prog_name, nvramtool_op.param, strerror(errno)); exit(1); } fclose(f); }
void set_iopl(void) { #ifdef OPENBSD if (i386_iopl(3) == -1) { #else if (iopl(3) == -1) { #endif perror(NULL); exit(1); } } int main(int argc, char **argv) { int i; char *infilename, *outfilename; infilename = outfilename = NULL; for (i = 1; i < argc; ++i) { if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) usage(); else if (!strcmp(argv[i], "-d")) ++dflag; else if (infilename == NULL) infilename = argv[i]; else if (outfilename == NULL) outfilename = argv[i]; else usage(); } if (!infilename) usage(); if (!outfilename) set_iopl(); pcspkr_play(infilename, outfilename); exit(0); }
/**************************************************************************** * list_cmos_entry * * Attempt to list the CMOS entry represented by 'e'. 'show_name' is a * boolean value indicating whether the parameter name should be displayed * along with its value. On success, return OK. On error, print an error * message and return 1. ****************************************************************************/ static int list_cmos_entry(const cmos_entry_t * e, int show_name) { const cmos_enum_t *p; unsigned long long value; char *w; /* sanity check CMOS entry */ switch (prepare_cmos_read(e)) { case OK: break; case CMOS_OP_RESERVED: BUG(); case CMOS_AREA_OUT_OF_RANGE: fprintf(stderr, "%s: Can not read coreboot parameter %s because " "layout info specifies out of range CMOS area.\n", prog_name, e->name); return 1; case CMOS_AREA_OVERLAPS_RTC: fprintf(stderr, "%s: Can not read coreboot parameter %s because " "layout info specifies CMOS area that overlaps realtime " "clock area.\n", prog_name, e->name); return 1; case CMOS_AREA_TOO_WIDE: fprintf(stderr, "%s: Can not read coreboot parameter %s because " "layout info specifies CMOS area that is too wide.\n", prog_name, e->name); return 1; default: fprintf(stderr, "%s: Unknown error encountered while attempting to " "read coreboot parameter %s\n", prog_name, e->name); return 1; } /* read the value from CMOS */ set_iopl(3); value = cmos_read(e); set_iopl(0); /* display the value */ switch (e->config) { case CMOS_ENTRY_ENUM: if ((p = find_cmos_enum(e->config_id, value)) == NULL) { if (show_name) printf("# Bad value -> %s = 0x%llx\n", e->name, value); else printf("Bad value -> 0x%llx\n", value); } else { if (show_name) printf("%s = %s\n", e->name, p->text); else printf("%s\n", p->text); } break; case CMOS_ENTRY_HEX: if (show_name) printf("%s = 0x%llx\n", e->name, value); else printf("0x%llx\n", value); break; case CMOS_ENTRY_STRING: w = (char *)(unsigned long)value; while (*w) { if(!isprint((int)(unsigned char)*w)) { if (show_name) printf("# Bad value -> %s\n", e->name); else printf("Bad value\n"); break; } w++; } if (!*w) { if (show_name) printf("%s = %s\n", e->name, (char *)(unsigned long)value); else printf("%s\n", (char *)(unsigned long)value); } free((void *)(unsigned long)value); break; case CMOS_ENTRY_RESERVED: default: BUG(); } return OK; }
/**************************************************************************** * set_one_param * * Set the CMOS parameter given by 'name' to 'value'. The 'name' parameter * is case-sensitive. If we are setting an enum parameter, then 'value' is * interpreted as a case-sensitive string that must match the option name * exactly. If we are setting a 'hex' parameter, then 'value' is treated as * a string representation of an unsigned integer that may be specified in * decimal, hex, or octal. ****************************************************************************/ static void set_one_param(const char name[], const char value[]) { const cmos_entry_t *e; unsigned long long n; if (is_checksum_name(name) || (e = find_cmos_entry(name)) == NULL) { fprintf(stderr, "%s: CMOS parameter %s not found.", prog_name, name); exit(1); } switch (prepare_cmos_write(e, value, &n)) { case OK: break; case CMOS_OP_BAD_ENUM_VALUE: fprintf(stderr, "%s: Bad value for parameter %s.", prog_name, name); goto fail; case CMOS_OP_NEGATIVE_INT: fprintf(stderr, "%s: This program does not support assignment of negative " "numbers to coreboot parameters.", prog_name); goto fail; case CMOS_OP_INVALID_INT: fprintf(stderr, "%s: %s is not a valid integer.", prog_name, value); goto fail; case CMOS_OP_RESERVED: fprintf(stderr, "%s: Can not modify reserved coreboot parameter %s.", prog_name, name); goto fail; case CMOS_OP_VALUE_TOO_WIDE: fprintf(stderr, "%s: Can not write value %s to CMOS parameter %s that is " "only %d bits wide.", prog_name, value, name, e->length); goto fail; case CMOS_OP_NO_MATCHING_ENUM: fprintf(stderr, "%s: coreboot parameter %s has no matching enums.", prog_name, name); goto fail; case CMOS_AREA_OUT_OF_RANGE: fprintf(stderr, "%s: The CMOS area specified by the layout info for " "coreboot parameter %s is out of range.", prog_name, name); goto fail; case CMOS_AREA_OVERLAPS_RTC: fprintf(stderr, "%s: The CMOS area specified by the layout info for " "coreboot parameter %s overlaps the realtime clock area.", prog_name, name); goto fail; case CMOS_AREA_TOO_WIDE: fprintf(stderr, "%s: The CMOS area specified by the layout info for " "coreboot parameter %s is too wide.", prog_name, name); goto fail; default: fprintf(stderr, "%s: Unknown error encountered while attempting to modify " "coreboot parameter %s.", prog_name, name); goto fail; } /* write the value to nonvolatile RAM */ set_iopl(3); cmos_write(e, n); cmos_checksum_write(cmos_checksum_compute()); set_iopl(0); return; fail: fprintf(stderr, " CMOS write not performed.\n"); exit(1); }