From 619a81516d3c05a55f0ce5463dd38993c6e9adc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Stehl=C3=A9?= Date: Wed, 10 Mar 2021 15:33:30 +0100 Subject: sandbox: dtsi: add rng MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having an rng in the sandbox is useful not only for tests but also for e.g. UEFI. Therefore, copy the rng node from test.dts to sandbox.dtsi. In the case of UEFI, it can then be verified with `efidebug dh' that a "Random Number Generator" protocol is indeed present. This also fixes the following `bootefi' error: Missing RNG device for EFI_RNG_PROTOCOL Signed-off-by: Vincent StehlĂ© Cc: Simon Glass --- arch/sandbox/dts/sandbox.dtsi | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 69d7d30..31db50d 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -200,6 +200,10 @@ compatible = "sandbox,reset"; }; + rng { + compatible = "sandbox,sandbox-rng"; + }; + sound { compatible = "sandbox,sound"; cpu { -- cgit v1.1 From b09c74f66d46fac7f25e53a0c06f832cf0638a5c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 10 Mar 2021 18:23:57 +0100 Subject: mtd: spi_flash_free() dfu_free_entities() invoking dfu_free_entity_sf() has let to segementation faults due to double freeing the same device. spi_flash_free() is not relevant for the driver model but exists only for compatibility with old drivers. We must not remove any device here: * The device may still be referenced. * We don't want to have to probe again. Signed-off-by: Heinrich Schuchardt --- drivers/mtd/spi/sf-uclass.c | 5 ----- include/spi_flash.h | 4 +++- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index 12d1321..fd1bec8 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -46,11 +46,6 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, return dev_get_uclass_priv(dev); } -void spi_flash_free(struct spi_flash *flash) -{ - device_remove(flash->spi->dev, DM_REMOVE_NORMAL); -} - int spi_flash_probe_bus_cs(unsigned int busnum, unsigned int cs, unsigned int max_hz, unsigned int spi_mode, struct udevice **devp) diff --git a/include/spi_flash.h b/include/spi_flash.h index 85cae32..478c543 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -97,7 +97,9 @@ struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int spi_mode); /* Compatibility function - this is the old U-Boot API */ -void spi_flash_free(struct spi_flash *flash); +static inline void spi_flash_free(struct spi_flash *flash) +{ +} static inline int spi_flash_read(struct spi_flash *flash, u32 offset, size_t len, void *buf) -- cgit v1.1 From 80814f4d0e47522e1b1797d461308797a8a5d246 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:01 +1300 Subject: x86: coral: Free the ACPI GPIOs after using them These GPIOs are needed later if Chromium OS verified boot is running, so free them after use. Signed-off-by: Simon Glass --- 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 f9fb3f1..b255bf6 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; } -- cgit v1.1 From 414e10b96c775a1d145eb4dc9524e02328531a1b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:02 +1300 Subject: x86: coral: Add information about building / running 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 --- 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 c39f1e3..4b58567 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/case_closed_debugging.md + +You can buy Suzy-Q from Sparkfun: + + https://chromium.googlesource.com/chromiumos/third_party/hdctools/+/main/docs/ccd.md#suzyq-suzyqable + +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 + 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 -- cgit v1.1 From 72d98ee09172d18919bd3e4c1c5393cc1b09cf76 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:03 +1300 Subject: x86: p2sb: Drop LOG_DEBUG We should not enable debugging by default. Drop this. Signed-off-by: Simon Glass --- 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 973d02d..51f8716 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 #include -- cgit v1.1 From 7d252d0279ec92ac90a5cec7378bd877df7af008 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:04 +1300 Subject: x86: Probe device if needed in intel_gpio_xlate() 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 --- 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 ab46a94..f15ce7b 100644 --- a/drivers/gpio/intel_gpio.c +++ b/drivers/gpio/intel_gpio.c @@ -23,6 +23,7 @@ #include #include #include +#include #include 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; } -- cgit v1.1 From 041089fe930b6c7bdaadfb1e81a77dd8ca45e907 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:05 +1300 Subject: x86: coral: Put the eMMC first 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 Reviewed-by: 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 d109a38..4cadfd1 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 6e8e8ec..00760b8 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" -- cgit v1.1 From ac7765017a7f6b2c7f882dc6dbe5f64f142991ba Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:06 +1300 Subject: x86: coral: Update the SD card-detect GPIO 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 Reviewed-by: 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 4cadfd1..db8eb88 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"; }; -- cgit v1.1 From 42ee0cd216e54a567fa8a1459ef9ebbf34272207 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:07 +1300 Subject: tegra: i2c: Drop LOG_DEBUG We should not enable debugging by default. Drop this. Signed-off-by: Simon Glass --- 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 5cf8225..932f737 100644 --- a/drivers/sound/tegra_i2s.c +++ b/drivers/sound/tegra_i2s.c @@ -4,7 +4,6 @@ * Written by Simon Glass */ #define LOG_CATEGORY UCLASS_I2S -#define LOG_DEBUG #include #include -- cgit v1.1 From 326aae258925b689b04dbd782a7e5e76e4eaf864 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:08 +1300 Subject: mmc: pci_mmc: Set up the card detect 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 --- 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 fd5dd22..b9ab064 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; -- cgit v1.1 From 72ca4859784227138a42d924678222d68fc20484 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:09 +1300 Subject: cbfs: Add support for attributes 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 --- 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 9007aa7..abc43ad 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 5f296d6..d98afea 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; }; /** -- cgit v1.1 From 11a38a2573fa6a765043df94eae44544a0d948f4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:10 +1300 Subject: cbfs: Rename new_node to node Rename this variable since there is no need to distinguish it from an old node. Signed-off-by: Simon Glass --- 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 abc43ad..c9323a5 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; -- cgit v1.1 From 272e62cb83f01acf7ae89449eaa9f020e76bff23 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:11 +1300 Subject: smbios: Allow writing to the coreboot version string 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 --- 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 ecc4fd1..ffeefb4 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 b89f988..34203f9 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 #include @@ -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 7d463c8..9eb226e 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 * -- cgit v1.1 From 5536f1285fd2f9ec3e177d6e74b7eb73c6821c8b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:12 +1300 Subject: cbfs: Allow access to CBFS without a header 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 --- 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 85cae54..5afdce1 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 c9323a5..13a74e6 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 d98afea..05770e2 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. */ -- cgit v1.1 From c4f5b5dcc31b5aee37dabbadc998fcf695885157 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:13 +1300 Subject: cbfs: Allow file traversal with any 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 --- 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 13a74e6..aed4026 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 05770e2..055edba 100644 --- a/include/cbfs.h +++ b/include/cbfs.h @@ -9,6 +9,8 @@ #include #include +struct cbfs_priv; + enum cbfs_result { CBFS_SUCCESS = 0, CBFS_NOT_INITIALIZED, @@ -150,6 +152,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. * * @return A handle for the first file in CBFS, NULL on error. @@ -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 * -- cgit v1.1 From 70a394a6b6437e18e67edfd7054302b830e1fe6a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:14 +1300 Subject: cbfs: Factor out filling a cache node into a new function 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 --- 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 aed4026..a93dc3d 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) -- cgit v1.1 From 0e2fee52d0fba6ceb455c7969eecb2cf73031267 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:15 +1300 Subject: cbfs: Simplify file iteration 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 --- 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 a93dc3d..9e534d1 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; } -- cgit v1.1 From a202f17d7bc2a51af53352c6e21d6a70d167effe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:16 +1300 Subject: cbfs: Support reading compression information 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 --- 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 9e534d1..443a148 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 055edba..ae94f1d 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; }; /** -- cgit v1.1 From ad66323a58cb6279aa9e8ba521a4daf25d0cbe79 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:17 +1300 Subject: cbfs: Drop unnecessary cast in file_cbfs_fill_cache() The results of malloc() are a void * and so this cast is unnecessary. Drop it. Signed-off-by: Simon Glass --- 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 443a148..415ea28 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, -- cgit v1.1 From e35b6497f417c60cdcaa521eb4cbd3b2bb2e8336 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:18 +1300 Subject: x86: Make coreboot sysinfo available to any x86 board 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 --- 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 | 62 ---------------------------- arch/x86/include/asm/cb_sysinfo.h | 62 ++++++++++++++++++++++++++++ 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 +- 11 files changed, 71 insertions(+), 71 deletions(-) delete mode 100644 arch/x86/include/asm/arch-coreboot/sysinfo.h create mode 100644 arch/x86/include/asm/cb_sysinfo.h diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 15c3ad8..69cf8f4 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index a2e47d1..43604ee 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c index c52741a..816a0ef 100644 --- a/arch/x86/cpu/coreboot/tables.c +++ b/arch/x86/cpu/coreboot/tables.c @@ -8,7 +8,7 @@ #include #include -#include +#include #include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/coreboot/timestamp.c b/arch/x86/cpu/coreboot/timestamp.c index 0162597..b1e2955 100644 --- a/arch/x86/cpu/coreboot/timestamp.c +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include struct timestamp_entry { diff --git a/arch/x86/include/asm/arch-coreboot/sysinfo.h b/arch/x86/include/asm/arch-coreboot/sysinfo.h deleted file mode 100644 index 419ec52..0000000 --- a/arch/x86/include/asm/arch-coreboot/sysinfo.h +++ /dev/null @@ -1,62 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * This file is part of the libpayload project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - */ - -#ifndef _COREBOOT_SYSINFO_H -#define _COREBOOT_SYSINFO_H - -#include - -/* Maximum number of memory range definitions */ -#define SYSINFO_MAX_MEM_RANGES 32 -/* Allow a maximum of 8 GPIOs */ -#define SYSINFO_MAX_GPIOS 8 - -struct sysinfo_t { - int n_memranges; - struct memrange { - unsigned long long base; - unsigned long long size; - unsigned int type; - } memrange[SYSINFO_MAX_MEM_RANGES]; - - u32 cmos_range_start; - u32 cmos_range_end; - u32 cmos_checksum_location; - u32 vbnv_start; - u32 vbnv_size; - - char *version; - char *extra_version; - char *build; - char *compile_time; - char *compile_by; - char *compile_host; - char *compile_domain; - char *compiler; - char *linker; - char *assembler; - - struct cb_framebuffer *framebuffer; - - int num_gpios; - struct cb_gpio gpios[SYSINFO_MAX_GPIOS]; - - void *vdat_addr; - u32 vdat_size; - void *tstamp_table; - void *cbmem_cons; - u64 smbios_start; - u32 smbios_size; - - struct cb_serial *serial; -}; - -extern struct sysinfo_t lib_sysinfo; - -int get_coreboot_info(struct sysinfo_t *info); - -#endif diff --git a/arch/x86/include/asm/cb_sysinfo.h b/arch/x86/include/asm/cb_sysinfo.h new file mode 100644 index 0000000..419ec52 --- /dev/null +++ b/arch/x86/include/asm/cb_sysinfo.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + */ + +#ifndef _COREBOOT_SYSINFO_H +#define _COREBOOT_SYSINFO_H + +#include + +/* Maximum number of memory range definitions */ +#define SYSINFO_MAX_MEM_RANGES 32 +/* Allow a maximum of 8 GPIOs */ +#define SYSINFO_MAX_GPIOS 8 + +struct sysinfo_t { + int n_memranges; + struct memrange { + unsigned long long base; + unsigned long long size; + unsigned int type; + } memrange[SYSINFO_MAX_MEM_RANGES]; + + u32 cmos_range_start; + u32 cmos_range_end; + u32 cmos_checksum_location; + u32 vbnv_start; + u32 vbnv_size; + + char *version; + char *extra_version; + char *build; + char *compile_time; + char *compile_by; + char *compile_host; + char *compile_domain; + char *compiler; + char *linker; + char *assembler; + + struct cb_framebuffer *framebuffer; + + int num_gpios; + struct cb_gpio gpios[SYSINFO_MAX_GPIOS]; + + void *vdat_addr; + u32 vdat_size; + void *tstamp_table; + void *cbmem_cons; + u64 smbios_start; + u32 smbios_size; + + struct cb_serial *serial; +}; + +extern struct sysinfo_t lib_sysinfo; + +int get_coreboot_info(struct sysinfo_t *info); + +#endif diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c index 9aafb89..175d3ce 100644 --- a/board/coreboot/coreboot/coreboot.c +++ b/board/coreboot/coreboot/coreboot.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include #include diff --git a/cmd/version.c b/cmd/version.c index 3686b87..685b458 100644 --- a/cmd/version.c +++ b/cmd/version.c @@ -9,7 +9,7 @@ #include #include #ifdef CONFIG_SYS_COREBOOT -#include +#include #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 5ba0a54..8bbe33d 100644 --- a/drivers/misc/cbmem_console.c +++ b/drivers/misc/cbmem_console.c @@ -9,7 +9,7 @@ #error This driver requires coreboot #endif -#include +#include struct cbmem_console { u32 buffer_size; diff --git a/drivers/serial/serial_coreboot.c b/drivers/serial/serial_coreboot.c index 88c8209..de09c86 100644 --- a/drivers/serial/serial_coreboot.c +++ b/drivers/serial/serial_coreboot.c @@ -9,7 +9,7 @@ #include #include #include -#include +#include static int coreboot_of_to_plat(struct udevice *dev) { diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c index 0a5fb08..55f72fe 100644 --- a/drivers/video/coreboot.c +++ b/drivers/video/coreboot.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include static int save_vesa_mode(struct cb_framebuffer *fb, struct vesa_mode_info *vesa) -- cgit v1.1 From 17753b0382ce9b291e48a4e23d68e6b1d62c5871 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:19 +1300 Subject: x86: Move coreboot timestamp info into coreboot_tables.h 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 --- arch/x86/cpu/coreboot/timestamp.c | 12 -------- arch/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 b1e2955..7f133ce 100644 --- a/arch/x86/cpu/coreboot/timestamp.c +++ b/arch/x86/cpu/coreboot/timestamp.c @@ -11,18 +11,6 @@ #include #include -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 85d42c0..531526b 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 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 7e15767..dec0c14 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 { -- cgit v1.1 From f9f06e628e17b021bdd6786717b74f1751999abe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:20 +1300 Subject: x86: coreboot: Sync up timestamp codes 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 --- 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 dec0c14..3172814 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 aa5f0bf..733dd71 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) -- cgit v1.1 From 68e03ca21acf3192dd08e0617ea878949ea0e4dc Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:21 +1300 Subject: x86: Move coreboot sysinfo parsing into generic x86 code 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 --- arch/x86/Kconfig | 21 +++ arch/x86/cpu/coreboot/Makefile | 1 - arch/x86/cpu/coreboot/tables.c | 255 ------------------------------------- arch/x86/lib/Makefile | 1 + arch/x86/lib/coreboot/Makefile | 6 + arch/x86/lib/coreboot/cb_sysinfo.c | 255 +++++++++++++++++++++++++++++++++++++ 6 files changed, 283 insertions(+), 256 deletions(-) delete mode 100644 arch/x86/cpu/coreboot/tables.c create mode 100644 arch/x86/lib/coreboot/Makefile create mode 100644 arch/x86/lib/coreboot/cb_sysinfo.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5b089af..970bdff 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1047,4 +1047,25 @@ config INTEL_GMA_SWSMISCI endif # INTEL_SOC +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 605f903..a6cdb9a 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/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c deleted file mode 100644 index 816a0ef..0000000 --- a/arch/x86/cpu/coreboot/tables.c +++ /dev/null @@ -1,255 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause -/* - * This file is part of the libpayload project. - * - * Copyright (C) 2008 Advanced Micro Devices, Inc. - * Copyright (C) 2009 coresystems GmbH - */ - -#include -#include -#include -#include - -DECLARE_GLOBAL_DATA_PTR; - -/* - * This needs to be in the .data section so that it's copied over during - * relocation. By default it's put in the .bss section which is simply filled - * with zeroes when transitioning from "ROM", which is really RAM, to other - * RAM. - */ -struct sysinfo_t lib_sysinfo __attribute__((section(".data"))); - -/* - * Some of this is x86 specific, and the rest of it is generic. Right now, - * since we only support x86, we'll avoid trying to make lots of infrastructure - * we don't need. If in the future, we want to use coreboot on some other - * architecture, then take out the generic parsing code and move it elsewhere. - */ - -/* === Parsing code === */ -/* This is the generic parsing code. */ - -static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_memory *mem = (struct cb_memory *)ptr; - int count = MEM_RANGE_COUNT(mem); - int i; - - if (count > SYSINFO_MAX_MEM_RANGES) - count = SYSINFO_MAX_MEM_RANGES; - - info->n_memranges = 0; - - for (i = 0; i < count; i++) { - struct cb_memory_range *range = - (struct cb_memory_range *)MEM_RANGE_PTR(mem, i); - - info->memrange[info->n_memranges].base = - UNPACK_CB64(range->start); - - info->memrange[info->n_memranges].size = - UNPACK_CB64(range->size); - - info->memrange[info->n_memranges].type = range->type; - - info->n_memranges++; - } -} - -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_vbnv(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr; - - info->vbnv_start = vbnv->vbnv_start; - info->vbnv_size = vbnv->vbnv_size; -} - -static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr; - - if (entry->id != CBMEM_ID_SMBIOS) - return; - - info->smbios_start = entry->address; - info->smbios_size = entry->entry_size; -} - -static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info) -{ - int i; - struct cb_gpios *gpios = (struct cb_gpios *)ptr; - - info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ? - (gpios->count) : SYSINFO_MAX_GPIOS; - - for (i = 0; i < info->num_gpios; i++) - info->gpios[i] = gpios->gpios[i]; -} - -static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info) -{ - struct cb_vdat *vdat = (struct cb_vdat *) ptr; - - info->vdat_addr = vdat->vdat_addr; - info->vdat_size = vdat->vdat_size; -} - -static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info) -{ - info->tstamp_table = ((struct cb_cbmem_tab *)ptr)->cbmem_tab; -} - -static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info) -{ - info->cbmem_cons = ((struct cb_cbmem_tab *)ptr)->cbmem_tab; -} - -static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info) -{ - info->framebuffer = (struct cb_framebuffer *)ptr; -} - -static void cb_parse_string(unsigned char *ptr, char **info) -{ - *info = (char *)((struct cb_string *)ptr)->string; -} - -__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr) -{ -} - -static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) -{ - unsigned char *ptr = addr; - struct cb_header *header; - int i; - - header = (struct cb_header *)ptr; - if (!header->table_bytes) - return 0; - - /* Make sure the checksums match. */ - if (!ip_checksum_ok(header, sizeof(*header))) - return -1; - - if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) != - header->table_checksum) - return -1; - - /* Now, walk the tables. */ - ptr += header->header_bytes; - - /* 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). */ - switch (rec->tag) { - case CB_TAG_FORWARD: - return cb_parse_header( - (void *)(unsigned long) - ((struct cb_forward *)rec)->forward, - len, info); - continue; - case CB_TAG_MEMORY: - cb_parse_memory(ptr, info); - break; - case CB_TAG_SERIAL: - cb_parse_serial(ptr, info); - break; - case CB_TAG_VERSION: - cb_parse_string(ptr, &info->version); - break; - case CB_TAG_EXTRA_VERSION: - cb_parse_string(ptr, &info->extra_version); - break; - case CB_TAG_BUILD: - cb_parse_string(ptr, &info->build); - break; - case CB_TAG_COMPILE_TIME: - cb_parse_string(ptr, &info->compile_time); - break; - case CB_TAG_COMPILE_BY: - cb_parse_string(ptr, &info->compile_by); - break; - case CB_TAG_COMPILE_HOST: - cb_parse_string(ptr, &info->compile_host); - break; - case CB_TAG_COMPILE_DOMAIN: - cb_parse_string(ptr, &info->compile_domain); - break; - case CB_TAG_COMPILER: - cb_parse_string(ptr, &info->compiler); - break; - case CB_TAG_LINKER: - cb_parse_string(ptr, &info->linker); - break; - case CB_TAG_ASSEMBLER: - cb_parse_string(ptr, &info->assembler); - break; - /* - * FIXME we should warn on serial if coreboot set up a - * framebuffer buf the payload does not know about it. - */ - case CB_TAG_FRAMEBUFFER: - cb_parse_framebuffer(ptr, info); - break; - case CB_TAG_GPIO: - cb_parse_gpios(ptr, info); - break; - case CB_TAG_VDAT: - cb_parse_vdat(ptr, info); - 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); - break; - case CB_TAG_CBMEM_ENTRY: - cb_parse_cbmem_entry(ptr, info); - break; - default: - cb_parse_unhandled(rec->tag, ptr); - break; - } - - ptr += rec->size; - } - - return 1; -} - -/* == Architecture specific == */ -/* This is the x86 specific stuff. */ - -int get_coreboot_info(struct sysinfo_t *info) -{ - long addr; - int ret; - - addr = locate_coreboot_table(); - if (addr < 0) - return addr; - ret = cb_parse_header((void *)addr, 0x1000, info); - if (!ret) - return -ENOENT; - gd->arch.coreboot_table = addr; - gd->flags |= GD_FLG_SKIP_LL_INIT; - - return 0; -} diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 1bcbb49..65d9b3b 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 0000000..b5250d9 --- /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/lib/coreboot/cb_sysinfo.c b/arch/x86/lib/coreboot/cb_sysinfo.c new file mode 100644 index 0000000..816a0ef --- /dev/null +++ b/arch/x86/lib/coreboot/cb_sysinfo.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2008 Advanced Micro Devices, Inc. + * Copyright (C) 2009 coresystems GmbH + */ + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * This needs to be in the .data section so that it's copied over during + * relocation. By default it's put in the .bss section which is simply filled + * with zeroes when transitioning from "ROM", which is really RAM, to other + * RAM. + */ +struct sysinfo_t lib_sysinfo __attribute__((section(".data"))); + +/* + * Some of this is x86 specific, and the rest of it is generic. Right now, + * since we only support x86, we'll avoid trying to make lots of infrastructure + * we don't need. If in the future, we want to use coreboot on some other + * architecture, then take out the generic parsing code and move it elsewhere. + */ + +/* === Parsing code === */ +/* This is the generic parsing code. */ + +static void cb_parse_memory(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_memory *mem = (struct cb_memory *)ptr; + int count = MEM_RANGE_COUNT(mem); + int i; + + if (count > SYSINFO_MAX_MEM_RANGES) + count = SYSINFO_MAX_MEM_RANGES; + + info->n_memranges = 0; + + for (i = 0; i < count; i++) { + struct cb_memory_range *range = + (struct cb_memory_range *)MEM_RANGE_PTR(mem, i); + + info->memrange[info->n_memranges].base = + UNPACK_CB64(range->start); + + info->memrange[info->n_memranges].size = + UNPACK_CB64(range->size); + + info->memrange[info->n_memranges].type = range->type; + + info->n_memranges++; + } +} + +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_vbnv(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_vbnv *vbnv = (struct cb_vbnv *)ptr; + + info->vbnv_start = vbnv->vbnv_start; + info->vbnv_size = vbnv->vbnv_size; +} + +static void cb_parse_cbmem_entry(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_cbmem_entry *entry = (struct cb_cbmem_entry *)ptr; + + if (entry->id != CBMEM_ID_SMBIOS) + return; + + info->smbios_start = entry->address; + info->smbios_size = entry->entry_size; +} + +static void cb_parse_gpios(unsigned char *ptr, struct sysinfo_t *info) +{ + int i; + struct cb_gpios *gpios = (struct cb_gpios *)ptr; + + info->num_gpios = (gpios->count < SYSINFO_MAX_GPIOS) ? + (gpios->count) : SYSINFO_MAX_GPIOS; + + for (i = 0; i < info->num_gpios; i++) + info->gpios[i] = gpios->gpios[i]; +} + +static void cb_parse_vdat(unsigned char *ptr, struct sysinfo_t *info) +{ + struct cb_vdat *vdat = (struct cb_vdat *) ptr; + + info->vdat_addr = vdat->vdat_addr; + info->vdat_size = vdat->vdat_size; +} + +static void cb_parse_tstamp(unsigned char *ptr, struct sysinfo_t *info) +{ + info->tstamp_table = ((struct cb_cbmem_tab *)ptr)->cbmem_tab; +} + +static void cb_parse_cbmem_cons(unsigned char *ptr, struct sysinfo_t *info) +{ + info->cbmem_cons = ((struct cb_cbmem_tab *)ptr)->cbmem_tab; +} + +static void cb_parse_framebuffer(unsigned char *ptr, struct sysinfo_t *info) +{ + info->framebuffer = (struct cb_framebuffer *)ptr; +} + +static void cb_parse_string(unsigned char *ptr, char **info) +{ + *info = (char *)((struct cb_string *)ptr)->string; +} + +__weak void cb_parse_unhandled(u32 tag, unsigned char *ptr) +{ +} + +static int cb_parse_header(void *addr, int len, struct sysinfo_t *info) +{ + unsigned char *ptr = addr; + struct cb_header *header; + int i; + + header = (struct cb_header *)ptr; + if (!header->table_bytes) + return 0; + + /* Make sure the checksums match. */ + if (!ip_checksum_ok(header, sizeof(*header))) + return -1; + + if (compute_ip_checksum(ptr + sizeof(*header), header->table_bytes) != + header->table_checksum) + return -1; + + /* Now, walk the tables. */ + ptr += header->header_bytes; + + /* 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). */ + switch (rec->tag) { + case CB_TAG_FORWARD: + return cb_parse_header( + (void *)(unsigned long) + ((struct cb_forward *)rec)->forward, + len, info); + continue; + case CB_TAG_MEMORY: + cb_parse_memory(ptr, info); + break; + case CB_TAG_SERIAL: + cb_parse_serial(ptr, info); + break; + case CB_TAG_VERSION: + cb_parse_string(ptr, &info->version); + break; + case CB_TAG_EXTRA_VERSION: + cb_parse_string(ptr, &info->extra_version); + break; + case CB_TAG_BUILD: + cb_parse_string(ptr, &info->build); + break; + case CB_TAG_COMPILE_TIME: + cb_parse_string(ptr, &info->compile_time); + break; + case CB_TAG_COMPILE_BY: + cb_parse_string(ptr, &info->compile_by); + break; + case CB_TAG_COMPILE_HOST: + cb_parse_string(ptr, &info->compile_host); + break; + case CB_TAG_COMPILE_DOMAIN: + cb_parse_string(ptr, &info->compile_domain); + break; + case CB_TAG_COMPILER: + cb_parse_string(ptr, &info->compiler); + break; + case CB_TAG_LINKER: + cb_parse_string(ptr, &info->linker); + break; + case CB_TAG_ASSEMBLER: + cb_parse_string(ptr, &info->assembler); + break; + /* + * FIXME we should warn on serial if coreboot set up a + * framebuffer buf the payload does not know about it. + */ + case CB_TAG_FRAMEBUFFER: + cb_parse_framebuffer(ptr, info); + break; + case CB_TAG_GPIO: + cb_parse_gpios(ptr, info); + break; + case CB_TAG_VDAT: + cb_parse_vdat(ptr, info); + 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); + break; + case CB_TAG_CBMEM_ENTRY: + cb_parse_cbmem_entry(ptr, info); + break; + default: + cb_parse_unhandled(rec->tag, ptr); + break; + } + + ptr += rec->size; + } + + return 1; +} + +/* == Architecture specific == */ +/* This is the x86 specific stuff. */ + +int get_coreboot_info(struct sysinfo_t *info) +{ + long addr; + int ret; + + addr = locate_coreboot_table(); + if (addr < 0) + return addr; + ret = cb_parse_header((void *)addr, 0x1000, info); + if (!ret) + return -ENOENT; + gd->arch.coreboot_table = addr; + gd->flags |= GD_FLG_SKIP_LL_INIT; + + return 0; +} -- cgit v1.1 From 1058ab37f7176370e835d53299c2ae44437925e3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:22 +1300 Subject: x86: coreboot: Update parsing of the latest sysinfo 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 --- 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 419ec52..675eef6 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-2013.04/src/soc/nvidia/tegra210/mtc.c + * @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 3172814..a74654b 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 816a0ef..e2c65bf 100644 --- a/arch/x86/lib/coreboot/cb_sysinfo.c +++ b/arch/x86/lib/coreboot/cb_sysinfo.c @@ -7,8 +7,10 @@ */ #include -#include #include +#include +#include +#include #include 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; +} -- cgit v1.1 From e7bae8283fea94cf470542916a063182c9e5771a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:23 +1300 Subject: x86: Allow installing an e820 when booting from coreboot 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 --- 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 | 13 ++++++++++-- 5 files changed, 69 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 43604ee..4a256ba 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 a66c0d2..850a0a7 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 b5250d9..cb0ae1d 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 0000000..ebb45cd --- /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 +#include +#include + +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 602788e..90fc8a4 100644 --- a/arch/x86/lib/zimage.c +++ b/arch/x86/lib/zimage.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #ifdef CONFIG_SYS_COREBOOT #include #endif @@ -35,6 +37,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + /* * Memory lay-out: * @@ -309,8 +313,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; -- cgit v1.1 From 71cebf0b5947cc0e393bec0841744d9eda0a038d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:24 +1300 Subject: x86: Add a command to display coreboot sysinfo 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 --- 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 e4bb1d4..8ab34f3 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -2251,6 +2251,15 @@ config CMD_BEDBUG for some PowerPC processors. For details please see the documentation in doc/README.bedbug. +config CMD_CBSYSINFO + bool "cbsysinfo" + depends on X86 + default y if SYS_COREBOOT + help + This provides information about the coreboot sysinfo table stored in + memory by coreboot before jumping to U-Boot. It can be useful for + debugging the beaaviour of coreboot or U-Boot. + config CMD_DIAG bool "diag - Board diagnostics" help diff --git a/cmd/x86/Makefile b/cmd/x86/Makefile index 144b1cf..5f82204 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 0000000..a0db0ad --- /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 + */ + +#include +#include +#include +#include +#include + +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 ""; +} + +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 35c515f..fb83434 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -21,6 +21,7 @@ Shell commands booti bootmenu button + x86/cbsysinfo conitrace echo exception diff --git a/doc/usage/x86/cbsysinfo.rst b/doc/usage/x86/cbsysinfo.rst new file mode 100644 index 0000000..8c03a85 --- /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 -- cgit v1.1 From 907bcd3a33253515cb1bdc01077e127c6735f74b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:25 +1300 Subject: cmd: Add missing check for CONFIG_SYS_LONGHELP Two commands are missing this check, so compilation fails when building without CONFIG_CMDLINE. Add it. Signed-off-by: Simon Glass --- cmd/acpi.c | 2 ++ cmd/bloblist.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/cmd/acpi.c b/cmd/acpi.c index 157261b..e5b9a17 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 - 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 97b5734..21e7ff6 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), -- cgit v1.1 From bcac36185b49eaaab437a8db196d804380872c5c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:26 +1300 Subject: video: Fix video on coreboot with the copy buffer 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 --- 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 a14a4db..7bad4c8 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; -- cgit v1.1 From 19987c9834bfd854ff27ae0382ce18511b84c6ea Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:27 +1300 Subject: x86: video: Allow coreboot video to be used on any x86 board 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 --- 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 667157c..63ae2ba 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 55f72fe..7237542 100644 --- a/drivers/video/coreboot.c +++ b/drivers/video/coreboot.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -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; } -- cgit v1.1 From 937175ee72fa5318016be3d887bd1a1b5409f038 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:28 +1300 Subject: x86: fsp: Don't enable FSP graphics if booted from coreboot 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 --- 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 cc909e0..02fd05c 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: "); -- cgit v1.1 From b8bcccedac91b8551bf00af724d6a5d45f47bd0f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:29 +1300 Subject: dm: core: Add CBFS support to flashmap 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 --- 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 ca15df2..fc4f974 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; }; /** -- cgit v1.1 From 2018a33cb7e5adc1c71dd63ec4502b79a758757a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:30 +1300 Subject: x86: coral: Avoid build error with !CONFIG_ACPIGEN When CONFIG_ACPIGEN is not enabled the CPU code does not build. Fix this by moving things around. Signed-off-by: Simon Glass --- 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 fbc016d..647c9df 100644 --- a/arch/x86/cpu/apollolake/cpu.c +++ b/arch/x86/cpu/apollolake/cpu.c @@ -19,6 +19,7 @@ #include #include +#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, -- cgit v1.1 From 51de94dfe497b150c066788a38e93bd989ae7552 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:31 +1300 Subject: x86: coral: Allow init of debug UART in U-Boot proper 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 --- 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 63f6999..5d7d26b 100644 --- a/arch/x86/cpu/apollolake/cpu_common.c +++ b/arch/x86/cpu/apollolake/cpu_common.c @@ -7,11 +7,17 @@ #include #include #include +#include #include +#include #include #include +#include #include +/* 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 9a18476..8f48457 100644 --- a/arch/x86/cpu/apollolake/cpu_spl.c +++ b/arch/x86/cpu/apollolake/cpu_spl.c @@ -31,68 +31,10 @@ #include #include #include -#include #include #include #include -/* 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 905c825..abfd4ab 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 38335b0..c3ca171 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 #include /** -- cgit v1.1 From 8657989f29d9c9d1c489ef9392501c6a3aae36e8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:32 +1300 Subject: x86: coral: Fall back to coreboot video when FSP missing 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 --- 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 db8eb88..527c0ad 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; }; -- cgit v1.1 From 9087e468c7f8a8bc6fb6b4511ba35539752ca33b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:33 +1300 Subject: x86: fsp: Don't notify if booted from coreboot 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 --- 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 503f97d..b2c7658 100644 --- a/arch/x86/lib/fsp2/fsp_support.c +++ b/arch/x86/lib/fsp2/fsp_support.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -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; -- cgit v1.1 From 70f5c99d607d8687d4e537c388af82bb194f2ef9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:00:34 +1300 Subject: x86: coreboot: Don't setup MTRR when booting from coreboot This currently hangs and it is not necessary in any case. Drop the code when booting from coreboot. Signed-off-by: Simon Glass --- 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 066dc40..67401b9 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(); } -- cgit v1.1 From 539db6ab09c06ff052dac6c585ec1eaf3f1d6dc8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:06 +1300 Subject: sandbox: Only call timer_timebase_fallback() if present This function only exists if CPU is enabled. Update the code to take account of this, so that it does not have to be enabled on all sandbox builds. Signed-off-by: Simon Glass Reviewed-by: Sean Anderson --- drivers/timer/sandbox_timer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/timer/sandbox_timer.c b/drivers/timer/sandbox_timer.c index 2075cd4..c846bfb 100644 --- a/drivers/timer/sandbox_timer.c +++ b/drivers/timer/sandbox_timer.c @@ -38,7 +38,8 @@ static int sandbox_timer_probe(struct udevice *dev) { struct timer_dev_priv *uc_priv = dev_get_uclass_priv(dev); - if (dev_read_bool(dev, "sandbox,timebase-frequency-fallback")) + if (CONFIG_IS_ENABLED(CPU) && + dev_read_bool(dev, "sandbox,timebase-frequency-fallback")) return timer_timebase_fallback(dev); else if (!uc_priv->clock_rate) uc_priv->clock_rate = SANDBOX_TIMER_RATE; -- cgit v1.1 From 5d8c37910d87828e914262991de7d5599d63692a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:07 +1300 Subject: sandbox: Only delete the executable if requested At present sandbox removes its executable after failing to run it, since there is no other way that it would get cleaned up. However, this is actually only wanted if the image was created within sandbox. For the case where the image was generated by the build system, such as u-boot-spl, we don't want to delete it. Handle the two code paths accordingly. Signed-off-by: Simon Glass --- arch/sandbox/cpu/os.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index 68825d2..b9ad341 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -711,7 +711,7 @@ static int add_args(char ***argvp, char *add_args[], int count) * @fname: Filename to exec * @return does not return on success, any return value is an error */ -static int os_jump_to_file(const char *fname) +static int os_jump_to_file(const char *fname, bool delete_it) { struct sandbox_state *state = state_get_current(); char mem_fname[30]; @@ -734,11 +734,13 @@ static int os_jump_to_file(const char *fname) os_fd_restore(); - extra_args[0] = "-j"; - extra_args[1] = (char *)fname; - extra_args[2] = "-m"; - extra_args[3] = mem_fname; - argc = 4; + argc = 0; + if (delete_it) { + extra_args[argc++] = "-j"; + extra_args[argc++] = (char *)fname; + } + extra_args[argc++] = "-m"; + extra_args[argc++] = mem_fname; if (state->ram_buf_rm) extra_args[argc++] = "--rm_memory"; err = add_args(&argv, extra_args, argc); @@ -762,7 +764,10 @@ static int os_jump_to_file(const char *fname) return err; } - return unlink(fname); + if (delete_it) + return unlink(fname); + + return -EFAULT; } int os_jump_to_image(const void *dest, int size) @@ -774,7 +779,7 @@ int os_jump_to_image(const void *dest, int size) if (err) return err; - return os_jump_to_file(fname); + return os_jump_to_file(fname, true); } int os_find_u_boot(char *fname, int maxlen, bool use_img) @@ -847,7 +852,8 @@ int os_spl_to_uboot(const char *fname) /* U-Boot will delete ram buffer after read: "--rm_memory"*/ state->ram_buf_rm = true; - return os_jump_to_file(fname); + + return os_jump_to_file(fname, false); } long os_get_time_offset(void) -- cgit v1.1 From a5bc9abcee0ac8982c14f9cd585570a268eb9e47 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:08 +1300 Subject: sandbox: cros_ec: Only write EC state when the EC is probed This can crash if the EC has not yet been probed. Add a check to prevent this. Signed-off-by: Simon Glass --- drivers/misc/cros_ec_sandbox.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index cb8adc4..bc01df0 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -153,10 +153,14 @@ static int cros_ec_write_state(void *blob, int node) { struct ec_state *ec = g_state; + if (!g_state) + return 0; + /* We are guaranteed enough space to write basic properties */ fdt_setprop_u32(blob, node, "current-image", ec->current_image); fdt_setprop(blob, node, "vbnv-context", ec->vbnv_context, sizeof(ec->vbnv_context)); + return state_setprop(node, "flash-data", ec->flash_data, ec->ec_config.flash.length); } -- cgit v1.1 From 1503c2c7906d191e24579246fc3a6fcd656a890b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:09 +1300 Subject: sandbox: Disintangle declarations in do_host_bind() This function has a strange mix of declarations and argument parsing which is a bit hard to follow and harder to modify. Separate out the declarations at the start of the function and adjust the ordering of the code slightly. Signed-off-by: Simon Glass --- cmd/host.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/cmd/host.c b/cmd/host.c index 1d21f79..927c23d 100644 --- a/cmd/host.c +++ b/cmd/host.c @@ -41,16 +41,21 @@ static int do_host_save(struct cmd_tbl *cmdtp, int flag, int argc, static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + const char *dev_str; + char *file; + char *ep; + int dev; + if (argc < 2 || argc > 3) return CMD_RET_USAGE; - char *ep; - char *dev_str = argv[1]; - char *file = argc >= 3 ? argv[2] : NULL; - int dev = simple_strtoul(dev_str, &ep, 16); + dev_str = argv[1]; + dev = simple_strtoul(dev_str, &ep, 16); if (*ep) { printf("** Bad device specification %s **\n", dev_str); return CMD_RET_USAGE; } + file = argc >= 3 ? argv[2] : NULL; + return !!host_dev_bind(dev, file); } -- cgit v1.1 From 803e9c1c94d06cfab43606056c653268e12926d8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:10 +1300 Subject: sandbox: Update do_host_bind() argument counting Remove the 'bind' subcommand before processing the arguments. This will make it easier to add an optional flag. Signed-off-by: Simon Glass --- cmd/host.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/host.c b/cmd/host.c index 927c23d..847bb1d 100644 --- a/cmd/host.c +++ b/cmd/host.c @@ -46,15 +46,18 @@ static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc, char *ep; int dev; - if (argc < 2 || argc > 3) + /* Skip 'bind' */ + argc--; + argv++; + if (argc < 1 || argv > 2) return CMD_RET_USAGE; - dev_str = argv[1]; + dev_str = argv[0]; dev = simple_strtoul(dev_str, &ep, 16); if (*ep) { printf("** Bad device specification %s **\n", dev_str); return CMD_RET_USAGE; } - file = argc >= 3 ? argv[2] : NULL; + file = argc > 1 ? argv[1] : NULL; return !!host_dev_bind(dev, file); } -- cgit v1.1 From 1758551ec9526d56303a2b5cf1f58147e66945ed Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:11 +1300 Subject: sandbox: Provide a way to bind fixed/removeable devices At present when a file is bound to a host device it is always marked as removeable. Arguably the device is removeable, since it can be unbound at will. However while it is bound, it is not considered removable by the user. Also it is useful to be able to model both fixed and removeable devices for code that distinguishes them. Add a -r flag to the 'host bind' command and plumb it through to provide this feature. Signed-off-by: Simon Glass --- cmd/host.c | 19 +++++++++++++++---- doc/arch/sandbox.rst | 2 ++ drivers/block/sandbox.c | 8 ++++---- include/sandboxblockdev.h | 9 ++++++++- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/cmd/host.c b/cmd/host.c index 847bb1d..6aa3d91 100644 --- a/cmd/host.c +++ b/cmd/host.c @@ -41,6 +41,7 @@ static int do_host_save(struct cmd_tbl *cmdtp, int flag, int argc, static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { + bool removable = false; const char *dev_str; char *file; char *ep; @@ -49,7 +50,16 @@ static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc, /* Skip 'bind' */ argc--; argv++; - if (argc < 1 || argv > 2) + if (argc < 2) + return CMD_RET_USAGE; + + if (!strcmp(argv[0], "-r")) { + removable = true; + argc--; + argv++; + } + + if (argc > 2) return CMD_RET_USAGE; dev_str = argv[0]; dev = simple_strtoul(dev_str, &ep, 16); @@ -59,7 +69,7 @@ static int do_host_bind(struct cmd_tbl *cmdtp, int flag, int argc, } file = argc > 1 ? argv[1] : NULL; - return !!host_dev_bind(dev, file); + return !!host_dev_bind(dev, file, removable); } static int do_host_info(struct cmd_tbl *cmdtp, int flag, int argc, @@ -154,7 +164,7 @@ static struct cmd_tbl cmd_host_sub[] = { U_BOOT_CMD_MKENT(ls, 3, 0, do_host_ls, "", ""), U_BOOT_CMD_MKENT(save, 6, 0, do_host_save, "", ""), U_BOOT_CMD_MKENT(size, 3, 0, do_host_size, "", ""), - U_BOOT_CMD_MKENT(bind, 3, 0, do_host_bind, "", ""), + U_BOOT_CMD_MKENT(bind, 4, 0, do_host_bind, "", ""), U_BOOT_CMD_MKENT(info, 3, 0, do_host_info, "", ""), U_BOOT_CMD_MKENT(dev, 0, 1, do_host_dev, "", ""), }; @@ -186,7 +196,8 @@ U_BOOT_CMD( "host save hostfs - [] - " "save a file to host\n" "host size hostfs - - determine size of file on host\n" - "host bind [] - bind \"host\" device to file\n" + "host bind [-r] [] - bind \"host\" device to file\n" + " -r = mark as removable\n" "host info [] - show device binding & info\n" "host dev [] - Set or retrieve the current host device\n" "host commands use the \"hostfs\" device. The \"host\" device is used\n" diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst index 8b18a22..e052b6b 100644 --- a/doc/arch/sandbox.rst +++ b/doc/arch/sandbox.rst @@ -389,6 +389,8 @@ the contents of the root directory on the second partion of the image =>host bind 0 ./disk.raw =>ls host 0:2 +The device can be marked removeable with 'host bind -r'. + A disk image can be created using the following commands:: $> truncate -s 1200M ./disk.raw diff --git a/drivers/block/sandbox.c b/drivers/block/sandbox.c index e2f229b..1c2c3b4 100644 --- a/drivers/block/sandbox.c +++ b/drivers/block/sandbox.c @@ -89,7 +89,7 @@ static unsigned long host_block_write(struct blk_desc *block_dev, } #ifdef CONFIG_BLK -int host_dev_bind(int devnum, char *filename) +int host_dev_bind(int devnum, char *filename, bool removable) { struct host_block_dev *host_dev; struct udevice *dev; @@ -146,7 +146,7 @@ int host_dev_bind(int devnum, char *filename) } desc = blk_get_devnum_by_type(IF_TYPE_HOST, devnum); - desc->removable = 1; + desc->removable = removable; snprintf(desc->vendor, BLK_VEN_SIZE, "U-Boot"); snprintf(desc->product, BLK_PRD_SIZE, "hostfile"); snprintf(desc->revision, BLK_REV_SIZE, "1.0"); @@ -160,7 +160,7 @@ err: return ret; } #else -int host_dev_bind(int dev, char *filename) +int host_dev_bind(int dev, char *filename, bool removable) { struct host_block_dev *host_dev = find_host_device(dev); @@ -195,7 +195,7 @@ int host_dev_bind(int dev, char *filename) blk_dev->block_write = host_block_write; blk_dev->devnum = dev; blk_dev->part_type = PART_TYPE_UNKNOWN; - blk_dev->removable = 1; + blk_dev->removable = removable; snprintf(blk_dev->vendor, BLK_VEN_SIZE, "U-Boot"); snprintf(blk_dev->product, BLK_PRD_SIZE, "hostfile"); snprintf(blk_dev->revision, BLK_REV_SIZE, "1.0"); diff --git a/include/sandboxblockdev.h b/include/sandboxblockdev.h index c1f0afb..4006e94 100644 --- a/include/sandboxblockdev.h +++ b/include/sandboxblockdev.h @@ -14,6 +14,13 @@ struct host_block_dev { int fd; }; -int host_dev_bind(int dev, char *filename); +/** + * host_dev_bind() - Bind or unbind a device + * + * @dev: Device number (0=first slot) + * @filename: Host filename to use, or NULL to unbind + * @removable: true if the block device should mark itself as removable + */ +int host_dev_bind(int dev, char *filename, bool removable); #endif -- cgit v1.1 From e2734d647e9c86f46083b29224fc7b41a46e1858 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:12 +1300 Subject: sandbox: image: Allow sandbox to load any image Sandbox is special in that it is used for testing and it does not match any particular target architecture. Allow it to load an image from any architecture, so that 'bootm' can be used as needed. Signed-off-by: Simon Glass --- common/image-fit.c | 4 ++++ include/image.h | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/common/image-fit.c b/common/image-fit.c index 28b3d2b..2d0ece6 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1512,6 +1512,10 @@ int fit_image_check_arch(const void *fit, int noffset, uint8_t arch) uint8_t image_arch; int aarch32_support = 0; + /* Let's assume that sandbox can load any architecture */ + if (IS_ENABLED(CONFIG_SANDBOX)) + return true; + if (IS_ENABLED(CONFIG_ARM64_SUPPORT_AARCH32)) aarch32_support = 1; diff --git a/include/image.h b/include/image.h index 138c83d..bcd126d 100644 --- a/include/image.h +++ b/include/image.h @@ -886,6 +886,11 @@ static inline int image_check_type(const image_header_t *hdr, uint8_t type) } static inline int image_check_arch(const image_header_t *hdr, uint8_t arch) { +#ifndef USE_HOSTCC + /* Let's assume that sandbox can load any architecture */ + if (IS_ENABLED(CONFIG_SANDBOX)) + return true; +#endif return (image_get_arch(hdr) == arch) || (image_get_arch(hdr) == IH_ARCH_ARM && arch == IH_ARCH_ARM64); } -- cgit v1.1 From b6da55976439c63e4f3037a65b0dde1656e7af6a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:13 +1300 Subject: test: Silenece the echo and print tests These tests current produce unwanted output on sandbox. Use the correct functions to controller console output, to avoid this. Signed-off-by: Simon Glass --- test/cmd/test_echo.c | 3 ++- test/lib/test_print.c | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/test/cmd/test_echo.c b/test/cmd/test_echo.c index aa5cebc..9d60d7d 100644 --- a/test/cmd/test_echo.c +++ b/test/cmd/test_echo.c @@ -44,9 +44,10 @@ static int lib_test_hush_echo(struct unit_test_state *uts) int i; for (i = 0; i < ARRAY_SIZE(echo_data); ++i) { + ut_silence_console(uts); console_record_reset_enable(); ut_assertok(run_command(echo_data[i].cmd, 0)); - gd->flags &= ~GD_FLG_RECORD; + ut_unsilence_console(uts); console_record_readline(uts->actual_str, sizeof(uts->actual_str)); ut_asserteq_str(echo_data[i].expected, uts->actual_str); diff --git a/test/lib/test_print.c b/test/lib/test_print.c index 12972f1..a60a5a5 100644 --- a/test/lib/test_print.c +++ b/test/lib/test_print.c @@ -18,12 +18,14 @@ DECLARE_GLOBAL_DATA_PTR; static int test_print_freq(struct unit_test_state *uts, uint64_t freq, char *expected) { + ut_silence_console(uts); console_record_reset_enable(); print_freq(freq, ";\n"); - gd->flags &= ~GD_FLG_RECORD; + ut_unsilence_console(uts); console_record_readline(uts->actual_str, sizeof(uts->actual_str)); ut_asserteq_str(expected, uts->actual_str); ut_assertok(ut_check_console_end(uts)); + return 0; } @@ -46,12 +48,14 @@ LIB_TEST(lib_test_print_freq, 0); static int test_print_size(struct unit_test_state *uts, uint64_t freq, char *expected) { + ut_silence_console(uts); console_record_reset_enable(); print_size(freq, ";\n"); - gd->flags &= ~GD_FLG_RECORD; + ut_unsilence_console(uts); console_record_readline(uts->actual_str, sizeof(uts->actual_str)); ut_asserteq_str(expected, uts->actual_str); ut_assertok(ut_check_console_end(uts)); + return 0; } -- cgit v1.1 From dc2886b039af3add52edf370d12d05366fe59eb6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:14 +1300 Subject: binman: Show a message when changing subnodes This change seems important enough to warrant a visible message. Change the log_debug() to log_info(). Signed-off-by: Simon Glass --- lib/binman.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/binman.c b/lib/binman.c index 6040ec8..530df6a 100644 --- a/lib/binman.c +++ b/lib/binman.c @@ -128,8 +128,8 @@ int binman_select_subnode(const char *name) if (!ofnode_valid(node)) return log_msg_ret("node", -ENOENT); binman->image = node; - log_debug("binman: Selected image subnode '%s'\n", - ofnode_get_name(binman->image)); + log_info("binman: Selected image subnode '%s'\n", + ofnode_get_name(binman->image)); return 0; } -- cgit v1.1 From 05e3a0d64833763990303eaab117d8902c38470f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:15 +1300 Subject: spl: Split out bootstage ID into a function We have two separate places that need to figure out the bootstage ID to use. Put this code in a function so that the logic is in one place. Signed-off-by: Simon Glass --- common/spl/spl.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index 5f51098..556a91a 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -387,6 +387,22 @@ static inline int write_spl_handoff(void) { return 0; } #endif /* HANDOFF */ +/** + * get_bootstage_id() - Get the bootstage ID to emit + * + * @start: true if this is for starting SPL, false for ending it + * @return bootstage ID to use + */ +static enum bootstage_id get_bootstage_id(bool start) +{ + enum u_boot_phase phase = spl_phase(); + + if (IS_ENABLED(CONFIG_TPL_BUILD) && phase == PHASE_TPL) + return start ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_END_TPL; + else + return start ? BOOTSTAGE_ID_START_SPL : BOOTSTAGE_ID_END_SPL; +} + static int spl_common_init(bool setup_malloc) { int ret; @@ -417,8 +433,8 @@ static int spl_common_init(bool setup_malloc) __func__, ret); } #endif /* CONFIG_BOOTSTAGE_STASH */ - bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL : - BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME); + bootstage_mark_name(get_bootstage_id(true), + spl_phase_name(spl_phase())); #if CONFIG_IS_ENABLED(LOG) ret = log_init(); if (ret) { @@ -733,8 +749,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); #endif - bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_END_TPL : - BOOTSTAGE_ID_END_SPL, "end " SPL_TPL_NAME); + bootstage_mark_name(get_bootstage_id(false), "end phase"); #ifdef CONFIG_BOOTSTAGE_STASH ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, CONFIG_BOOTSTAGE_STASH_SIZE); -- cgit v1.1 From eb26d88d55e6ed92214d98b81457ddcc743347a0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:16 +1300 Subject: bootstage: Warning if space is exhausted At present bootstage silently ignores new records if it runs out of space. It is sometimes obvious by looking at the report, but the IDs are not contiguous, so it is easy to miss. Aad a message so that action can be taken. Signed-off-by: Simon Glass --- common/bootstage.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/common/bootstage.c b/common/bootstage.c index 2c0110c..4621105 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -9,6 +9,8 @@ * permits accurate timestamping of each. */ +#define LOG_CATEGORY LOGC_BOOT + #include #include #include @@ -127,12 +129,16 @@ ulong bootstage_add_record(enum bootstage_id id, const char *name, /* Only record the first event for each */ rec = find_id(data, id); - if (!rec && data->rec_count < RECORD_COUNT) { - rec = &data->record[data->rec_count++]; - rec->time_us = mark; - rec->name = name; - rec->flags = flags; - rec->id = id; + if (!rec) { + if (data->rec_count < RECORD_COUNT) { + rec = &data->record[data->rec_count++]; + rec->time_us = mark; + rec->name = name; + rec->flags = flags; + rec->id = id; + } else { + log_warning("Bootstage space exhasuted\n"); + } } /* Tell the board about this progress */ -- cgit v1.1 From b3b60f59124a1f4fdcee5b7eff3f057e33cfa4c7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:17 +1300 Subject: sf: Support querying write-protect This feature was dropped from U-Boot some time ago: f12f96cfaf5 (sf: Drop spl_flash_get_sw_write_prot") However, we do need a way to see if a flash device is write-protected, since if it is, it may not be possible to write to do (i.e. failing to write is expected). I am not sure of the correct layer to implement this, so this patch is a stab at it. If spi-flash makes sense then I will add to the 'sf' also. Re the points mentioned in the removal commit: 1) This kind of requirement can be achieved using existing flash operations and flash locking API calls instead of making a separate flash API. Which uclass is this? 2) Technically there is no real hardware user for this API to use in the source tree. I do want coral (at least) to support this. 3) Having a flash operations API for simple register read bits also make difficult to extend the flash operations. This new patch only mentions write-protect being on or off, rather than the actual mechanism. 4) Instead of touching generic code, it is possible to have this functionality inside spinor operations in the form of flash hooks or fixups for associated flash chips. That sounds to me like what drivers are for. But we still need some sort of API for it to be accessible. Signed-off-by: Simon Glass --- drivers/mtd/spi/sf-uclass.c | 9 +++++++++ drivers/mtd/spi/sf_internal.h | 4 ++++ drivers/mtd/spi/sf_probe.c | 8 ++++++++ drivers/mtd/spi/spi-nor-core.c | 11 +++++++++++ drivers/mtd/spi/spi-nor-tiny.c | 6 ++++++ include/spi_flash.h | 27 +++++++++++++++++++++++++++ test/dm/sf.c | 10 +++++++++- 7 files changed, 74 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/spi/sf-uclass.c b/drivers/mtd/spi/sf-uclass.c index fd1bec8..cfce00e 100644 --- a/drivers/mtd/spi/sf-uclass.c +++ b/drivers/mtd/spi/sf-uclass.c @@ -31,6 +31,15 @@ int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len) return log_ret(sf_get_ops(dev)->erase(dev, offset, len)); } +int spl_flash_get_sw_write_prot(struct udevice *dev) +{ + struct dm_spi_flash_ops *ops = sf_get_ops(dev); + + if (!ops->get_sw_write_prot) + return -ENOSYS; + return log_ret(ops->get_sw_write_prot(dev)); +} + /* * TODO(sjg@chromium.org): This is an old-style function. We should remove * it when all SPI flash drivers use dm diff --git a/drivers/mtd/spi/sf_internal.h b/drivers/mtd/spi/sf_internal.h index 9ceff0e..786301b 100644 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@ -75,6 +75,10 @@ extern const struct flash_info spi_nor_ids[]; #define JEDEC_MFR(info) ((info)->id[0]) #define JEDEC_ID(info) (((info)->id[1]) << 8 | ((info)->id[2])) +/* Get software write-protect value (BP bits) */ +int spi_flash_cmd_get_sw_write_prot(struct spi_flash *flash); + + #if CONFIG_IS_ENABLED(SPI_FLASH_MTD) int spi_flash_mtd_register(struct spi_flash *flash); void spi_flash_mtd_unregister(void); diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 6c87434..3befbe9 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -130,6 +130,13 @@ static int spi_flash_std_erase(struct udevice *dev, u32 offset, size_t len) return mtd->_erase(mtd, &instr); } +static int spi_flash_std_get_sw_write_prot(struct udevice *dev) +{ + struct spi_flash *flash = dev_get_uclass_priv(dev); + + return spi_flash_cmd_get_sw_write_prot(flash); +} + int spi_flash_std_probe(struct udevice *dev) { struct spi_slave *slave = dev_get_parent_priv(dev); @@ -153,6 +160,7 @@ static const struct dm_spi_flash_ops spi_flash_std_ops = { .read = spi_flash_std_read, .write = spi_flash_std_write, .erase = spi_flash_std_erase, + .get_sw_write_prot = spi_flash_std_get_sw_write_prot, }; static const struct udevice_id spi_flash_std_ids[] = { diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index e0efebc..a662553 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -2647,3 +2647,14 @@ int spi_nor_scan(struct spi_nor *nor) return 0; } + +/* U-Boot specific functions, need to extend MTD to support these */ +int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor) +{ + int sr = read_sr(nor); + + if (sr < 0) + return sr; + + return (sr >> 2) & 7; +} diff --git a/drivers/mtd/spi/spi-nor-tiny.c b/drivers/mtd/spi/spi-nor-tiny.c index 07c8c7b..1d5861d 100644 --- a/drivers/mtd/spi/spi-nor-tiny.c +++ b/drivers/mtd/spi/spi-nor-tiny.c @@ -809,3 +809,9 @@ int spi_nor_scan(struct spi_nor *nor) return 0; } + +/* U-Boot specific functions, need to extend MTD to support these */ +int spi_flash_cmd_get_sw_write_prot(struct spi_nor *nor) +{ + return -ENOTSUPP; +} diff --git a/include/spi_flash.h b/include/spi_flash.h index 478c543..3d747c9 100644 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@ -35,6 +35,19 @@ struct dm_spi_flash_ops { int (*write)(struct udevice *dev, u32 offset, size_t len, const void *buf); int (*erase)(struct udevice *dev, u32 offset, size_t len); + /** + * get_sw_write_prot() - Check state of software write-protect feature + * + * SPI flash chips can lock a region of the flash defined by a + * 'protected area'. This function checks if this protected area is + * defined. + * + * @dev: SPI flash device + * @return 0 if no region is write-protected, 1 if a region is + * write-protected, -ENOSYS if the driver does not implement this, + * other -ve value on error + */ + int (*get_sw_write_prot)(struct udevice *dev); }; /* Access the serial operations for a device */ @@ -77,6 +90,20 @@ int spi_flash_write_dm(struct udevice *dev, u32 offset, size_t len, int spi_flash_erase_dm(struct udevice *dev, u32 offset, size_t len); /** + * spl_flash_get_sw_write_prot() - Check state of software write-protect feature + * + * SPI flash chips can lock a region of the flash defined by a + * 'protected area'. This function checks if this protected area is + * defined. + * + * @dev: SPI flash device + * @return 0 if no region is write-protected, 1 if a region is + * write-protected, -ENOSYS if the driver does not implement this, + * other -ve value on error + */ +int spl_flash_get_sw_write_prot(struct udevice *dev); + +/** * spi_flash_std_probe() - Probe a SPI flash device * * This is the standard internal method for probing a SPI flash device to diff --git a/test/dm/sf.c b/test/dm/sf.c index cc1fc4d..17d43fe 100644 --- a/test/dm/sf.c +++ b/test/dm/sf.c @@ -21,7 +21,7 @@ /* Simple test of sandbox SPI flash */ static int dm_test_spi_flash(struct unit_test_state *uts) { - struct udevice *dev; + struct udevice *dev, *emul; int full_size = 0x200000; int size = 0x10000; u8 *src, *dst; @@ -51,6 +51,14 @@ static int dm_test_spi_flash(struct unit_test_state *uts) ut_assertok(spi_flash_read_dm(dev, 0, size, dst)); ut_asserteq_mem(src, dst, size); + /* Try the write-protect stuff */ + ut_assertok(uclass_first_device_err(UCLASS_SPI_EMUL, &emul)); + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); + sandbox_sf_set_block_protect(emul, 1); + ut_asserteq(1, spl_flash_get_sw_write_prot(dev)); + sandbox_sf_set_block_protect(emul, 0); + ut_asserteq(0, spl_flash_get_sw_write_prot(dev)); + /* Check mapping */ ut_assertok(dm_spi_get_mmap(dev, &map_base, &map_size, &offset)); ut_asserteq(0x1000, map_base); -- cgit v1.1 From 529d5f96cf7be9ae60db1a5f1c2a2aa0a3d5d26d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:18 +1300 Subject: cpu: Rename SPL_CPU_SUPPORT to SPL_CPU The _SUPPORT suffix is from an earlier time and interferes with use of the CONFIG_IS_ENABLED() macro. Rename the option to drop the suffix. Tidy up the TODO that prompted this. Signed-off-by: Simon Glass --- arch/riscv/cpu/ax25/Kconfig | 2 +- arch/riscv/cpu/fu540/Kconfig | 2 +- arch/riscv/cpu/generic/Kconfig | 2 +- arch/x86/lib/spl.c | 2 +- common/spl/Kconfig | 2 +- configs/chromebook_coral_defconfig | 2 +- configs/chromebook_link64_defconfig | 2 +- configs/qemu-x86_64_defconfig | 2 +- drivers/Makefile | 2 +- drivers/timer/timer-uclass.c | 6 +----- 10 files changed, 10 insertions(+), 14 deletions(-) diff --git a/arch/riscv/cpu/ax25/Kconfig b/arch/riscv/cpu/ax25/Kconfig index 327b74e..941d963 100644 --- a/arch/riscv/cpu/ax25/Kconfig +++ b/arch/riscv/cpu/ax25/Kconfig @@ -6,7 +6,7 @@ config RISCV_NDS imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE) imply ANDES_PLIC if (RISCV_MMODE || SPL_RISCV_MMODE) imply ANDES_PLMT_TIMER if (RISCV_MMODE || SPL_RISCV_MMODE) - imply SPL_CPU_SUPPORT + imply SPL_CPU imply SPL_OPENSBI imply SPL_LOAD_FIT help diff --git a/arch/riscv/cpu/fu540/Kconfig b/arch/riscv/cpu/fu540/Kconfig index 61bd5c4..616b256 100644 --- a/arch/riscv/cpu/fu540/Kconfig +++ b/arch/riscv/cpu/fu540/Kconfig @@ -13,7 +13,7 @@ config SIFIVE_FU540 imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE) imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE) imply CMD_CPU - imply SPL_CPU_SUPPORT + imply SPL_CPU imply SPL_OPENSBI imply SPL_LOAD_FIT imply SMP diff --git a/arch/riscv/cpu/generic/Kconfig b/arch/riscv/cpu/generic/Kconfig index f4c2e26..198e36e 100644 --- a/arch/riscv/cpu/generic/Kconfig +++ b/arch/riscv/cpu/generic/Kconfig @@ -10,6 +10,6 @@ config GENERIC_RISCV imply RISCV_TIMER if (RISCV_SMODE || SPL_RISCV_SMODE) imply SIFIVE_CLINT if (RISCV_MMODE || SPL_RISCV_MMODE) imply CMD_CPU - imply SPL_CPU_SUPPORT + imply SPL_CPU imply SPL_OPENSBI imply SPL_LOAD_FIT diff --git a/arch/x86/lib/spl.c b/arch/x86/lib/spl.c index 1bae1f4..b18c1cd 100644 --- a/arch/x86/lib/spl.c +++ b/arch/x86/lib/spl.c @@ -96,7 +96,7 @@ static int x86_spl_init(void) } #endif preloader_console_init(); -#ifndef CONFIG_TPL +#if !defined(CONFIG_TPL) && !CONFIG_IS_ENABLED(CPU) ret = print_cpuinfo(); if (ret) { debug("%s: print_cpuinfo() failed\n", __func__); diff --git a/common/spl/Kconfig b/common/spl/Kconfig index 584f848..0711cbf 100644 --- a/common/spl/Kconfig +++ b/common/spl/Kconfig @@ -500,7 +500,7 @@ config SPL_CACHE_SUPPORT future requests for that data can be served faster. Enable this option to build the drivers in drivers/cache as part of an SPL build. -config SPL_CPU_SUPPORT +config SPL_CPU bool "Support CPU drivers" help Enable this to support CPU drivers in SPL. These drivers can set diff --git a/configs/chromebook_coral_defconfig b/configs/chromebook_coral_defconfig index e3756cf..4823913 100644 --- a/configs/chromebook_coral_defconfig +++ b/configs/chromebook_coral_defconfig @@ -43,7 +43,7 @@ CONFIG_BLOBLIST_ADDR=0x100000 CONFIG_HANDOFF=y CONFIG_TPL_SYS_MALLOC_SIMPLE=y CONFIG_SPL_SEPARATE_BSS=y -CONFIG_SPL_CPU_SUPPORT=y +CONFIG_SPL_CPU=y CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_PCI=y # CONFIG_SPL_SPI_FLASH_TINY is not set diff --git a/configs/chromebook_link64_defconfig b/configs/chromebook_link64_defconfig index 8f56ee3..872e33d 100644 --- a/configs/chromebook_link64_defconfig +++ b/configs/chromebook_link64_defconfig @@ -31,7 +31,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_MISC_INIT_R=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_CPU_SUPPORT=y +CONFIG_SPL_CPU=y CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_I2C_SUPPORT=y CONFIG_SPL_DM_SPI_FLASH=y diff --git a/configs/qemu-x86_64_defconfig b/configs/qemu-x86_64_defconfig index 99a489c..4815d8a 100644 --- a/configs/qemu-x86_64_defconfig +++ b/configs/qemu-x86_64_defconfig @@ -31,7 +31,7 @@ CONFIG_DISPLAY_BOARDINFO_LATE=y CONFIG_LAST_STAGE_INIT=y CONFIG_PCI_INIT_R=y CONFIG_SPL_SYS_MALLOC_SIMPLE=y -CONFIG_SPL_CPU_SUPPORT=y +CONFIG_SPL_CPU=y CONFIG_SPL_ENV_SUPPORT=y CONFIG_SPL_DM_SPI_FLASH=y CONFIG_SPL_NET_SUPPORT=y diff --git a/drivers/Makefile b/drivers/Makefile index c562a71..3510dab 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -38,7 +38,7 @@ ifdef CONFIG_SPL_BUILD obj-$(CONFIG_SPL_BOOTCOUNT_LIMIT) += bootcount/ obj-$(CONFIG_SPL_CACHE_SUPPORT) += cache/ -obj-$(CONFIG_SPL_CPU_SUPPORT) += cpu/ +obj-$(CONFIG_SPL_CPU) += cpu/ obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/ obj-$(CONFIG_SPL_MPC8XXX_INIT_DDR_SUPPORT) += ddr/fsl/ obj-$(CONFIG_ARMADA_38X) += ddr/marvell/a38x/ diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c index 6f00a5d..73b4a5c 100644 --- a/drivers/timer/timer-uclass.c +++ b/drivers/timer/timer-uclass.c @@ -83,11 +83,7 @@ static int timer_post_probe(struct udevice *dev) return 0; } -/* - * TODO: should be CONFIG_IS_ENABLED(CPU), but the SPL config has _SUPPORT on - * the end... - */ -#if defined(CONFIG_CPU) || defined(CONFIG_SPL_CPU_SUPPORT) +#if CONFIG_IS_ENABLED(CPU) int timer_timebase_fallback(struct udevice *dev) { struct udevice *cpu; -- cgit v1.1 From c197f6e27923b4cff9d782cd9be7a058d5d65aa2 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:19 +1300 Subject: malloc: Export malloc_simple_info() Export this function always so it can be used behind IS_ENABLED() instead of requiring an #ifdef. Signed-off-by: Simon Glass --- include/malloc.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/malloc.h b/include/malloc.h index e15e528..024b18b 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -880,6 +880,8 @@ extern Void_t* sbrk(); #else +void malloc_simple_info(void); + #if CONFIG_IS_ENABLED(SYS_MALLOC_SIMPLE) #define malloc malloc_simple #define realloc realloc_simple @@ -887,7 +889,6 @@ extern Void_t* sbrk(); static inline void free(void *ptr) {} void *calloc(size_t nmemb, size_t size); void *realloc_simple(void *ptr, size_t size); -void malloc_simple_info(void); #else # ifdef USE_DL_PREFIX -- cgit v1.1 From 2d0423aff9fd9adc0933f94df6726e29ee2c89be Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:20 +1300 Subject: doc: Convert Chromium OS docs to rst Move this documentation over to reST. Move the example files into a files/ directory so they are still separate. Do a few minor updates while we are here: - Tidy up sandbox build instructions - Update my github account name - Add some talks and links Signed-off-by: Simon Glass --- doc/README.chromium | 218 ----------------- doc/README.chromium-chainload | 239 ------------------- doc/chromium/chainload.rst | 257 +++++++++++++++++++++ doc/chromium/chromebook_jerry.its | 42 ---- doc/chromium/devkeys/kernel.keyblock | Bin 1208 -> 0 bytes doc/chromium/devkeys/kernel_data_key.vbprivk | Bin 1199 -> 0 bytes doc/chromium/files/chromebook_jerry.its | 42 ++++ doc/chromium/files/devkeys/kernel.keyblock | Bin 0 -> 1208 bytes doc/chromium/files/devkeys/kernel_data_key.vbprivk | Bin 0 -> 1199 bytes doc/chromium/files/nyan-big.its | 42 ++++ doc/chromium/index.rst | 14 ++ doc/chromium/nyan-big.its | 42 ---- doc/chromium/overview.rst | 74 ++++++ doc/chromium/run_vboot.rst | 204 ++++++++++++++++ doc/index.rst | 8 + 15 files changed, 641 insertions(+), 541 deletions(-) delete mode 100644 doc/README.chromium delete mode 100644 doc/README.chromium-chainload create mode 100644 doc/chromium/chainload.rst delete mode 100644 doc/chromium/chromebook_jerry.its delete mode 100644 doc/chromium/devkeys/kernel.keyblock delete mode 100644 doc/chromium/devkeys/kernel_data_key.vbprivk create mode 100644 doc/chromium/files/chromebook_jerry.its create mode 100644 doc/chromium/files/devkeys/kernel.keyblock create mode 100644 doc/chromium/files/devkeys/kernel_data_key.vbprivk create mode 100644 doc/chromium/files/nyan-big.its create mode 100644 doc/chromium/index.rst delete mode 100644 doc/chromium/nyan-big.its create mode 100644 doc/chromium/overview.rst create mode 100644 doc/chromium/run_vboot.rst diff --git a/doc/README.chromium b/doc/README.chromium deleted file mode 100644 index 75f2f24..0000000 --- a/doc/README.chromium +++ /dev/null @@ -1,218 +0,0 @@ -Chromium OS Support in U-Boot -============================= - -Introduction ------------- - -This describes how to use U-Boot with Chromium OS. Several options are -available: - - - Running U-Boot from the 'altfw' feature, which is available on selected - Chromebooks from 2019 onwards (initially Grunt). Press '1' from the - developer-mode screen to get into U-Boot. See here for details: - https://sites.google.com/a/chromium.org/dev/chromium-os/poking-around-your-chrome-os-device?pli=1 - - - Running U-Boot from the disk partition. This involves signing U-Boot and - placing it on the disk, for booting as a 'kernel'. See - README.chromium-chainload for information on this. This is the only - option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat - more involved. - - - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be - used instead of either or both of depthcharge (a bootloader which forked - from U-Boot in 2013) and coreboot. See below for more information on - this. - - - Running U-Boot from coreboot. This allows U-Boot to run on more devices - since many of them only support coreboot as the bootloader and have - no bare-metal support in U-Boot. For this, use the 'coreboot' target. - - - Running U-Boot and booting into a Chrome OS image, but without verified - boot. This can be useful for testing. - - -U-Boot with Chromium OS verified boot -------------------------------------- - -To obtain: - - git clone https://github.com/sglass68/u-boot.git - cd u-boot - git checkout cros-master - - cd .. - git clone https://chromium.googlesource.com/chromiumos/platform/vboot_reference - cd vboot_reference - git checkout 45964294 - # futility: updater: Correct output version for Snow - -To build for sandbox: - - UB=/tmp/b/chromeos_sandbox # U-Boot build directory - cd u-boot - make O=$UB chromeos_sandbox_defconfig - make O=$UB -j20 -s VBOOT_SOURCE=/path/to/vboot_reference \ - MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1 - -Replace sandbox with another supported target. - -This produces $UB/image.bin which contains the firmware binaries in a SPI -flash image. - -To run on sandbox: - - $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out \ - -L6 -c "host bind 0 $CROS/src/build/images/cheza/latest/chromiumos_image.bin; vboot go auto" \ - -l -w -s state.dtb -r - -To run on other boards: - Install image.bin in the SPI flash of your device - Boot your system - - -Sandbox -------- - -Most Chromium OS development with U-Boot is undertaken using sandbox. There is -a sandbox target available (chromeos_sandbox) which allows running U-Boot on -a Linux machine completion with emulations of the display, TPM, disk, etc. - -Running sandbox starts TPL, which contains the first phase of vboot, providing -a device tree and binding a Chromium OS disk image for use to find kernels -(any Chromium OS image will do). It also saves driver state between U-Boot -phases into state.dtb and will automatically ensure that memory is shared -between all phases. TPL will jump to SPL and then on to U-Boot proper. - -It is possible to run with debugging on, e.g. - - gdb --args $UB/tpl/u-boot-tpl -d .... - -Breakpoints can be set in any U-Boot phase. Overall this is a good debugging -environment for new verified-boot features. - - -Samus ------ - -Basic support is available for samus, using the chromeos_samus target. If you -have an em100, use: - - sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r - -to write the image and then boot samus (Power-Refresh). - - -Boot flow ---------- - -Verified boot starts in TPL, which selects the A or B SPL, which in turn selects -the A or B U-Boot. Then this jumps to the selected kernel. If anything goes -wrong, the device reboots and the recovery SPL and U-Boot are used instead. - -More details are available here: - - https://www.chromium.org/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery - - -New uclasses ------------- - -Several uclasses are provided in cros/: - - UCLASS_CROS_AUX_FW Chrome OS auxiliary firmware - UCLASS_CROS_FWSTORE Chrome OS firmware storage - UCLASS_CROS_NVDATA Chrome OS non-volatile data device - UCLASS_CROS_VBOOT_EC Chrome OS vboot EC operations - UCLASS_CROS_VBOOT_FLAG Chrome OS verified boot flag - -The existing UCLASS_CROS_EC is also used. - - -Commands --------- - -A new 'vboot' command is provided to run particular vboot stages. The most -useful command is 'vboot go auto', which continues where the last stage left -off. - -Note that TPL and SPL do not supports commands as yet, so the vboot code is -called directly from the SPL boot devices (BOOT_DEVICE_CROS_VBOOT). See -cros_load_image_tpl() and cros_load_image_spl() which both call -vboot_run_auto(). - - -Config options --------------- - -The main option is CONFIG_CHROMEOS, which enables a wide array of other options -so that the required features are present. - - -Device-tree config ------------------- - -Various options are available which control the operation of verified boot. -See cros/dts/bindings/config.txt for details. Most config is handled at run- -time, although build-time config (with Kconfig) could also be added fairly -easily. - - -Porting to other hardware -------------------------- - -A basic port to samus (Chromebook Pixel 2015) is in a basic working state, -using the chromeos_samus target. Patches will likely be forthcoming in early -2019. Ports to an ARM board and coreboot (for x86 Chromebooks) are in the -dreaming state. - - -Tests ------ - -Chromium OS firmware has a very limited set of tests. The tests that originally -existed in U-Boot were not brought over to coreboot or depthcharge. - -The U-Boot tests ('make check') do operate, but at present there are no -Chromium OS tests available. These will hopefully come together over time. Of -course the above sandbox feature provides a sort of functional test and can -detect problems that affect the flow or particular vboot features. - - -U-Boot without Chromium OS verified boot ----------------------------------------- - -The following script can be used to boot a Chrome OS image on coral: - - # Read the image header and obtain the address of the kernel - # The offset 4f0 is defined by verified boot and may change for other - # Chromebooks - read mmc 2:2 100000 0 80; setexpr loader *001004f0; - - # Get the kernel size and calculate the number of blocks (0x200 bytes each) - setexpr size *00100518; setexpr blocks $size / 200; - - # Read the full kernel and calculate the address of the setup block - read mmc 2:2 100000 80 $blocks; setexpr setup $loader - 1000; - - # Locate the command line - setexpr cmdline $loader - 2000; - - # Start the zboot process with the loaded kernel, setup block and cmdline - zboot start 100000 0 0 0 $setup $cmdline; - - # Load the kernel, fix up the 'setup' block, dump information - zboot load; zboot setup; zboot dump - - # Boot into Chrome OS - zboot go - - -TO DO ------ - -Get the full ACPI tables working with Coral - - -Simon Glass -sjg@chromium.org -7 October 2018 diff --git a/doc/README.chromium-chainload b/doc/README.chromium-chainload deleted file mode 100644 index 45eaece..0000000 --- a/doc/README.chromium-chainload +++ /dev/null @@ -1,239 +0,0 @@ -Running U-Boot from coreboot on Chromebooks -=========================================== - -U-Boot can be used as a secondary boot loader in a few situations such as from -UEFI and coreboot (see README.x86). Recent Chromebooks use coreboot even on -ARM platforms to start up the machine. - -This document aims to provide a guide to booting U-Boot on a Chromebook. It -is only a starting point, and there are many guides on the interwebs. But -placing this information in the U-Boot tree should make it easier to find for -those who use U-Boot habitually. - -Most of these platforms are supported by U-Boot natively, but it is risky to -replace the ROM unless you have a servo board and cable to restore it with. - - -For all of these the standard U-Boot build instructions apply. For example on -ARM: - - sudo apt install gcc-arm-linux-gnueabi - mkdir b - make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all - -You can obtain the vbutil_kernel utility here: - - https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U - - -Snow (Samsung ARM Chromebook) ------------------------------ - -See here: - -https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook - - -Nyan-big --------- - -Compiled based on information here: -https://lists.denx.de/pipermail/u-boot/2015-March/209530.html -https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big -https://lists.denx.de/pipermail/u-boot/2017-May/289491.html -https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card - -1. Build U-Boot - - mkdir b - make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all - - -2. Select a .its file - -Select something from doc/chromium which matches your board, or create your -own. - -Note that the device tree node is required, even though it is not actually -used by U-Boot. This is because the Chromebook expects to pass it to the -kernel, and crashes if it is not present. - - -3. Build and sign an image - - ./b/nyan-big/tools/mkimage -f doc/chromium/nyan-big.its u-boot-chromium.fit - echo test >dummy.txt - vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \ - --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \ - --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \ - --bootloader dummy.txt --pack u-boot.kpart - - -4. Prepare an SD card - - DISK=/dev/sdc # Replace with your actual SD card device - sudo cgpt create $DISK - sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK - sudo cgpt add -b 32802 -s 2000000 -t rootfs $DISK - sudo gdisk $DISK # Enter command 'w' to write a protective MBR to the disk - - -5. Write U-Boot to the SD card - - sudo dd if=u-boot.kpart of=/dev/sdc1; sync - - -6. Start it up - -Reboot the device in dev mode. Make sure that you have USB booting enabled. To -do this, login as root (via Ctrl-Alt-forward_arrow) and type -'enable_dev_usb_boot'. You only need to do this once. - -Reboot the device with the SD card inserted. Press Clrl-U at the developer -mode screen. It should show something like the following on the display: - - U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600) - - Model: Acer Chromebook 13 CB5-311 - Board: Google/NVIDIA Nyan-big, ID: 1 - - Net: No ethernet found. - Hit any key to stop autoboot: 0 - Tegra124 (Nyan-big) # - - -7. Known problems - -On the serial console the word MMC is chopped at the start of the line: - -C: sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0 - -This is likely due to some problem with change-over of the serial driver -during relocation (or perhaps updating the clock setup in board_init()). - - -9. Notes - -To check that you copied the u-boot.its file correctly, use these commands. -You should see that the data at 0x100 in u-boot-chromium.fit is the first few -bytes of U-Boot: - - hd u-boot-chromium.fit |head -20 - ... - 00000100 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................| - - hd b/nyan-big/u-boot.bin |head - 00000000 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................| - - -The 'data' property of the FIT is set up to start at offset 0x100 bytes into -the file. The change to CONFIG_SYS_TEXT_BASE is also an offset of 0x100 bytes -from the load address. If this changes, you either need to modify U-Boot to be -fully relocatable, or expect it to hang. - - -chromebook_jerry ----------------- - -The instruction are similar to those for Nyan with changes as noted below: - -1. Patch U-Boot - -Open include/configs/rk3288_common.h - -Change: - -#define CONFIG_SYS_TEXT_BASE 0x00100000 - -to: - -#define CONFIG_SYS_TEXT_BASE 0x02000100 - - - -2. Build U-Boot - - mkdir b - make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \ - chromebook_jerry_defconfig all - - -3. See above - -4. Build and sign an image - - ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \ - u-boot-chromium.fit - echo test >dummy.txt - vbutil_kernel --arch arm --keyblock doc/chromium/devkeys/kernel.keyblock \ - --signprivate doc/chromium/devkeys/kernel_data_key.vbprivk \ - --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \ - --bootloader dummy.txt --pack u-boot.kpart - - -5. See above - -6. See above - -7. Start it up - -Reboot the device in dev mode. Make sure that you have USB booting enabled. To -do this, login as root (via Ctrl-Alt-forward_arrow) and type -'enable_dev_usb_boot'. You only need to do this once. - -Reboot the device with the SD card inserted. Press Clrl-U at the developer -mode screen. It should show something like the following on the display: - - U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600) - - Model: Google Jerry - Net: Net Initialization Skipped - No ethernet found. - Hit any key to stop autoboot: 0 - - -8. Known problems - -None as yet. - - -9. Notes - -None as yet. - - -Other notes -=========== - -flashrom --------- - - Used to make a backup of your firmware, or to replace it. - - See: https://www.chromium.org/chromium-os/packages/cros-flashrom - - -coreboot --------- - -Coreboot itself is not designed to actually boot an OS. Instead, a program -called Depthcharge is used. This originally came out of U-Boot and was then -heavily hacked and modified such that is is almost unrecognisable. It does -include a very small part of the U-Boot command-line interface but is not -usable as a general-purpose boot loader. - -In addition, it has a very unusual design in that it does not do device init -itself, but instead relies on coreboot. This is similar to (in U-Boot) having -a SPI driver with an empty probe() method, relying on whatever was set up -beforehand. It can be quite hard to figure out between these two code bases -what settings are actually used. When chain-loading into U-Boot we must be -careful to reinit anything that U-Boot expects. If not, some peripherals (or -the whole machine) may not work. This makes the process of chainloading more -complicated than it could be on some platforms. - -Finally, it supports only a subset of the U-Boot's FIT format. In particular -it uses a fixed address to load the FIT and does not support load/exec -addresses. This means that U-Boot must be able to boot from whatever -address Depthcharge happens to use (it is the CONFIG_KERNEL_START setting -in Depthcharge). In practice this means that the data in the kernel@1 FIT node -(see above) must start at the same address as U-Boot's CONFIG_SYS_TEXT_BASE. diff --git a/doc/chromium/chainload.rst b/doc/chromium/chainload.rst new file mode 100644 index 0000000..7b6bb10 --- /dev/null +++ b/doc/chromium/chainload.rst @@ -0,0 +1,257 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2020 Google LLC + +Running U-Boot from coreboot on Chromebooks +=========================================== + +U-Boot can be used as a secondary boot loader in a few situations such as from +UEFI and coreboot (see README.x86). Recent Chromebooks use coreboot even on +ARM platforms to start up the machine. + +This document aims to provide a guide to booting U-Boot on a Chromebook. It +is only a starting point, and there are many guides on the interwebs. But +placing this information in the U-Boot tree should make it easier to find for +those who use U-Boot habitually. + +Most of these platforms are supported by U-Boot natively, but it is risky to +replace the ROM unless you have a servo board and cable to restore it with. + + +For all of these the standard U-Boot build instructions apply. For example on +ARM:: + + sudo apt install gcc-arm-linux-gnueabi + mkdir b + make O=b/nyan_big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all + +You can obtain the vbutil_kernel utility here: + + https://drive.google.com/open?id=0B7WYZbZ9zd-3dHlVVXo4VXE2T0U + + +Snow (Samsung ARM Chromebook) +----------------------------- + +See here: + +https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-the-samsung-arm-chromebook + + +Nyan-big +-------- + +Compiled based on information here:: + + https://lists.denx.de/pipermail/u-boot/2015-March/209530.html + https://git.collabora.com/cgit/user/tomeu/u-boot.git/commit/?h=nyan-big + https://lists.denx.de/pipermail/u-boot/2017-May/289491.html + https://github.com/chromeos-nvidia-androidtv/gnu-linux-on-acer-chromebook-13#copy-data-to-the-sd-card + +1. Build U-Boot + +Steps:: + + mkdir b + make -j8 O=b/nyan-big CROSS_COMPILE=arm-linux-gnueabi- nyan-big_defconfig all + + +2. Select a .its file + +Select something from doc/chromium which matches your board, or create your +own. + +Note that the device tree node is required, even though it is not actually +used by U-Boot. This is because the Chromebook expects to pass it to the +kernel, and crashes if it is not present. + + +3. Build and sign an image + +Steps:: + + ./b/nyan-big/tools/mkimage -f doc/chromium/files/nyan-big.its u-boot-chromium.fit + echo test >dummy.txt + vbutil_kernel --arch arm \ + --keyblock doc/chromium/files/devkeys/kernel.keyblock \ + --signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk \ + --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \ + --bootloader dummy.txt --pack u-boot.kpart + + +4. Prepare an SD card + +Steps:: + + DISK=/dev/sdc # Replace with your actual SD card device + sudo cgpt create $DISK + sudo cgpt add -b 34 -s 32768 -P 1 -S 1 -t kernel $DISK + sudo cgpt add -b 32802 -s 2000000 -t rootfs $DISK + sudo gdisk $DISK # Enter command 'w' to write a protective MBR to the disk + + +5. Write U-Boot to the SD card + +Steps:: + + sudo dd if=u-boot.kpart of=/dev/sdc1; sync + + +6. Start it up + +Reboot the device in dev mode. Make sure that you have USB booting enabled. To +do this, login as root (via Ctrl-Alt-forward_arrow) and type +'enable_dev_usb_boot'. You only need to do this once. + +Reboot the device with the SD card inserted. Press Clrl-U at the developer +mode screen. It should show something like the following on the display:: + + U-Boot 2017.07-00637-g242eb42-dirty (May 22 2017 - 06:14:21 -0600) + + Model: Acer Chromebook 13 CB5-311 + Board: Google/NVIDIA Nyan-big, ID: 1 + + Net: No ethernet found. + Hit any key to stop autoboot: 0 + Tegra124 (Nyan-big) # + + +7. Known problems + +On the serial console the word MMC is chopped at the start of the line:: + + C: sdhci@700b0000: 2, sdhci@700b0400: 1, sdhci@700b0600: 0 + +This is likely due to some problem with change-over of the serial driver +during relocation (or perhaps updating the clock setup in board_init()). + + +9. Notes + +To check that you copied the u-boot.its file correctly, use these commands. +You should see that the data at 0x100 in u-boot-chromium.fit is the first few +bytes of U-Boot:: + + hd u-boot-chromium.fit |head -20 + ... + 00000100 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................| + + hd b/nyan-big/u-boot.bin |head + 00000000 b8 00 00 ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 |................| + + +The 'data' property of the FIT is set up to start at offset 0x100 bytes into +the file. The change to CONFIG_SYS_TEXT_BASE is also an offset of 0x100 bytes +from the load address. If this changes, you either need to modify U-Boot to be +fully relocatable, or expect it to hang. + + +chromebook_jerry +---------------- + +The instruction are similar to those for Nyan with changes as noted below: + +1. Patch U-Boot + +Open include/configs/rk3288_common.h + +Change:: + + #define CONFIG_SYS_TEXT_BASE 0x00100000 + +to:: + + #define CONFIG_SYS_TEXT_BASE 0x02000100 + + + +2. Build U-Boot + +Steps:: + + mkdir b + make -j8 O=b/chromebook_jerry CROSS_COMPILE=arm-linux-gnueabi- \ + chromebook_jerry_defconfig all + + +3. See above + +4. Build and sign an image + +Steps:: + + ./b/chromebook_jerry/tools/mkimage -f doc/chromium/chromebook_jerry.its \ + u-boot-chromium.fit + echo test >dummy.txt + vbutil_kernel --arch arm \ + --keyblock doc/chromium/files/devkeys/kernel.keyblock \ + --signprivate doc/chromium/files/devkeys/kernel_data_key.vbprivk \ + --version 1 --config dummy.txt --vmlinuz u-boot-chromium.fit \ + --bootloader dummy.txt --pack u-boot.kpart + + +5. See above + +6. See above + +7. Start it up + +Reboot the device in dev mode. Make sure that you have USB booting enabled. To +do this, login as root (via Ctrl-Alt-forward_arrow) and type +'enable_dev_usb_boot'. You only need to do this once. + +Reboot the device with the SD card inserted. Press Clrl-U at the developer +mode screen. It should show something like the following on the display:: + + U-Boot 2017.05-00649-g72acdbf-dirty (May 29 2017 - 14:57:05 -0600) + + Model: Google Jerry + Net: Net Initialization Skipped + No ethernet found. + Hit any key to stop autoboot: 0 + + +8. Known problems + +None as yet. + + +9. Notes + +None as yet. + + +Other notes +----------- + +flashrom +~~~~~~~~ + +Used to make a backup of your firmware, or to replace it. + +See: https://www.chromium.org/chromium-os/packages/cros-flashrom + + +coreboot +~~~~~~~~ + +Coreboot itself is not designed to actually boot an OS. Instead, a program +called Depthcharge is used. This originally came out of U-Boot and was then +heavily hacked and modified such that is is almost unrecognisable. It does +include a very small part of the U-Boot command-line interface but is not +usable as a general-purpose boot loader. + +In addition, it has a very unusual design in that it does not do device init +itself, but instead relies on coreboot. This is similar to (in U-Boot) having +a SPI driver with an empty probe() method, relying on whatever was set up +beforehand. It can be quite hard to figure out between these two code bases +what settings are actually used. When chain-loading into U-Boot we must be +careful to reinit anything that U-Boot expects. If not, some peripherals (or +the whole machine) may not work. This makes the process of chainloading more +complicated than it could be on some platforms. + +Finally, it supports only a subset of the U-Boot's FIT format. In particular +it uses a fixed address to load the FIT and does not support load/exec +addresses. This means that U-Boot must be able to boot from whatever +address Depthcharge happens to use (it is the CONFIG_KERNEL_START setting +in Depthcharge). In practice this means that the data in the kernel@1 FIT node +(see above) must start at the same address as U-Boot's CONFIG_SYS_TEXT_BASE. diff --git a/doc/chromium/chromebook_jerry.its b/doc/chromium/chromebook_jerry.its deleted file mode 100644 index 7505a20..0000000 --- a/doc/chromium/chromebook_jerry.its +++ /dev/null @@ -1,42 +0,0 @@ -/dts-v1/; - -/ { - description = "U-Boot mainline"; - #address-cells = <1>; - - images { - kernel { - description = "U-Boot mainline"; - type = "kernel_noload"; - arch = "arm"; - os = "linux"; - data = /incbin/("../../b/chromebook_jerry/u-boot.bin"); - compression = "none"; - load = <0>; - entry = <0>; - hash-2 { - algo = "sha1"; - }; - }; - - fdt-1{ - description = "rk3288-veryron-jerry.dtb"; - data = /incbin/("../../b/chromebook_jerry/u-boot.dtb"); - type = "flat_dt"; - arch = "arm"; - compression = "none"; - hash-1{ - algo = "sha1"; - }; - }; - }; - - configurations { - default = "config-1"; - config-1 { - description = "Boot U-Boot"; - kernel = "kernel"; - fdt = "fdt-1"; - }; - }; -}; diff --git a/doc/chromium/devkeys/kernel.keyblock b/doc/chromium/devkeys/kernel.keyblock deleted file mode 100644 index 9740be4..0000000 Binary files a/doc/chromium/devkeys/kernel.keyblock and /dev/null differ diff --git a/doc/chromium/devkeys/kernel_data_key.vbprivk b/doc/chromium/devkeys/kernel_data_key.vbprivk deleted file mode 100644 index 8d392fb..0000000 Binary files a/doc/chromium/devkeys/kernel_data_key.vbprivk and /dev/null differ diff --git a/doc/chromium/files/chromebook_jerry.its b/doc/chromium/files/chromebook_jerry.its new file mode 100644 index 0000000..7505a20 --- /dev/null +++ b/doc/chromium/files/chromebook_jerry.its @@ -0,0 +1,42 @@ +/dts-v1/; + +/ { + description = "U-Boot mainline"; + #address-cells = <1>; + + images { + kernel { + description = "U-Boot mainline"; + type = "kernel_noload"; + arch = "arm"; + os = "linux"; + data = /incbin/("../../b/chromebook_jerry/u-boot.bin"); + compression = "none"; + load = <0>; + entry = <0>; + hash-2 { + algo = "sha1"; + }; + }; + + fdt-1{ + description = "rk3288-veryron-jerry.dtb"; + data = /incbin/("../../b/chromebook_jerry/u-boot.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash-1{ + algo = "sha1"; + }; + }; + }; + + configurations { + default = "config-1"; + config-1 { + description = "Boot U-Boot"; + kernel = "kernel"; + fdt = "fdt-1"; + }; + }; +}; diff --git a/doc/chromium/files/devkeys/kernel.keyblock b/doc/chromium/files/devkeys/kernel.keyblock new file mode 100644 index 0000000..9740be4 Binary files /dev/null and b/doc/chromium/files/devkeys/kernel.keyblock differ diff --git a/doc/chromium/files/devkeys/kernel_data_key.vbprivk b/doc/chromium/files/devkeys/kernel_data_key.vbprivk new file mode 100644 index 0000000..8d392fb Binary files /dev/null and b/doc/chromium/files/devkeys/kernel_data_key.vbprivk differ diff --git a/doc/chromium/files/nyan-big.its b/doc/chromium/files/nyan-big.its new file mode 100644 index 0000000..bd41291 --- /dev/null +++ b/doc/chromium/files/nyan-big.its @@ -0,0 +1,42 @@ +/dts-v1/; + +/ { + description = "U-Boot mainline"; + #address-cells = <1>; + + images { + kernel { + description = "U-Boot mainline "; + type = "kernel_noload"; + arch = "arm"; + os = "linux"; + data = /incbin/("../.././b/nyan-big/u-boot.bin"); + compression = "none"; + load = <0>; + entry = <0>; + hash-2 { + algo = "sha1"; + }; + }; + + fdt-1{ + description = "tegra124-nyan-big.dtb"; + data = /incbin/("../.././b/nyan-big/u-boot.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash-1{ + algo = "sha1"; + }; + }; + }; + + configurations { + default = "config-1"; + config-1 { + description = "Boot U-Boot"; + kernel = "kernel"; + fdt = "fdt-1"; + }; + }; +}; diff --git a/doc/chromium/index.rst b/doc/chromium/index.rst new file mode 100644 index 0000000..0722c25 --- /dev/null +++ b/doc/chromium/index.rst @@ -0,0 +1,14 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2020 Google LLC + +Chromium OS-specific doc +======================== + +This provides some information about Chromium OS and U-Boot. + +.. toctree:: + :maxdepth: 2 + + overview + run_vboot + chainload diff --git a/doc/chromium/nyan-big.its b/doc/chromium/nyan-big.its deleted file mode 100644 index bd41291..0000000 --- a/doc/chromium/nyan-big.its +++ /dev/null @@ -1,42 +0,0 @@ -/dts-v1/; - -/ { - description = "U-Boot mainline"; - #address-cells = <1>; - - images { - kernel { - description = "U-Boot mainline "; - type = "kernel_noload"; - arch = "arm"; - os = "linux"; - data = /incbin/("../.././b/nyan-big/u-boot.bin"); - compression = "none"; - load = <0>; - entry = <0>; - hash-2 { - algo = "sha1"; - }; - }; - - fdt-1{ - description = "tegra124-nyan-big.dtb"; - data = /incbin/("../.././b/nyan-big/u-boot.dtb"); - type = "flat_dt"; - arch = "arm"; - compression = "none"; - hash-1{ - algo = "sha1"; - }; - }; - }; - - configurations { - default = "config-1"; - config-1 { - description = "Boot U-Boot"; - kernel = "kernel"; - fdt = "fdt-1"; - }; - }; -}; diff --git a/doc/chromium/overview.rst b/doc/chromium/overview.rst new file mode 100644 index 0000000..5498ed9 --- /dev/null +++ b/doc/chromium/overview.rst @@ -0,0 +1,74 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2020 Google LLC + +Chromium OS Support in U-Boot +============================= + +Introduction +------------ + +This describes how to use U-Boot with Chromium OS. Several options are +available: + + - Running U-Boot from the 'altfw' feature, which is available on selected + Chromebooks from 2019 onwards (initially Grunt). Press '1' from the + developer-mode screen to get into U-Boot. See here for details: + https://chromium.googlesource.com/chromiumos/docs/+/HEAD/developer_mode.md + + - Running U-Boot from the disk partition. This involves signing U-Boot and + placing it on the disk, for booting as a 'kernel'. See + :doc:`chainload` for information on this. This is the only + option on non-U-Boot Chromebooks from 2013 to 2018 and is somewhat + more involved. + + - Running U-Boot with Chromium OS verified boot. This allows U-Boot to be + used instead of either or both of depthcharge (a bootloader which forked + from U-Boot in 2013) and coreboot. See :doc:`run_vboot` for more + information on this. + + - Running U-Boot from coreboot. This allows U-Boot to run on more devices + since many of them only support coreboot as the bootloader and have + no bare-metal support in U-Boot. For this, use the 'coreboot' target. + + - Running U-Boot and booting into a Chrome OS image, but without verified + boot. This can be useful for testing. + + +Talks and documents +------------------- + +Here is some material relevant to Chromium OS verified boot with U-Boot: + + - "U-Boot with Chrome OS and firmware packaging" + + - Author: Simon Glass + - Presented at Open Source Firmware Conference 2018, Erlangen + - Describes the work in progress as at the end of 2018 + - Slides at `OSFC `_ + - Video on `Youtube `_ + + - "Verified Boot in Chrome OS and how to make it work for you" + + - Author: Simon Glass + - Presented at ELCE 2013, Edinburgh + - Describes the original 2013 implementation as shipped on snow (first + `ARM Chromebook was a Samsung Chromebook `_ + with Samsung Exynos5250 `review `_), + spring (`HP Chromebook 11 `_) + and pit/pi (`Samsung Chromebook 2 `_ + with Exynos 5 Octa 5420 in 2014). + - Slides at `Google research `_ + - Video at `Youtube `_ + + - "Chrome University 2018: Chrome OS Firmware and Verified Boot 201" + + - Author: Duncan Laurie + - Describes Chrome OS firmware as of 2018 and includes a wide range of + topics. This has no U-Boot information, but does cover coreboot and also + talks about the Chrome OS EC and Security chip. This is probably the + best introduction talk. + - Video at `YouTube `_ + + - `Chromium OS U-Boot `_ + + - `Firmware porting Guide `_ diff --git a/doc/chromium/run_vboot.rst b/doc/chromium/run_vboot.rst new file mode 100644 index 0000000..41b4f63 --- /dev/null +++ b/doc/chromium/run_vboot.rst @@ -0,0 +1,204 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2020 Google LLC +.. sectionauthor:: Simon Glass + + +Running U-Boot with Chromium OS verified boot +============================================= + +To obtain:: + + git clone https://github.com/sjg20/u-boot.git + cd u-boot + git checkout cros-master + + cd .. + git clone https://chromium.googlesource.com/chromiumos/platform/vboot_reference + cd vboot_reference + git checkout 45964294 + # futility: updater: Correct output version for Snow + +To build for sandbox:: + + UB=/tmp/b/chromeos_sandbox # U-Boot build directory + cd u-boot + make O=$UB chromeos_sandbox_defconfig + make O=$UB -j20 -s VBOOT_SOURCE=/path/to/vboot_reference \ + MAKEFLAGS_VBOOT=DEBUG=1 QUIET=1 + +Replace sandbox with another supported target. + +This produces $UB/image.bin which contains the firmware binaries in a SPI +flash image. + +To run on sandbox:: + + CROS=~/cosarm + IMG=$CROS/src/build/images/coral/latest/chromiumos_image.bin + $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out \ + -L6 -c "host bind 0 $IMG; vboot go auto" \ + -l -w -s state.dtb -r -n -m $UB/ram + + $UB/tpl/u-boot-tpl -d $UB/u-boot.dtb.out -L6 -l \ + -c "host bind 0 $IMG; vboot go auto" -w -s $UB/state.dtb -r -n -m $UB/mem + + +To run on other boards: + + - Install image.bin in the SPI flash of your device + - Boot your system + + +Sandbox +------- + +Most Chromium OS development with U-Boot is undertaken using sandbox. There is +a sandbox target available (chromeos_sandbox) which allows running U-Boot on +a Linux machine completion with emulations of the display, TPM, disk, etc. + +Running sandbox starts TPL, which contains the first phase of vboot, providing +a device tree and binding a Chromium OS disk image for use to find kernels +(any Chromium OS image will do). It also saves driver state between U-Boot +phases into state.dtb and will automatically ensure that memory is shared +between all phases. TPL will jump to SPL and then on to U-Boot proper. + +It is possible to run with debugging on, e.g.:: + + gdb --args $UB/tpl/u-boot-tpl -d .... + +Breakpoints can be set in any U-Boot phase. Overall this is a good debugging +environment for new verified-boot features. + + +Samus +----- + +Basic support is available for samus, using the chromeos_samus target. If you +have an em100, use:: + + sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r + +to write the image and then boot samus (Power-Refresh). + + +Boot flow +--------- + +Verified boot starts in TPL, which selects the A or B SPL, which in turn selects +the A or B U-Boot. Then this jumps to the selected kernel. If anything goes +wrong, the device reboots and the recovery SPL and U-Boot are used instead. + +More details are available here: + + https://www.chromium.org/chromium-os/chromiumos-design-docs/firmware-boot-and-recovery + + +New uclasses +------------ + +Several uclasses are provided in cros/: + +UCLASS_CROS_AUX_FW + Chrome OS auxiliary firmware + +UCLASS_CROS_FWSTORE + Chrome OS firmware storage + +UCLASS_CROS_NVDATA + Chrome OS non-volatile data device + +UCLASS_CROS_VBOOT_EC + Chrome OS vboot EC operations + +UCLASS_CROS_VBOOT_FLAG + Chrome OS verified boot flag + +The existing UCLASS_CROS_EC is also used. + + +Commands +-------- + +A new 'vboot' command is provided to run particular vboot stages. The most +useful command is 'vboot go auto', which continues where the last stage left +off. + +Note that TPL and SPL do not supports commands as yet, so the vboot code is +called directly from the SPL boot devices (BOOT_DEVICE_CROS_VBOOT). See +cros_load_image_tpl() and cros_load_image_spl() which both call +vboot_run_auto(). + + +Config options +-------------- + +The main option is CONFIG_CHROMEOS, which enables a wide array of other options +so that the required features are present. + + +Device-tree config +------------------ + +Various options are available which control the operation of verified boot. +See cros/dts/bindings/config.txt for details. Most config is handled at run- +time, although build-time config (with Kconfig) could also be added fairly +easily. + + +Porting to other hardware +------------------------- + +A basic port to samus (Chromebook Pixel 2015) is in a basic working state, +using the chromeos_samus target. Patches will likely be forthcoming in early +2019. Ports to an ARM board and coreboot (for x86 Chromebooks) are in the +dreaming state. + + +Tests +----- + +Chromium OS firmware has a very limited set of tests. The tests that originally +existed in U-Boot were not brought over to coreboot or depthcharge. + +The U-Boot tests ('make check') do operate, but at present there are no +Chromium OS tests available. These will hopefully come together over time. Of +course the above sandbox feature provides a sort of functional test and can +detect problems that affect the flow or particular vboot features. + + +U-Boot without Chromium OS verified boot +---------------------------------------- + +The following script can be used to boot a Chrome OS image on coral:: + + # Read the image header and obtain the address of the kernel + # The offset 4f0 is defined by verified boot and may change for other + # Chromebooks + read mmc 2:2 100000 0 80; setexpr loader *001004f0; + + # Get the kernel size and calculate the number of blocks (0x200 bytes each) + setexpr size *00100518; setexpr blocks $size / 200; + + # Read the full kernel and calculate the address of the setup block + read mmc 2:2 100000 80 $blocks; setexpr setup $loader - 1000; + + # Locate the command line + setexpr cmdline $loader - 2000; + + # Start the zboot process with the loaded kernel, setup block and cmdline + zboot start 100000 0 0 0 $setup $cmdline; + + # Load the kernel, fix up the 'setup' block, dump information + zboot load; zboot setup; zboot dump + + # Boot into Chrome OS + zboot go + + +TO DO +----- + +Get the full ACPI tables working with Coral + + +7 October 2018 diff --git a/doc/index.rst b/doc/index.rst index f7aada9..02de1d4 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -87,6 +87,14 @@ Android-specific features available in U-Boot. android/index +Chromium OS-specific doc +------------------------ + +.. toctree:: + :maxdepth: 2 + + chromium/index + Indices and tables ================== -- cgit v1.1 From 45cd2e55755b77b644401bb3887c11f7653327c0 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:21 +1300 Subject: command: Fix operation of !CONFIG_CMDLINE The U_BOOT_CMDREP_COMPLETE() macro produces a build error if CONFIG_CMDLINE is not enabled. Fix this by updating the macro to provide the 'repeatable' arugment in this case. Signed-off-by: Simon Glass --- include/command.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/command.h b/include/command.h index 747f8f8..137cfbc 100644 --- a/include/command.h +++ b/include/command.h @@ -389,6 +389,14 @@ int run_command_list(const char *cmd, int len, int flag); return 0; \ } +#define _CMD_REMOVE_REP(_name, _cmd) \ + int __remove_ ## _name(void) \ + { \ + if (0) \ + _cmd(NULL, 0, 0, NULL, NULL); \ + return 0; \ + } + #define U_BOOT_CMDREP_MKENT_COMPLETE(_name, _maxargs, _cmd_rep, \ _usage, _help, _comp) \ { #_name, _maxargs, 0 ? _cmd_rep : NULL, NULL, _usage, \ @@ -405,7 +413,7 @@ int run_command_list(const char *cmd, int len, int flag); #define U_BOOT_CMDREP_COMPLETE(_name, _maxargs, _cmd_rep, _usage, \ _help, _comp) \ - _CMD_REMOVE(sub_ ## _name, _cmd_rep) + _CMD_REMOVE_REP(sub_ ## _name, _cmd_rep) #endif /* CONFIG_CMDLINE */ -- cgit v1.1 From f2c1442e9643396a764fc3c9c28ffc2f36a73bbe Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:22 +1300 Subject: bloblist: Make BLOBLIST_TABLES depend on BLOBLIST Add an extra condition here since we cannot put x86 tables in a bloblist when bloblists are not supported. Signed-off-by: Simon Glass --- lib/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Kconfig b/lib/Kconfig index 7288340..80ff244 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -642,7 +642,7 @@ menu "System tables" config BLOBLIST_TABLES bool "Put tables in a bloblist" - depends on X86 + depends on X86 && BLOBLIST help Normally tables are placed at address 0xf0000 and can be up to 64KB long. With this option, tables are instead placed in the bloblist -- cgit v1.1 From a8d696275aca9a121d438db50fcc44c02d7793cb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:23 +1300 Subject: bootm: Skip command-line substitution if !CONFIG_CMDLINE When there is no command line, we cannot enable this feature. Add a check to avoid a build error. Signed-off-by: Simon Glass --- common/bootm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/bootm.c b/common/bootm.c index dab7c36..ea71522 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -583,7 +583,8 @@ int bootm_process_cmdline(char *buf, int maxlen, int flags) if (ret) return log_msg_ret("silent", ret); } - if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && (flags & BOOTM_CL_SUBST)) { + if (IS_ENABLED(CONFIG_BOOTARGS_SUBST) && IS_ENABLED(CONFIG_CMDLINE) && + (flags & BOOTM_CL_SUBST)) { ret = process_subst(buf, maxlen); if (ret) return log_msg_ret("subst", ret); -- cgit v1.1 From c119528a1dd0ac719040d234c0a368a0ebaeb745 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 15 Mar 2021 18:11:24 +1300 Subject: sandbox: Correct uninit conflict It is not possible to remove the state before driver model is uninited, since the devices are allocated in the memory buffer. Also it is not possible to uninit driver model afterwards, since the RAM has been freed. Drop the uninit altogether, since it is not actually necessary. Signed-off-by: Simon Glass --- arch/sandbox/cpu/cpu.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index edd48e2..48636ab 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -17,7 +16,6 @@ #include #include #include -#include DECLARE_GLOBAL_DATA_PTR; @@ -34,10 +32,8 @@ void sandbox_exit(void) { /* Do this here while it still has an effect */ os_fd_restore(); - if (state_uninit()) - os_exit(2); - if (dm_uninit()) + if (state_uninit()) os_exit(2); /* This is considered normal termination for now */ -- cgit v1.1 From 96dedb0da2e8b27165c755fab8d06b15a8b8097a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 16:50:06 +1300 Subject: sysinfo: Allow showing model info from sysinfo Some boards may want to show the SKU ID or other information obtained at runtime. Allow this to come from sysinfo. The board can then provide a sysinfo driver to provide it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- common/board_info.c | 37 +++++++++++++++++++++++++++++-------- include/sysinfo.h | 4 ++++ 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/common/board_info.c b/common/board_info.c index b54aa30..1cfe34f 100644 --- a/common/board_info.c +++ b/common/board_info.c @@ -1,31 +1,52 @@ // SPDX-License-Identifier: GPL-2.0+ #include +#include #include +#include #include #include #include +DECLARE_GLOBAL_DATA_PTR; + int __weak checkboard(void) { return 0; } /* - * If the root node of the DTB has a "model" property, show it. + * Check sysinfo for board information. Failing that if the root node of the DTB + * has a "model" property, show it. + * * Then call checkboard(). */ int __weak show_board_info(void) { -#ifdef CONFIG_OF_CONTROL - DECLARE_GLOBAL_DATA_PTR; - const char *model; + if (IS_ENABLED(CONFIG_OF_CONTROL)) { + struct udevice *dev; + const char *model; + char str[80]; + int ret = -ENOSYS; + + if (IS_ENABLED(CONFIG_SYSINFO)) { + /* This might provide more detail */ + ret = uclass_first_device_err(UCLASS_SYSINFO, &dev); + if (!ret) + ret = sysinfo_get_str(dev, + SYSINFO_ID_BOARD_MODEL, + sizeof(str), str); + } - model = fdt_getprop(gd->fdt_blob, 0, "model", NULL); + /* Fail back to the main 'model' if available */ + if (ret) + model = fdt_getprop(gd->fdt_blob, 0, "model", NULL); + else + model = str; - if (model) - printf("Model: %s\n", model); -#endif + if (model) + printf("Model: %s\n", model); + } return checkboard(); } diff --git a/include/sysinfo.h b/include/sysinfo.h index 270ac1b..68fad25 100644 --- a/include/sysinfo.h +++ b/include/sysinfo.h @@ -37,9 +37,13 @@ struct udevice; enum sysinfo_id { SYSINFO_ID_NONE, + /* For SMBIOS tables */ SYSINFO_ID_SMBIOS_SYSTEM_VERSION, SYSINFO_ID_SMBIOS_BASEBOARD_VERSION, + /* For show_board_info() */ + SYSINFO_ID_BOARD_MODEL, + /* First value available for downstream/board used */ SYSINFO_ID_USER = 0x1000, }; -- cgit v1.1 From 80a4570c99233cf9c7b30bf77b9c9ab47b41fb15 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 16:50:07 +1300 Subject: x86: coral: Show memory config and SKU ID on startup Provide the model information through sysinfo so that it shows up on boot. For memconfig 4 pins are provided, for 16 combinations. For SKU ID there are two options: - two pins provided in a ternary arrangement, for 9 combinations. - reading from the EC Add a binding doc and drop the unused #defines as well. Example: U-Boot 2021.01-rc5 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 (memconfig 5, SKU 3) This depends on the GPIO series: http://patchwork.ozlabs.org/project/uboot/list/?series=228126 Signed-off-by: Simon Glass Acked-by: Bin Meng --- arch/x86/dts/chromebook_coral.dts | 11 ++ board/google/chromebook_coral/coral.c | 139 ++++++++++++++++++++-- board/google/chromebook_coral/variant_gpio.h | 6 - doc/device-tree-bindings/sysinfo/google,coral.txt | 37 ++++++ 4 files changed, 179 insertions(+), 14 deletions(-) create mode 100644 doc/device-tree-bindings/sysinfo/google,coral.txt diff --git a/arch/x86/dts/chromebook_coral.dts b/arch/x86/dts/chromebook_coral.dts index 527c0ad..c8cb4e2 100644 --- a/arch/x86/dts/chromebook_coral.dts +++ b/arch/x86/dts/chromebook_coral.dts @@ -56,6 +56,17 @@ recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>; write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>; phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>; + memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH + &gpio_nw GPIO_102 GPIO_ACTIVE_HIGH + &gpio_n GPIO_38 GPIO_ACTIVE_HIGH + &gpio_n GPIO_45 GPIO_ACTIVE_HIGH>; + + /* + * This is used for reef only: + * + * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH + * &gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>; + */ smbios { /* Type 1 table */ system { diff --git a/board/google/chromebook_coral/coral.c b/board/google/chromebook_coral/coral.c index b255bf6..3f9235c 100644 --- a/board/google/chromebook_coral/coral.c +++ b/board/google/chromebook_coral/coral.c @@ -3,9 +3,12 @@ * Copyright 2019 Google LLC */ +#define LOG_CATEGORY UCLASS_SYSINFO + #include #include #include +#include #include #include #include @@ -15,6 +18,7 @@ #include #include #include +#include #include "variant_gpio.h" struct cros_gpio_info { @@ -29,10 +33,125 @@ int arch_misc_init(void) return 0; } -/* This function is needed if CONFIG_CMDLINE is not enabled */ -int board_run_command(const char *cmdline) +static int get_memconfig(struct udevice *dev) { - printf("No command line\n"); + struct gpio_desc gpios[4]; + int cfg; + int ret; + + ret = gpio_request_list_by_name(dev, "memconfig-gpios", gpios, + ARRAY_SIZE(gpios), + GPIOD_IS_IN | GPIOD_PULL_UP); + if (ret < 0) { + log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret); + return ret; + } + + /* Give the lines time to settle */ + udelay(10); + + ret = dm_gpio_get_values_as_int(gpios, ARRAY_SIZE(gpios)); + if (ret < 0) + return log_msg_ret("get", ret); + cfg = ret; + + ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios)); + if (ret) + return log_msg_ret("free", ret); + + return cfg; +} + +/** + * get_skuconfig() - Get the SKU number either from pins or the EC + * + * Two options are supported: + * skuconfig-gpios - two pins in the device tree (tried first) + * EC - reading from the EC (backup) + * + * @dev: sysinfo device to use + * @return SKU ID, or -ve error if not found + */ +static int get_skuconfig(struct udevice *dev) +{ + struct gpio_desc gpios[2]; + int cfg; + int ret; + + ret = gpio_request_list_by_name(dev, "skuconfig-gpios", gpios, + ARRAY_SIZE(gpios), + GPIOD_IS_IN); + if (ret != ARRAY_SIZE(gpios)) { + struct udevice *cros_ec; + + log_debug("Cannot get GPIO list '%s' (%d)\n", dev->name, ret); + + /* Try the EC */ + ret = uclass_first_device_err(UCLASS_CROS_EC, &cros_ec); + if (ret < 0) { + log_err("Cannot find EC for SKU details\n"); + return log_msg_ret("sku", ret); + } + ret = cros_ec_get_sku_id(cros_ec); + if (ret < 0) { + log_err("Cannot read SKU details\n"); + return log_msg_ret("sku", ret); + } + + return ret; + } + + ret = dm_gpio_get_values_as_int_base3(gpios, ARRAY_SIZE(gpios)); + if (ret < 0) + return log_msg_ret("get", ret); + cfg = ret; + + ret = gpio_free_list(dev, gpios, ARRAY_SIZE(gpios)); + if (ret) + return log_msg_ret("free", ret); + + return cfg; +} + +static int coral_get_str(struct udevice *dev, int id, size_t size, char *val) +{ + int ret; + + if (IS_ENABLED(CONFIG_SPL_BUILD)) + return -ENOSYS; + + switch (id) { + case SYSINFO_ID_SMBIOS_SYSTEM_VERSION: + case SYSINFO_ID_SMBIOS_BASEBOARD_VERSION: { + ret = get_skuconfig(dev); + + if (ret < 0) + return ret; + if (size < 15) + return -ENOSPC; + sprintf(val, "rev%d", ret); + break; + } + case SYSINFO_ID_BOARD_MODEL: { + int mem_config, sku_config; + const char *model; + + ret = get_memconfig(dev); + if (ret < 0) + log_warning("Unable to read memconfig (err=%d)\n", ret); + mem_config = ret; + ret = get_skuconfig(dev); + if (ret < 0) + log_warning("Unable to read skuconfig (err=%d)\n", ret); + sku_config = ret; + model = fdt_getprop(gd->fdt_blob, 0, "model", NULL); + snprintf(val, size, "%s (memconfig %d, SKU %d)", model, + mem_config, sku_config); + break; + } + default: + return -ENOENT; + } return 0; } @@ -45,12 +164,15 @@ int chromeos_get_gpio(const struct udevice *dev, const char *prop, int ret; ret = gpio_request_by_name((struct udevice *)dev, prop, 0, &desc, 0); - if (ret == -ENOTBLK) + if (ret == -ENOTBLK) { info->gpio_num = CROS_GPIO_VIRTUAL; - else if (ret) + log_debug("GPIO '%s' is virtual\n", prop); + } else if (ret) { return log_msg_ret("gpio", ret); - else + } else { info->gpio_num = desc.offset; + dm_gpio_free((struct udevice *)dev, &desc); + } info->linux_name = dev_read_string(desc.dev, "linux-name"); if (!info->linux_name) return log_msg_ret("linux-name", -ENOENT); @@ -83,11 +205,11 @@ static int chromeos_acpi_gpio_generate(const struct udevice *dev, ret = chromeos_get_gpio(dev, "write-protect-gpios", CROS_GPIO_WP, &info[1]); if (ret) - return log_msg_ret("rec", ret); + return log_msg_ret("wp", ret); ret = chromeos_get_gpio(dev, "phase-enforce-gpios", CROS_GPIO_PE, &info[2]); if (ret) - return log_msg_ret("rec", ret); + return log_msg_ret("phase", ret); acpigen_write_scope(ctx, "\\"); acpigen_write_name(ctx, "OIPG"); acpigen_write_package(ctx, count); @@ -147,6 +269,7 @@ struct acpi_ops coral_acpi_ops = { }; struct sysinfo_ops coral_sysinfo_ops = { + .get_str = coral_get_str, }; #if !CONFIG_IS_ENABLED(OF_PLATDATA) diff --git a/board/google/chromebook_coral/variant_gpio.h b/board/google/chromebook_coral/variant_gpio.h index f516d88..403e241 100644 --- a/board/google/chromebook_coral/variant_gpio.h +++ b/board/google/chromebook_coral/variant_gpio.h @@ -34,12 +34,6 @@ /* Determine if board is in final shipping mode. */ #define GPIO_SHIP_MODE GPIO_10 -/* Memory SKU GPIOs. */ -#define MEM_CONFIG3 GPIO_45 -#define MEM_CONFIG2 GPIO_38 -#define MEM_CONFIG1 GPIO_102 -#define MEM_CONFIG0 GPIO_101 - /* DMIC_CONFIG_PIN: High for 1-DMIC and low for 4-DMIC's */ #define DMIC_CONFIG_PIN GPIO_17 diff --git a/doc/device-tree-bindings/sysinfo/google,coral.txt b/doc/device-tree-bindings/sysinfo/google,coral.txt new file mode 100644 index 0000000..d8a1a79 --- /dev/null +++ b/doc/device-tree-bindings/sysinfo/google,coral.txt @@ -0,0 +1,37 @@ +Google Coral sysinfo information +================================ + +This binding allows information about the board to be described. It includes +the SMBIOS binding as well. + +Required properties: + + - compatible: "google,coral" + - recovery-gpios: GPIO to use for recovery button (-1 if none) + - wite-protect-gpios: GPIO to use for write-protect screw + - phase-enforce-gpios: GPIO to indicate the board is in final ship mode + - memconfig-gpios: 4 GPIOs to use to read memory config (as base2 int) + +Optional properties: + - skuconfig-gpios: 2 GPIOs to use to read SKU ID. If not present, the + Chromium OS EC SKU_ID is used instead + +Example: + +board: board { + compatible = "google,coral"; + recovery-gpios = <&gpio_nw (-1) GPIO_ACTIVE_LOW>; + write-protect-gpios = <&gpio_nw GPIO_75 GPIO_ACTIVE_HIGH>; + phase-enforce-gpios = <&gpio_n GPIO_10 GPIO_ACTIVE_HIGH>; + memconfig-gpios = <&gpio_nw GPIO_101 GPIO_ACTIVE_HIGH + &gpio_nw GPIO_102 GPIO_ACTIVE_HIGH + &gpio_n GPIO_38 GPIO_ACTIVE_HIGH + &gpio_n GPIO_45 GPIO_ACTIVE_HIGH>; + + /* + * This is used for reef only: + * + * skuconfig-gpios = <&gpio_nw GPIO_16 GPIO_ACTIVE_HIGH + * &gpio_nw GPIO_17 GPIO_ACTIVE_HIGH>; + */ + }; -- cgit v1.1 From e9e0db8894523b53af9ecbe1b995fabf3d3c5b78 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:29 +1300 Subject: binman: Use a unique number for the symbols test file Two test devicetree files currently have 192 as their unique number. Fix this by separating them out. Signed-off-by: Simon Glass --- tools/binman/ftest.py | 2 +- tools/binman/test/192_symbols_nodtb.dts | 26 -------------------------- tools/binman/test/196_symbols_nodtb.dts | 26 ++++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 27 deletions(-) delete mode 100644 tools/binman/test/192_symbols_nodtb.dts create mode 100644 tools/binman/test/196_symbols_nodtb.dts diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 81c213a..3444955 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1377,7 +1377,7 @@ class TestFunctional(unittest.TestCase): def testSymbolsNoDtb(self): """Test binman can assign symbols embedded in U-Boot SPL""" - self.checkSymbols('192_symbols_nodtb.dts', + self.checkSymbols('196_symbols_nodtb.dts', U_BOOT_SPL_NODTB_DATA + U_BOOT_SPL_DTB_DATA, 0x38) diff --git a/tools/binman/test/192_symbols_nodtb.dts b/tools/binman/test/192_symbols_nodtb.dts deleted file mode 100644 index 5c900d6..0000000 --- a/tools/binman/test/192_symbols_nodtb.dts +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/dts-v1/; - -/ { - #address-cells = <1>; - #size-cells = <1>; - - binman { - pad-byte = <0xff>; - u-boot-spl-nodtb { - }; - u-boot-spl-dtb { - }; - - u-boot { - offset = <0x38>; - }; - - u-boot-spl2 { - type = "u-boot-spl-nodtb"; - }; - u-boot-spl-dtb2 { - type = "u-boot-spl-dtb"; - }; - }; -}; diff --git a/tools/binman/test/196_symbols_nodtb.dts b/tools/binman/test/196_symbols_nodtb.dts new file mode 100644 index 0000000..5c900d6 --- /dev/null +++ b/tools/binman/test/196_symbols_nodtb.dts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0+ +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + pad-byte = <0xff>; + u-boot-spl-nodtb { + }; + u-boot-spl-dtb { + }; + + u-boot { + offset = <0x38>; + }; + + u-boot-spl2 { + type = "u-boot-spl-nodtb"; + }; + u-boot-spl-dtb2 { + type = "u-boot-spl-dtb"; + }; + }; +}; -- cgit v1.1 From 3d4333829388db834e6f0945bbefc837da590d78 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:30 +1300 Subject: binman: Allow disabling expanding an entry At present there is a command-line flag to disable substitution of expanded entries. Add an option to the entry node as well, so it can be controlled at the node level. Add a test to cover this. Fix up the comment to the checkSymbols() function it uses, while we are here. Signed-off-by: Simon Glass --- tools/binman/binman.rst | 7 +++++++ tools/binman/entries.rst | 6 +++--- tools/binman/entry.py | 3 ++- tools/binman/etype/u_boot.py | 2 +- tools/binman/etype/u_boot_spl.py | 2 +- tools/binman/etype/u_boot_tpl.py | 2 +- tools/binman/ftest.py | 20 ++++++++++++++++++-- tools/binman/test/197_symbols_expand.dts | 23 +++++++++++++++++++++++ 8 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 tools/binman/test/197_symbols_expand.dts diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst index 15314d1..28cb2e7 100644 --- a/tools/binman/binman.rst +++ b/tools/binman/binman.rst @@ -472,6 +472,13 @@ missing-msg: information about what needs to be fixed. See missing-blob-help for the message for each tag. +no-expanded: + By default binman substitutes entries with expanded versions if available, + so that a `u-boot` entry type turns into `u-boot-expanded`, for example. The + `--no-expanded` command-line option disables this globally. The + `no-expanded` property disables this just for a single entry. Put the + `no-expanded` boolean property in the node to select this behaviour. + The attributes supported for images and sections are described below. Several are similar to those for entries. diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index f6faa15..1a71413 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -863,7 +863,7 @@ U-Boot can access binman symbols at runtime. See: in the binman README for more information. Note that this entry is automatically replaced with u-boot-expanded unless ---no-expanded is used. +--no-expanded is used or the node has a 'no-expanded' property. @@ -984,7 +984,7 @@ The ELF file 'spl/u-boot-spl' must also be available for this to work, since binman uses that to look up symbols to write into the SPL binary. Note that this entry is automatically replaced with u-boot-spl-expanded -unless --no-expanded is used. +unless --no-expanded is used or the node has a 'no-expanded' property. @@ -1113,7 +1113,7 @@ The ELF file 'tpl/u-boot-tpl' must also be available for this to work, since binman uses that to look up symbols to write into the TPL binary. Note that this entry is automatically replaced with u-boot-tpl-expanded -unless --no-expanded is used. +unless --no-expanded is used or the node has a 'no-expanded' property. diff --git a/tools/binman/entry.py b/tools/binman/entry.py index 1cfa024..ac25986 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -164,7 +164,8 @@ class Entry(object): if obj and expanded: # Check whether to use the expanded entry new_etype = etype + '-expanded' - if obj.UseExpanded(node, etype, new_etype): + can_expand = not fdt_util.GetBool(node, 'no-expanded') + if can_expand and obj.UseExpanded(node, etype, new_etype): etype = new_etype else: obj = None diff --git a/tools/binman/etype/u_boot.py b/tools/binman/etype/u_boot.py index d2eaba6..e8d180a 100644 --- a/tools/binman/etype/u_boot.py +++ b/tools/binman/etype/u_boot.py @@ -25,7 +25,7 @@ class Entry_u_boot(Entry_blob): in the binman README for more information. Note that this entry is automatically replaced with u-boot-expanded unless - --no-expanded is used. + --no-expanded is used or the node has a 'no-expanded' property. """ def __init__(self, section, etype, node): super().__init__(section, etype, node) diff --git a/tools/binman/etype/u_boot_spl.py b/tools/binman/etype/u_boot_spl.py index 1c39f98..6f79bf5 100644 --- a/tools/binman/etype/u_boot_spl.py +++ b/tools/binman/etype/u_boot_spl.py @@ -32,7 +32,7 @@ class Entry_u_boot_spl(Entry_blob): binman uses that to look up symbols to write into the SPL binary. Note that this entry is automatically replaced with u-boot-spl-expanded - unless --no-expanded is used. + unless --no-expanded is used or the node has a 'no-expanded' property. """ def __init__(self, section, etype, node): super().__init__(section, etype, node) diff --git a/tools/binman/etype/u_boot_tpl.py b/tools/binman/etype/u_boot_tpl.py index 95d9bd6..0c575df 100644 --- a/tools/binman/etype/u_boot_tpl.py +++ b/tools/binman/etype/u_boot_tpl.py @@ -32,7 +32,7 @@ class Entry_u_boot_tpl(Entry_blob): binman uses that to look up symbols to write into the TPL binary. Note that this entry is automatically replaced with u-boot-tpl-expanded - unless --no-expanded is used. + unless --no-expanded is used or the node has a 'no-expanded' property. """ def __init__(self, section, etype, node): super().__init__(section, etype, node) diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 3444955..cd93dc1 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1344,13 +1344,19 @@ class TestFunctional(unittest.TestCase): data = self._DoReadFile('052_u_boot_spl_nodtb.dts') self.assertEqual(U_BOOT_SPL_NODTB_DATA, data[:len(U_BOOT_SPL_NODTB_DATA)]) - def checkSymbols(self, dts, base_data, u_boot_offset): + def checkSymbols(self, dts, base_data, u_boot_offset, entry_args=None, + use_expanded=False): """Check the image contains the expected symbol values Args: dts: Device tree file to use for test base_data: Data before and after 'u-boot' section u_boot_offset: Offset of 'u-boot' section in image + entry_args: Dict of entry args to supply to binman + key: arg name + value: value of that arg + use_expanded: True to use expanded entries where available, e.g. + 'u-boot-expanded' instead of 'u-boot' """ elf_fname = self.ElfTestFile('u_boot_binman_syms') syms = elf.GetSymbols(elf_fname, ['binman', 'image']) @@ -1359,7 +1365,8 @@ class TestFunctional(unittest.TestCase): addr) self._SetupSplElf('u_boot_binman_syms') - data = self._DoReadFile(dts) + data = self._DoReadFileDtb(dts, entry_args=entry_args, + use_expanded=use_expanded)[0] # The image should contain the symbols from u_boot_binman_syms.c # Note that image_pos is adjusted by the base address of the image, # which is 0x10 in our test image @@ -4460,5 +4467,14 @@ class TestFunctional(unittest.TestCase): start += fdt_size + len(U_BOOT_TPL_DATA) self.assertEqual(len(data), start) + def testSymbolsExpanded(self): + """Test binman can assign symbols in expanded entries""" + entry_args = { + 'spl-dtb': '1', + } + self.checkSymbols('197_symbols_expand.dts', U_BOOT_SPL_NODTB_DATA + + U_BOOT_SPL_DTB_DATA, 0x38, + entry_args=entry_args, use_expanded=True) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/197_symbols_expand.dts b/tools/binman/test/197_symbols_expand.dts new file mode 100644 index 0000000..8aee76d --- /dev/null +++ b/tools/binman/test/197_symbols_expand.dts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + pad-byte = <0xff>; + u-boot-spl { + }; + + u-boot { + offset = <0x38>; + no-expanded; + }; + + u-boot-spl2 { + type = "u-boot-spl"; + }; + }; +}; -- cgit v1.1 From 189f291914cb867f8782d7224a1073d6e17fc800 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:31 +1300 Subject: binman: Add support for a collection of entries The vblock entry type includes code to collect the data from a number of other entries (not necessarily subentries) and concatenating it. This is a useful feature for other entry types. Make it a base class, so that vblock can use it, along with other entry types. Signed-off-by: Simon Glass --- tools/binman/entries.rst | 13 ++++++++ tools/binman/entry.py | 5 +++ tools/binman/etype/collection.py | 61 ++++++++++++++++++++++++++++++++++++ tools/binman/etype/vblock.py | 26 +++++++-------- tools/binman/ftest.py | 10 +++++- tools/binman/test/198_collection.dts | 27 ++++++++++++++++ 6 files changed, 128 insertions(+), 14 deletions(-) create mode 100644 tools/binman/etype/collection.py create mode 100644 tools/binman/test/198_collection.dts diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index 1a71413..d5f8d95 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -248,6 +248,19 @@ both of size 1MB. +Entry: collection: An entry which contains a collection of other entries +------------------------------------------------------------------------ + +Properties / Entry arguments: + - content: List of phandles to entries to include + +This allows reusing the contents of other entries. The contents of the +listed entries are combined to form this entry. This serves as a useful +base class for entry types which need to process data from elsewhere in +the image, not necessarily child entries. + + + Entry: cros-ec-rw: A blob entry which contains a Chromium OS read-write EC image -------------------------------------------------------------------------------- diff --git a/tools/binman/entry.py b/tools/binman/entry.py index ac25986..a157038 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -438,6 +438,11 @@ class Entry(object): """Convenience function to raise an error referencing a node""" raise ValueError("Node '%s': %s" % (self._node.path, msg)) + def Info(self, msg): + """Convenience function to log info referencing a node""" + tag = "Info '%s'" % self._node.path + tout.Detail('%30s: %s' % (tag, msg)) + def Detail(self, msg): """Convenience function to log detail referencing a node""" tag = "Node '%s'" % self._node.path diff --git a/tools/binman/etype/collection.py b/tools/binman/etype/collection.py new file mode 100644 index 0000000..c0c552a --- /dev/null +++ b/tools/binman/etype/collection.py @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright 2021 Google LLC +# Written by Simon Glass +# + +# Support for a collection of entries from other parts of an image + +from collections import OrderedDict +import os + +from binman.entry import Entry +from dtoc import fdt_util + +class Entry_collection(Entry): + """An entry which contains a collection of other entries + + Properties / Entry arguments: + - content: List of phandles to entries to include + + This allows reusing the contents of other entries. The contents of the + listed entries are combined to form this entry. This serves as a useful + base class for entry types which need to process data from elsewhere in + the image, not necessarily child entries. + """ + def __init__(self, section, etype, node): + super().__init__(section, etype, node) + self.content = fdt_util.GetPhandleList(self._node, 'content') + if not self.content: + self.Raise("Collection must have a 'content' property") + + def GetContents(self): + """Get the contents of this entry + + Returns: + bytes content of the entry + """ + # Join up all the data + self.Info('Getting content') + data = b'' + for entry_phandle in self.content: + entry_data = self.section.GetContentsByPhandle(entry_phandle, self) + if entry_data is None: + # Data not available yet + return None + data += entry_data + + self.Info('Returning contents size %x' % len(data)) + + return data + + def ObtainContents(self): + data = self.GetContents() + if data is None: + return False + self.SetContents(data) + return True + + def ProcessContents(self): + # The blob may have changed due to WriteSymbols() + data = self.GetContents() + return self.ProcessContentsUpdate(data) diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py index eba5351..d473083 100644 --- a/tools/binman/etype/vblock.py +++ b/tools/binman/etype/vblock.py @@ -9,12 +9,13 @@ from collections import OrderedDict import os -from binman.entry import Entry, EntryArg +from binman.entry import EntryArg +from binman.etype.collection import Entry_collection from dtoc import fdt_util from patman import tools -class Entry_vblock(Entry): +class Entry_vblock(Entry_collection): """An entry which contains a Chromium OS verified boot block Properties / Entry arguments: @@ -37,9 +38,6 @@ class Entry_vblock(Entry): """ def __init__(self, section, etype, node): super().__init__(section, etype, node) - self.content = fdt_util.GetPhandleList(self._node, 'content') - if not self.content: - self.Raise("Vblock must have a 'content' property") (self.keydir, self.keyblock, self.signprivate, self.version, self.kernelkey, self.preamble_flags) = self.GetEntryArgsOrProps([ EntryArg('keydir', str), @@ -50,14 +48,16 @@ class Entry_vblock(Entry): EntryArg('preamble-flags', int)]) def GetVblock(self): + """Get the contents of this entry + + Returns: + bytes content of the entry, which is the signed vblock for the + provided data + """ # Join up the data files to be signed - input_data = b'' - for entry_phandle in self.content: - data = self.section.GetContentsByPhandle(entry_phandle, self) - if data is None: - # Data not available yet - return False - input_data += data + input_data = self.GetContents() + if input_data is None: + return None uniq = self.GetUniqueName() output_fname = tools.GetOutputFilename('vblock.%s' % uniq) @@ -80,7 +80,7 @@ class Entry_vblock(Entry): def ObtainContents(self): data = self.GetVblock() - if data is False: + if data is None: return False self.SetContents(data) return True diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index cd93dc1..fdd4f4d 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -1718,7 +1718,7 @@ class TestFunctional(unittest.TestCase): """Test we detect a vblock which has no content to sign""" with self.assertRaises(ValueError) as e: self._DoReadFile('075_vblock_no_content.dts') - self.assertIn("Node '/binman/vblock': Vblock must have a 'content' " + self.assertIn("Node '/binman/vblock': Collection must have a 'content' " 'property', str(e.exception)) def testVblockBadPhandle(self): @@ -4476,5 +4476,13 @@ class TestFunctional(unittest.TestCase): U_BOOT_SPL_DTB_DATA, 0x38, entry_args=entry_args, use_expanded=True) + def testCollection(self): + """Test a collection""" + data = self._DoReadFile('198_collection.dts') + self.assertEqual(U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA + + tools.GetBytes(0xff, 2) + U_BOOT_NODTB_DATA + + tools.GetBytes(0xfe, 3) + U_BOOT_DTB_DATA, + data) + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/198_collection.dts b/tools/binman/test/198_collection.dts new file mode 100644 index 0000000..484a1b0 --- /dev/null +++ b/tools/binman/test/198_collection.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + collection { + content = <&u_boot_nodtb &dtb>; + }; + fill { + size = <2>; + fill-byte = [ff]; + }; + u_boot_nodtb: u-boot-nodtb { + }; + fill2 { + type = "fill"; + size = <3>; + fill-byte = [fe]; + }; + dtb: u-boot-dtb { + }; + }; +}; -- cgit v1.1 From 631f752de5b8dccbf9a0d4824213e9e6e0d96167 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:32 +1300 Subject: binman: Support obtaining section contents immediately Generally the content of sections is not built until the final assembly of the image. This is partly to avoid wasting time, since the entries within sections may change multiple times as binman works through its various stages. This works quite well since sections exist in a strict hierarchy, so they can be processed in a depth-first manner. However the 'collection' entry type does not have this luxury. If it contains a section within its 'content' list, then it must produce the section contents, if available. That section is typically a sibling node, i.e. not part oc the collection's hierarchy. Add a new 'required' argument to section.GetData() to support this. When required is True, any referenced sections are immediately built. If this is not possible (because one of the subentries does not have its data yet) then an error is produced. The test for this uses a 'collection' entry type, referencing a section as its first member. This forces a call to _BuildSectionData() with required set to False, at first, then True later, when the image is assembled. Signed-off-by: Simon Glass --- tools/binman/entry.py | 6 ++++- tools/binman/etype/collection.py | 18 ++++++++++----- tools/binman/etype/section.py | 33 +++++++++++++++++++++------- tools/binman/etype/vblock.py | 12 ++++++---- tools/binman/ftest.py | 13 +++++++++++ tools/binman/test/199_collection_section.dts | 32 +++++++++++++++++++++++++++ 6 files changed, 95 insertions(+), 19 deletions(-) create mode 100644 tools/binman/test/199_collection_section.dts diff --git a/tools/binman/entry.py b/tools/binman/entry.py index a157038..b7b9791 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -482,9 +482,13 @@ class Entry(object): """ return self._node.path - def GetData(self): + def GetData(self, required=True): """Get the contents of an entry + Args: + required: True if the data must be present, False if it is OK to + return None + Returns: bytes content of the entry, excluding any padding. If the entry is compressed, the compressed data is returned diff --git a/tools/binman/etype/collection.py b/tools/binman/etype/collection.py index c0c552a..1625575 100644 --- a/tools/binman/etype/collection.py +++ b/tools/binman/etype/collection.py @@ -28,18 +28,24 @@ class Entry_collection(Entry): if not self.content: self.Raise("Collection must have a 'content' property") - def GetContents(self): + def GetContents(self, required): """Get the contents of this entry + Args: + required: True if the data must be present, False if it is OK to + return None + Returns: bytes content of the entry """ # Join up all the data - self.Info('Getting content') + self.Info('Getting contents, required=%s' % required) data = b'' for entry_phandle in self.content: - entry_data = self.section.GetContentsByPhandle(entry_phandle, self) - if entry_data is None: + entry_data = self.section.GetContentsByPhandle(entry_phandle, self, + required) + if not required and entry_data is None: + self.Info('Contents not available yet') # Data not available yet return None data += entry_data @@ -49,7 +55,7 @@ class Entry_collection(Entry): return data def ObtainContents(self): - data = self.GetContents() + data = self.GetContents(False) if data is None: return False self.SetContents(data) @@ -57,5 +63,5 @@ class Entry_collection(Entry): def ProcessContents(self): # The blob may have changed due to WriteSymbols() - data = self.GetContents() + data = self.GetContents(True) return self.ProcessContentsUpdate(data) diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index cce1500..d4a097b 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -180,7 +180,7 @@ class Entry_section(Entry): return data - def _BuildSectionData(self): + def _BuildSectionData(self, required): """Build the contents of a section This places all entries at the right place, dealing with padding before @@ -188,13 +188,20 @@ class Entry_section(Entry): pad-before and pad-after properties in the section items) since that is handled by the parent section. + Args: + required: True if the data must be present, False if it is OK to + return None + Returns: Contents of the section (bytes) """ section_data = b'' for entry in self._entries.values(): - data = self.GetPaddedDataForEntry(entry, entry.GetData()) + entry_data = entry.GetData(required) + if not required and entry_data is None: + return None + data = self.GetPaddedDataForEntry(entry, entry_data) # Handle empty space before the entry pad = (entry.offset or 0) - self._skip_at_start - len(section_data) if pad > 0: @@ -226,18 +233,24 @@ class Entry_section(Entry): data = self.GetData() return section.GetPaddedDataForEntry(self, data) - def GetData(self): + def GetData(self, required=True): """Get the contents of an entry This builds the contents of the section, stores this as the contents of the section and returns it + Args: + required: True if the data must be present, False if it is OK to + return None + Returns: bytes content of the section, made up for all all of its subentries. This excludes any padding. If the section is compressed, the compressed data is returned """ - data = self._BuildSectionData() + data = self._BuildSectionData(required) + if data is None: + return None self.SetContents(data) return data @@ -263,7 +276,7 @@ class Entry_section(Entry): self._SortEntries() self._ExpandEntries() - data = self._BuildSectionData() + data = self._BuildSectionData(True) self.SetContents(data) self.CheckSize() @@ -360,16 +373,20 @@ class Entry_section(Entry): def GetEntries(self): return self._entries - def GetContentsByPhandle(self, phandle, source_entry): + def GetContentsByPhandle(self, phandle, source_entry, required): """Get the data contents of an entry specified by a phandle This uses a phandle to look up a node and and find the entry - associated with it. Then it returnst he contents of that entry. + associated with it. Then it returns the contents of that entry. + + The node must be a direct subnode of this section. Args: phandle: Phandle to look up (integer) source_entry: Entry containing that phandle (used for error reporting) + required: True if the data must be present, False if it is OK to + return None Returns: data from associated entry (as a string), or None if not found @@ -379,7 +396,7 @@ class Entry_section(Entry): source_entry.Raise("Cannot find node for phandle %d" % phandle) for entry in self._entries.values(): if entry._node == node: - return entry.GetData() + return entry.GetData(required) source_entry.Raise("Cannot find entry for node '%s'" % node.name) def LookupSymbol(self, sym_name, optional, msg, base_addr, entries=None): diff --git a/tools/binman/etype/vblock.py b/tools/binman/etype/vblock.py index d473083..c0a6a28 100644 --- a/tools/binman/etype/vblock.py +++ b/tools/binman/etype/vblock.py @@ -47,15 +47,19 @@ class Entry_vblock(Entry_collection): EntryArg('kernelkey', str), EntryArg('preamble-flags', int)]) - def GetVblock(self): + def GetVblock(self, required): """Get the contents of this entry + Args: + required: True if the data must be present, False if it is OK to + return None + Returns: bytes content of the entry, which is the signed vblock for the provided data """ # Join up the data files to be signed - input_data = self.GetContents() + input_data = self.GetContents(required) if input_data is None: return None @@ -79,7 +83,7 @@ class Entry_vblock(Entry_collection): return tools.ReadFile(output_fname) def ObtainContents(self): - data = self.GetVblock() + data = self.GetVblock(False) if data is None: return False self.SetContents(data) @@ -87,5 +91,5 @@ class Entry_vblock(Entry_collection): def ProcessContents(self): # The blob may have changed due to WriteSymbols() - data = self.GetVblock() + data = self.GetVblock(True) return self.ProcessContentsUpdate(data) diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index fdd4f4d..043b1b0 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -4484,5 +4484,18 @@ class TestFunctional(unittest.TestCase): tools.GetBytes(0xfe, 3) + U_BOOT_DTB_DATA, data) + def testCollectionSection(self): + """Test a collection where a section must be built first""" + # Sections never have their contents when GetData() is called, but when + # _BuildSectionData() is called with required=True, a section will force + # building the contents, producing an error is anything is still + # missing. + data = self._DoReadFile('199_collection_section.dts') + section = U_BOOT_NODTB_DATA + U_BOOT_DTB_DATA + self.assertEqual(section + U_BOOT_DATA + tools.GetBytes(0xff, 2) + + section + tools.GetBytes(0xfe, 3) + U_BOOT_DATA, + data) + + if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/199_collection_section.dts b/tools/binman/test/199_collection_section.dts new file mode 100644 index 0000000..03a7319 --- /dev/null +++ b/tools/binman/test/199_collection_section.dts @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + collection { + content = <§ion &u_boot>; + }; + fill { + size = <2>; + fill-byte = [ff]; + }; + section: section { + u-boot-nodtb { + }; + u-boot-dtb { + }; + }; + fill2 { + type = "fill"; + size = <3>; + fill-byte = [fe]; + }; + u_boot: u-boot { + no-expanded; + }; + }; +}; -- cgit v1.1 From 5ff9fedc9bc02e01d73d57e9c7d7eac9fd6320d4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:33 +1300 Subject: binman: Support default alignment for sections Sometimes it is useful to specify the default alignment for all entries in a section, such as when word-alignment is necessary, for example. It is tedious and error-prone to specify this individually for each section. Add a property to control this for a section. Signed-off-by: Simon Glass --- tools/binman/binman.rst | 7 +++++++ tools/binman/entries.rst | 2 ++ tools/binman/entry.py | 2 ++ tools/binman/etype/cbfs.py | 1 + tools/binman/etype/mkimage.py | 1 + tools/binman/etype/section.py | 3 +++ tools/binman/ftest.py | 12 ++++++++++++ tools/binman/test/200_align_default.dts | 30 ++++++++++++++++++++++++++++++ 8 files changed, 58 insertions(+) create mode 100644 tools/binman/test/200_align_default.dts diff --git a/tools/binman/binman.rst b/tools/binman/binman.rst index 28cb2e7..1aa2459 100644 --- a/tools/binman/binman.rst +++ b/tools/binman/binman.rst @@ -562,6 +562,13 @@ skip-at-start: 'end-at-4gb' property is not applicable where CONFIG_SYS_TEXT_BASE + Image size != 4gb. +align-default: + Specifies the default alignment for entries in this section, if they do + not specify an alignment. Note that this only applies to top-level entries + in the section (direct subentries), not any subentries of those entries. + This means that each section must specify its own default alignment, if + required. + Examples of the above options can be found in the tests. See the tools/binman/test directory. diff --git a/tools/binman/entries.rst b/tools/binman/entries.rst index d5f8d95..a91211e 100644 --- a/tools/binman/entries.rst +++ b/tools/binman/entries.rst @@ -796,6 +796,8 @@ Properties / Entry arguments: (see binman README for more information): file, since the first 16 bytes are skipped when writing. name-prefix: Adds a prefix to the name of every entry in the section when writing out the map + align_default: Default alignment for this section, if no alignment is + given in the entry Properties: allow_missing: True if this section permits external blobs to be diff --git a/tools/binman/entry.py b/tools/binman/entry.py index b7b9791..7022271 100644 --- a/tools/binman/entry.py +++ b/tools/binman/entry.py @@ -201,6 +201,8 @@ class Entry(object): if tools.NotPowerOfTwo(self.align): raise ValueError("Node '%s': Alignment %s must be a power of two" % (self._node.path, self.align)) + if self.section and self.align is None: + self.align = self.section.align_default self.pad_before = fdt_util.GetInt(self._node, 'pad-before', 0) self.pad_after = fdt_util.GetInt(self._node, 'pad-after', 0) self.align_size = fdt_util.GetInt(self._node, 'align-size') diff --git a/tools/binman/etype/cbfs.py b/tools/binman/etype/cbfs.py index 1daddeb..44db7b9 100644 --- a/tools/binman/etype/cbfs.py +++ b/tools/binman/etype/cbfs.py @@ -169,6 +169,7 @@ class Entry_cbfs(Entry): super().__init__(section, etype, node) self._cbfs_arg = fdt_util.GetString(node, 'cbfs-arch', 'x86') + self.align_default = None self._cbfs_entries = OrderedDict() self._ReadSubnodes() self.reader = None diff --git a/tools/binman/etype/mkimage.py b/tools/binman/etype/mkimage.py index e9f8272..e499775 100644 --- a/tools/binman/etype/mkimage.py +++ b/tools/binman/etype/mkimage.py @@ -36,6 +36,7 @@ class Entry_mkimage(Entry): super().__init__(section, etype, node) self._args = fdt_util.GetString(self._node, 'args').split(' ') self._mkimage_entries = OrderedDict() + self.align_default = None self._ReadSubnodes() def ObtainContents(self): diff --git a/tools/binman/etype/section.py b/tools/binman/etype/section.py index d4a097b..c3bac02 100644 --- a/tools/binman/etype/section.py +++ b/tools/binman/etype/section.py @@ -36,6 +36,8 @@ class Entry_section(Entry): file, since the first 16 bytes are skipped when writing. name-prefix: Adds a prefix to the name of every entry in the section when writing out the map + align_default: Default alignment for this section, if no alignment is + given in the entry Properties: allow_missing: True if this section permits external blobs to be @@ -76,6 +78,7 @@ class Entry_section(Entry): if self._skip_at_start is None: self._skip_at_start = 0 self._name_prefix = fdt_util.GetString(self._node, 'name-prefix') + self.align_default = fdt_util.GetInt(self._node, 'align-default', 0) filename = fdt_util.GetString(self._node, 'filename') if filename: self._filename = filename diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py index 043b1b0..89fe661 100644 --- a/tools/binman/ftest.py +++ b/tools/binman/ftest.py @@ -4496,6 +4496,18 @@ class TestFunctional(unittest.TestCase): section + tools.GetBytes(0xfe, 3) + U_BOOT_DATA, data) + def testAlignDefault(self): + """Test that default alignment works on sections""" + data = self._DoReadFile('200_align_default.dts') + expected = (U_BOOT_DATA + tools.GetBytes(0, 8 - len(U_BOOT_DATA)) + + U_BOOT_DATA) + # Special alignment for section + expected += tools.GetBytes(0, 32 - len(expected)) + # No alignment within the nested section + expected += U_BOOT_DATA + U_BOOT_NODTB_DATA; + # Now the final piece, which should be default-aligned + expected += tools.GetBytes(0, 88 - len(expected)) + U_BOOT_NODTB_DATA + self.assertEqual(expected, data) if __name__ == "__main__": unittest.main() diff --git a/tools/binman/test/200_align_default.dts b/tools/binman/test/200_align_default.dts new file mode 100644 index 0000000..1b15577 --- /dev/null +++ b/tools/binman/test/200_align_default.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0+ + +/dts-v1/; + +/ { + #address-cells = <1>; + #size-cells = <1>; + + binman { + align-default = <8>; + u-boot { + }; + + u-boot-align { + type = "u-boot"; + }; + + section { + align = <32>; + u-boot { + }; + + u-boot-nodtb { + }; + }; + + u-boot-nodtb { + }; + }; +}; -- cgit v1.1 From acd98611c3ca26f10b997ab09aeacd9f4b91d5f3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:34 +1300 Subject: dtoc: Improve internal error for Refresh() Add the node name too so it is easy to see which node failed. Signed-off-by: Simon Glass --- tools/dtoc/fdt.py | 4 ++-- tools/dtoc/test_fdt.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index 25ce513..f0d1384 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -339,8 +339,8 @@ class Node: p = fdt_obj.get_property_by_offset(poffset) prop = self.props.get(p.name) if not prop: - raise ValueError("Internal error, property '%s' missing, " - 'offset %d' % (p.name, poffset)) + raise ValueError("Internal error, node '%s' property '%s' missing, " + 'offset %d' % (self.path, p.name, poffset)) prop.RefreshOffset(poffset) poffset = fdt_obj.next_property_offset(poffset, QUIET_NOTFOUND) diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py index 1c3a8a2..72095b0 100755 --- a/tools/dtoc/test_fdt.py +++ b/tools/dtoc/test_fdt.py @@ -209,7 +209,7 @@ class TestNode(unittest.TestCase): del self.node.props['notstring'] with self.assertRaises(ValueError) as e: self.dtb.Refresh() - self.assertIn("Internal error, property 'notstring' missing, offset ", + self.assertIn("Internal error, node '/spl-test' property 'notstring' missing, offset ", str(e.exception)) def testLookupPhandle(self): -- cgit v1.1 From 37ba9844c2e3689a6860d3f5c6d312490a3f2d80 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:35 +1300 Subject: dtoc: Tidy up property-offset handling If a property does not yet have an offset, then that means it exists in the cache'd fdt but has not yet been synced back to the flat tree. Use the dirty flag for this so we don't need to check the offset too. Improve the comments for Prop and Node to make it clear what an offset of None means. Also clear the dirty flag after the property is synced. Signed-off-by: Simon Glass --- tools/dtoc/fdt.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index f0d1384..36993c2 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -103,6 +103,8 @@ class Prop: """A device tree property Properties: + node: Node containing this property + offset: Offset of the property (None if still to be synced) name: Property name (as per the device tree) value: Property value as a string of bytes, or a list of strings of bytes @@ -114,7 +116,7 @@ class Prop: self.name = name self.value = None self.bytes = bytes(data) - self.dirty = False + self.dirty = offset is None if not data: self.type = Type.BOOL self.value = True @@ -228,7 +230,7 @@ class Prop: Raises: FdtException if auto_resize is False and there is not enough space """ - if self._offset is None or self.dirty: + if self.dirty: node = self._node fdt_obj = node._fdt._fdt_obj if auto_resize: @@ -239,13 +241,15 @@ class Prop: fdt_obj.setprop(node.Offset(), self.name, self.bytes) else: fdt_obj.setprop(node.Offset(), self.name, self.bytes) + self.dirty = False class Node: """A device tree node Properties: - offset: Integer offset in the device tree + parent: Parent Node + offset: Integer offset in the device tree (None if to be synced) name: Device tree node tname path: Full path to node, along with the node name itself _fdt: Device tree object -- cgit v1.1 From 71719e15e870f47ab368966394a5f2f32bf98095 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:36 +1300 Subject: dtoc: Tweak ordering of fdt-offsets refreshing Once the tree has been synced, thus potentially moving things around in the fdt, we set _cached_offsets to False so that a refresh will happen next time a property is accessed. This 'lazy' refresh doesn't really save much time, since refresh is a very fast operation, just a single walk of the tree. Also, having the refresh happen in the bowels of property access it makes it harder to figure out what is going on. Simplify the code by always doing a refresh before and after a sync. Set _cached_offsets to True immediately after this, in the Refresh() function, since this makes more sense than doing it in the caller. Signed-off-by: Simon Glass --- tools/dtoc/fdt.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index 36993c2..a5e1d0b 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -646,8 +646,9 @@ class Fdt: Raises: FdtException if auto_resize is False and there is not enough space """ + self.CheckCache() self._root.Sync(auto_resize) - self.Invalidate() + self.Refresh() def Pack(self): """Pack the device tree down to its minimum size @@ -656,7 +657,7 @@ class Fdt: build up in the device tree binary. """ CheckErr(self._fdt_obj.pack(), 'pack') - self.Invalidate() + self.Refresh() def GetContents(self): """Get the contents of the FDT @@ -708,11 +709,11 @@ class Fdt: if self._cached_offsets: return self.Refresh() - self._cached_offsets = True def Refresh(self): """Refresh the offset cache""" self._root.Refresh(0) + self._cached_offsets = True def GetStructOffset(self, offset): """Get the file offset of a given struct offset -- cgit v1.1 From 76677dd2b230ffb6d83e4acb85d2e7473ab74a4f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:37 +1300 Subject: dtoc: Add a subnode test for multiple nodes Add a new test that adds a subnode alongside an existing one, as well as adding properties to a subnode. This will expand to adding multiple subnodes in future patches. Put a node after the one we are adding to so we can check that things sync correctly. The testAddNode() test should be in the TestNode class since it is a node test, so move it. Signed-off-by: Simon Glass --- tools/dtoc/test/dtoc_test_simple.dts | 4 ++++ tools/dtoc/test_fdt.py | 42 +++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/tools/dtoc/test/dtoc_test_simple.dts b/tools/dtoc/test/dtoc_test_simple.dts index d8ab861..b5c1274 100644 --- a/tools/dtoc/test/dtoc_test_simple.dts +++ b/tools/dtoc/test/dtoc_test_simple.dts @@ -56,4 +56,8 @@ low-power; }; }; + + orig-node { + orig = <1 23 4>; + }; }; diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py index 72095b0..1e66e1b 100755 --- a/tools/dtoc/test_fdt.py +++ b/tools/dtoc/test_fdt.py @@ -154,6 +154,7 @@ class TestNode(unittest.TestCase): def setUp(self): self.dtb = fdt.FdtScan(find_dtb_file('dtoc_test_simple.dts')) self.node = self.dtb.GetNode('/spl-test') + self.fdt = self.dtb.GetFdtObj() def testOffset(self): """Tests that we can obtain the offset of a node""" @@ -197,7 +198,7 @@ class TestNode(unittest.TestCase): def testRefreshExtraNode(self): """Test refreshing offsets when an expected node is missing""" # Delete it from the device tre, not our tables - self.dtb.GetFdtObj().del_node(self.node.Offset()) + self.fdt.del_node(self.node.Offset()) with self.assertRaises(ValueError) as e: self.dtb.Refresh() self.assertIn('Internal error, node name mismatch ' @@ -220,6 +221,34 @@ class TestNode(unittest.TestCase): target = dtb.GetNode('/phandle-target') self.assertEqual(target, dtb.LookupPhandle(fdt32_to_cpu(prop.value))) + def testAddNodeSpace(self): + """Test adding a single node when out of space""" + self.fdt.pack() + self.node.AddSubnode('subnode') + with self.assertRaises(libfdt.FdtException) as e: + self.dtb.Sync(auto_resize=False) + self.assertIn('FDT_ERR_NOSPACE', str(e.exception)) + + self.dtb.Sync(auto_resize=True) + offset = self.fdt.path_offset('/spl-test/subnode') + self.assertTrue(offset > 0) + + def testAddNodes(self): + """Test adding various subnode and properies""" + node = self.dtb.GetNode('/i2c@0') + + # Add a property to the node after i2c@0 to check that this is not + # disturbed by adding a subnode to i2c@0 + orig_node = self.dtb.GetNode('/orig-node') + orig_node.AddInt('integer-4', 456) + + # Add a property to the pmic node to check that pmic properties are not + # disturbed + pmic = self.dtb.GetNode('/i2c@0/pmic@9') + pmic.AddInt('integer-5', 567) + + self.dtb.Sync(auto_resize=True) + class TestProp(unittest.TestCase): """Test operation of the Prop class""" @@ -385,17 +414,6 @@ class TestProp(unittest.TestCase): self.assertIn('FDT_ERR_NOSPACE', str(e.exception)) self.dtb.Sync(auto_resize=True) - def testAddNode(self): - self.fdt.pack() - self.node.AddSubnode('subnode') - with self.assertRaises(libfdt.FdtException) as e: - self.dtb.Sync(auto_resize=False) - self.assertIn('FDT_ERR_NOSPACE', str(e.exception)) - - self.dtb.Sync(auto_resize=True) - offset = self.fdt.path_offset('/spl-test/subnode') - self.assertTrue(offset > 0) - def testAddMore(self): """Test various other methods for adding and setting properties""" self.node.AddZeroProp('one') -- cgit v1.1 From f6176651bc1bad080d0512aeeed438e8763b951b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:38 +1300 Subject: dtoc: Support adding subnodes alongside existing ones So far we have only needed to add subnodes to empty notds, so have not had to deal with ordering. However this feature is needed for binman's expanded nodes, since there may be another node in the same section. While libfdt adds new properties after existing properties, it adds new subnodes before existing subnodes. This means that we must reorder the nodes in the cached version, so that the ordering remains consistent. Update the sync implementation to sync existing subnodes first, then add new ones, then tidy up the ordering in the cached version. Update the test to cover this behaviour. Also improve the comment about property syncing while we are here. Signed-off-by: Simon Glass --- tools/dtoc/fdt.py | 44 +++++++++++++++++++++++++++++++++++--------- tools/dtoc/test_fdt.py | 16 ++++++++++++++++ 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index a5e1d0b..63d1f68 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -503,9 +503,13 @@ class Node: auto_resize: Resize the device tree automatically if it does not have enough space for the update + Returns: + True if the node had to be added, False if it already existed + Raises: FdtException if auto_resize is False and there is not enough space """ + added = False if self._offset is None: # The subnode doesn't exist yet, so add it fdt_obj = self._fdt._fdt_obj @@ -519,23 +523,45 @@ class Node: else: offset = fdt_obj.add_subnode(self.parent._offset, self.name) self._offset = offset + added = True - # Sync subnodes in reverse so that we don't disturb node offsets for - # nodes that are earlier in the DT. This avoids an O(n^2) rescan of - # node offsets. + # Sync the existing subnodes first, so that we can rely on the offsets + # being correct. As soon as we add new subnodes, it pushes all the + # existing subnodes up. for node in reversed(self.subnodes): - node.Sync(auto_resize) + if node._offset is not None: + node.Sync(auto_resize) - # Sync properties now, whose offsets should not have been disturbed. - # We do this after subnodes, since this disturbs the offsets of these - # properties. Note that new properties will have an offset of None here, - # which Python 3 cannot sort against int. So use a large value instead - # to ensure that the new properties are added first. + # Sync subnodes in reverse so that we get the expected order. Each + # new node goes at the start of the subnode list. This avoids an O(n^2) + # rescan of node offsets. + num_added = 0 + for node in reversed(self.subnodes): + if node.Sync(auto_resize): + num_added += 1 + if num_added: + # Reorder our list of nodes to put the new ones first, since that's + # what libfdt does + old_count = len(self.subnodes) - num_added + subnodes = self.subnodes[old_count:] + self.subnodes[:old_count] + self.subnodes = subnodes + + # Sync properties now, whose offsets should not have been disturbed, + # since properties come before subnodes. This is done after all the + # subnode processing above, since updating properties can disturb the + # offsets of those subnodes. + # Properties are synced in reverse order, with new properties added + # before existing properties are synced. This ensures that the offsets + # of earlier properties are not disturbed. + # Note that new properties will have an offset of None here, which + # Python cannot sort against int. So use a large value instead so that + # new properties are added first. prop_list = sorted(self.props.values(), key=lambda prop: prop._offset or 1 << 31, reverse=True) for prop in prop_list: prop.Sync(auto_resize) + return added class Fdt: diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py index 1e66e1b..49a2853 100755 --- a/tools/dtoc/test_fdt.py +++ b/tools/dtoc/test_fdt.py @@ -237,6 +237,22 @@ class TestNode(unittest.TestCase): """Test adding various subnode and properies""" node = self.dtb.GetNode('/i2c@0') + # Add one more node next to the pmic one + sn1 = node.AddSubnode('node-one') + sn1.AddInt('integer-a', 12) + sn1.AddInt('integer-b', 23) + + # Sync so that everything is clean + self.dtb.Sync(auto_resize=True) + + # Add two subnodes next to pmic and node-one + sn2 = node.AddSubnode('node-two') + sn2.AddInt('integer-2a', 34) + sn2.AddInt('integer-2b', 45) + + sn3 = node.AddSubnode('node-three') + sn3.AddInt('integer-3', 123) + # Add a property to the node after i2c@0 to check that this is not # disturbed by adding a subnode to i2c@0 orig_node = self.dtb.GetNode('/orig-node') -- cgit v1.1 From 5d1bec30efcd1d0e74643a54a348718e8f79fc92 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sun, 21 Mar 2021 18:24:39 +1300 Subject: dtoc: Add new check that offsets are correct Add a few more internal checks to make sure offsets are correct, before updating the dtb. To make this easier, update the functions which add a property to return that property,. Signed-off-by: Simon Glass --- tools/dtoc/fdt.py | 27 ++++++++++++++++++++++++--- tools/dtoc/test_fdt.py | 16 ++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/tools/dtoc/fdt.py b/tools/dtoc/fdt.py index 63d1f68..3996971 100644 --- a/tools/dtoc/fdt.py +++ b/tools/dtoc/fdt.py @@ -233,6 +233,11 @@ class Prop: if self.dirty: node = self._node fdt_obj = node._fdt._fdt_obj + node_name = fdt_obj.get_name(node._offset) + if node_name and node_name != node.name: + raise ValueError("Internal error, node '%s' name mismatch '%s'" % + (node.path, node_name)) + if auto_resize: while fdt_obj.setprop(node.Offset(), self.name, self.bytes, (libfdt.NOSPACE,)) == -libfdt.NOSPACE: @@ -328,6 +333,11 @@ class Node: fdt_obj = self._fdt._fdt_obj if self._offset != my_offset: self._offset = my_offset + name = fdt_obj.get_name(self._offset) + if name and self.name != name: + raise ValueError("Internal error, node '%s' name mismatch '%s'" % + (self.path, name)) + offset = fdt_obj.first_subnode(self._offset, QUIET_NOTFOUND) for subnode in self.subnodes: if subnode.name != fdt_obj.get_name(offset): @@ -451,8 +461,13 @@ class Node: Args: prop_name: Name of property to add val: Bytes value of property + + Returns: + Prop added """ - self.props[prop_name] = Prop(self, None, prop_name, val) + prop = Prop(self, None, prop_name, val) + self.props[prop_name] = prop + return prop def AddString(self, prop_name, val): """Add a new string property to a node @@ -463,9 +478,12 @@ class Node: Args: prop_name: Name of property to add val: String value of property + + Returns: + Prop added """ val = bytes(val, 'utf-8') - self.AddData(prop_name, val + b'\0') + return self.AddData(prop_name, val + b'\0') def AddInt(self, prop_name, val): """Add a new integer property to a node @@ -476,8 +494,11 @@ class Node: Args: prop_name: Name of property to add val: Integer value of property + + Returns: + Prop added """ - self.AddData(prop_name, struct.pack('>I', val)) + return self.AddData(prop_name, struct.pack('>I', val)) def AddSubnode(self, name): """Add a new subnode to the node diff --git a/tools/dtoc/test_fdt.py b/tools/dtoc/test_fdt.py index 49a2853..856392b 100755 --- a/tools/dtoc/test_fdt.py +++ b/tools/dtoc/test_fdt.py @@ -265,6 +265,22 @@ class TestNode(unittest.TestCase): self.dtb.Sync(auto_resize=True) + def testRefreshNameMismatch(self): + """Test name mismatch when syncing nodes and properties""" + prop = self.node.AddInt('integer-a', 12) + + wrong_offset = self.dtb.GetNode('/i2c@0')._offset + self.node._offset = wrong_offset + with self.assertRaises(ValueError) as e: + self.dtb.Sync() + self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'", + str(e.exception)) + + with self.assertRaises(ValueError) as e: + self.node.Refresh(wrong_offset) + self.assertIn("Internal error, node '/spl-test' name mismatch 'i2c@0'", + str(e.exception)) + class TestProp(unittest.TestCase): """Test operation of the Prop class""" -- cgit v1.1 From 346df7d4fa62afc578d820b3a18815eec765074f Mon Sep 17 00:00:00 2001 From: T Karthik Reddy Date: Wed, 17 Mar 2021 12:31:30 +0100 Subject: spi: spi-uclass: Add support to manually relocate spi memory ops Add spi memory operations to relocate manually when CONFIG_NEEDS_MANUAL_RELOC is enabled. Signed-off-by: T Karthik Reddy Acked-by: Ashok Reddy Soma Signed-off-by: Michal Simek Reviewed-by: Pratyush Yadav --- drivers/spi/spi-uclass.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 7155d4a..ee30110 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -199,6 +200,16 @@ static int spi_post_probe(struct udevice *bus) ops->set_mode += gd->reloc_off; if (ops->cs_info) ops->cs_info += gd->reloc_off; + if (ops->mem_ops) { + struct spi_controller_mem_ops *mem_ops = + (struct spi_controller_mem_ops *)ops->mem_ops; + if (mem_ops->adjust_op_size) + mem_ops->adjust_op_size += gd->reloc_off; + if (mem_ops->supports_op) + mem_ops->supports_op += gd->reloc_off; + if (mem_ops->exec_op) + mem_ops->exec_op += gd->reloc_off; + } reloc_done++; } #endif -- cgit v1.1 From e5021221db3faf7e90a295d6eb045fbf5c6a908b Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 23 Mar 2021 12:37:47 +0100 Subject: sandbox: define __dyn_sym_start, dyn_sym_end On RISC-V the symbols __dyn_sym_start, dyn_sym_end are referenced in efi_runtime_relocate(). Signed-off-by: Heinrich Schuchardt Reviewed-by: Simon Glass --- arch/sandbox/cpu/u-boot.lds | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/sandbox/cpu/u-boot.lds b/arch/sandbox/cpu/u-boot.lds index 936da5e..a1f509c 100644 --- a/arch/sandbox/cpu/u-boot.lds +++ b/arch/sandbox/cpu/u-boot.lds @@ -44,6 +44,13 @@ SECTIONS { *(.__efi_runtime_rel_stop) } + + .dynsym : + { + __dyn_sym_start = .; + *(.dynsym) + __dyn_sym_end = .; + } } INSERT BEFORE .data; -- cgit v1.1