diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/Makefile | 1 | ||||
-rw-r--r-- | doc/arch/sandbox.rst | 52 | ||||
-rw-r--r-- | doc/arch/x86.rst | 4 | ||||
-rw-r--r-- | doc/board/emulation/qemu_capsule_update.rst | 4 | ||||
-rw-r--r-- | doc/board/google/chromebook_coral.rst | 234 | ||||
-rw-r--r-- | doc/chromium/chainload.rst (renamed from doc/README.chromium-chainload) | 80 | ||||
-rw-r--r-- | doc/chromium/files/chromebook_jerry.its (renamed from doc/chromium/chromebook_jerry.its) | 0 | ||||
-rw-r--r-- | doc/chromium/files/devkeys/kernel.keyblock (renamed from doc/chromium/devkeys/kernel.keyblock) | bin | 1208 -> 1208 bytes | |||
-rw-r--r-- | doc/chromium/files/devkeys/kernel_data_key.vbprivk (renamed from doc/chromium/devkeys/kernel_data_key.vbprivk) | bin | 1199 -> 1199 bytes | |||
-rw-r--r-- | doc/chromium/files/nyan-big.its (renamed from doc/chromium/nyan-big.its) | 0 | ||||
-rw-r--r-- | doc/chromium/index.rst | 14 | ||||
-rw-r--r-- | doc/chromium/overview.rst | 74 | ||||
-rw-r--r-- | doc/chromium/run_vboot.rst (renamed from doc/README.chromium) | 90 | ||||
-rw-r--r-- | doc/develop/driver-model/bind.rst (renamed from doc/driver-model/bind.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/debugging.rst (renamed from doc/driver-model/debugging.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/design.rst (renamed from doc/driver-model/design.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/ethernet.rst (renamed from doc/driver-model/ethernet.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/fdt-fixup.rst (renamed from doc/driver-model/fdt-fixup.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/fs_firmware_loader.rst (renamed from doc/driver-model/fs_firmware_loader.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/i2c-howto.rst (renamed from doc/driver-model/i2c-howto.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/index.rst (renamed from doc/driver-model/index.rst) | 4 | ||||
-rw-r--r-- | doc/develop/driver-model/livetree.rst (renamed from doc/driver-model/livetree.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/migration.rst (renamed from doc/driver-model/migration.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/of-plat.rst | 913 | ||||
-rw-r--r-- | doc/develop/driver-model/pci-info.rst (renamed from doc/driver-model/pci-info.rst) | 1 | ||||
-rw-r--r-- | doc/develop/driver-model/pmic-framework.rst (renamed from doc/driver-model/pmic-framework.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/remoteproc-framework.rst (renamed from doc/driver-model/remoteproc-framework.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/serial-howto.rst (renamed from doc/driver-model/serial-howto.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/soc-framework.rst (renamed from doc/driver-model/soc-framework.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/spi-howto.rst (renamed from doc/driver-model/spi-howto.rst) | 0 | ||||
-rw-r--r-- | doc/develop/driver-model/usb-info.rst (renamed from doc/driver-model/usb-info.rst) | 0 | ||||
-rw-r--r-- | doc/develop/index.rst | 12 | ||||
-rw-r--r-- | doc/develop/logging.rst | 31 | ||||
l--------- | doc/develop/package/binman.rst | 1 | ||||
l--------- | doc/develop/package/entries.rst | 1 | ||||
-rw-r--r-- | doc/develop/package/index.rst | 19 | ||||
-rw-r--r-- | doc/develop/py_testing.rst | 3 | ||||
-rw-r--r-- | doc/develop/testing.rst | 46 | ||||
-rw-r--r-- | doc/develop/tests_sandbox.rst | 209 | ||||
-rw-r--r-- | doc/develop/tests_writing.rst | 346 | ||||
-rw-r--r-- | doc/develop/uefi/index.rst (renamed from doc/uefi/index.rst) | 4 | ||||
-rw-r--r-- | doc/develop/uefi/iscsi.rst (renamed from doc/uefi/iscsi.rst) | 0 | ||||
-rw-r--r-- | doc/develop/uefi/u-boot_on_efi.rst (renamed from doc/uefi/u-boot_on_efi.rst) | 0 | ||||
-rw-r--r-- | doc/develop/uefi/uefi.rst (renamed from doc/uefi/uefi.rst) | 2 | ||||
-rw-r--r-- | doc/device-tree-bindings/sysinfo/google,coral.txt | 37 | ||||
-rw-r--r-- | doc/driver-model/of-plat.rst | 359 | ||||
-rw-r--r-- | doc/index.rst | 31 | ||||
-rw-r--r-- | doc/usage/fit.rst | 8 | ||||
-rw-r--r-- | doc/usage/index.rst | 4 | ||||
-rw-r--r-- | doc/usage/md.rst | 106 | ||||
-rw-r--r-- | doc/usage/scp03.rst | 33 | ||||
-rw-r--r-- | doc/usage/x86/cbsysinfo.rst | 25 |
52 files changed, 2213 insertions, 535 deletions
diff --git a/doc/Makefile b/doc/Makefile index a686d4728e..683e4b5609 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -56,7 +56,6 @@ quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4) PYTHONDONTWRITEBYTECODE=1 \ BUILDDIR=$(abspath $(BUILDDIR)) SPHINX_CONF=$(abspath $(srctree)/$(src)/$5/$(SPHINX_CONF)) \ $(SPHINXBUILD) \ - -W \ -b $2 \ -c $(abspath $(srctree)/$(src)) \ -d $(abspath $(BUILDDIR)/.doctrees/$3) \ diff --git a/doc/arch/sandbox.rst b/doc/arch/sandbox.rst index 60ee1e0741..e052b6bdb0 100644 --- a/doc/arch/sandbox.rst +++ b/doc/arch/sandbox.rst @@ -17,6 +17,12 @@ of the sandbox U-Boot. The purpose of running U-Boot under Linux is to test all the generic code, not specific to any one architecture. The idea is to create unit tests which we can run to test this upper level code. +Sandbox allows development of many types of new features in a traditional way, +rather than needing to test each iteration on real hardware. Many U-Boot +features were developed on sandbox, including the core driver model, most +uclasses, verified boot, bloblist, logging and dozens of others. Sandbox has +enabled many large-scale code refactors as well. + CONFIG_SANDBOX is defined when building a native board. The board name is 'sandbox' but the vendor name is unset, so there is a @@ -76,7 +82,7 @@ console:: You can issue commands as your would normally. If the command you want is not supported you can add it to include/configs/sandbox.h. -To exit, type 'reset' or press Ctrl-C. +To exit, type 'poweroff' or press Ctrl-C. Console / LCD support @@ -383,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 @@ -486,42 +494,10 @@ Testing ------- U-Boot sandbox can be used to run various tests, mostly in the test/ -directory. These include: - -command_ut: - Unit tests for command parsing and handling -compression: - Unit tests for U-Boot's compression algorithms, useful for - security checking. It supports gzip, bzip2, lzma and lzo. -driver model: - Run this pytest:: - - ./test/py/test.py --bd sandbox --build -k ut_dm -v - -image: - Unit tests for images: - test/image/test-imagetools.sh - multi-file images - test/image/test-fit.py - FIT images -tracing: - test/trace/test-trace.sh tests the tracing system (see README.trace) -verified boot: - See test/vboot/vboot_test.sh for this - -If you change or enhance any of the above subsystems, you shold write or -expand a test and include it with your patch series submission. Test -coverage in U-Boot is limited, as we need to work to improve it. - -Note that many of these tests are implemented as commands which you can -run natively on your board if desired (and enabled). - -To run all tests use "make check". - -To run a single test in an existing sandbox build, you can use -T to use the -test device tree, and -c to select the test: - - /tmp/b/sandbox/u-boot -T -c "ut dm pci_busdev" +directory. -This runs dm_test_pci_busdev() which is in test/dm/pci.c +See :doc:`../develop/tests_sandbox` for more information and +:doc:`../develop/testing` for information about testing generally. Memory Map @@ -537,5 +513,7 @@ Addr Config Usage e000 CONFIG_BLOBLIST_ADDR Blob list 10000 CONFIG_MALLOC_F_ADDR Early memory allocation f0000 CONFIG_PRE_CON_BUF_ADDR Pre-console buffer - 100000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled) + 100000 CONFIG_TRACE_EARLY_ADDR Early trace buffer (if enabled). Also used + as the SPL load buffer in spl_test_load(). + 200000 CONFIG_SYS_TEXT_BASE Load buffer for U-Boot (sandbox_spl only) ======= ======================== =============================== diff --git a/doc/arch/x86.rst b/doc/arch/x86.rst index cc307aa8d5..2ebfed871b 100644 --- a/doc/arch/x86.rst +++ b/doc/arch/x86.rst @@ -709,8 +709,8 @@ to load a 'u-boot-payload.efi', see below test logs on QEMU. No controllers found Hit any key to stop autoboot: 0 -See :doc:`../uefi/u-boot_on_efi` and :doc:`../uefi/uefi` for details of -EFI support in U-Boot. +See :doc:`../develop/uefi/u-boot_on_efi` and :doc:`../develop/uefi/uefi` for +details of EFI support in U-Boot. Chain-loading ------------- diff --git a/doc/board/emulation/qemu_capsule_update.rst b/doc/board/emulation/qemu_capsule_update.rst index 9fec75f8f1..33ce4bcd32 100644 --- a/doc/board/emulation/qemu_capsule_update.rst +++ b/doc/board/emulation/qemu_capsule_update.rst @@ -60,7 +60,7 @@ to be pointing to the EFI System Partition which contains the capsule file. The BootNext, BootXXXX and OsIndications variables can be set using the following commands:: - => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name> + => efidebug boot add -b 0 Boot0000 virtio 0:1 <capsule_file_name> => efidebug boot next 0 => setenv -e -nv -bs -rt -v OsIndications =0x04 => saveenv @@ -198,7 +198,7 @@ command line:: 3. Set the following environment and UEFI boot variables => setenv -e -nv -bs -rt -v OsIndications =0x04 - => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name> + => efidebug boot add -b 0 Boot0000 virtio 0:1 <capsule_file_name> => efidebug boot next 0 => saveenv diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst index c39f1e310c..4b585678dc 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 <NULL> + 0 a0000 RAM + a0000 60000 Reserved + 7b000000 800000 Reserved + 7b800000 4800000 Reserved + 7ac00000 400000 Reserved + 100000 ff00000 RAM + 10000000 2151000 Reserved + 12151000 68aaf000 RAM + 100000000 80000000 RAM + e0000000 10000000 Reserved + 7991bfd0 12e4030 Reserved + d0000000 10000000 Reserved + fed10000 8000 Reserved + Setup sectors : 1e + Root flags : 1 + Sys size : 63420 + RAM size : 0 + Video mode : ffff + Root dev : 0 + Boot flag : 0 + Jump : 66eb + Header : 53726448 + Kernel V2 + Version : 20d + Real mode switch : 0 + Start sys : 1000 + Kernel version : 38cc + @00003acc: + Type of loader : 80 + U-Boot, version 0 + Load flags : 81 + : loaded-high can-use-heap + Setup move size : 8000 + Code32 start : 100000 + Ramdisk image : 0 + Ramdisk size : 0 + Bootsect kludge : 0 + Heap end ptr : 8e00 + Ext loader ver : 0 + Ext loader type : 0 + Command line ptr : 99000 + console= loglevel=7 init=/sbin/init cros_secure oops=panic panic=-1 root=PARTUUID=35c775e7-3735-d745-93e5-d9e0238f7ed0/PARTNROFF=1 rootwait rw dm_verity.error_behavior=3 dm_verity.max_bios=-1 dm_verity.dev_wait=0 dm="1 vroot none rw 1,0 3788800 verity payload=ROOT_DEV hashtree=HASH_DEV hashstart=3788800 alg=sha1 root_hexdigest=55052b629d3ac889f25a9583ea12cdcd3ea15ff8 salt=a2d4d9e574069f4fed5e3961b99054b7a4905414b60a25d89974a7334021165c" noinitrd vt.global_cursor_default=0 kern_guid=35c775e7-3735-d745-93e5-d9e0238f7ed0 add_efi_memmap boot=local noresume noswap i915.modeset=1 tpm_tis.force=1 tpm_tis.interrupts=0 nmi_watchdog=panic,lapic disablevmx=off + Initrd addr max : 7fffffff + Kernel alignment : 200000 + Relocatable kernel : 1 + Min alignment : 15 + : 200000 + Xload flags : 3 + : 64-bit-entry can-load-above-4gb + Cmdline size : 7ff + Hardware subarch : 0 + HW subarch data : 0 + Payload offset : 26e + Payload length : 612045 + Setup data : 0 + Pref address : 1000000 + Init size : 1383000 + Handover offset : 0 + + Starting kernel ... + + Timer summary in microseconds (17 records): + Mark Elapsed Stage + 0 0 reset + 155,279 155,279 TPL + 237,088 81,809 end phase + 237,533 445 SPL + 816,456 578,923 end phase + 817,357 901 board_init_f + 1,061,751 244,394 board_init_r + 1,402,435 340,684 id=64 + 1,430,071 27,636 main_loop + 5,532,057 4,101,986 start_kernel + + Accumulated time: + 685 dm_r + 2,817 fast_spi + 33,095 dm_spl + 52,468 dm_f + 208,242 fsp-m + 242,221 fsp-s + 332,710 mmap_spi + + Boot flow - TPL --------------- @@ -181,7 +344,7 @@ Partial memory map ff000000 Bottom of ROM fefc0000 Top of CAR region fef96000 Stack for FSP-M - fef40000 59000 FSP-M + fef40000 59000 FSP-M (also VPL loads here) fef11000 SPL loaded here fef10000 CONFIG_BLOBLIST_ADDR fef10000 Stack top in TPL, SPL and U-Boot before relocation @@ -195,35 +358,72 @@ Partial memory map 1110000 CONFIG_SYS_TEXT_BASE +Speeding up SPL for development +------------------------------- + +The 21-second wait for memory training is annoying during development, since +every new image incurs this cost when booting. There is no cache to fall back on +since that area of the image is empty on start-up. + +You can add suitable cache contents to the image to fix this, for development +purposes only, like this:: + + # Read the image back after booting through SPL + em100 -s -c w25q128fw -u image.bin + + # Extract the two cache regions + binman extract -i image.bin extra *cache + + # Move them into the source directory + mv *cache board/google/chromebook_coral + +Then add something like this to the devicetree:: + + #if IS_ENABLED(CONFIG_HAVE_MRC) || IS_ENABLED(CONFIG_FSP_VERSION2) + /* Provide initial contents of the MRC data for faster development */ + rw-mrc-cache { + type = "blob"; + /* Mirror the offset in spi-flash@0 */ + offset = <0xff8e0000>; + size = <0x10000>; + filename = "board/google/chromebook_coral/rw-mrc-cache"; + }; + rw-var-mrc-cache { + type = "blob"; + size = <0x1000>; + filename = "board/google/chromebook_coral/rw-var-mrc-cache"; + }; + #endif + +This tells binman to put the cache contents in the same place as the +`rw-mrc-cache` and `rw-var-mrc-cache` regions defined by the SPI-flash driver. + + Supported peripherals --------------------- -- UART -- SPI flash -- Video -- MMC (dev 0) and micro-SD (dev 1) -- Chrome OS EC -- Keyboard -- USB +The following have U-Boot drivers: + + - UART + - SPI flash + - Video + - MMC (dev 0) and micro-SD (dev 1) + - Chrome OS EC + - Cr50 (security chip) + - Keyboard + - USB To do ----- - Finish peripherals - - left-side USB - - USB-C - - Cr50 (security chip: a basic driver is running but not included here) - Sound (Intel I2S support exists, but need da7219 driver) - - Various minor features supported by LPC, etc. -- Booting Chrome OS, e.g. with verified boot -- Integrate with Chrome OS vboot -- Improvements to booting from coreboot (i.e. as a coreboot target) - Use FSP-T binary instead of our own CAR implementation - Use the official FSP package instead of the coreboot one -- Enable all CPU cores - Suspend / resume -- ACPI +- Fix MMC which seems to try to read even though the card is empty +- Fix USB3 crash "WARN halted endpoint, queueing URB anyway." Credits diff --git a/doc/README.chromium-chainload b/doc/chromium/chainload.rst index 45eaeced2d..7b6bb10d36 100644 --- a/doc/README.chromium-chainload +++ b/doc/chromium/chainload.rst @@ -1,3 +1,6 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2020 Google LLC + Running U-Boot from coreboot on Chromebooks =========================================== @@ -15,7 +18,7 @@ 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: +ARM:: sudo apt install gcc-arm-linux-gnueabi mkdir b @@ -37,14 +40,17 @@ https://www.chromium.org/chromium-os/firmware-porting-guide/using-nv-u-boot-on-t 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 +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 @@ -61,16 +67,21 @@ 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 +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/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 + 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 @@ -80,6 +91,8 @@ kernel, and crashes if it is not present. 5. Write U-Boot to the SD card +Steps:: + sudo dd if=u-boot.kpart of=/dev/sdc1; sync @@ -90,7 +103,7 @@ 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: +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) @@ -104,9 +117,9 @@ mode screen. It should show something like the following on the display: 7. Known problems -On the serial console the word MMC is chopped at the start of the line: +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 + 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()). @@ -116,7 +129,7 @@ during relocation (or perhaps updating the clock setup in board_init()). 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: +bytes of U-Boot:: hd u-boot-chromium.fit |head -20 ... @@ -141,34 +154,39 @@ The instruction are similar to those for Nyan with changes as noted below: Open include/configs/rk3288_common.h -Change: +Change:: -#define CONFIG_SYS_TEXT_BASE 0x00100000 + #define CONFIG_SYS_TEXT_BASE 0x00100000 -to: +to:: -#define CONFIG_SYS_TEXT_BASE 0x02000100 + #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 + 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 + 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 + 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 @@ -182,7 +200,7 @@ 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: +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) @@ -203,18 +221,18 @@ None as yet. Other notes -=========== +----------- flashrom --------- +~~~~~~~~ - Used to make a backup of your firmware, or to replace it. +Used to make a backup of your firmware, or to replace it. - See: https://www.chromium.org/chromium-os/packages/cros-flashrom +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 diff --git a/doc/chromium/chromebook_jerry.its b/doc/chromium/files/chromebook_jerry.its index 7505a20535..7505a20535 100644 --- a/doc/chromium/chromebook_jerry.its +++ b/doc/chromium/files/chromebook_jerry.its diff --git a/doc/chromium/devkeys/kernel.keyblock b/doc/chromium/files/devkeys/kernel.keyblock Binary files differindex 9740be4e60..9740be4e60 100644 --- a/doc/chromium/devkeys/kernel.keyblock +++ b/doc/chromium/files/devkeys/kernel.keyblock diff --git a/doc/chromium/devkeys/kernel_data_key.vbprivk b/doc/chromium/files/devkeys/kernel_data_key.vbprivk Binary files differindex 8d392fb294..8d392fb294 100644 --- a/doc/chromium/devkeys/kernel_data_key.vbprivk +++ b/doc/chromium/files/devkeys/kernel_data_key.vbprivk diff --git a/doc/chromium/nyan-big.its b/doc/chromium/files/nyan-big.its index bd412915e9..bd412915e9 100644 --- a/doc/chromium/nyan-big.its +++ b/doc/chromium/files/nyan-big.its diff --git a/doc/chromium/index.rst b/doc/chromium/index.rst new file mode 100644 index 0000000000..0722c25003 --- /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/overview.rst b/doc/chromium/overview.rst new file mode 100644 index 0000000000..5498ed9c16 --- /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 <https://2018.osfc.io/uploads/talk/paper/26/U-Boot_with_Chrome_OS_and_firmware_packaging.pdf>`_ + - Video on `Youtube <https://www.youtube.com/watch?v=1jknxUvmwpo>`_ + + - "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 <https://www.cnet.com/products/samsung-series-3-chromebook-xe303c12-11-6-exynos-5250-2-gb-ram-16-gb-ssd-bilingual-english-french/>`_ + with Samsung Exynos5250 `review <https://www.cnet.com/reviews/samsung-chromebook-series-3-review/>`_), + spring (`HP Chromebook 11 <https://www.cnet.com/products/hp-chromebook-11-g2-11-6-exynos-5250-4-gb-ram-16-gb-emmc/>`_) + and pit/pi (`Samsung Chromebook 2 <https://www.cnet.com/products/samsung-chromebook-2-xe503c12-11-6-exynos-5-octa-4-gb-ram-16-gb-ssd/>`_ + with Exynos 5 Octa 5420 in 2014). + - Slides at `Google research <https://research.google/pubs/pub42038/>`_ + - Video at `Youtube <https://www.youtube.com/watch?v=kdpZC9jFzZA>`_ + + - "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 <https://www.youtube.com/watch?v=WY2sWpuda2g>`_ + + - `Chromium OS U-Boot <https://www.chromium.org/developers/u-boot>`_ + + - `Firmware porting Guide <https://www.chromium.org/chromium-os/firmware-porting-guide>`_ diff --git a/doc/README.chromium b/doc/chromium/run_vboot.rst index 75f2f24042..41b4f63183 100644 --- a/doc/README.chromium +++ b/doc/chromium/run_vboot.rst @@ -1,42 +1,14 @@ -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. +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2020 Google LLC +.. sectionauthor:: Simon Glass <sjg@chromium.org> -U-Boot with Chromium OS verified boot -------------------------------------- +Running U-Boot with Chromium OS verified boot +============================================= -To obtain: +To obtain:: - git clone https://github.com/sglass68/u-boot.git + git clone https://github.com/sjg20/u-boot.git cd u-boot git checkout cros-master @@ -46,28 +18,35 @@ To obtain: git checkout 45964294 # futility: updater: Correct output version for Snow -To build for sandbox: +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 + 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: +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 $CROS/src/build/images/cheza/latest/chromiumos_image.bin; vboot go auto" \ - -l -w -s state.dtb -r + -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 + + - Install image.bin in the SPI flash of your device + - Boot your system Sandbox @@ -83,7 +62,7 @@ a device tree and binding a Chromium OS disk image for use to find kernels 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. +It is possible to run with debugging on, e.g.:: gdb --args $UB/tpl/u-boot-tpl -d .... @@ -95,7 +74,7 @@ Samus ----- Basic support is available for samus, using the chromeos_samus target. If you -have an em100, use: +have an em100, use:: sudo em100 -s -c W25Q128FW -d $UB/image.bin -t -r @@ -119,11 +98,20 @@ 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 +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. @@ -181,7 +169,7 @@ 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: +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 @@ -213,6 +201,4 @@ TO DO Get the full ACPI tables working with Coral -Simon Glass -sjg@chromium.org 7 October 2018 diff --git a/doc/driver-model/bind.rst b/doc/develop/driver-model/bind.rst index b19661b5fe..b19661b5fe 100644 --- a/doc/driver-model/bind.rst +++ b/doc/develop/driver-model/bind.rst diff --git a/doc/driver-model/debugging.rst b/doc/develop/driver-model/debugging.rst index bbb2794340..bbb2794340 100644 --- a/doc/driver-model/debugging.rst +++ b/doc/develop/driver-model/debugging.rst diff --git a/doc/driver-model/design.rst b/doc/develop/driver-model/design.rst index 4e5cecbab6..4e5cecbab6 100644 --- a/doc/driver-model/design.rst +++ b/doc/develop/driver-model/design.rst diff --git a/doc/driver-model/ethernet.rst b/doc/develop/driver-model/ethernet.rst index cdbccca34d..cdbccca34d 100644 --- a/doc/driver-model/ethernet.rst +++ b/doc/develop/driver-model/ethernet.rst diff --git a/doc/driver-model/fdt-fixup.rst b/doc/develop/driver-model/fdt-fixup.rst index 974c09031e..974c09031e 100644 --- a/doc/driver-model/fdt-fixup.rst +++ b/doc/develop/driver-model/fdt-fixup.rst diff --git a/doc/driver-model/fs_firmware_loader.rst b/doc/develop/driver-model/fs_firmware_loader.rst index a44708cb4c..a44708cb4c 100644 --- a/doc/driver-model/fs_firmware_loader.rst +++ b/doc/develop/driver-model/fs_firmware_loader.rst diff --git a/doc/driver-model/i2c-howto.rst b/doc/develop/driver-model/i2c-howto.rst index 27e7440cd4..27e7440cd4 100644 --- a/doc/driver-model/i2c-howto.rst +++ b/doc/develop/driver-model/i2c-howto.rst diff --git a/doc/driver-model/index.rst b/doc/develop/driver-model/index.rst index c9faf0a591..fd4575db9b 100644 --- a/doc/driver-model/index.rst +++ b/doc/develop/driver-model/index.rst @@ -3,6 +3,10 @@ Driver Model ============ +The following holds information on the U-Boot device driver framework: +driver-model, including the design details of itself and several driver +subsystems + .. toctree:: :maxdepth: 2 diff --git a/doc/driver-model/livetree.rst b/doc/develop/driver-model/livetree.rst index 9f654f3b89..9f654f3b89 100644 --- a/doc/driver-model/livetree.rst +++ b/doc/develop/driver-model/livetree.rst diff --git a/doc/driver-model/migration.rst b/doc/develop/driver-model/migration.rst index 8d0bb7635b..8d0bb7635b 100644 --- a/doc/driver-model/migration.rst +++ b/doc/develop/driver-model/migration.rst diff --git a/doc/develop/driver-model/of-plat.rst b/doc/develop/driver-model/of-plat.rst new file mode 100644 index 0000000000..74f1932473 --- /dev/null +++ b/doc/develop/driver-model/of-plat.rst @@ -0,0 +1,913 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Compiled-in Device Tree / Platform Data +======================================= + + +Introduction +------------ + +Device tree is the standard configuration method in U-Boot. It is used to +define what devices are in the system and provide configuration information +to these devices. + +The overhead of adding devicetree access to U-Boot is fairly modest, +approximately 3KB on Thumb 2 (plus the size of the DT itself). This means +that in most cases it is best to use devicetree for configuration. + +However there are some very constrained environments where U-Boot needs to +work. These include SPL with severe memory limitations. For example, some +SoCs require a 16KB SPL image which must include a full MMC stack. In this +case the overhead of devicetree access may be too great. + +It is possible to create platform data manually by defining C structures +for it, and reference that data in a `U_BOOT_DRVINFO()` declaration. This +bypasses the use of devicetree completely, effectively creating a parallel +configuration mechanism. But it is an available option for SPL. + +As an alternative, the 'of-platdata' feature is provided. This converts the +devicetree contents into C code which can be compiled into the SPL binary. +This saves the 3KB of code overhead and perhaps a few hundred more bytes due +to more efficient storage of the data. + + +How it works +------------ + +The feature is enabled by CONFIG OF_PLATDATA. This is only available in +SPL/TPL and should be tested with: + +.. code-block:: c + + #if CONFIG_IS_ENABLED(OF_PLATDATA) + +A tool called 'dtoc' converts a devicetree file either into a set of +struct declarations, one for each compatible node, and a set of +`U_BOOT_DRVINFO()` declarations along with the actual platform data for each +device. As an example, consider this MMC node: + +.. code-block:: none + + sdmmc: dwmmc@ff0c0000 { + compatible = "rockchip,rk3288-dw-mshc"; + clock-freq-min-max = <400000 150000000>; + clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, + <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; + clock-names = "biu", "ciu", "ciu_drv", "ciu_sample"; + fifo-depth = <0x100>; + interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; + reg = <0xff0c0000 0x4000>; + bus-width = <4>; + cap-mmc-highspeed; + cap-sd-highspeed; + card-detect-delay = <200>; + disable-wp; + num-slots = <1>; + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; + vmmc-supply = <&vcc_sd>; + status = "okay"; + u-boot,dm-pre-reloc; + }; + + +Some of these properties are dropped by U-Boot under control of the +CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce +the following C struct declaration: + +.. code-block:: c + + struct dtd_rockchip_rk3288_dw_mshc { + fdt32_t bus_width; + bool cap_mmc_highspeed; + bool cap_sd_highspeed; + fdt32_t card_detect_delay; + fdt32_t clock_freq_min_max[2]; + struct phandle_1_arg clocks[4]; + bool disable_wp; + fdt32_t fifo_depth; + fdt32_t interrupts[3]; + fdt32_t num_slots; + fdt32_t reg[2]; + fdt32_t vmmc_supply; + }; + +and the following device declarations: + +.. code-block:: c + + /* Node /clock-controller@ff760000 index 0 */ + ... + + /* Node /dwmmc@ff0c0000 index 2 */ + static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = { + .fifo_depth = 0x100, + .cap_sd_highspeed = true, + .interrupts = {0x0, 0x20, 0x4}, + .clock_freq_min_max = {0x61a80, 0x8f0d180}, + .vmmc_supply = 0xb, + .num_slots = 0x1, + .clocks = {{0, 456}, + {0, 68}, + {0, 114}, + {0, 118}}, + .cap_mmc_highspeed = true, + .disable_wp = true, + .bus_width = 0x4, + .u_boot_dm_pre_reloc = true, + .reg = {0xff0c0000, 0x4000}, + .card_detect_delay = 0xc8, + }; + + U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = { + .name = "rockchip_rk3288_dw_mshc", + .plat = &dtv_dwmmc_at_ff0c0000, + .plat_size = sizeof(dtv_dwmmc_at_ff0c0000), + .parent_idx = -1, + }; + +The device is then instantiated at run-time and the platform data can be +accessed using: + +.. code-block:: c + + struct udevice *dev; + struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev); + +This avoids the code overhead of converting the devicetree data to +platform data in the driver. The `of_to_plat()` method should +therefore do nothing in such a driver. + +Note that for the platform data to be matched with a driver, the 'name' +property of the `U_BOOT_DRVINFO()` declaration has to match a driver declared +via `U_BOOT_DRIVER()`. This effectively means that a `U_BOOT_DRIVER()` with a +'name' corresponding to the devicetree 'compatible' string (after converting +it to a valid name for C) is needed, so a dedicated driver is required for +each 'compatible' string. + +In order to make this a bit more flexible, the `DM_DRIVER_ALIAS()` macro can be +used to declare an alias for a driver name, typically a 'compatible' string. +This macro produces no code, but is used by dtoc tool. It must be located in the +same file as its associated driver, ideally just after it. + +The parent_idx is the index of the parent `driver_info` structure within its +linker list (instantiated by the `U_BOOT_DRVINFO()` macro). This is used to +support `dev_get_parent()`. + +During the build process dtoc parses both `U_BOOT_DRIVER()` and +`DM_DRIVER_ALIAS()` to build a list of valid driver names and driver aliases. +If the 'compatible' string used for a device does not not match a valid driver +name, it will be checked against the list of driver aliases in order to get the +right driver name to use. If in this step there is no match found a warning is +issued to avoid run-time failures. + +Where a node has multiple compatible strings, dtoc generates a `#define` to +make them equivalent, e.g.: + +.. code-block:: c + + #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc + + +Converting of-platdata to a useful form +--------------------------------------- + +Of course it would be possible to use the of-platdata directly in your driver +whenever configuration information is required. However this means that the +driver will not be able to support devicetree, since the of-platdata +structure is not available when devicetree is used. It would make no sense +to use this structure if devicetree were available, since the structure has +all the limitations metioned in caveats below. + +Therefore it is recommended that the of-platdata structure should be used +only in the `probe()` method of your driver. It cannot be used in the +`of_to_plat()` method since this is not called when platform data is +already present. + + +How to structure your driver +---------------------------- + +Drivers should always support devicetree as an option. The of-platdata +feature is intended as a add-on to existing drivers. + +Your driver should convert the plat struct in its `probe()` method. The +existing devicetree decoding logic should be kept in the +`of_to_plat()` method and wrapped with `#if`. + +For example: + +.. code-block:: c + + #include <dt-structs.h> + + struct mmc_plat { + #if CONFIG_IS_ENABLED(OF_PLATDATA) + /* Put this first since driver model will copy the data here */ + struct dtd_mmc dtplat; + #endif + /* + * Other fields can go here, to be filled in by decoding from + * the devicetree (or the C structures when of-platdata is used). + */ + int fifo_depth; + }; + + static int mmc_of_to_plat(struct udevice *dev) + { + #if !CONFIG_IS_ENABLED(OF_PLATDATA) + /* Decode the devicetree data */ + struct mmc_plat *plat = dev_get_plat(dev); + const void *blob = gd->fdt_blob; + int node = dev_of_offset(dev); + + plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0); + #endif + + return 0; + } + + static int mmc_probe(struct udevice *dev) + { + struct mmc_plat *plat = dev_get_plat(dev); + + #if CONFIG_IS_ENABLED(OF_PLATDATA) + /* Decode the of-platdata from the C structures */ + struct dtd_mmc *dtplat = &plat->dtplat; + + plat->fifo_depth = dtplat->fifo_depth; + #endif + /* Set up the device from the plat data */ + writel(plat->fifo_depth, ...) + } + + static const struct udevice_id mmc_ids[] = { + { .compatible = "vendor,mmc" }, + { } + }; + + U_BOOT_DRIVER(mmc_drv) = { + .name = "mmc_drv", + .id = UCLASS_MMC, + .of_match = mmc_ids, + .of_to_plat = mmc_of_to_plat, + .probe = mmc_probe, + .priv_auto = sizeof(struct mmc_priv), + .plat_auto = sizeof(struct mmc_plat), + }; + + DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */ + +Note that `struct mmc_plat` is defined in the C file, not in a header. This +is to avoid needing to include dt-structs.h in a header file. The idea is to +keep the use of each of-platdata struct to the smallest possible code area. +There is just one driver C file for each struct, that can convert from the +of-platdata struct to the standard one used by the driver. + +In the case where SPL_OF_PLATDATA is enabled, `plat_auto` is +still used to allocate space for the platform data. This is different from +the normal behaviour and is triggered by the use of of-platdata (strictly +speaking it is a non-zero `plat_size` which triggers this). + +The of-platdata struct contents is copied from the C structure data to the +start of the newly allocated area. In the case where devicetree is used, +the platform data is allocated, and starts zeroed. In this case the +`of_to_plat()` method should still set up the platform data (and the +of-platdata struct will not be present). + +SPL must use either of-platdata or devicetree. Drivers cannot use both at +the same time, but they must support devicetree. Supporting of-platdata is +optional. + +The devicetree becomes inaccessible when CONFIG_SPL_OF_PLATDATA is enabled, +since the devicetree access code is not compiled in. A corollary is that +a board can only move to using of-platdata if all the drivers it uses support +it. There would be little point in having some drivers require the device +tree data, since then libfdt would still be needed for those drivers and +there would be no code-size benefit. + + +Build-time instantiation +------------------------ + +Even with of-platdata there is a fair amount of code required in driver model. +It is possible to have U-Boot handle the instantiation of devices at build-time, +so avoiding the need for the `device_bind()` code and some parts of +`device_probe()`. + +The feature is enabled by CONFIG_OF_PLATDATA_INST. + +Here is an example device, as generated by dtoc:: + + /* + * Node /serial index 6 + * driver sandbox_serial parent root_driver + */ + + #include <asm/serial.h> + struct sandbox_serial_plat __attribute__ ((section (".priv_data"))) + _sandbox_serial_plat_serial = { + .dtplat = { + .sandbox_text_colour = "cyan", + }, + }; + #include <asm/serial.h> + u8 _sandbox_serial_priv_serial[sizeof(struct sandbox_serial_priv)] + __attribute__ ((section (".priv_data"))); + #include <serial.h> + u8 _sandbox_serial_uc_priv_serial[sizeof(struct serial_dev_priv)] + __attribute__ ((section (".priv_data"))); + + DM_DEVICE_INST(serial) = { + .driver = DM_DRIVER_REF(sandbox_serial), + .name = "sandbox_serial", + .plat_ = &_sandbox_serial_plat_serial, + .priv_ = _sandbox_serial_priv_serial, + .uclass = DM_UCLASS_REF(serial), + .uclass_priv_ = _sandbox_serial_uc_priv_serial, + .uclass_node = { + .prev = &DM_UCLASS_REF(serial)->dev_head, + .next = &DM_UCLASS_REF(serial)->dev_head, + }, + .child_head = { + .prev = &DM_DEVICE_REF(serial)->child_head, + .next = &DM_DEVICE_REF(serial)->child_head, + }, + .sibling_node = { + .prev = &DM_DEVICE_REF(i2c_at_0)->sibling_node, + .next = &DM_DEVICE_REF(spl_test)->sibling_node, + }, + .seq_ = 0, + }; + +Here is part of the driver, for reference:: + + static const struct udevice_id sandbox_serial_ids[] = { + { .compatible = "sandbox,serial" }, + { } + }; + + U_BOOT_DRIVER(sandbox_serial) = { + .name = "sandbox_serial", + .id = UCLASS_SERIAL, + .of_match = sandbox_serial_ids, + .of_to_plat = sandbox_serial_of_to_plat, + .plat_auto = sizeof(struct sandbox_serial_plat), + .priv_auto = sizeof(struct sandbox_serial_priv), + .probe = sandbox_serial_probe, + .remove = sandbox_serial_remove, + .ops = &sandbox_serial_ops, + .flags = DM_FLAG_PRE_RELOC, + }; + + +The `DM_DEVICE_INST()` macro declares a struct udevice so you can see that the +members are from that struct. The private data is declared immediately above, +as `_sandbox_serial_priv_serial`, so there is no need for run-time memory +allocation. The #include lines are generated as well, since dtoc searches the +U-Boot source code for the definition of `struct sandbox_serial_priv` and adds +the relevant header so that the code will compile without errors. + +The `plat_` member is set to the dtv data which is declared immediately above +the device. This is similar to how it would look without of-platdata-inst, but +node that the `dtplat` member inside is part of the wider +`_sandbox_serial_plat_serial` struct. This is because the driver declares its +own platform data, and the part generated by dtoc can only be a portion of it. +The `dtplat` part is always first in the struct. If the device has no +`.plat_auto` field, then a simple dtv struct can be used as with this example:: + + static struct dtd_sandbox_clk dtv_clk_sbox = { + .assigned_clock_rates = 0x141, + .assigned_clocks = {0x7, 0x3}, + }; + + #include <asm/clk.h> + u8 _sandbox_clk_priv_clk_sbox[sizeof(struct sandbox_clk_priv)] + __attribute__ ((section (".priv_data"))); + + DM_DEVICE_INST(clk_sbox) = { + .driver = DM_DRIVER_REF(sandbox_clk), + .name = "sandbox_clk", + .plat_ = &dtv_clk_sbox, + +Here is part of the driver, for reference:: + + static const struct udevice_id sandbox_clk_ids[] = { + { .compatible = "sandbox,clk" }, + { } + }; + + U_BOOT_DRIVER(sandbox_clk) = { + .name = "sandbox_clk", + .id = UCLASS_CLK, + .of_match = sandbox_clk_ids, + .ops = &sandbox_clk_ops, + .probe = sandbox_clk_probe, + .priv_auto = sizeof(struct sandbox_clk_priv), + }; + + +You can see that `dtv_clk_sbox` just has the devicetree contents and there is +no need for the `dtplat` separation, since the driver has no platform data of +its own, besides that provided by the devicetree (i.e. no `.plat_auto` field). + +The doubly linked lists are handled by explicitly declaring the value of each +node, as you can see with the `.prev` and `.next` values in the example above. +Since dtoc knows the order of devices it can link them into the appropriate +lists correctly. + +One of the features of driver model is the ability for a uclass to have a +small amount of private data for each device in that uclass. This is used to +provide a generic data structure that the uclass can use for all devices, thus +allowing generic features to be implemented in common code. An example is I2C, +which stores the bus speed there. + +Similarly, parent devices can have data associated with each of their children. +This is used to provide information common to all children of a particular bus. +For an I2C bus, this is used to store the I2C address of each child on the bus. + +This is all handled automatically by dtoc:: + + #include <asm/i2c.h> + u8 _sandbox_i2c_priv_i2c_at_0[sizeof(struct sandbox_i2c_priv)] + __attribute__ ((section (".priv_data"))); + #include <i2c.h> + u8 _sandbox_i2c_uc_priv_i2c_at_0[sizeof(struct dm_i2c_bus)] + __attribute__ ((section (".priv_data"))); + + DM_DEVICE_INST(i2c_at_0) = { + .driver = DM_DRIVER_REF(sandbox_i2c), + .name = "sandbox_i2c", + .plat_ = &dtv_i2c_at_0, + .priv_ = _sandbox_i2c_priv_i2c_at_0, + .uclass = DM_UCLASS_REF(i2c), + .uclass_priv_ = _sandbox_i2c_uc_priv_i2c_at_0, + ... + +Part of driver, for reference:: + + static const struct udevice_id sandbox_i2c_ids[] = { + { .compatible = "sandbox,i2c" }, + { } + }; + + U_BOOT_DRIVER(sandbox_i2c) = { + .name = "sandbox_i2c", + .id = UCLASS_I2C, + .of_match = sandbox_i2c_ids, + .ops = &sandbox_i2c_ops, + .priv_auto = sizeof(struct sandbox_i2c_priv), + }; + +Part of I2C uclass, for reference:: + + UCLASS_DRIVER(i2c) = { + .id = UCLASS_I2C, + .name = "i2c", + .flags = DM_UC_FLAG_SEQ_ALIAS, + .post_bind = i2c_post_bind, + .pre_probe = i2c_pre_probe, + .post_probe = i2c_post_probe, + .per_device_auto = sizeof(struct dm_i2c_bus), + .per_child_plat_auto = sizeof(struct dm_i2c_chip), + .child_post_bind = i2c_child_post_bind, + }; + +Here, `_sandbox_i2c_uc_priv_i2c_at_0` is required by the uclass but is declared +in the device, as required by driver model. The required header file is included +so that the code will compile without errors. A similar mechanism is used for +child devices, but is not shown by this example. + +It would not be that useful to avoid binding devices but still need to allocate +uclasses at runtime. So dtoc generates uclass instances as well:: + + struct list_head uclass_head = { + .prev = &DM_UCLASS_REF(serial)->sibling_node, + .next = &DM_UCLASS_REF(clk)->sibling_node, + }; + + DM_UCLASS_INST(clk) = { + .uc_drv = DM_UCLASS_DRIVER_REF(clk), + .sibling_node = { + .prev = &uclass_head, + .next = &DM_UCLASS_REF(i2c)->sibling_node, + }, + .dev_head = { + .prev = &DM_DEVICE_REF(clk_sbox)->uclass_node, + .next = &DM_DEVICE_REF(clk_fixed)->uclass_node, + }, + }; + +At the top is the list head. Driver model uses this on start-up, instead of +creating its own. + +Below that are a set of `DM_UCLASS_INST()` macros, each declaring a +`struct uclass`. The doubly linked lists work as for devices. + +All private data is placed into a `.priv_data` section so that it is contiguous +in the resulting output binary. + + +Indexes +------- + +U-Boot stores drivers, devices and many other things in linker_list structures. +These are sorted by name, so dtoc knows the order that they will appear when +the linker runs. Each driver_info / udevice is referenced by its index in the +linker_list array, called 'idx' in the code. + +When CONFIG_OF_PLATDATA_INST is enabled, idx is the udevice index, otherwise it +is the driver_info index. In either case, indexes are used to reference devices +using device_get_by_ofplat_idx(). This allows phandles to work as expected. + + +Phases +------ + +U-Boot operates in several phases, typically TPL, SPL and U-Boot proper. +The latter does not use dtoc. + +In some rare cases different drivers are used for two phases. For example, +in TPL it may not be necessary to use the full PCI subsystem, so a simple +driver can be used instead. + +This works in the build system simply by compiling in one driver or the +other (e.g. PCI driver + uclass for SPL; simple_bus for TPL). But dtoc has +no way of knowing which code is compiled in for which phase, since it does +not inspect Makefiles or dependency graphs. + +So to make this work for dtoc, we need to be able to explicitly mark +drivers with their phase. This is done by adding a macro to the driver:: + + /* code in tpl.c only compiled into TPL */ + U_BOOT_DRIVER(pci_x86) = { + .name = "pci_x86", + .id = UCLASS_SIMPLE_BUS, + .of_match = of_match_ptr(tpl_fake_pci_ids), + DM_PHASE(tpl) + }; + + + /* code in pci_x86.c compiled into SPL and U-Boot proper */ + U_BOOT_DRIVER(pci_x86) = { + .name = "pci_x86", + .id = UCLASS_PCI, + .of_match = pci_x86_ids, + .ops = &pci_x86_ops, + }; + + +Notice that the second driver has the same name but no DM_PHASE(), so it will be +used for SPL and U-Boot. + +Note also that this only affects the code generated by dtoc. You still need to +make sure that only the required driver is build into each phase. + + +Header files +------------ + +With OF_PLATDATA_INST, dtoc must include the correct header file in the +generated code for any structs that are used, so that the code will compile. +For example, if `struct ns16550_plat` is used, the code must include the +`ns16550.h` header file. + +Typically dtoc can detect the header file needed for a driver by looking +for the structs that it uses. For example, if a driver as a `.priv_auto` +that uses `struct ns16550_plat`, then dtoc can search header files for the +definition of that struct and use the file. + +In some cases, enums are used in drivers, typically with the `.data` field +of `struct udevice_id`. Since dtoc does not support searching for these, +you must use the `DM_HDR()` macro to tell dtoc which header to use. This works +as a macro included in the driver definition:: + + static const struct udevice_id apl_syscon_ids[] = { + { .compatible = "intel,apl-punit", .data = X86_SYSCON_PUNIT }, + { } + }; + + U_BOOT_DRIVER(intel_apl_punit) = { + .name = "intel_apl_punit", + .id = UCLASS_SYSCON, + .of_match = apl_syscon_ids, + .probe = apl_punit_probe, + DM_HEADER(<asm/cpu.h>) /* for X86_SYSCON_PUNIT */ + }; + + + +Caveats +------- + +There are various complications with this feature which mean it should only +be used when strictly necessary, i.e. in SPL with limited memory. Notable +caveats include: + + - Device tree does not describe data types. But the C code must define a + type for each property. These are guessed using heuristics which + are wrong in several fairly common cases. For example an 8-byte value + is considered to be a 2-item integer array, and is byte-swapped. A + boolean value that is not present means 'false', but cannot be + included in the structures since there is generally no mention of it + in the devicetree file. + + - Naming of nodes and properties is automatic. This means that they follow + the naming in the devicetree, which may result in C identifiers that + look a bit strange. + + - It is not possible to find a value given a property name. Code must use + the associated C member variable directly in the code. This makes + the code less robust in the face of devicetree changes. To avoid having + a second struct with similar members and names you need to explicitly + declare it as an alias with `DM_DRIVER_ALIAS()`. + + - The platform data is provided to drivers as a C structure. The driver + must use the same structure to access the data. Since a driver + normally also supports devicetree it must use `#ifdef` to separate + out this code, since the structures are only available in SPL. This could + be fixed fairly easily by making the structs available outside SPL, so + that `IS_ENABLED()` could be used. + + - With CONFIG_OF_PLATDATA_INST all binding happens at build-time, meaning + that (by default) it is not possible to call `device_bind()` from C code. + This means that all devices must have an associated devicetree node and + compatible string. For example if a GPIO device currently creates child + devices in its `bind()` method, it will not work with + CONFIG_OF_PLATDATA_INST. Arguably this is bad practice anyway and the + devicetree binding should be updated to declare compatible strings for + the child devices. It is possible to disable OF_PLATDATA_NO_BIND but this + is not recommended since it increases code size. + + +Internals +--------- + +Generated files +``````````````` + +When enabled, dtoc generates the following five files: + +include/generated/dt-decl.h (OF_PLATDATA_INST only) + Contains declarations for all drivers, devices and uclasses. This allows + any `struct udevice`, `struct driver` or `struct uclass` to be located by its + name + +include/generated/dt-structs-gen.h + Contains the struct definitions for the devicetree nodes that are used. This + is the same as without OF_PLATDATA_INST + +spl/dts/dt-plat.c (only with !OF_PLATDATA_INST) + Contains the `U_BOOT_DRVINFO()` declarations that U-Boot uses to bind devices + at start-up. See above for an example + +spl/dts/dt-device.c (only with OF_PLATDATA_INST) + Contains `DM_DEVICE_INST()` declarations for each device that can be used at + run-time. These are declared in the file along with any private/platform data + that they use. Every device has an idx, as above. Since each device must be + part of a double-linked list, the nodes are declared in the code as well. + +spl/dts/dt-uclass.c (only with OF_PLATDATA_INST) + Contains `DM_UCLASS_INST()` declarations for each uclass that can be used at + run-time. These are declared in the file along with any private data + associated with the uclass itself (the `.priv_auto` member). Since each + uclass must be part of a double-linked list, the nodes are declared in the + code as well. + +The dt-structs.h file includes the generated file +`(include/generated/dt-structs.h`) if CONFIG_SPL_OF_PLATDATA is enabled. +Otherwise (such as in U-Boot proper) these structs are not available. This +prevents them being used inadvertently. All usage must be bracketed with +`#if CONFIG_IS_ENABLED(OF_PLATDATA)`. + +The dt-plat.c file contains the device declarations and is is built in +spl/dt-plat.c. + + +CONFIG options +`````````````` + +Several CONFIG options are used to control the behaviour of of-platdata, all +available for both SPL and TPL: + +OF_PLATDATA + This is the main option which enables the of-platdata feature + +OF_PLATDATA_PARENT + This allows `device_get_parent()` to work. Without this, all devices exist as + direct children of the root node. This option is highly desirable (if not + always absolutely essential) for buses such as I2C. + +OF_PLATDATA_INST + This controls the instantiation of devices at build time. With it disabled, + only `U_BOOT_DRVINFO()` records are created, with U-Boot handling the binding + in `device_bind()` on start-up. With it enabled, only `DM_DEVICE_INST()` and + `DM_UCLASS_INST()` records are created, and `device_bind()` is not needed at + runtime. + +OF_PLATDATA_NO_BIND + This controls whether `device_bind()` is supported. It is enabled by default + with OF_PLATDATA_INST since code-size reduction is really the main point of + the feature. It can be disabled if needed but is not likely to be supported + in the long term. + +OF_PLATDATA_DRIVER_RT + This controls whether the `struct driver_rt` records are used by U-Boot. + Normally when a device is bound, U-Boot stores the device pointer in one of + these records. There is one for every `struct driver_info` in the system, + i.e. one for every device that is bound from those records. It provides a + way to locate a device in the code and is used by + `device_get_by_ofplat_idx()`. This option is always enabled with of-platdata, + provided OF_PLATDATA_INST is not. In that case the records are useless since + we don't have any `struct driver_info` records. + +OF_PLATDATA_RT + This controls whether the `struct udevice_rt` records are used by U-Boot. + It moves the updatable fields from `struct udevice` (currently only `flags`) + into a separate structure, allowing the records to be kept in read-only + memory. It is generally enabled if OF_PLATDATA_INST is enabled. This option + also controls whether the private data is used in situ, or first copied into + an allocated region. Again this is to allow the private data declared by + dtoc-generated code to be in read-only memory. Note that access to private + data must be done via accessor functions, such as `dev_get_priv()`, so that + the relocation is handled. + +READ_ONLY + This indicates that the data generated by dtoc should not be modified. Only + a few fields actually do get changed in U-Boot, such as device flags. This + option causes those to move into an allocated space (see OF_PLATDATA_RT). + Also, since updating doubly linked lists is generally impossible when some of + the nodes cannot be updated, OF_PLATDATA_NO_BIND is enabled. + +Data structures +``````````````` + +A few extra data structures are used with of-platdata: + +`struct udevice_rt` + Run-time information for devices. When OF_PLATDATA_RT is enabled, this holds + the flags for each device, so that `struct udevice` can remain unchanged by + U-Boot, and potentially reside in read-only memory. Access to flags is then + via functions like `dev_get_flags()` and `dev_or_flags()`. This data + structure is allocated on start-up, where the private data is also copied. + All flags values start at 0 and any changes are handled by `dev_or_flags()` + and `dev_bic_flags()`. It would be more correct for the flags to be set to + `DM_FLAG_BOUND`, or perhaps `DM_FLAG_BOUND | DM_FLAG_ALLOC_PDATA`, but since + there is no code to bind/unbind devices and no code to allocate/free + private data / platform data, it doesn't matter. + +`struct driver_rt` + Run-time information for `struct driver_info` records. When + OF_PLATDATA_DRIVER_RT is enabled, this holds a pointer to the device + created by each record. This is needed so that is it possible to locate a + device from C code. Specifically, the code can use `DM_DRVINFO_GET(name)` to + get a reference to a particular `struct driver_info`, with `name` being the + name of the devicetree node. This is very convenient. It is also fast, since + no searching or string comparison is needed. This data structure is + allocated on start-up, filled out by `device_bind()` and used by + `device_get_by_ofplat_idx()`. + +Other changes +````````````` + +Some other changes are made with of-platdata: + +Accessor functions + Accessing private / platform data via functions such as `dev_get_priv()` has + always been encouraged. With OF_PLATDATA_RT this is essential, since the + `priv_` and `plat_` (etc.) values point to the data generated by dtoc, not + the read-write copy that is sometimes made on start-up. Changing the + private / platform data pointers has always been discouraged (the API is + marked internal) but with OF_PLATDATA_RT this is not currently supported in + general, since it assumes that all such pointers point to the relocated data. + Note also that the renaming of struct members to have a trailing underscore + was partly done to make people aware that they should not be accessed + directly. + +`gd->uclass_root_s` + Normally U-Boot sets up the head of the uclass list here and makes + `gd->uclass_root` point to it. With OF_PLATDATA_INST, dtoc generates a + declaration of `uclass_head` in `dt-uclass.c` since it needs to link the + head node into the list. In that case, `gd->uclass_root_s` is not used and + U-Boot just makes `gd->uclass_root` point to `uclass_head`. + +`gd->dm_driver_rt` + This holds a pointer to a list of `struct driver_rt` records, one for each + `struct driver_info`. The list is in alphabetical order by the name used + in `U_BOOT_DRVINFO(name)` and indexed by idx, with the first record having + an index of 0. It is only used if OF_PLATDATA_INST is not enabled. This is + accessed via macros so that it can be used inside IS_ENABLED(), rather than + requiring #ifdefs in the C code when it is not present. + +`gd->dm_udevice_rt` + This holds a pointer to a list of `struct udevice_rt` records, one for each + `struct udevice`. The list is in alphabetical order by the name used + in `DM_DEVICE_INST(name)` (a C version of the devicetree node) and indexed by + idx, with the first record having an index of 0. It is only used if + OF_PLATDATA_INST is enabled. This is accessed via macros so that it can be + used inside `IS_ENABLED()`, rather than requiring #ifdefs in the C code when + it is not present. + +`gd->dm_priv_base` + When OF_PLATDATA_RT is enabled, the private/platform data for each device is + copied into an allocated region by U-Boot on start-up. This points to that + region. All calls to accessor functions (e.g. `dev_get_priv()`) then + translate from the pointer provided by the caller (assumed to lie between + `__priv_data_start` and `__priv_data_end`) to the new allocated region. This + member is accessed via macros so that it can be used inside IS_ENABLED(), + rather than required #ifdefs in the C code when it is not present. + +`struct udevice->flags_` + When OF_PLATDATA_RT is enabled, device flags are no-longer part of + `struct udevice`, but are instead kept in `struct udevice_rt`, as described + above. Flags are accessed via functions, such as `dev_get_flags()` and + `dev_or_flags()`. + +`struct udevice->node_` + When OF_PLATDATA is enabled, there is no devicetree at runtime, so no need + for this field. It is removed, just to save space. + +`DM_PHASE` + This macro is used to indicate which phase of U-Boot a driver is intended + for. See above for details. + +`DM_HDR` + This macro is used to indicate which header file dtoc should use to allow + a driver declaration to compile correctly. See above for details. + +`device_get_by_ofplat_idx()` + There used to be a function called `device_get_by_driver_info()` which + looked up a `struct driver_info` pointer and returned the `struct udevice` + that was created from it. It was only available for use with of-platdata. + This has been removed in favour of `device_get_by_ofplat_idx()` which uses + `idx`, the index of the `struct driver_info` or `struct udevice` in the + linker_list. Similarly, the `struct phandle_0_arg` (etc.) structs have been + updated to use this index instead of a pointer to `struct driver_info`. + +`DM_DRVINFO_GET` + This has been removed since we now use indexes to obtain a driver from + `struct phandle_0_arg` and the like. + +Two-pass binding + The original of-platdata tried to order `U_BOOT_DRVINFO()` in the generated + files so as to have parents declared ahead of children. This was convenient + as it avoided any special code in U-Boot. With OF_PLATDATA_INST this does + not work as the idx value relies on using alphabetical order for everything, + so that dtoc and U-Boot's linker_lists agree on the idx value. Devices are + then bound in order of idx, having no regard to parent/child relationships. + For this reason, device binding now hapens in multiple passes, with parents + being bound before their children. This is important so that children can + find their parents in the bind() method if needed. + +Root device + The root device is generally bound by U-Boot but with OF_PLATDATA_INST it + cannot be, since binding needs to be done at build time. So in this case + dtoc sets up a root device using `DM_DEVICE_INST()` in `dt-device.c` and + U-Boot makes use of that. When OF_PLATDATA_INST is not enabled, U-Boot + generally ignores the root node and does not create a `U_BOOT_DRVINFO()` + record for it. This means that the idx numbers used by `struct driver_info` + (when OF_PLATDATA_INST is disabled) and the idx numbers used by + `struct udevice` (when OF_PLATDATA_INST is enabled) differ, since one has a + root node and the other does not. This does not actually matter, since only + one of them is actually used for any particular build, but it is worth + keeping in mind if comparing index values and switching OF_PLATDATA_INST on + and off. + +`__priv_data_start` and `__priv_data_end` + The private/platform data declared by dtoc is all collected together in + a linker section and these symbols mark the start and end of it. This allows + U-Boot to relocate the area to a new location if needed (with + OF_PLATDATA_RT) + +`dm_priv_to_rw()` + This function converts a private- or platform-data pointer value generated by + dtoc into one that can be used by U-Boot. It is a NOP unless OF_PLATDATA_RT + is enabled, in which case it translates the address to the relocated + region. See above for more information. + +The dm_populate_phandle_data() function that was previous needed has now been +removed, since dtoc can address the drivers directly from dt-plat.c and does +not need to fix up things at runtime. + +The pylibfdt Python module is used to access the devicetree. + + +Credits +------- + +This is an implementation of an idea by Tom Rini <trini@konsulko.com>. + + +Future work +----------- +- Consider programmatically reading binding files instead of devicetree + contents +- Allow IS_ENABLED() to be used in the C code instead of #if + + +.. Simon Glass <sjg@chromium.org> +.. Google, Inc +.. 6/6/16 +.. Updated Independence Day 2016 +.. Updated 1st October 2020 +.. Updated 5th February 2021 diff --git a/doc/driver-model/pci-info.rst b/doc/develop/driver-model/pci-info.rst index 8b9faa1066..251601a51e 100644 --- a/doc/driver-model/pci-info.rst +++ b/doc/develop/driver-model/pci-info.rst @@ -125,6 +125,7 @@ emulator driver. For example:: compatible = "sandbox,pci-emul-parent"; emul_1f: emul@1f,0 { compatible = "sandbox,swap-case"; + #emul-cells = <0>; }; }; diff --git a/doc/driver-model/pmic-framework.rst b/doc/develop/driver-model/pmic-framework.rst index d24a1badd6..d24a1badd6 100644 --- a/doc/driver-model/pmic-framework.rst +++ b/doc/develop/driver-model/pmic-framework.rst diff --git a/doc/driver-model/remoteproc-framework.rst b/doc/develop/driver-model/remoteproc-framework.rst index 566495a21c..566495a21c 100644 --- a/doc/driver-model/remoteproc-framework.rst +++ b/doc/develop/driver-model/remoteproc-framework.rst diff --git a/doc/driver-model/serial-howto.rst b/doc/develop/driver-model/serial-howto.rst index 1469131124..1469131124 100644 --- a/doc/driver-model/serial-howto.rst +++ b/doc/develop/driver-model/serial-howto.rst diff --git a/doc/driver-model/soc-framework.rst b/doc/develop/driver-model/soc-framework.rst index 2609fda644..2609fda644 100644 --- a/doc/driver-model/soc-framework.rst +++ b/doc/develop/driver-model/soc-framework.rst diff --git a/doc/driver-model/spi-howto.rst b/doc/develop/driver-model/spi-howto.rst index 97fbf750cb..97fbf750cb 100644 --- a/doc/driver-model/spi-howto.rst +++ b/doc/develop/driver-model/spi-howto.rst diff --git a/doc/driver-model/usb-info.rst b/doc/develop/driver-model/usb-info.rst index 24d1e81a6c..24d1e81a6c 100644 --- a/doc/driver-model/usb-info.rst +++ b/doc/develop/driver-model/usb-info.rst diff --git a/doc/develop/index.rst b/doc/develop/index.rst index ac57fdb8f3..3edffbc637 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -10,9 +10,11 @@ Implementation :maxdepth: 1 commands + driver-model/index global_data logging menus + uefi/index version Debugging @@ -24,6 +26,14 @@ Debugging crash_dumps trace +Packaging +--------- + +.. toctree:: + :maxdepth: 1 + + package/index + Testing ------- @@ -33,3 +43,5 @@ Testing coccinelle testing py_testing + tests_writing + tests_sandbox diff --git a/doc/develop/logging.rst b/doc/develop/logging.rst index 60c18c5b3a..f4e925048e 100644 --- a/doc/develop/logging.rst +++ b/doc/develop/logging.rst @@ -96,16 +96,45 @@ Also debug() and error() will generate log records - these use LOG_CATEGORY as the category, so you should #define this right at the top of the source file to ensure the category is correct. +Generally each log format_string ends with a newline. If it does not, then the +next log statement will have the LOGRECF_CONT flag set. This can be used to +continue the statement on the same line as the previous one without emitting +new header information (such as category/level). This behaviour is implemented +with log_console. Here is an example that prints a list all on one line with +the tags at the start: + +.. code-block:: c + + log_debug("Here is a list:"); + for (i = 0; i < count; i++) + log_debug(" item %d", i); + log_debug("\n"); + +Also see the special category LOGL_CONT and level LOGC_CONT. + You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This can be used whenever your function returns an error value: .. code-block:: c - return log_ret(uclass_first_device(UCLASS_MMC, &dev)); + return log_ret(uclass_first_device_err(UCLASS_MMC, &dev)); This will write a log record when an error code is detected (a value < 0). This can make it easier to trace errors that are generated deep in the call stack. +The log_msg_ret() variant will print a short string if CONFIG_LOG_ERROR_RETURN +is enabled. So long as the string is unique within the function you can normally +determine exactly which call failed: + +.. code-block:: c + + ret = gpio_request_by_name(dev, "cd-gpios", 0, &desc, GPIOD_IS_IN); + if (ret) + return log_msg_ret("gpio", ret); + +Some functions return 0 for success and any other value is an error. For these, +log_retz() and log_msg_retz() are available. + Convenience functions ~~~~~~~~~~~~~~~~~~~~~ diff --git a/doc/develop/package/binman.rst b/doc/develop/package/binman.rst new file mode 120000 index 0000000000..2e26e84b7d --- /dev/null +++ b/doc/develop/package/binman.rst @@ -0,0 +1 @@ +../../../tools/binman/binman.rst
\ No newline at end of file diff --git a/doc/develop/package/entries.rst b/doc/develop/package/entries.rst new file mode 120000 index 0000000000..ecedcebaad --- /dev/null +++ b/doc/develop/package/entries.rst @@ -0,0 +1 @@ +../../../tools/binman/entries.rst
\ No newline at end of file diff --git a/doc/develop/package/index.rst b/doc/develop/package/index.rst new file mode 100644 index 0000000000..9374be2e62 --- /dev/null +++ b/doc/develop/package/index.rst @@ -0,0 +1,19 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Package U-Boot +============== + +U-Boot uses Flat Image Tree (FIT) as a standard file format for packaging +images that it it reads and boots. Documentation about FIT is available at +doc/uImage.FIT + +U-Boot also provides binman for cases not covered by FIT. Examples include +initial execution (since FIT itself does not have an executable header) and +dealing with device boundaries, such as the read-only/read-write separation in +SPI flash. + + +.. toctree:: + :maxdepth: 2 + + binman diff --git a/doc/develop/py_testing.rst b/doc/develop/py_testing.rst index 7f01858cfd..c4cecc0a01 100644 --- a/doc/develop/py_testing.rst +++ b/doc/develop/py_testing.rst @@ -13,7 +13,8 @@ results. Advantages of this approach are: U-Boot; there can be no disconnect. - There is no need to write or embed test-related code into U-Boot itself. It is asserted that writing test-related code in Python is simpler and more - flexible than writing it all in C. + flexible than writing it all in C. But see :doc:`tests_writing` for caveats + and more discussion / analysis. - It is reasonably simple to interact with U-Boot in this way. Requirements diff --git a/doc/develop/testing.rst b/doc/develop/testing.rst index 4bc9ca3a6a..ced13ac8bb 100644 --- a/doc/develop/testing.rst +++ b/doc/develop/testing.rst @@ -8,17 +8,27 @@ tested and what tests you should write when adding a new feature. Running tests ------------- -To run most tests on sandbox, type this: +To run most tests on sandbox, type this:: make check in the U-Boot directory. Note that only the pytest suite is run using this command. -Some tests take ages to run. To run just the quick ones, type this: +Some tests take ages to run and are marked with @pytest.mark.slow. To run just +the quick ones, type this:: make qcheck +It is also possible to run just the tests for tools (patman, binman, etc.). +Such tests are included with those tools, i.e. no actual U-Boot unit tests are +run. Type this:: + + make tcheck + +All of the above use the test/run script with a paremeter to select which tests +are run. + Sandbox ------- @@ -26,6 +36,7 @@ U-Boot can be built as a user-space application (e.g. for Linux). This allows test to be executed without needing target hardware. The 'sandbox' target provides this feature and it is widely used in tests. +See :doc:`tests_sandbox` for more information. Pytest Suite ------------ @@ -35,14 +46,27 @@ either on sandbox or on real hardware. It relies on the U-Boot console to inject test commands and check the result. It is slower to run than C code, but provides the ability to unify lots of tests and summarise their results. -You can run the tests on sandbox with: +You can run the tests on sandbox with:: - ./test/py/test.py --bd sandbox --build + ./test/py/test.py --bd sandbox --build This will produce HTML output in build-sandbox/test-log.html +Some tests run with other versions of sandbox. For example sandbox_flattree +runs the tests with livetree (the hierachical devicetree) disabled. You can +also select particular tests with -k:: + + ./test/py/test.py --bd sandbox_flattree --build -k hello + +There are some special tests that run in SPL. For this you need the sandbox_spl +build:: + + ./test/py/test.py --bd sandbox_spl --build -k test_spl + See test/py/README.md for more information about the pytest suite. +See :doc:`tests_sandbox` for how to run tests directly (not through pytest). + tbot ---- @@ -58,10 +82,14 @@ Ad-hoc tests There are several ad-hoc tests which run outside the pytest environment: - test/fs - File system test (shell script) - test/image - FIT and legacy image tests (shell script and Python) - test/stdint - A test that stdint.h can be used in U-Boot (shell script) - trace - Test for the tracing feature (shell script) +test/fs + File system test (shell script) +test/image + FIT and legacy image tests (shell script and Python) +test/stdint + A test that stdint.h can be used in U-Boot (shell script) +trace + Test for the tracing feature (shell script) TODO: Move these into pytest. @@ -89,6 +117,8 @@ or is covered sparingly. So here are some suggestions: is much easier to add onto a test - writing a new large test can seem daunting to most contributors. +See doc:`tests_writing` for how to write tests. + Future work ----------- diff --git a/doc/develop/tests_sandbox.rst b/doc/develop/tests_sandbox.rst new file mode 100644 index 0000000000..84608dcb84 --- /dev/null +++ b/doc/develop/tests_sandbox.rst @@ -0,0 +1,209 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Sandbox tests +============= + +Test Design +----------- + +Most uclasses and many functions of U-Boot have sandbox tests. This allows much +of the code to be checked in an developer-friendly environment. + +Sandbox provides a way to write and run unit tests. The traditional approach to +unit tests is to build lots of little executables, one for each test or +category of tests. With sandbox, so far as possible, all the tests share a +small number of executables (e.g. 'u-boot' for sandbox, 'u-boot-spl' and +'u-boot' for sandbox_spl) and can be run very quickly. The vast majority of +tests can run on the 'sandbox' build, + +Available tests +--------------- + +Some of the available tests are: + + - command_ut: Unit tests for command parsing and handling + - compression: Unit tests for U-Boot's compression algorithms, useful for + security checking. It supports gzip, bzip2, lzma and lzo. + - image: Unit tests for images: + + - test/image/test-imagetools.sh - multi-file images + - test/py/tests/test-fit.py - FIT images + - tracing: test/trace/test-trace.sh tests the tracing system (see + README.trace) + - verified boot: test/py/tests/test_vboot.py + +If you change or enhance any U-Boot subsystem, you should write or expand a +test and include it with your patch series submission. Test coverage in some +older areas of U-Boot is still somewhat limited and we need to work to improve +it. + +Note that many of these tests are implemented as commands which you can +run natively on your board if desired (and enabled). + +To run all tests, use 'make check'. + + +Running sandbox tests directly +------------------------------ + +Typically tests are run using the pytest suite. Running pytests on sandbox is +easy and always gets things right. For example some tests require files to be +set up before they can work. + +But it is also possible to run some sandbox tests directly. For example, this +runs the dm_test_gpio() test which you can find in test/dm/gpio.c:: + + $ ./u-boot -T -c "ut dm gpio" + + + U-Boot 2021.01 + + Model: sandbox + DRAM: 128 MiB + WDT: Started with servicing (60s timeout) + MMC: mmc2: 2 (SD), mmc1: 1 (SD), mmc0: 0 (SD) + In: serial + Out: vidconsole + Err: vidconsole + Model: sandbox + SCSI: + Net: eth0: eth@10002000, eth5: eth@10003000, eth3: sbe5, eth6: eth@10004000 + Test: dm_test_gpio: gpio.c + Test: dm_test_gpio: gpio.c (flat tree) + Failures: 0 + +The -T option tells the U-Boot sandbox to run with the 'test' devicetree +(test.dts) instead of -D which selects the normal sandbox.dts - this is +necessary because many tests rely on nodes or properties in the test devicetree. +If you try running tests without -T then you may see failures, like:: + + $ ./u-boot -c "ut dm gpio" + + + U-Boot 2021.01 + + DRAM: 128 MiB + WDT: Not found! + MMC: + In: serial + Out: serial + Err: serial + SCSI: + Net: No ethernet found. + Please run with test device tree: + ./u-boot -d arch/sandbox/dts/test.dtb + Test: dm_test_gpio: gpio.c + test/dm/gpio.c:37, dm_test_gpio(): 0 == gpio_lookup_name("b4", &dev, &offset, &gpio): Expected 0x0 (0), got 0xffffffea (-22) + Test: dm_test_gpio: gpio.c (flat tree) + test/dm/gpio.c:37, dm_test_gpio(): 0 == gpio_lookup_name("b4", &dev, &offset, &gpio): Expected 0x0 (0), got 0xffffffea (-22) + Failures: 2 + +The message above should provide a hint if you forget to use the -T flag. Even +running with -D will produce different results. + +You can easily use gdb on these tests, without needing --gdbserver:: + + $ gdb u-boot --args -T -c "ut dm gpio" + ... + (gdb) break dm_test_gpio + Breakpoint 1 at 0x1415bd: file test/dm/gpio.c, line 37. + (gdb) run -T -c "ut dm gpio" + Starting program: u-boot -T -c "ut dm gpio" + Test: dm_test_gpio: gpio.c + + Breakpoint 1, dm_test_gpio (uts=0x5555558029a0 <global_dm_test_state>) + at files/test/dm/gpio.c:37 + 37 ut_assertok(gpio_lookup_name("b4", &dev, &offset, &gpio)); + (gdb) + +You can then single-step and look at variables as needed. + + +Running sandbox_spl tests directly +---------------------------------- + +SPL is the phase before U-Boot proper. It is present in the sandbox_spl build, +so you can run SPL like this:: + + ./spl/u-boot-spl + +SPL tests are special in that they run (only in the SPL phase, of course) if the +-u flag is given:: + + ./spl/u-boot-spl -u + + U-Boot SPL 2021.01-00723-g43c77b51be5-dirty (Jan 24 2021 - 16:38:24 -0700) + Running 5 driver model tests + Test: dm_test_of_plat_base: of_platdata.c (flat tree) + Test: dm_test_of_plat_dev: of_platdata.c (flat tree) + Test: dm_test_of_plat_parent: of_platdata.c (flat tree) + Test: dm_test_of_plat_phandle: of_platdata.c (flat tree) + Test: dm_test_of_plat_props: of_platdata.c (flat tree) + Failures: 0 + + + U-Boot 2021.01-00723-g43c77b51be5-dirty (Jan 24 2021 - 16:38:24 -0700) + + DRAM: 128 MiB + ... + +It is not possible to run SPL tests in U-Boot proper, firstly because they are +not built into U-Boot proper and secondly because the environment is very +different, e.g. some SPL tests rely on of-platdata which is only available in +SPL. + +Note that after running, SPL continues to boot into U-Boot proper. You can add +'-c exit' to make U-Boot quit without doing anything further. It is not +currently possible to run SPL tests and then stop, since the pytests require +that U-Boot produces the expected banner. + +You can use the -k flag to select which tests run:: + + ./spl/u-boot-spl -u -k dm_test_of_plat_parent + +Of course you can use gdb with sandbox_spl, just as with sandbox. + + +Running all tests directly +-------------------------- + +A fast way to run all sandbox tests is:: + + ./u-boot -T -c "ut all" + +It typically runs single-thread in 6 seconds on 2021 hardware, with 2s of that +to the delays in the time test. + +This should not be considered a substitute for 'make check', but can be helpful +for git bisect, etc. + + +What tests are built in? +------------------------ + +Whatever sandbox build is used, which tests are present is determined by which +source files are built. For sandbox_spl, the of_platdata tests are built +because of the build rule in test/dm/Makefile:: + + ifeq ($(CONFIG_SPL_BUILD),y) + obj-$(CONFIG_SPL_OF_PLATDATA) += of_platdata.o + else + ...other tests for non-spl + endif + +You can get a list of tests in a U-Boot ELF file by looking for the +linker_list:: + + $ nm /tmp/b/sandbox_spl/spl/u-boot-spl |grep 2_dm_test + 000000000001f200 D _u_boot_list_2_dm_test_2_dm_test_of_plat_base + 000000000001f220 D _u_boot_list_2_dm_test_2_dm_test_of_plat_dev + 000000000001f240 D _u_boot_list_2_dm_test_2_dm_test_of_plat_parent + 000000000001f260 D _u_boot_list_2_dm_test_2_dm_test_of_plat_phandle + 000000000001f280 D _u_boot_list_2_dm_test_2_dm_test_of_plat_props + + +Writing tests +------------- + +See :doc:`tests_writing` for how to write new tests. + diff --git a/doc/develop/tests_writing.rst b/doc/develop/tests_writing.rst new file mode 100644 index 0000000000..1ddf7a353a --- /dev/null +++ b/doc/develop/tests_writing.rst @@ -0,0 +1,346 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. Copyright 2021 Google LLC +.. sectionauthor:: Simon Glass <sjg@chromium.org> + +Writing Tests +============= + +This describes how to write tests in U-Boot and describes the possible options. + +Test types +---------- + +There are two basic types of test in U-Boot: + + - Python tests, in test/py/tests + - C tests, in test/ and its subdirectories + +(there are also UEFI tests in lib/efi_selftest/ not considered here.) + +Python tests talk to U-Boot via the command line. They support both sandbox and +real hardware. They typically do not require building test code into U-Boot +itself. They are fairly slow to run, due to the command-line interface and there +being two separate processes. Python tests are fairly easy to write. They can +be a little tricky to debug sometimes due to the voluminous output of pytest. + +C tests are written directly in U-Boot. While they can be used on boards, they +are more commonly used with sandbox, as they obviously add to U-Boot code size. +C tests are easy to write so long as the required facilities exist. Where they +do not it can involve refactoring or adding new features to sandbox. They are +fast to run and easy to debug. + +Regardless of which test type is used, all tests are collected and run by the +pytest framework, so there is typically no need to run them separately. This +means that C tests can be used when it makes sense, and Python tests when it +doesn't. + + +This table shows how to decide whether to write a C or Python test: + +===================== =========================== ============================= +Attribute C test Python test +===================== =========================== ============================= +Fast to run? Yes No (two separate processes) +Easy to write? Yes, if required test Yes + features exist in sandbox + or the target system +Needs code in U-Boot? Yes No, provided the test can be + executed and the result + determined using the command + line +Easy to debug? Yes No, since access to the U-Boot + state is not available and the + amount of output can + sometimes require a bit of + digging +Can use gdb? Yes, directly Yes, with --gdbserver +Can run on boards? Some can, but only if Some + compiled in and not + dependent on sandboxau +===================== =========================== ============================= + + +Python or C +----------- + +Typically in U-Boot we encourage C test using sandbox for all features. This +allows fast testing, easy development and allows contributors to make changes +without needing dozens of boards to test with. + +When a test requires setup or interaction with the running host (such as to +generate images and then running U-Boot to check that they can be loaded), or +cannot be run on sandbox, Python tests should be used. These should typically +NOT rely on running with sandbox, but instead should function correctly on any +board supported by U-Boot. + + +How slow are Python tests? +-------------------------- + +Under the hood, when running on sandbox, Python tests work by starting a sandbox +test and connecting to it via a pipe. Each interaction with the U-Boot process +requires at least a context switch to handle the pipe interaction. The test +sends a command to U-Boot, which then reacts and shows some output, then the +test sees that and continues. Of course on real hardware, communications delays +(e.g. with a serial console) make this slower. + +For comparison, consider a test that checks the 'md' (memory dump). All times +below are approximate, as measured on an AMD 2950X system. Here is is the test +in Python:: + + @pytest.mark.buildconfigspec('cmd_memory') + def test_md(u_boot_console): + """Test that md reads memory as expected, and that memory can be modified + using the mw command.""" + + ram_base = u_boot_utils.find_ram_base(u_boot_console) + addr = '%08x' % ram_base + val = 'a5f09876' + expected_response = addr + ': ' + val + u_boot_console.run_command('mw ' + addr + ' 0 10') + response = u_boot_console.run_command('md ' + addr + ' 10') + assert(not (expected_response in response)) + u_boot_console.run_command('mw ' + addr + ' ' + val) + response = u_boot_console.run_command('md ' + addr + ' 10') + assert(expected_response in response) + +This runs a few commands and checks the output. Note that it runs a command, +waits for the response and then checks it agains what is expected. If run by +itself it takes around 800ms, including test collection. For 1000 runs it takes +19 seconds, or 19ms per run. Of course 1000 runs it not that useful since we +only want to run it once. + +There is no exactly equivalent C test, but here is a similar one that tests 'ms' +(memory search):: + + /* Test 'ms' command with bytes */ + static int mem_test_ms_b(struct unit_test_state *uts) + { + u8 *buf; + + buf = map_sysmem(0, BUF_SIZE + 1); + memset(buf, '\0', BUF_SIZE); + buf[0x0] = 0x12; + buf[0x31] = 0x12; + buf[0xff] = 0x12; + buf[0x100] = 0x12; + ut_assertok(console_record_reset_enable()); + run_command("ms.b 1 ff 12", 0); + ut_assert_nextline("00000030: 00 12 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................"); + ut_assert_nextline("--"); + ut_assert_nextline("000000f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 ................"); + ut_assert_nextline("2 matches"); + ut_assert_console_end(); + + ut_asserteq(2, env_get_hex("memmatches", 0)); + ut_asserteq(0xff, env_get_hex("memaddr", 0)); + ut_asserteq(0xfe, env_get_hex("mempos", 0)); + + unmap_sysmem(buf); + + return 0; + } + MEM_TEST(mem_test_ms_b, UT_TESTF_CONSOLE_REC); + +This runs the command directly in U-Boot, then checks the console output, also +directly in U-Boot. If run by itself this takes 100ms. For 1000 runs it takes +660ms, or 0.66ms per run. + +So overall running a C test is perhaps 8 times faster individually and the +interactions are perhaps 25 times faster. + +It should also be noted that the C test is fairly easy to debug. You can set a +breakpoint on do_mem_search(), which is what implements the 'ms' command, +single step to see what might be wrong, etc. That is also possible with the +pytest, but requires two terminals and --gdbserver. + + +Why does speed matter? +---------------------- + +Many development activities rely on running tests: + + - 'git bisect run make qcheck' can be used to find a failing commit + - test-driven development relies on quick iteration of build/test + - U-Boot's continuous integration (CI) systems make use of tests. Running + all sandbox tests typically takes 90 seconds and running each qemu test + takes about 30 seconds. This is currently dwarfed by the time taken to + build all boards + +As U-Boot continues to grow its feature set, fast and reliable tests are a +critical factor factor in developer productivity and happiness. + + +Writing C tests +--------------- + +C tests are arranged into suites which are typically executed by the 'ut' +command. Each suite is in its own file. This section describes how to accomplish +some common test tasks. + +(there are also UEFI C tests in lib/efi_selftest/ not considered here.) + +Add a new driver model test +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use this when adding a test for a new or existing uclass, adding new operations +or features to a uclass, adding new ofnode or dev_read_() functions, or anything +else related to driver model. + +Find a suitable place for your test, perhaps near other test functions in +existing code, or in a new file. Each uclass should have its own test file. + +Declare the test with:: + + /* Test that ... */ + static int dm_test_uclassname_what(struct unit_test_state *uts) + { + /* test code here */ + + return 0; + } + DM_TEST(dm_test_uclassname_what, UT_TESTF_SCAN_FDT); + +Replace 'uclassname' with the name of your uclass, if applicable. Replace 'what' +with what you are testing. + +The flags for DM_TEST() are defined in test/test.h and you typically want +UT_TESTF_SCAN_FDT so that the devicetree is scanned and all devices are bound +and ready for use. The DM_TEST macro adds UT_TESTF_DM automatically so that +the test runner knows it is a driver model test. + +Driver model tests are special in that the entire driver model state is +recreated anew for each test. This ensures that if a previous test deletes a +device, for example, it does not affect subsequent tests. Driver model tests +also run both with livetree and flattree, to ensure that both devicetree +implementations work as expected. + +Example commit: c48cb7ebfb4 ("sandbox: add ADC unit tests") [1] + +[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/c48cb7ebfb4 + + +Add a C test to an existing suite +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use this when you are adding to or modifying an existing feature outside driver +model. An example is bloblist. + +Add a new function in the same file as the rest of the suite and register it +with the suite. For example, to add a new mem_search test:: + + /* Test 'ms' command with 32-bit values */ + static int mem_test_ms_new_thing(struct unit_test_state *uts) + { + /* test code here*/ + + return 0; + } + MEM_TEST(mem_test_ms_new_thing, UT_TESTF_CONSOLE_REC); + +Note that the MEM_TEST() macros is defined at the top of the file. + +Example commit: 9fe064646d2 ("bloblist: Support relocating to a larger space") [1] + +[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/9fe064646d2 + + +Add a new test suite +~~~~~~~~~~~~~~~~~~~~ + +Each suite should focus on one feature or subsystem, so if you are writing a +new one of those, you should add a new suite. + +Create a new file in test/ or a subdirectory and define a macro to register the +suite. For example:: + + #include <common.h> + #include <console.h> + #include <mapmem.h> + #include <dm/test.h> + #include <test/ut.h> + + /* Declare a new wibble test */ + #define WIBBLE_TEST(_name, _flags) UNIT_TEST(_name, _flags, wibble_test) + + /* Tetss go here */ + + /* At the bottom of the file: */ + + int do_ut_wibble(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) + { + struct unit_test *tests = UNIT_TEST_SUITE_START(wibble_test); + const int n_ents = UNIT_TEST_SUITE_COUNT(wibble_test); + + return cmd_ut_category("cmd_wibble", "wibble_test_", tests, n_ents, argc, argv); + } + +Then add new tests to it as above. + +Register this new suite in test/cmd_ut.c by adding to cmd_ut_sub[]:: + + /* Within cmd_ut_sub[]... */ + + U_BOOT_CMD_MKENT(wibble, CONFIG_SYS_MAXARGS, 1, do_ut_wibble, "", ""), + +and adding new help to ut_help_text[]:: + + "ut wibble - Test the wibble feature\n" + +If your feature is conditional on a particular Kconfig, then you can use #ifdef +to control that. + +Finally, add the test to the build by adding to the Makefile in the same +directory:: + + obj-$(CONFIG_$(SPL_)CMDLINE) += wibble.o + +Note that CMDLINE is never enabled in SPL, so this test will only be present in +U-Boot proper. See below for how to do SPL tests. + +As before, you can add an extra Kconfig check if needed:: + + ifneq ($(CONFIG_$(SPL_)WIBBLE),) + obj-$(CONFIG_$(SPL_)CMDLINE) += wibble.o + endif + + +Example commit: 919e7a8fb64 ("test: Add a simple test for bloblist") [1] + +[1] https://gitlab.denx.de/u-boot/u-boot/-/commit/919e7a8fb64 + + +Making the test run from pytest +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All C tests must run from pytest. Typically this is automatic, since pytest +scans the U-Boot executable for available tests to run. So long as you have a +'ut' subcommand for your test suite, it will run. The same applies for driver +model tests since they use the 'ut dm' subcommand. + +See test/py/tests/test_ut.py for how unit tests are run. + + +Add a C test for SPL +~~~~~~~~~~~~~~~~~~~~ + +Note: C tests are only available for sandbox_spl at present. There is currently +no mechanism in other boards to existing SPL tests even if they are built into +the image. + +SPL tests cannot be run from the 'ut' command since there are no commands +available in SPL. Instead, sandbox (only) calls ut_run_list() on start-up, when +the -u flag is given. This runs the available unit tests, no matter what suite +they are in. + +To create a new SPL test, follow the same rules as above, either adding to an +existing suite or creating a new one. + +An example SPL test is spl_test_load(). + + +Writing Python tests +-------------------- + +See :doc:`py_testing` for brief notes how to write Python tests. You +should be able to use the existing tests in test/py/tests as examples. diff --git a/doc/uefi/index.rst b/doc/develop/uefi/index.rst index b790a91f17..7e65dbc5d5 100644 --- a/doc/uefi/index.rst +++ b/doc/develop/uefi/index.rst @@ -3,6 +3,10 @@ Unified Extensible Firmware (UEFI) ================================== +U-Boot provides an implementation of the UEFI API allowing to run UEFI +compliant software like Linux, GRUB, and iPXE. Furthermore U-Boot itself +can be run an UEFI payload. + .. toctree:: :maxdepth: 2 diff --git a/doc/uefi/iscsi.rst b/doc/develop/uefi/iscsi.rst index 51d38cde24..51d38cde24 100644 --- a/doc/uefi/iscsi.rst +++ b/doc/develop/uefi/iscsi.rst diff --git a/doc/uefi/u-boot_on_efi.rst b/doc/develop/uefi/u-boot_on_efi.rst index c9a41bc919..c9a41bc919 100644 --- a/doc/uefi/u-boot_on_efi.rst +++ b/doc/develop/uefi/u-boot_on_efi.rst diff --git a/doc/uefi/uefi.rst b/doc/develop/uefi/uefi.rst index 5a67737c15..b3494c22e0 100644 --- a/doc/uefi/uefi.rst +++ b/doc/develop/uefi/uefi.rst @@ -178,7 +178,7 @@ Now in U-Boot install the keys on your board:: Set up boot parameters on your board:: - efidebug boot add 1 HELLO mmc 0:1 /helloworld.efi.signed "" + efidebug boot add -b 1 HELLO mmc 0:1 /helloworld.efi.signed "" Now your board can run the signed image via the boot manager (see below). You can also try this sequence by running Pytest, test_efi_secboot, 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 0000000000..d8a1a79687 --- /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>; + */ + }; diff --git a/doc/driver-model/of-plat.rst b/doc/driver-model/of-plat.rst deleted file mode 100644 index 4ef2fe699a..0000000000 --- a/doc/driver-model/of-plat.rst +++ /dev/null @@ -1,359 +0,0 @@ -.. SPDX-License-Identifier: GPL-2.0+ - -Compiled-in Device Tree / Platform Data -======================================= - - -Introduction ------------- - -Device tree is the standard configuration method in U-Boot. It is used to -define what devices are in the system and provide configuration information -to these devices. - -The overhead of adding device tree access to U-Boot is fairly modest, -approximately 3KB on Thumb 2 (plus the size of the DT itself). This means -that in most cases it is best to use device tree for configuration. - -However there are some very constrained environments where U-Boot needs to -work. These include SPL with severe memory limitations. For example, some -SoCs require a 16KB SPL image which must include a full MMC stack. In this -case the overhead of device tree access may be too great. - -It is possible to create platform data manually by defining C structures -for it, and reference that data in a U_BOOT_DRVINFO() declaration. This -bypasses the use of device tree completely, effectively creating a parallel -configuration mechanism. But it is an available option for SPL. - -As an alternative, a new 'of-platdata' feature is provided. This converts the -device tree contents into C code which can be compiled into the SPL binary. -This saves the 3KB of code overhead and perhaps a few hundred more bytes due -to more efficient storage of the data. - -Note: Quite a bit of thought has gone into the design of this feature. -However it still has many rough edges and comments and suggestions are -strongly encouraged! Quite possibly there is a much better approach. - - -Caveats -------- - -There are many problems with this features. It should only be used when -strictly necessary. Notable problems include: - - - Device tree does not describe data types. But the C code must define a - type for each property. These are guessed using heuristics which - are wrong in several fairly common cases. For example an 8-byte value - is considered to be a 2-item integer array, and is byte-swapped. A - boolean value that is not present means 'false', but cannot be - included in the structures since there is generally no mention of it - in the device tree file. - - - Naming of nodes and properties is automatic. This means that they follow - the naming in the device tree, which may result in C identifiers that - look a bit strange. - - - It is not possible to find a value given a property name. Code must use - the associated C member variable directly in the code. This makes - the code less robust in the face of device-tree changes. It also - makes it very unlikely that your driver code will be useful for more - than one SoC. Even if the code is common, each SoC will end up with - a different C struct name, and a likely a different format for the - platform data. - - - The platform data is provided to drivers as a C structure. The driver - must use the same structure to access the data. Since a driver - normally also supports device tree it must use #ifdef to separate - out this code, since the structures are only available in SPL. - - -How it works ------------- - -The feature is enabled by CONFIG OF_PLATDATA. This is only available in -SPL/TPL and should be tested with: - -.. code-block:: c - - #if CONFIG_IS_ENABLED(OF_PLATDATA) - -A new tool called 'dtoc' converts a device tree file either into a set of -struct declarations, one for each compatible node, and a set of -U_BOOT_DRVINFO() declarations along with the actual platform data for each -device. As an example, consider this MMC node: - -.. code-block:: none - - sdmmc: dwmmc@ff0c0000 { - compatible = "rockchip,rk3288-dw-mshc"; - clock-freq-min-max = <400000 150000000>; - clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, - <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; - clock-names = "biu", "ciu", "ciu_drv", "ciu_sample"; - fifo-depth = <0x100>; - interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; - reg = <0xff0c0000 0x4000>; - bus-width = <4>; - cap-mmc-highspeed; - cap-sd-highspeed; - card-detect-delay = <200>; - disable-wp; - num-slots = <1>; - pinctrl-names = "default"; - pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; - vmmc-supply = <&vcc_sd>; - status = "okay"; - u-boot,dm-pre-reloc; - }; - - -Some of these properties are dropped by U-Boot under control of the -CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce -the following C struct declaration: - -.. code-block:: c - - struct dtd_rockchip_rk3288_dw_mshc { - fdt32_t bus_width; - bool cap_mmc_highspeed; - bool cap_sd_highspeed; - fdt32_t card_detect_delay; - fdt32_t clock_freq_min_max[2]; - struct phandle_1_arg clocks[4]; - bool disable_wp; - fdt32_t fifo_depth; - fdt32_t interrupts[3]; - fdt32_t num_slots; - fdt32_t reg[2]; - fdt32_t vmmc_supply; - }; - -and the following device declarations: - -.. code-block:: c - - /* Node /clock-controller@ff760000 index 0 */ - ... - - /* Node /dwmmc@ff0c0000 index 2 */ - static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = { - .fifo_depth = 0x100, - .cap_sd_highspeed = true, - .interrupts = {0x0, 0x20, 0x4}, - .clock_freq_min_max = {0x61a80, 0x8f0d180}, - .vmmc_supply = 0xb, - .num_slots = 0x1, - .clocks = {{0, 456}, - {0, 68}, - {0, 114}, - {0, 118}}, - .cap_mmc_highspeed = true, - .disable_wp = true, - .bus_width = 0x4, - .u_boot_dm_pre_reloc = true, - .reg = {0xff0c0000, 0x4000}, - .card_detect_delay = 0xc8, - }; - - U_BOOT_DRVINFO(dwmmc_at_ff0c0000) = { - .name = "rockchip_rk3288_dw_mshc", - .plat = &dtv_dwmmc_at_ff0c0000, - .plat_size = sizeof(dtv_dwmmc_at_ff0c0000), - .parent_idx = -1, - }; - -The device is then instantiated at run-time and the platform data can be -accessed using: - -.. code-block:: c - - struct udevice *dev; - struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev); - -This avoids the code overhead of converting the device tree data to -platform data in the driver. The of_to_plat() method should -therefore do nothing in such a driver. - -Note that for the platform data to be matched with a driver, the 'name' -property of the U_BOOT_DRVINFO() declaration has to match a driver declared -via U_BOOT_DRIVER(). This effectively means that a U_BOOT_DRIVER() with a -'name' corresponding to the devicetree 'compatible' string (after converting -it to a valid name for C) is needed, so a dedicated driver is required for -each 'compatible' string. - -In order to make this a bit more flexible DM_DRIVER_ALIAS macro can be -used to declare an alias for a driver name, typically a 'compatible' string. -This macro produces no code, but it is by dtoc tool. - -The parent_idx is the index of the parent driver_info structure within its -linker list (instantiated by the U_BOOT_DRVINFO() macro). This is used to support -dev_get_parent(). - -During the build process dtoc parses both U_BOOT_DRIVER and DM_DRIVER_ALIAS -to build a list of valid driver names and driver aliases. If the 'compatible' -string used for a device does not not match a valid driver name, it will be -checked against the list of driver aliases in order to get the right driver -name to use. If in this step there is no match found a warning is issued to -avoid run-time failures. - -Where a node has multiple compatible strings, a #define is used to make them -equivalent, e.g.: - -.. code-block:: c - - #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc - - -Converting of-platdata to a useful form ---------------------------------------- - -Of course it would be possible to use the of-platdata directly in your driver -whenever configuration information is required. However this means that the -driver will not be able to support device tree, since the of-platdata -structure is not available when device tree is used. It would make no sense -to use this structure if device tree were available, since the structure has -all the limitations metioned in caveats above. - -Therefore it is recommended that the of-platdata structure should be used -only in the probe() method of your driver. It cannot be used in the -of_to_plat() method since this is not called when platform data is -already present. - - -How to structure your driver ----------------------------- - -Drivers should always support device tree as an option. The of-platdata -feature is intended as a add-on to existing drivers. - -Your driver should convert the plat struct in its probe() method. The -existing device tree decoding logic should be kept in the -of_to_plat() method and wrapped with #if. - -For example: - -.. code-block:: c - - #include <dt-structs.h> - - struct mmc_plat { - #if CONFIG_IS_ENABLED(OF_PLATDATA) - /* Put this first since driver model will copy the data here */ - struct dtd_mmc dtplat; - #endif - /* - * Other fields can go here, to be filled in by decoding from - * the device tree (or the C structures when of-platdata is used). - */ - int fifo_depth; - }; - - static int mmc_of_to_plat(struct udevice *dev) - { - #if !CONFIG_IS_ENABLED(OF_PLATDATA) - /* Decode the device tree data */ - struct mmc_plat *plat = dev_get_plat(dev); - const void *blob = gd->fdt_blob; - int node = dev_of_offset(dev); - - plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0); - #endif - - return 0; - } - - static int mmc_probe(struct udevice *dev) - { - struct mmc_plat *plat = dev_get_plat(dev); - - #if CONFIG_IS_ENABLED(OF_PLATDATA) - /* Decode the of-platdata from the C structures */ - struct dtd_mmc *dtplat = &plat->dtplat; - - plat->fifo_depth = dtplat->fifo_depth; - #endif - /* Set up the device from the plat data */ - writel(plat->fifo_depth, ...) - } - - static const struct udevice_id mmc_ids[] = { - { .compatible = "vendor,mmc" }, - { } - }; - - U_BOOT_DRIVER(mmc_drv) = { - .name = "mmc_drv", - .id = UCLASS_MMC, - .of_match = mmc_ids, - .of_to_plat = mmc_of_to_plat, - .probe = mmc_probe, - .priv_auto = sizeof(struct mmc_priv), - .plat_auto = sizeof(struct mmc_plat), - }; - - DM_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */ - -Note that struct mmc_plat is defined in the C file, not in a header. This -is to avoid needing to include dt-structs.h in a header file. The idea is to -keep the use of each of-platdata struct to the smallest possible code area. -There is just one driver C file for each struct, that can convert from the -of-platdata struct to the standard one used by the driver. - -In the case where SPL_OF_PLATDATA is enabled, plat_auto is -still used to allocate space for the platform data. This is different from -the normal behaviour and is triggered by the use of of-platdata (strictly -speaking it is a non-zero plat_size which triggers this). - -The of-platdata struct contents is copied from the C structure data to the -start of the newly allocated area. In the case where device tree is used, -the platform data is allocated, and starts zeroed. In this case the -of_to_plat() method should still set up the platform data (and the -of-platdata struct will not be present). - -SPL must use either of-platdata or device tree. Drivers cannot use both at -the same time, but they must support device tree. Supporting of-platdata is -optional. - -The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled, -since the device-tree access code is not compiled in. A corollary is that -a board can only move to using of-platdata if all the drivers it uses support -it. There would be little point in having some drivers require the device -tree data, since then libfdt would still be needed for those drivers and -there would be no code-size benefit. - -Internals ---------- - -The dt-structs.h file includes the generated file -(include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled. -Otherwise (such as in U-Boot proper) these structs are not available. This -prevents them being used inadvertently. All usage must be bracketed with -#if CONFIG_IS_ENABLED(OF_PLATDATA). - -The dt-plat.c file contains the device declarations and is is built in -spl/dt-plat.c. - -The dm_populate_phandle_data() function that was previous needed has now been -removed, since dtoc can address the drivers directly from dt-plat.c and does -not need to fix up things at runtime. - -The pylibfdt Python module is used to access the devicetree. - - -Credits -------- - -This is an implementation of an idea by Tom Rini <trini@konsulko.com>. - - -Future work ------------ -- Consider programmatically reading binding files instead of device tree - contents - - -.. Simon Glass <sjg@chromium.org> -.. Google, Inc -.. 6/6/16 -.. Updated Independence Day 2016 -.. Updated 1st October 2020 diff --git a/doc/index.rst b/doc/index.rst index 4c44955d67..02de1d4684 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -38,29 +38,6 @@ want to contribute to U-Boot. develop/index -Unified Extensible Firmware (UEFI) ----------------------------------- - -U-Boot provides an implementation of the UEFI API allowing to run UEFI -compliant software like Linux, GRUB, and iPXE. Furthermore U-Boot itself -can be run an UEFI payload. - -.. toctree:: - :maxdepth: 2 - - uefi/index - -Driver-Model documentation --------------------------- - -The following holds information on the U-Boot device driver framework: -driver-model, including the design details of itself and several driver -subsystems. - -.. toctree:: - :maxdepth: 2 - - driver-model/index U-Boot API documentation ------------------------ @@ -110,6 +87,14 @@ Android-specific features available in U-Boot. android/index +Chromium OS-specific doc +------------------------ + +.. toctree:: + :maxdepth: 2 + + chromium/index + Indices and tables ================== diff --git a/doc/usage/fit.rst b/doc/usage/fit.rst new file mode 100644 index 0000000000..7037434057 --- /dev/null +++ b/doc/usage/fit.rst @@ -0,0 +1,8 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Flat Image Tree (FIT) +===================== + +U-Boot uses Flat Image Tree (FIT) as a standard file format for packaging +images that it it reads and boots. Documentation about FIT is available at +doc/uImage.FIT diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 6c59bbadab..5faf279f43 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -6,6 +6,7 @@ Use U-Boot dfu fdt_overlays + fit netconsole partitions @@ -21,6 +22,7 @@ Shell commands booti bootmenu button + x86/cbsysinfo conitrace echo exception @@ -30,7 +32,9 @@ Shell commands load loady mbr + md pstore qfw sbi true + scp03 diff --git a/doc/usage/md.rst b/doc/usage/md.rst new file mode 100644 index 0000000000..4c1073ea35 --- /dev/null +++ b/doc/usage/md.rst @@ -0,0 +1,106 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +md command +========== + +Synopis +------- + +:: + + md <address>[<data_size>] [<length>] + +Description +----------- + +The md command is used to dump the contents of memory. It uses a standard +format that includes the address, hex data and ASCII display. It supports +various data sizes and uses the endianness of the target. + +The specified data_size and length become the defaults for future memory +commands commands. + +address + start address to display + +data_size + size of each value to display (defaults to .l): + + ========= =================== + data_size Output size + ========= =================== + .b byte + .w word (16 bits) + .l long (32 bits) + .q quadword (64 bits) + ========= =================== + +length + number of values to dump. Defaults to 40 (0d64). Note that this is not + the same as the number of bytes, unless .b is used. + +Note that the format of 'md.b' can be emulated from linux with:: + + # This works but requires using sed to get the extra spaces + # <addr> is the address, <f> is the filename + xxd -o <addr> -g1 <f> |sed 's/ / /' >bad + + # This uses a single tool but the offset always starts at 0 + # <f> is the filename + hexdump -v -e '"%08.8_ax: " 16/1 "%02x " " "' -e '16/1 "%_p" "\n" ' <f> + + +Example +------- + +:: + + => md 10000 + 00010000: 00010000 00000000 f0f30f00 00005596 .............U.. + 00010010: 10011010 00000000 10011010 00000000 ................ + 00010020: 10011050 00000000 b96d4cd8 00007fff P........Lm..... + 00010030: 00000000 00000000 f0f30f18 00005596 .............U.. + 00010040: 10011040 00000000 10011040 00000000 @.......@....... + 00010050: b96d4cd8 00007fff 10011020 00000000 .Lm..... ....... + 00010060: 00000003 000000c3 00000000 00000000 ................ + 00010070: 00000000 00000000 f0e892f3 00005596 .............U.. + 00010080: 00000000 000000a1 00000000 00000000 ................ + 00010090: 00000000 00000000 f0e38aa6 00005596 .............U.. + 000100a0: 00000000 000000a6 00000022 00000000 ........"....... + 000100b0: 00000001 00000000 f0e38aa1 00005596 .............U.. + 000100c0: 00000000 000000be 00000000 00000000 ................ + 000100d0: 00000000 00000000 00000000 00000000 ................ + 000100e0: 00000000 00000000 00000000 00000000 ................ + 000100f0: 00000000 00000000 00000000 00000000 ................ + => md.b 10000 + 00010000: 00 00 01 00 00 00 00 00 00 0f f3 f0 96 55 00 00 .............U.. + 00010010: 10 10 01 10 00 00 00 00 10 10 01 10 00 00 00 00 ................ + 00010020: 50 10 01 10 00 00 00 00 d8 4c 6d b9 ff 7f 00 00 P........Lm..... + 00010030: 00 00 00 00 00 00 00 00 18 0f f3 f0 96 55 00 00 .............U.. + => md.b 10000 10 + 00010000: 00 00 01 00 00 00 00 00 00 0f f3 f0 96 55 00 00 .............U.. + => + 00010010: 10 10 01 10 00 00 00 00 10 10 01 10 00 00 00 00 ................ + => + 00010020: 50 10 01 10 00 00 00 00 d8 4c 6d b9 ff 7f 00 00 P........Lm..... + => + => md.q 10000 + 00010000: 0000000000010000 00005596f0f30f00 .............U.. + 00010010: 0000000010011010 0000000010011010 ................ + 00010020: 0000000010011050 00007fffb96d4cd8 P........Lm..... + 00010030: 0000000000000000 00005596f0f30f18 .............U.. + 00010040: 0000000010011040 0000000010011040 @.......@....... + 00010050: 00007fffb96d4cd8 0000000010011020 .Lm..... ....... + 00010060: 000000c300000003 0000000000000000 ................ + 00010070: 0000000000000000 00005596f0e892f3 .............U.. + +The empty commands cause a 'repeat', so that md shows the next available data +in the same format as before. + + +Return value +------------ + +The return value $? is always 0 (true). + + diff --git a/doc/usage/scp03.rst b/doc/usage/scp03.rst new file mode 100644 index 0000000000..7ff87ed85a --- /dev/null +++ b/doc/usage/scp03.rst @@ -0,0 +1,33 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +scp03 command +============= + +Synopsis +-------- + +:: + + scp03 enable + scp03 provision + +Description +----------- + +The *scp03* command calls into a Trusted Application executing in a +Trusted Execution Environment to enable (if present) the Secure +Channel Protocol 03 stablished between the processor and the secure +element. + +This protocol encrypts all the communication between the processor and +the secure element using a set of pre-defined keys. These keys can be +rotated (provisioned) using the *provision* request. + +See also +-------- + +For some information on the internals implemented in the TEE, please +check the GlobalPlatform documentation on `Secure Channel Protocol '03'`_ + +.. _Secure Channel Protocol '03': + https://globalplatform.org/wp-content/uploads/2014/07/GPC_2.3_D_SCP03_v1.1.2_PublicRelease.pdf diff --git a/doc/usage/x86/cbsysinfo.rst b/doc/usage/x86/cbsysinfo.rst new file mode 100644 index 0000000000..8c03a85169 --- /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 |