x86: Add a command to display coreboot sysinfo
authorSimon Glass <sjg@chromium.org>
Mon, 15 Mar 2021 05:00:24 +0000 (18:00 +1300)
committerSimon Glass <sjg@chromium.org>
Sat, 27 Mar 2021 02:04:30 +0000 (15:04 +1300)
This information is interesting to look at and can be important for
debugging and inspection. Add a command to display it in a helpful
format.

Signed-off-by: Simon Glass <sjg@chromium.org>
cmd/Kconfig
cmd/x86/Makefile
cmd/x86/cbsysinfo.c [new file with mode: 0644]
doc/usage/index.rst
doc/usage/x86/cbsysinfo.rst [new file with mode: 0644]

index e4bb1d4..8ab34f3 100644 (file)
@@ -2251,6 +2251,15 @@ config CMD_BEDBUG
          for some PowerPC processors. For details please see the
          documentation in doc/README.bedbug.
 
+config CMD_CBSYSINFO
+       bool "cbsysinfo"
+       depends on X86
+       default y if SYS_COREBOOT
+       help
+         This provides information about the coreboot sysinfo table stored in
+         memory by coreboot before jumping to U-Boot. It can be useful for
+         debugging the beaaviour of coreboot or U-Boot.
+
 config CMD_DIAG
        bool "diag - Board diagnostics"
        help
index 144b1cf..5f82204 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0+
 
+obj-$(CONFIG_CMD_CBSYSINFO) += cbsysinfo.o
 obj-y += mtrr.o
 obj-$(CONFIG_CMD_EXCEPTION) += exception.o
 obj-$(CONFIG_USE_HOB) += hob.o
