lbtable.c
1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <stdint.h> 4 #include <inttypes.h> 5 #include <string.h> 6 #ifndef __MINGW32__ 7 #include <sys/mman.h> 8 #endif 9 #include "common.h" 10 #include "coreboot_tables.h" 11 #include "ip_checksum.h" 12 #include "lbtable.h" 13 #include "layout.h" 14 #include "cmos_lowlevel.h" 15 #include "hexdump.h" 16 #include "cbfs.h" 17 18 typedef void (*lbtable_print_fn_t) (const struct lb_record * rec); 19 20 /* This structure represents an item in the coreboot table that may be 21 * displayed using the -l option. 22 */ 23 typedef struct { 24 uint32_t tag; 25 const char *name; 26 const char *description; 27 const char *nofound_msg; 28 lbtable_print_fn_t print_fn; 29 } lbtable_choice_t; 30 31 typedef struct { 32 unsigned long start; /* address of first byte of memory range */ 33 unsigned long end; /* address of last byte of memory range */ 34 } mem_range_t; 35 36 static const struct lb_header *lbtable_scan(unsigned long start, 37 unsigned long end, 38 int *bad_header_count, 39 int *bad_table_count); 40 static const char *lbrec_tag_to_str(uint32_t tag); 41 static void memory_print_fn(const struct lb_record *rec); 42 static void mainboard_print_fn(const struct lb_record *rec); 43 static void cmos_opt_table_print_fn(const struct lb_record *rec); 44 static void print_option_record(const struct cmos_entries *cmos_entry); 45 static void print_enum_record(const struct cmos_enums *cmos_enum); 46 static void print_defaults_record(const struct cmos_defaults *cmos_defaults); 47 static void print_unknown_record(const struct lb_record *cmos_item); 48 static void option_checksum_print_fn(const struct lb_record *rec); 49 static void string_print_fn(const struct lb_record *rec); 50 51 static const char memory_desc[] = 52 " This shows information about system memory.\n"; 53 54 static const char mainboard_desc[] = 55 " This shows information about your mainboard.\n"; 56 57 static const char version_desc[] = 58 " This shows coreboot version information.\n"; 59 60 static const char extra_version_desc[] = 61 " This shows extra coreboot version information.\n"; 62 63 static const char build_desc[] = " This shows coreboot build information.\n"; 64 65 static const char compile_time_desc[] = 66 " This shows when coreboot was compiled.\n"; 67 68 static const char compile_by_desc[] = " This shows who compiled coreboot.\n"; 69 70 static const char compile_host_desc[] = 71 " This shows the name of the machine that compiled coreboot.\n"; 72 73 static const char compile_domain_desc[] = 74 " This shows the domain name of the machine that compiled coreboot.\n"; 75 76 static const char compiler_desc[] = 77 " This shows the name of the compiler used to build coreboot.\n"; 78 79 static const char linker_desc[] = 80 " This shows the name of the linker used to build coreboot.\n"; 81 82 static const char assembler_desc[] = 83 " This shows the name of the assembler used to build coreboot.\n"; 84 85 static const char cmos_opt_table_desc[] = 86 " This does a low-level dump of the CMOS option table. The table " 87 "contains\n" 88 " information about the layout of the values that coreboot stores in\n" 89 " nonvolatile RAM.\n"; 90 91 static const char option_checksum_desc[] = 92 " This shows the location of the CMOS checksum and the area over which it " 93 "is\n" " calculated.\n"; 94 95 static const char generic_nofound_msg[] = 96 "%s: Item %s not found in coreboot table.\n"; 97 98 static const char nofound_msg_cmos_opt_table[] = 99 "%s: Item %s not found in coreboot table. Apparently, the " 100 "coreboot installed on this system was built without specifying " 101 "CONFIG_HAVE_OPTION_TABLE.\n"; 102 103 static const char nofound_msg_option_checksum[] = 104 "%s: Item %s not found in coreboot table. Apparently, you are " 105 "using coreboot v1.\n"; 106 107 int fd; 108 109 /* This is the number of items from the coreboot table that may be displayed 110 * using the -l option. 111 */ 112 #define NUM_LBTABLE_CHOICES 14 113 114 /* These represent the various items from the coreboot table that may be 115 * displayed using the -l option. 116 */ 117 static const lbtable_choice_t lbtable_choices[NUM_LBTABLE_CHOICES] = 118 { {LB_TAG_MEMORY, "memory", 119 memory_desc, generic_nofound_msg, 120 memory_print_fn}, 121 {LB_TAG_MAINBOARD, "mainboard", 122 mainboard_desc, generic_nofound_msg, 123 mainboard_print_fn}, 124 {LB_TAG_VERSION, "version", 125 version_desc, generic_nofound_msg, 126 string_print_fn}, 127 {LB_TAG_EXTRA_VERSION, "extra_version", 128 extra_version_desc, generic_nofound_msg, 129 string_print_fn}, 130 {LB_TAG_BUILD, "build", 131 build_desc, generic_nofound_msg, 132 string_print_fn}, 133 {LB_TAG_COMPILE_TIME, "compile_time", 134 compile_time_desc, generic_nofound_msg, 135 string_print_fn}, 136 {LB_TAG_COMPILE_BY, "compile_by", 137 compile_by_desc, generic_nofound_msg, 138 string_print_fn}, 139 {LB_TAG_COMPILE_HOST, "compile_host", 140 compile_host_desc, generic_nofound_msg, 141 string_print_fn}, 142 {LB_TAG_COMPILE_DOMAIN, "compile_domain", 143 compile_domain_desc, generic_nofound_msg, 144 string_print_fn}, 145 {LB_TAG_COMPILER, "compiler", 146 compiler_desc, generic_nofound_msg, 147 string_print_fn}, 148 {LB_TAG_LINKER, "linker", 149 linker_desc, generic_nofound_msg, 150 string_print_fn}, 151 {LB_TAG_ASSEMBLER, "assembler", 152 assembler_desc, generic_nofound_msg, 153 string_print_fn}, 154 {LB_TAG_CMOS_OPTION_TABLE, "cmos_opt_table", 155 cmos_opt_table_desc, nofound_msg_cmos_opt_table, 156 cmos_opt_table_print_fn}, 157 {LB_TAG_OPTION_CHECKSUM, "option_checksum", 158 option_checksum_desc, nofound_msg_option_checksum, 159 option_checksum_print_fn} 160 }; 161 162 /* The coreboot table resides in low physical memory, which we access using 163 * /dev/mem. These are ranges of physical memory that should be scanned for a 164 * coreboot table. 165 */ 166 167 #define NUM_MEM_RANGES 2 168 169 static const mem_range_t mem_ranges[NUM_MEM_RANGES] = 170 { {0x00000000, 0x00000fff}, 171 {0x000f0000, 0x000fffff} 172 }; 173 174 /* Pointer to low physical memory that we access by calling mmap() on 175 * /dev/mem. 176 */ 177 static const void *low_phys_mem; 178 /* impossible value since not page aligned: first map request will happen */ 179 static unsigned long low_phys_base = 0x1; 180 181 /* count of mapped pages */ 182 static unsigned long mapped_pages = 0; 183 184 /* Pointer to coreboot table. */ 185 static const struct lb_header *lbtable = NULL; 186 187 static const hexdump_format_t format = 188 { 12, 4, " ", " | ", " ", " | ", '.' }; 189 190 /**************************************************************************** 191 * vtophys 192 * 193 * Convert a virtual address to a physical address. 'vaddr' is a virtual 194 * address in the address space of the current process. It points to 195 * somewhere in the chunk of memory that we mapped by calling mmap() on 196 * /dev/mem. This macro converts 'vaddr' to a physical address. 197 ****************************************************************************/ 198 #define vtophys(vaddr) (((unsigned long) vaddr) - \ 199 ((unsigned long) low_phys_mem) + low_phys_base) 200 201 /**************************************************************************** 202 * phystov 203 * 204 * Convert a physical address to a virtual address. 'paddr' is a physical 205 * address. This macro converts 'paddr' to a virtual address in the address 206 * space of the current process. The virtual to physical mapping was set up 207 * by calling mmap() on /dev/mem. 208 ****************************************************************************/ 209 #define phystov(paddr) (((unsigned long) low_phys_mem) + \ 210 ((unsigned long) paddr) - low_phys_base) 211 212 /**************************************************************************** 213 * map_pages 214 * 215 * Maps just enough pages to cover base_address + length 216 * and updates affected variables 217 ****************************************************************************/ 218 static void map_pages(unsigned long base_address, unsigned long length) 219 { 220 unsigned long num_pages = (length + 221 (base_address & (getpagesize() - 1)) + 222 getpagesize() - 1) >> 12; 223 base_address &= ~(getpagesize() - 1); 224 225 /* no need to do anything */ 226 if ((low_phys_base == base_address) && (mapped_pages == num_pages)) { 227 return; 228 } 229 230 if (low_phys_mem) { 231 munmap((void *)low_phys_mem, mapped_pages << 12); 232 } 233 if ((low_phys_mem = mmap(NULL, num_pages << 12, PROT_READ, MAP_SHARED, fd, 234 (off_t) base_address)) == MAP_FAILED) { 235 fprintf(stderr, 236 "%s: Failed to mmap /dev/mem at %lx: %s\n", 237 prog_name, base_address, strerror(errno)); 238 exit(1); 239 } 240 low_phys_base = base_address; 241 } 242 243 /**************************************************************************** 244 * get_lbtable 245 * 246 * Find the coreboot table and set global variable lbtable to point to it. 247 ****************************************************************************/ 248 void get_lbtable(void) 249 { 250 int i, bad_header_count, bad_table_count, bad_headers, bad_tables; 251 252 if (lbtable != NULL) 253 return; 254 255 /* The coreboot table is located in low physical memory, which may be 256 * conveniently accessed by calling mmap() on /dev/mem. 257 */ 258 259 if ((fd = open("/dev/mem", O_RDONLY, 0)) < 0) { 260 fprintf(stderr, "%s: Can not open /dev/mem for reading: %s\n", 261 prog_name, strerror(errno)); 262 exit(1); 263 } 264 265 bad_header_count = 0; 266 bad_table_count = 0; 267 268 for (i = 0; i < NUM_MEM_RANGES; i++) { 269 lbtable = lbtable_scan(mem_ranges[i].start, mem_ranges[i].end, 270 &bad_headers, &bad_tables); 271 272 if (lbtable != NULL) 273 return; /* success: we found it! */ 274 275 bad_header_count += bad_headers; 276 bad_table_count += bad_tables; 277 } 278 279 fprintf(stderr, 280 "%s: coreboot table not found. coreboot does not appear to\n" 281 " be installed on this system. Scanning for the table " 282 "produced the\n" 283 " following results:\n\n" 284 " %d valid signatures were found with bad header " 285 "checksums.\n" 286 " %d valid headers were found with bad table " 287 "checksums.\n", prog_name, bad_header_count, bad_table_count); 288 exit(1); 289 } 290 291 /**************************************************************************** 292 * dump_lbtable 293 * 294 * Do a low-level dump of the coreboot table. 295 ****************************************************************************/ 296 void dump_lbtable(void) 297 { 298 const char *p, *data; 299 uint32_t bytes_processed; 300 const struct lb_record *lbrec; 301 302 p = ((const char *)lbtable) + lbtable->header_bytes; 303 printf("coreboot table at physical address 0x%lx:\n" 304 " signature: 0x%x (ASCII: %c%c%c%c)\n" 305 " header_bytes: 0x%x (decimal: %d)\n" 306 " header_checksum: 0x%x (decimal: %d)\n" 307 " table_bytes: 0x%x (decimal: %d)\n" 308 " table_checksum: 0x%x (decimal: %d)\n" 309 " table_entries: 0x%x (decimal: %d)\n\n", 310 vtophys(lbtable), lbtable->signature32, 311 lbtable->signature[0], lbtable->signature[1], 312 lbtable->signature[2], lbtable->signature[3], 313 lbtable->header_bytes, lbtable->header_bytes, 314 lbtable->header_checksum, lbtable->header_checksum, 315 lbtable->table_bytes, lbtable->table_bytes, 316 lbtable->table_checksum, lbtable->table_checksum, 317 lbtable->table_entries, lbtable->table_entries); 318 319 if ((lbtable->table_bytes == 0) != (lbtable->table_entries == 0)) { 320 printf 321 ("Inconsistent values for table_bytes and table_entries!!!\n" 322 "They should be either both 0 or both nonzero.\n"); 323 return; 324 } 325 326 if (lbtable->table_bytes == 0) { 327 printf("The coreboot table is empty!!!\n"); 328 return; 329 } 330 331 for (bytes_processed = 0;;) { 332 lbrec = (const struct lb_record *)&p[bytes_processed]; 333 printf(" %s record at physical address 0x%lx:\n" 334 " tag: 0x%x (decimal: %d)\n" 335 " size: 0x%x (decimal: %d)\n" 336 " data:\n", 337 lbrec_tag_to_str(lbrec->tag), vtophys(lbrec), lbrec->tag, 338 lbrec->tag, lbrec->size, lbrec->size); 339 340 data = ((const char *)lbrec) + sizeof(*lbrec); 341 hexdump(data, lbrec->size - sizeof(*lbrec), vtophys(data), 342 stdout, &format); 343 344 bytes_processed += lbrec->size; 345 346 if (bytes_processed >= lbtable->table_bytes) 347 break; 348 349 printf("\n"); 350 } 351 } 352 353 /**************************************************************************** 354 * list_lbtable_choices 355 * 356 * List names and informational blurbs for items from the coreboot table 357 * that may be displayed using the -l option. 358 ****************************************************************************/ 359 void list_lbtable_choices(void) 360 { 361 int i; 362 363 for (i = 0;;) { 364 printf("%s:\n%s", 365 lbtable_choices[i].name, lbtable_choices[i].description); 366 367 if (++i >= NUM_LBTABLE_CHOICES) 368 break; 369 370 printf("\n"); 371 } 372 } 373 374 /**************************************************************************** 375 * list_lbtable_item 376 * 377 * Show the coreboot table item specified by 'item'. 378 ****************************************************************************/ 379 void list_lbtable_item(const char item[]) 380 { 381 int i; 382 const struct lb_record *rec; 383 384 for (i = 0; i < NUM_LBTABLE_CHOICES; i++) { 385 if (strcmp(item, lbtable_choices[i].name) == 0) 386 break; 387 } 388 389 if (i == NUM_LBTABLE_CHOICES) { 390 fprintf(stderr, "%s: Invalid coreboot table item %s.\n", 391 prog_name, item); 392 exit(1); 393 } 394 395 if ((rec = find_lbrec(lbtable_choices[i].tag)) == NULL) { 396 fprintf(stderr, lbtable_choices[i].nofound_msg, prog_name, 397 lbtable_choices[i].name); 398 exit(1); 399 } 400 401 lbtable_choices[i].print_fn(rec); 402 } 403 404 /**************************************************************************** 405 * lbtable_scan 406 * 407 * Scan the chunk of memory specified by 'start' and 'end' for a coreboot 408 * table. The first 4 bytes of the table are marked by the signature 409 * { 'L', 'B', 'I', 'O' }. 'start' and 'end' indicate the addresses of the 410 * first and last bytes of the chunk of memory to be scanned. For instance, 411 * values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k 412 * chunk of memory starting at address 0x10000000. 'start' and 'end' are 413 * physical addresses. 414 * 415 * If a coreboot table is found, return a pointer to it. Otherwise return 416 * NULL. On return, *bad_header_count and *bad_table_count are set as 417 * follows: 418 * 419 * *bad_header_count: 420 * Indicates the number of times in which a valid signature was found 421 * but the header checksum was invalid. 422 * 423 * *bad_table_count: 424 * Indicates the number of times in which a header with a valid 425 * checksum was found but the table checksum was invalid. 426 ****************************************************************************/ 427 static const struct lb_header *lbtable_scan(unsigned long start, 428 unsigned long end, 429 int *bad_header_count, 430 int *bad_table_count) 431 { 432 static const char signature[4] = { 'L', 'B', 'I', 'O' }; 433 const struct lb_header *table; 434 const struct lb_forward *forward; 435 unsigned long p; 436 uint32_t sig; 437 438 assert(end >= start); 439 memcpy(&sig, signature, sizeof(sig)); 440 table = NULL; 441 *bad_header_count = 0; 442 *bad_table_count = 0; 443 444 /* Look for signature. Table is aligned on 16-byte boundary. Therefore 445 * only check every fourth 32-bit memory word. As the loop is coded below, 446 * this function will behave in a reasonable manner for ALL possible values 447 * for 'start' and 'end': even weird boundary cases like 0x00000000 and 448 * 0xffffffff on a 32-bit architecture. 449 */ 450 map_pages(start, end - start); 451 for (p = start; 452 (p <= end) && 453 (end - p >= (sizeof(uint32_t) - 1)); p += 4) { 454 if (*(uint32_t*)phystov(p) != sig) 455 continue; 456 457 /* We found a valid signature. */ 458 table = (const struct lb_header *)phystov(p); 459 460 /* validate header checksum */ 461 if (compute_ip_checksum((void *)table, sizeof(*table))) { 462 (*bad_header_count)++; 463 continue; 464 } 465 466 map_pages(p, table->table_bytes + sizeof(*table)); 467 468 table = (const struct lb_header *)phystov(p); 469 470 /* validate table checksum */ 471 if (table->table_checksum != 472 compute_ip_checksum(((char *)table) + sizeof(*table), 473 table->table_bytes)) { 474 (*bad_table_count)++; 475 continue; 476 } 477 478 /* checksums are ok: we found it! */ 479 /* But it may just be a forwarding table, so look if there's a forwarder */ 480 lbtable = table; 481 forward = (struct lb_forward *)find_lbrec(LB_TAG_FORWARD); 482 lbtable = NULL; 483 484 if (forward) { 485 uint64_t new_phys = forward->forward; 486 table = lbtable_scan(new_phys, new_phys + getpagesize(), 487 bad_header_count, bad_table_count); 488 } 489 return table; 490 } 491 492 return NULL; 493 } 494 495 /**************************************************************************** 496 * find_lbrec 497 * 498 * Find the record in the coreboot table that matches 'tag'. Return pointer 499 * to record on success or NULL if record not found. 500 ****************************************************************************/ 501 const struct lb_record *find_lbrec(uint32_t tag) 502 { 503 const char *p; 504 uint32_t bytes_processed; 505 const struct lb_record *lbrec; 506 507 p = ((const char *)lbtable) + lbtable->header_bytes; 508 509 for (bytes_processed = 0; 510 bytes_processed < lbtable->table_bytes; 511 bytes_processed += lbrec->size) { 512 lbrec = (const struct lb_record *)&p[bytes_processed]; 513 514 if (lbrec->tag == tag) 515 return lbrec; 516 } 517 518 return NULL; 519 } 520 521 /**************************************************************************** 522 * lbrec_tag_to_str 523 * 524 * Return a pointer to the string representation of the given coreboot table 525 * tag. 526 ****************************************************************************/ 527 static const char *lbrec_tag_to_str(uint32_t tag) 528 { 529 switch (tag) { 530 case LB_TAG_UNUSED: 531 return "UNUSED"; 532 533 case LB_TAG_MEMORY: 534 return "MEMORY"; 535 536 case LB_TAG_HWRPB: 537 return "HWRPB"; 538 539 case LB_TAG_MAINBOARD: 540 return "MAINBOARD"; 541 542 case LB_TAG_VERSION: 543 return "VERSION"; 544 545 case LB_TAG_EXTRA_VERSION: 546 return "EXTRA_VERSION"; 547 548 case LB_TAG_BUILD: 549 return "BUILD"; 550 551 case LB_TAG_COMPILE_TIME: 552 return "COMPILE_TIME"; 553 554 case LB_TAG_COMPILE_BY: 555 return "COMPILE_BY"; 556 557 case LB_TAG_COMPILE_HOST: 558 return "COMPILE_HOST"; 559 560 case LB_TAG_COMPILE_DOMAIN: 561 return "COMPILE_DOMAIN"; 562 563 case LB_TAG_COMPILER: 564 return "COMPILER"; 565 566 case LB_TAG_LINKER: 567 return "LINKER"; 568 569 case LB_TAG_ASSEMBLER: 570 return "ASSEMBLER"; 571 572 case LB_TAG_SERIAL: 573 return "SERIAL"; 574 575 case LB_TAG_CONSOLE: 576 return "CONSOLE"; 577 578 case LB_TAG_FORWARD: 579 return "FORWARD"; 580 581 case LB_TAG_CMOS_OPTION_TABLE: 582 return "CMOS_OPTION_TABLE"; 583 584 case LB_TAG_OPTION_CHECKSUM: 585 return "OPTION_CHECKSUM"; 586 587 default: 588 break; 589 } 590 591 return "UNKNOWN"; 592 } 593 594 /**************************************************************************** 595 * memory_print_fn 596 * 597 * Display function for 'memory' item of coreboot table. 598 ****************************************************************************/ 599 static void memory_print_fn(const struct lb_record *rec) 600 { 601 const struct lb_memory *p; 602 const char *mem_type; 603 const struct lb_memory_range *ranges; 604 uint64_t size, start, end; 605 int i, entries; 606 607 p = (const struct lb_memory *)rec; 608 entries = (p->size - sizeof(*p)) / sizeof(p->map[0]); 609 ranges = p->map; 610 611 if (entries == 0) { 612 printf("No memory ranges were found.\n"); 613 return; 614 } 615 616 for (i = 0;;) { 617 switch (ranges[i].type) { 618 case LB_MEM_RAM: 619 mem_type = "AVAILABLE"; 620 break; 621 622 case LB_MEM_RESERVED: 623 mem_type = "RESERVED"; 624 break; 625 626 case LB_MEM_TABLE: 627 mem_type = "CONFIG_TABLE"; 628 break; 629 630 default: 631 mem_type = "UNKNOWN"; 632 break; 633 } 634 635 size = ranges[i].size; 636 start = ranges[i].start; 637 end = start + size - 1; 638 printf("%s memory:\n" 639 " from physical addresses 0x%016" PRIx64 640 " to 0x%016" PRIx64 "\n size is 0x%016" PRIx64 641 " bytes (%" PRId64 " in decimal)\n", 642 mem_type, start, end, size, size); 643 644 if (++i >= entries) 645 break; 646 647 printf("\n"); 648 } 649 } 650 651 /**************************************************************************** 652 * mainboard_print_fn 653 * 654 * Display function for 'mainboard' item of coreboot table. 655 ****************************************************************************/ 656 static void mainboard_print_fn(const struct lb_record *rec) 657 { 658 const struct lb_mainboard *p; 659 660 p = (const struct lb_mainboard *)rec; 661 printf("Vendor: %s\n" 662 "Part number: %s\n", 663 &p->strings[p->vendor_idx], &p->strings[p->part_number_idx]); 664 } 665 666 /**************************************************************************** 667 * cmos_opt_table_print_fn 668 * 669 * Display function for 'cmos_opt_table' item of coreboot table. 670 ****************************************************************************/ 671 static void cmos_opt_table_print_fn(const struct lb_record *rec) 672 { 673 const struct cmos_option_table *p; 674 const struct lb_record *cmos_item; 675 uint32_t bytes_processed, bytes_for_entries; 676 const char *q; 677 678 p = (const struct cmos_option_table *)rec; 679 q = ((const char *)p) + p->header_length; 680 bytes_for_entries = p->size - p->header_length; 681 682 printf("CMOS option table at physical address 0x%lx:\n" 683 " tag: 0x%x (decimal: %d)\n" 684 " size: 0x%x (decimal: %d)\n" 685 " header_length: 0x%x (decimal: %d)\n\n", 686 vtophys(p), p->tag, p->tag, p->size, p->size, p->header_length, 687 p->header_length); 688 689 if (p->header_length > p->size) { 690 printf 691 ("Header length for CMOS option table is greater than the size " 692 "of the entire table including header!!!\n"); 693 return; 694 } 695 696 if (bytes_for_entries == 0) { 697 printf("The CMOS option table is empty!!!\n"); 698 return; 699 } 700 701 for (bytes_processed = 0;;) { 702 cmos_item = (const struct lb_record *)&q[bytes_processed]; 703 704 switch (cmos_item->tag) { 705 case LB_TAG_OPTION: 706 print_option_record((const struct cmos_entries *) 707 cmos_item); 708 break; 709 710 case LB_TAG_OPTION_ENUM: 711 print_enum_record((const struct cmos_enums *)cmos_item); 712 break; 713 714 case LB_TAG_OPTION_DEFAULTS: 715 print_defaults_record((const struct cmos_defaults *) 716 cmos_item); 717 break; 718 719 default: 720 print_unknown_record(cmos_item); 721 break; 722 } 723 724 bytes_processed += cmos_item->size; 725 726 if (bytes_processed >= bytes_for_entries) 727 break; 728 729 printf("\n"); 730 } 731 } 732 733 /**************************************************************************** 734 * print_option_record 735 * 736 * Display "option" record from CMOS option table. 737 ****************************************************************************/ 738 static void print_option_record(const struct cmos_entries *cmos_entry) 739 { 740 static const size_t S_BUFSIZE = 80; 741 char s[S_BUFSIZE]; 742 743 switch (cmos_entry->config) { 744 case 'e': 745 strcpy(s, "ENUM"); 746 break; 747 748 case 'h': 749 strcpy(s, "HEX"); 750 break; 751 752 case 'r': 753 strcpy(s, "RESERVED"); 754 break; 755 756 default: 757 snprintf(s, S_BUFSIZE, "UNKNOWN: value is 0x%x (decimal: %d)", 758 cmos_entry->config, cmos_entry->config); 759 break; 760 } 761 762 printf(" OPTION record at physical address 0x%lx:\n" 763 " tag: 0x%x (decimal: %d)\n" 764 " size: 0x%x (decimal: %d)\n" 765 " bit: 0x%x (decimal: %d)\n" 766 " length: 0x%x (decimal: %d)\n" 767 " config: %s\n" 768 " config_id: 0x%x (decimal: %d)\n" 769 " name: %s\n", 770 vtophys(cmos_entry), cmos_entry->tag, cmos_entry->tag, 771 cmos_entry->size, cmos_entry->size, cmos_entry->bit, 772 cmos_entry->bit, cmos_entry->length, cmos_entry->length, s, 773 cmos_entry->config_id, cmos_entry->config_id, cmos_entry->name); 774 } 775 776 /**************************************************************************** 777 * print_enum_record 778 * 779 * Display "enum" record from CMOS option table. 780 ****************************************************************************/ 781 static void print_enum_record(const struct cmos_enums *cmos_enum) 782 { 783 printf(" ENUM record at physical address 0x%lx:\n" 784 " tag: 0x%x (decimal: %d)\n" 785 " size: 0x%x (decimal: %d)\n" 786 " config_id: 0x%x (decimal: %d)\n" 787 " value: 0x%x (decimal: %d)\n" 788 " text: %s\n", 789 vtophys(cmos_enum), cmos_enum->tag, cmos_enum->tag, 790 cmos_enum->size, cmos_enum->size, cmos_enum->config_id, 791 cmos_enum->config_id, cmos_enum->value, cmos_enum->value, 792 cmos_enum->text); 793 } 794 795 /**************************************************************************** 796 * print_defaults_record 797 * 798 * Display "defaults" record from CMOS option table. 799 ****************************************************************************/ 800 static void print_defaults_record(const struct cmos_defaults *cmos_defaults) 801 { 802 printf(" DEFAULTS record at physical address 0x%lx:\n" 803 " tag: 0x%x (decimal: %d)\n" 804 " size: 0x%x (decimal: %d)\n" 805 " name_length: 0x%x (decimal: %d)\n" 806 " name: %s\n" 807 " default_set:\n", 808 vtophys(cmos_defaults), cmos_defaults->tag, cmos_defaults->tag, 809 cmos_defaults->size, cmos_defaults->size, 810 cmos_defaults->name_length, cmos_defaults->name_length, 811 cmos_defaults->name); 812 hexdump(cmos_defaults->default_set, CMOS_IMAGE_BUFFER_SIZE, 813 vtophys(cmos_defaults->default_set), stdout, &format); 814 } 815 816 /**************************************************************************** 817 * print_unknown_record 818 * 819 * Display record of unknown type from CMOS option table. 820 ****************************************************************************/ 821 static void print_unknown_record(const struct lb_record *cmos_item) 822 { 823 const char *data; 824 825 printf(" UNKNOWN record at physical address 0x%lx:\n" 826 " tag: 0x%x (decimal: %d)\n" 827 " size: 0x%x (decimal: %d)\n" 828 " data:\n", 829 vtophys(cmos_item), cmos_item->tag, cmos_item->tag, 830 cmos_item->size, cmos_item->size); 831 data = ((const char *)cmos_item) + sizeof(*cmos_item); 832 hexdump(data, cmos_item->size - sizeof(*cmos_item), vtophys(data), 833 stdout, &format); 834 } 835 836 /**************************************************************************** 837 * option_checksum_print_fn 838 * 839 * Display function for 'option_checksum' item of coreboot table. 840 ****************************************************************************/ 841 static void option_checksum_print_fn(const struct lb_record *rec) 842 { 843 struct cmos_checksum *p; 844 845 p = (struct cmos_checksum *)rec; 846 printf("CMOS checksum from bit %d to bit %d\n" 847 "at position %d is type %s.\n", 848 p->range_start, p->range_end, p->location, 849 (p->type == CHECKSUM_PCBIOS) ? "PC BIOS" : "NONE"); 850 } 851 852 /**************************************************************************** 853 * string_print_fn 854 * 855 * Display function for a generic item of coreboot table that simply 856 * consists of a string. 857 ****************************************************************************/ 858 static void string_print_fn(const struct lb_record *rec) 859 { 860 const struct lb_string *p; 861 862 p = (const struct lb_string *)rec; 863 printf("%s\n", p->string); 864 }