[PATCH 00/34] x86: Enhancements for booting from coreboot

This series contains various changes to improve U-Boots Coreboot Filesystem (CBFS) implementation and the overall booting of U-Boot from coreboot:
- CBFS compression, bare CBFSs - More coreboot sysinfo parsing - Command to display coreboot sysinfo - Various other minor things - Additional features for booting a coral image from coreboot
These core changes are required to allow the 'coral' U-Boot to run on top of coreboot and complete the Chromium OS verified boot flow.
Simon Glass (34): x86: coral: Free the ACPI GPIOs after using them x86: coral: Add information about building / running x86: p2sb: Drop LOG_DEBUG x86: Probe device if needed in intel_gpio_xlate() x86: coral: Put the eMMC first x86: coral: Update the SD card-detect GPIO tegra: i2c: Drop LOG_DEBUG mmc: pci_mmc: Set up the card detect cbfs: Add support for attributes cbfs: Rename new_node to node smbios: Allow writing to the coreboot version string cbfs: Allow access to CBFS without a header cbfs: Allow file traversal with any CBFS cbfs: Factor out filling a cache node into a new function cbfs: Simplify file iteration cbfs: Support reading compression information cbfs: Drop unnecessary cast in file_cbfs_fill_cache() x86: Make coreboot sysinfo available to any x86 board x86: Move coreboot timestamp info into coreboot_tables.h x86: coreboot: Sync up timestamp codes x86: Move coreboot sysinfo parsing into generic x86 code x86: coreboot: Update parsing of the latest sysinfo x86: Allow installing an e820 when booting from coreboot x86: Add a command to display coreboot sysinfo cmd: Add missing check for CONFIG_SYS_LONGHELP video: Fix video on coreboot with the copy buffer x86: video: Allow coreboot video to be used on any x86 board x86: fsp: Don't enable FSP graphics if booted from coreboot dm: core: Add CBFS support to flashmap x86: coral: Avoid build error with !CONFIG_ACPIGEN x86: coral: Allow init of debug UART in U-Boot proper x86: coral: Fall back to coreboot video when FSP missing x86: fsp: Don't notify if booted from coreboot x86: coreboot: Don't setup MTRR when booting from coreboot
arch/x86/Kconfig | 21 + arch/x86/cpu/apollolake/cpu.c | 14 +- arch/x86/cpu/apollolake/cpu_common.c | 60 +++ arch/x86/cpu/apollolake/cpu_spl.c | 58 --- arch/x86/cpu/coreboot/Makefile | 1 - arch/x86/cpu/coreboot/coreboot.c | 2 +- arch/x86/cpu/coreboot/sdram.c | 29 +- arch/x86/cpu/coreboot/tables.c | 255 ---------- arch/x86/cpu/coreboot/timestamp.c | 14 +- arch/x86/cpu/start_from_spl.S | 4 + arch/x86/dts/chromebook_coral.dts | 8 +- arch/x86/include/asm/arch-apollolake/uart.h | 1 + arch/x86/include/asm/arch-coreboot/sysinfo.h | 62 --- .../x86/include/asm/arch-coreboot/timestamp.h | 25 +- arch/x86/include/asm/cb_sysinfo.h | 220 ++++++++ arch/x86/include/asm/coreboot_tables.h | 261 ++++++++-- arch/x86/include/asm/e820.h | 16 +- arch/x86/lib/Makefile | 1 + arch/x86/lib/bootm.c | 2 +- arch/x86/lib/coreboot/Makefile | 7 + arch/x86/lib/coreboot/cb_support.c | 41 ++ arch/x86/lib/coreboot/cb_sysinfo.c | 468 ++++++++++++++++++ arch/x86/lib/fsp/fsp_graphics.c | 2 +- arch/x86/lib/fsp2/fsp_init.c | 3 +- arch/x86/lib/fsp2/fsp_support.c | 4 + arch/x86/lib/init_helpers.c | 6 +- arch/x86/lib/zimage.c | 12 +- board/coreboot/coreboot/coreboot.c | 2 +- board/google/chromebook_coral/coral.c | 2 + cmd/Kconfig | 9 + cmd/acpi.c | 2 + cmd/bloblist.c | 2 + cmd/version.c | 2 +- cmd/x86/Makefile | 1 + cmd/x86/cbsysinfo.c | 394 +++++++++++++++ doc/board/google/chromebook_coral.rst | 234 ++++++++- doc/usage/index.rst | 1 + doc/usage/x86/cbsysinfo.rst | 25 + drivers/gpio/intel_gpio.c | 14 +- drivers/misc/cbmem_console.c | 2 +- drivers/misc/p2sb_emul.c | 1 - drivers/mmc/pci_mmc.c | 6 +- drivers/pci/pci_rom.c | 7 +- drivers/serial/serial_coreboot.c | 2 +- drivers/sound/tegra_i2s.c | 1 - drivers/video/Kconfig | 2 +- drivers/video/coreboot.c | 18 +- fs/cbfs/cbfs.c | 124 +++-- include/cbfs.h | 77 ++- include/configs/chromebook_coral.h | 6 +- include/dm/of_extra.h | 8 + include/smbios.h | 20 + lib/smbios-parser.c | 38 ++ lib/smbios.c | 4 - 54 files changed, 2031 insertions(+), 570 deletions(-) delete mode 100644 arch/x86/cpu/coreboot/tables.c delete mode 100644 arch/x86/include/asm/arch-coreboot/sysinfo.h create mode 100644 arch/x86/include/asm/cb_sysinfo.h create mode 100644 arch/x86/lib/coreboot/Makefile create mode 100644 arch/x86/lib/coreboot/cb_support.c create mode 100644 arch/x86/lib/coreboot/cb_sysinfo.c create mode 100644 cmd/x86/cbsysinfo.c create mode 100644 doc/usage/x86/cbsysinfo.rst

These GPIOs are needed later if Chromium OS verified boot is running, so free them after use.
Signed-off-by: Simon Glass sjg@chromium.org ---
board/google/chromebook_coral/coral.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/board/google/chromebook_coral/coral.c b/board/google/chromebook_coral/coral.c index f9fb3f163f0..b255bf6187e 100644 --- a/board/google/chromebook_coral/coral.c +++ b/board/google/chromebook_coral/coral.c @@ -63,6 +63,8 @@ int chromeos_get_gpio(const struct udevice *dev, const char *prop, } info->flags = desc.flags & GPIOD_ACTIVE_LOW ? CROS_GPIO_ACTIVE_LOW : CROS_GPIO_ACTIVE_HIGH; + if (!ret) + dm_gpio_free(desc.dev, &desc);
return 0; }

These GPIOs are needed later if Chromium OS verified boot is running, so free them after use.
Signed-off-by: Simon Glass sjg@chromium.org ---
board/google/chromebook_coral/coral.c | 2 ++ 1 file changed, 2 insertions(+)
Applied to u-boot-dm/next, thanks!

Add detailed information on how to build the coral image, since it needs binary blobs. Provide a way to avoid the memory-training delay. Also show the console output from a sample run.
Signed-off-by: Simon Glass sjg@chromium.org ---
doc/board/google/chromebook_coral.rst | 234 ++++++++++++++++++++++++-- 1 file changed, 217 insertions(+), 17 deletions(-)
diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst index c39f1e310c7..4b585678dcf 100644 --- a/doc/board/google/chromebook_coral.rst +++ b/doc/board/google/chromebook_coral.rst @@ -16,6 +16,169 @@ Note that booting U-Boot on APL is already supported by coreboot and Slim Bootloader. This documentation refers to a 'bare metal' port.
+Building +-------- + +First, you need the following binary blobs: + + * descriptor.bin - Intel flash descriptor + * fitimage.bin - Base flash image structure + * fsp_m.bin - FSP-M, for setting up SDRAM + * fsp_s.bin - FSP-S, for setting up Silicon + * vbt.bin - for setting up display + +These binaries do not seem to be available publicly. If you have a ROM image, +such as santa.bin then you can do this:: + + cbfstool santa.bin extract -n fspm.bin -f fsp-m.bin + cbfstool santa.bin extract -n fsps.bin -f fsp-s.bin + cbfstool santa.bin extract -n vbt-santa.bin -f vbt.bin + mkdir tmp + cd tmp + dump_fmap -x ../santa.bin + mv SI_DESC ../descriptor.bin + mv IFWI ../fitimage.bin + +Put all of these files in `board/google/chromebook_coral` so they can be found +by the build. + +To build:: + + make O=/tmp/b/chromebook_coral chromebook_coral_defconfig + make O=/tmp/b/chromebook_coral -s -j30 all + +That should produce `/tmp/b/chrombook_coral/u-boot.rom` which you can use with +a Dediprog em100:: + + em100 -s -c w25q128fw -d /tmp/b/chromebook_coral/u-boot.rom -r + +or you can use flashrom to write it to the board. If you do that, make sure you +have a way to restore the old ROM without booting the board. Otherwise you may +brick it. Having said that, you may find these instructions useful if you want +to unbrick your device: + + https://chromium.googlesource.com/chromiumos/platform/ec/+/cr50_stab/docs/ca... + +You can buy Suzy-Q from Sparkfun: + + https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/main/doc... + +Note that it will hang at the SPL prompt for 21 seconds. When booting into +Chrome OS it will always select developer mode, so will wipe anything you have +on the device if you let it proceed. You have two seconds in U-Boot to stop the +auto-boot prompt and several seconds at the 'developer wipe' screen to stop it +wiping the disk. + +Here is the console output:: + + U-Boot TPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700) + Trying to boot from Mapped SPI + + U-Boot SPL 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700) + Trying to boot from Mapped SPI + + + U-Boot 2021.04-rc1-00128-g344eefcdfec-dirty (Feb 11 2021 - 20:13:08 -0700) + + CPU: Intel(R) Celeron(R) CPU N3450 @ 1.10GHz + DRAM: 3.9 GiB + MMC: sdmmc@1b,0: 1, emmc@1c,0: 2 + Video: 1024x768x32 @ b0000000 + Model: Google Coral + Net: No ethernet found. + SF: Detected w25q128fw with page size 256 Bytes, erase size 4 KiB, total 16 MiB + Hit any key to stop autoboot: 0 + cmdline=console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=${uuid}/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=${uuid} add_efi_memmap boot=local noresume noswap i915.modeset=1 Kernel command line: "console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off " + Setup located at 00090000: + + ACPI RSDP addr : 7991f000 + E820: 14 entries + Addr Size Type + d0000000 1000000 <NULL> + 0 a0000 RAM + a0000 60000 Reserved + 7b000000 800000 Reserved + 7b800000 4800000 Reserved + 7ac00000 400000 Reserved + 100000 ff00000 RAM + 10000000 2151000 Reserved + 12151000 68aaf000 RAM + 100000000 80000000 RAM + e0000000 10000000 Reserved + 7991bfd0 12e4030 Reserved + d0000000 10000000 Reserved + fed10000 8000 Reserved + Setup sectors : 1e + Root flags : 1 + Sys size : 63420 + RAM size : 0 + Video mode : ffff + Root dev : 0 + Boot flag : 0 + Jump : 66eb + Header : 53726448 + Kernel V2 + Version : 20d + Real mode switch : 0 + Start sys : 1000 + Kernel version : 38cc + @00003acc: + Type of loader : 80 + U-Boot, version 0 + Load flags : 81 + : loaded-high can-use-heap + Setup move size : 8000 + Code32 start : 100000 + Ramdisk image : 0 + Ramdisk size : 0 + Bootsect kludge : 0 + Heap end ptr : 8e00 + Ext loader ver : 0 + Ext loader type : 0 + Command line ptr : 99000 + console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off + Initrd addr max : 7fffffff + Kernel alignment : 200000 + Relocatable kernel : 1 + Min alignment : 15 + : 200000 + Xload flags : 3 + : 64-bit-entry can-load-above-4gb + Cmdline size : 7ff + Hardware subarch : 0 + HW subarch data : 0 + Payload offset : 26e + Payload length : 612045 + Setup data : 0 + Pref address : 1000000 + Init size : 1383000 + Handover offset : 0 + + Starting kernel ... + + Timer summary in microseconds (17 records): + Mark Elapsed Stage + 0 0 reset + 155,279 155,279 TPL + 237,088 81,809 end phase + 237,533 445 SPL + 816,456 578,923 end phase + 817,357 901 board_init_f + 1,061,751 244,394 board_init_r + 1,402,435 340,684 id=64 + 1,430,071 27,636 main_loop + 5,532,057 4,101,986 start_kernel + + Accumulated time: + 685 dm_r + 2,817 fast_spi + 33,095 dm_spl + 52,468 dm_f + 208,242 fsp-m + 242,221 fsp-s + 332,710 mmap_spi + + Boot flow - TPL ---------------
@@ -181,7 +344,7 @@ Partial memory map ff000000 Bottom of ROM fefc0000 Top of CAR region fef96000 Stack for FSP-M - fef40000 59000 FSP-M + fef40000 59000 FSP-M (also VPL loads here) fef11000 SPL loaded here fef10000 CONFIG_BLOBLIST_ADDR fef10000 Stack top in TPL, SPL and U-Boot before relocation @@ -195,35 +358,72 @@ Partial memory map 1110000 CONFIG_SYS_TEXT_BASE
+Speeding up SPL for development +------------------------------- + +The 21-second wait for memory training is annoying during development, since +every new image incurs this cost when booting. There is no cache to fall back on +since that area of the image is empty on start-up. + +You can add suitable cache contents to the image to fix this, for development +purposes only, like this:: + + # Read the image back after booting through SPL + em100 -s -c w25q128fw -u image.bin + + # Extract the two cache regions + binman extract -i image.bin extra *cache + + # Move them into the source directory + mv *cache board/google/chromebook_coral + +Then add something like this to the devicetree:: + + #if IS_ENABLED(CONFIG_HAVE_MRC) || IS_ENABLED(CONFIG_FSP_VERSION2) + /* Provide initial contents of the MRC data for faster development */ + rw-mrc-cache { + type = "blob"; + /* Mirror the offset in spi-flash@0 */ + offset = <0xff8e0000>; + size = <0x10000>; + filename = "board/google/chromebook_coral/rw-mrc-cache"; + }; + rw-var-mrc-cache { + type = "blob"; + size = <0x1000>; + filename = "board/google/chromebook_coral/rw-var-mrc-cache"; + }; + #endif + +This tells binman to put the cache contents in the same place as the +`rw-mrc-cache` and `rw-var-mrc-cache` regions defined by the SPI-flash driver. + + Supported peripherals ---------------------
-- UART -- SPI flash -- Video -- MMC (dev 0) and micro-SD (dev 1) -- Chrome OS EC -- Keyboard -- USB +The following have U-Boot drivers: + + - UART + - SPI flash + - Video + - MMC (dev 0) and micro-SD (dev 1) + - Chrome OS EC + - Cr50 (security chip) + - Keyboard + - USB
To do -----
- Finish peripherals - - left-side USB - - USB-C - - Cr50 (security chip: a basic driver is running but not included here) - Sound (Intel I2S support exists, but need da7219 driver) - - Various minor features supported by LPC, etc. -- Booting Chrome OS, e.g. with verified boot -- Integrate with Chrome OS vboot -- Improvements to booting from coreboot (i.e. as a coreboot target) - Use FSP-T binary instead of our own CAR implementation - Use the official FSP package instead of the coreboot one -- Enable all CPU cores - Suspend / resume -- ACPI +- Fix MMC which seems to try to read even though the card is empty +- Fix USB3 crash "WARN halted endpoint, queueing URB anyway."
Credits

