blob: 5f1f22d90be336486d19196ef9ceba2e95c05ab7 [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.
26 *
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.,
Stefan Reinauerac7a2d22009-09-23 21:53:25 +000029 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Stefan Reinauer6540ae52007-07-12 16:35:42 +000030\*****************************************************************************/
31
Stefan Reinauer9981cad2012-05-24 13:36:30 -070032#include <stdint.h>
33#include <inttypes.h>
Stefan Reinauer297b91c2008-09-18 14:49:33 +000034#include <string.h>
Zheng Bao54516722012-10-22 16:41:42 +080035#ifndef __MINGW32__
Stefan Reinauer6540ae52007-07-12 16:35:42 +000036#include <sys/mman.h>
Zheng Bao54516722012-10-22 16:41:42 +080037#endif
Stefan Reinauer6540ae52007-07-12 16:35:42 +000038#include "common.h"
Stefan Reinauer7223ab72008-01-18 16:17:44 +000039#include "coreboot_tables.h"
Stefan Reinauer6540ae52007-07-12 16:35:42 +000040#include "ip_checksum.h"
41#include "lbtable.h"
42#include "layout.h"
43#include "cmos_lowlevel.h"
44#include "hexdump.h"
Patrick Georgi269e9322011-01-21 07:24:08 +000045#include "cbfs.h"
Stefan Reinauer6540ae52007-07-12 16:35:42 +000046
Stefan Reinauer90b96b62010-01-13 21:00:23 +000047typedef void (*lbtable_print_fn_t) (const struct lb_record * rec);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000048
Stefan Reinauerf527e702008-01-18 15:33:49 +000049/* This structure represents an item in the coreboot table that may be
Stefan Reinauer6540ae52007-07-12 16:35:42 +000050 * displayed using the -l option.
51 */
Stefan Reinauer90b96b62010-01-13 21:00:23 +000052typedef struct {
53 uint32_t tag;
54 const char *name;
55 const char *description;
56 const char *nofound_msg;
57 lbtable_print_fn_t print_fn;
58} lbtable_choice_t;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000059
Stefan Reinauer90b96b62010-01-13 21:00:23 +000060typedef struct {
61 unsigned long start; /* address of first byte of memory range */
62 unsigned long end; /* address of last byte of memory range */
63} mem_range_t;
Stefan Reinauer6540ae52007-07-12 16:35:42 +000064
Stefan Reinauer90b96b62010-01-13 21:00:23 +000065static const struct lb_header *lbtable_scan(unsigned long start,
66 unsigned long end,
67 int *bad_header_count,
68 int *bad_table_count);
Stefan Reinauer90b96b62010-01-13 21:00:23 +000069static const char *lbrec_tag_to_str(uint32_t tag);
Stefan Reinauer90b96b62010-01-13 21:00:23 +000070static void memory_print_fn(const struct lb_record *rec);
71static void mainboard_print_fn(const struct lb_record *rec);
72static void cmos_opt_table_print_fn(const struct lb_record *rec);
73static void print_option_record(const struct cmos_entries *cmos_entry);
74static void print_enum_record(const struct cmos_enums *cmos_enum);
75static void print_defaults_record(const struct cmos_defaults *cmos_defaults);
76static void print_unknown_record(const struct lb_record *cmos_item);
77static void option_checksum_print_fn(const struct lb_record *rec);
78static void string_print_fn(const struct lb_record *rec);
Stefan Reinauer6540ae52007-07-12 16:35:42 +000079
80static const char memory_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000081 " This shows information about system memory.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000082
83static const char mainboard_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000084 " This shows information about your mainboard.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000085
86static const char version_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000087 " This shows coreboot version information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000088
89static const char extra_version_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000090 " This shows extra coreboot version information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000091
Stefan Reinauer90b96b62010-01-13 21:00:23 +000092static const char build_desc[] = " This shows coreboot build information.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000093
94static const char compile_time_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +000095 " This shows when coreboot was compiled.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000096
Stefan Reinauer90b96b62010-01-13 21:00:23 +000097static const char compile_by_desc[] = " This shows who compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +000098
99static const char compile_host_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000100 " This shows the name of the machine that compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000101
102static const char compile_domain_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000103 " This shows the domain name of the machine that compiled coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000104
105static const char compiler_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000106 " This shows the name of the compiler used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000107
108static const char linker_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000109 " This shows the name of the linker used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000110
111static const char assembler_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000112 " This shows the name of the assembler used to build coreboot.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000113
114static const char cmos_opt_table_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000115 " This does a low-level dump of the CMOS option table. The table "
116 "contains\n"
117 " information about the layout of the values that coreboot stores in\n"
118 " nonvolatile RAM.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000119
120static const char option_checksum_desc[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000121 " This shows the location of the CMOS checksum and the area over which it "
122 "is\n" " calculated.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000123
124static const char generic_nofound_msg[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000125 "%s: Item %s not found in coreboot table.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000126
127static const char nofound_msg_cmos_opt_table[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000128 "%s: Item %s not found in coreboot table. Apparently, the "
129 "coreboot installed on this system was built without specifying "
130 "CONFIG_HAVE_OPTION_TABLE.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000131
132static const char nofound_msg_option_checksum[] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000133 "%s: Item %s not found in coreboot table. Apparently, you are "
134 "using coreboot v1.\n";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000135
Stefan Reinauer764fe402009-03-17 14:39:36 +0000136int fd;
137
Stefan Reinauerf527e702008-01-18 15:33:49 +0000138/* This is the number of items from the coreboot table that may be displayed
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000139 * using the -l option.
140 */
141#define NUM_LBTABLE_CHOICES 14
142
Stefan Reinauerf527e702008-01-18 15:33:49 +0000143/* These represent the various items from the coreboot table that may be
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000144 * displayed using the -l option.
145 */
146static const lbtable_choice_t lbtable_choices[NUM_LBTABLE_CHOICES] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000147 { {LB_TAG_MEMORY, "memory",
148 memory_desc, generic_nofound_msg,
149 memory_print_fn},
150{LB_TAG_MAINBOARD, "mainboard",
151 mainboard_desc, generic_nofound_msg,
152 mainboard_print_fn},
153{LB_TAG_VERSION, "version",
154 version_desc, generic_nofound_msg,
155 string_print_fn},
156{LB_TAG_EXTRA_VERSION, "extra_version",
157 extra_version_desc, generic_nofound_msg,
158 string_print_fn},
159{LB_TAG_BUILD, "build",
160 build_desc, generic_nofound_msg,
161 string_print_fn},
162{LB_TAG_COMPILE_TIME, "compile_time",
163 compile_time_desc, generic_nofound_msg,
164 string_print_fn},
165{LB_TAG_COMPILE_BY, "compile_by",
166 compile_by_desc, generic_nofound_msg,
167 string_print_fn},
168{LB_TAG_COMPILE_HOST, "compile_host",
169 compile_host_desc, generic_nofound_msg,
170 string_print_fn},
171{LB_TAG_COMPILE_DOMAIN, "compile_domain",
172 compile_domain_desc, generic_nofound_msg,
173 string_print_fn},
174{LB_TAG_COMPILER, "compiler",
175 compiler_desc, generic_nofound_msg,
176 string_print_fn},
177{LB_TAG_LINKER, "linker",
178 linker_desc, generic_nofound_msg,
179 string_print_fn},
180{LB_TAG_ASSEMBLER, "assembler",
181 assembler_desc, generic_nofound_msg,
182 string_print_fn},
183{LB_TAG_CMOS_OPTION_TABLE, "cmos_opt_table",
184 cmos_opt_table_desc, nofound_msg_cmos_opt_table,
185 cmos_opt_table_print_fn},
186{LB_TAG_OPTION_CHECKSUM, "option_checksum",
187 option_checksum_desc, nofound_msg_option_checksum,
188 option_checksum_print_fn}
189};
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000190
Stefan Reinauerf527e702008-01-18 15:33:49 +0000191/* The coreboot table resides in low physical memory, which we access using
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000192 * /dev/mem. These are ranges of physical memory that should be scanned for a
Stefan Reinauerf527e702008-01-18 15:33:49 +0000193 * coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000194 */
195
196#define NUM_MEM_RANGES 2
197
198static const mem_range_t mem_ranges[NUM_MEM_RANGES] =
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000199 { {0x00000000, 0x00000fff},
200{0x000f0000, 0x000fffff}
201};
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000202
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000203/* Pointer to low physical memory that we access by calling mmap() on
204 * /dev/mem.
205 */
206static const void *low_phys_mem;
Patrick Georgi12781422013-02-21 14:03:47 +0100207/* impossible value since not page aligned: first map request will happen */
208static unsigned long low_phys_base = 0x1;
209
210/* count of mapped pages */
211static unsigned long mapped_pages = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000212
Stefan Reinauerf527e702008-01-18 15:33:49 +0000213/* Pointer to coreboot table. */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000214static const struct lb_header *lbtable = NULL;
215
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000216static const hexdump_format_t format =
Patrick Georgi024ec852011-01-18 12:14:08 +0000217 { 12, 4, " ", " | ", " ", " | ", '.' };
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000218
219/****************************************************************************
220 * vtophys
221 *
222 * Convert a virtual address to a physical address. 'vaddr' is a virtual
223 * address in the address space of the current process. It points to
224 * somewhere in the chunk of memory that we mapped by calling mmap() on
225 * /dev/mem. This macro converts 'vaddr' to a physical address.
226 ****************************************************************************/
227#define vtophys(vaddr) (((unsigned long) vaddr) - \
Stefan Reinauer764fe402009-03-17 14:39:36 +0000228 ((unsigned long) low_phys_mem) + low_phys_base)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000229
230/****************************************************************************
231 * phystov
232 *
233 * Convert a physical address to a virtual address. 'paddr' is a physical
234 * address. This macro converts 'paddr' to a virtual address in the address
235 * space of the current process. The virtual to physical mapping was set up
236 * by calling mmap() on /dev/mem.
237 ****************************************************************************/
238#define phystov(paddr) (((unsigned long) low_phys_mem) + \
Stefan Reinauer764fe402009-03-17 14:39:36 +0000239 ((unsigned long) paddr) - low_phys_base)
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000240
241/****************************************************************************
Patrick Georgi12781422013-02-21 14:03:47 +0100242 * map_pages
243 *
244 * Maps just enough pages to cover base_address + length
245 * and updates affected variables
246 ****************************************************************************/
247static void map_pages(unsigned long base_address, unsigned long length)
248{
249 unsigned long num_pages = (length +
250 (base_address & (getpagesize() - 1)) +
251 getpagesize() - 1) >> 12;
252 base_address &= ~(getpagesize() - 1);
253
254 /* no need to do anything */
255 if ((low_phys_base == base_address) && (mapped_pages == num_pages)) {
256 return;
257 }
258
259 if (low_phys_mem) {
260 munmap((void *)low_phys_mem, mapped_pages << 12);
261 }
262 if ((low_phys_mem = mmap(NULL, num_pages << 12, PROT_READ, MAP_SHARED, fd,
263 (off_t) base_address)) == MAP_FAILED) {
264 fprintf(stderr,
265 "%s: Failed to mmap /dev/mem at %lx: %s\n",
266 prog_name, base_address, strerror(errno));
267 exit(1);
268 }
269 low_phys_base = base_address;
270}
271
272/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000273 * get_lbtable
274 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000275 * Find the coreboot table and set global variable lbtable to point to it.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000276 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000277void get_lbtable(void)
278{
279 int i, bad_header_count, bad_table_count, bad_headers, bad_tables;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000280
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000281 if (lbtable != NULL)
282 return;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000283
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000284 /* The coreboot table is located in low physical memory, which may be
285 * conveniently accessed by calling mmap() on /dev/mem.
286 */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000287
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000288 if ((fd = open("/dev/mem", O_RDONLY, 0)) < 0) {
289 fprintf(stderr, "%s: Can not open /dev/mem for reading: %s\n",
290 prog_name, strerror(errno));
291 exit(1);
292 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000293
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000294 bad_header_count = 0;
295 bad_table_count = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000296
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000297 for (i = 0; i < NUM_MEM_RANGES; i++) {
Patrick Georgi12781422013-02-21 14:03:47 +0100298 lbtable = lbtable_scan(mem_ranges[i].start, mem_ranges[i].end,
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000299 &bad_headers, &bad_tables);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000300
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000301 if (lbtable != NULL)
302 return; /* success: we found it! */
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000303
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000304 bad_header_count += bad_headers;
305 bad_table_count += bad_tables;
306 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000307
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000308 fprintf(stderr,
309 "%s: coreboot table not found. coreboot does not appear to\n"
310 " be installed on this system. Scanning for the table "
311 "produced the\n"
312 " following results:\n\n"
313 " %d valid signatures were found with bad header "
314 "checksums.\n"
315 " %d valid headers were found with bad table "
316 "checksums.\n", prog_name, bad_header_count, bad_table_count);
317 exit(1);
318}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000319
320/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000321 * dump_lbtable
322 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000323 * Do a low-level dump of the coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000324 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000325void dump_lbtable(void)
326{
327 const char *p, *data;
328 uint32_t bytes_processed;
329 const struct lb_record *lbrec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000330
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000331 p = ((const char *)lbtable) + lbtable->header_bytes;
332 printf("Coreboot table at physical address 0x%lx:\n"
333 " signature: 0x%x (ASCII: %c%c%c%c)\n"
334 " header_bytes: 0x%x (decimal: %d)\n"
335 " header_checksum: 0x%x (decimal: %d)\n"
336 " table_bytes: 0x%x (decimal: %d)\n"
337 " table_checksum: 0x%x (decimal: %d)\n"
338 " table_entries: 0x%x (decimal: %d)\n\n",
Patrick Georgi26016972011-01-18 12:12:47 +0000339 vtophys(lbtable), lbtable->signature32,
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000340 lbtable->signature[0], lbtable->signature[1],
341 lbtable->signature[2], lbtable->signature[3],
342 lbtable->header_bytes, lbtable->header_bytes,
343 lbtable->header_checksum, lbtable->header_checksum,
344 lbtable->table_bytes, lbtable->table_bytes,
345 lbtable->table_checksum, lbtable->table_checksum,
346 lbtable->table_entries, lbtable->table_entries);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000347
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000348 if ((lbtable->table_bytes == 0) != (lbtable->table_entries == 0)) {
349 printf
350 ("Inconsistent values for table_bytes and table_entries!!!\n"
351 "They should be either both 0 or both nonzero.\n");
352 return;
353 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000354
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000355 if (lbtable->table_bytes == 0) {
356 printf("The coreboot table is empty!!!\n");
357 return;
358 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000359
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000360 for (bytes_processed = 0;;) {
361 lbrec = (const struct lb_record *)&p[bytes_processed];
362 printf(" %s record at physical address 0x%lx:\n"
363 " tag: 0x%x (decimal: %d)\n"
364 " size: 0x%x (decimal: %d)\n"
365 " data:\n",
366 lbrec_tag_to_str(lbrec->tag), vtophys(lbrec), lbrec->tag,
367 lbrec->tag, lbrec->size, lbrec->size);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000368
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000369 data = ((const char *)lbrec) + sizeof(*lbrec);
370 hexdump(data, lbrec->size - sizeof(*lbrec), vtophys(data),
371 stdout, &format);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000372
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000373 bytes_processed += lbrec->size;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000374
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000375 if (bytes_processed >= lbtable->table_bytes)
376 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000377
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000378 printf("\n");
379 }
380}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000381
382/****************************************************************************
383 * list_lbtable_choices
384 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000385 * List names and informational blurbs for items from the coreboot table
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000386 * that may be displayed using the -l option.
387 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000388void list_lbtable_choices(void)
389{
390 int i;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000391
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000392 for (i = 0;;) {
393 printf("%s:\n%s",
394 lbtable_choices[i].name, lbtable_choices[i].description);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000395
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000396 if (++i >= NUM_LBTABLE_CHOICES)
397 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000398
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000399 printf("\n");
400 }
401}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000402
403/****************************************************************************
404 * list_lbtable_item
405 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000406 * Show the coreboot table item specified by 'item'.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000407 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000408void list_lbtable_item(const char item[])
409{
410 int i;
411 const struct lb_record *rec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000412
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000413 for (i = 0; i < NUM_LBTABLE_CHOICES; i++) {
414 if (strcmp(item, lbtable_choices[i].name) == 0)
415 break;
416 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000417
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000418 if (i == NUM_LBTABLE_CHOICES) {
419 fprintf(stderr, "%s: Invalid coreboot table item %s.\n",
420 prog_name, item);
421 exit(1);
422 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000423
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000424 if ((rec = find_lbrec(lbtable_choices[i].tag)) == NULL) {
425 fprintf(stderr, lbtable_choices[i].nofound_msg, prog_name,
426 lbtable_choices[i].name);
427 exit(1);
428 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000429
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000430 lbtable_choices[i].print_fn(rec);
431}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000432
433/****************************************************************************
434 * lbtable_scan
435 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000436 * Scan the chunk of memory specified by 'start' and 'end' for a coreboot
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000437 * table. The first 4 bytes of the table are marked by the signature
438 * { 'L', 'B', 'I', 'O' }. 'start' and 'end' indicate the addresses of the
439 * first and last bytes of the chunk of memory to be scanned. For instance,
440 * values of 0x10000000 and 0x1000ffff for 'start' and 'end' specify a 64k
441 * chunk of memory starting at address 0x10000000. 'start' and 'end' are
Patrick Georgi12781422013-02-21 14:03:47 +0100442 * physical addresses.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000443 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000444 * If a coreboot table is found, return a pointer to it. Otherwise return
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000445 * NULL. On return, *bad_header_count and *bad_table_count are set as
446 * follows:
447 *
448 * *bad_header_count:
449 * Indicates the number of times in which a valid signature was found
450 * but the header checksum was invalid.
451 *
452 * *bad_table_count:
453 * Indicates the number of times in which a header with a valid
454 * checksum was found but the table checksum was invalid.
455 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000456static const struct lb_header *lbtable_scan(unsigned long start,
457 unsigned long end,
458 int *bad_header_count,
459 int *bad_table_count)
460{
Patrick Georgi26016972011-01-18 12:12:47 +0000461 static const char signature[4] = { 'L', 'B', 'I', 'O' };
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000462 const struct lb_header *table;
463 const struct lb_forward *forward;
Patrick Georgi12781422013-02-21 14:03:47 +0100464 unsigned long p;
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000465 uint32_t sig;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000466
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000467 assert(end >= start);
Patrick Georgi26016972011-01-18 12:12:47 +0000468 memcpy(&sig, signature, sizeof(sig));
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000469 table = NULL;
470 *bad_header_count = 0;
471 *bad_table_count = 0;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000472
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000473 /* Look for signature. Table is aligned on 16-byte boundary. Therefore
474 * only check every fourth 32-bit memory word. As the loop is coded below,
475 * this function will behave in a reasonable manner for ALL possible values
476 * for 'start' and 'end': even weird boundary cases like 0x00000000 and
477 * 0xffffffff on a 32-bit architecture.
478 */
Patrick Georgi12781422013-02-21 14:03:47 +0100479 map_pages(start, end - start);
480 for (p = start;
481 (p <= end) &&
482 (end - p >= (sizeof(uint32_t) - 1)); p += 4) {
483 if (*(uint32_t*)phystov(p) != sig)
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000484 continue;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000485
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000486 /* We found a valid signature. */
Patrick Georgi12781422013-02-21 14:03:47 +0100487 table = (const struct lb_header *)phystov(p);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000488
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000489 /* validate header checksum */
490 if (compute_ip_checksum((void *)table, sizeof(*table))) {
491 (*bad_header_count)++;
492 continue;
493 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000494
Patrick Georgi12781422013-02-21 14:03:47 +0100495 map_pages(p, table->table_bytes + sizeof(*table));
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000496 /* validate table checksum */
497 if (table->table_checksum !=
498 compute_ip_checksum(((char *)table) + sizeof(*table),
499 table->table_bytes)) {
500 (*bad_table_count)++;
501 continue;
502 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000503
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000504 /* checksums are ok: we found it! */
505 /* But it may just be a forwarding table, so look if there's a forwarder */
506 lbtable = table;
507 forward = (struct lb_forward *)find_lbrec(LB_TAG_FORWARD);
508 lbtable = NULL;
Stefan Reinauer764fe402009-03-17 14:39:36 +0000509
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000510 if (forward) {
511 uint64_t new_phys = forward->forward;
Patrick Georgi12781422013-02-21 14:03:47 +0100512 table = lbtable_scan(new_phys, new_phys + getpagesize(),
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000513 bad_header_count, bad_table_count);
514 }
515 return table;
516 }
517
518 return NULL;
519}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000520
521/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000522 * find_lbrec
523 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000524 * Find the record in the coreboot table that matches 'tag'. Return pointer
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000525 * to record on success or NULL if record not found.
526 ****************************************************************************/
Mathias Krause155c3792011-03-10 07:52:02 +0000527const struct lb_record *find_lbrec(uint32_t tag)
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000528{
529 const char *p;
530 uint32_t bytes_processed;
531 const struct lb_record *lbrec;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000532
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000533 p = ((const char *)lbtable) + lbtable->header_bytes;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000534
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000535 for (bytes_processed = 0;
536 bytes_processed < lbtable->table_bytes;
537 bytes_processed += lbrec->size) {
538 lbrec = (const struct lb_record *)&p[bytes_processed];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000539
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000540 if (lbrec->tag == tag)
541 return lbrec;
542 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000543
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000544 return NULL;
545}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000546
547/****************************************************************************
548 * lbrec_tag_to_str
549 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000550 * Return a pointer to the string representation of the given coreboot table
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000551 * tag.
552 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000553static const char *lbrec_tag_to_str(uint32_t tag)
554{
555 switch (tag) {
556 case LB_TAG_UNUSED:
557 return "UNUSED";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000558
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000559 case LB_TAG_MEMORY:
560 return "MEMORY";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000561
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000562 case LB_TAG_HWRPB:
563 return "HWRPB";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000564
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000565 case LB_TAG_MAINBOARD:
566 return "MAINBOARD";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000567
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000568 case LB_TAG_VERSION:
569 return "VERSION";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000570
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000571 case LB_TAG_EXTRA_VERSION:
572 return "EXTRA_VERSION";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000573
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000574 case LB_TAG_BUILD:
575 return "BUILD";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000576
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000577 case LB_TAG_COMPILE_TIME:
578 return "COMPILE_TIME";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000579
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000580 case LB_TAG_COMPILE_BY:
581 return "COMPILE_BY";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000582
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000583 case LB_TAG_COMPILE_HOST:
584 return "COMPILE_HOST";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000585
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000586 case LB_TAG_COMPILE_DOMAIN:
587 return "COMPILE_DOMAIN";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000588
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000589 case LB_TAG_COMPILER:
590 return "COMPILER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000591
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000592 case LB_TAG_LINKER:
593 return "LINKER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000594
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000595 case LB_TAG_ASSEMBLER:
596 return "ASSEMBLER";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000597
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000598 case LB_TAG_SERIAL:
599 return "SERIAL";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000600
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000601 case LB_TAG_CONSOLE:
602 return "CONSOLE";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000603
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000604 case LB_TAG_FORWARD:
605 return "FORWARD";
Stefan Reinauer764fe402009-03-17 14:39:36 +0000606
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000607 case LB_TAG_CMOS_OPTION_TABLE:
608 return "CMOS_OPTION_TABLE";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000609
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000610 case LB_TAG_OPTION_CHECKSUM:
611 return "OPTION_CHECKSUM";
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000612
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000613 default:
614 break;
615 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000616
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000617 return "UNKNOWN";
618}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000619
620/****************************************************************************
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000621 * memory_print_fn
622 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000623 * Display function for 'memory' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000624 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000625static void memory_print_fn(const struct lb_record *rec)
626{
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000627 const struct lb_memory *p;
628 const char *mem_type;
629 const struct lb_memory_range *ranges;
630 uint64_t size, start, end;
631 int i, entries;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000632
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000633 p = (const struct lb_memory *)rec;
634 entries = (p->size - sizeof(*p)) / sizeof(p->map[0]);
635 ranges = p->map;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000636
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000637 if (entries == 0) {
638 printf("No memory ranges were found.\n");
639 return;
640 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000641
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000642 for (i = 0;;) {
643 switch (ranges[i].type) {
644 case LB_MEM_RAM:
645 mem_type = "AVAILABLE";
646 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000647
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000648 case LB_MEM_RESERVED:
649 mem_type = "RESERVED";
650 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000651
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000652 case LB_MEM_TABLE:
653 mem_type = "CONFIG_TABLE";
654 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000655
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000656 default:
657 mem_type = "UNKNOWN";
658 break;
659 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000660
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000661 size = unpack_lb64(ranges[i].size);
662 start = unpack_lb64(ranges[i].start);
663 end = start + size - 1;
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000664 printf("%s memory:\n"
Stefan Reinauer9981cad2012-05-24 13:36:30 -0700665 " from physical addresses 0x%016" PRIx64
666 " to 0x%016" PRIx64 "\n size is 0x%016" PRIx64
667 " bytes (%" PRId64 " in decimal)\n",
668 mem_type, start, end, size, size);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000669
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000670 if (++i >= entries)
671 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000672
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000673 printf("\n");
674 }
675}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000676
677/****************************************************************************
678 * mainboard_print_fn
679 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000680 * Display function for 'mainboard' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000681 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000682static void mainboard_print_fn(const struct lb_record *rec)
683{
684 const struct lb_mainboard *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000685
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000686 p = (const struct lb_mainboard *)rec;
687 printf("Vendor: %s\n"
688 "Part number: %s\n",
689 &p->strings[p->vendor_idx], &p->strings[p->part_number_idx]);
690}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000691
692/****************************************************************************
693 * cmos_opt_table_print_fn
694 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000695 * Display function for 'cmos_opt_table' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000696 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000697static void cmos_opt_table_print_fn(const struct lb_record *rec)
698{
699 const struct cmos_option_table *p;
700 const struct lb_record *cmos_item;
701 uint32_t bytes_processed, bytes_for_entries;
702 const char *q;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000703
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000704 p = (const struct cmos_option_table *)rec;
705 q = ((const char *)p) + p->header_length;
706 bytes_for_entries = p->size - p->header_length;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000707
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000708 printf("CMOS option table at physical address 0x%lx:\n"
709 " tag: 0x%x (decimal: %d)\n"
710 " size: 0x%x (decimal: %d)\n"
711 " header_length: 0x%x (decimal: %d)\n\n",
712 vtophys(p), p->tag, p->tag, p->size, p->size, p->header_length,
713 p->header_length);
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000714
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000715 if (p->header_length > p->size) {
716 printf
717 ("Header length for CMOS option table is greater than the size "
718 "of the entire table including header!!!\n");
719 return;
720 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000721
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000722 if (bytes_for_entries == 0) {
723 printf("The CMOS option table is empty!!!\n");
724 return;
725 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000726
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000727 for (bytes_processed = 0;;) {
728 cmos_item = (const struct lb_record *)&q[bytes_processed];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000729
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000730 switch (cmos_item->tag) {
731 case LB_TAG_OPTION:
732 print_option_record((const struct cmos_entries *)
733 cmos_item);
734 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000735
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000736 case LB_TAG_OPTION_ENUM:
737 print_enum_record((const struct cmos_enums *)cmos_item);
738 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000739
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000740 case LB_TAG_OPTION_DEFAULTS:
741 print_defaults_record((const struct cmos_defaults *)
742 cmos_item);
743 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000744
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000745 default:
746 print_unknown_record(cmos_item);
747 break;
748 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000749
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000750 bytes_processed += cmos_item->size;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000751
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000752 if (bytes_processed >= bytes_for_entries)
753 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000754
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000755 printf("\n");
756 }
757}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000758
759/****************************************************************************
760 * print_option_record
761 *
762 * Display "option" record from CMOS option table.
763 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000764static void print_option_record(const struct cmos_entries *cmos_entry)
765{
766 static const size_t S_BUFSIZE = 80;
767 char s[S_BUFSIZE];
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000768
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000769 switch (cmos_entry->config) {
770 case 'e':
771 strcpy(s, "ENUM");
772 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000773
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000774 case 'h':
775 strcpy(s, "HEX");
776 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000777
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000778 case 'r':
779 strcpy(s, "RESERVED");
780 break;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000781
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000782 default:
783 snprintf(s, S_BUFSIZE, "UNKNOWN: value is 0x%x (decimal: %d)",
784 cmos_entry->config, cmos_entry->config);
785 break;
786 }
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000787
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000788 printf(" OPTION record at physical address 0x%lx:\n"
789 " tag: 0x%x (decimal: %d)\n"
790 " size: 0x%x (decimal: %d)\n"
791 " bit: 0x%x (decimal: %d)\n"
792 " length: 0x%x (decimal: %d)\n"
793 " config: %s\n"
794 " config_id: 0x%x (decimal: %d)\n"
795 " name: %s\n",
796 vtophys(cmos_entry), cmos_entry->tag, cmos_entry->tag,
797 cmos_entry->size, cmos_entry->size, cmos_entry->bit,
798 cmos_entry->bit, cmos_entry->length, cmos_entry->length, s,
799 cmos_entry->config_id, cmos_entry->config_id, cmos_entry->name);
800}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000801
802/****************************************************************************
803 * print_enum_record
804 *
805 * Display "enum" record from CMOS option table.
806 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000807static void print_enum_record(const struct cmos_enums *cmos_enum)
808{
809 printf(" ENUM record at physical address 0x%lx:\n"
810 " tag: 0x%x (decimal: %d)\n"
811 " size: 0x%x (decimal: %d)\n"
812 " config_id: 0x%x (decimal: %d)\n"
813 " value: 0x%x (decimal: %d)\n"
814 " text: %s\n",
815 vtophys(cmos_enum), cmos_enum->tag, cmos_enum->tag,
816 cmos_enum->size, cmos_enum->size, cmos_enum->config_id,
817 cmos_enum->config_id, cmos_enum->value, cmos_enum->value,
818 cmos_enum->text);
819}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000820
821/****************************************************************************
822 * print_defaults_record
823 *
824 * Display "defaults" record from CMOS option table.
825 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000826static void print_defaults_record(const struct cmos_defaults *cmos_defaults)
827{
828 printf(" DEFAULTS record at physical address 0x%lx:\n"
829 " tag: 0x%x (decimal: %d)\n"
830 " size: 0x%x (decimal: %d)\n"
831 " name_length: 0x%x (decimal: %d)\n"
832 " name: %s\n"
833 " default_set:\n",
834 vtophys(cmos_defaults), cmos_defaults->tag, cmos_defaults->tag,
835 cmos_defaults->size, cmos_defaults->size,
836 cmos_defaults->name_length, cmos_defaults->name_length,
837 cmos_defaults->name);
838 hexdump(cmos_defaults->default_set, CMOS_IMAGE_BUFFER_SIZE,
839 vtophys(cmos_defaults->default_set), stdout, &format);
840}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000841
842/****************************************************************************
843 * print_unknown_record
844 *
845 * Display record of unknown type from CMOS option table.
846 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000847static void print_unknown_record(const struct lb_record *cmos_item)
848{
849 const char *data;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000850
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000851 printf(" UNKNOWN record at physical address 0x%lx:\n"
852 " tag: 0x%x (decimal: %d)\n"
853 " size: 0x%x (decimal: %d)\n"
854 " data:\n",
855 vtophys(cmos_item), cmos_item->tag, cmos_item->tag,
856 cmos_item->size, cmos_item->size);
857 data = ((const char *)cmos_item) + sizeof(*cmos_item);
858 hexdump(data, cmos_item->size - sizeof(*cmos_item), vtophys(data),
859 stdout, &format);
860}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000861
862/****************************************************************************
863 * option_checksum_print_fn
864 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000865 * Display function for 'option_checksum' item of coreboot table.
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000866 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000867static void option_checksum_print_fn(const struct lb_record *rec)
868{
869 struct cmos_checksum *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000870
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000871 p = (struct cmos_checksum *)rec;
872 printf("CMOS checksum from bit %d to bit %d\n"
873 "at position %d is type %s.\n",
874 p->range_start, p->range_end, p->location,
875 (p->type == CHECKSUM_PCBIOS) ? "PC BIOS" : "NONE");
876}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000877
878/****************************************************************************
879 * string_print_fn
880 *
Stefan Reinauerf527e702008-01-18 15:33:49 +0000881 * Display function for a generic item of coreboot table that simply
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000882 * consists of a string.
883 ****************************************************************************/
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000884static void string_print_fn(const struct lb_record *rec)
885{
886 const struct lb_string *p;
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000887
Stefan Reinauer90b96b62010-01-13 21:00:23 +0000888 p = (const struct lb_string *)rec;
889 printf("%s\n", p->string);
890}
Stefan Reinauer6540ae52007-07-12 16:35:42 +0000891