diff --git a/cmd/x86/cbsysinfo.c b/cmd/x86/cbsysinfo.c
new file mode 100644 (file)
index 0000000..a0db0ad
--- /dev/null
@@ -0,0 +1,394 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2021 Google LLC
+ * Written by Simon Glass <sjg@chromium.org>
+ */
+
+#include <common.h>
+#include <asm/cb_sysinfo.h>
+#include <command.h>
+#include <console.h>
+#include <asm/global_data.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void cbprompt(const char *name)
+{
+       for (; *name == '>'; name++)
+               puts("   ");
+       printf("%-12s: ", name);
+}
+
+static void print_dec(const char *name, int value)
+{
+       cbprompt(name);
+       printf(value > 9 ? "0d%d\n" : "%d\n", value);
+}
+
+static void print_hex(const char *name, int value)
+{
+       cbprompt(name);
+       printf("%x\n", value);
+}
+
+static void print_addr(const char *name, ulong value)
+{
+       cbprompt(name);
+       printf("%08lx\n", value);
+}
+
+static void print_addr64(const char *name, u64 value)
+{
+       cbprompt(name);
+       printf("%16llx\n", value);
+}
+
+static void print_ptr(const char *name, const void *value)
+{
+       cbprompt(name);
+       printf("%p\n", value);
+}
+
+static void print_str(const char *name, const char *value)
+{
+       if (value) {
+               cbprompt(name);
+               printf("%s\n", value);
+       }
+}
+
+static void print_idx(const char *name, uint idx, const u8 *strings)
+{
+       const char *ptr;
+
+       cbprompt(name);
+       ptr = (char *)strings + idx;
+       printf("%d: %s\n", idx, ptr ? ptr : "(unknown)");
+}
+
+static const char *const cb_mem_name[] = {
+       NULL,
+       "ram",
+       "reserved",
+       "acpi",
+       "nvs",
+       "unusable",
+       "vendor",
+};
+
+static const char *get_mem_name(int tag)
+{
+       if (tag >= CB_MEM_RAM && tag <= CB_MEM_VENDOR_RSVD)
+               return cb_mem_name[tag];
+
+       if (tag == CB_MEM_TABLE)
+               return "table";
+
+       return "(unknown)";
+}
+
+static const struct timestamp_id_to_name {
+       uint id;
+       const char *name;
+} timestamp_ids[] = {
+       /* Marker to report base_time */
+       { 0,                    "1st timestamp" },
+       { TS_START_ROMSTAGE,    "start of romstage" },
+       { TS_BEFORE_INITRAM,    "before ram initialization" },
+       { TS_AFTER_INITRAM,     "after ram initialization" },
+       { TS_END_ROMSTAGE,      "end of romstage" },
+       { TS_START_VBOOT,       "start of verified boot" },
+       { TS_END_VBOOT,         "end of verified boot" },
+       { TS_START_COPYRAM,     "starting to load ramstage" },
+       { TS_END_COPYRAM,       "finished loading ramstage" },
+       { TS_START_RAMSTAGE,    "start of ramstage" },
+       { TS_START_BOOTBLOCK,   "start of bootblock" },
+       { TS_END_BOOTBLOCK,     "end of bootblock" },
+       { TS_START_COPYROM,     "starting to load romstage" },
+       { TS_END_COPYROM,       "finished loading romstage" },
+       { TS_START_ULZMA,       "starting LZMA decompress (ignore for x86)" },
+       { TS_END_ULZMA,         "finished LZMA decompress (ignore for x86)" },
+       { TS_START_ULZ4F,       "starting LZ4 decompress (ignore for x86)" },
+       { TS_END_ULZ4F,         "finished LZ4 decompress (ignore for x86)" },
+       { TS_DEVICE_ENUMERATE,  "device enumeration" },
+       { TS_DEVICE_CONFIGURE,  "device configuration" },
+       { TS_DEVICE_ENABLE,     "device enable" },
+       { TS_DEVICE_INITIALIZE, "device initialization" },
+       { TS_DEVICE_DONE,       "device setup done" },
+       { TS_CBMEM_POST,        "cbmem post" },
+       { TS_WRITE_TABLES,      "write tables" },
+       { TS_FINALIZE_CHIPS,    "finalize chips" },
+       { TS_LOAD_PAYLOAD,      "load payload" },
+       { TS_ACPI_WAKE_JUMP,    "ACPI wake jump" },
+       { TS_SELFBOOT_JUMP,     "selfboot jump" },
+
+       { TS_START_COPYVER,     "starting to load verstage" },
+       { TS_END_COPYVER,       "finished loading verstage" },
+       { TS_START_TPMINIT,     "starting to initialize TPM" },
+       { TS_END_TPMINIT,       "finished TPM initialization" },
+       { TS_START_VERIFY_SLOT, "starting to verify keyblock/preamble (RSA)" },
+       { TS_END_VERIFY_SLOT,   "finished verifying keyblock/preamble (RSA)" },
+       { TS_START_HASH_BODY,   "starting to verify body (load+SHA2+RSA) " },
+       { TS_DONE_LOADING,      "finished loading body (ignore for x86)" },
+       { TS_DONE_HASHING,      "finished calculating body hash (SHA2)" },
+       { TS_END_HASH_BODY,     "finished verifying body signature (RSA)" },
+
+       { TS_START_COPYVPD,     "starting to load Chrome OS VPD" },
+       { TS_END_COPYVPD_RO,    "finished loading Chrome OS VPD (RO)" },
+       { TS_END_COPYVPD_RW,    "finished loading Chrome OS VPD (RW)" },
+
+       { TS_U_BOOT_INITTED,    "U-Boot start" },
+       { TS_RO_PARAMS_INIT,    "RO parameter init" },
+       { TS_RO_VB_INIT,        "RO vboot init" },
+       { TS_RO_VB_SELECT_FIRMWARE,             "RO vboot select firmware" },
+       { TS_RO_VB_SELECT_AND_LOAD_KERNEL,      "RO vboot select&load kernel" },
+       { TS_RW_VB_SELECT_AND_LOAD_KERNEL,      "RW vboot select&load kernel" },
+       { TS_VB_SELECT_AND_LOAD_KERNEL,         "vboot select&load kernel" },
+       { TS_VB_EC_VBOOT_DONE,  "finished EC verification" },
+       { TS_VB_STORAGE_INIT_DONE, "finished storage device initialization" },
+       { TS_VB_READ_KERNEL_DONE, "finished reading kernel from disk" },
+       { TS_VB_VBOOT_DONE,     "finished vboot kernel verification" },
+       { TS_KERNEL_DECOMPRESSION, "starting kernel decompression/relocation" },
+       { TS_START_KERNEL,      "jumping to kernel" },
+       { TS_U_BOOT_START_KERNEL,       "just before jump to kernel" },
+
+       /* Intel ME-related timestamps */
+       { TS_ME_INFORM_DRAM_WAIT, "waiting for ME acknowledgment of raminit"},
+       { TS_ME_INFORM_DRAM_DONE, "finished waiting for ME response"},
+
+       /* FSP-related timestamps */
+       { TS_FSP_MEMORY_INIT_START, "calling FspMemoryInit" },
+       { TS_FSP_MEMORY_INIT_END, "returning from FspMemoryInit" },
+       { TS_FSP_TEMP_RAM_EXIT_START, "calling FspTempRamExit" },
+       { TS_FSP_TEMP_RAM_EXIT_END, "returning from FspTempRamExit" },
+       { TS_FSP_SILICON_INIT_START, "calling FspSiliconInit" },
+       { TS_FSP_SILICON_INIT_END, "returning from FspSiliconInit" },
+       { TS_FSP_BEFORE_ENUMERATE, "calling FspNotify(AfterPciEnumeration)" },
+       { TS_FSP_AFTER_ENUMERATE,
+                "returning from FspNotify(AfterPciEnumeration)" },
+       { TS_FSP_BEFORE_FINALIZE, "calling FspNotify(ReadyToBoot)" },
+       { TS_FSP_AFTER_FINALIZE, "returning from FspNotify(ReadyToBoot)" },
+       { TS_FSP_BEFORE_END_OF_FIRMWARE, "calling FspNotify(EndOfFirmware)" },
+       { TS_FSP_AFTER_END_OF_FIRMWARE,
+               "returning from FspNotify(EndOfFirmware)" },
+};
+
+static const char *timestamp_name(uint32_t id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(timestamp_ids); i++) {
+               if (timestamp_ids[i].id == id)
+                       return timestamp_ids[i].name;
+       }
+
+       return "<unknown>";
+}
+
+static void show_table(struct sysinfo_t *info, bool verbose)
+{
+       struct cb_serial *ser = info->serial;
+       int i;
+
+       printf("Coreboot table at %lx, decoded to %p",
+              gd->arch.coreboot_table, info);
+       if (info->header)
+               printf(", forwarded to %p\n", info->header);
+       printf("\n");
+
+       print_dec("CPU KHz", info->cpu_khz);
+
+       print_addr("Serial I/O port", info->ser_ioport);
+       print_addr(">base", info->ser_base);
+       print_ptr(">pointer", ser);
+       if (ser) {
+               print_hex(">type", ser->type);
+               print_addr(">base", ser->baseaddr);
+               print_dec(">baud", ser->baud);
+               print_hex(">baud", ser->regwidth);
+               print_dec(">input_hz", ser->input_hertz);
+               print_addr(">PCI addr", ser->uart_pci_addr);
+       }
+
+       print_dec("Mem ranges", info->n_memranges);
+       printf("%12s: %-11s        ||   base        ||   size\n", "id", "type");
+       for (i = 0; i < info->n_memranges; i++) {
+               const struct memrange *mr = &info->memrange[i];
+
+               printf("%12d: %02x:%-8s %016llx %016llx\n", i, mr->type,
+                      get_mem_name(mr->type), mr->base, mr->size);
+       }
+       print_ptr("option_table", info->option_table);
+
+       print_hex("CMOS start", info->cmos_range_start);
+       if (info->cmos_range_start) {
+               print_hex(">CMOS end", info->cmos_range_end);
+               print_hex(">CMOS csum loc", info->cmos_checksum_location);
+       }
+
+       print_hex("VBNV start", info->vbnv_start);
+       print_hex("VBNV size", info->vbnv_size);
+
+       print_str("CB version", info->cb_version);
+       print_str(">Extra", info->extra_version);
+       print_str(">Build", info->build);
+       print_str(">Time", info->compile_time);
+       print_str(">By", info->compile_by);
+       print_str(">Host", info->compile_host);
+       print_str(">Domain", info->compile_domain);
+       print_str(">Compiler", info->compiler);
+       print_str(">Linker", info->linker);
+       print_str(">Assembler", info->assembler);
+
+       print_ptr("Framebuffer", info->framebuffer);
+       if (info->framebuffer) {
+               struct cb_framebuffer *fb = info->framebuffer;
+
+               print_addr64(">Phys addr", fb->physical_address);
+               print_dec(">X res", fb->x_resolution);
+               print_dec(">X res", fb->y_resolution);
+               print_hex(">Bytes / line", fb->bytes_per_line);
+               print_dec(">Bpp", fb->bits_per_pixel);
+               printf("   %-12s  red %d/%d, green %d/%d, blue %d/%d, reserved %d/%d\n",
+                      "pos/size", fb->red_mask_pos, fb->red_mask_size,
+                      fb->green_mask_pos, fb->green_mask_size,
+                      fb->blue_mask_pos, fb->blue_mask_size,
+                      fb->reserved_mask_pos, fb->reserved_mask_size);
+       }
+
+       print_dec("GPIOs", info->num_gpios);
+       printf("%12s: %4s %12s %3s %s\n", "id", "port", "polarity", "val",
+              "name");
+       for (i = 0; i < info->num_gpios; i++) {
+               const struct cb_gpio *gpio = &info->gpios[i];
+               char portstr[4];
+
+               if (gpio->port == 0xffffffff)
+                       strcpy(portstr, "-");
+               else
+                       sprintf(portstr, "%x", gpio->port);
+               printf("%12d: %4s %12s %3d %s\n", i, portstr,
+                      gpio->polarity == CB_GPIO_ACTIVE_LOW ? "active-low" :
+                      "active-high", gpio->value, gpio->name);
+       }
+       print_dec("MACs", info->num_macs);
+       for (i = 0; i < info->num_macs; i++) {
+               const struct mac_address *mac = &info->macs[i];
+               int j;
+
+               printf("%12d: ", i);
+               for (j = 0; j < sizeof(mac->mac_addr); j++)
+                       printf("%s%02x", j ? ":" : "", mac->mac_addr[j]);
+               printf("\n");
+       }
+       print_str(">Serial #", info->serialno);
+       print_ptr("Multiboot tab", info->mbtable);
+       print_ptr("CB header", info->header);
+       print_ptr("CB mainboard", info->mainboard);
+       if (info->mainboard) {
+               struct cb_mainboard *mb = info->mainboard;
+
+               print_idx(">vendor", mb->vendor_idx, mb->strings);
+               print_idx(">part_number", mb->part_number_idx, mb->strings);
+       }
+       print_ptr("vboot handoff", info->vboot_handoff);
+       print_hex(">size", info->vboot_handoff_size);
+       print_ptr(">vdat addr", info->vdat_addr);
+       print_hex(">size", info->vdat_size);
+
+       print_addr64("SMBIOS", info->smbios_start);
+       print_hex(">size", info->smbios_size);
+       print_hex("ROM MTRR", info->x86_rom_var_mtrr_index);
+
+       print_ptr("Tstamp table", info->tstamp_table);
+       if (verbose && info->tstamp_table) {
+               struct timestamp_table *ts = info->tstamp_table;
+
+               printf("%-12s", "Base_time");
+               print_grouped_ull(ts->base_time, 12);
+               printf("\n");
+               print_dec("Tick MHz", ts->tick_freq_mhz);
+               for (i = 0; i < ts->num_entries; i++) {
+                       const struct timestamp_entry *tse;
+
+                       tse = &ts->entries[i];
+                       printf("   ");
+                       print_grouped_ull(tse->entry_stamp, 12);
+                       printf("  %s\n", timestamp_name(tse->entry_id));
+               }
+       }
+
+       print_ptr("CBmem cons", info->cbmem_cons);
+       if (info->cbmem_cons) {
+               struct cbmem_console *cons = info->cbmem_cons;
+               int i;
+
+               print_hex("Size", cons->size);
+               print_hex("Cursor", cons->cursor);
+               if (verbose) {
+                       for (i = 0; i < cons->cursor; i++) {
+                               int ch = cons->body[i];
+
+                               putc(ch);
+
+                               if (ch == '\n') {
+                                       /* check for ctrl-c to abort... */
+                                       if (ctrlc()) {
+                                               puts("Abort\n");
+                                               return;
+                                       }
+                                       printf("   ");
+                               }
+                       }
+                       printf("\n");
+               }
+       }
+
+       print_ptr("MRC cache", info->mrc_cache);
+       print_ptr("ACPI GNVS", info->acpi_gnvs);
+       print_hex("Board ID", info->board_id);
+       print_hex("RAM code", info->ram_code);
+       print_ptr("WiFi calib", info->wifi_calibration);
+       print_addr64("Ramoops buff", info->ramoops_buffer);
+       print_hex(">size", info->ramoops_buffer_size);
+       print_hex("SF size", info->spi_flash.size);
+       print_hex("SF sector", info->spi_flash.sector_size);
+       print_hex("SF erase cmd", info->spi_flash.erase_cmd);
+
+       print_addr64("FMAP offset", info->fmap_offset);
+       print_addr64("CBFS offset", info->cbfs_offset);
+       print_addr64("CBFS size", info->cbfs_size);
+       print_addr64("Boot media size", info->boot_media_size);
+       print_addr64("MTC start", info->mtc_start);
+       print_hex("MTC size", info->mtc_size);
+
+       print_ptr("Chrome OS VPD", info->chromeos_vpd);
+}
+
+static int do_cbsysinfo(struct cmd_tbl *cmdtp, int flag, int argc,
+                       char *const argv[])
+{
+       bool verbose = false;
+
+       if (argc > 1) {
+               if (!strcmp("-v", argv[1]))
+                       verbose = true;
+               else
+                       return CMD_RET_USAGE;
+       }
+
+       if (!gd->arch.coreboot_table) {
+               printf("No coreboot sysinfo table found\n");
+               return CMD_RET_FAILURE;
+       }
+       show_table(&lib_sysinfo, verbose);
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       cbsysinfo,      2,      1,      do_cbsysinfo,
+       "Show coreboot sysinfo table",
+       "[-v]         Dumps out the contents of the sysinfo table. This only\n"
+       "works if U-Boot is booted from coreboot"
+);
index 35c515f..fb83434 100644 (file)
@@ -21,6 +21,7 @@ Shell commands
    booti
    bootmenu
    button
+   x86/cbsysinfo
    conitrace
    echo
    exception
diff --git a/doc/usage/x86/cbsysinfo.rst b/doc/usage/x86/cbsysinfo.rst
new file mode 100644 (file)
index 0000000..8c03a85
--- /dev/null
@@ -0,0 +1,25 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+cbsysinfo
+=========
+
+Synopis
+-------
+
+::
+
+    cbsysinfo
+
+
+Description
+-----------
+
+This displays information obtained from the coreboot sysinfo table. It is only
+useful when booting U-Boot from coreboot.
+
+Example
+-------
+
+::
+
+    => cbsysinfo