Add detailed information on how to build the coral image, since it needs binary blobs. Provide a way to avoid the memory-training delay. Also show the console output from a sample run.
Signed-off-by: Simon Glass sjg@chromium.org ---
doc/board/google/chromebook_coral.rst | 234 ++++++++++++++++++++++++-- 1 file changed, 217 insertions(+), 17 deletions(-)
Applied to u-boot-dm/next, thanks!

We should not enable debugging by default. Drop this.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/misc/p2sb_emul.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/misc/p2sb_emul.c b/drivers/misc/p2sb_emul.c index 973d02d6785..51f87161d5b 100644 --- a/drivers/misc/p2sb_emul.c +++ b/drivers/misc/p2sb_emul.c @@ -7,7 +7,6 @@ */
#define LOG_CATEGORY UCLASS_MISC -#define LOG_DEBUG
#include <common.h> #include <axi.h>

We should not enable debugging by default. Drop this.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/misc/p2sb_emul.c | 1 - 1 file changed, 1 deletion(-)
Applied to u-boot-dm/next, thanks!

The Intel GPIO binding allows GPIOs to be globally numbered, so that it does not matter which GPIO bank is specified in the device tree. This is convenient and avoid confusion since the banks do not have the same number of GPIOs and the numbering is not sequential.
The GPIO uclass ensures that the device mentioned in the devicetree binding is probed. It is fine for the driver to update gpio_desc to point to a different driver, but this may not have been probed. If it has not been, then it cannot be claimed since there is no uclass data.
We could handle this in the GPIO uclass but so far it is an unusual situation so it is probably not worth the extra code. Handle this case in the GPIO driver by probing the selected device if necessary.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/gpio/intel_gpio.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c index ab46a94dbc1..f15ce7b59ee 100644 --- a/drivers/gpio/intel_gpio.c +++ b/drivers/gpio/intel_gpio.c @@ -23,6 +23,7 @@ #include <asm/pci.h> #include <asm/arch/gpio.h> #include <dm/acpi.h> +#include <dm/device-internal.h> #include <dt-bindings/gpio/x86-gpio.h>
static int intel_gpio_get_value(struct udevice *dev, uint offset) @@ -85,7 +86,7 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc,
/* * GPIO numbers are global in the device tree so it doesn't matter - * which one is used + * which @orig_dev is used */ gpio = args->args[0]; ret = intel_pinctrl_get_pad(gpio, &pinctrl, &desc->offset); @@ -97,6 +98,17 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc, desc->flags = args->args[1] & GPIO_ACTIVE_LOW ? GPIOD_ACTIVE_LOW : 0; desc->dev = dev;
+ /* + * Handle the case where the wrong GPIO device was provided, since this + * will not have been probed by the GPIO uclass before calling here + * (see gpio_request_tail()). + */ + if (orig_dev != dev) { + ret = device_probe(dev); + if (ret) + return log_msg_ret("probe", ret); + } + return 0; }

The Intel GPIO binding allows GPIOs to be globally numbered, so that it does not matter which GPIO bank is specified in the device tree. This is convenient and avoid confusion since the banks do not have the same number of GPIOs and the numbering is not sequential.
The GPIO uclass ensures that the device mentioned in the devicetree binding is probed. It is fine for the driver to update gpio_desc to point to a different driver, but this may not have been probed. If it has not been, then it cannot be claimed since there is no uclass data.
We could handle this in the GPIO uclass but so far it is an unusual situation so it is probably not worth the extra code. Handle this case in the GPIO driver by probing the selected device if necessary.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/gpio/intel_gpio.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
Applied to u-boot-dm/next, thanks!

At present the eMMC device does not have an alias so it appears after the SD card which is device 1. There is no device 0 which is odd.
Make the eMMC device be the first one. Update the boot script to use the new device.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/chromebook_coral.dts | 1 + include/configs/chromebook_coral.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts index 2ffe3b423c3..9f84480e68e 100644 --- a/arch/x86/dts/chromebook_coral.dts +++ b/arch/x86/dts/chromebook_coral.dts @@ -47,6 +47,7 @@ i2c5 = &i2c_5; i2c6 = &i2c_6; i2c7 = &i2c_7; + mmc0 = &emmc; mmc1 = &sdmmc; };
diff --git a/include/configs/chromebook_coral.h b/include/configs/chromebook_coral.h index 6e8e8ec1709..00760b8a307 100644 --- a/include/configs/chromebook_coral.h +++ b/include/configs/chromebook_coral.h @@ -12,13 +12,13 @@
#define CONFIG_BOOTCOMMAND \ "tpm init; tpm startup TPM2_SU_CLEAR; " \ - "read mmc 2:2 100000 0 80; setexpr loader *001004f0; " \ + "read mmc 0:2 100000 0 80; setexpr loader *001004f0; " \ "setexpr size *00100518; setexpr blocks $size / 200; " \ - "read mmc 2:2 100000 80 $blocks; setexpr setup $loader - 1000; " \ + "read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; " \ "setexpr cmdline_ptr $loader - 2000; " \ "setexpr.s cmdline *$cmdline_ptr; " \ "setexpr cmdline gsub %U \\${uuid}; " \ - "if part uuid mmc 2:2 uuid; then " \ + "if part uuid mmc 0:2 uuid; then " \ "zboot start 100000 0 0 0 $setup cmdline; " \ "zboot load; zboot setup; zboot dump; zboot go;" \ "fi"

On 3/15/21 2:00 PM, Simon Glass wrote:
At present the eMMC device does not have an alias so it appears after the SD card which is device 1. There is no device 0 which is odd.
Make the eMMC device be the first one. Update the boot script to use the new device.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
arch/x86/dts/chromebook_coral.dts | 1 + include/configs/chromebook_coral.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts index 2ffe3b423c3..9f84480e68e 100644 --- a/arch/x86/dts/chromebook_coral.dts +++ b/arch/x86/dts/chromebook_coral.dts @@ -47,6 +47,7 @@ i2c5 = &i2c_5; i2c6 = &i2c_6; i2c7 = &i2c_7;
mmc1 = &sdmmc; };mmc0 = &emmc;
diff --git a/include/configs/chromebook_coral.h b/include/configs/chromebook_coral.h index 6e8e8ec1709..00760b8a307 100644 --- a/include/configs/chromebook_coral.h +++ b/include/configs/chromebook_coral.h @@ -12,13 +12,13 @@
#define CONFIG_BOOTCOMMAND \ "tpm init; tpm startup TPM2_SU_CLEAR; " \
- "read mmc 2:2 100000 0 80; setexpr loader *001004f0; " \
- "read mmc 0:2 100000 0 80; setexpr loader *001004f0; " \ "setexpr size *00100518; setexpr blocks $size / 200; " \
- "read mmc 2:2 100000 80 $blocks; setexpr setup $loader - 1000; " \
- "read mmc 0:2 100000 80 $blocks; setexpr setup $loader - 1000; " \ "setexpr cmdline_ptr $loader - 2000; " \ "setexpr.s cmdline *$cmdline_ptr; " \ "setexpr cmdline gsub %U \\${uuid}; " \
- "if part uuid mmc 2:2 uuid; then " \
- "if part uuid mmc 0:2 uuid; then " \ "zboot start 100000 0 0 0 $setup cmdline; " \ "zboot load; zboot setup; zboot dump; zboot go;" \ "fi"

On 3/15/21 2:00 PM, Simon Glass wrote:
At present the eMMC device does not have an alias so it appears after the SD card which is device 1. There is no device 0 which is odd.
Make the eMMC device be the first one. Update the boot script to use the new device.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
arch/x86/dts/chromebook_coral.dts | 1 + include/configs/chromebook_coral.h | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-)
Applied to u-boot-dm/next, thanks!

Since the recent bug fix, it doesn't matter which GPIO phandle is used so long as the GPIO number is right. Still, we may as well use the correct one to avoid confusion.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/chromebook_coral.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts index 9f84480e68e..30058be1ea3 100644 --- a/arch/x86/dts/chromebook_coral.dts +++ b/arch/x86/dts/chromebook_coral.dts @@ -572,7 +572,7 @@ sdmmc: sdmmc@1b,0 { reg = <0x0000d800 0 0 0 0>; compatible = "intel,apl-sd"; - cd-gpios = <&gpio_n GPIO_177 GPIO_ACTIVE_LOW>; + cd-gpios = <&gpio_sw GPIO_177 GPIO_ACTIVE_LOW>; acpi,name = "SDCD"; };

On 3/15/21 2:00 PM, Simon Glass wrote:
Since the recent bug fix, it doesn't matter which GPIO phandle is used so long as the GPIO number is right. Still, we may as well use the correct one to avoid confusion.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
arch/x86/dts/chromebook_coral.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts index 9f84480e68e..30058be1ea3 100644 --- a/arch/x86/dts/chromebook_coral.dts +++ b/arch/x86/dts/chromebook_coral.dts @@ -572,7 +572,7 @@ sdmmc: sdmmc@1b,0 { reg = <0x0000d800 0 0 0 0>; compatible = "intel,apl-sd";
cd-gpios = <&gpio_n GPIO_177 GPIO_ACTIVE_LOW>;
};cd-gpios = <&gpio_sw GPIO_177 GPIO_ACTIVE_LOW>; acpi,name = "SDCD";

On 3/15/21 2:00 PM, Simon Glass wrote:
Since the recent bug fix, it doesn't matter which GPIO phandle is used so long as the GPIO number is right. Still, we may as well use the correct one to avoid confusion.
Signed-off-by: Simon Glass sjg@chromium.org
Reviewed-by: Jaehoon Chung jh80.chung@samsung.com
Best Regards, Jaehoon Chung
arch/x86/dts/chromebook_coral.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Applied to u-boot-dm/next, thanks!

We should not enable debugging by default. Drop this.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/sound/tegra_i2s.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/drivers/sound/tegra_i2s.c b/drivers/sound/tegra_i2s.c index 5cf82250da2..932f737900e 100644 --- a/drivers/sound/tegra_i2s.c +++ b/drivers/sound/tegra_i2s.c @@ -4,7 +4,6 @@ * Written by Simon Glass sjg@chromium.org */ #define LOG_CATEGORY UCLASS_I2S -#define LOG_DEBUG
#include <common.h> #include <dm.h>

We should not enable debugging by default. Drop this.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/sound/tegra_i2s.c | 1 - 1 file changed, 1 deletion(-)
Applied to u-boot-dm/next, thanks!

The driver currently reads the card-detect but does not register it with the MMC stack. Update this so that card-detect works as expected.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/mmc/pci_mmc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index fd5dd229b58..b9ab064b60e 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -53,6 +53,7 @@ static int pci_mmc_probe(struct udevice *dev) host->ioaddr = (void *)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); host->name = dev->name; + host->cd_gpio = priv->cd_gpio; host->mmc = &plat->mmc; host->mmc->dev = dev; ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0); @@ -68,8 +69,11 @@ static int pci_mmc_of_to_plat(struct udevice *dev) { if (CONFIG_IS_ENABLED(DM_GPIO)) { struct pci_mmc_priv *priv = dev_get_priv(dev); + int ret;
- gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN); + ret = gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, + GPIOD_IS_IN); + log_debug("cd-gpio %s done, ret=%d\n", dev->name, ret); }
return 0;

The driver currently reads the card-detect but does not register it with the MMC stack. Update this so that card-detect works as expected.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/mmc/pci_mmc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
Applied to u-boot-dm/next, thanks!

