blob: 5db61c507d60c0357b3e1776624099d235572b01 [file] [log] [blame]
Stefan Reinauer6540ae52007-07-12 16:35:42 +00001/*****************************************************************************\
2 * lbtable.c
Stefan Reinauer6540ae52007-07-12 16:35:42 +00003 *****************************************************************************
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>.
8 * UCRL-CODE-2003-012
9 * All rights reserved.
10 *
Uwe Hermann6e565942008-03-01 19:06:32 +000011 * This file is part of nvramtool, a utility for reading/writing coreboot
Stefan Reinauerf527e702008-01-18 15:33:49 +000012 * parameters and displaying information from the coreboot table.
Uwe Hermann6e565942008-03-01 19:06:32 +000013 * For details, see http://coreboot.org/nvramtool.
Stefan Reinauer6540ae52007-07-12 16:35:42 +000014 *
15 * Please also read the file DISCLAIMER which is included in this software
16 * distribution.
17 *
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.
21 *
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.
Stefan Reinauer6540ae52007-07-12 16:35:42 +000026\*****************************************************************************/
27
Stefan Reinauer9981cad2012-05-24 13:36:30 -070028#include <stdint.h>
29#include <inttypes.h>
Stefan Reinauer297b91c2008-09-18 14:49:33 +000030#include <string.h>
Zheng Bao54516722012-10-22 16:41:42 +080031#ifndef __MINGW32__
Stefan Reinauer6540ae52007-07-12 16:35:42 +000032#include <sys/mman.h>
Zheng Bao54516722012-10-22 16:41:42 +080033#endif
Stefan Reinauer6540ae52007-07-12 16:35:42 +000034#include "common.h"
Stefan Reinauer7223ab72008-01-18 16:17:44 +000035#include "coreboot_tables.h"
Stefan Reinauer6540ae52007-07-12 16:35:42 +000036#include "ip_checksum.h"
37#include "lbtable.h"
38#include "layout.h"
39#include "cmos_lowlevel.h"
40#include "hexdump.h"
Patrick Georgi269e9322011-01-21 07:24:08 +000041#include "cbfs.h"
Stefan Reinauer6540ae52007-07-12 16:35:42 +000042
Stefan Reinauer90b96b62010-01-13 21:00:23 +000043typedef void (*lbtable_print_fn_t) (const struct lb_record * rec);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000044
Stefan Reinauerf527e702008-01-18 15:33:49 +000045/* This structure represents an item in the coreboot table that may be
Stefan Reinauer6540ae52007-07-12 16:35:42 +000046 * displayed using the -l option.
47 */
Stefan Reinauer90b96b62010-01-13 21:00:23 +000048typedef struct {
49 uint32_t tag;
50 const char *name;
51 const char *description;
52 const char *nofound_msg;
53 lbtable_print_fn_t print_fn;
54} lbtable_choice_t;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000055
Stefan Reinauer90b96b62010-01-13 21:00:23 +000056typedef struct {
57 unsigned long start; /* address of first byte of memory range */
58 unsigned long end; /* address of last byte of memory range */
59} mem_range_t;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000060
Stefan Reinauer90b96b62010-01-13 21:00:23 +000061static const struct lb_header *lbtable_scan(unsigned long start,
62 unsigned long end,
63 int *bad_header_count,
64 int *bad_table_count);
Stefan Reinauer90b96b62010-01-13 21:00:23 +000065static const char *lbrec_tag_to_str(uint32_t tag);
Stefan Reinauer90b96b62010-01-13 21:00:23 +000066static void memory_print_fn(const struct lb_record *rec);
67static void mainboard_print_fn(const struct lb_record *rec);
68static void cmos_opt_table_print_fn(const struct lb_record *rec);
69static void print_option_record(const struct cmos_entries *cmos_entry);
70static void print_enum_record(const struct cmos_enums *cmos_enum);
71static void print_defaults_record(const struct cmos_defaults *cmos_defaults);
72static void print_unknown_record(const struct lb_record *cmos_item);
73static void option_checksum_print_fn(const struct lb_record *rec);
74static void string_print_fn(const struct lb_record *rec);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000075
76static const char memory_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000077 " This shows information about system memory.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000078
79static const char mainboard_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000080 " This shows information about your mainboard.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000081
82static const char version_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000083 " This shows coreboot version information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000084
85static const char extra_version_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000086 " This shows extra coreboot version information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000087
Stefan Reinauer90b96b62010-01-13 21:00:23 +000088static const char build_desc[] = " This shows coreboot build information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000089
90static const char compile_time_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000091 " This shows when coreboot was compiled.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000092
Stefan Reinauer90b96b62010-01-13 21:00:23 +000093static const char compile_by_desc[] = " This shows who compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000094
95static const char compile_host_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000096 " This shows the name of the machine that compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000097
98static const char compile_domain_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000099 " This shows the domain name of the machine that compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000100
101static const char compiler_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000102 " This shows the name of the compiler used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000103
104static const char linker_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000105 " This shows the name of the linker used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000106
107static const char assembler_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000108 " This shows the name of the assembler used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000109
110static const char cmos_opt_table_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000111 " This does a low-level dump of the CMOS option table. The table "
112 "contains\n"
113 " information about the layout of the values that coreboot stores in\n"
114 " nonvolatile RAM.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000115
116static const char option_checksum_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000117 " This shows the location of the CMOS checksum and the area over which it "
118 "is\n" " calculated.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000119
120static const char generic_nofound_msg[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000121 "%s: Item %s not found in coreboot table.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000122
123static const char nofound_msg_cmos_opt_table[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000124 "%s: Item %s not found in coreboot table. Apparently, the "
125 "coreboot installed on this system was built without specifying "
126 "CONFIG_HAVE_OPTION_TABLE.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000127
128static const char nofound_msg_option_checksum[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000129 "%s: Item %s not found in coreboot table. Apparently, you are "
130 "using coreboot v1.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000131
Stefan Reinauer764fe402009-03-17 14:39:36 +0000132int fd;
133
Stefan Reinauerf527e702008-01-18 15:33:49 +0000134/* This is the number of items from the coreboot table that may be displayed
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000135 * using the -l option.
136 */
137#define NUM_LBTABLE_CHOICES 14
138
Stefan Reinauerf527e702008-01-18 15:33:49 +0000139/* These represent the various items from the coreboot table that may be
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000140 * displayed using the -l option.
141 */
142static const lbtable_choice_t lbtable_choices[NUM_LBTABLE_CHOICES] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000143 { {LB_TAG_MEMORY, "memory",
144 memory_desc, generic_nofound_msg,
145 memory_print_fn},
146{LB_TAG_MAINBOARD, "mainboard",
147 mainboard_desc, generic_nofound_msg,
148 mainboard_print_fn},
149{LB_TAG_VERSION, "version",
150 version_desc, generic_nofound_msg,
151 string_print_fn},
152{LB_TAG_EXTRA_VERSION, "extra_version",
153 extra_version_desc, generic_nofound_msg,
154 string_print_fn},
155{LB_TAG_BUILD, "build",
156 build_desc, generic_nofound_msg,
157 string_print_fn},
158{LB_TAG_COMPILE_TIME, "compile_time",
159 compile_time_desc, generic_nofound_msg,
160 string_print_fn},
161{LB_TAG_COMPILE_BY, "compile_by",
162 compile_by_desc, generic_nofound_msg,
163 string_print_fn},
164{LB_TAG_COMPILE_HOST, "compile_host",
165 compile_host_desc, generic_nofound_msg,
166 string_print_fn},
167{LB_TAG_COMPILE_DOMAIN, "compile_domain",
168 compile_domain_desc, generic_nofound_msg,
169 string_print_fn},
170{LB_TAG_COMPILER, "compiler",
171 compiler_desc, generic_nofound_msg,
172 string_print_fn},
173{LB_TAG_LINKER, "linker",
174 linker_desc, generic_nofound_msg,
175 string_print_fn},
176{LB_TAG_ASSEMBLER, "assembler",
177 assembler_desc, generic_nofound_msg,
178 string_print_fn},
179{LB_TAG_CMOS_OPTION_TABLE, "cmos_opt_table",
180 cmos_opt_table_desc, nofound_msg_cmos_opt_table,
181 cmos_opt_table_print_fn},
182{LB_TAG_OPTION_CHECKSUM, "option_checksum",
183 option_checksum_desc, nofound_msg_option_checksum,
184 option_checksum_print_fn}
185};
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000186
Stefan Reinauerf527e702008-01-18 15:33:49 +0000187/* The coreboot table resides in low physical memory, which we access using
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000188 * /dev/mem. These are ranges of physical memory that should be scanned for a
Stefan Reinauerf527e702008-01-18 15:33:49 +0000189 * coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000190 */
191
192#define NUM_MEM_RANGES 2
193
194static const mem_range_t mem_ranges[NUM_MEM_RANGES] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000195 { {0x00000000, 0x00000fff},
196{0x000f0000, 0x000fffff}
197};
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000198
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000199/* Pointer to low physical memory that we access by calling mmap() on
200 * /dev/mem.
201 */
202static const void *low_phys_mem;
Patrick Georgi12781422013-02-21 14:03:47 +0100203/* impossible value since not page aligned: first map request will happen */
204static unsigned long low_phys_base = 0x1;
205
206/* count of mapped pages */
207static unsigned long mapped_pages = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000208
Stefan Reinauerf527e702008-01-18 15:33:49 +0000209/* Pointer to coreboot table. */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000210static const struct lb_header *lbtable = NULL;
211
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000212static const hexdump_format_t format =
Patrick Georgi024ec852011-01-18 12:14:08 +0000213 { 12, 4, " ", " | ", " ", " | ", '.' };
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000214
215/****************************************************************************
216 * vtophys
217 *
218 * Convert a virtual address to a physical address. 'vaddr' is a virtual
219 * address in the address space of the current process. It points to
220 * somewhere in the chunk of memory that we mapped by calling mmap() on
221 * /dev/mem. This macro converts 'vaddr' to a physical address.
222 ****************************************************************************/
223#define vtophys(vaddr) (((unsigned long) vaddr) - \
Stefan Reinauer764fe402009-03-17 14:39:36 +0000224 ((unsigned long) low_phys_mem) + low_phys_base)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000225
226/****************************************************************************
227 * phystov
228 *
229 * Convert a physical address to a virtual address. 'paddr' is a physical
230 * address. This macro converts 'paddr' to a virtual address in the address
231 * space of the current process. The virtual to physical mapping was set up
232 * by calling mmap() on /dev/mem.
233 ****************************************************************************/
234#define phystov(paddr) (((unsigned long) low_phys_mem) + \
Stefan Reinauer764fe402009-03-17 14:39:36 +0000235 ((unsigned long) paddr) - low_phys_base)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000236
237/****************************************************************************
Patrick Georgi12781422013-02-21 14:03:47 +0100238 * map_pages
239 *
240 * Maps just enough pages to cover base_address + length
241 * and updates affected variables
242 ****************************************************************************/
243static void map_pages(unsigned long base_address, unsigned long length)
244{
245 unsigned long num_pages = (length +
246 (base_address & (getpagesize() - 1)) +
247 getpagesize() - 1) >> 12;
248 base_address &= ~(getpagesize() - 1);
249
250 /* no need to do anything */
251 if ((low_phys_base == base_address) && (mapped_pages == num_pages)) {
252 return;
253 }
254
255 if (low_phys_mem) {
256 munmap((void *)low_phys_mem, mapped_pages << 12);
257 }
258 if ((low_phys_mem = mmap(NULL, num_pages << 12, PROT_READ, MAP_SHARED, fd,
259 (off_t) base_address)) == MAP_FAILED) {
260 fprintf(stderr,
261 "%s: Failed to mmap /dev/mem at %lx: %s\n",
262 prog_name, base_address, strerror(errno));
263 exit(1);
264 }
265 low_phys_base = base_address;
266}
267
268/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000269 * get_lbtable
270 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000271 * Find the coreboot table and set global variable lbtable to point to it.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000272 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000273void get_lbtable(void)
274{
275 int i, bad_header_count, bad_table_count, bad_headers, bad_tables;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000276
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000277 if (lbtable != NULL)
278 return;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000279
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000280 /* The coreboot table is located in low physical memory, which may be
281 * conveniently accessed by calling mmap() on /dev/mem.
282 */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000283
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000284 if ((fd = open("/dev/mem", O_RDONLY, 0)) < 0) {
285 fprintf(stderr, "%s: Can not open /dev/mem for reading: %s\n",
286 prog_name, strerror(errno));
287 exit(1);
288 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000289
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000290 bad_header_count = 0;
291 bad_table_count = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000292
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000293 for (i = 0; i < NUM_MEM_RANGES; i++) {
Patrick Georgi12781422013-02-21 14:03:47 +0100294 lbtable = lbtable_scan(mem_ranges[i].start, mem_ranges[i].end,
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000295 &bad_headers, &bad_tables);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000296
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000297 if (lbtable != NULL)
298 return; /* success: we found it! */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000299
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000300 bad_header_count += bad_headers;
301 bad_table_count += bad_tables;
302 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000303
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000304 fprintf(stderr,
305 "%s: coreboot table not found. coreboot does not appear to\n"
306 " be installed on this system. Scanning for the table "
307 "produced the\n"
308 " following results:\n\n"
309 " %d valid signatures were found with bad header "
310 "checksums.\n"
311 " %d valid headers were found with bad table "
312 "checksums.\n", prog_name, bad_header_count, bad_table_count);
313 exit(1);
314}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000315
316/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000317 * dump_lbtable
318 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000319 * Do a low-level dump of the coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000320 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000321void dump_lbtable(void)
322{
323 const char *p, *data;
324 uint32_t bytes_processed;
325 const struct lb_record *lbrec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000326
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000327 p = ((const char *)lbtable) + lbtable->header_bytes;
328 printf("Coreboot table at physical address 0x%lx:\n"
329 " signature: 0x%x (ASCII: %c%c%c%c)\n"
330 " header_bytes: 0x%x (decimal: %d)\n"
331 " header_checksum: 0x%x (decimal: %d)\n"
332 " table_bytes: 0x%x (decimal: %d)\n"
333 " table_checksum: 0x%x (decimal: %d)\n"
334 " table_entries: 0x%x (decimal: %d)\n\n",
Patrick Georgi26016972011-01-18 12:12:47 +0000335 vtophys(lbtable), lbtable->signature32,
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000336 lbtable->signature[0], lbtable->signature[1],
337 lbtable->signature[2], lbtable->signature[3],
338 lbtable->header_bytes, lbtable->header_bytes,
339 lbtable->header_checksum, lbtable->header_checksum,
340 lbtable->table_bytes, lbtable->table_bytes,
341 lbtable->table_checksum, lbtable->table_checksum,
342 lbtable->table_entries, lbtable->table_entries);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000343
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000344 if ((lbtable->table_bytes == 0) != (lbtable->table_entries == 0)) {
345 printf
346 ("Inconsistent values for table_bytes and table_entries!!!\n"
347 "They should be either both 0 or both nonzero.\n");
348 return;
349 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000350
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000351 if (lbtable->table_bytes == 0) {
352 printf("The coreboot table is empty!!!\n");
353 return;
354 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000355
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000356 for (bytes_processed = 0;;) {
357 lbrec = (const struct lb_record *)&p[bytes_processed];
358 printf(" %s record at physical address 0x%lx:\n"
359 " tag: 0x%x (decimal: %d)\n"
360 " size: 0x%x (decimal: %d)\n"
361 " data:\n",
362 lbrec_tag_to_str(lbrec->tag), vtophys(lbrec), lbrec->tag,
363 lbrec->tag, lbrec->size, lbrec->size);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000364
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000365 data = ((const char *)lbrec) + sizeof(*lbrec);
366 hexdump(data, lbrec->size - sizeof(*lbrec), vtophys(data),
367 stdout, &format);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000368
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000369 bytes_processed += lbrec->size;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000370
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000371 if (bytes_processed >= lbtable->table_bytes)
372 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000373
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000374 printf("\n");
375 }
376}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000377
378/****************************************************************************
379 * list_lbtable_choices
380 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000381 * List names and informational blurbs for items from the coreboot table
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000382 * that may be displayed using the -l option.
383 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000384void list_lbtable_choices(void)
385{
386 int i;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000387
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000388 for (i = 0;;) {
389 printf("%s:\n%s",
390 lbtable_choices[i].name, lbtable_choices[i].description);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000391
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000392 if (++i >= NUM_LBTABLE_CHOICES)
393 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000394
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000395 printf("\n");
396 }
397}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000398
399/****************************************************************************
400 * list_lbtable_item
401 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000402 * Show the coreboot table item specified by 'item'.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000403 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000404void list_lbtable_item(const char item[])
405{
406 int i;
407 const struct lb_record *rec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000408
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000409 for (i = 0; i < NUM_LBTABLE_CHOICES; i++) {
410 if (strcmp(item, lbtable_choices[i].name) == 0)
411 break;
412 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000413
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000414 if (i == NUM_LBTABLE_CHOICES) {
415 fprintf(stderr, "%s: Invalid coreboot table item %s.\n",
416 prog_name, item);
417 exit(1);
418 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000419
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000420 if ((rec = find_lbrec(lbtable_choices[i].tag)) == NULL) {
421 fprintf(stderr, lbtable_choices[i].nofound_msg, prog_name,
422 lbtable_choices[i].name);
423 exit(1);
424 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000425
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000426 lbtable_choices[i].print_fn(rec);
427}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000428
429/****************************************************************************
430 * lbtable_scan
431 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000432 * Scan the chunk of memory specified by 'start' and 'end' for a coreboot
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000433 * table. The first 4 bytes of the table are marked by the signature
434 * { 'L', 'B', 'I', 'O' }. 'start' and 'end' indicate the addresses of the
435 * first and last bytes of the chunk of memory to be scanned. For instance,
436 * values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k
437 * chunk of memory starting at address 0x10000000. 'start' and 'end' are
Patrick Georgi12781422013-02-21 14:03:47 +0100438 * physical addresses.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000439 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000440 * If a coreboot table is found, return a pointer to it. Otherwise return
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000441 * NULL. On return, *bad_header_count and *bad_table_count are set as
442 * follows:
443 *
444 * *bad_header_count:
445 * Indicates the number of times in which a valid signature was found
446 * but the header checksum was invalid.
447 *
448 * *bad_table_count:
449 * Indicates the number of times in which a header with a valid
450 * checksum was found but the table checksum was invalid.
451 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000452static const struct lb_header *lbtable_scan(unsigned long start,
453 unsigned long end,
454 int *bad_header_count,
455 int *bad_table_count)
456{
Patrick Georgi26016972011-01-18 12:12:47 +0000457 static const char signature[4] = { 'L', 'B', 'I', 'O' };
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000458 const struct lb_header *table;
459 const struct lb_forward *forward;
Patrick Georgi12781422013-02-21 14:03:47 +0100460 unsigned long p;
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000461 uint32_t sig;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000462
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000463 assert(end >= start);
Patrick Georgi26016972011-01-18 12:12:47 +0000464 memcpy(&sig, signature, sizeof(sig));
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000465 table = NULL;
466 *bad_header_count = 0;
467 *bad_table_count = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000468
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000469 /* Look for signature. Table is aligned on 16-byte boundary. Therefore
470 * only check every fourth 32-bit memory word. As the loop is coded below,
471 * this function will behave in a reasonable manner for ALL possible values
472 * for 'start' and 'end': even weird boundary cases like 0x00000000 and
473 * 0xffffffff on a 32-bit architecture.
474 */
Patrick Georgi12781422013-02-21 14:03:47 +0100475 map_pages(start, end - start);
476 for (p = start;
477 (p <= end) &&
478 (end - p >= (sizeof(uint32_t) - 1)); p += 4) {
479 if (*(uint32_t*)phystov(p) != sig)
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000480 continue;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000481
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000482 /* We found a valid signature. */
Patrick Georgi12781422013-02-21 14:03:47 +0100483 table = (const struct lb_header *)phystov(p);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000484
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000485 /* validate header checksum */
486 if (compute_ip_checksum((void *)table, sizeof(*table))) {
487 (*bad_header_count)++;
488 continue;
489 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000490
Patrick Georgi12781422013-02-21 14:03:47 +0100491 map_pages(p, table->table_bytes + sizeof(*table));
Timothy Pearson347234c2015-12-01 13:49:59 -0600492
493 table = (const struct lb_header *)phystov(p);
494
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000495 /* validate table checksum */
496 if (table->table_checksum !=
497 compute_ip_checksum(((char *)table) + sizeof(*table),
498 table->table_bytes)) {
499 (*bad_table_count)++;
500 continue;
501 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000502
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000503 /* checksums are ok: we found it! */
504 /* But it may just be a forwarding table, so look if there's a forwarder */
505 lbtable = table;
506 forward = (struct lb_forward *)find_lbrec(LB_TAG_FORWARD);
507 lbtable = NULL;
Stefan Reinauer764fe402009-03-17 14:39:36 +0000508
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000509 if (forward) {
510 uint64_t new_phys = forward->forward;
Patrick Georgi12781422013-02-21 14:03:47 +0100511 table = lbtable_scan(new_phys, new_phys + getpagesize(),
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000512 bad_header_count, bad_table_count);
513 }
514 return table;
515 }
516
517 return NULL;
518}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000519
520/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000521 * find_lbrec
522 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000523 * Find the record in the coreboot table that matches 'tag'. Return pointer
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000524 * to record on success or NULL if record not found.
525 ****************************************************************************/
Mathias Krause155c3792011-03-10 07:52:02 +0000526const struct lb_record *find_lbrec(uint32_t tag)
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000527{
528 const char *p;
529 uint32_t bytes_processed;
530 const struct lb_record *lbrec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000531
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000532 p = ((const char *)lbtable) + lbtable->header_bytes;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000533
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000534 for (bytes_processed = 0;
535 bytes_processed < lbtable->table_bytes;
536 bytes_processed += lbrec->size) {
537 lbrec = (const struct lb_record *)&p[bytes_processed];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000538
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000539 if (lbrec->tag == tag)
540 return lbrec;
541 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000542
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000543 return NULL;
544}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000545
546/****************************************************************************
547 * lbrec_tag_to_str
548 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000549 * Return a pointer to the string representation of the given coreboot table
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000550 * tag.
551 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000552static const char *lbrec_tag_to_str(uint32_t tag)
553{
554 switch (tag) {
555 case LB_TAG_UNUSED:
556 return "UNUSED";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000557
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000558 case LB_TAG_MEMORY:
559 return "MEMORY";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000560
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000561 case LB_TAG_HWRPB:
562 return "HWRPB";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000563
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000564 case LB_TAG_MAINBOARD:
565 return "MAINBOARD";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000566
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000567 case LB_TAG_VERSION:
568 return "VERSION";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000569
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000570 case LB_TAG_EXTRA_VERSION:
571 return "EXTRA_VERSION";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000572
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000573 case LB_TAG_BUILD:
574 return "BUILD";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000575
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000576 case LB_TAG_COMPILE_TIME:
577 return "COMPILE_TIME";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000578
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000579 case LB_TAG_COMPILE_BY:
580 return "COMPILE_BY";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000581
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000582 case LB_TAG_COMPILE_HOST:
583 return "COMPILE_HOST";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000584
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000585 case LB_TAG_COMPILE_DOMAIN:
586 return "COMPILE_DOMAIN";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000587
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000588 case LB_TAG_COMPILER:
589 return "COMPILER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000590
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000591 case LB_TAG_LINKER:
592 return "LINKER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000593
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000594 case LB_TAG_ASSEMBLER:
595 return "ASSEMBLER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000596
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000597 case LB_TAG_SERIAL:
598 return "SERIAL";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000599
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000600 case LB_TAG_CONSOLE:
601 return "CONSOLE";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000602
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000603 case LB_TAG_FORWARD:
604 return "FORWARD";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000605
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000606 case LB_TAG_CMOS_OPTION_TABLE:
607 return "CMOS_OPTION_TABLE";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000608
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000609 case LB_TAG_OPTION_CHECKSUM:
610 return "OPTION_CHECKSUM";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000611
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000612 default:
613 break;
614 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000615
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000616 return "UNKNOWN";
617}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000618
619/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000620 * memory_print_fn
621 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000622 * Display function for 'memory' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000623 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000624static void memory_print_fn(const struct lb_record *rec)
625{
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000626 const struct lb_memory *p;
627 const char *mem_type;
628 const struct lb_memory_range *ranges;
629 uint64_t size, start, end;
630 int i, entries;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000631
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000632 p = (const struct lb_memory *)rec;
633 entries = (p->size - sizeof(*p)) / sizeof(p->map[0]);
634 ranges = p->map;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000635
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000636 if (entries == 0) {
637 printf("No memory ranges were found.\n");
638 return;
639 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000640
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000641 for (i = 0;;) {
642 switch (ranges[i].type) {
643 case LB_MEM_RAM:
644 mem_type = "AVAILABLE";
645 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000646
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000647 case LB_MEM_RESERVED:
648 mem_type = "RESERVED";
649 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000650
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000651 case LB_MEM_TABLE:
652 mem_type = "CONFIG_TABLE";
653 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000654
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000655 default:
656 mem_type = "UNKNOWN";
657 break;
658 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000659
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000660 size = unpack_lb64(ranges[i].size);
661 start = unpack_lb64(ranges[i].start);
662 end = start + size - 1;
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000663 printf("%s memory:\n"
Stefan Reinauer9981cad2012-05-24 13:36:30 -0700664 " from physical addresses 0x%016" PRIx64
665 " to 0x%016" PRIx64 "\n size is 0x%016" PRIx64
666 " bytes (%" PRId64 " in decimal)\n",
667 mem_type, start, end, size, size);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000668
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000669 if (++i >= entries)
670 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000671
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000672 printf("\n");
673 }
674}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000675
676/****************************************************************************
677 * mainboard_print_fn
678 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000679 * Display function for 'mainboard' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000680 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000681static void mainboard_print_fn(const struct lb_record *rec)
682{
683 const struct lb_mainboard *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000684
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000685 p = (const struct lb_mainboard *)rec;
686 printf("Vendor: %s\n"
687 "Part number: %s\n",
688 &p->strings[p->vendor_idx], &p->strings[p->part_number_idx]);
689}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000690
691/****************************************************************************
692 * cmos_opt_table_print_fn
693 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000694 * Display function for 'cmos_opt_table' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000695 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000696static void cmos_opt_table_print_fn(const struct lb_record *rec)
697{
698 const struct cmos_option_table *p;
699 const struct lb_record *cmos_item;
700 uint32_t bytes_processed, bytes_for_entries;
701 const char *q;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000702
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000703 p = (const struct cmos_option_table *)rec;
704 q = ((const char *)p) + p->header_length;
705 bytes_for_entries = p->size - p->header_length;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000706
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000707 printf("CMOS option table at physical address 0x%lx:\n"
708 " tag: 0x%x (decimal: %d)\n"
709 " size: 0x%x (decimal: %d)\n"
710 " header_length: 0x%x (decimal: %d)\n\n",
711 vtophys(p), p->tag, p->tag, p->size, p->size, p->header_length,
712 p->header_length);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000713
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000714 if (p->header_length > p->size) {
715 printf
716 ("Header length for CMOS option table is greater than the size "
717 "of the entire table including header!!!\n");
718 return;
719 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000720
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000721 if (bytes_for_entries == 0) {
722 printf("The CMOS option table is empty!!!\n");
723 return;
724 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000725
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000726 for (bytes_processed = 0;;) {
727 cmos_item = (const struct lb_record *)&q[bytes_processed];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000728
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000729 switch (cmos_item->tag) {
730 case LB_TAG_OPTION:
731 print_option_record((const struct cmos_entries *)
732 cmos_item);
733 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000734
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000735 case LB_TAG_OPTION_ENUM:
736 print_enum_record((const struct cmos_enums *)cmos_item);
737 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000738
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000739 case LB_TAG_OPTION_DEFAULTS:
740 print_defaults_record((const struct cmos_defaults *)
741 cmos_item);
742 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000743
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000744 default:
745 print_unknown_record(cmos_item);
746 break;
747 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000748
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000749 bytes_processed += cmos_item->size;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000750
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000751 if (bytes_processed >= bytes_for_entries)
752 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000753
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000754 printf("\n");
755 }
756}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000757
758/****************************************************************************
759 * print_option_record
760 *
761 * Display "option" record from CMOS option table.
762 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000763static void print_option_record(const struct cmos_entries *cmos_entry)
764{
765 static const size_t S_BUFSIZE = 80;
766 char s[S_BUFSIZE];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000767
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000768 switch (cmos_entry->config) {
769 case 'e':
770 strcpy(s, "ENUM");
771 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000772
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000773 case 'h':
774 strcpy(s, "HEX");
775 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000776
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000777 case 'r':
778 strcpy(s, "RESERVED");
779 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000780
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000781 default:
782 snprintf(s, S_BUFSIZE, "UNKNOWN: value is 0x%x (decimal: %d)",
783 cmos_entry->config, cmos_entry->config);
784 break;
785 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000786
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000787 printf(" OPTION record at physical address 0x%lx:\n"
788 " tag: 0x%x (decimal: %d)\n"
789 " size: 0x%x (decimal: %d)\n"
790 " bit: 0x%x (decimal: %d)\n"
791 " length: 0x%x (decimal: %d)\n"
792 " config: %s\n"
793 " config_id: 0x%x (decimal: %d)\n"
794 " name: %s\n",
795 vtophys(cmos_entry), cmos_entry->tag, cmos_entry->tag,
796 cmos_entry->size, cmos_entry->size, cmos_entry->bit,
797 cmos_entry->bit, cmos_entry->length, cmos_entry->length, s,
798 cmos_entry->config_id, cmos_entry->config_id, cmos_entry->name);
799}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000800
801/****************************************************************************
802 * print_enum_record
803 *
804 * Display "enum" record from CMOS option table.
805 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000806static void print_enum_record(const struct cmos_enums *cmos_enum)
807{
808 printf(" ENUM record at physical address 0x%lx:\n"
809 " tag: 0x%x (decimal: %d)\n"
810 " size: 0x%x (decimal: %d)\n"
811 " config_id: 0x%x (decimal: %d)\n"
812 " value: 0x%x (decimal: %d)\n"
813 " text: %s\n",
814 vtophys(cmos_enum), cmos_enum->tag, cmos_enum->tag,
815 cmos_enum->size, cmos_enum->size, cmos_enum->config_id,
816 cmos_enum->config_id, cmos_enum->value, cmos_enum->value,
817 cmos_enum->text);
818}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000819
820/****************************************************************************
821 * print_defaults_record
822 *
823 * Display "defaults" record from CMOS option table.
824 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000825static void print_defaults_record(const struct cmos_defaults *cmos_defaults)
826{
827 printf(" DEFAULTS record at physical address 0x%lx:\n"
828 " tag: 0x%x (decimal: %d)\n"
829 " size: 0x%x (decimal: %d)\n"
830 " name_length: 0x%x (decimal: %d)\n"
831 " name: %s\n"
832 " default_set:\n",
833 vtophys(cmos_defaults), cmos_defaults->tag, cmos_defaults->tag,
834 cmos_defaults->size, cmos_defaults->size,
835 cmos_defaults->name_length, cmos_defaults->name_length,
836 cmos_defaults->name);
837 hexdump(cmos_defaults->default_set, CMOS_IMAGE_BUFFER_SIZE,
838 vtophys(cmos_defaults->default_set), stdout, &format);
839}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000840
841/****************************************************************************
842 * print_unknown_record
843 *
844 * Display record of unknown type from CMOS option table.
845 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000846static void print_unknown_record(const struct lb_record *cmos_item)
847{
848 const char *data;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000849
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000850 printf(" UNKNOWN record at physical address 0x%lx:\n"
851 " tag: 0x%x (decimal: %d)\n"
852 " size: 0x%x (decimal: %d)\n"
853 " data:\n",
854 vtophys(cmos_item), cmos_item->tag, cmos_item->tag,
855 cmos_item->size, cmos_item->size);
856 data = ((const char *)cmos_item) + sizeof(*cmos_item);
857 hexdump(data, cmos_item->size - sizeof(*cmos_item), vtophys(data),
858 stdout, &format);
859}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000860
861/****************************************************************************
862 * option_checksum_print_fn
863 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000864 * Display function for 'option_checksum' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000865 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000866static void option_checksum_print_fn(const struct lb_record *rec)
867{
868 struct cmos_checksum *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000869
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000870 p = (struct cmos_checksum *)rec;
871 printf("CMOS checksum from bit %d to bit %d\n"
872 "at position %d is type %s.\n",
873 p->range_start, p->range_end, p->location,
874 (p->type == CHECKSUM_PCBIOS) ? "PC BIOS" : "NONE");
875}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000876
877/****************************************************************************
878 * string_print_fn
879 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000880 * Display function for a generic item of coreboot table that simply
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000881 * consists of a string.
882 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000883static void string_print_fn(const struct lb_record *rec)
884{
885 const struct lb_string *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000886
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000887 p = (const struct lb_string *)rec;
888 printf("%s\n", p->string);
889}