1 /* SPDX-License-Identifier: GPL-2.0-only */
10 #include "coreboot_tables.h"
11 #include "ip_checksum.h"
14 #include "cmos_lowlevel.h"
18 typedef void (*lbtable_print_fn_t
) (const struct lb_record
* rec
);
20 /* This structure represents an item in the coreboot table that may be
21 * displayed using the -l option.
26 const char *description
;
27 const char *nofound_msg
;
28 lbtable_print_fn_t print_fn
;
32 unsigned long start
; /* address of first byte of memory range */
33 unsigned long end
; /* address of last byte of memory range */
36 static const struct lb_header
*lbtable_scan(unsigned long start
,
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
);
51 static const char memory_desc
[] =
52 " This shows information about system memory.\n";
54 static const char mainboard_desc
[] =
55 " This shows information about your mainboard.\n";
57 static const char version_desc
[] =
58 " This shows coreboot version information.\n";
60 static const char extra_version_desc
[] =
61 " This shows extra coreboot version information.\n";
63 static const char build_desc
[] = " This shows coreboot build information.\n";
65 static const char compile_time_desc
[] =
66 " This shows when coreboot was compiled.\n";
68 static const char compile_by_desc
[] = " This shows who compiled coreboot.\n";
70 static const char compile_host_desc
[] =
71 " This shows the name of the machine that compiled coreboot.\n";
73 static const char compile_domain_desc
[] =
74 " This shows the domain name of the machine that compiled coreboot.\n";
76 static const char compiler_desc
[] =
77 " This shows the name of the compiler used to build coreboot.\n";
79 static const char linker_desc
[] =
80 " This shows the name of the linker used to build coreboot.\n";
82 static const char assembler_desc
[] =
83 " This shows the name of the assembler used to build coreboot.\n";
85 static const char cmos_opt_table_desc
[] =
86 " This does a low-level dump of the CMOS option table. The table "
88 " information about the layout of the values that coreboot stores in\n"
89 " nonvolatile RAM.\n";
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";
95 static const char generic_nofound_msg
[] =
96 "%s: Item %s not found in coreboot table.\n";
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";
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";
109 /* This is the number of items from the coreboot table that may be displayed
110 * using the -l option.
112 #define NUM_LBTABLE_CHOICES 14
114 /* These represent the various items from the coreboot table that may be
115 * displayed using the -l option.
117 static const lbtable_choice_t lbtable_choices
[NUM_LBTABLE_CHOICES
] =
118 { {LB_TAG_MEMORY
, "memory",
119 memory_desc
, generic_nofound_msg
,
121 {LB_TAG_MAINBOARD
, "mainboard",
122 mainboard_desc
, generic_nofound_msg
,
124 {LB_TAG_VERSION
, "version",
125 version_desc
, generic_nofound_msg
,
127 {LB_TAG_EXTRA_VERSION
, "extra_version",
128 extra_version_desc
, generic_nofound_msg
,
130 {LB_TAG_BUILD
, "build",
131 build_desc
, generic_nofound_msg
,
133 {LB_TAG_COMPILE_TIME
, "compile_time",
134 compile_time_desc
, generic_nofound_msg
,
136 {LB_TAG_COMPILE_BY
, "compile_by",
137 compile_by_desc
, generic_nofound_msg
,
139 {LB_TAG_COMPILE_HOST
, "compile_host",
140 compile_host_desc
, generic_nofound_msg
,
142 {LB_TAG_COMPILE_DOMAIN
, "compile_domain",
143 compile_domain_desc
, generic_nofound_msg
,
145 {LB_TAG_COMPILER
, "compiler",
146 compiler_desc
, generic_nofound_msg
,
148 {LB_TAG_LINKER
, "linker",
149 linker_desc
, generic_nofound_msg
,
151 {LB_TAG_ASSEMBLER
, "assembler",
152 assembler_desc
, generic_nofound_msg
,
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
}
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
167 #define NUM_MEM_RANGES 2
169 static const mem_range_t mem_ranges
[NUM_MEM_RANGES
] =
170 { {0x00000000, 0x00000fff},
171 {0x000f0000, 0x000fffff}
174 /* Pointer to low physical memory that we access by calling mmap() on
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;
181 /* count of mapped pages */
182 static unsigned long mapped_pages
= 0;
184 /* Pointer to coreboot table. */
185 static const struct lb_header
*lbtable
= NULL
;
187 static const hexdump_format_t format
=
188 { 12, 4, " ", " | ", " ", " | ", '.' };
190 /****************************************************************************
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)
201 /****************************************************************************
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)
212 /****************************************************************************
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
)
220 unsigned long num_pages
= (length
+
221 (base_address
& (getpagesize() - 1)) +
222 getpagesize() - 1) >> 12;
223 base_address
&= ~(getpagesize() - 1);
225 /* no need to do anything */
226 if ((low_phys_base
== base_address
) && (mapped_pages
== num_pages
)) {
231 munmap((void *)low_phys_mem
, mapped_pages
<< 12);
233 if ((low_phys_mem
= mmap(NULL
, num_pages
<< 12, PROT_READ
, MAP_SHARED
, fd
,
234 (off_t
) base_address
)) == MAP_FAILED
) {
236 "%s: Failed to mmap /dev/mem at %lx: %s\n",
237 prog_name
, base_address
, strerror(errno
));
240 low_phys_base
= base_address
;
243 /****************************************************************************
246 * Find the coreboot table and set global variable lbtable to point to it.
247 ****************************************************************************/
248 void get_lbtable(void)
250 int i
, bad_header_count
, bad_table_count
, bad_headers
, bad_tables
;
255 /* The coreboot table is located in low physical memory, which may be
256 * conveniently accessed by calling mmap() on /dev/mem.
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
));
265 bad_header_count
= 0;
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
);
273 return; /* success: we found it! */
275 bad_header_count
+= bad_headers
;
276 bad_table_count
+= bad_tables
;
280 "%s: coreboot table not found. coreboot does not appear to\n"
281 " be installed on this system. Scanning for the table "
283 " following results:\n\n"
284 " %d valid signatures were found with bad header "
286 " %d valid headers were found with bad table "
287 "checksums.\n", prog_name
, bad_header_count
, bad_table_count
);
291 /****************************************************************************
294 * Do a low-level dump of the coreboot table.
295 ****************************************************************************/
296 void dump_lbtable(void)
298 const char *p
, *data
;
299 uint32_t bytes_processed
;
300 const struct lb_record
*lbrec
;
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
);
319 if ((lbtable
->table_bytes
== 0) != (lbtable
->table_entries
== 0)) {
321 ("Inconsistent values for table_bytes and table_entries!!!\n"
322 "They should be either both 0 or both nonzero.\n");
326 if (lbtable
->table_bytes
== 0) {
327 printf("The coreboot table is empty!!!\n");
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"
337 lbrec_tag_to_str(lbrec
->tag
), vtophys(lbrec
), lbrec
->tag
,
338 lbrec
->tag
, lbrec
->size
, lbrec
->size
);
340 data
= ((const char *)lbrec
) + sizeof(*lbrec
);
341 hexdump(data
, lbrec
->size
- sizeof(*lbrec
), vtophys(data
),
344 bytes_processed
+= lbrec
->size
;
346 if (bytes_processed
>= lbtable
->table_bytes
)
353 /****************************************************************************
354 * list_lbtable_choices
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)
365 lbtable_choices
[i
].name
, lbtable_choices
[i
].description
);
367 if (++i
>= NUM_LBTABLE_CHOICES
)
374 /****************************************************************************
377 * Show the coreboot table item specified by 'item'.
378 ****************************************************************************/
379 void list_lbtable_item(const char item
[])
382 const struct lb_record
*rec
;
384 for (i
= 0; i
< NUM_LBTABLE_CHOICES
; i
++) {
385 if (strcmp(item
, lbtable_choices
[i
].name
) == 0)
389 if (i
== NUM_LBTABLE_CHOICES
) {
390 fprintf(stderr
, "%s: Invalid coreboot table item %s.\n",
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
);
401 lbtable_choices
[i
].print_fn(rec
);
404 /****************************************************************************
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.
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
420 * Indicates the number of times in which a valid signature was found
421 * but the header checksum was invalid.
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
,
429 int *bad_header_count
,
430 int *bad_table_count
)
432 static const char signature
[4] = { 'L', 'B', 'I', 'O' };
433 const struct lb_header
*table
;
434 const struct lb_forward
*forward
;
438 assert(end
>= start
);
439 memcpy(&sig
, signature
, sizeof(sig
));
441 *bad_header_count
= 0;
442 *bad_table_count
= 0;
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.
450 map_pages(start
, end
- start
);
453 (end
- p
>= (sizeof(uint32_t) - 1)); p
+= 4) {
454 if (*(uint32_t*)phystov(p
) != sig
)
457 /* We found a valid signature. */
458 table
= (const struct lb_header
*)phystov(p
);
460 /* validate header checksum */
461 if (compute_ip_checksum((void *)table
, sizeof(*table
))) {
462 (*bad_header_count
)++;
466 map_pages(p
, table
->table_bytes
+ sizeof(*table
));
468 table
= (const struct lb_header
*)phystov(p
);
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
)++;
478 /* checksums are ok: we found it! */
479 /* But it may just be a forwarding table, so look if there's a forwarder */
481 forward
= (struct lb_forward
*)find_lbrec(LB_TAG_FORWARD
);
485 uint64_t new_phys
= forward
->forward
;
486 table
= lbtable_scan(new_phys
, new_phys
+ getpagesize(),
487 bad_header_count
, bad_table_count
);
495 /****************************************************************************
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
)
504 uint32_t bytes_processed
;
505 const struct lb_record
*lbrec
;
507 p
= ((const char *)lbtable
) + lbtable
->header_bytes
;
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
];
514 if (lbrec
->tag
== tag
)
521 /****************************************************************************
524 * Return a pointer to the string representation of the given coreboot table
526 ****************************************************************************/
527 static const char *lbrec_tag_to_str(uint32_t tag
)
539 case LB_TAG_MAINBOARD
:
545 case LB_TAG_EXTRA_VERSION
:
546 return "EXTRA_VERSION";
551 case LB_TAG_COMPILE_TIME
:
552 return "COMPILE_TIME";
554 case LB_TAG_COMPILE_BY
:
557 case LB_TAG_COMPILE_HOST
:
558 return "COMPILE_HOST";
560 case LB_TAG_COMPILE_DOMAIN
:
561 return "COMPILE_DOMAIN";
563 case LB_TAG_COMPILER
:
569 case LB_TAG_ASSEMBLER
:
581 case LB_TAG_CMOS_OPTION_TABLE
:
582 return "CMOS_OPTION_TABLE";
584 case LB_TAG_OPTION_CHECKSUM
:
585 return "OPTION_CHECKSUM";
594 /****************************************************************************
597 * Display function for 'memory' item of coreboot table.
598 ****************************************************************************/
599 static void memory_print_fn(const struct lb_record
*rec
)
601 const struct lb_memory
*p
;
602 const char *mem_type
;
603 const struct lb_memory_range
*ranges
;
604 uint64_t size
, start
, end
;
607 p
= (const struct lb_memory
*)rec
;
608 entries
= (p
->size
- sizeof(*p
)) / sizeof(p
->map
[0]);
612 printf("No memory ranges were found.\n");
617 switch (ranges
[i
].type
) {
619 mem_type
= "AVAILABLE";
622 case LB_MEM_RESERVED
:
623 mem_type
= "RESERVED";
627 mem_type
= "CONFIG_TABLE";
631 mem_type
= "UNKNOWN";
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
);
651 /****************************************************************************
654 * Display function for 'mainboard' item of coreboot table.
655 ****************************************************************************/
656 static void mainboard_print_fn(const struct lb_record
*rec
)
658 const struct lb_mainboard
*p
;
660 p
= (const struct lb_mainboard
*)rec
;
661 printf("Vendor: %s\n"
663 &p
->strings
[p
->vendor_idx
], &p
->strings
[p
->part_number_idx
]);
666 /****************************************************************************
667 * cmos_opt_table_print_fn
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
)
673 const struct cmos_option_table
*p
;
674 const struct lb_record
*cmos_item
;
675 uint32_t bytes_processed
, bytes_for_entries
;
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
;
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
,
689 if (p
->header_length
> p
->size
) {
691 ("Header length for CMOS option table is greater than the size "
692 "of the entire table including header!!!\n");
696 if (bytes_for_entries
== 0) {
697 printf("The CMOS option table is empty!!!\n");
701 for (bytes_processed
= 0;;) {
702 cmos_item
= (const struct lb_record
*)&q
[bytes_processed
];
704 switch (cmos_item
->tag
) {
706 print_option_record((const struct cmos_entries
*)
710 case LB_TAG_OPTION_ENUM
:
711 print_enum_record((const struct cmos_enums
*)cmos_item
);
714 case LB_TAG_OPTION_DEFAULTS
:
715 print_defaults_record((const struct cmos_defaults
*)
720 print_unknown_record(cmos_item
);
724 bytes_processed
+= cmos_item
->size
;
726 if (bytes_processed
>= bytes_for_entries
)
733 /****************************************************************************
734 * print_option_record
736 * Display "option" record from CMOS option table.
737 ****************************************************************************/
738 static void print_option_record(const struct cmos_entries
*cmos_entry
)
740 static const size_t S_BUFSIZE
= 80;
743 switch (cmos_entry
->config
) {
753 strcpy(s
, "RESERVED");
757 snprintf(s
, S_BUFSIZE
, "UNKNOWN: value is 0x%x (decimal: %d)",
758 cmos_entry
->config
, cmos_entry
->config
);
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"
768 " config_id: 0x%x (decimal: %d)\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
);
776 /****************************************************************************
779 * Display "enum" record from CMOS option table.
780 ****************************************************************************/
781 static void print_enum_record(const struct cmos_enums
*cmos_enum
)
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"
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
,
795 /****************************************************************************
796 * print_defaults_record
798 * Display "defaults" record from CMOS option table.
799 ****************************************************************************/
800 static void print_defaults_record(const struct cmos_defaults
*cmos_defaults
)
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"
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
);
816 /****************************************************************************
817 * print_unknown_record
819 * Display record of unknown type from CMOS option table.
820 ****************************************************************************/
821 static void print_unknown_record(const struct lb_record
*cmos_item
)
825 printf(" UNKNOWN record at physical address 0x%lx:\n"
826 " tag: 0x%x (decimal: %d)\n"
827 " size: 0x%x (decimal: %d)\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
),
836 /****************************************************************************
837 * option_checksum_print_fn
839 * Display function for 'option_checksum' item of coreboot table.
840 ****************************************************************************/
841 static void option_checksum_print_fn(const struct lb_record
*rec
)
843 struct cmos_checksum
*p
;
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");
852 /****************************************************************************
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
)
860 const struct lb_string
*p
;
862 p
= (const struct lb_string
*)rec
;
863 printf("%s\n", p
->string
);