1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2021 Google LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #include <asm/cb_sysinfo.h>
8 #include <command.h>
9 #include <console.h>
10 #include <asm/global_data.h>
11 
12 DECLARE_GLOBAL_DATA_PTR;
13 
cbprompt(const char * name)14 static void cbprompt(const char *name)
15 {
16 	for (; *name == '>'; name++)
17 		puts("   ");
18 	printf("%-12s: ", name);
19 }
20 
print_dec(const char * name,int value)21 static void print_dec(const char *name, int value)
22 {
23 	cbprompt(name);
24 	printf(value > 9 ? "0d%d\n" : "%d\n", value);
25 }
26 
print_hex(const char * name,int value)27 static void print_hex(const char *name, int value)
28 {
29 	cbprompt(name);
30 	printf("%x\n", value);
31 }
32 
print_addr(const char * name,ulong value)33 static void print_addr(const char *name, ulong value)
34 {
35 	cbprompt(name);
36 	printf("%08lx\n", value);
37 }
38 
print_addr64(const char * name,u64 value)39 static void print_addr64(const char *name, u64 value)
40 {
41 	cbprompt(name);
42 	printf("%16llx\n", value);
43 }
44 
print_ptr(const char * name,const void * value)45 static void print_ptr(const char *name, const void *value)
46 {
47 	cbprompt(name);
48 	printf("%p\n", value);
49 }
50 
print_str(const char * name,const char * value)51 static void print_str(const char *name, const char *value)
52 {
53 	if (value) {
54 		cbprompt(name);
55 		printf("%s\n", value);
56 	}
57 }
58 
print_idx(const char * name,uint idx,const u8 * strings)59 static void print_idx(const char *name, uint idx, const u8 *strings)
60 {
61 	const char *ptr;
62 
63 	cbprompt(name);
64 	ptr = (char *)strings + idx;
65 	printf("%d: %s\n", idx, ptr ? ptr : "(unknown)");
66 }
67 
68 static const char *const cb_mem_name[] = {
69 	NULL,
70 	"ram",
71 	"reserved",
72 	"acpi",
73 	"nvs",
74 	"unusable",
75 	"vendor",
76 };
77 
get_mem_name(int tag)78 static const char *get_mem_name(int tag)
79 {
80 	if (tag >= CB_MEM_RAM && tag <= CB_MEM_VENDOR_RSVD)
81 		return cb_mem_name[tag];
82 
83 	if (tag == CB_MEM_TABLE)
84 		return "table";
85 
86 	return "(unknown)";
87 }
88 
89 static const struct timestamp_id_to_name {
90 	uint id;
91 	const char *name;
92 } timestamp_ids[] = {
93 	/* Marker to report base_time */
94 	{ 0,			"1st timestamp" },
95 	{ TS_START_ROMSTAGE,	"start of romstage" },
96 	{ TS_BEFORE_INITRAM,	"before ram initialization" },
97 	{ TS_AFTER_INITRAM,	"after ram initialization" },
98 	{ TS_END_ROMSTAGE,	"end of romstage" },
99 	{ TS_START_VBOOT,	"start of verified boot" },
100 	{ TS_END_VBOOT,		"end of verified boot" },
101 	{ TS_START_COPYRAM,	"starting to load ramstage" },
102 	{ TS_END_COPYRAM,	"finished loading ramstage" },
103 	{ TS_START_RAMSTAGE,	"start of ramstage" },
104 	{ TS_START_BOOTBLOCK,	"start of bootblock" },
105 	{ TS_END_BOOTBLOCK,	"end of bootblock" },
106 	{ TS_START_COPYROM,	"starting to load romstage" },
107 	{ TS_END_COPYROM,	"finished loading romstage" },
108 	{ TS_START_ULZMA,	"starting LZMA decompress (ignore for x86)" },
109 	{ TS_END_ULZMA,		"finished LZMA decompress (ignore for x86)" },
110 	{ TS_START_ULZ4F,	"starting LZ4 decompress (ignore for x86)" },
111 	{ TS_END_ULZ4F,		"finished LZ4 decompress (ignore for x86)" },
112 	{ TS_DEVICE_ENUMERATE,	"device enumeration" },
113 	{ TS_DEVICE_CONFIGURE,	"device configuration" },
114 	{ TS_DEVICE_ENABLE,	"device enable" },
115 	{ TS_DEVICE_INITIALIZE,	"device initialization" },
116 	{ TS_DEVICE_DONE,	"device setup done" },
117 	{ TS_CBMEM_POST,	"cbmem post" },
118 	{ TS_WRITE_TABLES,	"write tables" },
119 	{ TS_FINALIZE_CHIPS,	"finalize chips" },
120 	{ TS_LOAD_PAYLOAD,	"load payload" },
121 	{ TS_ACPI_WAKE_JUMP,	"ACPI wake jump" },
122 	{ TS_SELFBOOT_JUMP,	"selfboot jump" },
123 
124 	{ TS_START_COPYVER,	"starting to load verstage" },
125 	{ TS_END_COPYVER,	"finished loading verstage" },
126 	{ TS_START_TPMINIT,	"starting to initialize TPM" },
127 	{ TS_END_TPMINIT,	"finished TPM initialization" },
128 	{ TS_START_VERIFY_SLOT,	"starting to verify keyblock/preamble (RSA)" },
129 	{ TS_END_VERIFY_SLOT,	"finished verifying keyblock/preamble (RSA)" },
130 	{ TS_START_HASH_BODY,	"starting to verify body (load+SHA2+RSA) " },
131 	{ TS_DONE_LOADING,	"finished loading body (ignore for x86)" },
132 	{ TS_DONE_HASHING,	"finished calculating body hash (SHA2)" },
133 	{ TS_END_HASH_BODY,	"finished verifying body signature (RSA)" },
134 
135 	{ TS_START_COPYVPD,	"starting to load Chrome OS VPD" },
136 	{ TS_END_COPYVPD_RO,	"finished loading Chrome OS VPD (RO)" },
137 	{ TS_END_COPYVPD_RW,	"finished loading Chrome OS VPD (RW)" },
138 
139 	{ TS_U_BOOT_INITTED,	"U-Boot start" },
140 	{ TS_RO_PARAMS_INIT,	"RO parameter init" },
141 	{ TS_RO_VB_INIT,	"RO vboot init" },
142 	{ TS_RO_VB_SELECT_FIRMWARE,		"RO vboot select firmware" },
143 	{ TS_RO_VB_SELECT_AND_LOAD_KERNEL,	"RO vboot select&load kernel" },
144 	{ TS_RW_VB_SELECT_AND_LOAD_KERNEL,	"RW vboot select&load kernel" },
145 	{ TS_VB_SELECT_AND_LOAD_KERNEL,		"vboot select&load kernel" },
146 	{ TS_VB_EC_VBOOT_DONE,	"finished EC verification" },
147 	{ TS_VB_STORAGE_INIT_DONE, "finished storage device initialization" },
148 	{ TS_VB_READ_KERNEL_DONE, "finished reading kernel from disk" },
149 	{ TS_VB_VBOOT_DONE,	"finished vboot kernel verification" },
150 	{ TS_KERNEL_DECOMPRESSION, "starting kernel decompression/relocation" },
151 	{ TS_START_KERNEL,	"jumping to kernel" },
152 	{ TS_U_BOOT_START_KERNEL,	"just before jump to kernel" },
153 
154 	/* Intel ME-related timestamps */
155 	{ TS_ME_INFORM_DRAM_WAIT, "waiting for ME acknowledgment of raminit"},
156 	{ TS_ME_INFORM_DRAM_DONE, "finished waiting for ME response"},
157 
158 	/* FSP-related timestamps */
159 	{ TS_FSP_MEMORY_INIT_START, "calling FspMemoryInit" },
160 	{ TS_FSP_MEMORY_INIT_END, "returning from FspMemoryInit" },
161 	{ TS_FSP_TEMP_RAM_EXIT_START, "calling FspTempRamExit" },
162 	{ TS_FSP_TEMP_RAM_EXIT_END, "returning from FspTempRamExit" },
163 	{ TS_FSP_SILICON_INIT_START, "calling FspSiliconInit" },
164 	{ TS_FSP_SILICON_INIT_END, "returning from FspSiliconInit" },
165 	{ TS_FSP_BEFORE_ENUMERATE, "calling FspNotify(AfterPciEnumeration)" },
166 	{ TS_FSP_AFTER_ENUMERATE,
167 		 "returning from FspNotify(AfterPciEnumeration)" },
168 	{ TS_FSP_BEFORE_FINALIZE, "calling FspNotify(ReadyToBoot)" },
169 	{ TS_FSP_AFTER_FINALIZE, "returning from FspNotify(ReadyToBoot)" },
170 	{ TS_FSP_BEFORE_END_OF_FIRMWARE, "calling FspNotify(EndOfFirmware)" },
171 	{ TS_FSP_AFTER_END_OF_FIRMWARE,
172 		"returning from FspNotify(EndOfFirmware)" },
173 };
174 
timestamp_name(uint32_t id)175 static const char *timestamp_name(uint32_t id)
176 {
177 	int i;
178 
179 	for (i = 0; i < ARRAY_SIZE(timestamp_ids); i++) {
180 		if (timestamp_ids[i].id == id)
181 			return timestamp_ids[i].name;
182 	}
183 
184 	return "<unknown>";
185 }
186 
show_option_vals(const struct cb_cmos_option_table * tab,uint id)187 static void show_option_vals(const struct cb_cmos_option_table *tab,
188 			     uint id)
189 {
190 	const void *ptr, *end;
191 	bool found = false;
192 
193 	end = (void *)tab + tab->size;
194 	for (ptr = (void *)tab + tab->header_length; ptr < end;) {
195 		const struct cb_record *rec = ptr;
196 
197 		switch (rec->tag) {
198 		case CB_TAG_OPTION_ENUM: {
199 			const struct cb_cmos_enums *enums = ptr;
200 
201 			if (enums->config_id == id) {
202 				if (!found)
203 					printf("  ");
204 				printf(" %d:%s", enums->value, enums->text);
205 				found = true;
206 			}
207 			break;
208 		}
209 			break;
210 		case CB_TAG_OPTION_DEFAULTS:
211 		case CB_TAG_OPTION_CHECKSUM:
212 		case CB_TAG_OPTION:
213 			break;
214 		default:
215 			printf("tag %x\n", rec->tag);
216 			break;
217 		}
218 		ptr += rec->size;
219 	}
220 }
221 
show_option_table(const struct cb_cmos_option_table * tab)222 static void show_option_table(const struct cb_cmos_option_table *tab)
223 {
224 	const void *ptr, *end;
225 
226 	print_ptr("option_table", tab);
227 	if (!tab->size)
228 		return;
229 
230 	printf(" Bit  Len  Cfg  ID  Name\n");
231 	end = (void *)tab + tab->size;
232 	for (ptr = (void *)tab + tab->header_length; ptr < end;) {
233 		const struct cb_record *rec = ptr;
234 
235 		switch (rec->tag) {
236 		case CB_TAG_OPTION: {
237 			const struct cb_cmos_entries *entry = ptr;
238 
239 			printf("%4x %4x  %3c %3x  %-20s", entry->bit,
240 			       entry->length, entry->config, entry->config_id,
241 			       entry->name);
242 			show_option_vals(tab, entry->config_id);
243 			printf("\n");
244 			break;
245 		}
246 		case CB_TAG_OPTION_ENUM:
247 		case CB_TAG_OPTION_DEFAULTS:
248 		case CB_TAG_OPTION_CHECKSUM:
249 			break;
250 		default:
251 			printf("tag %x\n", rec->tag);
252 			break;
253 		}
254 		ptr += rec->size;
255 	}
256 }
257 
show_table(struct sysinfo_t * info,bool verbose)258 static void show_table(struct sysinfo_t *info, bool verbose)
259 {
260 	struct cb_serial *ser = info->serial;
261 	int i;
262 
263 	printf("Coreboot table at %lx, size %x, records %x (dec %d), decoded to %p",
264 	       gd->arch.coreboot_table, info->table_size, info->rec_count,
265 	       info->rec_count, info);
266 	if (info->header)
267 		printf(", forwarded to %p\n", info->header);
268 	printf("\n");
269 
270 	print_dec("CPU KHz", info->cpu_khz);
271 
272 	print_addr("Serial I/O port", info->ser_ioport);
273 	print_addr(">base", info->ser_base);
274 	print_ptr(">pointer", ser);
275 	if (ser) {
276 		print_hex(">type", ser->type);
277 		print_addr(">base", ser->baseaddr);
278 		print_dec(">baud", ser->baud);
279 		print_hex(">regwidth", ser->regwidth);
280 		print_dec(">input_hz", ser->input_hertz);
281 		print_addr(">PCI addr", ser->uart_pci_addr);
282 	}
283 
284 	print_dec("Mem ranges", info->n_memranges);
285 	printf("%12s: %-11s        ||   base        ||   size\n", "id", "type");
286 	for (i = 0; i < info->n_memranges; i++) {
287 		const struct memrange *mr = &info->memrange[i];
288 
289 		printf("%12d: %02x:%-8s %016llx %016llx\n", i, mr->type,
290 		       get_mem_name(mr->type), mr->base, mr->size);
291 	}
292 	show_option_table(info->option_table);
293 
294 	print_hex("CMOS start", info->cmos_range_start);
295 	if (info->cmos_range_start) {
296 		print_hex(">CMOS end", info->cmos_range_end);
297 		print_hex(">CMOS csum loc", info->cmos_checksum_location);
298 	}
299 
300 	print_hex("VBNV start", info->vbnv_start);
301 	print_hex("VBNV size", info->vbnv_size);
302 
303 	print_str("CB version", info->cb_version);
304 	print_str(">Extra", info->extra_version);
305 	print_str(">Build", info->build);
306 	print_str(">Time", info->compile_time);
307 	print_str(">By", info->compile_by);
308 	print_str(">Host", info->compile_host);
309 	print_str(">Domain", info->compile_domain);
310 	print_str(">Compiler", info->compiler);
311 	print_str(">Linker", info->linker);
312 	print_str(">Assembler", info->assembler);
313 
314 	print_ptr("Framebuffer", info->framebuffer);
315 	if (info->framebuffer) {
316 		struct cb_framebuffer *fb = info->framebuffer;
317 
318 		print_addr64(">Phys addr", fb->physical_address);
319 		print_dec(">X res", fb->x_resolution);
320 		print_dec(">X res", fb->y_resolution);
321 		print_hex(">Bytes / line", fb->bytes_per_line);
322 		print_dec(">Bpp", fb->bits_per_pixel);
323 		printf("   %-12s  red %d/%d, green %d/%d, blue %d/%d, reserved %d/%d\n",
324 		       "pos/size", fb->red_mask_pos, fb->red_mask_size,
325 		       fb->green_mask_pos, fb->green_mask_size,
326 		       fb->blue_mask_pos, fb->blue_mask_size,
327 		       fb->reserved_mask_pos, fb->reserved_mask_size);
328 	}
329 
330 	print_dec("GPIOs", info->num_gpios);
331 	printf("%12s: %4s %12s %3s %s\n", "id", "port", "polarity", "val",
332 	       "name");
333 	for (i = 0; i < info->num_gpios; i++) {
334 		const struct cb_gpio *gpio = &info->gpios[i];
335 		char portstr[4];
336 
337 		if (gpio->port == 0xffffffff)
338 			strcpy(portstr, "-");
339 		else
340 			sprintf(portstr, "%x", gpio->port);
341 		printf("%12d: %4s %12s %3d %s\n", i, portstr,
342 		       gpio->polarity == CB_GPIO_ACTIVE_LOW ? "active-low" :
343 		       "active-high", gpio->value, gpio->name);
344 	}
345 	print_dec("MACs", info->num_macs);
346 	for (i = 0; i < info->num_macs; i++) {
347 		const struct mac_address *mac = &info->macs[i];
348 		int j;
349 
350 		printf("%12d: ", i);
351 		for (j = 0; j < sizeof(mac->mac_addr); j++)
352 			printf("%s%02x", j ? ":" : "", mac->mac_addr[j]);
353 		printf("\n");
354 	}
355 	print_str(">Serial #", info->serialno);
356 	print_ptr("Multiboot tab", info->mbtable);
357 	print_ptr("CB header", info->header);
358 	print_ptr("CB mainboard", info->mainboard);
359 	if (info->mainboard) {
360 		struct cb_mainboard *mb = info->mainboard;
361 
362 		print_idx(">vendor", mb->vendor_idx, mb->strings);
363 		print_idx(">part_number", mb->part_number_idx, mb->strings);
364 	}
365 	print_ptr("vboot handoff", info->vboot_handoff);
366 	print_hex(">size", info->vboot_handoff_size);
367 	print_ptr(">vdat addr", info->vdat_addr);
368 	print_hex(">size", info->vdat_size);
369 
370 	print_addr64("SMBIOS", info->smbios_start);
371 	print_hex(">size", info->smbios_size);
372 	print_hex("ROM MTRR", info->x86_rom_var_mtrr_index);
373 
374 	print_ptr("Tstamp table", info->tstamp_table);
375 	if (verbose && info->tstamp_table) {
376 		struct timestamp_table *ts = info->tstamp_table;
377 
378 		printf("%-12s", "Base_time");
379 		print_grouped_ull(ts->base_time, 12);
380 		printf("\n");
381 		print_dec("Tick MHz", ts->tick_freq_mhz);
382 		for (i = 0; i < ts->num_entries; i++) {
383 			const struct timestamp_entry *tse;
384 
385 			tse = &ts->entries[i];
386 			printf("   ");
387 			print_grouped_ull(tse->entry_stamp, 12);
388 			printf("  %s\n", timestamp_name(tse->entry_id));
389 		}
390 	}
391 
392 	print_ptr("CBmem cons", info->cbmem_cons);
393 	if (info->cbmem_cons) {
394 		struct cbmem_console *cons = info->cbmem_cons;
395 		int i;
396 
397 		print_hex("Size", cons->size);
398 		print_hex("Cursor", cons->cursor);
399 		if (verbose) {
400 			for (i = 0; i < cons->cursor; i++) {
401 				int ch = cons->body[i];
402 
403 				putc(ch);
404 
405 				if (ch == '\n') {
406 					/* check for ctrl-c to abort... */
407 					if (ctrlc()) {
408 						puts("Abort\n");
409 						return;
410 					}
411 					printf("   ");
412 				}
413 			}
414 			printf("\n");
415 		}
416 	}
417 
418 	print_ptr("MRC cache", info->mrc_cache);
419 	print_ptr("ACPI GNVS", info->acpi_gnvs);
420 	print_hex("Board ID", info->board_id);
421 	print_hex("RAM code", info->ram_code);
422 	print_ptr("WiFi calib", info->wifi_calibration);
423 	print_addr64("Ramoops buff", info->ramoops_buffer);
424 	print_hex(">size", info->ramoops_buffer_size);
425 	print_hex("SF size", info->spi_flash.size);
426 	print_hex("SF sector", info->spi_flash.sector_size);
427 	print_hex("SF erase cmd", info->spi_flash.erase_cmd);
428 
429 	print_addr64("FMAP offset", info->fmap_offset);
430 	print_addr64("CBFS offset", info->cbfs_offset);
431 	print_addr64("CBFS size", info->cbfs_size);
432 	print_addr64("Boot media size", info->boot_media_size);
433 	print_addr64("MTC start", info->mtc_start);
434 	print_hex("MTC size", info->mtc_size);
435 
436 	print_ptr("Chrome OS VPD", info->chromeos_vpd);
437 	print_ptr("RSDP", info->rsdp);
438 	printf("%-12s: ", "Unimpl.");
439 	if (info->unimpl_count) {
440 		for (i = 0; i < info->unimpl_count; i++)
441 			printf("%02x ", info->unimpl[i]);
442 		printf("\n");
443 	} else {
444 		printf("(none)\n");
445 	}
446 }
447 
do_cbsysinfo(struct cmd_tbl * cmdtp,int flag,int argc,char * const argv[])448 static int do_cbsysinfo(struct cmd_tbl *cmdtp, int flag, int argc,
449 			char *const argv[])
450 {
451 	bool verbose = false;
452 
453 	if (argc > 1) {
454 		if (!strcmp("-v", argv[1]))
455 			verbose = true;
456 		else
457 			return CMD_RET_USAGE;
458 	}
459 
460 	if (!gd->arch.coreboot_table) {
461 		printf("No coreboot sysinfo table found\n");
462 		return CMD_RET_FAILURE;
463 	}
464 	show_table(&lib_sysinfo, verbose);
465 
466 	return 0;
467 }
468 
469 U_BOOT_CMD(
470 	cbsysinfo,	2,	1,	do_cbsysinfo,
471 	"Show coreboot sysinfo table",
472 	"[-v]         Dumps out the contents of the sysinfo table. This only\n"
473 	"works if U-Boot is booted from coreboot"
474 );
475