blob: 6993cc0ce5d2c6a7c0dfb2577958aa51c2177beb [file] [log] [blame]
Patrick Georgi55189c92020-05-10 20:09:31 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Stefan Reinauer6540ae52007-07-12 16:35:42 +00002
Stefan Reinauer9981cad2012-05-24 13:36:30 -07003#include <stdint.h>
4#include <inttypes.h>
Stefan Reinauer297b91c2008-09-18 14:49:33 +00005#include <string.h>
Zheng Bao54516722012-10-22 16:41:42 +08006#ifndef __MINGW32__
Stefan Reinauer6540ae52007-07-12 16:35:42 +00007#include <sys/mman.h>
Zheng Bao54516722012-10-22 16:41:42 +08008#endif
Stefan Reinauer6540ae52007-07-12 16:35:42 +00009#include "common.h"
Stefan Reinauer7223ab72008-01-18 16:17:44 +000010#include "coreboot_tables.h"
Stefan Reinauer6540ae52007-07-12 16:35:42 +000011#include "ip_checksum.h"
12#include "lbtable.h"
13#include "layout.h"
14#include "cmos_lowlevel.h"
15#include "hexdump.h"
Patrick Georgi269e9322011-01-21 07:24:08 +000016#include "cbfs.h"
Stefan Reinauer6540ae52007-07-12 16:35:42 +000017
Stefan Reinauer90b96b62010-01-13 21:00:23 +000018typedef void (*lbtable_print_fn_t) (const struct lb_record * rec);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000019
Stefan Reinauerf527e702008-01-18 15:33:49 +000020/* This structure represents an item in the coreboot table that may be
Stefan Reinauer6540ae52007-07-12 16:35:42 +000021 * displayed using the -l option.
22 */
Stefan Reinauer90b96b62010-01-13 21:00:23 +000023typedef 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;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000030
Stefan Reinauer90b96b62010-01-13 21:00:23 +000031typedef 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;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000035
Stefan Reinauer90b96b62010-01-13 21:00:23 +000036static const struct lb_header *lbtable_scan(unsigned long start,
37 unsigned long end,
38 int *bad_header_count,
39 int *bad_table_count);
Stefan Reinauer90b96b62010-01-13 21:00:23 +000040static const char *lbrec_tag_to_str(uint32_t tag);
Stefan Reinauer90b96b62010-01-13 21:00:23 +000041static void memory_print_fn(const struct lb_record *rec);
42static void mainboard_print_fn(const struct lb_record *rec);
43static void cmos_opt_table_print_fn(const struct lb_record *rec);
44static void print_option_record(const struct cmos_entries *cmos_entry);
45static void print_enum_record(const struct cmos_enums *cmos_enum);
46static void print_defaults_record(const struct cmos_defaults *cmos_defaults);
47static void print_unknown_record(const struct lb_record *cmos_item);
48static void option_checksum_print_fn(const struct lb_record *rec);
49static void string_print_fn(const struct lb_record *rec);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000050
51static const char memory_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000052 " This shows information about system memory.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000053
54static const char mainboard_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000055 " This shows information about your mainboard.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000056
57static const char version_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000058 " This shows coreboot version information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000059
60static const char extra_version_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000061 " This shows extra coreboot version information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000062
Stefan Reinauer90b96b62010-01-13 21:00:23 +000063static const char build_desc[] = " This shows coreboot build information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000064
65static const char compile_time_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000066 " This shows when coreboot was compiled.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000067
Stefan Reinauer90b96b62010-01-13 21:00:23 +000068static const char compile_by_desc[] = " This shows who compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000069
70static const char compile_host_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000071 " This shows the name of the machine that compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000072
73static const char compile_domain_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000074 " This shows the domain name of the machine that compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000075
76static const char compiler_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000077 " This shows the name of the compiler used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000078
79static const char linker_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000080 " This shows the name of the linker used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000081
82static const char assembler_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000083 " This shows the name of the assembler used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000084
85static const char cmos_opt_table_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000086 " 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";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000090
91static const char option_checksum_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000092 " This shows the location of the CMOS checksum and the area over which it "
93 "is\n" " calculated.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000094
95static const char generic_nofound_msg[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000096 "%s: Item %s not found in coreboot table.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000097
98static const char nofound_msg_cmos_opt_table[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000099 "%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";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000102
103static const char nofound_msg_option_checksum[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000104 "%s: Item %s not found in coreboot table. Apparently, you are "
105 "using coreboot v1.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000106
Stefan Reinauer764fe402009-03-17 14:39:36 +0000107int fd;
108
Stefan Reinauerf527e702008-01-18 15:33:49 +0000109/* This is the number of items from the coreboot table that may be displayed
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000110 * using the -l option.
111 */
112#define NUM_LBTABLE_CHOICES 14
113
Stefan Reinauerf527e702008-01-18 15:33:49 +0000114/* These represent the various items from the coreboot table that may be
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000115 * displayed using the -l option.
116 */
117static const lbtable_choice_t lbtable_choices[NUM_LBTABLE_CHOICES] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000118 { {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};
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000161
Stefan Reinauerf527e702008-01-18 15:33:49 +0000162/* The coreboot table resides in low physical memory, which we access using
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000163 * /dev/mem. These are ranges of physical memory that should be scanned for a
Stefan Reinauerf527e702008-01-18 15:33:49 +0000164 * coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000165 */
166
167#define NUM_MEM_RANGES 2
168
169static const mem_range_t mem_ranges[NUM_MEM_RANGES] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000170 { {0x00000000, 0x00000fff},
171{0x000f0000, 0x000fffff}
172};
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000173
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000174/* Pointer to low physical memory that we access by calling mmap() on
175 * /dev/mem.
176 */
177static const void *low_phys_mem;
Patrick Georgi12781422013-02-21 14:03:47 +0100178/* impossible value since not page aligned: first map request will happen */
179static unsigned long low_phys_base = 0x1;
180
181/* count of mapped pages */
182static unsigned long mapped_pages = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000183
Stefan Reinauerf527e702008-01-18 15:33:49 +0000184/* Pointer to coreboot table. */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000185static const struct lb_header *lbtable = NULL;
186
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000187static const hexdump_format_t format =
Patrick Georgi024ec852011-01-18 12:14:08 +0000188 { 12, 4, " ", " | ", " ", " | ", '.' };
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000189
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) - \
Stefan Reinauer764fe402009-03-17 14:39:36 +0000199 ((unsigned long) low_phys_mem) + low_phys_base)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000200
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) + \
Stefan Reinauer764fe402009-03-17 14:39:36 +0000210 ((unsigned long) paddr) - low_phys_base)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000211
212/****************************************************************************
Patrick Georgi12781422013-02-21 14:03:47 +0100213 * map_pages
214 *
215 * Maps just enough pages to cover base_address + length
216 * and updates affected variables
217 ****************************************************************************/
218static 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/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000244 * get_lbtable
245 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000246 * Find the coreboot table and set global variable lbtable to point to it.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000247 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000248void get_lbtable(void)
249{
250 int i, bad_header_count, bad_table_count, bad_headers, bad_tables;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000251
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000252 if (lbtable != NULL)
253 return;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000254
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000255 /* The coreboot table is located in low physical memory, which may be
256 * conveniently accessed by calling mmap() on /dev/mem.
257 */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000258
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000259 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 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000264
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000265 bad_header_count = 0;
266 bad_table_count = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000267
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000268 for (i = 0; i < NUM_MEM_RANGES; i++) {
Patrick Georgi12781422013-02-21 14:03:47 +0100269 lbtable = lbtable_scan(mem_ranges[i].start, mem_ranges[i].end,
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000270 &bad_headers, &bad_tables);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000271
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000272 if (lbtable != NULL)
273 return; /* success: we found it! */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000274
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000275 bad_header_count += bad_headers;
276 bad_table_count += bad_tables;
277 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000278
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000279 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}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000290
291/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000292 * dump_lbtable
293 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000294 * Do a low-level dump of the coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000295 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000296void dump_lbtable(void)
297{
298 const char *p, *data;
299 uint32_t bytes_processed;
300 const struct lb_record *lbrec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000301
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000302 p = ((const char *)lbtable) + lbtable->header_bytes;
Martin Rotha5648112017-06-03 20:05:42 -0600303 printf("coreboot table at physical address 0x%lx:\n"
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000304 " 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",
Patrick Georgi26016972011-01-18 12:12:47 +0000310 vtophys(lbtable), lbtable->signature32,
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000311 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);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000318
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000319 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 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000325
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000326 if (lbtable->table_bytes == 0) {
327 printf("The coreboot table is empty!!!\n");
328 return;
329 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000330
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000331 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);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000339
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000340 data = ((const char *)lbrec) + sizeof(*lbrec);
341 hexdump(data, lbrec->size - sizeof(*lbrec), vtophys(data),
342 stdout, &format);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000343
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000344 bytes_processed += lbrec->size;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000345
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000346 if (bytes_processed >= lbtable->table_bytes)
347 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000348
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000349 printf("\n");
350 }
351}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000352
353/****************************************************************************
354 * list_lbtable_choices
355 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000356 * List names and informational blurbs for items from the coreboot table
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000357 * that may be displayed using the -l option.
358 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000359void list_lbtable_choices(void)
360{
361 int i;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000362
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000363 for (i = 0;;) {
364 printf("%s:\n%s",
365 lbtable_choices[i].name, lbtable_choices[i].description);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000366
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000367 if (++i >= NUM_LBTABLE_CHOICES)
368 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000369
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000370 printf("\n");
371 }
372}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000373
374/****************************************************************************
375 * list_lbtable_item
376 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000377 * Show the coreboot table item specified by 'item'.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000378 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000379void list_lbtable_item(const char item[])
380{
381 int i;
382 const struct lb_record *rec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000383
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000384 for (i = 0; i < NUM_LBTABLE_CHOICES; i++) {
385 if (strcmp(item, lbtable_choices[i].name) == 0)
386 break;
387 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000388
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000389 if (i == NUM_LBTABLE_CHOICES) {
390 fprintf(stderr, "%s: Invalid coreboot table item %s.\n",
391 prog_name, item);
392 exit(1);
393 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000394
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000395 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 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000400
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000401 lbtable_choices[i].print_fn(rec);
402}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000403
404/****************************************************************************
405 * lbtable_scan
406 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000407 * Scan the chunk of memory specified by 'start' and 'end' for a coreboot
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000408 * 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
Patrick Georgi12781422013-02-21 14:03:47 +0100413 * physical addresses.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000414 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000415 * If a coreboot table is found, return a pointer to it. Otherwise return
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000416 * 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 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000427static const struct lb_header *lbtable_scan(unsigned long start,
428 unsigned long end,
429 int *bad_header_count,
430 int *bad_table_count)
431{
Patrick Georgi26016972011-01-18 12:12:47 +0000432 static const char signature[4] = { 'L', 'B', 'I', 'O' };
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000433 const struct lb_header *table;
434 const struct lb_forward *forward;
Patrick Georgi12781422013-02-21 14:03:47 +0100435 unsigned long p;
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000436 uint32_t sig;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000437
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000438 assert(end >= start);
Patrick Georgi26016972011-01-18 12:12:47 +0000439 memcpy(&sig, signature, sizeof(sig));
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000440 table = NULL;
441 *bad_header_count = 0;
442 *bad_table_count = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000443
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000444 /* 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 */
Patrick Georgi12781422013-02-21 14:03:47 +0100450 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)
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000455 continue;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000456
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000457 /* We found a valid signature. */
Patrick Georgi12781422013-02-21 14:03:47 +0100458 table = (const struct lb_header *)phystov(p);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000459
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000460 /* validate header checksum */
461 if (compute_ip_checksum((void *)table, sizeof(*table))) {
462 (*bad_header_count)++;
463 continue;
464 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000465
Patrick Georgi12781422013-02-21 14:03:47 +0100466 map_pages(p, table->table_bytes + sizeof(*table));
Timothy Pearson347234c2015-12-01 13:49:59 -0600467
468 table = (const struct lb_header *)phystov(p);
469
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000470 /* 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 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000477
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000478 /* 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;
Stefan Reinauer764fe402009-03-17 14:39:36 +0000483
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000484 if (forward) {
485 uint64_t new_phys = forward->forward;
Patrick Georgi12781422013-02-21 14:03:47 +0100486 table = lbtable_scan(new_phys, new_phys + getpagesize(),
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000487 bad_header_count, bad_table_count);
488 }
489 return table;
490 }
491
492 return NULL;
493}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000494
495/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000496 * find_lbrec
497 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000498 * Find the record in the coreboot table that matches 'tag'. Return pointer
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000499 * to record on success or NULL if record not found.
500 ****************************************************************************/
Mathias Krause155c3792011-03-10 07:52:02 +0000501const struct lb_record *find_lbrec(uint32_t tag)
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000502{
503 const char *p;
504 uint32_t bytes_processed;
505 const struct lb_record *lbrec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000506
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000507 p = ((const char *)lbtable) + lbtable->header_bytes;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000508
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000509 for (bytes_processed = 0;
510 bytes_processed < lbtable->table_bytes;
511 bytes_processed += lbrec->size) {
512 lbrec = (const struct lb_record *)&p[bytes_processed];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000513
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000514 if (lbrec->tag == tag)
515 return lbrec;
516 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000517
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000518 return NULL;
519}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000520
521/****************************************************************************
522 * lbrec_tag_to_str
523 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000524 * Return a pointer to the string representation of the given coreboot table
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000525 * tag.
526 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000527static const char *lbrec_tag_to_str(uint32_t tag)
528{
529 switch (tag) {
530 case LB_TAG_UNUSED:
531 return "UNUSED";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000532
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000533 case LB_TAG_MEMORY:
534 return "MEMORY";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000535
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000536 case LB_TAG_HWRPB:
537 return "HWRPB";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000538
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000539 case LB_TAG_MAINBOARD:
540 return "MAINBOARD";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000541
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000542 case LB_TAG_VERSION:
543 return "VERSION";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000544
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000545 case LB_TAG_EXTRA_VERSION:
546 return "EXTRA_VERSION";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000547
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000548 case LB_TAG_BUILD:
549 return "BUILD";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000550
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000551 case LB_TAG_COMPILE_TIME:
552 return "COMPILE_TIME";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000553
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000554 case LB_TAG_COMPILE_BY:
555 return "COMPILE_BY";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000556
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000557 case LB_TAG_COMPILE_HOST:
558 return "COMPILE_HOST";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000559
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000560 case LB_TAG_COMPILE_DOMAIN:
561 return "COMPILE_DOMAIN";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000562
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000563 case LB_TAG_COMPILER:
564 return "COMPILER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000565
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000566 case LB_TAG_LINKER:
567 return "LINKER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000568
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000569 case LB_TAG_ASSEMBLER:
570 return "ASSEMBLER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000571
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000572 case LB_TAG_SERIAL:
573 return "SERIAL";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000574
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000575 case LB_TAG_CONSOLE:
576 return "CONSOLE";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000577
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000578 case LB_TAG_FORWARD:
579 return "FORWARD";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000580
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000581 case LB_TAG_CMOS_OPTION_TABLE:
582 return "CMOS_OPTION_TABLE";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000583
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000584 case LB_TAG_OPTION_CHECKSUM:
585 return "OPTION_CHECKSUM";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000586
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000587 default:
588 break;
589 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000590
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000591 return "UNKNOWN";
592}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000593
594/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000595 * memory_print_fn
596 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000597 * Display function for 'memory' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000598 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000599static void memory_print_fn(const struct lb_record *rec)
600{
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000601 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;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000606
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000607 p = (const struct lb_memory *)rec;
608 entries = (p->size - sizeof(*p)) / sizeof(p->map[0]);
609 ranges = p->map;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000610
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000611 if (entries == 0) {
612 printf("No memory ranges were found.\n");
613 return;
614 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000615
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000616 for (i = 0;;) {
617 switch (ranges[i].type) {
618 case LB_MEM_RAM:
619 mem_type = "AVAILABLE";
620 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000621
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000622 case LB_MEM_RESERVED:
623 mem_type = "RESERVED";
624 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000625
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000626 case LB_MEM_TABLE:
627 mem_type = "CONFIG_TABLE";
628 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000629
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000630 default:
631 mem_type = "UNKNOWN";
632 break;
633 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000634
Jianjun Wangb2537bd2022-04-08 16:57:28 +0800635 size = ranges[i].size;
636 start = ranges[i].start;
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000637 end = start + size - 1;
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000638 printf("%s memory:\n"
Stefan Reinauer9981cad2012-05-24 13:36:30 -0700639 " 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);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000643
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000644 if (++i >= entries)
645 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000646
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000647 printf("\n");
648 }
649}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000650
651/****************************************************************************
652 * mainboard_print_fn
653 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000654 * Display function for 'mainboard' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000655 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000656static void mainboard_print_fn(const struct lb_record *rec)
657{
658 const struct lb_mainboard *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000659
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000660 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}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000665
666/****************************************************************************
667 * cmos_opt_table_print_fn
668 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000669 * Display function for 'cmos_opt_table' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000670 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000671static 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;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000677
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000678 p = (const struct cmos_option_table *)rec;
679 q = ((const char *)p) + p->header_length;
680 bytes_for_entries = p->size - p->header_length;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000681
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000682 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);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000688
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000689 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 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000695
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000696 if (bytes_for_entries == 0) {
697 printf("The CMOS option table is empty!!!\n");
698 return;
699 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000700
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000701 for (bytes_processed = 0;;) {
702 cmos_item = (const struct lb_record *)&q[bytes_processed];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000703
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000704 switch (cmos_item->tag) {
705 case LB_TAG_OPTION:
706 print_option_record((const struct cmos_entries *)
707 cmos_item);
708 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000709
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000710 case LB_TAG_OPTION_ENUM:
711 print_enum_record((const struct cmos_enums *)cmos_item);
712 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000713
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000714 case LB_TAG_OPTION_DEFAULTS:
715 print_defaults_record((const struct cmos_defaults *)
716 cmos_item);
717 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000718
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000719 default:
720 print_unknown_record(cmos_item);
721 break;
722 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000723
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000724 bytes_processed += cmos_item->size;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000725
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000726 if (bytes_processed >= bytes_for_entries)
727 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000728
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000729 printf("\n");
730 }
731}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000732
733/****************************************************************************
734 * print_option_record
735 *
736 * Display "option" record from CMOS option table.
737 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000738static void print_option_record(const struct cmos_entries *cmos_entry)
739{
740 static const size_t S_BUFSIZE = 80;
741 char s[S_BUFSIZE];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000742
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000743 switch (cmos_entry->config) {
744 case 'e':
745 strcpy(s, "ENUM");
746 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000747
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000748 case 'h':
749 strcpy(s, "HEX");
750 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000751
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000752 case 'r':
753 strcpy(s, "RESERVED");
754 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000755
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000756 default:
757 snprintf(s, S_BUFSIZE, "UNKNOWN: value is 0x%x (decimal: %d)",
758 cmos_entry->config, cmos_entry->config);
759 break;
760 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000761
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000762 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}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000775
776/****************************************************************************
777 * print_enum_record
778 *
779 * Display "enum" record from CMOS option table.
780 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000781static 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}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000794
795/****************************************************************************
796 * print_defaults_record
797 *
798 * Display "defaults" record from CMOS option table.
799 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000800static 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}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000815
816/****************************************************************************
817 * print_unknown_record
818 *
819 * Display record of unknown type from CMOS option table.
820 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000821static void print_unknown_record(const struct lb_record *cmos_item)
822{
823 const char *data;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000824
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000825 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}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000835
836/****************************************************************************
837 * option_checksum_print_fn
838 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000839 * Display function for 'option_checksum' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000840 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000841static void option_checksum_print_fn(const struct lb_record *rec)
842{
843 struct cmos_checksum *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000844
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000845 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}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000851
852/****************************************************************************
853 * string_print_fn
854 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000855 * Display function for a generic item of coreboot table that simply
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000856 * consists of a string.
857 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000858static void string_print_fn(const struct lb_record *rec)
859{
860 const struct lb_string *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000861
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000862 p = (const struct lb_string *)rec;
863 printf("%s\n", p->string);
864}