1 /*****************************************************************************\
3 *****************************************************************************
4 * Copyright (C) 2002-2005 The Regents of the University of California.
5 * Produced at the Lawrence Livermore National Laboratory.
6 * Written by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>
7 * and Stefan Reinauer <stepan@openbios.org>.
11 * This file is part of nvramtool, a utility for reading/writing coreboot
12 * parameters and displaying information from the coreboot table.
13 * For details, see http://coreboot.org/nvramtool.
15 * Please also read the file DISCLAIMER which is included in this software
18 * This program is free software; you can redistribute it and/or modify it
19 * under the terms of the GNU General Public License (as published by the
20 * Free Software Foundation) version 2, dated June 1991.
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
25 * conditions of the GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License along
28 * with this program; if not, write to the Free Software Foundation, Inc.,
29 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30 \*****************************************************************************/
32 #include <arpa/inet.h>
36 #include "coreboot_tables.h"
37 #include "ip_checksum.h"
40 #include "cmos_lowlevel.h"
44 typedef void (*lbtable_print_fn_t) (const struct lb_record * rec);
46 /* This structure represents an item in the coreboot table that may be
47 * displayed using the -l option.
52 const char *description;
53 const char *nofound_msg;
54 lbtable_print_fn_t print_fn;
58 unsigned long start; /* address of first byte of memory range */
59 unsigned long end; /* address of last byte of memory range */
62 static const struct lb_header *lbtable_scan(unsigned long start,
64 int *bad_header_count,
65 int *bad_table_count);
66 static const char *lbrec_tag_to_str(uint32_t tag);
67 static void memory_print_fn(const struct lb_record *rec);
68 static void mainboard_print_fn(const struct lb_record *rec);
69 static void cmos_opt_table_print_fn(const struct lb_record *rec);
70 static void print_option_record(const struct cmos_entries *cmos_entry);
71 static void print_enum_record(const struct cmos_enums *cmos_enum);
72 static void print_defaults_record(const struct cmos_defaults *cmos_defaults);
73 static void print_unknown_record(const struct lb_record *cmos_item);
74 static void option_checksum_print_fn(const struct lb_record *rec);
75 static void string_print_fn(const struct lb_record *rec);
77 static const char memory_desc[] =
78 " This shows information about system memory.\n";
80 static const char mainboard_desc[] =
81 " This shows information about your mainboard.\n";
83 static const char version_desc[] =
84 " This shows coreboot version information.\n";
86 static const char extra_version_desc[] =
87 " This shows extra coreboot version information.\n";
89 static const char build_desc[] = " This shows coreboot build information.\n";
91 static const char compile_time_desc[] =
92 " This shows when coreboot was compiled.\n";
94 static const char compile_by_desc[] = " This shows who compiled coreboot.\n";
96 static const char compile_host_desc[] =
97 " This shows the name of the machine that compiled coreboot.\n";
99 static const char compile_domain_desc[] =
100 " This shows the domain name of the machine that compiled coreboot.\n";
102 static const char compiler_desc[] =
103 " This shows the name of the compiler used to build coreboot.\n";
105 static const char linker_desc[] =
106 " This shows the name of the linker used to build coreboot.\n";
108 static const char assembler_desc[] =
109 " This shows the name of the assembler used to build coreboot.\n";
111 static const char cmos_opt_table_desc[] =
112 " This does a low-level dump of the CMOS option table. The table "
114 " information about the layout of the values that coreboot stores in\n"
115 " nonvolatile RAM.\n";
117 static const char option_checksum_desc[] =
118 " This shows the location of the CMOS checksum and the area over which it "
119 "is\n" " calculated.\n";
121 static const char generic_nofound_msg[] =
122 "%s: Item %s not found in coreboot table.\n";
124 static const char nofound_msg_cmos_opt_table[] =
125 "%s: Item %s not found in coreboot table. Apparently, the "
126 "coreboot installed on this system was built without specifying "
127 "CONFIG_HAVE_OPTION_TABLE.\n";
129 static const char nofound_msg_option_checksum[] =
130 "%s: Item %s not found in coreboot table. Apparently, you are "
131 "using coreboot v1.\n";
135 /* This is the number of items from the coreboot table that may be displayed
136 * using the -l option.
138 #define NUM_LBTABLE_CHOICES 14
140 /* These represent the various items from the coreboot table that may be
141 * displayed using the -l option.
143 static const lbtable_choice_t lbtable_choices[NUM_LBTABLE_CHOICES] =
144 { {LB_TAG_MEMORY, "memory",
145 memory_desc, generic_nofound_msg,
147 {LB_TAG_MAINBOARD, "mainboard",
148 mainboard_desc, generic_nofound_msg,
150 {LB_TAG_VERSION, "version",
151 version_desc, generic_nofound_msg,
153 {LB_TAG_EXTRA_VERSION, "extra_version",
154 extra_version_desc, generic_nofound_msg,
156 {LB_TAG_BUILD, "build",
157 build_desc, generic_nofound_msg,
159 {LB_TAG_COMPILE_TIME, "compile_time",
160 compile_time_desc, generic_nofound_msg,
162 {LB_TAG_COMPILE_BY, "compile_by",
163 compile_by_desc, generic_nofound_msg,
165 {LB_TAG_COMPILE_HOST, "compile_host",
166 compile_host_desc, generic_nofound_msg,
168 {LB_TAG_COMPILE_DOMAIN, "compile_domain",
169 compile_domain_desc, generic_nofound_msg,
171 {LB_TAG_COMPILER, "compiler",
172 compiler_desc, generic_nofound_msg,
174 {LB_TAG_LINKER, "linker",
175 linker_desc, generic_nofound_msg,
177 {LB_TAG_ASSEMBLER, "assembler",
178 assembler_desc, generic_nofound_msg,
180 {LB_TAG_CMOS_OPTION_TABLE, "cmos_opt_table",
181 cmos_opt_table_desc, nofound_msg_cmos_opt_table,
182 cmos_opt_table_print_fn},
183 {LB_TAG_OPTION_CHECKSUM, "option_checksum",
184 option_checksum_desc, nofound_msg_option_checksum,
185 option_checksum_print_fn}
188 /* The coreboot table resides in low physical memory, which we access using
189 * /dev/mem. These are ranges of physical memory that should be scanned for a
193 #define NUM_MEM_RANGES 2
195 static const mem_range_t mem_ranges[NUM_MEM_RANGES] =
196 { {0x00000000, 0x00000fff},
197 {0x000f0000, 0x000fffff}
200 /* This is the number of bytes of physical memory to map, starting at physical
201 * address 0. This value must be large enough to contain all memory ranges
202 * specified in mem_ranges above plus the maximum possible size of the
203 * coreboot table (since the start of the table could potentially occur at
204 * the end of the last memory range).
206 static const size_t BYTES_TO_MAP = (1024 * 1024);
208 /* Pointer to low physical memory that we access by calling mmap() on
211 static const void *low_phys_mem;
212 static unsigned long low_phys_base = 0;
214 /* Pointer to coreboot table. */
215 static const struct lb_header *lbtable = NULL;
217 static const hexdump_format_t format =
218 { 12, 4, " ", " | ", " ", " | ", '.' };
220 /****************************************************************************
223 * Convert a virtual address to a physical address. 'vaddr' is a virtual
224 * address in the address space of the current process. It points to
225 * somewhere in the chunk of memory that we mapped by calling mmap() on
226 * /dev/mem. This macro converts 'vaddr' to a physical address.
227 ****************************************************************************/
228 #define vtophys(vaddr) (((unsigned long) vaddr) - \
229 ((unsigned long) low_phys_mem) + low_phys_base)
231 /****************************************************************************
234 * Convert a physical address to a virtual address. 'paddr' is a physical
235 * address. This macro converts 'paddr' to a virtual address in the address
236 * space of the current process. The virtual to physical mapping was set up
237 * by calling mmap() on /dev/mem.
238 ****************************************************************************/
239 #define phystov(paddr) (((unsigned long) low_phys_mem) + \
240 ((unsigned long) paddr) - low_phys_base)
242 /****************************************************************************
245 * Find the coreboot table and set global variable lbtable to point to it.
246 ****************************************************************************/
247 void get_lbtable(void)
249 int i, bad_header_count, bad_table_count, bad_headers, bad_tables;
254 /* The coreboot table is located in low physical memory, which may be
255 * conveniently accessed by calling mmap() on /dev/mem.
258 if ((fd = open("/dev/mem", O_RDONLY, 0)) < 0) {
259 fprintf(stderr, "%s: Can not open /dev/mem for reading: %s\n",
260 prog_name, strerror(errno));
265 mmap(NULL, BYTES_TO_MAP, PROT_READ, MAP_SHARED, fd, 0))
267 fprintf(stderr, "%s: Failed to mmap /dev/mem: %s\n", prog_name,
272 bad_header_count = 0;
275 for (i = 0; i < NUM_MEM_RANGES; i++) {
276 lbtable = lbtable_scan(phystov(mem_ranges[i].start),
277 phystov(mem_ranges[i].end),
278 &bad_headers, &bad_tables);
281 return; /* success: we found it! */
283 bad_header_count += bad_headers;
284 bad_table_count += bad_tables;
288 "%s: coreboot table not found. coreboot does not appear to\n"
289 " be installed on this system. Scanning for the table "
291 " following results:\n\n"
292 " %d valid signatures were found with bad header "
294 " %d valid headers were found with bad table "
295 "checksums.\n", prog_name, bad_header_count, bad_table_count);
299 /****************************************************************************
302 * Do a low-level dump of the coreboot table.
303 ****************************************************************************/
304 void dump_lbtable(void)
306 const char *p, *data;
307 uint32_t bytes_processed;
308 const struct lb_record *lbrec;
310 p = ((const char *)lbtable) + lbtable->header_bytes;
311 printf("Coreboot table at physical address 0x%lx:\n"
312 " signature: 0x%x (ASCII: %c%c%c%c)\n"
313 " header_bytes: 0x%x (decimal: %d)\n"
314 " header_checksum: 0x%x (decimal: %d)\n"
315 " table_bytes: 0x%x (decimal: %d)\n"
316 " table_checksum: 0x%x (decimal: %d)\n"
317 " table_entries: 0x%x (decimal: %d)\n\n",
318 vtophys(lbtable), lbtable->signature32,
319 lbtable->signature[0], lbtable->signature[1],
320 lbtable->signature[2], lbtable->signature[3],
321 lbtable->header_bytes, lbtable->header_bytes,
322 lbtable->header_checksum, lbtable->header_checksum,
323 lbtable->table_bytes, lbtable->table_bytes,
324 lbtable->table_checksum, lbtable->table_checksum,
325 lbtable->table_entries, lbtable->table_entries);
327 if ((lbtable->table_bytes == 0) != (lbtable->table_entries == 0)) {
329 ("Inconsistent values for table_bytes and table_entries!!!\n"
330 "They should be either both 0 or both nonzero.\n");
334 if (lbtable->table_bytes == 0) {
335 printf("The coreboot table is empty!!!\n");
339 for (bytes_processed = 0;;) {
340 lbrec = (const struct lb_record *)&p[bytes_processed];
341 printf(" %s record at physical address 0x%lx:\n"
342 " tag: 0x%x (decimal: %d)\n"
343 " size: 0x%x (decimal: %d)\n"
345 lbrec_tag_to_str(lbrec->tag), vtophys(lbrec), lbrec->tag,
346 lbrec->tag, lbrec->size, lbrec->size);
348 data = ((const char *)lbrec) + sizeof(*lbrec);
349 hexdump(data, lbrec->size - sizeof(*lbrec), vtophys(data),
352 bytes_processed += lbrec->size;
354 if (bytes_processed >= lbtable->table_bytes)
361 /****************************************************************************
362 * list_lbtable_choices
364 * List names and informational blurbs for items from the coreboot table
365 * that may be displayed using the -l option.
366 ****************************************************************************/
367 void list_lbtable_choices(void)
373 lbtable_choices[i].name, lbtable_choices[i].description);
375 if (++i >= NUM_LBTABLE_CHOICES)
382 /****************************************************************************
385 * Show the coreboot table item specified by 'item'.
386 ****************************************************************************/
387 void list_lbtable_item(const char item[])
390 const struct lb_record *rec;
392 for (i = 0; i < NUM_LBTABLE_CHOICES; i++) {
393 if (strcmp(item, lbtable_choices[i].name) == 0)
397 if (i == NUM_LBTABLE_CHOICES) {
398 fprintf(stderr, "%s: Invalid coreboot table item %s.\n",
403 if ((rec = find_lbrec(lbtable_choices[i].tag)) == NULL) {
404 fprintf(stderr, lbtable_choices[i].nofound_msg, prog_name,
405 lbtable_choices[i].name);
409 lbtable_choices[i].print_fn(rec);
412 /****************************************************************************
415 * Scan the chunk of memory specified by 'start' and 'end' for a coreboot
416 * table. The first 4 bytes of the table are marked by the signature
417 * { 'L', 'B', 'I', 'O' }. 'start' and 'end' indicate the addresses of the
418 * first and last bytes of the chunk of memory to be scanned. For instance,
419 * values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k
420 * chunk of memory starting at address 0x10000000. 'start' and 'end' are
421 * virtual addresses in the address space of the current process. They
422 * represent a chunk of memory obtained by calling mmap() on /dev/mem.
424 * If a coreboot table is found, return a pointer to it. Otherwise return
425 * NULL. On return, *bad_header_count and *bad_table_count are set as
429 * Indicates the number of times in which a valid signature was found
430 * but the header checksum was invalid.
433 * Indicates the number of times in which a header with a valid
434 * checksum was found but the table checksum was invalid.
435 ****************************************************************************/
436 static const struct lb_header *lbtable_scan(unsigned long start,
438 int *bad_header_count,
439 int *bad_table_count)
441 static const char signature[4] = { 'L', 'B', 'I', 'O' };
442 const struct lb_header *table;
443 const struct lb_forward *forward;
447 assert(end >= start);
448 memcpy(&sig, signature, sizeof(sig));
450 *bad_header_count = 0;
451 *bad_table_count = 0;
453 /* Look for signature. Table is aligned on 16-byte boundary. Therefore
454 * only check every fourth 32-bit memory word. As the loop is coded below,
455 * this function will behave in a reasonable manner for ALL possible values
456 * for 'start' and 'end': even weird boundary cases like 0x00000000 and
457 * 0xffffffff on a 32-bit architecture.
459 for (p = (const uint32_t *)start;
460 (((unsigned long)p) <= end) &&
461 ((end - (unsigned long)p) >= (sizeof(uint32_t) - 1)); p += 4) {
465 /* We found a valid signature. */
466 table = (const struct lb_header *)p;
468 /* validate header checksum */
469 if (compute_ip_checksum((void *)table, sizeof(*table))) {
470 (*bad_header_count)++;
474 /* validate table checksum */
475 if (table->table_checksum !=
476 compute_ip_checksum(((char *)table) + sizeof(*table),
477 table->table_bytes)) {
478 (*bad_table_count)++;
482 /* checksums are ok: we found it! */
483 /* But it may just be a forwarding table, so look if there's a forwarder */
485 forward = (struct lb_forward *)find_lbrec(LB_TAG_FORWARD);
489 uint64_t new_phys = forward->forward;
491 new_phys &= ~(getpagesize() - 1);
493 munmap((void *)low_phys_mem, BYTES_TO_MAP);
495 mmap(NULL, BYTES_TO_MAP, PROT_READ, MAP_SHARED, fd,
496 (off_t) new_phys)) == MAP_FAILED) {
498 "%s: Failed to mmap /dev/mem: %s\n",
499 prog_name, strerror(errno));
502 low_phys_base = new_phys;
504 lbtable_scan(phystov(low_phys_base),
505 phystov(low_phys_base + BYTES_TO_MAP),
506 bad_header_count, bad_table_count);
514 /****************************************************************************
517 * Find the record in the coreboot table that matches 'tag'. Return pointer
518 * to record on success or NULL if record not found.
519 ****************************************************************************/
520 const struct lb_record *find_lbrec(uint32_t tag)
523 uint32_t bytes_processed;
524 const struct lb_record *lbrec;
526 p = ((const char *)lbtable) + lbtable->header_bytes;
528 for (bytes_processed = 0;
529 bytes_processed < lbtable->table_bytes;
530 bytes_processed += lbrec->size) {
531 lbrec = (const struct lb_record *)&p[bytes_processed];
533 if (lbrec->tag == tag)
540 /****************************************************************************
543 * Return a pointer to the string representation of the given coreboot table
545 ****************************************************************************/
546 static const char *lbrec_tag_to_str(uint32_t tag)
558 case LB_TAG_MAINBOARD:
564 case LB_TAG_EXTRA_VERSION:
565 return "EXTRA_VERSION";
570 case LB_TAG_COMPILE_TIME:
571 return "COMPILE_TIME";
573 case LB_TAG_COMPILE_BY:
576 case LB_TAG_COMPILE_HOST:
577 return "COMPILE_HOST";
579 case LB_TAG_COMPILE_DOMAIN:
580 return "COMPILE_DOMAIN";
582 case LB_TAG_COMPILER:
588 case LB_TAG_ASSEMBLER:
600 case LB_TAG_CMOS_OPTION_TABLE:
601 return "CMOS_OPTION_TABLE";
603 case LB_TAG_OPTION_CHECKSUM:
604 return "OPTION_CHECKSUM";
613 /****************************************************************************
616 * Display function for 'memory' item of coreboot table.
617 ****************************************************************************/
618 static void memory_print_fn(const struct lb_record *rec)
620 const struct lb_memory *p;
621 const char *mem_type;
622 const struct lb_memory_range *ranges;
623 uint64_t size, start, end;
626 p = (const struct lb_memory *)rec;
627 entries = (p->size - sizeof(*p)) / sizeof(p->map[0]);
631 printf("No memory ranges were found.\n");
636 switch (ranges[i].type) {
638 mem_type = "AVAILABLE";
641 case LB_MEM_RESERVED:
642 mem_type = "RESERVED";
646 mem_type = "CONFIG_TABLE";
650 mem_type = "UNKNOWN";
654 size = unpack_lb64(ranges[i].size);
655 start = unpack_lb64(ranges[i].start);
656 end = start + size - 1;
657 printf("%s memory:\n"
658 " from physical addresses 0x%016llx to 0x%016llx\n"
659 " size is 0x%016llx bytes (%lld in decimal)\n",
660 mem_type, start, end, size,
661 (unsigned long long)size);
670 /****************************************************************************
673 * Display function for 'mainboard' item of coreboot table.
674 ****************************************************************************/
675 static void mainboard_print_fn(const struct lb_record *rec)
677 const struct lb_mainboard *p;
679 p = (const struct lb_mainboard *)rec;
680 printf("Vendor: %s\n"
682 &p->strings[p->vendor_idx], &p->strings[p->part_number_idx]);
685 /****************************************************************************
686 * cmos_opt_table_print_fn
688 * Display function for 'cmos_opt_table' item of coreboot table.
689 ****************************************************************************/
690 static void cmos_opt_table_print_fn(const struct lb_record *rec)
692 const struct cmos_option_table *p;
693 const struct lb_record *cmos_item;
694 uint32_t bytes_processed, bytes_for_entries;
697 p = (const struct cmos_option_table *)rec;
698 q = ((const char *)p) + p->header_length;
699 bytes_for_entries = p->size - p->header_length;
701 printf("CMOS option table at physical address 0x%lx:\n"
702 " tag: 0x%x (decimal: %d)\n"
703 " size: 0x%x (decimal: %d)\n"
704 " header_length: 0x%x (decimal: %d)\n\n",
705 vtophys(p), p->tag, p->tag, p->size, p->size, p->header_length,
708 if (p->header_length > p->size) {
710 ("Header length for CMOS option table is greater than the size "
711 "of the entire table including header!!!\n");
715 if (bytes_for_entries == 0) {
716 printf("The CMOS option table is empty!!!\n");
720 for (bytes_processed = 0;;) {
721 cmos_item = (const struct lb_record *)&q[bytes_processed];
723 switch (cmos_item->tag) {
725 print_option_record((const struct cmos_entries *)
729 case LB_TAG_OPTION_ENUM:
730 print_enum_record((const struct cmos_enums *)cmos_item);
733 case LB_TAG_OPTION_DEFAULTS:
734 print_defaults_record((const struct cmos_defaults *)
739 print_unknown_record(cmos_item);
743 bytes_processed += cmos_item->size;
745 if (bytes_processed >= bytes_for_entries)
752 /****************************************************************************
753 * print_option_record
755 * Display "option" record from CMOS option table.
756 ****************************************************************************/
757 static void print_option_record(const struct cmos_entries *cmos_entry)
759 static const size_t S_BUFSIZE = 80;
762 switch (cmos_entry->config) {
772 strcpy(s, "RESERVED");
776 snprintf(s, S_BUFSIZE, "UNKNOWN: value is 0x%x (decimal: %d)",
777 cmos_entry->config, cmos_entry->config);
781 printf(" OPTION record at physical address 0x%lx:\n"
782 " tag: 0x%x (decimal: %d)\n"
783 " size: 0x%x (decimal: %d)\n"
784 " bit: 0x%x (decimal: %d)\n"
785 " length: 0x%x (decimal: %d)\n"
787 " config_id: 0x%x (decimal: %d)\n"
789 vtophys(cmos_entry), cmos_entry->tag, cmos_entry->tag,
790 cmos_entry->size, cmos_entry->size, cmos_entry->bit,
791 cmos_entry->bit, cmos_entry->length, cmos_entry->length, s,
792 cmos_entry->config_id, cmos_entry->config_id, cmos_entry->name);
795 /****************************************************************************
798 * Display "enum" record from CMOS option table.
799 ****************************************************************************/
800 static void print_enum_record(const struct cmos_enums *cmos_enum)
802 printf(" ENUM record at physical address 0x%lx:\n"
803 " tag: 0x%x (decimal: %d)\n"
804 " size: 0x%x (decimal: %d)\n"
805 " config_id: 0x%x (decimal: %d)\n"
806 " value: 0x%x (decimal: %d)\n"
808 vtophys(cmos_enum), cmos_enum->tag, cmos_enum->tag,
809 cmos_enum->size, cmos_enum->size, cmos_enum->config_id,
810 cmos_enum->config_id, cmos_enum->value, cmos_enum->value,
814 /****************************************************************************
815 * print_defaults_record
817 * Display "defaults" record from CMOS option table.
818 ****************************************************************************/
819 static void print_defaults_record(const struct cmos_defaults *cmos_defaults)
821 printf(" DEFAULTS record at physical address 0x%lx:\n"
822 " tag: 0x%x (decimal: %d)\n"
823 " size: 0x%x (decimal: %d)\n"
824 " name_length: 0x%x (decimal: %d)\n"
827 vtophys(cmos_defaults), cmos_defaults->tag, cmos_defaults->tag,
828 cmos_defaults->size, cmos_defaults->size,
829 cmos_defaults->name_length, cmos_defaults->name_length,
830 cmos_defaults->name);
831 hexdump(cmos_defaults->default_set, CMOS_IMAGE_BUFFER_SIZE,
832 vtophys(cmos_defaults->default_set), stdout, &format);
835 /****************************************************************************
836 * print_unknown_record
838 * Display record of unknown type from CMOS option table.
839 ****************************************************************************/
840 static void print_unknown_record(const struct lb_record *cmos_item)
844 printf(" UNKNOWN record at physical address 0x%lx:\n"
845 " tag: 0x%x (decimal: %d)\n"
846 " size: 0x%x (decimal: %d)\n"
848 vtophys(cmos_item), cmos_item->tag, cmos_item->tag,
849 cmos_item->size, cmos_item->size);
850 data = ((const char *)cmos_item) + sizeof(*cmos_item);
851 hexdump(data, cmos_item->size - sizeof(*cmos_item), vtophys(data),
855 /****************************************************************************
856 * option_checksum_print_fn
858 * Display function for 'option_checksum' item of coreboot table.
859 ****************************************************************************/
860 static void option_checksum_print_fn(const struct lb_record *rec)
862 struct cmos_checksum *p;
864 p = (struct cmos_checksum *)rec;
865 printf("CMOS checksum from bit %d to bit %d\n"
866 "at position %d is type %s.\n",
867 p->range_start, p->range_end, p->location,
868 (p->type == CHECKSUM_PCBIOS) ? "PC BIOS" : "NONE");
871 /****************************************************************************
874 * Display function for a generic item of coreboot table that simply
875 * consists of a string.
876 ****************************************************************************/
877 static void string_print_fn(const struct lb_record *rec)
879 const struct lb_string *p;
881 p = (const struct lb_string *)rec;
882 printf("%s\n", p->string);