CBFS now supports attributes for things that cannot fit in the header as originally conceived. Add the structures for these.
Also rename attributes_offset to something shorter, to ease code readability.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 2 +- include/cbfs.h | 39 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 9007aa7d159..abc43ad33f6 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -129,7 +129,7 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size, new_node->name = (char *)file_header + sizeof(struct cbfs_fileheader); new_node->name_length = name_len; - new_node->attributes_offset = header.attributes_offset; + new_node->attr_offset = header.attributes_offset;
step = header.len; if (step % align) diff --git a/include/cbfs.h b/include/cbfs.h index 5f296d6a371..d98afea6480 100644 --- a/include/cbfs.h +++ b/include/cbfs.h @@ -68,6 +68,43 @@ struct cbfs_fileheader { /* offset to struct cbfs_file_attribute or 0 */ u32 attributes_offset; u32 offset; + char filename[]; +} __packed; + +/* + * Depending on how the header was initialized, it may be backed with 0x00 or + * 0xff, so support both + */ +#define CBFS_FILE_ATTR_TAG_UNUSED 0 +#define CBFS_FILE_ATTR_TAG_UNUSED2 0xffffffff +#define CBFS_FILE_ATTR_TAG_COMPRESSION 0x42435a4c +#define CBFS_FILE_ATTR_TAG_HASH 0x68736148 + +/* + * The common fields of extended cbfs file attributes. Attributes are expected + * to start with tag/len, then append their specific fields + */ +struct cbfs_file_attribute { + u32 tag; + /* len covers the whole structure, incl. tag and len */ + u32 len; + u8 data[0]; +} __packed; + +struct cbfs_file_attr_compression { + u32 tag; + u32 len; + /* whole file compression format. 0 if no compression. */ + u32 compression; + u32 decompressed_size; +} __packed; + +struct cbfs_file_attr_hash { + u32 tag; + u32 len; + u32 hash_type; + /* hash_data is len - sizeof(struct) bytes */ + u8 hash_data[]; } __packed;
struct cbfs_cachenode { @@ -77,7 +114,7 @@ struct cbfs_cachenode { u32 type; u32 data_length; u32 name_length; - u32 attributes_offset; + u32 attr_offset; };
/**

Rename this variable since there is no need to distinguish it from an old node.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index abc43ad33f6..c9323a562c6 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -87,7 +87,7 @@ static void swap_file_header(struct cbfs_fileheader *dest, * @param start The location in memory to start from. * @param size The size of the memory region to search. * @param align The alignment boundaries to check on. - * @param new_node A pointer to the file structure to load. + * @param node A pointer to the file structure to load. * @param used A pointer to the count of of bytes scanned through, * including the file if one is found. * @@ -95,7 +95,7 @@ static void swap_file_header(struct cbfs_fileheader *dest, * is found. */ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size, - int align, struct cbfs_cachenode *new_node, + int align, struct cbfs_cachenode *node, int *used) { struct cbfs_fileheader header; @@ -121,15 +121,15 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size, priv->result = CBFS_BAD_FILE; return -EBADF; } - new_node->next = NULL; - new_node->type = header.type; - new_node->data = start + header.offset; - new_node->data_length = header.len; + node->next = NULL; + node->type = header.type; + node->data = start + header.offset; + node->data_length = header.len; name_len = header.offset - sizeof(struct cbfs_fileheader); - new_node->name = (char *)file_header + + node->name = (char *)file_header + sizeof(struct cbfs_fileheader); - new_node->name_length = name_len; - new_node->attr_offset = header.attributes_offset; + node->name_length = name_len; + node->attr_offset = header.attributes_offset;
step = header.len; if (step % align) @@ -146,7 +146,7 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size, static int file_cbfs_fill_cache(struct cbfs_priv *priv, int size, int align) { struct cbfs_cachenode *cache_node; - struct cbfs_cachenode *new_node; + struct cbfs_cachenode *node; struct cbfs_cachenode **cache_tail = &priv->file_cache; void *start;
@@ -164,21 +164,21 @@ static int file_cbfs_fill_cache(struct cbfs_priv *priv, int size, int align) int used; int ret;
- new_node = (struct cbfs_cachenode *) + node = (struct cbfs_cachenode *) malloc(sizeof(struct cbfs_cachenode)); - if (!new_node) + if (!node) return -ENOMEM; - ret = file_cbfs_next_file(priv, start, size, align, new_node, + ret = file_cbfs_next_file(priv, start, size, align, node, &used);
if (ret < 0) { - free(new_node); + free(node); if (ret == -ENOENT) break; return ret; } - *cache_tail = new_node; - cache_tail = &new_node->next; + *cache_tail = node; + cache_tail = &node->next;
size -= used; start += used;

Rename this variable since there is no need to distinguish it from an old node.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
Applied to u-boot-dm/next, thanks!

When U-Boot is booted from coreboot the SMBIOS tables are written by coreboot, not U-Boot. The existing method of updating the BIOS version string does not work in that case, since gd->smbios_version is only set when U-Boot writes the tables.
Add a new function which allows the version to be updated by parsing the tables and writing the string in the correct place. Since coreboot provides a pointer to the SMBIOS tables in its sysinfo structure, this makes it easy to do the update.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/smbios.h | 20 ++++++++++++++++++++ lib/smbios-parser.c | 38 ++++++++++++++++++++++++++++++++++++++ lib/smbios.c | 4 ---- 3 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/include/smbios.h b/include/smbios.h index ecc4fd1de3b..ffeefb47372 100644 --- a/include/smbios.h +++ b/include/smbios.h @@ -14,6 +14,10 @@ #define SMBIOS_MAJOR_VER 3 #define SMBIOS_MINOR_VER 0
+enum { + SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */ +}; + /* SMBIOS structure types */ enum { SMBIOS_BIOS_INFORMATION = 0, @@ -269,4 +273,20 @@ const char *smbios_string(const struct smbios_header *header, int index); */ int smbios_update_version(const char *version);
+/** + * smbios_update_version_full() - Update the version string + * + * This can be called after the SMBIOS tables are written (e.g. after the U-Boot + * main loop has started) to update the BIOS version string (SMBIOS table 0). + * It scans for the correct place to put the version, so does not need U-Boot + * to have actually written the tables itself (e.g. if a previous bootloader + * did it). + * + * @smbios_tab: Start of SMBIOS tables + * @version: New version string to use + * @return 0 if OK, -ENOENT if no version string was previously written, + * -ENOSPC if the new string is too large to fit + */ +int smbios_update_version_full(void *smbios_tab, const char *version); + #endif /* _SMBIOS_H_ */ diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c index b89f988ef9f..34203f952c9 100644 --- a/lib/smbios-parser.c +++ b/lib/smbios-parser.c @@ -3,6 +3,8 @@ * Copyright (C) 2020, Bachmann electronic GmbH */
+#define LOG_CATEGORY LOGC_BOOT + #include <common.h> #include <smbios.h>
@@ -94,3 +96,39 @@ const char *smbios_string(const struct smbios_header *header, int index)
return string_from_smbios_table(header, index); } + +int smbios_update_version_full(void *smbios_tab, const char *version) +{ + const struct smbios_header *hdr; + struct smbios_type0 *bios; + uint old_len, len; + char *ptr; + + log_info("Updating SMBIOS table at %p\n", smbios_tab); + hdr = smbios_header(smbios_tab, SMBIOS_BIOS_INFORMATION); + if (!hdr) + return log_msg_ret("tab", -ENOENT); + bios = (struct smbios_type0 *)hdr; + ptr = (char *)smbios_string(hdr, bios->bios_ver); + if (!ptr) + return log_msg_ret("str", -ENOMEDIUM); + + /* + * This string is supposed to have at least enough bytes and is + * padded with spaces. Update it, taking care not to move the + * \0 terminator, so that other strings in the string table + * are not disturbed. See smbios_add_string() + */ + old_len = strnlen(ptr, SMBIOS_STR_MAX); + len = strnlen(version, SMBIOS_STR_MAX); + if (len > old_len) + return log_ret(-ENOSPC); + + log_debug("Replacing SMBIOS type 0 version string '%s'\n", ptr); + memcpy(ptr, version, len); +#ifdef LOG_DEBUG + print_buffer((ulong)ptr, ptr, 1, old_len + 1, 0); +#endif + + return 0; +} diff --git a/lib/smbios.c b/lib/smbios.c index 7d463c84a93..9eb226ec9fb 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -20,10 +20,6 @@
DECLARE_GLOBAL_DATA_PTR;
-enum { - SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */ -}; - /** * struct smbios_ctx - context for writing SMBIOS tables *

When U-Boot is booted from coreboot the SMBIOS tables are written by coreboot, not U-Boot. The existing method of updating the BIOS version string does not work in that case, since gd->smbios_version is only set when U-Boot writes the tables.
Add a new function which allows the version to be updated by parsing the tables and writing the string in the correct place. Since coreboot provides a pointer to the SMBIOS tables in its sysinfo structure, this makes it easy to do the update.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/smbios.h | 20 ++++++++++++++++++++ lib/smbios-parser.c | 38 ++++++++++++++++++++++++++++++++++++++ lib/smbios.c | 4 ---- 3 files changed, 58 insertions(+), 4 deletions(-)
Applied to u-boot-dm/next, thanks!

In some cases CBFS does not start with a header but is just a collection of files. It is possible to support this so long as the size of the CBFS is provided.
Update the cbfs_init_mem() function to support this.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/fsp2/fsp_init.c | 3 ++- fs/cbfs/cbfs.c | 18 +++++++++++++----- include/cbfs.h | 8 ++++++-- 3 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/arch/x86/lib/fsp2/fsp_init.c b/arch/x86/lib/fsp2/fsp_init.c index 85cae54a0ca..5afdce1e0d4 100644 --- a/arch/x86/lib/fsp2/fsp_init.c +++ b/arch/x86/lib/fsp2/fsp_init.c @@ -84,7 +84,8 @@ static int get_cbfs_fsp(enum fsp_type_t type, ulong map_base, struct cbfs_priv *cbfs; int ret;
- ret = cbfs_init_mem(map_base + cbfs_base, &cbfs); + ret = cbfs_init_mem(map_base + cbfs_base, CBFS_SIZE_UNKNOWN, true, + &cbfs); if (ret) return ret; if (!ret) { diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index c9323a562c6..13a74e6ed43 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -276,18 +276,26 @@ int file_cbfs_init(ulong end_of_rom) return cbfs_init(&cbfs_s, end_of_rom); }
-int cbfs_init_mem(ulong base, struct cbfs_priv **privp) +int cbfs_init_mem(ulong base, ulong size, bool require_hdr, + struct cbfs_priv **privp) { struct cbfs_priv priv_s, *priv = &priv_s; int ret;
/* - * Use a local variable to start with until we know that the CBFS is - * valid. + * Use a local variable to start with until we know that the * CBFS is + * valid. Note that size is detected from the header, if present, + * meaning the parameter is ignored. */ ret = cbfs_load_header_ptr(priv, base); - if (ret) - return ret; + if (ret) { + if (require_hdr || size == CBFS_SIZE_UNKNOWN) + return ret; + memset(priv, '\0', sizeof(struct cbfs_priv)); + priv->header.rom_size = size; + priv->header.align = CBFS_ALIGN_SIZE; + priv->start = (void *)base; + }
ret = file_cbfs_fill_cache(priv, priv->header.rom_size, priv->header.align); diff --git a/include/cbfs.h b/include/cbfs.h index d98afea6480..05770e2c7ec 100644 --- a/include/cbfs.h +++ b/include/cbfs.h @@ -42,6 +42,8 @@ enum cbfs_filetype {
enum { CBFS_HEADER_MAGIC = 0x4f524243, + CBFS_SIZE_UNKNOWN = 0xffffffff, + CBFS_ALIGN_SIZE = 0x40, };
/** @@ -186,11 +188,13 @@ const struct cbfs_cachenode *cbfs_find_file(struct cbfs_priv *cbfs, * cbfs_init_mem() - Set up a new CBFS * * @base: Base address of CBFS + * @size: Size of CBFS if known, else CBFS_SIZE_UNKNOWN + * @require_header: true to read a header at the start, false to not require one * @cbfsp: Returns a pointer to CBFS on success * @return 0 if OK, -ve on error */ -int cbfs_init_mem(ulong base, struct cbfs_priv **privp); - +int cbfs_init_mem(ulong base, ulong size, bool require_hdr, + struct cbfs_priv **privp);
/***************************************************************************/ /* All of the functions below can be used without first initializing CBFS. */

The file traversal functions currently use a single global CBFS. In some cases we need to access multiple CBFSs to obtain different files. Add new functions to support this.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 11 +++++++++++ include/cbfs.h | 19 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 13a74e6ed43..aed4026d653 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -325,6 +325,17 @@ const struct cbfs_header *file_cbfs_get_header(void) } }
+const struct cbfs_cachenode *cbfs_get_first(const struct cbfs_priv *priv) +{ + return priv->file_cache; +} + +void cbfs_get_next(const struct cbfs_cachenode **filep) +{ + if (*filep) + *filep = (*filep)->next; +} + const struct cbfs_cachenode *file_cbfs_get_first(void) { struct cbfs_priv *priv = &cbfs_s; diff --git a/include/cbfs.h b/include/cbfs.h index 05770e2c7ec..055edbaac2e 100644 --- a/include/cbfs.h +++ b/include/cbfs.h @@ -9,6 +9,8 @@ #include <compiler.h> #include <linux/compiler.h>
+struct cbfs_priv; + enum cbfs_result { CBFS_SUCCESS = 0, CBFS_NOT_INITIALIZED, @@ -149,6 +151,21 @@ int file_cbfs_init(ulong end_of_rom); */ const struct cbfs_header *file_cbfs_get_header(void);
+/** + * cbfs_get_first() - Get the first file in a CBFS + * + * @return pointer to first file, or NULL if it is empty + */ +const struct cbfs_cachenode *cbfs_get_first(const struct cbfs_priv *priv); + +/** + * cbfs_get_next() - Get the next file in a CBFS + * + * @filep: Pointer to current file; updated to point to the next file, if any, + * else NULL + */ +void cbfs_get_next(const struct cbfs_cachenode **filep); + /** * file_cbfs_get_first() - Get a handle for the first file in CBFS. * @@ -172,8 +189,6 @@ void file_cbfs_get_next(const struct cbfs_cachenode **file); */ const struct cbfs_cachenode *file_cbfs_find(const char *name);
-struct cbfs_priv; - /** * cbfs_find_file() - Find a file in a given CBFS *

The file_cbfs_next_file() function is already fairly long. Before expanding it further, move the core part into a separate function.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index aed4026d653..a93dc3d0c16 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -79,6 +79,35 @@ static void swap_file_header(struct cbfs_fileheader *dest, dest->offset = be32_to_cpu(src->offset); }
+/** + * fill_node() - Fill a node struct with information from the CBFS + * + * @node: Node to fill + * @start: Pointer to the start of the CBFS file in memory + * @header: Pointer to the header information (in our enddianess) + * @return 0 if OK, -EBADF if the header is too small + */ +static int fill_node(struct cbfs_cachenode *node, void *start, + struct cbfs_fileheader *header) +{ + uint name_len; + + /* Check the header is large enough */ + if (header->offset < sizeof(struct cbfs_fileheader)) + return -EBADF; + + node->next = NULL; + node->type = header->type; + node->data = start + header->offset; + node->data_length = header->len; + name_len = header->offset - sizeof(struct cbfs_fileheader); + node->name = start + sizeof(struct cbfs_fileheader); + node->name_length = name_len; + node->attr_offset = header->attributes_offset; + + return 0; +} + /* * Given a starting position in memory, scan forward, bounded by a size, and * find the next valid CBFS file. No memory is allocated by this function. The @@ -104,8 +133,8 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
while (size >= align) { const struct cbfs_fileheader *file_header = start; - u32 name_len; u32 step; + int ret;
/* Check if there's a file here. */ if (memcmp(good_file_magic, &file_header->magic, @@ -117,19 +146,11 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size, }
swap_file_header(&header, file_header); - if (header.offset < sizeof(struct cbfs_fileheader)) { + ret = fill_node(node, start, &header); + if (ret) { priv->result = CBFS_BAD_FILE; - return -EBADF; + return log_msg_ret("fill", ret); } - node->next = NULL; - node->type = header.type; - node->data = start + header.offset; - node->data_length = header.len; - name_len = header.offset - sizeof(struct cbfs_fileheader); - node->name = (char *)file_header + - sizeof(struct cbfs_fileheader); - node->name_length = name_len; - node->attr_offset = header.attributes_offset;
step = header.len; if (step % align)

The file_cbfs_next_file() function is already fairly long. Before expanding it further, move the core part into a separate function.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-)
Applied to u-boot-dm/next, thanks!

In file_cbfs_next_file() there is a lot of complicated code to move to the next file. Use the ALIGN() macros to simplify this.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index a93dc3d0c16..9e534d15f28 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -133,7 +133,6 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size,
while (size >= align) { const struct cbfs_fileheader *file_header = start; - u32 step; int ret;
/* Check if there's a file here. */ @@ -152,11 +151,7 @@ static int file_cbfs_next_file(struct cbfs_priv *priv, void *start, int size, return log_msg_ret("fill", ret); }
- step = header.len; - if (step % align) - step = step + align - step % align; - - *used += step; + *used += ALIGN(header.len, align); return 0; }

In file_cbfs_next_file() there is a lot of complicated code to move to the next file. Use the ALIGN() macros to simplify this.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-)
Applied to u-boot-dm/next, thanks!

CBFS now supports compressed filed. Add support for reading this information so that the correct decompression can be applied. The decompression itself is not implemented in CBFS.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 22 ++++++++++++++++++++++ include/cbfs.h | 11 +++++++++++ 2 files changed, 33 insertions(+)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 9e534d15f28..443a148e3f1 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -91,6 +91,7 @@ static int fill_node(struct cbfs_cachenode *node, void *start, struct cbfs_fileheader *header) { uint name_len; + uint offset;
/* Check the header is large enough */ if (header->offset < sizeof(struct cbfs_fileheader)) @@ -104,6 +105,27 @@ static int fill_node(struct cbfs_cachenode *node, void *start, node->name = start + sizeof(struct cbfs_fileheader); node->name_length = name_len; node->attr_offset = header->attributes_offset; + node->comp_algo = CBFS_COMPRESS_NONE; + node->decomp_size = 0; + + for (offset = node->attr_offset; offset < header->offset;) { + const struct cbfs_file_attribute *attr; + uint tag, len; + + attr = start + offset; + tag = be32_to_cpu(attr->tag); + len = be32_to_cpu(attr->len); + if (tag == CBFS_FILE_ATTR_TAG_COMPRESSION) { + struct cbfs_file_attr_compression *comp; + + comp = start + offset; + node->comp_algo = be32_to_cpu(comp->compression); + node->decomp_size = + be32_to_cpu(comp->decompressed_size); + } + + offset += len; + }
return 0; } diff --git a/include/cbfs.h b/include/cbfs.h index 055edbaac2e..ae94f1dcdf5 100644 --- a/include/cbfs.h +++ b/include/cbfs.h @@ -75,6 +75,15 @@ struct cbfs_fileheader { char filename[]; } __packed;
+/** + * These are standard values for the known compression alogrithms that coreboot + * knows about for stages and payloads. Of course, other CBFS users can use + * whatever values they want, as long as they understand them. + */ +#define CBFS_COMPRESS_NONE 0 +#define CBFS_COMPRESS_LZMA 1 +#define CBFS_COMPRESS_LZ4 2 + /* * Depending on how the header was initialized, it may be backed with 0x00 or * 0xff, so support both @@ -119,6 +128,8 @@ struct cbfs_cachenode { u32 data_length; u32 name_length; u32 attr_offset; + u32 comp_algo; + u32 decomp_size; };
/**

The results of malloc() are a void * and so this cast is unnecessary. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 443a148e3f1..415ea28b871 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -202,8 +202,7 @@ static int file_cbfs_fill_cache(struct cbfs_priv *priv, int size, int align) int used; int ret;
- node = (struct cbfs_cachenode *) - malloc(sizeof(struct cbfs_cachenode)); + node = malloc(sizeof(struct cbfs_cachenode)); if (!node) return -ENOMEM; ret = file_cbfs_next_file(priv, start, size, align, node,

The results of malloc() are a void * and so this cast is unnecessary. Drop it.
Signed-off-by: Simon Glass sjg@chromium.org ---
fs/cbfs/cbfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
Applied to u-boot-dm/next, thanks!

It is possible to boot U-Boot for chromebook_coral either 'bare metal' or from coreboot. In the latter case we want to provide access to the coreboot sysinfo tables. Move the definitions into a file available to any x86 board.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/coreboot/coreboot.c | 2 +- arch/x86/cpu/coreboot/sdram.c | 2 +- arch/x86/cpu/coreboot/tables.c | 2 +- arch/x86/cpu/coreboot/timestamp.c | 2 +- arch/x86/include/asm/{arch-coreboot/sysinfo.h => cb_sysinfo.h} | 0 board/coreboot/coreboot/coreboot.c | 2 +- cmd/version.c | 2 +- drivers/misc/cbmem_console.c | 2 +- drivers/serial/serial_coreboot.c | 2 +- drivers/video/coreboot.c | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename arch/x86/include/asm/{arch-coreboot/sysinfo.h => cb_sysinfo.h} (100%)
diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 15c3ad879a0..69cf8f417c7 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -14,7 +14,7 @@ #include <asm/io.h> #include <asm/msr.h> #include <asm/mtrr.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #include <asm/arch/timestamp.h>
DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index a2e47d196a2..43604ee837a 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -8,7 +8,7 @@ #include <common.h> #include <init.h> #include <asm/e820.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c index c52741ac9da..816a0efd135 100644 --- a/arch/x86/cpu/coreboot/tables.c +++ b/arch/x86/cpu/coreboot/tables.c @@ -8,7 +8,7 @@
#include <common.h> #include <net.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c index 01625978095..b1e29558826 100644 --- a/arch/x86/cpu/coreboot/timestamp.c +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -8,7 +8,7 @@ #include <common.h> #include <bootstage.h> #include <asm/arch/timestamp.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #include <linux/compiler.h>
struct timestamp_entry { diff --git a/arch/x86/include/asm/arch-coreboot/sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h similarity index 100% rename from arch/x86/include/asm/arch-coreboot/sysinfo.h rename to arch/x86/include/asm/cb_sysinfo.h diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c index 9aafb8920cd..175d3ce691a 100644 --- a/board/coreboot/coreboot/coreboot.c +++ b/board/coreboot/coreboot/coreboot.c @@ -4,7 +4,7 @@ */
#include <common.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #include <asm/global_data.h> #include <init.h> #include <smbios.h> diff --git a/cmd/version.c b/cmd/version.c index 3686b873324..685b458ce26 100644 --- a/cmd/version.c +++ b/cmd/version.c @@ -9,7 +9,7 @@ #include <version.h> #include <linux/compiler.h> #ifdef CONFIG_SYS_COREBOOT -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h> #endif
const char __weak version_string[] = U_BOOT_VERSION_STRING; diff --git a/drivers/misc/cbmem_console.c b/drivers/misc/cbmem_console.c index 5ba0a542060..8bbe33d414d 100644 --- a/drivers/misc/cbmem_console.c +++ b/drivers/misc/cbmem_console.c @@ -9,7 +9,7 @@ #error This driver requires coreboot #endif
-#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h>
struct cbmem_console { u32 buffer_size; diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c index 88c8209c5db..de09c8681f5 100644 --- a/drivers/serial/serial_coreboot.c +++ b/drivers/serial/serial_coreboot.c @@ -9,7 +9,7 @@ #include <dm.h> #include <ns16550.h> #include <serial.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h>
static int coreboot_of_to_plat(struct udevice *dev) { diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c index 0a5fb08dc8a..55f72fe886f 100644 --- a/drivers/video/coreboot.c +++ b/drivers/video/coreboot.c @@ -7,7 +7,7 @@ #include <dm.h> #include <vbe.h> #include <video.h> -#include <asm/arch/sysinfo.h> +#include <asm/cb_sysinfo.h>
static int save_vesa_mode(struct cb_framebuffer *fb, struct vesa_mode_info *vesa)

It is possible to boot U-Boot for chromebook_coral either 'bare metal' or from coreboot. In the latter case we want to provide access to the coreboot sysinfo tables. Move the definitions into a file available to any x86 board.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/coreboot/coreboot.c | 2 +- arch/x86/cpu/coreboot/sdram.c | 2 +- arch/x86/cpu/coreboot/tables.c | 2 +- arch/x86/cpu/coreboot/timestamp.c | 2 +- arch/x86/include/asm/{arch-coreboot/sysinfo.h => cb_sysinfo.h} | 0 board/coreboot/coreboot/coreboot.c | 2 +- cmd/version.c | 2 +- drivers/misc/cbmem_console.c | 2 +- drivers/serial/serial_coreboot.c | 2 +- drivers/video/coreboot.c | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename arch/x86/include/asm/{arch-coreboot/sysinfo.h => cb_sysinfo.h} (100%)
Applied to u-boot-dm/next, thanks!

This all relates to the sysinfo structure provided by coreboot. Put the timestamp definitions into the same file as the others. Tidy up a few comments at the same time.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/coreboot/timestamp.c | 12 ------ .../x86/include/asm/arch-coreboot/timestamp.h | 25 +----------- arch/x86/include/asm/coreboot_tables.h | 38 +++++++++++++++++++ 3 files changed, 39 insertions(+), 36 deletions(-)
diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c index b1e29558826..7f133cefae3 100644 --- a/arch/x86/cpu/coreboot/timestamp.c +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -11,18 +11,6 @@ #include <asm/cb_sysinfo.h> #include <linux/compiler.h>
-struct timestamp_entry { - uint32_t entry_id; - uint64_t entry_stamp; -} __packed; - -struct timestamp_table { - uint64_t base_time; - uint32_t max_entries; - uint32_t num_entries; - struct timestamp_entry entries[0]; /* Variable number of entries */ -} __packed; - static struct timestamp_table *ts_table __attribute__((section(".data")));
void timestamp_init(void) diff --git a/arch/x86/include/asm/arch-coreboot/timestamp.h b/arch/x86/include/asm/arch-coreboot/timestamp.h index 85d42c02c46..531526b3141 100644 --- a/arch/x86/include/asm/arch-coreboot/timestamp.h +++ b/arch/x86/include/asm/arch-coreboot/timestamp.h @@ -8,30 +8,7 @@ #ifndef __COREBOOT_TIMESTAMP_H__ #define __COREBOOT_TIMESTAMP_H__
-enum timestamp_id { - /* coreboot specific timestamp IDs */ - TS_START_ROMSTAGE = 1, - TS_BEFORE_INITRAM = 2, - TS_AFTER_INITRAM = 3, - TS_END_ROMSTAGE = 4, - TS_START_COPYRAM = 8, - TS_END_COPYRAM = 9, - TS_START_RAMSTAGE = 10, - TS_DEVICE_ENUMERATE = 30, - TS_DEVICE_CONFIGURE = 40, - TS_DEVICE_ENABLE = 50, - TS_DEVICE_INITIALIZE = 60, - TS_DEVICE_DONE = 70, - TS_CBMEM_POST = 75, - TS_WRITE_TABLES = 80, - TS_LOAD_PAYLOAD = 90, - TS_ACPI_WAKE_JUMP = 98, - TS_SELFBOOT_JUMP = 99, - - /* U-Boot entry IDs start at 1000 */ - TS_U_BOOT_INITTED = 1000, /* This is where u-boot starts */ - TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel. */ -}; +#include <asm/cb_sysinfo.h>
void timestamp_init(void); void timestamp_add(enum timestamp_id id, uint64_t ts_time); diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h index 7e1576768be..dec0c14ec71 100644 --- a/arch/x86/include/asm/coreboot_tables.h +++ b/arch/x86/include/asm/coreboot_tables.h @@ -8,6 +8,44 @@ #ifndef _COREBOOT_TABLES_H #define _COREBOOT_TABLES_H
+struct timestamp_entry { + u32 entry_id; + u64 entry_stamp; +} __packed; + +struct timestamp_table { + u64 base_time; + u16 max_entries; + u16 tick_freq_mhz; + u32 num_entries; + struct timestamp_entry entries[0]; /* Variable number of entries */ +} __packed; + +enum timestamp_id { + /* coreboot specific timestamp IDs */ + TS_START_ROMSTAGE = 1, + TS_BEFORE_INITRAM = 2, + TS_AFTER_INITRAM = 3, + TS_END_ROMSTAGE = 4, + TS_START_COPYRAM = 8, + TS_END_COPYRAM = 9, + TS_START_RAMSTAGE = 10, + TS_DEVICE_ENUMERATE = 30, + TS_DEVICE_CONFIGURE = 40, + TS_DEVICE_ENABLE = 50, + TS_DEVICE_INITIALIZE = 60, + TS_DEVICE_DONE = 70, + TS_CBMEM_POST = 75, + TS_WRITE_TABLES = 80, + TS_LOAD_PAYLOAD = 90, + TS_ACPI_WAKE_JUMP = 98, + TS_SELFBOOT_JUMP = 99, + + /* U-Boot entry IDs start at 1000 */ + TS_U_BOOT_INITTED = 1000, /* This is where U-Boot starts */ + TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel */ +}; + struct memory_area;
struct cbuint64 {

This all relates to the sysinfo structure provided by coreboot. Put the timestamp definitions into the same file as the others. Tidy up a few comments at the same time.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/coreboot/timestamp.c | 12 ------ .../x86/include/asm/arch-coreboot/timestamp.h | 25 +----------- arch/x86/include/asm/coreboot_tables.h | 38 +++++++++++++++++++ 3 files changed, 39 insertions(+), 36 deletions(-)
Applied to u-boot-dm/next, thanks!

Add new timestamp codes that are present in coreboot, so that we can decode these in U-Boot.
At present TS_U_BOOT_START_KERNEL is used twice. It should only be used just before jumping to Linux, so update the other call site to use TS_START_KERNEL.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/coreboot_tables.h | 64 +++++++++++++++++++++++++- arch/x86/lib/bootm.c | 2 +- 2 files changed, 64 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h index dec0c14ec71..3172814d09a 100644 --- a/arch/x86/include/asm/coreboot_tables.h +++ b/arch/x86/include/asm/coreboot_tables.h @@ -22,14 +22,24 @@ struct timestamp_table { } __packed;
enum timestamp_id { - /* coreboot specific timestamp IDs */ + /* coreboot-specific timestamp IDs */ TS_START_ROMSTAGE = 1, TS_BEFORE_INITRAM = 2, TS_AFTER_INITRAM = 3, TS_END_ROMSTAGE = 4, + TS_START_VBOOT = 5, + TS_END_VBOOT = 6, TS_START_COPYRAM = 8, TS_END_COPYRAM = 9, TS_START_RAMSTAGE = 10, + TS_START_BOOTBLOCK = 11, + TS_END_BOOTBLOCK = 12, + TS_START_COPYROM = 13, + TS_END_COPYROM = 14, + TS_START_ULZMA = 15, + TS_END_ULZMA = 16, + TS_START_ULZ4F = 17, + TS_END_ULZ4F = 18, TS_DEVICE_ENUMERATE = 30, TS_DEVICE_CONFIGURE = 40, TS_DEVICE_ENABLE = 50, @@ -37,12 +47,64 @@ enum timestamp_id { TS_DEVICE_DONE = 70, TS_CBMEM_POST = 75, TS_WRITE_TABLES = 80, + TS_FINALIZE_CHIPS = 85, TS_LOAD_PAYLOAD = 90, TS_ACPI_WAKE_JUMP = 98, TS_SELFBOOT_JUMP = 99,
+ /* 500+ reserved for vendorcode extensions (500-600: google/chromeos) */ + TS_START_COPYVER = 501, + TS_END_COPYVER = 502, + TS_START_TPMINIT = 503, + TS_END_TPMINIT = 504, + TS_START_VERIFY_SLOT = 505, + TS_END_VERIFY_SLOT = 506, + TS_START_HASH_BODY = 507, + TS_DONE_LOADING = 508, + TS_DONE_HASHING = 509, + TS_END_HASH_BODY = 510, + TS_START_COPYVPD = 550, + TS_END_COPYVPD_RO = 551, + TS_END_COPYVPD_RW = 552, + + /* 940-950 reserved for vendorcode extensions (940-950: Intel ME) */ + TS_ME_INFORM_DRAM_WAIT = 940, + TS_ME_INFORM_DRAM_DONE = 941, + + /* 950+ reserved for vendorcode extensions (950-999: intel/fsp) */ + TS_FSP_MEMORY_INIT_START = 950, + TS_FSP_MEMORY_INIT_END = 951, + TS_FSP_TEMP_RAM_EXIT_START = 952, + TS_FSP_TEMP_RAM_EXIT_END = 953, + TS_FSP_SILICON_INIT_START = 954, + TS_FSP_SILICON_INIT_END = 955, + TS_FSP_BEFORE_ENUMERATE = 956, + TS_FSP_AFTER_ENUMERATE = 957, + TS_FSP_BEFORE_FINALIZE = 958, + TS_FSP_AFTER_FINALIZE = 959, + TS_FSP_BEFORE_END_OF_FIRMWARE = 960, + TS_FSP_AFTER_END_OF_FIRMWARE = 961, + + /* 1000+ reserved for payloads (1000-1200: ChromeOS depthcharge) */ + /* U-Boot entry IDs start at 1000 */ TS_U_BOOT_INITTED = 1000, /* This is where U-Boot starts */ + + TS_RO_PARAMS_INIT = 1001, + TS_RO_VB_INIT = 1002, + TS_RO_VB_SELECT_FIRMWARE = 1003, + TS_RO_VB_SELECT_AND_LOAD_KERNEL = 1004, + + TS_RW_VB_SELECT_AND_LOAD_KERNEL = 1010, + + TS_VB_SELECT_AND_LOAD_KERNEL = 1020, + TS_VB_EC_VBOOT_DONE = 1030, + TS_VB_STORAGE_INIT_DONE = 1040, + TS_VB_READ_KERNEL_DONE = 1050, + TS_VB_VBOOT_DONE = 1100, + + TS_START_KERNEL = 1101, + TS_KERNEL_DECOMPRESSION = 1102, TS_U_BOOT_START_KERNEL = 1100, /* Right before jumping to kernel */ };
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c index aa5f0bf6b72..733dd712570 100644 --- a/arch/x86/lib/bootm.c +++ b/arch/x86/lib/bootm.c @@ -36,7 +36,7 @@ void bootm_announce_and_cleanup(void) printf("\nStarting kernel ...\n\n");
#ifdef CONFIG_SYS_COREBOOT - timestamp_add_now(TS_U_BOOT_START_KERNEL); + timestamp_add_now(TS_START_KERNEL); #endif bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel"); #if CONFIG_IS_ENABLED(BOOTSTAGE_REPORT)

Add new timestamp codes that are present in coreboot, so that we can decode these in U-Boot.
At present TS_U_BOOT_START_KERNEL is used twice. It should only be used just before jumping to Linux, so update the other call site to use TS_START_KERNEL.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/coreboot_tables.h | 64 +++++++++++++++++++++++++- arch/x86/lib/bootm.c | 2 +- 2 files changed, 64 insertions(+), 2 deletions(-)
Applied to u-boot-dm/next, thanks!

It is useful to be able to parse coreboot tables on any x86 build which is booted from coreboot. Add a new Kconfig option to enable this feature and move the code so it can be used on any board, if enabled.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/Kconfig | 21 +++++++++++++++++++ arch/x86/cpu/coreboot/Makefile | 1 - arch/x86/lib/Makefile | 1 + arch/x86/lib/coreboot/Makefile | 6 ++++++ .../tables.c => lib/coreboot/cb_sysinfo.c} | 0 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 arch/x86/lib/coreboot/Makefile rename arch/x86/{cpu/coreboot/tables.c => lib/coreboot/cb_sysinfo.c} (100%)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index eddf2a774ef..ef2df10d38d 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1023,4 +1023,25 @@ config INTEL_GMA_SWSMISCI Select this option for Atom-based platforms which use the SWSMISCI register (0xe0) rather than the SWSCI register (0xe8).
+config COREBOOT_SYSINFO + bool "Support reading coreboot sysinfo" + default y if SYS_COREBOOT + help + Select this option to read the coreboot sysinfo table on start-up, + if present. This is written by coreboot before it exits and provides + various pieces of information about the running system, including + display, memory and build information. It is stored in + struct sysinfo_t after parsing by get_coreboot_info(). + +config SPL_COREBOOT_SYSINFO + bool "Support reading coreboot sysinfo" + depends on SPL + default y if COREBOOT_SYSINFO + help + Select this option to read the coreboot sysinfo table in SPL, + if present. This is written by coreboot before it exits and provides + various pieces of information about the running system, including + display, memory and build information. It is stored in + struct sysinfo_t after parsing by get_coreboot_info(). + endmenu diff --git a/arch/x86/cpu/coreboot/Makefile b/arch/x86/cpu/coreboot/Makefile index 605f90304e3..a6cdb9a1485 100644 --- a/arch/x86/cpu/coreboot/Makefile +++ b/arch/x86/cpu/coreboot/Makefile @@ -20,5 +20,4 @@ else obj-y += sdram.o endif obj-y += coreboot.o -obj-y += tables.o obj-y += timestamp.o diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 1bcbb49a61f..65d9b3bd6a3 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -15,6 +15,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_CMD_BOOTM) += bootm.o endif obj-y += cmd_boot.o +obj-$(CONFIG_$(SPL_)COREBOOT_SYSINFO) += coreboot/ obj-$(CONFIG_SEABIOS) += coreboot_table.o obj-y += early_cmos.o obj-y += e820.o diff --git a/arch/x86/lib/coreboot/Makefile b/arch/x86/lib/coreboot/Makefile new file mode 100644 index 00000000000..b5250d916b2 --- /dev/null +++ b/arch/x86/lib/coreboot/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2021 Google LLC +# + +obj-y += cb_sysinfo.o diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/lib/coreboot/cb_sysinfo.c similarity index 100% rename from arch/x86/cpu/coreboot/tables.c rename to arch/x86/lib/coreboot/cb_sysinfo.c

It is useful to be able to parse coreboot tables on any x86 build which is booted from coreboot. Add a new Kconfig option to enable this feature and move the code so it can be used on any board, if enabled.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/Kconfig | 21 +++++++++++++++++++ arch/x86/cpu/coreboot/Makefile | 1 - arch/x86/lib/Makefile | 1 + arch/x86/lib/coreboot/Makefile | 6 ++++++ .../tables.c => lib/coreboot/cb_sysinfo.c} | 0 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 arch/x86/lib/coreboot/Makefile rename arch/x86/{cpu/coreboot/tables.c => lib/coreboot/cb_sysinfo.c} (100%)
Applied to u-boot-dm/next, thanks!

Quite a few new tag types have been added over the years. Bring these into U-Boot so that all required tags can be parsed.
Add a proper comment to struct sysinfo_t while we are here, since many of the meanings are not obvious.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/cb_sysinfo.h | 164 +++++++++++++++- arch/x86/include/asm/coreboot_tables.h | 161 +++++++++++++--- arch/x86/lib/coreboot/cb_sysinfo.c | 257 ++++++++++++++++++++++--- 3 files changed, 525 insertions(+), 57 deletions(-)
diff --git a/arch/x86/include/asm/cb_sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h index 419ec529335..675eef6f2c9 100644 --- a/arch/x86/include/asm/cb_sysinfo.h +++ b/arch/x86/include/asm/cb_sysinfo.h @@ -14,15 +14,141 @@ #define SYSINFO_MAX_MEM_RANGES 32 /* Allow a maximum of 8 GPIOs */ #define SYSINFO_MAX_GPIOS 8 +/* Up to 10 MAC addresses */ +#define SYSINFO_MAX_MACS 10
+/** + * struct sysinfo_t - Information passed to U-Boot from coreboot + * + * Coreboot passes on a lot of information using a list of individual data + * structures identified by a numeric tag. These are parsed in U-Boot to produce + * this struct. Some of the pointers here point back to the tagged data + * structure, since it is assumed to remain around while U-Boot is running. + * + * The 'cbsysinfo' command can display this information. + * + * @cpu_khz: CPU frequence in KHz (e.g. 1100000) + * @serial: Pointer to the serial information, NULL if none + * @ser_ioport: Not actually provided by a tag and not used on modern hardware, + * which typicaally uses a memory-mapped port + * @ser_base: Not used at all, but present to match up with the coreboot data + * structure + * @n_memranges: Number of memory ranges + * @memrange: List of memory ranges: + * @base: Base address of range + * @size: Size of range in bytes + * @type: Type of range (CB_MEM_RAM, etc.) + * @option_table: Provides a pointer to the CMOS RAM options table, which + * indicates which options are available. The header is followed by a list + * of struct cb_cmos_entries records, so that an option can be found from + * its name. This is not used in U-Boot. NULL if not present + * @cmos_range_start: Start bit of the CMOS checksum range (in fact this must + * be a multiple of 8) + * @cmos_range_end: End bit of the CMOS checksum range (multiple of 8). This is + * the inclusive end. + * @cmos_checksum_location: Location of checksum, multiplied by 8. This is the + * byte offset into the CMOS RAM of the first checksum byte. The second one + * follows immediately. The checksum is a simple 16-bit sum of all the + * bytes from offset cmos_range_start / 8 to cmos_range_end / 8, inclusive, + * in big-endian format (so sum >> 8 is stored in the first byte). + * @vbnv_start: Start offset of CMOS RAM used for Chromium OS verified boot + * (typically 0x34) + * @vbnv_size: Number of bytes used by Chromium OS verified boot (typically + * 0x10) + * @extra_version: Extra version information, typically "" + * @build: Build date, e.g. "Wed Nov 18 02:51:58 UTC 2020" + * @compile_time: Compilation time, e.g. "02:51:58" + * @compile_by: Who compiled coreboot (never set?) + * @compile_host: Name of the machine that compiled coreboot (never set?) + * @compile_domain: Domain name of the machine that compiled coreboot (never + * set?) + * @compiler: Name of the compiler used to build coreboot (never set?) + * @linker: Name of the linker used to build coreboot (never set?) + * @assembler: Name of the assembler used to build coreboot (never set?) + * @cb_version: Coreboot version string, e.g. v1.9308_26_0.0.22-2599-g232f22c75d + * @framebuffer: Address of framebuffer tag, or NULL if none. See + * struct cb_framebuffer for the definition + * @num_gpios: Number of verified-boot GPIOs + * @gpios: List of GPIOs: + * @port: GPIO number, or 0xffffffff if not a GPIO + * @polarity: CB_GPIO_ACTIVE_LOW or CB_GPIO_ACTIVE_HIGH + * @value: Value of GPIO (0 or 1) + * @name: Name of GPIO + * + * A typical list is: + * id: port polarity val name + * 0: - active-high 1 write protect + * 1: - active-high 0 recovery + * 2: - active-high 1 lid + * 3: - active-high 0 power + * 4: - active-high 0 oprom + * 5: 29 active-high 0 EC in RW + * + * @num_macs: Number of MAC addresses + * @macs: List of MAC addresses + * @serialno: Serial number, or NULL (never set?) + * @mbtable: Address of the multiboot table, or NULL. This is a + * struct multiboot_header, not used in U-Boot + * @header: Address of header, if there is a CB_TAG_FORWARD, else NULL + * @mainboard: Pointer to mainboard info or NULL. Typically the vendor is + * "Google" and the part number is "" + * @vboot_handoff: Pointer to Chromium OS verified boot hand-off information. + * This is struct vboot_handoff, providing access to internal information + * generated by coreboot when this is being used + * @vboot_handoff_size: Size of hand-off information (typically 0xc0c) + * @vdat_addr: Pointer to Chromium OS verified boot data, which uses + * struct chromeos_acpi. It sits in the Intel Global NVS struct, after the + * first 0x100 bytes + * @vdat_size: Size of this data, typically 0xf00 + * @smbios_start: Address of SMBIOS tables + * @smbios_size: Size of SMBIOS tables (e.g. 0x800) + * @x86_rom_var_mtrr_index: MTRR number used for ROM caching. Not used in U-Boot + * @tstamp_table: Pointer to timestamp_table, struct timestamp_table + * @cbmem_cons: Pointer to the console dump, struct cbmem_console. This provides + * access to the console output generated by coreboot, typically about 64KB + * and mostly PCI enumeration info + * @mrc_cache: Pointer to memory-reference-code cache, typically NULL + * acpi_gnvs: @Pointer to Intel Global NVS struct, see struct acpi_global_nvs + * @board_id: Board ID indicating the board variant, typically 0xffffffff + * @ram_code: RAM code indicating the SDRAM type, typically 0xffffffff + * @wifi_calibration: WiFi calibration info, NULL if none + * @ramoops_buffer: Address of kernel Ramoops buffer + * @ramoops_buffer_size: Sizeof of Ramoops buffer, typically 1MB + * @spi_flash: Information about SPI flash: + * @size: Size in bytes, e.g. 16MB + * @sector_size; Sector size of flash device, e.g. 4KB + * @erase_cmd: Command used to erase flash, or 0 if not used + * @fmap_offset: SPI-flash offset of the flash map (FMAP) table. This has a + * __FMAP__ header. It provides information about the different top-level + * sections in the SPI flash, e.g. 0x204000 + * @cbfs_offset: SPI-flash offset of the Coreboot Filesystem (CBFS) used for + * read-only data, e.g. 0x205000. This is typically called 'COREBOOT' in + * the flash map. It holds various coreboot binaries as well as + * video-configuration files and graphics data for the Chromium OS + * verified boot user interface. + * @cbfs_size: Size of CBFS, e.g. 0x17b000 + * @boot_media_size; Size of boot media (i.e. SPI flash), e.g. 16MB + * @mtc_start; Start of MTC region (Nvidia private data), 0 if not used. See + * https://chromium.googlesource.com/chromiumos/third_party/coreboot/+/chromeos... + * @mtc_size: Size of MTC region + * @chromeos_vpd: Chromium OS Vital Product Data region, typically NULL, meaning + * not used + */ struct sysinfo_t { + unsigned int cpu_khz; + struct cb_serial *serial; + unsigned short ser_ioport; + unsigned long ser_base; // for mmapped serial + int n_memranges; + struct memrange { unsigned long long base; unsigned long long size; unsigned int type; } memrange[SYSINFO_MAX_MEM_RANGES];
+ struct cb_cmos_option_table *option_table; u32 cmos_range_start; u32 cmos_range_end; u32 cmos_checksum_location; @@ -40,19 +166,51 @@ struct sysinfo_t { char *linker; char *assembler;
+ char *cb_version; + struct cb_framebuffer *framebuffer;
int num_gpios; struct cb_gpio gpios[SYSINFO_MAX_GPIOS]; + int num_macs; + struct mac_address macs[SYSINFO_MAX_MACS]; + char *serialno; + + unsigned long *mbtable; /** Pointer to the multiboot table */
+ struct cb_header *header; + struct cb_mainboard *mainboard; + + void *vboot_handoff; + u32 vboot_handoff_size; void *vdat_addr; u32 vdat_size; - void *tstamp_table; - void *cbmem_cons; u64 smbios_start; u32 smbios_size;
- struct cb_serial *serial; + int x86_rom_var_mtrr_index; + + void *tstamp_table; + void *cbmem_cons; + void *mrc_cache; + void *acpi_gnvs; + u32 board_id; + u32 ram_code; + void *wifi_calibration; + u64 ramoops_buffer; + u32 ramoops_buffer_size; + struct { + u32 size; + u32 sector_size; + u32 erase_cmd; + } spi_flash; + u64 fmap_offset; + u64 cbfs_offset; + u64 cbfs_size; + u64 boot_media_size; + u64 mtc_start; + u32 mtc_size; + void *chromeos_vpd; };
extern struct sysinfo_t lib_sysinfo; diff --git a/arch/x86/include/asm/coreboot_tables.h b/arch/x86/include/asm/coreboot_tables.h index 3172814d09a..a74654bbe3a 100644 --- a/arch/x86/include/asm/coreboot_tables.h +++ b/arch/x86/include/asm/coreboot_tables.h @@ -262,13 +262,14 @@ struct cb_framebuffer { };
#define CB_TAG_GPIO 0x0013 -#define GPIO_MAX_NAME_LENGTH 16 - +#define CB_GPIO_ACTIVE_LOW 0 +#define CB_GPIO_ACTIVE_HIGH 1 +#define CB_GPIO_MAX_NAME_LENGTH 16 struct cb_gpio { u32 port; u32 polarity; u32 value; - u8 name[GPIO_MAX_NAME_LENGTH]; + u8 name[CB_GPIO_MAX_NAME_LENGTH]; };
struct cb_gpios { @@ -281,61 +282,158 @@ struct cb_gpios { #define CB_TAG_FDT 0x0014
struct cb_fdt { - uint32_t tag; - uint32_t size; /* size of the entire entry */ + u32 tag; + u32 size; /* size of the entire entry */ /* the actual FDT gets placed here */ };
#define CB_TAG_VDAT 0x0015
struct cb_vdat { - uint32_t tag; - uint32_t size; /* size of the entire entry */ + u32 tag; + u32 size; /* size of the entire entry */ void *vdat_addr; - uint32_t vdat_size; + u32 vdat_size; };
#define CB_TAG_TIMESTAMPS 0x0016 #define CB_TAG_CBMEM_CONSOLE 0x0017 + +struct cbmem_console { + u32 size; + u32 cursor; + char body[0]; +} __packed; + #define CB_TAG_MRC_CACHE 0x0018
struct cb_cbmem_tab { - uint32_t tag; - uint32_t size; - void *cbmem_tab; + u32 tag; + u32 size; + u64 cbmem_tab; };
#define CB_TAG_VBNV 0x0019
struct cb_vbnv { - uint32_t tag; - uint32_t size; - uint32_t vbnv_start; - uint32_t vbnv_size; + u32 tag; + u32 size; + u32 vbnv_start; + u32 vbnv_size; +}; + +#define CB_TAG_VBOOT_HANDOFF 0x0020 + +#define CB_TAG_X86_ROM_MTRR 0x0021 +struct cb_x86_rom_mtrr { + u32 tag; + u32 size; + /* + * The variable range MTRR index covering the ROM. If one wants to + * enable caching the ROM, the variable MTRR needs to be set to + * write-protect. To disable the caching after enabling set the + * type to uncacheable + */ + u32 index; +}; + +#define CB_TAG_DMA 0x0022 +#define CB_TAG_RAM_OOPS 0x0023 +#define CB_TAG_ACPI_GNVS 0x0024 + +#define CB_TAG_BOARD_ID 0x0025 +struct cb_board_id { + u32 tag; + u32 size; + /* Board ID as retrieved from the board revision GPIOs. */ + u32 board_id; +}; + +#define CB_TAG_MAC_ADDRS 0x0026 +struct mac_address { + u8 mac_addr[6]; + u8 pad[2]; /* Pad it to 8 bytes to keep it simple. */ +}; + +struct cb_macs { + u32 tag; + u32 size; + u32 count; + struct mac_address mac_addrs[0]; };
-#define CB_TAG_CBMEM_ENTRY 0x0031 -#define CBMEM_ID_SMBIOS 0x534d4254 +#define CB_TAG_WIFI_CALIBRATION 0x0027 + +#define CB_TAG_RAM_CODE 0x0028 +struct cb_ram_code { + u32 tag; + u32 size; + u32 ram_code; +}; + +#define CB_TAG_SPI_FLASH 0x0029 +struct cb_spi_flash { + u32 tag; + u32 size; + u32 flash_size; + u32 sector_size; + u32 erase_cmd; +}; + +#define CB_TAG_MTC 0x002b +#define CB_TAG_VPD 0x002c +struct lb_range { + u32 tag; + u32 size; + u64 range_start; + u32 range_size; +}; + +#define CB_TAG_BOOT_MEDIA_PARAMS 0x0030 +struct cb_boot_media_params { + u32 tag; + u32 size; + /* offsets are relative to start of boot media */ + u64 fmap_offset; + u64 cbfs_offset; + u64 cbfs_size; + u64 boot_media_size; +}; + +#define CB_TAG_CBMEM_ENTRY 0x0031 +#define CBMEM_ID_SMBIOS 0x534d4254
struct cb_cbmem_entry { - uint32_t tag; - uint32_t size; - uint64_t address; - uint32_t entry_size; - uint32_t id; + u32 tag; + u32 size; + u64 address; + u32 entry_size; + u32 id; };
+#define CB_TAG_TSC_INFO 0x0032 +struct cb_tsc_info { + u32 tag; + u32 size; + + u32 freq_khz; +}; + +#define CB_TAG_SERIALNO 0x002a +#define CB_MAX_SERIALNO_LENGTH 32 + #define CB_TAG_CMOS_OPTION_TABLE 0x00c8
struct cb_cmos_option_table { u32 tag; u32 size; u32 header_length; + /* entries follow after this header */ };
#define CB_TAG_OPTION 0x00c9
-#define CMOS_MAX_NAME_LENGTH 32 +#define CB_CMOS_MAX_NAME_LENGTH 32
struct cb_cmos_entries { u32 tag; @@ -344,34 +442,33 @@ struct cb_cmos_entries { u32 length; u32 config; u32 config_id; - u8 name[CMOS_MAX_NAME_LENGTH]; + u8 name[CB_CMOS_MAX_NAME_LENGTH]; };
#define CB_TAG_OPTION_ENUM 0x00ca -#define CMOS_MAX_TEXT_LENGTH 32 - +#define CB_CMOS_MAX_TEXT_LENGTH 32 struct cb_cmos_enums { u32 tag; u32 size; u32 config_id; u32 value; - u8 text[CMOS_MAX_TEXT_LENGTH]; + u8 text[CB_CMOS_MAX_TEXT_LENGTH]; };
#define CB_TAG_OPTION_DEFAULTS 0x00cb -#define CMOS_IMAGE_BUFFER_SIZE 128 +#define CB_CMOS_IMAGE_BUFFER_SIZE 128
struct cb_cmos_defaults { u32 tag; u32 size; u32 name_length; - u8 name[CMOS_MAX_NAME_LENGTH]; - u8 default_set[CMOS_IMAGE_BUFFER_SIZE]; + u8 name[CB_CMOS_MAX_NAME_LENGTH]; + u8 default_set[CB_CMOS_IMAGE_BUFFER_SIZE]; };
#define CB_TAG_OPTION_CHECKSUM 0x00cc -#define CHECKSUM_NONE 0 -#define CHECKSUM_PCBIOS 1 +#define CB_CHECKSUM_NONE 0 +#define CB_CHECKSUM_PCBIOS 1
struct cb_cmos_checksum { u32 tag; diff --git a/arch/x86/lib/coreboot/cb_sysinfo.c b/arch/x86/lib/coreboot/cb_sysinfo.c index 816a0efd135..e2c65bfb1ee 100644 --- a/arch/x86/lib/coreboot/cb_sysinfo.c +++ b/arch/x86/lib/coreboot/cb_sysinfo.c @@ -7,8 +7,10 @@ */
#include <common.h> -#include <net.h> #include <asm/cb_sysinfo.h> +#include <init.h> +#include <mapmem.h> +#include <net.h> #include <asm/global_data.h>
DECLARE_GLOBAL_DATA_PTR; @@ -29,7 +31,7 @@ struct sysinfo_t lib_sysinfo __attribute__((section(".data"))); */
/* === Parsing code === */ -/* This is the generic parsing code. */ +/* This is the generic parsing code */
static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info) { @@ -61,15 +63,24 @@ static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info) static void cb_parse_serial(unsigned char *ptr, struct sysinfo_t *info) { struct cb_serial *ser = (struct cb_serial *)ptr; + info->serial = ser; }
+static void cb_parse_vboot_handoff(unsigned char *ptr, struct sysinfo_t *info) +{ + struct lb_range *vbho = (struct lb_range *)ptr; + + info->vboot_handoff = (void *)(uintptr_t)vbho->range_start; + info->vboot_handoff_size = vbho->range_size; +} + static void cb_parse_vbnv(unsigned char *ptr, struct sysinfo_t *info) { - struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr; + struct lb_range *vbnv = (struct lb_range *)ptr;
- info->vbnv_start = vbnv->vbnv_start; - info->vbnv_size = vbnv->vbnv_size; + info->vbnv_start = vbnv->range_start; + info->vbnv_size = vbnv->range_size; }
static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info) @@ -97,25 +108,79 @@ static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info)
static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info) { - struct cb_vdat *vdat = (struct cb_vdat *) ptr; + struct lb_range *vdat = (struct lb_range *)ptr; + + info->vdat_addr = map_sysmem(vdat->range_start, vdat->range_size); + info->vdat_size = vdat->range_size; +} + +static void cb_parse_mac_addresses(unsigned char *ptr, + struct sysinfo_t *info) +{ + struct cb_macs *macs = (struct cb_macs *)ptr; + int i; + + info->num_macs = (macs->count < ARRAY_SIZE(info->macs)) ? + macs->count : ARRAY_SIZE(info->macs); + + for (i = 0; i < info->num_macs; i++) + info->macs[i] = macs->mac_addrs[i]; +} + +static void cb_parse_tstamp(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = ptr; + + info->tstamp_table = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_cbmem_cons(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = ptr; + + info->cbmem_cons = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_acpi_gnvs(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr;
- info->vdat_addr = vdat->vdat_addr; - info->vdat_size = vdat->vdat_size; + info->acpi_gnvs = map_sysmem(cbmem->cbmem_tab, 0); }
-static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info) +static void cb_parse_board_id(unsigned char *ptr, struct sysinfo_t *info) { - info->tstamp_table = ((struct cb_cbmem_tab *)ptr)->cbmem_tab; + struct cb_board_id *const cbbid = (struct cb_board_id *)ptr; + + info->board_id = cbbid->board_id; }
-static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info) +static void cb_parse_ram_code(unsigned char *ptr, struct sysinfo_t *info) { - info->cbmem_cons = ((struct cb_cbmem_tab *)ptr)->cbmem_tab; + struct cb_ram_code *const ram_code = (struct cb_ram_code *)ptr; + + info->ram_code = ram_code->ram_code; }
-static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info) +static void cb_parse_optiontable(void *ptr, struct sysinfo_t *info) { - info->framebuffer = (struct cb_framebuffer *)ptr; + /* ptr points to a coreboot table entry and is already virtual */ + info->option_table = ptr; +} + +static void cb_parse_checksum(void *ptr, struct sysinfo_t *info) +{ + struct cb_cmos_checksum *cmos_cksum = ptr; + + info->cmos_range_start = cmos_cksum->range_start; + info->cmos_range_end = cmos_cksum->range_end; + info->cmos_checksum_location = cmos_cksum->location; +} + +static void cb_parse_framebuffer(void *ptr, struct sysinfo_t *info) +{ + /* ptr points to a coreboot table entry and is already virtual */ + info->framebuffer = ptr; }
static void cb_parse_string(unsigned char *ptr, char **info) @@ -123,6 +188,82 @@ static void cb_parse_string(unsigned char *ptr, char **info) *info = (char *)((struct cb_string *)ptr)->string; }
+static void cb_parse_wifi_calibration(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + + info->wifi_calibration = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_ramoops(void *ptr, struct sysinfo_t *info) +{ + struct lb_range *ramoops = (struct lb_range *)ptr; + + info->ramoops_buffer = ramoops->range_start; + info->ramoops_buffer_size = ramoops->range_size; +} + +static void cb_parse_mtc(void *ptr, struct sysinfo_t *info) +{ + struct lb_range *mtc = (struct lb_range *)ptr; + + info->mtc_start = mtc->range_start; + info->mtc_size = mtc->range_size; +} + +static void cb_parse_spi_flash(void *ptr, struct sysinfo_t *info) +{ + struct cb_spi_flash *flash = (struct cb_spi_flash *)ptr; + + info->spi_flash.size = flash->flash_size; + info->spi_flash.sector_size = flash->sector_size; + info->spi_flash.erase_cmd = flash->erase_cmd; +} + +static void cb_parse_boot_media_params(unsigned char *ptr, + struct sysinfo_t *info) +{ + struct cb_boot_media_params *const bmp = + (struct cb_boot_media_params *)ptr; + + info->fmap_offset = bmp->fmap_offset; + info->cbfs_offset = bmp->cbfs_offset; + info->cbfs_size = bmp->cbfs_size; + info->boot_media_size = bmp->boot_media_size; +} + +static void cb_parse_vpd(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + + info->chromeos_vpd = map_sysmem(cbmem->cbmem_tab, 0); +} + +static void cb_parse_tsc_info(void *ptr, struct sysinfo_t *info) +{ + const struct cb_tsc_info *tsc_info = ptr; + + if (tsc_info->freq_khz == 0) + return; + + /* Honor the TSC frequency passed to the payload */ + info->cpu_khz = tsc_info->freq_khz; +} + +static void cb_parse_x86_rom_var_mtrr(void *ptr, struct sysinfo_t *info) +{ + struct cb_x86_rom_mtrr *rom_mtrr = ptr; + + info->x86_rom_var_mtrr_index = rom_mtrr->index; +} + +static void cb_parse_mrc_cache(void *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_tab *const cbmem = (struct cb_cbmem_tab *)ptr; + + info->mrc_cache = map_sysmem(cbmem->cbmem_tab, 0); +} + __weak void cb_parse_unhandled(u32 tag, unsigned char *ptr) { } @@ -137,7 +278,7 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) if (!header->table_bytes) return 0;
- /* Make sure the checksums match. */ + /* Make sure the checksums match */ if (!ip_checksum_ok(header, sizeof(*header))) return -1;
@@ -145,16 +286,26 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) header->table_checksum) return -1;
- /* Now, walk the tables. */ + info->header = header; + + /* + * Board straps represented by numerical values are small numbers. + * Preset them to an invalid value in case the firmware does not + * supply the info. + */ + info->board_id = ~0; + info->ram_code = ~0; + + /* Now, walk the tables */ ptr += header->header_bytes;
- /* Inintialize some fields to sentinel values. */ + /* Inintialize some fields to sentinel values */ info->vbnv_start = info->vbnv_size = (uint32_t)(-1);
for (i = 0; i < header->table_entries; i++) { struct cb_record *rec = (struct cb_record *)ptr;
- /* We only care about a few tags here (maybe more later). */ + /* We only care about a few tags here (maybe more later) */ switch (rec->tag) { case CB_TAG_FORWARD: return cb_parse_header( @@ -169,7 +320,7 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) cb_parse_serial(ptr, info); break; case CB_TAG_VERSION: - cb_parse_string(ptr, &info->version); + cb_parse_string(ptr, &info->cb_version); break; case CB_TAG_EXTRA_VERSION: cb_parse_string(ptr, &info->extra_version); @@ -198,6 +349,12 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) case CB_TAG_ASSEMBLER: cb_parse_string(ptr, &info->assembler); break; + case CB_TAG_CMOS_OPTION_TABLE: + cb_parse_optiontable(ptr, info); + break; + case CB_TAG_OPTION_CHECKSUM: + cb_parse_checksum(ptr, info); + break; /* * FIXME we should warn on serial if coreboot set up a * framebuffer buf the payload does not know about it. @@ -205,24 +362,72 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) case CB_TAG_FRAMEBUFFER: cb_parse_framebuffer(ptr, info); break; + case CB_TAG_MAINBOARD: + info->mainboard = (struct cb_mainboard *)ptr; + break; case CB_TAG_GPIO: cb_parse_gpios(ptr, info); break; case CB_TAG_VDAT: cb_parse_vdat(ptr, info); break; + case CB_TAG_VBNV: + cb_parse_vbnv(ptr, info); + break; + case CB_TAG_VBOOT_HANDOFF: + cb_parse_vboot_handoff(ptr, info); + break; + case CB_TAG_MAC_ADDRS: + cb_parse_mac_addresses(ptr, info); + break; + case CB_TAG_SERIALNO: + cb_parse_string(ptr, &info->serialno); + break; case CB_TAG_TIMESTAMPS: cb_parse_tstamp(ptr, info); break; case CB_TAG_CBMEM_CONSOLE: cb_parse_cbmem_cons(ptr, info); break; - case CB_TAG_VBNV: - cb_parse_vbnv(ptr, info); + case CB_TAG_ACPI_GNVS: + cb_parse_acpi_gnvs(ptr, info); break; case CB_TAG_CBMEM_ENTRY: cb_parse_cbmem_entry(ptr, info); break; + case CB_TAG_BOARD_ID: + cb_parse_board_id(ptr, info); + break; + case CB_TAG_RAM_CODE: + cb_parse_ram_code(ptr, info); + break; + case CB_TAG_WIFI_CALIBRATION: + cb_parse_wifi_calibration(ptr, info); + break; + case CB_TAG_RAM_OOPS: + cb_parse_ramoops(ptr, info); + break; + case CB_TAG_SPI_FLASH: + cb_parse_spi_flash(ptr, info); + break; + case CB_TAG_MTC: + cb_parse_mtc(ptr, info); + break; + case CB_TAG_BOOT_MEDIA_PARAMS: + cb_parse_boot_media_params(ptr, info); + break; + case CB_TAG_TSC_INFO: + cb_parse_tsc_info(ptr, info); + break; + case CB_TAG_VPD: + cb_parse_vpd(ptr, info); + break; + case CB_TAG_X86_ROM_MTRR: + cb_parse_x86_rom_var_mtrr(rec, info); + break; + case CB_TAG_MRC_CACHE: + cb_parse_mrc_cache(rec, info); + break; default: cb_parse_unhandled(rec->tag, ptr); break; @@ -235,7 +440,7 @@ static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) }
/* == Architecture specific == */ -/* This is the x86 specific stuff. */ +/* This is the x86 specific stuff */
int get_coreboot_info(struct sysinfo_t *info) { @@ -253,3 +458,11 @@ int get_coreboot_info(struct sysinfo_t *info)
return 0; } + +const struct sysinfo_t *cb_get_sysinfo(void) +{ + if (!ll_boot_init()) + return &lib_sysinfo; + + return NULL; +}

Quite a few new tag types have been added over the years. Bring these into U-Boot so that all required tags can be parsed.
Add a proper comment to struct sysinfo_t while we are here, since many of the meanings are not obvious.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/include/asm/cb_sysinfo.h | 164 +++++++++++++++- arch/x86/include/asm/coreboot_tables.h | 161 +++++++++++++--- arch/x86/lib/coreboot/cb_sysinfo.c | 257 ++++++++++++++++++++++--- 3 files changed, 525 insertions(+), 57 deletions(-)
Applied to u-boot-dm/next, thanks!

Move this code into a generic location so that it can be used by other x86 boards which want to boot from coreboot. Also ensure that this is called if booting from coreboot.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/coreboot/sdram.c | 27 +------------------- arch/x86/include/asm/e820.h | 16 +++++++++++- arch/x86/lib/coreboot/Makefile | 1 + arch/x86/lib/coreboot/cb_support.c | 41 ++++++++++++++++++++++++++++++ arch/x86/lib/zimage.c | 12 +++++++-- 5 files changed, 68 insertions(+), 29 deletions(-) create mode 100644 arch/x86/lib/coreboot/cb_support.c
diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index 43604ee837a..4a256bad445 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -16,32 +16,7 @@ DECLARE_GLOBAL_DATA_PTR; unsigned int install_e820_map(unsigned int max_entries, struct e820_entry *entries) { - unsigned int num_entries; - int i; - - num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries); - if (num_entries < lib_sysinfo.n_memranges) { - printf("Warning: Limiting e820 map to %d entries.\n", - num_entries); - } - for (i = 0; i < num_entries; i++) { - struct memrange *memrange = &lib_sysinfo.memrange[i]; - - entries[i].addr = memrange->base; - entries[i].size = memrange->size; - - /* - * coreboot has some extensions (type 6 & 16) to the E820 types. - * When we detect this, mark it as E820_RESERVED. - */ - if (memrange->type == CB_MEM_VENDOR_RSVD || - memrange->type == CB_MEM_TABLE) - entries[i].type = E820_RESERVED; - else - entries[i].type = memrange->type; - } - - return num_entries; + return cb_install_e820_map(max_entries, entries); }
/* diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h index a66c0d24891..850a0a7a89e 100644 --- a/arch/x86/include/asm/e820.h +++ b/arch/x86/include/asm/e820.h @@ -22,9 +22,23 @@ struct e820_entry { #define ISA_START_ADDRESS 0xa0000 #define ISA_END_ADDRESS 0x100000
-/* Implementation defined function to install an e820 map */ +/* Implementation-defined function to install an e820 map */ unsigned int install_e820_map(unsigned int max_entries, struct e820_entry *); + +/** + * cb_install_e820_map() - Install e820 map provided by coreboot sysinfo + * + * This should be used when booting from coreboot, since in that case the + * memory areas are provided by coreboot in its sysinfo. + * + * @max_entries: Maximum number of entries to write + * @entries: Place to put entires + * @return number of entries written + */ +unsigned int cb_install_e820_map(unsigned int max_entries, + struct e820_entry *entries); + #endif /* __ASSEMBLY__ */
#endif /* _ASM_X86_E820_H */ diff --git a/arch/x86/lib/coreboot/Makefile b/arch/x86/lib/coreboot/Makefile index b5250d916b2..cb0ae1d017b 100644 --- a/arch/x86/lib/coreboot/Makefile +++ b/arch/x86/lib/coreboot/Makefile @@ -4,3 +4,4 @@ #
obj-y += cb_sysinfo.o +obj-y += cb_support.o diff --git a/arch/x86/lib/coreboot/cb_support.c b/arch/x86/lib/coreboot/cb_support.c new file mode 100644 index 00000000000..ebb45cdfb5b --- /dev/null +++ b/arch/x86/lib/coreboot/cb_support.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Support for booting from coreboot + * + * Copyright 2021 Google LLC + */ + +#include <common.h> +#include <asm/cb_sysinfo.h> +#include <asm/e820.h> + +unsigned int cb_install_e820_map(unsigned int max_entries, + struct e820_entry *entries) +{ + unsigned int num_entries; + int i; + + num_entries = min((unsigned int)lib_sysinfo.n_memranges, max_entries); + if (num_entries < lib_sysinfo.n_memranges) { + printf("Warning: Limiting e820 map to %d entries\n", + num_entries); + } + for (i = 0; i < num_entries; i++) { + struct memrange *memrange = &lib_sysinfo.memrange[i]; + + entries[i].addr = memrange->base; + entries[i].size = memrange->size; + + /* + * coreboot has some extensions (type 6 & 16) to the E820 types. + * When we detect this, mark it as E820_RESERVED. + */ + if (memrange->type == CB_MEM_VENDOR_RSVD || + memrange->type == CB_MEM_TABLE) + entries[i].type = E820_RESERVED; + else + entries[i].type = memrange->type; + } + + return num_entries; +} diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c index 602788e016d..af188c7f019 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -18,6 +18,7 @@ #include <bootm.h> #include <command.h> #include <env.h> +#include <init.h> #include <irq_func.h> #include <log.h> #include <malloc.h> @@ -35,6 +36,8 @@ #include <linux/ctype.h> #include <linux/libfdt.h>
+DECLARE_GLOBAL_DATA_PTR; + /* * Memory lay-out: * @@ -309,8 +312,13 @@ int setup_zimage(struct boot_params *setup_base, char *cmd_line, int auto_boot, int bootproto = get_boot_protocol(hdr, false);
log_debug("Setup E820 entries\n"); - setup_base->e820_entries = install_e820_map( - ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); + if (ll_boot_init()) { + setup_base->e820_entries = install_e820_map( + ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); + } else if (IS_ENABLED(CONFIG_COREBOOT_SYSINFO)) { + setup_base->e820_entries = cb_install_e820_map( + ARRAY_SIZE(setup_base->e820_map), setup_base->e820_map); + }
if (bootproto == 0x0100) { setup_base->screen_info.cl_magic = COMMAND_LINE_MAGIC;

Move this code into a generic location so that it can be used by other x86 boards which want to boot from coreboot. Also ensure that this is called if booting from coreboot.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/coreboot/sdram.c | 27 +------------------- arch/x86/include/asm/e820.h | 16 +++++++++++- arch/x86/lib/coreboot/Makefile | 1 + arch/x86/lib/coreboot/cb_support.c | 41 ++++++++++++++++++++++++++++++ arch/x86/lib/zimage.c | 12 +++++++-- 5 files changed, 68 insertions(+), 29 deletions(-) create mode 100644 arch/x86/lib/coreboot/cb_support.c
Applied to u-boot-dm/next, thanks!

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 | 9 + cmd/x86/Makefile | 1 + cmd/x86/cbsysinfo.c | 394 ++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + doc/usage/x86/cbsysinfo.rst | 25 +++ 5 files changed, 430 insertions(+) create mode 100644 cmd/x86/cbsysinfo.c create mode 100644 doc/usage/x86/cbsysinfo.rst
diff --git a/cmd/Kconfig b/cmd/Kconfig index 4defbd9cf9c..8e7129289e8 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2236,6 +2236,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 diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile index 144b1cf5abe..5f82204c87e 100644 --- a/cmd/x86/Makefile +++ b/cmd/x86/Makefile @@ -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 index 00000000000..a0db0ad364e --- /dev/null +++ b/cmd/x86/cbsysinfo.c @@ -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" +); diff --git a/doc/usage/index.rst b/doc/usage/index.rst index f7b706f9166..c7009ce49d6 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -19,6 +19,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 index 00000000000..8c03a85169d --- /dev/null +++ b/doc/usage/x86/cbsysinfo.rst @@ -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

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 | 9 + cmd/x86/Makefile | 1 + cmd/x86/cbsysinfo.c | 394 ++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + doc/usage/x86/cbsysinfo.rst | 25 +++ 5 files changed, 430 insertions(+) create mode 100644 cmd/x86/cbsysinfo.c create mode 100644 doc/usage/x86/cbsysinfo.rst
Applied to u-boot-dm/next, thanks!

Two commands are missing this check, so compilation fails when building without CONFIG_CMDLINE. Add it.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/acpi.c | 2 ++ cmd/bloblist.c | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/cmd/acpi.c b/cmd/acpi.c index 157261bffbe..e5b9a1752bc 100644 --- a/cmd/acpi.c +++ b/cmd/acpi.c @@ -187,10 +187,12 @@ static int do_acpi_dump(struct cmd_tbl *cmdtp, int flag, int argc, return 0; }
+#ifdef CONFIG_SYS_LONGHELP static char acpi_help_text[] = "list - list ACPI tables\n" "acpi items [-d] - List/dump each piece of ACPI data from devices\n" "acpi dump <name> - Dump ACPI table"; +#endif
U_BOOT_CMD_WITH_SUBCMDS(acpi, "ACPI tables", acpi_help_text, U_BOOT_SUBCMD_MKENT(list, 1, 1, do_acpi_list), diff --git a/cmd/bloblist.c b/cmd/bloblist.c index 97b57341617..21e7ff67af2 100644 --- a/cmd/bloblist.c +++ b/cmd/bloblist.c @@ -29,9 +29,11 @@ static int do_bloblist_list(struct cmd_tbl *cmdtp, int flag, int argc, return 0; }
+#ifdef CONFIG_SYS_LONGHELP static char bloblist_help_text[] = "info - show information about the bloblist\n" "bloblist list - list blobs in the bloblist"; +#endif
U_BOOT_CMD_WITH_SUBCMDS(bloblist, "Bloblists", bloblist_help_text, U_BOOT_SUBCMD_MKENT(info, 1, 1, do_bloblist_info),

Two commands are missing this check, so compilation fails when building without CONFIG_CMDLINE. Add it.
Signed-off-by: Simon Glass sjg@chromium.org ---
cmd/acpi.c | 2 ++ cmd/bloblist.c | 2 ++ 2 files changed, 4 insertions(+)
Applied to u-boot-dm/next, thanks!

The copy buffer, if enabled, prevents booting from coreboot correctly, since no memory is allocated for it. Allow it to fall back to disabled in this situation. This ensures that a console is displayed, even if it is slow.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci_rom.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index a14a4db3c2f..7bad4c82c0c 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -349,13 +349,10 @@ int vbe_setup_video_priv(struct vesa_mode_info *vesa, }
/* Use double buffering if enabled */ - if (IS_ENABLED(CONFIG_VIDEO_COPY)) { - if (!plat->base) - return log_msg_ret("copy", -ENFILE); + if (IS_ENABLED(CONFIG_VIDEO_COPY) && plat->base) plat->copy_base = vesa->phys_base_ptr; - } else { + else plat->base = vesa->phys_base_ptr; - } log_debug("base = %lx, copy_base = %lx\n", plat->base, plat->copy_base); plat->size = vesa->bytes_per_scanline * vesa->y_resolution;

The copy buffer, if enabled, prevents booting from coreboot correctly, since no memory is allocated for it. Allow it to fall back to disabled in this situation. This ensures that a console is displayed, even if it is slow.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/pci/pci_rom.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
Applied to u-boot-dm/next, thanks!

When booting from coreboot we need this driver for the video to work. Update the driver to be usable on any board.
The driver disables itself if it sees that is not booted from coreboot.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/Kconfig | 2 +- drivers/video/coreboot.c | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 667157c2e97..63ae2ba43c4 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -241,7 +241,7 @@ config VIDCONSOLE_AS_NAME
config VIDEO_COREBOOT bool "Enable coreboot framebuffer driver support" - depends on X86 && SYS_COREBOOT + depends on X86 help Turn on this option to enable a framebuffer driver when U-Boot is loaded by coreboot where the graphics device is configured by diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c index 55f72fe886f..7237542c076 100644 --- a/drivers/video/coreboot.c +++ b/drivers/video/coreboot.c @@ -5,6 +5,7 @@
#include <common.h> #include <dm.h> +#include <init.h> #include <vbe.h> #include <video.h> #include <asm/cb_sysinfo.h> @@ -17,7 +18,7 @@ static int save_vesa_mode(struct cb_framebuffer *fb, * running on the serial console. */ if (!fb) - return -ENXIO; + return log_msg_ret("save", -ENXIO);
vesa->x_resolution = fb->x_resolution; vesa->y_resolution = fb->y_resolution; @@ -44,16 +45,23 @@ static int coreboot_video_probe(struct udevice *dev) struct vesa_mode_info *vesa = &mode_info.vesa; int ret;
+ if (ll_boot_init()) + return log_msg_ret("ll", -ENODEV); + printf("Video: ");
/* Initialize vesa_mode_info structure */ ret = save_vesa_mode(fb, vesa); - if (ret) + if (ret) { + ret = log_msg_ret("save", ret); goto err; + }
ret = vbe_setup_video_priv(vesa, uc_priv, plat); - if (ret) + if (ret) { + ret = log_msg_ret("setup", ret); goto err; + }
printf("%dx%dx%d\n", uc_priv->xsize, uc_priv->ysize, vesa->bits_per_pixel); @@ -61,7 +69,7 @@ static int coreboot_video_probe(struct udevice *dev) return 0;
err: - printf("No video mode configured in coreboot!\n"); + printf("No video mode configured in coreboot (err=%d)\n", ret); return ret; }

When booting from coreboot we need this driver for the video to work. Update the driver to be usable on any board.
The driver disables itself if it sees that is not booted from coreboot.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/video/Kconfig | 2 +- drivers/video/coreboot.c | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-)
Applied to u-boot-dm/next, thanks!

This driver cannot work when booted from coreboot, since the FSP information is not available. Disable it in that case, so that the coreboot video driver can be used instead.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/fsp/fsp_graphics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/x86/lib/fsp/fsp_graphics.c b/arch/x86/lib/fsp/fsp_graphics.c index cc909e0e16a..02fd05c9faf 100644 --- a/arch/x86/lib/fsp/fsp_graphics.c +++ b/arch/x86/lib/fsp/fsp_graphics.c @@ -87,7 +87,7 @@ static int fsp_video_probe(struct udevice *dev) int ret;
if (!ll_boot_init()) - return 0; + return -ENODEV;
printf("Video: ");

This driver cannot work when booted from coreboot, since the FSP information is not available. Disable it in that case, so that the coreboot video driver can be used instead.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/fsp/fsp_graphics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Applied to u-boot-dm/next, thanks!

Allow referencing a CBFS file in the flashmap, so that it is possible to boot from coreboot, where files are not available from binman.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/dm/of_extra.h | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/include/dm/of_extra.h b/include/dm/of_extra.h index ca15df21b06..fc4f9743196 100644 --- a/include/dm/of_extra.h +++ b/include/dm/of_extra.h @@ -11,7 +11,11 @@
enum fmap_compress_t { FMAP_COMPRESS_NONE, + FMAP_COMPRESS_LZMA, FMAP_COMPRESS_LZ4, + + FMAP_COMPRESS_COUNT, + FMAP_COMPRESS_UNKNOWN, };
enum fmap_hash_t { @@ -30,6 +34,10 @@ struct fmap_entry { enum fmap_hash_t hash_algo; /* Hash algorithm */ const uint8_t *hash; /* Hash value */ int hash_size; /* Hash size */ + /* Node pointer if CBFS, else NULL */ + const struct cbfs_cachenode *cbfs_node; + /* Hash node pointer if CBFS, else NULL */ + const struct cbfs_cachenode *cbfs_hash_node; };
/**

Allow referencing a CBFS file in the flashmap, so that it is possible to boot from coreboot, where files are not available from binman.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/dm/of_extra.h | 8 ++++++++ 1 file changed, 8 insertions(+)
Applied to u-boot-dm/next, thanks!

When CONFIG_ACPIGEN is not enabled the CPU code does not build. Fix this by moving things around.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/cpu.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/arch/x86/cpu/apollolake/cpu.c b/arch/x86/cpu/apollolake/cpu.c index fbc016d0e0b..647c9df6a72 100644 --- a/arch/x86/cpu/apollolake/cpu.c +++ b/arch/x86/cpu/apollolake/cpu.c @@ -19,6 +19,7 @@ #include <asm/arch/iomap.h> #include <dm/acpi.h>
+#ifdef CONFIG_ACPIGEN #define CSTATE_RES(address_space, width, offset, address) \ { \ .space_id = address_space, \ @@ -57,11 +58,6 @@ static struct acpi_cstate cstate_map[] = { }, };
-static int apl_get_info(const struct udevice *dev, struct cpu_info *info) -{ - return cpu_intel_get_info(info, INTEL_BCLK_MHZ); -} - static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx) { uint core_id = dev_seq(dev); @@ -89,6 +85,12 @@ static int acpi_cpu_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
return 0; } +#endif /* CONFIG_ACPIGEN */ + +static int apl_get_info(const struct udevice *dev, struct cpu_info *info) +{ + return cpu_intel_get_info(info, INTEL_BCLK_MHZ); +}
static void update_fixed_mtrrs(void) { @@ -170,9 +172,11 @@ static int cpu_apl_probe(struct udevice *dev) return 0; }
+#ifdef CONFIG_ACPIGEN struct acpi_ops apl_cpu_acpi_ops = { .fill_ssdt = acpi_cpu_fill_ssdt, }; +#endif
static const struct cpu_ops cpu_x86_apl_ops = { .get_desc = cpu_x86_get_desc,

When CONFIG_ACPIGEN is not enabled the CPU code does not build. Fix this by moving things around.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/cpu.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
Applied to u-boot-dm/next, thanks!

At present the debug UART is only set up in SPL, on the assumption that the boot flow will always pass through there. When booting from coreboot, SPL is not used, so the debug UART is not available.
Move the code into a common place so that it can be used in U-Boot proper also. Add the required init to start_from_spl.S as well.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/cpu_common.c | 60 +++++++++++++++++++++ arch/x86/cpu/apollolake/cpu_spl.c | 58 -------------------- arch/x86/cpu/start_from_spl.S | 4 ++ arch/x86/include/asm/arch-apollolake/uart.h | 1 + 4 files changed, 65 insertions(+), 58 deletions(-)
diff --git a/arch/x86/cpu/apollolake/cpu_common.c b/arch/x86/cpu/apollolake/cpu_common.c index 63f6999b024..5d7d26b140f 100644 --- a/arch/x86/cpu/apollolake/cpu_common.c +++ b/arch/x86/cpu/apollolake/cpu_common.c @@ -7,11 +7,17 @@ #include <dm.h> #include <log.h> #include <asm/cpu_common.h> +#include <asm/io.h> #include <asm/msr.h> +#include <asm/pci.h> #include <asm/arch/cpu.h> #include <asm/arch/iomap.h> +#include <asm/arch/uart.h> #include <power/acpi_pmc.h>
+/* Define this here to avoid referencing any drivers for the debug UART 1 */ +#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0) + void cpu_flush_l1d_to_l2(void) { struct msr_t msr; @@ -40,3 +46,57 @@ void enable_pm_timer_emulation(const struct udevice *pmc) debug("PM timer %x %x\n", msr.hi, msr.lo); msr_write(MSR_EMULATE_PM_TIMER, msr); } + +static void pch_uart_init(void) +{ + /* + * Set up the pinmux so that the UART rx/tx signals are connected + * outside the SoC. + * + * There are about 500 lines of code required to program the GPIO + * configuration for the UARTs. But it boils down to four writes, and + * for the debug UART we want the minimum possible amount of code before + * the UART is running. So just add the magic writes here. See + * apl_hostbridge_early_init_pinctrl() for the full horror. + */ + if (PCI_FUNC(PCH_DEV_UART) == 1) { + writel(0x40000402, 0xd0c50650); + writel(0x3c47, 0xd0c50654); + writel(0x40000400, 0xd0c50658); + writel(0x3c48, 0xd0c5065c); + } else { /* UART2 */ + writel(0x40000402, 0xd0c50670); + writel(0x3c4b, 0xd0c50674); + writel(0x40000400, 0xd0c50678); + writel(0x3c4c, 0xd0c5067c); + } + +#ifdef CONFIG_DEBUG_UART + apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE); +#endif +} + +static void p2sb_enable_bar(ulong bar) +{ + /* Enable PCR Base address in PCH */ + pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar, + PCI_SIZE_32); + pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32); + + /* Enable P2SB MSE */ + pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND, + PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, + PCI_SIZE_8); +} + +/* + * board_debug_uart_init() - Init the debug UART ready for use + * + * This is the minimum init needed to get the UART running. It avoids any + * drivers or complex code, so that the UART is running as soon as possible. + */ +void board_debug_uart_init(void) +{ + p2sb_enable_bar(IOMAP_P2SB_BAR); + pch_uart_init(); +} diff --git a/arch/x86/cpu/apollolake/cpu_spl.c b/arch/x86/cpu/apollolake/cpu_spl.c index 9a18476b22c..8f48457ee22 100644 --- a/arch/x86/cpu/apollolake/cpu_spl.c +++ b/arch/x86/cpu/apollolake/cpu_spl.c @@ -31,68 +31,10 @@ #include <asm/arch/lpc.h> #include <asm/arch/pch.h> #include <asm/arch/systemagent.h> -#include <asm/arch/uart.h> #include <asm/fsp2/fsp_api.h> #include <linux/sizes.h> #include <power/acpi_pmc.h>
-/* Define this here to avoid referencing any drivers for the debug UART 1 */ -#define PCH_DEV_P2SB PCI_BDF(0, 0x0d, 0) - -static void pch_uart_init(void) -{ - /* - * Set up the pinmux so that the UART rx/tx signals are connected - * outside the SoC. - * - * There are about 500 lines of code required to program the GPIO - * configuration for the UARTs. But it boils down to four writes, and - * for the debug UART we want the minimum possible amount of code before - * the UART is running. So just add the magic writes here. See - * apl_hostbridge_early_init_pinctrl() for the full horror. - */ - if (PCI_FUNC(PCH_DEV_UART) == 1) { - writel(0x40000402, 0xd0c50650); - writel(0x3c47, 0xd0c50654); - writel(0x40000400, 0xd0c50658); - writel(0x3c48, 0xd0c5065c); - } else { /* UART2 */ - writel(0x40000402, 0xd0c50670); - writel(0x3c4b, 0xd0c50674); - writel(0x40000400, 0xd0c50678); - writel(0x3c4c, 0xd0c5067c); - } - -#ifdef CONFIG_DEBUG_UART - apl_uart_init(PCH_DEV_UART, CONFIG_DEBUG_UART_BASE); -#endif -} - -static void p2sb_enable_bar(ulong bar) -{ - /* Enable PCR Base address in PCH */ - pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_0, bar, - PCI_SIZE_32); - pci_x86_write_config(PCH_DEV_P2SB, PCI_BASE_ADDRESS_1, 0, PCI_SIZE_32); - - /* Enable P2SB MSE */ - pci_x86_write_config(PCH_DEV_P2SB, PCI_COMMAND, - PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY, - PCI_SIZE_8); -} - -/* - * board_debug_uart_init() - Init the debug UART ready for use - * - * This is the minimum init needed to get the UART running. It avoids any - * drivers or complex code, so that the UART is running as soon as possible. - */ -void board_debug_uart_init(void) -{ - p2sb_enable_bar(IOMAP_P2SB_BAR); - pch_uart_init(); -} - static int fast_spi_cache_bios_region(void) { uint map_size, offset; diff --git a/arch/x86/cpu/start_from_spl.S b/arch/x86/cpu/start_from_spl.S index 905c825cdc4..abfd4abb623 100644 --- a/arch/x86/cpu/start_from_spl.S +++ b/arch/x86/cpu/start_from_spl.S @@ -43,6 +43,10 @@ use_existing_stack:
call board_init_f_init_reserve
+#ifdef CONFIG_DEBUG_UART + call debug_uart_init +#endif + call x86_cpu_reinit_f xorl %eax, %eax call board_init_f diff --git a/arch/x86/include/asm/arch-apollolake/uart.h b/arch/x86/include/asm/arch-apollolake/uart.h index 38335b04903..c3ca171b83b 100644 --- a/arch/x86/include/asm/arch-apollolake/uart.h +++ b/arch/x86/include/asm/arch-apollolake/uart.h @@ -6,6 +6,7 @@ #ifndef _ASM_ARCH_UART_H #define _ASM_ARCH_UART_H
+#include <dt-structs.h> #include <ns16550.h>
/**

At present the debug UART is only set up in SPL, on the assumption that the boot flow will always pass through there. When booting from coreboot, SPL is not used, so the debug UART is not available.
Move the code into a common place so that it can be used in U-Boot proper also. Add the required init to start_from_spl.S as well.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/cpu/apollolake/cpu_common.c | 60 +++++++++++++++++++++ arch/x86/cpu/apollolake/cpu_spl.c | 58 -------------------- arch/x86/cpu/start_from_spl.S | 4 ++ arch/x86/include/asm/arch-apollolake/uart.h | 1 + 4 files changed, 65 insertions(+), 58 deletions(-)
Applied to u-boot-dm/next, thanks!

When booting from coreboot the FSP video information is no-longer available. Enable the coreboot driver so that we can get some sort of display in this case.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/chromebook_coral.dts | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts index 30058be1ea3..2beada77032 100644 --- a/arch/x86/dts/chromebook_coral.dts +++ b/arch/x86/dts/chromebook_coral.dts @@ -149,6 +149,11 @@ #interrupt-cells = <2>; };
+ coreboot-video { + /* This will only activate when booted from coreboot */ + compatible = "coreboot-fb"; + }; + keyboard { intel,duplicate-por; };

When booting from coreboot the FSP video information is no-longer available. Enable the coreboot driver so that we can get some sort of display in this case.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/dts/chromebook_coral.dts | 5 +++++ 1 file changed, 5 insertions(+)
Applied to u-boot-dm/next, thanks!

When booting from coreboot there is no need to notify the FSP of anything, since coreboot has already done it. Nor it is possible, since the FSP details are not provided by coreboot.
Skip it in this case.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/fsp2/fsp_support.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/arch/x86/lib/fsp2/fsp_support.c b/arch/x86/lib/fsp2/fsp_support.c index 503f97d5f33..b2c76582453 100644 --- a/arch/x86/lib/fsp2/fsp_support.c +++ b/arch/x86/lib/fsp2/fsp_support.c @@ -6,6 +6,7 @@
#include <common.h> #include <dm.h> +#include <init.h> #include <log.h> #include <spi_flash.h> #include <asm/fsp/fsp_support.h> @@ -114,6 +115,9 @@ u32 fsp_notify(struct fsp_header *fsp_hdr, u32 phase) struct fsp_notify_params *params_ptr; u32 status;
+ if (!ll_boot_init()) + return 0; + if (!fsp_hdr) fsp_hdr = gd->arch.fsp_s_hdr;

When booting from coreboot there is no need to notify the FSP of anything, since coreboot has already done it. Nor it is possible, since the FSP details are not provided by coreboot.
Skip it in this case.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/fsp2/fsp_support.c | 4 ++++ 1 file changed, 4 insertions(+)
Applied to u-boot-dm/next, thanks!

This currently hangs and it is not necessary in any case. Drop the code when booting from coreboot.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/init_helpers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index 066dc404a2d..67401b9ba79 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -18,6 +18,9 @@ int init_cache_f_r(void) IS_ENABLED(CONFIG_FSP_VERSION2); int ret;
+ if (!ll_boot_init()) + return 0; + do_mtrr &= !IS_ENABLED(CONFIG_FSP_VERSION1) && !IS_ENABLED(CONFIG_SYS_SLIMBOOTLOADER);
@@ -31,9 +34,6 @@ int init_cache_f_r(void) return ret; }
- if (!ll_boot_init()) - return 0; - /* Initialise the CPU cache(s) */ return init_cache(); }

This currently hangs and it is not necessary in any case. Drop the code when booting from coreboot.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/x86/lib/init_helpers.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
Applied to u-boot-dm/next, thanks!
participants (2)
-
Jaehoon Chung
-
Simon Glass