diff options
| author | Tom Rini <[email protected]> | 2023-07-05 11:28:55 -0400 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2023-07-05 11:28:55 -0400 |
| commit | e80f4079b3a3db0961b73fa7a96e6c90242d8d25 (patch) | |
| tree | 5352d65d18b44e0982152654dc9f8018047e65ae /doc/usage | |
| parent | 45f77b807c2f6b8da88ae897b7eb2238e25df36b (diff) | |
| parent | e1bebc16e1d9aa0ddd56c53c0b781f7186dce557 (diff) | |
Merge tag 'v2023.07-rc6' into next
Prepare v2023.07-rc6
Diffstat (limited to 'doc/usage')
30 files changed, 4721 insertions, 3 deletions
diff --git a/doc/usage/cmd/bind.rst b/doc/usage/cmd/bind.rst new file mode 100644 index 00000000000..1a5cffcb723 --- /dev/null +++ b/doc/usage/cmd/bind.rst @@ -0,0 +1,103 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +bind command +============ + +Synopsis +-------- + +:: + + bind <node path> <driver> + bind <class> <index> <driver> + +Description +----------- + +The bind command is used to bind a device to a driver. This makes the +device available in U-Boot. + +While binding to a *node path* typically provides a working device +binding by parent node and driver may lead to a device that is only +partially initialized. + +node path + path of the device's device-tree node + +class + device class name + +index + index of the parent device in the device class + +driver + device driver name + +Example +------- + +Given a system with a real time clock device with device path */pl031@9010000* +and using driver rtc-pl031 unbinding and binding of the device is demonstrated +using the two alternative bind syntaxes. + +.. code-block:: + + => dm tree + Class Index Probed Driver Name + ----------------------------------------------------------- + root 0 [ + ] root_driver root_driver + ... + rtc 0 [ ] rtc-pl031 |-- pl031@9010000 + ... + => fdt addr $fdtcontroladdr + Working FDT set to 7ed7fdb0 + => fdt print + / { + interrupt-parent = <0x00008003>; + model = "linux,dummy-virt"; + #size-cells = <0x00000002>; + #address-cells = <0x00000002>; + compatible = "linux,dummy-virt"; + ... + pl031@9010000 { + clock-names = "apb_pclk"; + clocks = <0x00008000>; + interrupts = <0x00000000 0x00000002 0x00000004>; + reg = <0x00000000 0x09010000 0x00000000 0x00001000>; + compatible = "arm,pl031", "arm,primecell"; + }; + ... + } + => unbind /pl031@9010000 + => date + Cannot find RTC: err=-19 + => dm tree + Class Index Probed Driver Name + ----------------------------------------------------------- + root 0 [ + ] root_driver root_driver + ... + => bind /pl031@9010000 rtc-pl031 + => dm tree + Class Index Probed Driver Name + ----------------------------------------------------------- + root 0 [ + ] root_driver root_driver + ... + rtc 0 [ ] rtc-pl031 |-- pl031@9010000 + => date + Date: 2023-06-22 (Thursday) Time: 15:14:51 + => unbind rtc 0 rtc-pl031 + => bind root 0 rtc-pl031 + => date + Date: 1980-08-19 (Tuesday) Time: 14:45:30 + +Obviously the device is not initialized correctly by the last bind command. + +Configuration +------------- + +The bind command is only available if CONFIG_CMD_BIND=y. + +Return code +----------- + +The return code $? is 0 (true) on success and 1 (false) on failure. diff --git a/doc/usage/cmd/bootm.rst b/doc/usage/cmd/bootm.rst new file mode 100644 index 00000000000..a7e5f6ce69a --- /dev/null +++ b/doc/usage/cmd/bootm.rst @@ -0,0 +1,300 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +bootm command +============= + +Synopsis +-------- + +:: + + bootm [fit_addr]#<conf>[#extra-conf] + bootm [[fit_addr]:<os_subimg>] [[<fit_addr2>]:<rd_subimg2>] [[<fit_addr3>]:<fdt_subimg>] + + bootm <addr1> [[<addr2> [<addr3>]] # Legacy boot + +Description +----------- + +The *bootm* command is used to boot an Operating System. It has a large number +of options depending on what needs to be booted. + +Note that the second form supports the first and/or second arguments to be +omitted by using a hyphen '-' instead. + +fit_addr / fit_addr2 / fit_addr3 + address of FIT to boot, defaults to CONFIG_SYS_LOAD_ADDR. See notes below. + +conf + configuration unit to boot (must be preceded by hash '#') + +extra-conf + extra configuration to boot. This is supported only for additional + devicetree overlays to apply on the base device tree supplied by the first + configuration unit. + +os_subimg + OS sub-image to boot (must be preceded by colon ':') + +rd_subimg + ramdisk sub-image to boot. Use a hyphen '-' if there is no ramdisk but an + FDT is needed. + +fdt_subimg + FDT sub-image to boot + +See below for legacy boot. Booting using :doc:`../fit/index` is recommended. + +Note on current image address +----------------------------- + +When bootm is called without arguments, the image at current image address is +booted. The current image address is the address set most recently by a load +command, etc, and is by default equal to CONFIG_SYS_LOAD_ADDR. For example, +consider the following commands:: + + tftp 200000 /tftpboot/kernel + bootm + # Last command is equivalent to: + # bootm 200000 + +As shown above, with FIT the address portion of any argument +can be omitted. If <addr3> is omitted, then it is assumed that image at +<addr2> should be used. Similarly, when <addr2> is omitted, it is assumed that +image at <addr1> should be used. If <addr1> is omitted, it is assumed that the +current image address is to be used. For example, consider the following +commands:: + + tftp 200000 /tftpboot/uImage + bootm :kernel-1 + # Last command is equivalent to: + # bootm 200000:kernel-1 + + tftp 200000 /tftpboot/uImage + bootm 400000:kernel-1 :ramdisk-1 + # Last command is equivalent to: + # bootm 400000:kernel-1 400000:ramdisk-1 + + tftp 200000 /tftpboot/uImage + bootm :kernel-1 400000:ramdisk-1 :fdt-1 + # Last command is equivalent to: + # bootm 200000:kernel-1 400000:ramdisk-1 400000:fdt-1 + + +Legacy boot +----------- + +U-Boot supports a legacy image format, enabled by `CONFIG_LEGACY_IMAGE_FORMAT`. +This is not recommended as it is quite limited and insecure. Use +:doc:`../fit/index` instead. It is documented here for old boards which still +use it. + +Arguments are: + +addr1 + address of legacy image to boot. If the image includes a second component + (ramdisk) it is used as well, unless the second parameter is hyphen '-'. + +addr2 + address of legacy image to use as ramdisk + +addr3 + address of legacy image to use as FDT + + +Example syntax +-------------- + +This section provides various examples of possible usage:: + + 1. bootm /* boot image at the current address, equivalent to 2,3,8 */ + +This is equivalent to cases 2, 3 or 8, depending on the type of image at +the current image address. + +Boot method: see cases 2,3,8 + +Legacy uImage syntax +~~~~~~~~~~~~~~~~~~~~ + +:: + + 2. bootm <addr1> /* single image at <addr1> */ + +Boot kernel image located at <addr1>. + +Boot method: non-FDT + +:: + + 3. bootm <addr1> /* multi-image at <addr1> */ + +First and second components of the image at <addr1> are assumed to be a +kernel and a ramdisk, respectively. The kernel is booted with initrd loaded +with the ramdisk from the image. + +Boot method: depends on the number of components at <addr1>, and on whether +U-Boot is compiled with OF support, which it should be. + + ==================== ======================== ======================== + Configuration 2 components 3 components + (kernel, initrd) (kernel, initrd, fdt) + ==================== ======================== ======================== + #ifdef CONFIG_OF_* non-FDT FDT + #ifndef CONFIG_OF_* non-FDT non-FDT + ==================== ======================== ======================== + +:: + + 4. bootm <addr1> - /* multi-image at <addr1> */ + +Similar to case 3, but the kernel is booted without initrd. Second +component of the multi-image is irrelevant (it can be a dummy, 1-byte file). + +Boot method: see case 3 + +:: + + 5. bootm <addr1> <addr2> /* single image at <addr1> */ + +Boot kernel image located at <addr1> with initrd loaded with ramdisk +from the image at <addr2>. + +Boot method: non-FDT + +:: + + 6. bootm <addr1> <addr2> <addr3> /* single image at <addr1> */ + +<addr1> is the address of a kernel image, <addr2> is the address of a +ramdisk image, and <addr3> is the address of a FDT binary blob. Kernel is +booted with initrd loaded with ramdisk from the image at <addr2>. + +Boot method: FDT + +:: + + 7. bootm <addr1> - <addr3> /* single image at <addr1> */ + +<addr1> is the address of a kernel image and <addr3> is the address of +a FDT binary blob. Kernel is booted without initrd. + +Boot method: FDT + +FIT syntax +~~~~~~~~~~ + +:: + + 8. bootm <addr1> + +Image at <addr1> is assumed to contain a default configuration, which +is booted. + +Boot method: FDT or non-FDT, depending on whether the default configuration +defines FDT + +:: + + 9. bootm [<addr1>]:<subimg1> + +Similar to case 2: boot kernel stored in <subimg1> from the image at +address <addr1>. + +Boot method: non-FDT + +:: + + 10. bootm [<addr1>]#<conf>[#<extra-conf[#...]] + +Boot configuration <conf> from the image at <addr1>. + +Boot method: FDT or non-FDT, depending on whether the configuration given +defines FDT + +:: + + 11. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> + +Equivalent to case 5: boot kernel stored in <subimg1> from the image +at <addr1> with initrd loaded with ramdisk <subimg2> from the image at +<addr2>. + +Boot method: non-FDT + +:: + + 12. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> [<addr3>]:<subimg3> + +Equivalent to case 6: boot kernel stored in <subimg1> from the image +at <addr1> with initrd loaded with ramdisk <subimg2> from the image at +<addr2>, and pass FDT blob <subimg3> from the image at <addr3>. + +Boot method: FDT + +:: + + 13. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> <addr3> + +Similar to case 12, the difference being that <addr3> is the address +of FDT binary blob that is to be passed to the kernel. + +Boot method: FDT + +:: + + 14. bootm [<addr1>]:<subimg1> - [<addr3>]:<subimg3> + +Equivalent to case 7: boot kernel stored in <subimg1> from the image +at <addr1>, without initrd, and pass FDT blob <subimg3> from the image at +<addr3>. + +Boot method: FDT + + 15. bootm [<addr1>]:<subimg1> - <addr3> + +Similar to case 14, the difference being that <addr3> is the address +of the FDT binary blob that is to be passed to the kernel. + +Boot method: FDT + + + +Example +------- + +boot kernel "kernel-1" stored in a new uImage located at 200000:: + + bootm 200000:kernel-1 + +boot configuration "cfg-1" from a new uImage located at 200000:: + + bootm 200000#cfg-1 + +boot configuration "cfg-1" with extra "cfg-2" from a new uImage located +at 200000:: + + bootm 200000#cfg-1#cfg-2 + +boot "kernel-1" from a new uImage at 200000 with initrd "ramdisk-2" found in +some other new uImage stored at address 800000:: + + bootm 200000:kernel-1 800000:ramdisk-2 + +boot "kernel-2" from a new uImage at 200000, with initrd "ramdisk-1" and FDT +"fdt-1", both stored in some other new uImage located at 800000:: + + bootm 200000:kernel-1 800000:ramdisk-1 800000:fdt-1 + +boot kernel "kernel-2" with initrd "ramdisk-2", both stored in a new uImage +at address 200000, with a raw FDT blob stored at address 600000:: + + bootm 200000:kernel-2 200000:ramdisk-2 600000 + +boot kernel "kernel-2" from new uImage at 200000 with FDT "fdt-1" from the +same new uImage:: + + bootm 200000:kernel-2 - 200000:fdt-1 + +.. sectionauthor:: Bartlomiej Sieka <[email protected]> +.. sectionauthor:: Simon Glass <[email protected]> diff --git a/doc/usage/cmd/imxtract.rst b/doc/usage/cmd/imxtract.rst new file mode 100644 index 00000000000..eb64b1cefab --- /dev/null +++ b/doc/usage/cmd/imxtract.rst @@ -0,0 +1,81 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +imxtract command +================ + +Synopsis +-------- + +:: + + imxtract addr part [dest] + imxtract addr uname [dest] + +Description +----------- + +The imxtract command is used to extract a part of a multi-image file. + +Two different file formats are supported: + +* FIT images +* legacy U-Boot images + +addr + Address of the multi-image file from which a part shall be extracted + +part + Index (hexadecimal) of the part of a legacy U-Boot image to be extracted + +uname + Name of the part of a FIT image to be extracted + +dest + Destination address (defaults to 0x0) + +The value of environment variable *verify* controls if the hashes and +signatures of FIT images or the check sums of legacy U-Boot images are checked. +To enable checking set *verify* to one of the values *1*, *yes*, *true*. +(Actually only the first letter is checked disregarding the case.) + +To list the parts of an image the *iminfo* command can be used. + +Examples +-------- + +With verify=no incorrect hashes, signatures, or check sums don't stop the +extraction. But correct hashes are still indicated in the output +(here: md5, sha1). + +.. code-block:: console + + => setenv verify no + => imxtract $loadaddr kernel-1 $kernel_addr_r + ## Copying 'kernel-1' subimage from FIT image at 40200000 ... + md5+ sha1+ Loading part 0 ... OK + => + +With verify=yes incorrect hashes, signatures, or check sums stop the extraction. + +.. code-block:: console + + => setenv verify yes + => imxtract $loadaddr kernel-1 $kernel_addr_r + ## Copying 'kernel-1' subimage from FIT image at 40200000 ... + md5 error! + Bad hash value for 'hash-1' hash node in 'kernel-1' image node + Bad Data Hash + => + +Configuration +------------- + +The imxtract command is only available if CONFIG_CMD_XIMG=y. Support for FIT +images requires CONFIG_FIT=y. Support for legacy U-Boot images requires +CONFIG_LEGACY_IMAGE_FORMAT=y. + +Return value +------------ + +On success the return value $? of the command is 0 (true). On failure the +return value is 1 (false). diff --git a/doc/usage/cmd/loadb.rst b/doc/usage/cmd/loadb.rst index b37d1d7b596..0464b1f41ce 100644 --- a/doc/usage/cmd/loadb.rst +++ b/doc/usage/cmd/loadb.rst @@ -13,7 +13,7 @@ Synopsis Description ----------- -The loady command is used to transfer a file to the device via the serial line +The loadb command is used to transfer a file to the device via the serial line using the Kermit protocol. The number of transferred bytes is saved in environment variable filesize. diff --git a/doc/usage/cmd/loads.rst b/doc/usage/cmd/loads.rst new file mode 100644 index 00000000000..e4cb063df6d --- /dev/null +++ b/doc/usage/cmd/loads.rst @@ -0,0 +1,96 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +loads command +============= + +Synopsis +-------- + +:: + + loads [offset [baud]] + +Description +----------- + +The loads command is used to transfer a file to the device via the serial line +using the Motorola S-record file format. + +offset + offset added to the addresses in the S-record file + +baud + baud rate to use for download. This parameter is only available if + CONFIG_SYS_LOADS_BAUD_CHANGE=y + +Example +------- + +As example file to be transferred we use a script printing 'hello s-record'. +Here are the commands to create the S-record file: + +.. code-block:: bash + + $ echo 'echo hello s-record' > script.txt + $ mkimage -T script -d script.txt script.scr + Image Name: + Created: Sun Jun 25 10:35:02 2023 + Image Type: PowerPC Linux Script (gzip compressed) + Data Size: 28 Bytes = 0.03 KiB = 0.00 MiB + Load Address: 00000000 + Entry Point: 00000000 + Contents: + Image 0: 20 Bytes = 0.02 KiB = 0.00 MiB + $ srec_cat script.scr -binary -CRLF -Output script.srec + $ echo -e "S9030000FC\r" >> script.srec + $ cat script.srec + S0220000687474703A2F2F737265636F72642E736F75726365666F7267652E6E65742F1D + S1230000270519566D773EB6649815E30000001700000000000000003DE3D97005070601E2 + S12300200000000000000000000000000000000000000000000000000000000000000000BC + S11A00400000000F0000000068656C6C6F20732D7265636F72640A39 + S5030003F9 + S9030000FC + $ + +The load address in the first S1 record is 0x0000. + +The terminal emulation program picocom is invoked with *cat* as the send +command to transfer the file. + +.. code-block:: + + picocom --send-cmd 'cat' --baud 115200 /dev/ttyUSB0 + +After entering the *loads* command the key sequence <CTRL-A><CTRL-S> is used to +let picocom prompt for the file name. Picocom invokes the program *cat* for the +file transfer. The loaded script is executed using the *source* command. + +.. code-block:: + + => loads $scriptaddr + ## Ready for S-Record download ... + + *** file: script.srec + $ cat script.srec + + *** exit status: 0 *** + + ## First Load Addr = 0x4FC00000 + ## Last Load Addr = 0x4FC0005B + ## Total Size = 0x0000005C = 92 Bytes + ## Start Addr = 0x00000000 + => source $scriptaddr + ## Executing script at 4fc00000 + hello s-record + => + +Configuration +------------- + +The command is only available if CONFIG_CMD_LOADS=y. The parameter to set the +baud rate is only available if CONFIG_SYS_LOADS_BAUD_CHANGE=y + +Return value +------------ + +The return value $? is 0 (true) on success, 1 (false) otherwise. diff --git a/doc/usage/cmd/saves.rst b/doc/usage/cmd/saves.rst new file mode 100644 index 00000000000..5823f883790 --- /dev/null +++ b/doc/usage/cmd/saves.rst @@ -0,0 +1,88 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +saves command +============= + +Synopsis +-------- + +:: + + saves [offset [size [baud]]] + +Description +----------- + +The *saves* command is used to transfer a file from the device via the serial +line using the Motorola S-record file format. + +offset + start address of memory area to save, defaults to 0x0 + +size + size of memory area to save, defaults to 0x0 + +baud + baud rate to use for upload. This parameter is only available if + CONFIG_SYS_LOADS_BAUD_CHANGE=y + +Example +------- + +In the example the *screen* command is used to connect to the U-Boot serial +console. + +In a first screen session a file is loaded from the SD-card and the *saves* +command is invoked. <CTRL+A><k> is used to kill the screen session. + +A new screen session is started which logs the output to a file and the +<ENTER> key is hit to start the file output. <CTRL+A><k> is issued to kill the +screen session. + +The log file is converted to a binary file using the *srec_cat* command. +A negative offset of -1337982976 (= -0x4c000000) is applied to compensate for +the offset used in the *saves* command. + +.. code-block:: + + $ screen /dev/ttyUSB0 115200 + => echo $scriptaddr + 0x4FC00000 + => load mmc 0:1 $scriptaddr boot.txt + 124 bytes read in 1 ms (121.1 KiB/s) + => saves $scriptaddr $filesize + ## Ready for S-Record upload, press ENTER to proceed ... + Really kill this window [y/n] + $ screen -Logfile out.srec -L /dev/ttyUSB0 115200 + S0030000FC + S3154FC00000736574656E76206175746F6C6F616420AD + S3154FC000106E6F0A646863700A6C6F6164206D6D633E + S3154FC0002020303A3120246664745F616464725F72B3 + S3154FC00030206474620A6C6F6164206D6D6320303AC0 + S3154FC000403120246B65726E656C5F616464725F72DA + S3154FC0005020736E702E6566690A626F6F74656669C6 + S3154FC0006020246B65726E656C5F616464725F7220CB + S3114FC00070246664745F616464725F720A38 + S70500000000FA + ## S-Record upload complete + => + Really kill this window [y/n] + $ srec_cat out.srec -offset -1337982976 -Output out.txt -binary 2>/dev/null + $ cat out.txt + setenv autoload no + dhcp + load mmc 0:1 $fdt_addr_r dtb + load mmc 0:1 $kernel_addr_r snp.efi + bootefi $kernel_addr_r $fdt_addr_r + $ + +Configuration +------------- + +The command is only available if CONFIG_CMD_SAVES=y. The parameter to set the +baud rate is only available if CONFIG_SYS_LOADS_BAUD_CHANGE=y + +Return value +------------ + +The return value $? is 0 (true) on success, 1 (false) otherwise. diff --git a/doc/usage/cmd/source.rst b/doc/usage/cmd/source.rst index a5c5204a28b..697f644745b 100644 --- a/doc/usage/cmd/source.rst +++ b/doc/usage/cmd/source.rst @@ -22,7 +22,7 @@ Two formats for script files exist: * Flat Image Tree (FIT) The benefit of the FIT images is that they can be signed and verifed as -decribed in :download:`signature.txt <../../uImage.FIT/signature.txt>`. +described in :doc:`../fit/signature`. Both formats can be created with the mkimage tool. diff --git a/doc/usage/cmd/unbind.rst b/doc/usage/cmd/unbind.rst new file mode 100644 index 00000000000..594e4f06892 --- /dev/null +++ b/doc/usage/cmd/unbind.rst @@ -0,0 +1,95 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +unbind command +============== + +Synopsis +-------- + +:: + + unbind <node path> + unbind <class> <index> + unbind <class> <index> <driver> + +Description +----------- + +The unbind command is used to unbind a device from a driver. This makes the +device unavailable in U-Boot. + +node path + path of the device's device-tree node + +class + device class name + +index + index of the device in the device class + +driver + device driver name + +Example +------- + +Given a system with a real time clock device with device path */pl031@9010000* +and using driver rtc-pl031 unbinding and binding of the device is demonstrated +using the three alternative unbind syntaxes. + +.. code-block:: + + => dm tree + Class Index Probed Driver Name + ----------------------------------------------------------- + root 0 [ + ] root_driver root_driver + ... + rtc 0 [ ] rtc-pl031 |-- pl031@9010000 + ... + => fdt addr $fdtcontroladdr + Working FDT set to 7ed7fdb0 + => fdt print + / { + interrupt-parent = <0x00008003>; + model = "linux,dummy-virt"; + #size-cells = <0x00000002>; + #address-cells = <0x00000002>; + compatible = "linux,dummy-virt"; + ... + pl031@9010000 { + clock-names = "apb_pclk"; + clocks = <0x00008000>; + interrupts = <0x00000000 0x00000002 0x00000004>; + reg = <0x00000000 0x09010000 0x00000000 0x00001000>; + compatible = "arm,pl031", "arm,primecell"; + }; + ... + } + => unbind /pl031@9010000 + => dm tree + Class Index Probed Driver Name + ----------------------------------------------------------- + root 0 [ + ] root_driver root_driver + ... + => unbind /pl031@9010000 + Cannot find a device with path /pl031@9010000 + => bind /pl031@9010000 rtc-pl031 + => dm tree + Class Index Probed Driver Name + ----------------------------------------------------------- + root 0 [ + ] root_driver root_driver + ... + rtc 0 [ ] rtc-pl031 |-- pl031@9010000 + => unbind rtc 0 + => bind /pl031@9010000 rtc-pl031 + => unbind rtc 0 rtc-pl031 + +Configuration +------------- + +The unbind command is only available if CONFIG_CMD_BIND=y. + +Return code +----------- + +The return code $? is 0 (true) on success and 1 (false) on failure. diff --git a/doc/usage/fit/beaglebone_vboot.rst b/doc/usage/fit/beaglebone_vboot.rst new file mode 100644 index 00000000000..0580ee10bdc --- /dev/null +++ b/doc/usage/fit/beaglebone_vboot.rst @@ -0,0 +1,612 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Verified Boot on the Beaglebone Black +===================================== + +Introduction +------------ + +Before reading this, please read :doc:`verified-boot` and :doc:`signature`. +These instructions are for mainline U-Boot from v2014.07 onwards. + +There is quite a bit of documentation in this directory describing how +verified boot works in U-Boot. There is also a test which runs through the +entire process of signing an image and running U-Boot (sandbox) to check it. +However, it might be useful to also have an example on a real board. + +Beaglebone Black is a fairly common board so seems to be a reasonable choice +for an example of how to enable verified boot using U-Boot. + +First a note that may to help avoid confusion. U-Boot and Linux both use +device tree. They may use the same device tree source, but it is seldom useful +for them to use the exact same binary from the same place. More typically, +U-Boot has its device tree packaged with it, and the kernel's device tree is +packaged with the kernel. In particular this is important with verified boot, +since U-Boot's device tree must be immutable. If it can be changed then the +public keys can be changed and verified boot is useless. An attacker can +simply generate a new key and put his public key into U-Boot so that +everything verifies. On the other hand the kernel's device tree typically +changes when the kernel changes, so it is useful to package an updated device +tree with the kernel binary. U-Boot supports the latter with its flexible FIT +format (Flat Image Tree). + + +Overview +-------- + +The steps are roughly as follows: + +#. Build U-Boot for the board, with the verified boot options enabled. + +#. Obtain a suitable Linux kernel + +#. Create a Image Tree Source file (ITS) file describing how you want the + kernel to be packaged, compressed and signed. + +#. Create a key pair + +#. Sign the kernel + +#. Put the public key into U-Boot's image + +#. Put U-Boot and the kernel onto the board + +#. Try it + + +Step 1: Build U-Boot +-------------------- + +a. Set up the environment variable to point to your toolchain. You will need + this for U-Boot and also for the kernel if you build it. For example if you + installed a Linaro version manually it might be something like:: + + export CROSS_COMPILE=/opt/linaro/gcc-linaro-arm-linux-gnueabihf-4.8-2013.08_linux/bin/arm-linux-gnueabihf- + + or if you just installed gcc-arm-linux-gnueabi then it might be:: + + export CROSS_COMPILE=arm-linux-gnueabi- + +b. Configure and build U-Boot with verified boot enabled:: + + export UBOOT=/path/to/u-boot + cd $UBOOT + # You can add -j10 if you have 10 CPUs to make it faster + make O=b/am335x_boneblack_vboot am335x_boneblack_vboot_config all + export UOUT=$UBOOT/b/am335x_boneblack_vboot + +c. You will now have a U-Boot image:: + + file b/am335x_boneblack_vboot/u-boot-dtb.img + b/am335x_boneblack_vboot/u-boot-dtb.img: u-boot legacy uImage, + U-Boot 2014.07-rc2-00065-g2f69f8, Firmware/ARM, Firmware Image + (Not compressed), 395375 bytes, Sat May 31 16:19:04 2014, + Load Address: 0x80800000, Entry Point: 0x00000000, + Header CRC: 0x0ABD6ACA, Data CRC: 0x36DEF7E4 + + +Step 2: Build Linux +-------------------- + +a. Find the kernel image ('Image') and device tree (.dtb) file you plan to + use. In our case it is am335x-boneblack.dtb and it is built with the kernel. + At the time of writing an SD Boot image can be obtained from here:: + + http://www.elinux.org/Beagleboard:Updating_The_Software#Image_For_Booting_From_microSD + + You can write this to an SD card and then mount it to extract the kernel and + device tree files. + + You can also build a kernel. Instructions for this are are here:: + + http://elinux.org/Building_BBB_Kernel + + or you can use your favourite search engine. Following these instructions + produces a kernel Image and device tree files. For the record the steps + were:: + + export KERNEL=/path/to/kernel + cd $KERNEL + git clone git://github.com/beagleboard/kernel.git . + git checkout v3.14 + ./patch.sh + cp configs/beaglebone kernel/arch/arm/configs/beaglebone_defconfig + cd kernel + make beaglebone_defconfig + make uImage dtbs # -j10 if you have 10 CPUs + export OKERNEL=$KERNEL/kernel/arch/arm/boot + +b. You now have the 'Image' and 'am335x-boneblack.dtb' files needed to boot. + + +Step 3: Create the ITS +---------------------- + +Set up a directory for your work:: + + export WORK=/path/to/dir + cd $WORK + +Put this into a file in that directory called sign.its:: + + /dts-v1/; + + / { + description = "Beaglebone black"; + #address-cells = <1>; + + images { + kernel { + data = /incbin/("Image.lzo"); + type = "kernel"; + arch = "arm"; + os = "linux"; + compression = "lzo"; + load = <0x80008000>; + entry = <0x80008000>; + hash-1 { + algo = "sha1"; + }; + }; + fdt-1 { + description = "beaglebone-black"; + data = /incbin/("am335x-boneblack.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash-1 { + algo = "sha1"; + }; + }; + }; + configurations { + default = "conf-1"; + conf-1 { + kernel = "kernel"; + fdt = "fdt-1"; + signature-1 { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + sign-images = "fdt", "kernel"; + }; + }; + }; + }; + + +The explanation for this is all in the documentation you have already read. +But briefly it packages a kernel and device tree, and provides a single +configuration to be signed with a key named 'dev'. The kernel is compressed +with LZO to make it smaller. + + +Step 4: Create a key pair +------------------------- + +See :doc:`signature` for details on this step:: + + cd $WORK + mkdir keys + openssl genrsa -F4 -out keys/dev.key 2048 + openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt + +Note: keys/dev.key contains your private key and is very secret. If anyone +gets access to that file they can sign kernels with it. Keep it secure. + + +Step 5: Sign the kernel +----------------------- + +We need to use mkimage (which was built when you built U-Boot) to package the +Linux kernel into a FIT (Flat Image Tree, a flexible file format that U-Boot +can load) using the ITS file you just created. + +At the same time we must put the public key into U-Boot device tree, with the +'required' property, which tells U-Boot that this key must be verified for the +image to be valid. You will make this key available to U-Boot for booting in +step 6:: + + ln -s $OKERNEL/dts/am335x-boneblack.dtb + ln -s $OKERNEL/Image + ln -s $UOUT/u-boot-dtb.img + cp $UOUT/arch/arm/dts/am335x-boneblack.dtb am335x-boneblack-pubkey.dtb + lzop Image + $UOUT/tools/mkimage -f sign.its -K am335x-boneblack-pubkey.dtb -k keys -r image.fit + +You should see something like this:: + + FIT description: Beaglebone black + Created: Sun Jun 1 12:50:30 2014 + Image 0 (kernel) + Description: unavailable + Created: Sun Jun 1 12:50:30 2014 + Type: Kernel Image + Compression: lzo compressed + Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB + Architecture: ARM + OS: Linux + Load Address: 0x80008000 + Entry Point: 0x80008000 + Hash algo: sha1 + Hash value: c94364646427e10f423837e559898ef02c97b988 + Image 1 (fdt-1) + Description: beaglebone-black + Created: Sun Jun 1 12:50:30 2014 + Type: Flat Device Tree + Compression: uncompressed + Data Size: 31547 Bytes = 30.81 kB = 0.03 MB + Architecture: ARM + Hash algo: sha1 + Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d + Default Configuration: 'conf-1' + Configuration 0 (conf-1) + Description: unavailable + Kernel: kernel + FDT: fdt-1 + + +Now am335x-boneblack-pubkey.dtb contains the public key and image.fit contains +the signed kernel. Jump to step 6 if you like, or continue reading to increase +your understanding. + +You can also run fit_check_sign to check it:: + + $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb + +which results in:: + + Verifying Hash Integrity ... sha1,rsa2048:dev+ + ## Loading kernel from FIT Image at 7fc6ee469000 ... + Using 'conf-1' configuration + Verifying Hash Integrity ... + sha1,rsa2048:dev+ + OK + + Trying 'kernel' kernel subimage + Description: unavailable + Created: Sun Jun 1 12:50:30 2014 + Type: Kernel Image + Compression: lzo compressed + Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB + Architecture: ARM + OS: Linux + Load Address: 0x80008000 + Entry Point: 0x80008000 + Hash algo: sha1 + Hash value: c94364646427e10f423837e559898ef02c97b988 + Verifying Hash Integrity ... + sha1+ + OK + + Unimplemented compression type 4 + ## Loading fdt from FIT Image at 7fc6ee469000 ... + Using 'conf-1' configuration + Trying 'fdt-1' fdt subimage + Description: beaglebone-black + Created: Sun Jun 1 12:50:30 2014 + Type: Flat Device Tree + Compression: uncompressed + Data Size: 31547 Bytes = 30.81 kB = 0.03 MB + Architecture: ARM + Hash algo: sha1 + Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d + Verifying Hash Integrity ... + sha1+ + OK + + Loading Flat Device Tree ... OK + + ## Loading ramdisk from FIT Image at 7fc6ee469000 ... + Using 'conf-1' configuration + Could not find subimage node + + Signature check OK + + +At the top, you see "sha1,rsa2048:dev+". This means that it checked an RSA key +of size 2048 bits using SHA1 as the hash algorithm. The key name checked was +'dev' and the '+' means that it verified. If it showed '-' that would be bad. + +Once the configuration is verified it is then possible to rely on the hashes +in each image referenced by that configuration. So fit_check_sign goes on to +load each of the images. We have a kernel and an FDT but no ramkdisk. In each +case fit_check_sign checks the hash and prints sha1+ meaning that the SHA1 +hash verified. This means that none of the images has been tampered with. + +There is a test in test/vboot which uses U-Boot's sandbox build to verify that +the above flow works. + +But it is fun to do this by hand, so you can load image.fit into a hex editor +like ghex, and change a byte in the kernel:: + + $UOUT/tools/fit_info -f image.fit -n /images/kernel -p data + NAME: kernel + LEN: 7790938 + OFF: 168 + +This tells us that the kernel starts at byte offset 168 (decimal) in image.fit +and extends for about 7MB. Try changing a byte at 0x2000 (say) and run +fit_check_sign again. You should see something like:: + + Verifying Hash Integrity ... sha1,rsa2048:dev+ + ## Loading kernel from FIT Image at 7f5a39571000 ... + Using 'conf-1' configuration + Verifying Hash Integrity ... + sha1,rsa2048:dev+ + OK + + Trying 'kernel' kernel subimage + Description: unavailable + Created: Sun Jun 1 13:09:21 2014 + Type: Kernel Image + Compression: lzo compressed + Data Size: 7790938 Bytes = 7608.34 kB = 7.43 MB + Architecture: ARM + OS: Linux + Load Address: 0x80008000 + Entry Point: 0x80008000 + Hash algo: sha1 + Hash value: c94364646427e10f423837e559898ef02c97b988 + Verifying Hash Integrity ... + sha1 error + Bad hash value for 'hash-1' hash node in 'kernel' image node + Bad Data Hash + + ## Loading fdt from FIT Image at 7f5a39571000 ... + Using 'conf-1' configuration + Trying 'fdt-1' fdt subimage + Description: beaglebone-black + Created: Sun Jun 1 13:09:21 2014 + Type: Flat Device Tree + Compression: uncompressed + Data Size: 31547 Bytes = 30.81 kB = 0.03 MB + Architecture: ARM + Hash algo: sha1 + Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d + Verifying Hash Integrity ... + sha1+ + OK + + Loading Flat Device Tree ... OK + + ## Loading ramdisk from FIT Image at 7f5a39571000 ... + Using 'conf-1' configuration + Could not find subimage node + + Signature check Bad (error 1) + + +It has detected the change in the kernel. + +You can also be sneaky and try to switch images, using the libfdt utilities +that come with dtc (package name is device-tree-compiler but you will need a +recent version like 1.4:: + + dtc -v + Version: DTC 1.4.0 + +First we can check which nodes are actually hashed by the configuration:: + + $ fdtget -l image.fit / + images + configurations + + $ fdtget -l image.fit /configurations + conf-1 + fdtget -l image.fit /configurations/conf-1 + signature-1 + + $ fdtget -p image.fit /configurations/conf-1/signature-1 + hashed-strings + hashed-nodes + timestamp + signer-version + signer-name + value + algo + key-name-hint + sign-images + + $ fdtget image.fit /configurations/conf-1/signature-1 hashed-nodes + / /configurations/conf-1 /images/fdt-1 /images/fdt-1/hash /images/kernel /images/kernel/hash-1 + +This gives us a bit of a look into the signature that mkimage added. Note you +can also use fdtdump to list the entire device tree. + +Say we want to change the kernel that this configuration uses +(/images/kernel). We could just put a new kernel in the image, but we will +need to change the hash to match. Let's simulate that by changing a byte of +the hash:: + + fdtget -tx image.fit /images/kernel/hash-1 value + c9436464 6427e10f 423837e5 59898ef0 2c97b988 + fdtput -tx image.fit /images/kernel/hash-1 value c9436464 6427e10f 423837e5 59898ef0 2c97b981 + +Now check it again:: + + $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb + Verifying Hash Integrity ... sha1,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13 + rsa_verify_with_keynode: RSA failed to verify: -13 + - + Failed to verify required signature 'key-dev' + Signature check Bad (error 1) + +This time we don't even get as far as checking the images, since the +configuration signature doesn't match. We can't change any hashes without the +signature check noticing. The configuration is essentially locked. U-Boot has +a public key for which it requires a match, and will not permit the use of any +configuration that does not match that public key. The only way the +configuration will match is if it was signed by the matching private key. + +It would also be possible to add a new signature node that does match your new +configuration. But that won't work since you are not allowed to change the +configuration in any way. Try it with a fresh (valid) image if you like by +running the mkimage link again. Then:: + + fdtput -p image.fit /configurations/conf-1/signature-1 value fred + $UOUT/tools/fit_check_sign -f image.fit -k am335x-boneblack-pubkey.dtb + Verifying Hash Integrity ... - + sha1,rsa2048:devrsa_verify_with_keynode: RSA failed to verify: -13 + rsa_verify_with_keynode: RSA failed to verify: -13 + - + Failed to verify required signature 'key-dev' + Signature check Bad (error 1) + + +Of course it would be possible to add an entirely new configuration and boot +with that, but it still needs to be signed, so it won't help. + + +6. Put the public key into U-Boot's image +----------------------------------------- + +Having confirmed that the signature is doing its job, let's try it out in +U-Boot on the board. U-Boot needs access to the public key corresponding to +the private key that you signed with so that it can verify any kernels that +you sign:: + + cd $UBOOT + make O=b/am335x_boneblack_vboot EXT_DTB=${WORK}/am335x-boneblack-pubkey.dtb + +Here we are overriding the normal device tree file with our one, which +contains the public key. + +Now you have a special U-Boot image with the public key. It can verify can +kernel that you sign with the private key as in step 5. + +If you like you can take a look at the public key information that mkimage +added to U-Boot's device tree:: + + fdtget -p am335x-boneblack-pubkey.dtb /signature/key-dev + required + algo + rsa,r-squared + rsa,modulus + rsa,n0-inverse + rsa,num-bits + key-name-hint + +This has information about the key and some pre-processed values which U-Boot +can use to verify against it. These values are obtained from the public key +certificate by mkimage, but require quite a bit of code to generate. To save +code space in U-Boot, the information is extracted and written in raw form for +U-Boot to easily use. The same mechanism is used in Google's Chrome OS. + +Notice the 'required' property. This marks the key as required - U-Boot will +not boot any image that does not verify against this key. + + +7. Put U-Boot and the kernel onto the board +------------------------------------------- + +The method here varies depending on how you are booting. For this example we +are booting from an micro-SD card with two partitions, one for U-Boot and one +for Linux. Put it into your machine and write U-Boot and the kernel to it. +Here the card is /dev/sde:: + + cd $WORK + export UDEV=/dev/sde1 # Change thes two lines to the correct device + export KDEV=/dev/sde2 + sudo mount $UDEV /mnt/tmp && sudo cp $UOUT/u-boot-dtb.img /mnt/tmp/u-boot.img && sleep 1 && sudo umount $UDEV + sudo mount $KDEV /mnt/tmp && sudo cp $WORK/image.fit /mnt/tmp/boot/image.fit && sleep 1 && sudo umount $KDEV + + +8. Try it +--------- + +Boot the board using the commands below:: + + setenv bootargs console=ttyO0,115200n8 quiet root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait + ext2load mmc 0:2 82000000 /boot/image.fit + bootm 82000000 + +You should then see something like this:: + + U-Boot# setenv bootargs console=ttyO0,115200n8 quiet root=/dev/mmcblk0p2 ro rootfstype=ext4 rootwait + U-Boot# ext2load mmc 0:2 82000000 /boot/image.fit + 7824930 bytes read in 589 ms (12.7 MiB/s) + U-Boot# bootm 82000000 + ## Loading kernel from FIT Image at 82000000 ... + Using 'conf-1' configuration + Verifying Hash Integrity ... sha1,rsa2048:dev+ OK + Trying 'kernel' kernel subimage + Description: unavailable + Created: 2014-06-01 19:32:54 UTC + Type: Kernel Image + Compression: lzo compressed + Data Start: 0x820000a8 + Data Size: 7790938 Bytes = 7.4 MiB + Architecture: ARM + OS: Linux + Load Address: 0x80008000 + Entry Point: 0x80008000 + Hash algo: sha1 + Hash value: c94364646427e10f423837e559898ef02c97b988 + Verifying Hash Integrity ... sha1+ OK + ## Loading fdt from FIT Image at 82000000 ... + Using 'conf-1' configuration + Trying 'fdt-1' fdt subimage + Description: beaglebone-black + Created: 2014-06-01 19:32:54 UTC + Type: Flat Device Tree + Compression: uncompressed + Data Start: 0x8276e2ec + Data Size: 31547 Bytes = 30.8 KiB + Architecture: ARM + Hash algo: sha1 + Hash value: cb09202f889d824f23b8e4404b781be5ad38a68d + Verifying Hash Integrity ... sha1+ OK + Booting using the fdt blob at 0x8276e2ec + Uncompressing Kernel Image ... OK + Loading Device Tree to 8fff5000, end 8ffffb3a ... OK + + Starting kernel ... + + [ 0.582377] omap_init_mbox: hwmod doesn't have valid attrs + [ 2.589651] musb-hdrc musb-hdrc.0.auto: Failed to request rx1. + [ 2.595830] musb-hdrc musb-hdrc.0.auto: musb_init_controller failed with status -517 + [ 2.606470] musb-hdrc musb-hdrc.1.auto: Failed to request rx1. + [ 2.612723] musb-hdrc musb-hdrc.1.auto: musb_init_controller failed with status -517 + [ 2.940808] drivers/rtc/hctosys.c: unable to open rtc device (rtc0) + [ 7.248889] libphy: PHY 4a101000.mdio:01 not found + [ 7.253995] net eth0: phy 4a101000.mdio:01 not found on slave 1 + systemd-fsck[83]: Angstrom: clean, 50607/218160 files, 306348/872448 blocks + + .---O---. + | | .-. o o + | | |-----.-----.-----.| | .----..-----.-----. + | | | __ | ---'| '--.| .-'| | | + | | | | | |--- || --'| | | ' | | | | + '---'---'--'--'--. |-----''----''--' '-----'-'-'-' + -' | + '---' + + The Angstrom Distribution beaglebone ttyO0 + + Angstrom v2012.12 - Kernel 3.14.1+ + + beaglebone login: + +At this point your kernel has been verified and you can be sure that it is one +that you signed. As an exercise, try changing image.fit as in step 5 and see +what happens. + + +Further Improvements +-------------------- + +Several of the steps here can be easily automated. In particular it would be +capital if signing and packaging a kernel were easy, perhaps a simple make +target in the kernel. + +Some mention of how to use multiple .dtb files in a FIT might be useful. + +U-Boot's verified boot mechanism has not had a robust and independent security +review. Such a review should look at the implementation and its resistance to +attacks. + +Perhaps the verified boot feature could be integrated into the Amstrom +distribution. + + +.. sectionauthor:: Simon Glass <[email protected]>, 2-June-14 diff --git a/doc/usage/fit/howto.rst b/doc/usage/fit/howto.rst new file mode 100644 index 00000000000..c933703d1d0 --- /dev/null +++ b/doc/usage/fit/howto.rst @@ -0,0 +1,419 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +How to use images in the new image format +========================================= + +Overview +-------- + +The new uImage format allows more flexibility in handling images of various +types (kernel, ramdisk, etc.), it also enhances integrity protection of images +with sha1 and md5 checksums. + +Two auxiliary tools are needed on the development host system in order to +create an uImage in the new format: mkimage and dtc, although only one +(mkimage) is invoked directly. dtc is called from within mkimage and operates +behind the scenes, but needs to be present in the $PATH nevertheless. It is +important that the dtc used has support for binary includes -- refer to:: + + git://git.kernel.org/pub/scm/utils/dtc/dtc.git + +for its latest version. mkimage (together with dtc) takes as input +an image source file, which describes the contents of the image and defines +its various properties used during booting. By convention, image source file +has the ".its" extension, also, the details of its format are given in +doc/uImage.FIT/source_file_format.txt. The actual data that is to be included in +the uImage (kernel, ramdisk, etc.) is specified in the image source file in the +form of paths to appropriate data files. The outcome of the image creation +process is a binary file (by convention with the ".itb" extension) that +contains all the referenced data (kernel, ramdisk, etc.) and other information +needed by U-Boot to handle the uImage properly. The uImage file is then +transferred to the target (e.g., via tftp) and booted using the bootm command. + +To summarize the prerequisites needed for new uImage creation: + +- mkimage +- dtc (with support for binary includes) +- image source file (`*.its`) +- image data file(s) + + +Here's a graphical overview of the image creation and booting process:: + + image source file mkimage + dtc transfer to target + + ---------------> image file --------------------> bootm + image data file(s) + +SPL usage +--------- + +The SPL can make use of the new image format as well, this traditionally +is used to ship multiple device tree files within one image. Code in the SPL +will choose the one matching the current board and append this to the +U-Boot proper binary to be automatically used up by it. +Aside from U-Boot proper and one device tree blob the SPL can load multiple, +arbitrary image files as well. These binaries should be specified in their +own subnode under the /images node, which should then be referenced from one or +multiple /configurations subnodes. The required images must be enumerated in +the "loadables" property as a list of strings. + +If a platform specific image source file (.its) is shipped with the U-Boot +source, it can be specified using the CONFIG_SPL_FIT_SOURCE Kconfig symbol. +In this case it will be automatically used by U-Boot's Makefile to generate +the image. +If a static source file is not flexible enough, CONFIG_SPL_FIT_GENERATOR +can point to a script which generates this image source file during +the build process. It gets passed a list of device tree files (taken from the +CONFIG_OF_LIST symbol). + +The SPL also records to a DT all additional images (called loadables) which are +loaded. The information about loadables locations is passed via the DT node with +fit-images name. + +Finally, if there are multiple xPL phases (e.g. SPL, VPL), images can be marked +as intended for a particular phase using the 'phase' property. For example, if +fit_image_load() is called with image_ph(IH_PHASE_SPL, IH_TYPE_FIRMWARE), then +only the image listed into the "firmware" property where phase is set to "spl" +will be loaded. + +Loadables Example +----------------- +Consider the following case for an ARM64 platform where U-Boot runs in EL2 +started by ATF where SPL is loading U-Boot (as loadables) and ATF (as firmware). + +:: + + /dts-v1/; + + / { + description = "Configuration to load ATF before U-Boot"; + + images { + uboot { + description = "U-Boot (64-bit)"; + data = /incbin/("u-boot-nodtb.bin"); + type = "firmware"; + os = "u-boot"; + arch = "arm64"; + compression = "none"; + load = <0x8 0x8000000>; + entry = <0x8 0x8000000>; + hash { + algo = "md5"; + }; + }; + atf { + description = "ARM Trusted Firmware"; + data = /incbin/("bl31.bin"); + type = "firmware"; + os = "arm-trusted-firmware"; + arch = "arm64"; + compression = "none"; + load = <0xfffea000>; + entry = <0xfffea000>; + hash { + algo = "md5"; + }; + }; + fdt_1 { + description = "zynqmp-zcu102-revA"; + data = /incbin/("arch/arm/dts/zynqmp-zcu102-revA.dtb"); + type = "flat_dt"; + arch = "arm64"; + compression = "none"; + load = <0x100000>; + hash { + algo = "md5"; + }; + }; + }; + configurations { + default = "config_1"; + + config_1 { + description = "zynqmp-zcu102-revA"; + firmware = "atf"; + loadables = "uboot"; + fdt = "fdt_1"; + }; + }; + }; + +In this case the SPL records via fit-images DT node the information about +loadables U-Boot image:: + + ZynqMP> fdt addr $fdtcontroladdr + ZynqMP> fdt print /fit-images + fit-images { + uboot { + os = "u-boot"; + type = "firmware"; + size = <0x001017c8>; + entry = <0x00000008 0x08000000>; + load = <0x00000008 0x08000000>; + }; + }; + +As you can see entry and load properties are 64bit wide to support loading +images above 4GB (in past entry and load properties where just 32bit). + + +Example 1 -- old-style (non-FDT) kernel booting +----------------------------------------------- + +Consider a simple scenario, where a PPC Linux kernel built from sources on the +development host is to be booted old-style (non-FDT) by U-Boot on an embedded +target. Assume that the outcome of the build is vmlinux.bin.gz, a file which +contains a gzip-compressed PPC Linux kernel (the only data file in this case). +The uImage can be produced using the image source file +doc/uImage.FIT/kernel.its (note that kernel.its assumes that vmlinux.bin.gz is +in the current working directory; if desired, an alternative path can be +specified in the kernel.its file). Here's how to create the image and inspect +its contents: + +[on the host system]:: + + $ mkimage -f kernel.its kernel.itb + DTC: dts->dtb on file "kernel.its" + $ + $ mkimage -l kernel.itb + FIT description: Simple image with single Linux kernel + Created: Tue Mar 11 17:26:15 2008 + Image 0 (kernel) + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Size: 943347 Bytes = 921.24 kB = 0.90 MB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2ae2bb40 + Hash algo: sha1 + Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4 + Default Configuration: 'config-1' + Configuration 0 (config-1) + Description: Boot Linux kernel + Kernel: kernel + + +The resulting image file kernel.itb can be now transferred to the target, +inspected and booted (note that first three U-Boot commands below are shown +for completeness -- they are part of the standard booting procedure and not +specific to the new image format). + +[on the target system]:: + + => print nfsargs + nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath} + => print addip + addip=setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off panic=1 + => run nfsargs addip + => tftp 900000 /path/to/tftp/location/kernel.itb + Using FEC device + TFTP from server 192.168.1.1; our IP address is 192.168.160.5 + Filename '/path/to/tftp/location/kernel.itb'. + Load address: 0x900000 + Loading: ################################################################# + done + Bytes transferred = 944464 (e6950 hex) + => iminfo + + ## Checking Image at 00900000 ... + FIT image found + FIT description: Simple image with single Linux kernel + Created: 2008-03-11 16:26:15 UTC + Image 0 (kernel) + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Start: 0x009000e0 + Data Size: 943347 Bytes = 921.2 kB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2ae2bb40 + Hash algo: sha1 + Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4 + Default Configuration: 'config-1' + Configuration 0 (config-1) + Description: Boot Linux kernel + Kernel: kernel + + => bootm + ## Booting kernel from FIT Image at 00900000 ... + Using 'config-1' configuration + Trying 'kernel' kernel subimage + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Start: 0x009000e0 + Data Size: 943347 Bytes = 921.2 kB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2ae2bb40 + Hash algo: sha1 + Hash value: 3c200f34e2c226ddc789240cca0c59fc54a67cf4 + Verifying Hash Integrity ... crc32+ sha1+ OK + Uncompressing Kernel Image ... OK + Memory BAT mapping: BAT2=256Mb, BAT3=0Mb, residual: 0Mb + Linux version 2.4.25 (m8@hekate) (gcc version 4.0.0 (DENX ELDK 4.0 4.0.0)) #2 czw lip 5 17:56:18 CEST 2007 + On node 0 totalpages: 65536 + zone(0): 65536 pages. + zone(1): 0 pages. + zone(2): 0 pages. + Kernel command line: root=/dev/nfs rw nfsroot=192.168.1.1:/opt/eldk-4.1/ppc_6xx ip=192.168.160.5:192.168.1.1::255.255.0.0:lite5200b:eth0:off panic=1 + Calibrating delay loop... 307.20 BogoMIPS + + +Example 2 -- new-style (FDT) kernel booting +------------------------------------------- + +Consider another simple scenario, where a PPC Linux kernel is to be booted +new-style, i.e., with a FDT blob. In this case there are two prerequisite data +files: vmlinux.bin.gz (Linux kernel) and target.dtb (FDT blob). The uImage can +be produced using image source file doc/uImage.FIT/kernel_fdt.its like this +(note again, that both prerequisite data files are assumed to be present in +the current working directory -- image source file kernel_fdt.its can be +modified to take the files from some other location if needed): + +[on the host system]:: + + $ mkimage -f kernel_fdt.its kernel_fdt.itb + DTC: dts->dtb on file "kernel_fdt.its" + $ + $ mkimage -l kernel_fdt.itb + FIT description: Simple image with single Linux kernel and FDT blob + Created: Tue Mar 11 16:29:22 2008 + Image 0 (kernel) + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Size: 1092037 Bytes = 1066.44 kB = 1.04 MB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2c0cc807 + Hash algo: sha1 + Hash value: 264b59935470e42c418744f83935d44cdf59a3bb + Image 1 (fdt-1) + Description: Flattened Device Tree blob + Type: Flat Device Tree + Compression: uncompressed + Data Size: 16384 Bytes = 16.00 kB = 0.02 MB + Architecture: PowerPC + Hash algo: crc32 + Hash value: 0d655d71 + Hash algo: sha1 + Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def + Default Configuration: 'conf-1' + Configuration 0 (conf-1) + Description: Boot Linux kernel with FDT blob + Kernel: kernel + FDT: fdt-1 + + +The resulting image file kernel_fdt.itb can be now transferred to the target, +inspected and booted: + +[on the target system]:: + + => tftp 900000 /path/to/tftp/location/kernel_fdt.itb + Using FEC device + TFTP from server 192.168.1.1; our IP address is 192.168.160.5 + Filename '/path/to/tftp/location/kernel_fdt.itb'. + Load address: 0x900000 + Loading: ################################################################# + ########### + done + Bytes transferred = 1109776 (10ef10 hex) + => iminfo + + ## Checking Image at 00900000 ... + FIT image found + FIT description: Simple image with single Linux kernel and FDT blob + Created: 2008-03-11 15:29:22 UTC + Image 0 (kernel) + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Start: 0x009000ec + Data Size: 1092037 Bytes = 1 MB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2c0cc807 + Hash algo: sha1 + Hash value: 264b59935470e42c418744f83935d44cdf59a3bb + Image 1 (fdt-1) + Description: Flattened Device Tree blob + Type: Flat Device Tree + Compression: uncompressed + Data Start: 0x00a0abdc + Data Size: 16384 Bytes = 16 kB + Architecture: PowerPC + Hash algo: crc32 + Hash value: 0d655d71 + Hash algo: sha1 + Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def + Default Configuration: 'conf-1' + Configuration 0 (conf-1) + Description: Boot Linux kernel with FDT blob + Kernel: kernel + FDT: fdt-1 + => bootm + ## Booting kernel from FIT Image at 00900000 ... + Using 'conf-1' configuration + Trying 'kernel' kernel subimage + Description: Vanilla Linux kernel + Type: Kernel Image + Compression: gzip compressed + Data Start: 0x009000ec + Data Size: 1092037 Bytes = 1 MB + Architecture: PowerPC + OS: Linux + Load Address: 0x00000000 + Entry Point: 0x00000000 + Hash algo: crc32 + Hash value: 2c0cc807 + Hash algo: sha1 + Hash value: 264b59935470e42c418744f83935d44cdf59a3bb + Verifying Hash Integrity ... crc32+ sha1+ OK + Uncompressing Kernel Image ... OK + ## Flattened Device Tree from FIT Image at 00900000 + Using 'conf-1' configuration + Trying 'fdt-1' FDT blob subimage + Description: Flattened Device Tree blob + Type: Flat Device Tree + Compression: uncompressed + Data Start: 0x00a0abdc + Data Size: 16384 Bytes = 16 kB + Architecture: PowerPC + Hash algo: crc32 + Hash value: 0d655d71 + Hash algo: sha1 + Hash value: 25ab4e15cd4b8a5144610394560d9c318ce52def + Verifying Hash Integrity ... crc32+ sha1+ OK + Booting using the fdt blob at 0xa0abdc + Loading Device Tree to 007fc000, end 007fffff ... OK + [ 0.000000] Using lite5200 machine description + [ 0.000000] Linux version 2.6.24-rc6-gaebecdfc (m8@hekate) (gcc version 4.0.0 (DENX ELDK 4.1 4.0.0)) #1 Sat Jan 12 15:38:48 CET 2008 + + +Example 3 -- advanced booting +----------------------------- + +Refer to :doc:`multi` for an image source file that allows more +sophisticated booting scenarios (multiple kernels, ramdisks and fdt blobs). + +.. sectionauthor:: Bartlomiej Sieka <[email protected]> diff --git a/doc/usage/fit.rst b/doc/usage/fit/index.rst index 70374340577..bd25bd30b28 100644 --- a/doc/usage/fit.rst +++ b/doc/usage/fit/index.rst @@ -6,3 +6,14 @@ 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 + +.. toctree:: + :maxdepth: 1 + + source_file_format + howto + x86-fit-boot + signature + verified-boot + beaglebone_vboot + overlay-fdt-boot diff --git a/doc/usage/fit/kernel.rst b/doc/usage/fit/kernel.rst new file mode 100644 index 00000000000..012a81efead --- /dev/null +++ b/doc/usage/fit/kernel.rst @@ -0,0 +1,93 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Single kernel +============= + +:: + + /dts-v1/; + + / { + description = "Simple image with single Linux kernel"; + #address-cells = <1>; + + images { + kernel { + description = "Vanilla Linux kernel"; + data = /incbin/("./vmlinux.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "sha1"; + }; + }; + }; + + configurations { + default = "config-1"; + config-1 { + description = "Boot Linux kernel"; + kernel = "kernel"; + }; + }; + }; + + +For x86 a setup node is also required: see x86-fit-boot:: + + /dts-v1/; + + / { + description = "Simple image with single Linux kernel on x86"; + #address-cells = <1>; + + images { + kernel { + description = "Vanilla Linux kernel"; + data = /incbin/("./image.bin.lzo"); + type = "kernel"; + arch = "x86"; + os = "linux"; + compression = "lzo"; + load = <0x01000000>; + entry = <0x00000000>; + hash-2 { + algo = "sha1"; + }; + }; + + setup { + description = "Linux setup.bin"; + data = /incbin/("./setup.bin"); + type = "x86_setup"; + arch = "x86"; + os = "linux"; + compression = "none"; + load = <0x00090000>; + entry = <0x00090000>; + hash-2 { + algo = "sha1"; + }; + }; + }; + + configurations { + default = "config-1"; + config-1 { + description = "Boot Linux kernel"; + kernel = "kernel"; + setup = "setup"; + }; + }; + }; + +Note: the above assumes a 32-bit kernel. To directly boot a 64-bit kernel, +change both arch values to "x86_64". U-Boot will then change to 64-bit mode +before booting the kernel (see boot_linux_kernel()). diff --git a/doc/usage/fit/kernel_fdt.rst b/doc/usage/fit/kernel_fdt.rst new file mode 100644 index 00000000000..8eee13af780 --- /dev/null +++ b/doc/usage/fit/kernel_fdt.rst @@ -0,0 +1,54 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Single kernel and FDT blob +========================== + +:: + + /dts-v1/; + + / { + description = "Simple image with single Linux kernel and FDT blob"; + #address-cells = <1>; + + images { + kernel { + description = "Vanilla Linux kernel"; + data = /incbin/("./vmlinux.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "sha1"; + }; + }; + fdt-1 { + description = "Flattened Device Tree blob"; + data = /incbin/("./target.dtb"); + type = "flat_dt"; + arch = "ppc"; + compression = "none"; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "sha1"; + }; + }; + }; + + configurations { + default = "conf-1"; + conf-1 { + description = "Boot Linux kernel with FDT blob"; + kernel = "kernel"; + fdt = "fdt-1"; + }; + }; + }; diff --git a/doc/usage/fit/kernel_fdts_compressed.rst b/doc/usage/fit/kernel_fdts_compressed.rst new file mode 100644 index 00000000000..0b169c7c27c --- /dev/null +++ b/doc/usage/fit/kernel_fdts_compressed.rst @@ -0,0 +1,77 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Kernel and multiple compressed FDT blobs +======================================== + +Since the FDTs are compressed, configurations must provide a compatible +string to match directly. + +:: + + /dts-v1/; + + / { + description = "Image with single Linux kernel and compressed FDT blobs"; + #address-cells = <1>; + + images { + kernel { + description = "Vanilla Linux kernel"; + data = /incbin/("./vmlinux.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "sha1"; + }; + }; + fdt@1 { + description = "Flattened Device Tree blob 1"; + data = /incbin/("./myboard-var1.dtb"); + type = "flat_dt"; + arch = "ppc"; + compression = "gzip"; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "sha1"; + }; + }; + fdt@2 { + description = "Flattened Device Tree blob 2"; + data = /incbin/("./myboard-var2.dtb"); + type = "flat_dt"; + arch = "ppc"; + compression = "lzma"; + hash-1 { + algo = "crc32"; + }; + hash-2 { + algo = "sha1"; + }; + }; + }; + + configurations { + default = "conf@1"; + conf@1 { + description = "Boot Linux kernel with FDT blob 1"; + kernel = "kernel"; + fdt = "fdt@1"; + compatible = "myvendor,myboard-variant1"; + }; + conf@2 { + description = "Boot Linux kernel with FDT blob 2"; + kernel = "kernel"; + fdt = "fdt@2"; + compatible = "myvendor,myboard-variant2"; + }; + }; + }; diff --git a/doc/usage/fit/multi-with-fpga.rst b/doc/usage/fit/multi-with-fpga.rst new file mode 100644 index 00000000000..28d7d5d2626 --- /dev/null +++ b/doc/usage/fit/multi-with-fpga.rst @@ -0,0 +1,70 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Multiple kernels, ramdisks and FDT blobs with FPGA +================================================== + +This example makes use of the 'loadables' field:: + + /dts-v1/; + + / { + description = "Configuration to load fpga before Kernel"; + #address-cells = <1>; + + images { + fdt-1 { + description = "zc706"; + data = /incbin/("/tftpboot/devicetree.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + load = <0x10000000>; + hash-1 { + algo = "md5"; + }; + }; + + fpga { + description = "FPGA"; + data = /incbin/("/tftpboot/download.bit"); + type = "fpga"; + arch = "arm"; + compression = "none"; + load = <0x30000000>; + compatible = "u-boot,fpga-legacy" + hash-1 { + algo = "md5"; + }; + }; + + linux_kernel { + description = "Linux"; + data = /incbin/("/tftpboot/zImage"); + type = "kernel"; + arch = "arm"; + os = "linux"; + compression = "none"; + load = <0x8000>; + entry = <0x8000>; + hash-1 { + algo = "md5"; + }; + }; + }; + + configurations { + default = "config-2"; + config-1 { + description = "Linux"; + kernel = "linux_kernel"; + fdt = "fdt-1"; + }; + + config-2 { + description = "Linux with fpga"; + kernel = "linux_kernel"; + fdt = "fdt-1"; + loadables = "fpga"; + }; + }; + }; diff --git a/doc/usage/fit/multi-with-loadables.rst b/doc/usage/fit/multi-with-loadables.rst new file mode 100644 index 00000000000..a0241df96ca --- /dev/null +++ b/doc/usage/fit/multi-with-loadables.rst @@ -0,0 +1,91 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Multiple kernels, ramdisks and FDT blobs with Xen +================================================= + +This example makes use of the 'loadables' field:: + + /dts-v1/; + + / { + description = "Configuration to load a Xen Kernel"; + #address-cells = <1>; + + images { + xen_kernel { + description = "xen binary"; + data = /incbin/("./xen"); + type = "kernel"; + arch = "arm"; + os = "linux"; + compression = "none"; + load = <0xa0000000>; + entry = <0xa0000000>; + hash-1 { + algo = "md5"; + }; + }; + + fdt-1 { + description = "xexpress-ca15 tree blob"; + data = /incbin/("./vexpress-v2p-ca15-tc1.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + load = <0xb0000000>; + hash-1 { + algo = "md5"; + }; + }; + + fdt-2 { + description = "xexpress-ca15 tree blob"; + data = /incbin/("./vexpress-v2p-ca15-tc1.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + load = <0xb0400000>; + hash-1 { + algo = "md5"; + }; + }; + + linux_kernel { + description = "Linux Image"; + data = /incbin/("./Image"); + type = "kernel"; + arch = "arm"; + os = "linux"; + compression = "none"; + load = <0xa0000000>; + entry = <0xa0000000>; + hash-1 { + algo = "md5"; + }; + }; + }; + + configurations { + default = "config-2"; + + config-1 { + description = "Just plain Linux"; + kernel = "linux_kernel"; + fdt = "fdt-1"; + }; + + config-2 { + description = "Xen one loadable"; + kernel = "xen_kernel"; + fdt = "fdt-1"; + loadables = "linux_kernel"; + }; + + config-3 { + description = "Xen two loadables"; + kernel = "xen_kernel"; + fdt = "fdt-1"; + loadables = "linux_kernel", "fdt-2"; + }; + }; + }; diff --git a/doc/usage/fit/multi.rst b/doc/usage/fit/multi.rst new file mode 100644 index 00000000000..2e6ae58c409 --- /dev/null +++ b/doc/usage/fit/multi.rst @@ -0,0 +1,136 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Multiple kernels, ramdisks and FDT blobs +======================================== + +:: + + /dts-v1/; + + / { + description = "Various kernels, ramdisks and FDT blobs"; + #address-cells = <1>; + + images { + kernel-1 { + description = "vanilla-2.6.23"; + data = /incbin/("./vmlinux.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "md5"; + }; + hash-2 { + algo = "sha1"; + }; + }; + + kernel-2 { + description = "2.6.23-denx"; + data = /incbin/("./2.6.23-denx.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "sha1"; + }; + }; + + kernel-3 { + description = "2.4.25-denx"; + data = /incbin/("./2.4.25-denx.bin.gz"); + type = "kernel"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "md5"; + }; + }; + + ramdisk-1 { + description = "eldk-4.2-ramdisk"; + data = /incbin/("./eldk-4.2-ramdisk"); + type = "ramdisk"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "sha1"; + }; + }; + + ramdisk-2 { + description = "eldk-3.1-ramdisk"; + data = /incbin/("./eldk-3.1-ramdisk"); + type = "ramdisk"; + arch = "ppc"; + os = "linux"; + compression = "gzip"; + load = <00000000>; + entry = <00000000>; + hash-1 { + algo = "crc32"; + }; + }; + + fdt-1 { + description = "tqm5200-fdt"; + data = /incbin/("./tqm5200.dtb"); + type = "flat_dt"; + arch = "ppc"; + compression = "none"; + hash-1 { + algo = "crc32"; + }; + }; + + fdt-2 { + description = "tqm5200s-fdt"; + data = /incbin/("./tqm5200s.dtb"); + type = "flat_dt"; + arch = "ppc"; + compression = "none"; + load = <00700000>; + hash-1 { + algo = "sha1"; + }; + }; + + }; + + configurations { + default = "config-1"; + + config-1 { + description = "tqm5200 vanilla-2.6.23 configuration"; + kernel = "kernel-1"; + ramdisk = "ramdisk-1"; + fdt = "fdt-1"; + }; + + config-2 { + description = "tqm5200s denx-2.6.23 configuration"; + kernel = "kernel-2"; + ramdisk = "ramdisk-1"; + fdt = "fdt-2"; + }; + + config-3 { + description = "tqm5200s denx-2.4.25 configuration"; + kernel = "kernel-3"; + ramdisk = "ramdisk-2"; + }; + }; + }; diff --git a/doc/usage/fit/multi_spl.rst b/doc/usage/fit/multi_spl.rst new file mode 100644 index 00000000000..74b6f865abd --- /dev/null +++ b/doc/usage/fit/multi_spl.rst @@ -0,0 +1,101 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Multiple images for SPL +======================= + +(Bogus) example FIT image description file demonstrating the usage +of multiple images loaded by the SPL. +Several binaries will be loaded at their respective load addresses. + +For booting U-Boot, "firmware" is searched first. If not found, "loadables" +is used to identify images to be loaded into memory. If falcon boot is +enabled, "kernel" is searched first. If not found, it falls back to the +same flow as booting U-Boot. Changing image type will result skipping +specific image. + +Finally the one image specifying an entry point will be entered by the SPL. + +:: + + /dts-v1/; + + / { + description = "multiple firmware blobs and U-Boot, loaded by SPL"; + #address-cells = <0x1>; + + images { + + uboot { + description = "U-Boot (64-bit)"; + type = "standalone"; + arch = "arm64"; + compression = "none"; + load = <0x4a000000>; + }; + + atf { + description = "ARM Trusted Firmware"; + type = "firmware"; + arch = "arm64"; + compression = "none"; + load = <0x18000>; + entry = <0x18000>; + }; + + mgmt-firmware { + description = "arisc management processor firmware"; + type = "firmware"; + arch = "or1k"; + compression = "none"; + load = <0x40000>; + }; + + fdt-1 { + description = "Pine64+ DT"; + type = "flat_dt"; + compression = "none"; + load = <0x4fa00000>; + arch = "arm64"; + }; + + fdt-2 { + description = "Pine64 DT"; + type = "flat_dt"; + compression = "none"; + load = <0x4fa00000>; + arch = "arm64"; + }; + + kernel { + description = "4.7-rc5 kernel"; + type = "kernel"; + compression = "none"; + load = <0x40080000>; + arch = "arm64"; + }; + + initrd { + description = "Debian installer initrd"; + type = "ramdisk"; + compression = "none"; + load = <0x4fe00000>; + arch = "arm64"; + }; + }; + + configurations { + default = "config-1"; + + config-1 { + description = "sun50i-a64-pine64-plus"; + loadables = "uboot", "atf", "kernel", "initrd"; + fdt = "fdt-1"; + }; + + config-2 { + description = "sun50i-a64-pine64"; + loadables = "uboot", "atf", "mgmt-firmware"; + fdt = "fdt-2"; + }; + }; + }; diff --git a/doc/usage/fit/overlay-fdt-boot.rst b/doc/usage/fit/overlay-fdt-boot.rst new file mode 100644 index 00000000000..a7db1a37f7a --- /dev/null +++ b/doc/usage/fit/overlay-fdt-boot.rst @@ -0,0 +1,227 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot FDT Overlay FIT usage +============================ + +Introduction +------------ + +In many cases it is desirable to have a single FIT image support a multitude +of similar boards and their expansion options. The same kernel on DT enabled +platforms can support this easily enough by providing a DT blob upon boot +that matches the desired configuration. + +This document focuses on specifically using overlays as part of a FIT image. +General information regarding overlays including its syntax and building it +can be found in doc/README.fdt-overlays + +Configuration without overlays +------------------------------ + +Take a hypothetical board named 'foo' where there are different supported +revisions, reva and revb. Assume that both board revisions can use add a bar +add-on board, while only the revb board can use a baz add-on board. + +Without using overlays the configuration would be as follows for every case:: + + /dts-v1/; + / { + images { + kernel { + data = /incbin/("./zImage"); + type = "kernel"; + arch = "arm"; + os = "linux"; + load = <0x82000000>; + entry = <0x82000000>; + }; + fdt-1 { + data = /incbin/("./foo-reva.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt-2 { + data = /incbin/("./foo-revb.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt-3 { + data = /incbin/("./foo-reva-bar.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt-4 { + data = /incbin/("./foo-revb-bar.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt-5 { + data = /incbin/("./foo-revb-baz.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt-6 { + data = /incbin/("./foo-revb-bar-baz.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + }; + + configurations { + default = "foo-reva.dtb; + foo-reva.dtb { + kernel = "kernel"; + fdt = "fdt-1"; + }; + foo-revb.dtb { + kernel = "kernel"; + fdt = "fdt-2"; + }; + foo-reva-bar.dtb { + kernel = "kernel"; + fdt = "fdt-3"; + }; + foo-revb-bar.dtb { + kernel = "kernel"; + fdt = "fdt-4"; + }; + foo-revb-baz.dtb { + kernel = "kernel"; + fdt = "fdt-5"; + }; + foo-revb-bar-baz.dtb { + kernel = "kernel"; + fdt = "fdt-6"; + }; + }; + }; + +Note the blob needs to be compiled for each case and the combinatorial explosion of +configurations. A typical device tree blob is in the low hunderds of kbytes so a +multitude of configuration grows the image quite a bit. + +Booting this image is done by using:: + + # bootm <addr>#<config> + +Where config is one of:: + + foo-reva.dtb, foo-revb.dtb, foo-reva-bar.dtb, foo-revb-bar.dtb, + foo-revb-baz.dtb, foo-revb-bar-baz.dtb + +This selects the DTB to use when booting. + +Configuration using overlays +---------------------------- + +Device tree overlays can be applied to a base DT and result in the same blob +being passed to the booting kernel. This saves on space and avoid the combinatorial +explosion problem:: + + /dts-v1/; + / { + images { + kernel { + data = /incbin/("./zImage"); + type = "kernel"; + arch = "arm"; + os = "linux"; + load = <0x82000000>; + entry = <0x82000000>; + }; + fdt-1 { + data = /incbin/("./foo.dtb"); + type = "flat_dt"; + arch = "arm"; + load = <0x87f00000>; + }; + fdt-2 { + data = /incbin/("./reva.dtbo"); + type = "flat_dt"; + arch = "arm"; + load = <0x87fc0000>; + }; + fdt-3 { + data = /incbin/("./revb.dtbo"); + type = "flat_dt"; + arch = "arm"; + load = <0x87fc0000>; + }; + fdt-4 { + data = /incbin/("./bar.dtbo"); + type = "flat_dt"; + arch = "arm"; + load = <0x87fc0000>; + }; + fdt-5 { + data = /incbin/("./baz.dtbo"); + type = "flat_dt"; + arch = "arm"; + load = <0x87fc0000>; + }; + }; + + configurations { + default = "foo-reva.dtb; + foo-reva.dtb { + kernel = "kernel"; + fdt = "fdt-1", "fdt-2"; + }; + foo-revb.dtb { + kernel = "kernel"; + fdt = "fdt-1", "fdt-3"; + }; + foo-reva-bar.dtb { + kernel = "kernel"; + fdt = "fdt-1", "fdt-2", "fdt-4"; + }; + foo-revb-bar.dtb { + kernel = "kernel"; + fdt = "fdt-1", "fdt-3", "fdt-4"; + }; + foo-revb-baz.dtb { + kernel = "kernel"; + fdt = "fdt-1", "fdt-3", "fdt-5"; + }; + foo-revb-bar-baz.dtb { + kernel = "kernel"; + fdt = "fdt-1", "fdt-3", "fdt-4", "fdt-5"; + }; + bar { + fdt = "fdt-4"; + }; + baz { + fdt = "fdt-5"; + }; + }; + }; + +Booting this image is exactly the same as the non-overlay example. +u-boot will retrieve the base blob and apply the overlays in sequence as +they are declared in the configuration. + +Note the minimum amount of different DT blobs, as well as the requirement for +the DT blobs to have a load address; the overlay application requires the blobs +to be writeable. + +Configuration using overlays and feature selection +-------------------------------------------------- + +Although the configuration in the previous section works is a bit inflexible +since it requires all possible configuration options to be laid out before +hand in the FIT image. For the add-on boards the extra config selection method +might make sense. + +Note the two bar & baz configuration nodes. To boot a reva board with +the bar add-on board enabled simply use:: + + => bootm <addr>#foo-reva.dtb#bar + +While booting a revb with bar and baz is as follows:: + + => bootm <addr>#foo-revb.dtb#bar#baz + +The limitation for a feature selection configuration node is that a single +fdt option is currently supported. + +.. sectionauthor:: Pantelis Antoniou <[email protected]>, 12/6/2017 diff --git a/doc/usage/fit/sec_firmware_ppa.rst b/doc/usage/fit/sec_firmware_ppa.rst new file mode 100644 index 00000000000..4cb292cb4ee --- /dev/null +++ b/doc/usage/fit/sec_firmware_ppa.rst @@ -0,0 +1,54 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +SEC Firmware and multiple loadable images +========================================= + +Example FIT image description file demonstrating the usage +of SEC Firmware and multiple loadable images loaded by U-Boot. +For booting PPA (SEC Firmware), "firmware" is searched and loaded. + +Multiple binaries will be loaded as "loadables" (if present) at their +respective load offsets from firmware image address. + +:: + + /dts-v1/; + + /{ + description = "PPA Firmware"; + #address-cells = <1>; + images { + firmware@1 { + description = "PPA Firmware: <version>"; + data = /incbin/("../obj/monitor.bin"); + type = "firmware"; + arch = "arm64"; + compression = "none"; + }; + trustedOS@1 { + description = "Trusted OS"; + data = /incbin/("../../tee.bin"); + type = "OS"; + arch = "arm64"; + compression = "none"; + load = <0x00200000>; + }; + fuse_scr { + description = "Fuse Script"; + data = /incbin/("../../fuse_scr.bin"); + type = "firmware"; + arch = "arm64"; + compression = "none"; + load = <0x00180000>; + }; + }; + + configurations { + default = "config-1"; + config-1 { + description = "PPA Secure firmware"; + firmware = "firmware@1"; + loadables = "trustedOS@1", "fuse_scr"; + }; + }; + }; diff --git a/doc/usage/fit/sign-configs.rst b/doc/usage/fit/sign-configs.rst new file mode 100644 index 00000000000..6a3df8f2c5b --- /dev/null +++ b/doc/usage/fit/sign-configs.rst @@ -0,0 +1,52 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Signed configurations +===================== + +:: + + /dts-v1/; + + / { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel { + data = /incbin/("test-kernel.bin"); + type = "kernel_noload"; + arch = "sandbox"; + os = "linux"; + compression = "lzo"; + load = <0x4>; + entry = <0x8>; + kernel-version = <1>; + hash-1 { + algo = "sha1"; + }; + }; + fdt-1 { + description = "snow"; + data = /incbin/("sandbox-kernel.dtb"); + type = "flat_dt"; + arch = "sandbox"; + compression = "none"; + fdt-version = <1>; + hash-1 { + algo = "sha1"; + }; + }; + }; + configurations { + default = "conf-1"; + conf-1 { + kernel = "kernel"; + fdt = "fdt-1"; + signature { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + sign-images = "fdt", "kernel"; + }; + }; + }; + }; diff --git a/doc/usage/fit/sign-images.rst b/doc/usage/fit/sign-images.rst new file mode 100644 index 00000000000..7d54d702c97 --- /dev/null +++ b/doc/usage/fit/sign-images.rst @@ -0,0 +1,49 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Signed Images +============= + +:: + + /dts-v1/; + + / { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel { + data = /incbin/("test-kernel.bin"); + type = "kernel_noload"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + load = <0x4>; + entry = <0x8>; + kernel-version = <1>; + signature { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + }; + }; + fdt-1 { + description = "snow"; + data = /incbin/("sandbox-kernel.dtb"); + type = "flat_dt"; + arch = "sandbox"; + compression = "none"; + fdt-version = <1>; + signature { + algo = "sha1,rsa2048"; + key-name-hint = "dev"; + }; + }; + }; + configurations { + default = "conf-1"; + conf-1 { + kernel = "kernel"; + fdt = "fdt-1"; + }; + }; + }; diff --git a/doc/usage/fit/signature.rst b/doc/usage/fit/signature.rst new file mode 100644 index 00000000000..0804bffd1ed --- /dev/null +++ b/doc/usage/fit/signature.rst @@ -0,0 +1,696 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot FIT Signature Verification +================================= + +Introduction +------------ + +FIT supports hashing of images so that these hashes can be checked on +loading. This protects against corruption of the image. However it does not +prevent the substitution of one image for another. + +The signature feature allows the hash to be signed with a private key such +that it can be verified using a public key later. Provided that the private +key is kept secret and the public key is stored in a non-volatile place, +any image can be verified in this way. + +See verified-boot.txt for more general information on verified boot. + + +Concepts +-------- + +Some familiarity with public key cryptography is assumed in this section. + +The procedure for signing is as follows: + + - hash an image in the FIT + - sign the hash with a private key to produce a signature + - store the resulting signature in the FIT + +The procedure for verification is: + + - read the FIT + - obtain the public key + - extract the signature from the FIT + - hash the image from the FIT + - verify (with the public key) that the extracted signature matches the + hash + +The signing is generally performed by mkimage, as part of making a firmware +image for the device. The verification is normally done in U-Boot on the +device. + + +Algorithms +---------- +In principle any suitable algorithm can be used to sign and verify a hash. +U-Boot supports a few hashing and verification algorithms. See below for +details. + +While it is acceptable to bring in large cryptographic libraries such as +openssl on the host side (e.g. mkimage), it is not desirable for U-Boot. +For the run-time verification side, it is important to keep code and data +size as small as possible. + +For this reason the RSA image verification uses pre-processed public keys +which can be used with a very small amount of code - just some extraction +of data from the FDT and exponentiation mod n. Code size impact is a little +under 5KB on Tegra Seaboard, for example. + +It is relatively straightforward to add new algorithms if required. If +another RSA variant is needed, then it can be added with the +U_BOOT_CRYPTO_ALGO() macro. If another algorithm is needed (such as DSA) then +it can be placed in a directory alongside lib/rsa/, and its functions added +using U_BOOT_CRYPTO_ALGO(). + + +Creating an RSA key pair and certificate +---------------------------------------- +To create a new public/private key pair, size 2048 bits:: + + $ openssl genpkey -algorithm RSA -out keys/dev.key \ + -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537 + +To create a certificate for this containing the public key:: + + $ openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt + +If you like you can look at the public key also:: + + $ openssl rsa -in keys/dev.key -pubout + + +Public Key Storage +------------------ +In order to verify an image that has been signed with a public key we need to +have a trusted public key. This cannot be stored in the signed image, since +it would be easy to alter. For this implementation we choose to store the +public key in U-Boot's control FDT (using CONFIG_OF_CONTROL). + +Public keys should be stored as sub-nodes in a /signature node. Required +properties are: + +algo + Algorithm name (e.g. "sha1,rsa2048" or "sha256,ecdsa256") + +Optional properties are: + +key-name-hint + Name of key used for signing. This is only a hint since it + is possible for the name to be changed. Verification can proceed by checking + all available signing keys until one matches. + +required + If present this indicates that the key must be verified for the + image / configuration to be considered valid. Only required keys are + normally verified by the FIT image booting algorithm. Valid values are + "image" to force verification of all images, and "conf" to force verification + of the selected configuration (which then relies on hashes in the images to + verify those). + +Each signing algorithm has its own additional properties. + +For RSA the following are mandatory: + +rsa,num-bits + Number of key bits (e.g. 2048) + +rsa,modulus + Modulus (N) as a big-endian multi-word integer + +rsa,exponent + Public exponent (E) as a 64 bit unsigned integer + +rsa,r-squared + (2^num-bits)^2 as a big-endian multi-word integer + +rsa,n0-inverse + -1 / modulus[0] mod 2^32 + +For ECDSA the following are mandatory: + +ecdsa,curve + Name of ECDSA curve (e.g. "prime256v1") + +ecdsa,x-point + Public key X coordinate as a big-endian multi-word integer + +ecdsa,y-point + Public key Y coordinate as a big-endian multi-word integer + +These parameters can be added to a binary device tree using parameter -K of the +mkimage command:: + + tools/mkimage -f fit.its -K control.dtb -k keys -r image.fit + +Here is an example of a generated device tree node:: + + signature { + key-dev { + required = "conf"; + algo = "sha256,rsa2048"; + rsa,r-squared = <0xb76d1acf 0xa1763ca5 0xeb2f126 + 0x742edc80 0xd3f42177 0x9741d9d9 + 0x35bb476e 0xff41c718 0xd3801430 + 0xf22537cb 0xa7e79960 0xae32a043 + 0x7da1427a 0x341d6492 0x3c2762f5 + 0xaac04726 0x5b262d96 0xf984e86d + 0xb99443c7 0x17080c33 0x940f6892 + 0xd57a95d1 0x6ea7b691 0xc5038fa8 + 0x6bb48a6e 0x73f1b1ea 0x37160841 + 0xe05715ce 0xa7c45bbd 0x690d82d5 + 0x99c2454c 0x6ff117b3 0xd830683b + 0x3f81c9cf 0x1ca38a91 0x0c3392e4 + 0xd817c625 0x7b8e9a24 0x175b89ea + 0xad79f3dc 0x4d50d7b4 0x9d4e90f8 + 0xad9e2939 0xc165d6a4 0x0ada7e1b + 0xfb1bf495 0xfc3131c2 0xb8c6e604 + 0xc2761124 0xf63de4a6 0x0e9565f9 + 0xc8e53761 0x7e7a37a5 0xe99dcdae + 0x9aff7e1e 0xbd44b13d 0x6b0e6aa4 + 0x038907e4 0x8e0d6850 0xef51bc20 + 0xf73c94af 0x88bea7b1 0xcbbb1b30 + 0xd024b7f3>; + rsa,modulus = <0xc0711d6cb 0x9e86db7f 0x45986dbe + 0x023f1e8c9 0xe1a4c4d0 0x8a0dfdc9 + 0x023ba0c48 0x06815f6a 0x5caa0654 + 0x07078c4b7 0x3d154853 0x40729023 + 0x0b007c8fe 0x5a3647e5 0x23b41e20 + 0x024720591 0x66915305 0x0e0b29b0 + 0x0de2ad30d 0x8589430f 0xb1590325 + 0x0fb9f5d5e 0x9eba752a 0xd88e6de9 + 0x056b3dcc6 0x9a6b8e61 0x6784f61f + 0x000f39c21 0x5eec6b33 0xd78e4f78 + 0x0921a305f 0xaa2cc27e 0x1ca917af + 0x06e1134f4 0xd48cac77 0x4e914d07 + 0x0f707aa5a 0x0d141f41 0x84677f1d + 0x0ad47a049 0x028aedb6 0xd5536fcf + 0x03fef1e4f 0x133a03d2 0xfd7a750a + 0x0f9159732 0xd207812e 0x6a807375 + 0x06434230d 0xc8e22dad 0x9f29b3d6 + 0x07c44ac2b 0xfa2aad88 0xe2429504 + 0x041febd41 0x85d0d142 0x7b194d65 + 0x06e5d55ea 0x41116961 0xf3181dde + 0x068bf5fbc 0x3dd82047 0x00ee647e + 0x0d7a44ab3>; + rsa,exponent = <0x00 0x10001>; + rsa,n0-inverse = <0xb3928b85>; + rsa,num-bits = <0x800>; + key-name-hint = "dev"; + }; + }; + + +Signed Configurations +--------------------- +While signing images is useful, it does not provide complete protection +against several types of attack. For example, it is possible to create a +FIT with the same signed images, but with the configuration changed such +that a different one is selected (mix and match attack). It is also possible +to substitute a signed image from an older FIT version into a newer FIT +(roll-back attack). + +As an example, consider this FIT:: + + / { + images { + kernel-1 { + data = <data for kernel1> + signature-1 { + algo = "sha1,rsa2048"; + value = <...kernel signature 1...> + }; + }; + kernel-2 { + data = <data for kernel2> + signature-1 { + algo = "sha1,rsa2048"; + value = <...kernel signature 2...> + }; + }; + fdt-1 { + data = <data for fdt1>; + signature-1 { + algo = "sha1,rsa2048"; + value = <...fdt signature 1...> + }; + }; + fdt-2 { + data = <data for fdt2>; + signature-1 { + algo = "sha1,rsa2048"; + value = <...fdt signature 2...> + }; + }; + }; + configurations { + default = "conf-1"; + conf-1 { + kernel = "kernel-1"; + fdt = "fdt-1"; + }; + conf-2 { + kernel = "kernel-2"; + fdt = "fdt-2"; + }; + }; + }; + +Since both kernels are signed it is easy for an attacker to add a new +configuration 3 with kernel 1 and fdt 2:: + + configurations { + default = "conf-1"; + conf-1 { + kernel = "kernel-1"; + fdt = "fdt-1"; + }; + conf-2 { + kernel = "kernel-2"; + fdt = "fdt-2"; + }; + conf-3 { + kernel = "kernel-1"; + fdt = "fdt-2"; + }; + }; + +With signed images, nothing protects against this. Whether it gains an +advantage for the attacker is debatable, but it is not secure. + +To solve this problem, we support signed configurations. In this case it +is the configurations that are signed, not the image. Each image has its +own hash, and we include the hash in the configuration signature. + +So the above example is adjusted to look like this:: + + / { + images { + kernel-1 { + data = <data for kernel1> + hash-1 { + algo = "sha1"; + value = <...kernel hash 1...> + }; + }; + kernel-2 { + data = <data for kernel2> + hash-1 { + algo = "sha1"; + value = <...kernel hash 2...> + }; + }; + fdt-1 { + data = <data for fdt1>; + hash-1 { + algo = "sha1"; + value = <...fdt hash 1...> + }; + }; + fdt-2 { + data = <data for fdt2>; + hash-1 { + algo = "sha1"; + value = <...fdt hash 2...> + }; + }; + }; + configurations { + default = "conf-1"; + conf-1 { + kernel = "kernel-1"; + fdt = "fdt-1"; + signature-1 { + algo = "sha1,rsa2048"; + value = <...conf 1 signature...>; + }; + }; + conf-2 { + kernel = "kernel-2"; + fdt = "fdt-2"; + signature-1 { + algo = "sha1,rsa2048"; + value = <...conf 1 signature...>; + }; + }; + }; + }; + + +You can see that we have added hashes for all images (since they are no +longer signed), and a signature to each configuration. In the above example, +mkimage will sign configurations/conf-1, the kernel and fdt that are +pointed to by the configuration (/images/kernel-1, /images/kernel-1/hash-1, +/images/fdt-1, /images/fdt-1/hash-1) and the root structure of the image +(so that it isn't possible to add or remove root nodes). The signature is +written into /configurations/conf-1/signature-1/value. It can easily be +verified later even if the FIT has been signed with other keys in the +meantime. + + +Details +------- +The signature node contains a property ('hashed-nodes') which lists all the +nodes that the signature was made over. The image is walked in order and each +tag processed as follows: + +DTB_BEGIN_NODE + The tag and the following name are included in the signature + if the node or its parent are present in 'hashed-nodes' + +DTB_END_NODE + The tag is included in the signature if the node or its parent + are present in 'hashed-nodes' + +DTB_PROPERTY + The tag, the length word, the offset in the string table, and + the data are all included if the current node is present in 'hashed-nodes' + and the property name is not 'data'. + +DTB_END + The tag is always included in the signature. + +DTB_NOP + The tag is included in the signature if the current node is present + in 'hashed-nodes' + +In addition, the signature contains a property 'hashed-strings' which contains +the offset and length in the string table of the strings that are to be +included in the signature (this is done last). + +IMPORTANT: To verify the signature outside u-boot, it is vital to not only +calculate the hash of the image and verify the signature with that, but also to +calculate the hashes of the kernel, fdt, and ramdisk images and check those +match the hash values in the corresponding 'hash*' subnodes. + + +Verification +------------ +FITs are verified when loaded. After the configuration is selected a list +of required images is produced. If there are 'required' public keys, then +each image must be verified against those keys. This means that every image +that might be used by the target needs to be signed with 'required' keys. + +This happens automatically as part of a bootm command when FITs are used. + +For Signed Configurations, the default verification behavior can be changed by +the following optional property in /signature node in U-Boot's control FDT. + +required-mode + Valid values are "any" to allow verified boot to succeed if + the selected configuration is signed by any of the 'required' keys, and "all" + to allow verified boot to succeed if the selected configuration is signed by + all of the 'required' keys. + +This property can be added to a binary device tree using fdtput as shown in +below examples:: + + fdtput -t s control.dtb /signature required-mode any + fdtput -t s control.dtb /signature required-mode all + + +Enabling FIT Verification +------------------------- +In addition to the options to enable FIT itself, the following CONFIGs must +be enabled: + +CONFIG_FIT_SIGNATURE + enable signing and verification in FITs + +CONFIG_RSA + enable RSA algorithm for signing + +CONFIG_ECDSA + enable ECDSA algorithm for signing + +WARNING: When relying on signed FIT images with required signature check +the legacy image format is default disabled by not defining +CONFIG_LEGACY_IMAGE_FORMAT + + +Testing +------- + +An easy way to test signing and verification is to use the test script +provided in test/vboot/vboot_test.sh. This uses sandbox (a special version +of U-Boot which runs under Linux) to show the operation of a 'bootm' +command loading and verifying images. + +A sample run is show below:: + + $ make O=sandbox sandbox_config + $ make O=sandbox + $ O=sandbox ./test/vboot/vboot_test.sh + + +Simple Verified Boot Test +------------------------- + +Please see :doc:`verified-boot` for more information:: + + /home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000 + Build keys + do sha1 test + Build FIT with signed images + Test Verified Boot Run: unsigned signatures:: OK + Sign images + Test Verified Boot Run: signed images: OK + Build FIT with signed configuration + Test Verified Boot Run: unsigned config: OK + Sign images + Test Verified Boot Run: signed config: OK + check signed config on the host + Signature check OK + OK + Test Verified Boot Run: signed config: OK + Test Verified Boot Run: signed config with bad hash: OK + do sha256 test + Build FIT with signed images + Test Verified Boot Run: unsigned signatures:: OK + Sign images + Test Verified Boot Run: signed images: OK + Build FIT with signed configuration + Test Verified Boot Run: unsigned config: OK + Sign images + Test Verified Boot Run: signed config: OK + check signed config on the host + Signature check OK + OK + Test Verified Boot Run: signed config: OK + Test Verified Boot Run: signed config with bad hash: OK + + Test passed + + +Software signing: keydir vs keyfile +----------------------------------- + +In the simplest case, signing is done by giving mkimage the 'keyfile'. This is +the path to a file containing the signing key. + +The alternative is to pass the 'keydir' argument. In this case the filename of +the key is derived from the 'keydir' and the "key-name-hint" property in the +FIT. In this case the "key-name-hint" property is mandatory, and the key must +exist in "<keydir>/<key-name-hint>.<ext>" Here the extension "ext" is +specific to the signing algorithm. + + +Hardware Signing with PKCS#11 or with HSM +----------------------------------------- + +Securely managing private signing keys can challenging, especially when the +keys are stored on the file system of a computer that is connected to the +Internet. If an attacker is able to steal the key, they can sign malicious FIT +images which will appear genuine to your devices. + +An alternative solution is to keep your signing key securely stored on hardware +device like a smartcard, USB token or Hardware Security Module (HSM) and have +them perform the signing. PKCS#11 is standard for interfacing with these crypto +device. + +Requirements: + - Smartcard/USB token/HSM which can work with some openssl engine + - openssl + +For pkcs11 engine usage: + - libp11 (provides pkcs11 engine) + - p11-kit (recommended to simplify setup) + - opensc (for smartcards and smartcard like USB devices) + - gnutls (recommended for key generation, p11tool) + +For generic HSMs respective openssl engine must be installed and locateable by +openssl. This may require setting up LD_LIBRARY_PATH if engine is not installed +to openssl's default search paths. + +PKCS11 engine support forms "key id" based on "keydir" and with +"key-name-hint". "key-name-hint" is used as "object" name (if not defined in +keydir). "keydir" (if defined) is used to define (prefix for) which PKCS11 source +is being used for lookup up for the key. + +PKCS11 engine key ids + "pkcs11:<keydir>;object=<key-name-hint>;type=<public|private>" + +or, if keydir contains "object=" + "pkcs11:<keydir>;type=<public|private>" + +or + "pkcs11:object=<key-name-hint>;type=<public|private>", + +Generic HSM engine support forms "key id" based on "keydir" and with +"key-name-hint". If "keydir" is specified for mkimage it is used as a prefix in +"key id" and is appended with "key-name-hint". + +Generic engine key ids: + "<keydir><key-name-hint>" + +or + "< key-name-hint>" + +In order to set the pin in the HSM, an environment variable "MKIMAGE_SIGN_PIN" +can be specified. + +The following examples use the Nitrokey Pro using pkcs11 engine. Instructions +for other devices may vary. + +Notes on pkcs11 engine setup: + +Make sure p11-kit, opensc are installed and that p11-kit is setup to use opensc. +/usr/share/p11-kit/modules/opensc.module should be present on your system. + + +Generating Keys On the Nitrokey:: + + $ gpg --card-edit + + Reader ...........: Nitrokey Nitrokey Pro (xxxxxxxx0000000000000000) 00 00 + Application ID ...: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + Version ..........: 2.1 + Manufacturer .....: ZeitControl + Serial number ....: xxxxxxxx + Name of cardholder: [not set] + Language prefs ...: de + Sex ..............: unspecified + URL of public key : [not set] + Login data .......: [not set] + Signature PIN ....: forced + Key attributes ...: rsa2048 rsa2048 rsa2048 + Max. PIN lengths .: 32 32 32 + PIN retry counter : 3 0 3 + Signature counter : 0 + Signature key ....: [none] + Encryption key....: [none] + Authentication key: [none] + General key info..: [none] + + gpg/card> generate + Make off-card backup of encryption key? (Y/n) n + + Please note that the factory settings of the PINs are + PIN = '123456' Admin PIN = '12345678' + You should change them using the command --change-pin + + What keysize do you want for the Signature key? (2048) 4096 + The card will now be re-configured to generate a key of 4096 bits + Note: There is no guarantee that the card supports the requested size. + If the key generation does not succeed, please check the + documentation of your card to see what sizes are allowed. + What keysize do you want for the Encryption key? (2048) 4096 + The card will now be re-configured to generate a key of 4096 bits + What keysize do you want for the Authentication key? (2048) 4096 + The card will now be re-configured to generate a key of 4096 bits + Please specify how long the key should be valid. + 0 = key does not expire + <n> = key expires in n days + <n>w = key expires in n weeks + <n>m = key expires in n months + <n>y = key expires in n years + Key is valid for? (0) + Key does not expire at all + Is this correct? (y/N) y + + GnuPG needs to construct a user ID to identify your key. + + Real name: John Doe + Email address: [email protected] + Comment: + You selected this USER-ID: + "John Doe <[email protected]>" + + Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o + + +Using p11tool to get the token URL: + +Depending on system configuration, gpg-agent may need to be killed first:: + + $ p11tool --provider /usr/lib/opensc-pkcs11.so --list-tokens + Token 0: + URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29 + Label: OpenPGP card (User PIN (sig)) + Type: Hardware token + Manufacturer: ZeitControl + Model: PKCS#15 emulated + Serial: 000xxxxxxxxx + Module: (null) + + + Token 1: + URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%29 + Label: OpenPGP card (User PIN) + Type: Hardware token + Manufacturer: ZeitControl + Model: PKCS#15 emulated + Serial: 000xxxxxxxxx + Module: (null) + +Use the portion of the signature token URL after "pkcs11:" as the keydir argument (-k) to mkimage below. + + +Use the URL of the token to list the private keys:: + + $ p11tool --login --provider /usr/lib/opensc-pkcs11.so --list-privkeys \ + "pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29" + Token 'OpenPGP card (User PIN (sig))' with URL 'pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29' requires user PIN + Enter PIN: + Object 0: + URL: pkcs11:model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29;id=%01;object=Signature%20key;type=private + Type: Private key + Label: Signature key + Flags: CKA_PRIVATE; CKA_NEVER_EXTRACTABLE; CKA_SENSITIVE; + ID: 01 + +Use the label, in this case "Signature key" as the key-name-hint in your FIT. + +Create the fitImage:: + + $ ./tools/mkimage -f fit-image.its fitImage + + +Sign the fitImage with the hardware key:: + + $ ./tools/mkimage -F -k \ + "model=PKCS%2315%20emulated;manufacturer=ZeitControl;serial=000xxxxxxxxx;token=OpenPGP%20card%20%28User%20PIN%20%28sig%29%29" \ + -K u-boot.dtb -N pkcs11 -r fitImage + + +Future Work +----------- + +- Roll-back protection using a TPM is done using the tpm command. This can + be scripted, but we might consider a default way of doing this, built into + bootm. + + +Possible Future Work +-------------------- + +- More sandbox tests for failure modes +- Passwords for keys/certificates +- Perhaps implement OAEP +- Enhance bootm to permit scripted signature verification (so that a script + can verify an image but not actually boot it) + + +.. sectionauthor:: Simon Glass <[email protected]>, 1-1-13 diff --git a/doc/usage/fit/source_file_format.rst b/doc/usage/fit/source_file_format.rst new file mode 100644 index 00000000000..b2b1e42bd73 --- /dev/null +++ b/doc/usage/fit/source_file_format.rst @@ -0,0 +1,684 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Flattened Image Tree (FIT) Format +================================= + +Introduction +------------ + +The number of elements playing a role in the kernel booting process has +increased over time and now typically includes the devicetree, kernel image and +possibly a ramdisk image. Generally, all must be placed in the system memory and +booted together. + +For firmware images a similar process has taken place, with various binaries +loaded at different addresses, such as ARM's ATF, OpenSBI, FPGA and U-Boot +itself. + +FIT provides a flexible and extensible format to deal with this complexity. It +provides support for multiple components. It also supports multiple +configurations, so that the same FIT can be used to boot multiple boards, with +some components in common (e.g. kernel) and some specific to that board (e.g. +devicetree). + +Terminology +~~~~~~~~~~~ + +This document defines FIT by providing FDT (Flat Device Tree) bindings. These +describe the final form of the FIT at the moment when it is used. The user +perspective may be simpler, as some of the properties (like timestamps and +hashes) are filled in automatically by the U-Boot mkimage tool. + +To avoid confusion with the kernel FDT the following naming convention is used: + +FIT + Flattened Image Tree + +FIT is formally a flattened devicetree (in the libfdt meaning), which conforms +to bindings defined in this document. + +.its + image tree source + +.itb + flattened image tree blob + +Image-building procedure +~~~~~~~~~~~~~~~~~~~~~~~~ + +The following picture shows how the FIT is prepared. Input consists of +image source file (.its) and a set of data files. Image is created with the +help of standard U-Boot mkimage tool which in turn uses dtc (device tree +compiler) to produce image tree blob (.itb). The resulting .itb file is the +actual binary of a new FIT:: + + tqm5200.its + + + vmlinux.bin.gz mkimage + dtc xfer to target + eldk-4.2-ramdisk --------------> tqm5200.itb --------------> boot + tqm5200.dtb /|\ + | + 'new FIT' + +Steps: + +#. Create .its file, automatically filled-in properties are omitted + +#. Call mkimage tool on a .its file + +#. mkimage calls dtc to create .itb image and assures that + missing properties are added + +#. .itb (new FIT) is uploaded onto the target and used therein + + +Unique identifiers +~~~~~~~~~~~~~~~~~~ + +To identify FIT sub-nodes representing images, hashes, configurations (which +are defined in the following sections), the "unit name" of the given sub-node +is used as it's identifier as it assures uniqueness without additional +checking required. + + +External data +~~~~~~~~~~~~~ + +FIT is normally built initially with image data in the 'data' property of each +image node. It is also possible for this data to reside outside the FIT itself. +This allows the 'FDT' part of the FIT to be quite small, so that it can be +loaded and scanned without loading a large amount of data. Then when an image is +needed it can be loaded from an external source. + +External FITs use 'data-offset' or 'data-position' instead of 'data'. + +The mkimage tool can convert a FIT to use external data using the `-E` argument, +optionally using `-p` to specific a fixed position. + +It is often desirable to align each image to a block size or cache-line size +(e.g. 512 bytes), so that there is no need to copy it to an aligned address when +reading the image data. The mkimage tool provides a `-B` argument to support +this. + +Root-node properties +-------------------- + +The root node of the FIT should have the following layout:: + + / o image-tree + |- description = "image description" + |- timestamp = <12399321> + |- #address-cells = <1> + | + o images + | | + | o image-1 {...} + | o image-2 {...} + | ... + | + o configurations + |- default = "conf-1" + | + o conf-1 {...} + o conf-2 {...} + ... + +Optional property +~~~~~~~~~~~~~~~~~ + +description + Textual description of the FIT + +Mandatory property +~~~~~~~~~~~~~~~~~~ + +timestamp + Last image modification time being counted in seconds since + 1970-01-01 00:00:00 - to be automatically calculated by mkimage tool. + +Conditionally mandatory property +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#address-cells + Number of 32bit cells required to represent entry and + load addresses supplied within sub-image nodes. May be omitted when no + entry or load addresses are used. + +Mandatory nodes +~~~~~~~~~~~~~~~ + +images + This node contains a set of sub-nodes, each of them representing + single component sub-image (like kernel, ramdisk, etc.). At least one + sub-image is required. + +configurations + Contains a set of available configuration nodes and + defines a default configuration. + + +'/images' node +-------------- + +This node is a container node for component sub-image nodes. Each sub-node of +the '/images' node should have the following layout:: + + o image-1 + |- description = "component sub-image description" + |- data = /incbin/("path/to/data/file.bin") + |- type = "sub-image type name" + |- arch = "ARCH name" + |- os = "OS name" + |- compression = "compression name" + |- load = <00000000> + |- entry = <00000000> + | + o hash-1 {...} + o hash-2 {...} + ... + +Mandatory properties +~~~~~~~~~~~~~~~~~~~~ + +description + Textual description of the component sub-image + +type + Name of component sub-image type. Supported types are: + + ==================== ================== + Sub-image type Meaning + ==================== ================== + invalid Invalid Image + aisimage Davinci AIS image + atmelimage ATMEL ROM-Boot Image + copro Coprocessor Image} + fdt_legacy legacy Image with Flat Device Tree + filesystem Filesystem Image + firmware Firmware + firmware_ivt Firmware with HABv4 IVT } + flat_dt Flat Device Tree + fpga FPGA Image } + gpimage TI Keystone SPL Image + imx8image NXP i.MX8 Boot Image + imx8mimage NXP i.MX8M Boot Image + imximage Freescale i.MX Boot Image + kernel Kernel Image + kernel_noload Kernel Image (no loading done) + kwbimage Kirkwood Boot Image + lpc32xximage LPC32XX Boot Image + mtk_image MediaTek BootROM loadable Image } + multi Multi-File Image + mxsimage Freescale MXS Boot Image + omapimage TI OMAP SPL With GP CH + pblimage Freescale PBL Boot Image + pmmc TI Power Management Micro-Controller Firmware + ramdisk RAMDisk Image + rkimage Rockchip Boot Image } + rksd Rockchip SD Boot Image } + rkspi Rockchip SPI Boot Image } + script Script + socfpgaimage Altera SoCFPGA CV/AV preloader + socfpgaimage_v1 Altera SoCFPGA A10 preloader + spkgimage Renesas SPKG Image } + standalone Standalone Program + stm32image STMicroelectronics STM32 Image } + sunxi_egon Allwinner eGON Boot Image } + sunxi_toc0 Allwinner TOC0 Boot Image } + tee Trusted Execution Environment Image + ublimage Davinci UBL image + vybridimage Vybrid Boot Image + x86_setup x86 setup.bin + zynqimage Xilinx Zynq Boot Image } + zynqmpbif Xilinx ZynqMP Boot Image (bif) } + zynqmpimage Xilinx ZynqMP Boot Image } + ==================== ================== + +compression + Compression used by included data. If no compression is used, the + compression property should be set to "none". If the data is compressed but + it should not be uncompressed by the loader (e.g. compressed ramdisk), this + should also be set to "none". + + Supported compression types are: + + ==================== ================== + Compression type Meaning + ==================== ================== + none uncompressed + bzip2 bzip2 compressed + gzip gzip compressed + lz4 lz4 compressed + lzma lzma compressed + lzo lzo compressed + zstd zstd compressed + ==================== ================== + +data-size + size of the data in bytes + + +Conditionally mandatory property +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +data + Path to the external file which contains this node's binary data. Within + the FIT this is the contents of the file. This is mandatory unless + external data is used. + +data-offset + Offset of the data in a separate image store. The image store is placed + immediately after the last byte of the device tree binary, aligned to a + 4-byte boundary. This is mandatory if external data is used, with an offset. + +data-position + Machine address at which the data is to be found. This is a fixed address + not relative to the loading of the FIT. This is mandatory if external data + used with a fixed address. + +os + OS name, mandatory for types "kernel". Valid OS names are: + + ==================== ================== + OS name Meaning + ==================== ================== + invalid Invalid OS + 4_4bsd 4_4BSD + arm-trusted-firmware ARM Trusted Firmware + dell Dell + efi EFI Firmware + esix Esix + freebsd FreeBSD + integrity INTEGRITY + irix Irix + linux Linux + ncr NCR + netbsd NetBSD + openbsd OpenBSD + openrtos OpenRTOS + opensbi RISC-V OpenSBI + ose Enea OSE + plan9 Plan 9 + psos pSOS + qnx QNX + rtems RTEMS + sco SCO + solaris Solaris + svr4 SVR4 + tee Trusted Execution Environment + u-boot U-Boot + vxworks VxWorks + ==================== ================== + +arch + Architecture name, mandatory for types: "standalone", "kernel", + "firmware", "ramdisk" and "fdt". Valid architecture names are: + + ==================== ================== + Architecture type Meaning + ==================== ================== + invalid Invalid ARCH + alpha Alpha + arc ARC + arm64 AArch64 + arm ARM + avr32 AVR32 + blackfin Blackfin + ia64 IA64 + m68k M68K + microblaze MicroBlaze + mips64 MIPS 64 Bit + mips MIPS + nds32 NDS32 + nios2 NIOS II + or1k OpenRISC 1000 + powerpc PowerPC + ppc PowerPC + riscv RISC-V + s390 IBM S390 + sandbox Sandbox + sh SuperH + sparc64 SPARC 64 Bit + sparc SPARC + x86_64 AMD x86_64 + x86 Intel x86 + xtensa Xtensa + ==================== ================== + +entry + entry point address, address size is determined by + '#address-cells' property of the root node. + Mandatory for types: "firmware", and "kernel". + +load + load address, address size is determined by '#address-cells' + property of the root node. + Mandatory for types: "firmware", and "kernel". + +compatible + compatible method for loading image. + Mandatory for types: "fpga", and images that do not specify a load address. + Supported compatible methods: + + ========================== ========================================= + Compatible string Meaning + ========================== ========================================= + u-boot,fpga-legacy Generic fpga loading routine. + u-boot,zynqmp-fpga-ddrauth Signed non-encrypted FPGA bitstream for + Xilinx Zynq UltraScale+ (ZymqMP) device. + u-boot,zynqmp-fpga-enc Encrypted FPGA bitstream for Xilinx Zynq + UltraScale+ (ZynqMP) device. + ========================== ========================================= + +phase + U-Boot phase for which the image is intended. + + "spl" + image is an SPL image + + "u-boot" + image is a U-Boot image + +Optional nodes: + +hash-1 + Each hash sub-node represents separate hash or checksum + calculated for node's data according to specified algorithm. + +signature-1 + Each signature sub-node represents separate signature + calculated for node's data according to specified algorithm. + + +Hash nodes +---------- + +:: + + o hash-1 + |- algo = "hash or checksum algorithm name" + |- value = [hash or checksum value] + +Mandatory properties +~~~~~~~~~~~~~~~~~~~~ + +algo + Algorithm name. Supported algoriths and their value sizes are: + + ==================== ============ ========================================= + Sub-image type Size (bytes) Meaning + ==================== ============ ========================================= + crc16-ccitt 2 Cyclic Redundancy Check 16-bit + (Consultative Committee for International + Telegraphy and Telephony) + crc32 4 Cyclic Redundancy Check 32-bit + md5 16 Message Digest 5 (MD5) + sha1 20 Secure Hash Algorithm 1 (SHA1) + sha256 32 Secure Hash Algorithm 2 (SHA256) + sha384 48 Secure Hash Algorithm 2 (SHA384) + sha512 64 Secure Hash Algorithm 2 (SHA512) + ==================== ============ ========================================= + +value + Actual checksum or hash value. + +Image-signature nodes +--------------------- + +:: + + o signature-1 + |- algo = "algorithm name" + |- key-name-hint = "key name" + |- value = [hash or checksum value] + + +Mandatory properties +~~~~~~~~~~~~~~~~~~~~ + +_`FIT Algorithm`: + +algo + Algorithm name. Supported algoriths and their value sizes are shown below. + Note that the hash is specified separately from the signing algorithm, so + it is possible to mix and match any SHA algorithm with any signing + algorithm. The size of the signature relates to the signing algorithm, not + the hash, since it is the hash that is signed. + + ==================== ============ ========================================= + Sub-image type Size (bytes) Meaning + ==================== ============ ========================================= + sha1,rsa2048 256 SHA1 hash signed with 2048-bit + Rivest–Shamir–Adleman algorithm + sha1,rsa3072 384 SHA1 hash signed with 2048-bit RSA + sha1,rsa4096 512 SHA1 hash signed with 2048-bit RSA + sha1,ecdsa256 32 SHA1 hash signed with 256-bit Elliptic + Curve Digital Signature Algorithm + sha256,... + sha384,... + sha512,... + ==================== ============ ========================================= + +key-name-hint + Name of key to use for signing. The keys will normally be in + a single directory (parameter -k to mkimage). For a given key <name>, its + private key is stored in <name>.key and the certificate is stored in + <name>.crt. + +sign-images + A list of images to sign, each being a property of the conf + node that contains then. The default is "kernel,fdt" which means that these + two images will be looked up in the config and signed if present. This is + used by mkimage to determine which images to sign. + +The following properies are added as part of signing, and are mandatory: + +value + Actual signature value. This is added by mkimage. + +hashed-nodes + A list of nodes which were hashed by the signer. Each is + a string - the full path to node. A typical value might be:: + + hashed-nodes = "/", "/configurations/conf-1", "/images/kernel", + "/images/kernel/hash-1", "/images/fdt-1", + "/images/fdt-1/hash-1"; + +hashed-strings + The start and size of the string region of the FIT that was hashed. The + start is normally 0, indicating the first byte of the string table. The size + indicates the number of bytes hashed as part of signing. + +The following properies are added as part of signing, and are optional: + +timestamp + Time when image was signed (standard Unix time_t format) + +signer-name + Name of the signer (e.g. "mkimage") + +signer-version + Version string of the signer (e.g. "2013.01") + +comment + Additional information about the signer or image + +padding + The padding algorithm, it may be pkcs-1.5 or pss, + if no value is provided we assume pkcs-1.5 + + +'/configurations' node +---------------------- + +The 'configurations' node creates convenient, labeled boot configurations, +which combine together kernel images with their ramdisks and fdt blobs. + +The 'configurations' node has the following structure:: + + o configurations + |- default = "default configuration sub-node unit name" + | + o config-1 {...} + o config-2 {...} + ... + + +Optional property +~~~~~~~~~~~~~~~~~ + +default + Selects one of the configuration sub-nodes as a default configuration. + +Mandatory nodes +~~~~~~~~~~~~~~~ + +configuration-sub-node-unit-name + At least one of the configuration sub-nodes is required. + +Optional nodes +~~~~~~~~~~~~~~ + +signature-1 + Each signature sub-node represents separate signature + calculated for the configuration according to specified algorithm. + + +Configuration nodes +------------------- + +Each configuration has the following structure:: + + o config-1 + |- description = "configuration description" + |- kernel = "kernel sub-node unit name" + |- fdt = "fdt sub-node unit-name" [, "fdt overlay sub-node unit-name", ...] + |- loadables = "loadables sub-node unit-name" + |- script = " + |- compatible = "vendor,board-style device tree compatible string" + o signature-1 {...} + +Mandatory properties +~~~~~~~~~~~~~~~~~~~~ + +description + Textual configuration description. + +kernel or firmware + Unit name of the corresponding kernel or firmware + (u-boot, op-tee, etc) image. If both "kernel" and "firmware" are specified, + control is passed to the firmware image. + +Optional properties +~~~~~~~~~~~~~~~~~~~ + +fdt + Unit name of the corresponding fdt blob (component image node of a + "fdt type"). Additional fdt overlay nodes can be supplied which signify + that the resulting device tree blob is generated by the first base fdt + blob with all subsequent overlays applied. + +fpga + Unit name of the corresponding fpga bitstream blob + (component image node of a "fpga type"). + +loadables + Unit name containing a list of additional binaries to be + loaded at their given locations. "loadables" is a comma-separated list + of strings. U-Boot will load each binary at its given start-address and + may optionally invoke additional post-processing steps on this binary based + on its component image node type. + +script + The image to use when loading a U-Boot script (for use with the + source command). + +compatible + The root compatible string of the U-Boot device tree that + this configuration shall automatically match when CONFIG_FIT_BEST_MATCH is + enabled. If this property is not provided, the compatible string will be + extracted from the fdt blob instead. This is only possible if the fdt is + not compressed, so images with compressed fdts that want to use compatible + string matching must always provide this property. + +The FDT blob is required to properly boot FDT based kernel, so the minimal +configuration for 2.6 FDT kernel is (kernel, fdt) pair. + +Older, 2.4 kernel and 2.6 non-FDT kernel do not use FDT blob, in such cases +'struct bd_info' must be passed instead of FDT blob, thus fdt property *must +not* be specified in a configuration node. + +Configuration-signature nodes +----------------------------- + +:: + + o signature-1 + |- algo = "algorithm name" + |- key-name-hint = "key name" + |- sign-images = "path1", "path2"; + |- value = [hash or checksum value] + |- hashed-strings = <0 len> + + +Mandatory properties +~~~~~~~~~~~~~~~~~~~~ + +algo + See `FIT Algorithm`_. + +key-name-hint + Name of key to use for signing. The keys will normally be in + a single directory (parameter -k to mkimage). For a given key <name>, its + private key is stored in <name>.key and the certificate is stored in + <name>.crt. + +The following properies are added as part of signing, and are mandatory: + +value + Actual signature value. This is added by mkimage. + +The following properies are added as part of signing, and are optional: + +timestamp + Time when image was signed (standard Unix time_t format) + +signer-name + Name of the signer (e.g. "mkimage") + +signer-version + Version string of the signer (e.g. "2013.01") + +comment + Additional information about the signer or image + +padding + The padding algorithm, it may be pkcs-1.5 or pss, + if no value is provided we assume pkcs-1.5 + + + +Examples +-------- + +Some example files are available here, showing various scenarios + +.. toctree:: + :maxdepth: 1 + + kernel + kernel_fdt + kernel_fdts_compressed + multi + multi_spl + multi-with-fpga + multi-with-loadables + sec_firmware_ppa + sign-configs + sign-images + uefi + update3 + update_uboot + +.. sectionauthor:: Marian Balakowicz <[email protected]> +.. sectionauthor:: External data additions, 25/1/16 Simon Glass <[email protected]> diff --git a/doc/usage/fit/uefi.rst b/doc/usage/fit/uefi.rst new file mode 100644 index 00000000000..3bbacb5cad0 --- /dev/null +++ b/doc/usage/fit/uefi.rst @@ -0,0 +1,72 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +UEFI +==== + +Example FIT image description file demonstrating the usage of the +bootm command to launch UEFI binaries. + +Two boot configurations are available to enable booting GRUB2 on QEMU, +the former uses a FDT blob contained in the FIT image, while the later +relies on the FDT provided by the board emulator. + +:: + + /dts-v1/; + + / { + description = "GRUB2 EFI and QEMU FDT blob"; + #address-cells = <1>; + + images { + efi-grub { + description = "GRUB EFI Firmware"; + data = /incbin/("bootarm.efi"); + type = "kernel_noload"; + arch = "arm"; + os = "efi"; + compression = "none"; + load = <0x0>; + entry = <0x0>; + hash-1 { + algo = "sha256"; + }; + }; + + fdt-qemu { + description = "QEMU DTB"; + data = /incbin/("qemu-arm.dtb"); + type = "flat_dt"; + arch = "arm"; + compression = "none"; + hash-1 { + algo = "sha256"; + }; + }; + }; + + configurations { + default = "config-grub-fdt"; + + config-grub-fdt { + description = "GRUB EFI Boot w/ FDT"; + kernel = "efi-grub"; + fdt = "fdt-qemu"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel", "fdt"; + }; + }; + + config-grub-nofdt { + description = "GRUB EFI Boot w/o FDT"; + kernel = "efi-grub"; + signature-1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "kernel"; + }; + }; + }; + }; diff --git a/doc/usage/fit/update3.rst b/doc/usage/fit/update3.rst new file mode 100644 index 00000000000..4ff3950c01e --- /dev/null +++ b/doc/usage/fit/update3.rst @@ -0,0 +1,47 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Automatic software update: multiple files +========================================= + +:: + + /dts-v1/; + + / { + description = "Automatic software updates: kernel, ramdisk, FDT"; + #address-cells = <1>; + + images { + update-1 { + description = "Linux kernel binary"; + data = /incbin/("./vmlinux.bin.gz"); + compression = "none"; + type = "firmware"; + load = <FF700000>; + hash-1 { + algo = "sha1"; + }; + }; + update-2 { + description = "Ramdisk image"; + data = /incbin/("./ramdisk_image.gz"); + compression = "none"; + type = "firmware"; + load = <FF8E0000>; + hash-1 { + algo = "sha1"; + }; + }; + + update-3 { + description = "FDT blob"; + data = /incbin/("./blob.fdt"); + compression = "none"; + type = "firmware"; + load = <FFAC0000>; + hash-1 { + algo = "sha1"; + }; + }; + }; + }; diff --git a/doc/usage/fit/update_uboot.rst b/doc/usage/fit/update_uboot.rst new file mode 100644 index 00000000000..a9288ee6367 --- /dev/null +++ b/doc/usage/fit/update_uboot.rst @@ -0,0 +1,28 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Automatic software update +========================= + +Make sure the flashing addresses ('load' prop) is correct for your board! + +:: + + /dts-v1/; + + / { + description = "Automatic U-Boot update"; + #address-cells = <1>; + + images { + update-1 { + description = "U-Boot binary"; + data = /incbin/("./u-boot.bin"); + compression = "none"; + type = "firmware"; + load = <0xFFFC0000>; + hash-1 { + algo = "sha1"; + }; + }; + }; + }; diff --git a/doc/usage/fit/verified-boot.rst b/doc/usage/fit/verified-boot.rst new file mode 100644 index 00000000000..301207711db --- /dev/null +++ b/doc/usage/fit/verified-boot.rst @@ -0,0 +1,107 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot Verified Boot +==================== + +Introduction +------------ + +Verified boot here means the verification of all software loaded into a +machine during the boot process to ensure that it is authorised and correct +for that machine. + +Verified boot extends from the moment of system reset to as far as you wish +into the boot process. An example might be loading U-Boot from read-only +memory, then loading a signed kernel, then using the kernel's dm-verity +driver to mount a signed root filesystem. + +A key point is that it is possible to field-upgrade the software on machines +which use verified boot. Since the machine will only run software that has +been correctly signed, it is safe to read software from an updatable medium. +It is also possible to add a secondary signed firmware image, in read-write +memory, so that firmware can easily be upgraded in a secure manner. + + +Signing +------- + +Verified boot uses cryptographic algorithms to 'sign' software images. +Images are signed using a private key known only to the signer, but can +be verified using a public key. As its name suggests the public key can be +made available without risk to the verification process. The private and +public keys are mathematically related. For more information on how this +works look up "public key cryptography" and "RSA" (a particular algorithm). + +The signing and verification process looks something like this:: + + + Signing Verification + ======= ============ + + +--------------+ * + | RSA key pair | * +---------------+ + | .key .crt | * | Public key in | + +--------------+ +------> public key ----->| trusted place | + | | * +---------------+ + | | * | + v | * v + +---------+ | * +--------------+ + | |---------+ * | | + | signer | * | U-Boot | + | |---------+ * | signature |--> yes/no + +---------+ | * | verification | + ^ | * | | + | | * +--------------+ + | | * ^ + +----------+ | * | + | Software | +----> signed image -------------+ + | image | * + +----------+ * + + +The signature algorithm relies only on the public key to do its work. Using +this key it checks the signature that it finds in the image. If it verifies +then we know that the image is OK. + +The public key from the signer allows us to verify and therefore trust +software from updatable memory. + +It is critical that the public key be secure and cannot be tampered with. +It can be stored in read-only memory, or perhaps protected by other on-chip +crypto provided by some modern SOCs. If the public key can be changed, then +the verification is worthless. + + +Chaining Images +--------------- + +The above method works for a signer providing images to a run-time U-Boot. +It is also possible to extend this scheme to a second level, like this: + +#. Master private key is used by the signer to sign a first-stage image. +#. Master public key is placed in read-only memory. +#. Secondary private key is created and used to sign second-stage images. +#. Secondary public key is placed in first stage images +#. We use the master public key to verify the first-stage image. We then + use the secondary public key in the first-stage image to verify the second- + state image. +#. This chaining process can go on indefinitely. It is recommended to use a + different key at each stage, so that a compromise in one place will not + affect the whole change. + + +Flattened Image Tree (FIT) +-------------------------- + +The FIT format is already widely used in U-Boot. It is a flattened device +tree (FDT) in a particular format, with images contained within. FITs +include hashes to verify images, so it is relatively straightforward to +add signatures as well. + +The public key can be stored in U-Boot's CONFIG_OF_CONTROL device tree in +a standard place. Then when a FIT is loaded it can be verified using that +public key. Multiple keys and multiple signatures are supported. + +See :doc:`signature` for more information. + +.. sectionauthor:: Simon Glass <[email protected]> 1-1-13 diff --git a/doc/usage/fit/x86-fit-boot.rst b/doc/usage/fit/x86-fit-boot.rst new file mode 100644 index 00000000000..93b73bb9019 --- /dev/null +++ b/doc/usage/fit/x86-fit-boot.rst @@ -0,0 +1,269 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Booting Linux on x86 with FIT +============================= + +Background +---------- + +Generally Linux x86 uses its own very complex booting method. There is a setup +binary which contains all sorts of parameters and a compressed self-extracting +binary for the kernel itself, often with a small built-in serial driver to +display decompression progress. + +The x86 CPU has various processor modes. I am no expert on these, but my +understanding is that an x86 CPU (even a really new one) starts up in a 16-bit +'real' mode where only 1MB of memory is visible, moves to 32-bit 'protected' +mode where 4GB is visible (or more with special memory access techniques) and +then to 64-bit 'long' mode if 64-bit execution is required. + +Partly the self-extracting nature of Linux was introduced to cope with boot +loaders that were barely capable of loading anything. Even changing to 32-bit +mode was something of a challenge, so putting this logic in the kernel seemed +to make sense. + +Bit by bit more and more logic has been added to this post-boot pre-Linux +wrapper: + +- Changing to 32-bit mode +- Decompression +- Serial output (with drivers for various chips) +- Load address randomisation +- Elf loader complete with relocation (for the above) +- Random number generator via 3 methods (again for the above) +- Some sort of EFI mini-loader (1000+ glorious lines of code) +- Locating and tacking on a device tree and ramdisk + +To my mind, if you sit back and look at things from first principles, this +doesn't make a huge amount of sense. Any boot loader worth its salts already +has most of the above features and more besides. The boot loader already knows +the layout of memory, has a serial driver, can decompress things, includes an +ELF loader and supports device tree and ramdisks. The decision to duplicate +all these features in a Linux wrapper caters for the lowest common +denominator: a boot loader which consists of a BIOS call to load something off +disk, followed by a jmp instruction. + +(Aside: On ARM systems, we worry that the boot loader won't know where to load +the kernel. It might be easier to just provide that information in the image, +or in the boot loader rather than adding a self-relocator to put it in the +right place. Or just use ELF? + +As a result, the x86 kernel boot process is needlessly complex. The file +format is also complex, and obfuscates the contents to a degree that it is +quite a challenge to extract anything from it. This bzImage format has become +so prevalent that is actually isn't possible to produce the 'raw' kernel build +outputs with the standard Makefile (as it is on ARM for example, at least at +the time of writing). + +This document describes an alternative boot process which uses simple raw +images which are loaded into the right place by the boot loader and then +executed. + + +Build the kernel +---------------- + +Note: these instructions assume a 32-bit kernel. U-Boot also supports directly +booting a 64-bit kernel by jumping into 64-bit mode first (see below). + +You can build the kernel as normal with 'make'. This will create a file called +'vmlinux'. This is a standard ELF file and you can look at it if you like:: + + $ objdump -h vmlinux + + vmlinux: file format elf32-i386 + + Sections: + Idx Name Size VMA LMA File off Algn + 0 .text 00416850 81000000 01000000 00001000 2**5 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .notes 00000024 81416850 01416850 00417850 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 2 __ex_table 00000c50 81416880 01416880 00417880 2**3 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 3 .rodata 00154b9e 81418000 01418000 00419000 2**5 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 4 __bug_table 0000597c 8156cba0 0156cba0 0056dba0 2**0 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 5 .pci_fixup 00001b80 8157251c 0157251c 0057351c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 6 .tracedata 00000024 8157409c 0157409c 0057509c 2**0 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 7 __ksymtab 00007ec0 815740c0 015740c0 005750c0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 8 __ksymtab_gpl 00004a28 8157bf80 0157bf80 0057cf80 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 9 __ksymtab_strings 0001d6fc 815809a8 015809a8 005819a8 2**0 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 10 __init_rodata 00001c3c 8159e0a4 0159e0a4 0059f0a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 11 __param 00000ff0 8159fce0 0159fce0 005a0ce0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 12 __modver 00000330 815a0cd0 015a0cd0 005a1cd0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 13 .data 00063000 815a1000 015a1000 005a2000 2**12 + CONTENTS, ALLOC, LOAD, RELOC, DATA + 14 .init.text 0002f104 81604000 01604000 00605000 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .init.data 00040cdc 81634000 01634000 00635000 2**12 + CONTENTS, ALLOC, LOAD, RELOC, DATA + 16 .x86_cpu_dev.init 0000001c 81674cdc 01674cdc 00675cdc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 17 .altinstructions 0000267c 81674cf8 01674cf8 00675cf8 2**0 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 18 .altinstr_replacement 00000942 81677374 01677374 00678374 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 19 .iommu_table 00000014 81677cb8 01677cb8 00678cb8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 20 .apicdrivers 00000004 81677cd0 01677cd0 00678cd0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, DATA + 21 .exit.text 00001a80 81677cd8 01677cd8 00678cd8 2**0 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .data..percpu 00007880 8167a000 0167a000 0067b000 2**12 + CONTENTS, ALLOC, LOAD, RELOC, DATA + 23 .smp_locks 00003000 81682000 01682000 00683000 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 24 .bss 000a1000 81685000 01685000 00686000 2**12 + ALLOC + 25 .brk 00424000 81726000 01726000 00686000 2**0 + ALLOC + 26 .comment 00000049 00000000 00000000 00686000 2**0 + CONTENTS, READONLY + 27 .GCC.command.line 0003e055 00000000 00000000 00686049 2**0 + CONTENTS, READONLY + 28 .debug_aranges 0000f4c8 00000000 00000000 006c40a0 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 29 .debug_info 0440b0df 00000000 00000000 006d3568 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 30 .debug_abbrev 0022a83b 00000000 00000000 04ade647 2**0 + CONTENTS, READONLY, DEBUGGING + 31 .debug_line 004ead0d 00000000 00000000 04d08e82 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 32 .debug_frame 0010a960 00000000 00000000 051f3b90 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 33 .debug_str 001b442d 00000000 00000000 052fe4f0 2**0 + CONTENTS, READONLY, DEBUGGING + 34 .debug_loc 007c7fa9 00000000 00000000 054b291d 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 35 .debug_ranges 00098828 00000000 00000000 05c7a8c8 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + +There is also the setup binary mentioned earlier. This is at +arch/x86/boot/setup.bin and is about 12KB in size. It includes the command +line and various settings need by the kernel. Arguably the boot loader should +provide all of this also, but setting it up is some complex that the kernel +helps by providing a head start. + +As you can see the code loads to address 0x01000000 and everything else +follows after that. We could load this image using the 'bootelf' command but +we would still need to provide the setup binary. This is not supported by +U-Boot although I suppose you could mostly script it. This would permit the +use of a relocatable kernel. + +All we need to boot is the vmlinux file and the setup.bin file. + + +Create a FIT +------------ + +To create a FIT you will need a source file describing what should go in the +FIT. See kernel.its for an example for x86 and also instructions on setting +the 'arch' value for booting 64-bit kernels if desired. Put this into a file +called image.its. + +Note that setup is loaded to the special address of 0x90000 (a special address +you just have to know) and the kernel is loaded to 0x01000000 (the address you +saw above). This means that you will need to load your FIT to a different +address so that U-Boot doesn't overwrite it when decompressing. Something like +0x02000000 will do so you can set CONFIG_SYS_LOAD_ADDR to that. + +In that example the kernel is compressed with lzo. Also we need to provide a +flat binary, not an ELF. So the steps needed to set things are are:: + + # Create a flat binary + objcopy -O binary vmlinux vmlinux.bin + + # Compress it into LZO format + lzop vmlinux.bin + + # Build a FIT image + mkimage -f image.its image.fit + +(be careful to run the mkimage from your U-Boot tools directory since it +will have x86_setup support.) + +You can take a look at the resulting fit file if you like:: + + $ dumpimage -l image.fit + FIT description: Simple image with single Linux kernel on x86 + Created: Tue Oct 7 10:57:24 2014 + Image 0 (kernel) + Description: Vanilla Linux kernel + Created: Tue Oct 7 10:57:24 2014 + Type: Kernel Image + Compression: lzo compressed + Data Size: 4591767 Bytes = 4484.15 kB = 4.38 MB + Architecture: Intel x86 + OS: Linux + Load Address: 0x01000000 + Entry Point: 0x00000000 + Hash algo: sha1 + Hash value: 446b5163ebfe0fb6ee20cbb7a8501b263cd92392 + Image 1 (setup) + Description: Linux setup.bin + Created: Tue Oct 7 10:57:24 2014 + Type: x86 setup.bin + Compression: uncompressed + Data Size: 12912 Bytes = 12.61 kB = 0.01 MB + Hash algo: sha1 + Hash value: a1f2099cf47ff9816236cd534c77af86e713faad + Default Configuration: 'config-1' + Configuration 0 (config-1) + Description: Boot Linux kernel + Kernel: kernel + + +Booting the FIT +--------------- + +To make it boot you need to load it and then use 'bootm' to boot it. A +suitable script to do this from a network server is:: + + bootp + tftp image.fit + bootm + +This will load the image from the network and boot it. The command line (from +the 'bootargs' environment variable) will be passed to the kernel. + +If you want a ramdisk you can add it as normal with FIT. If you want a device +tree then x86 doesn't normally use those - it has ACPI instead. + + +Why Bother? +----------- + +#. It demystifies the process of booting an x86 kernel +#. It allows use of the standard U-Boot boot file format +#. It allows U-Boot to perform decompression - problems will provide an error + message and you are still in the boot loader. It is possible to investigate. +#. It avoids all the pre-loader code in the kernel which is quite complex to + follow +#. You can use verified/secure boot and other features which haven't yet been + added to the pre-Linux +#. It makes x86 more like other architectures in the way it boots a kernel. + You can potentially use the same file format for the kernel, and the same + procedure for building and packaging it. + + +References +---------- + +In the Linux kernel, Documentation/x86/boot.txt defines the boot protocol for +the kernel including the setup.bin format. This is handled in U-Boot in +arch/x86/lib/zimage.c and arch/x86/lib/bootm.c. + +Various files in the same directory as this file describe the FIT format. + + +.. sectionauthor:: Simon Glass <[email protected]> 7-Oct-2014 diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 84ef8a9a427..388e59f1733 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -8,7 +8,7 @@ Use U-Boot dfu environment fdt_overlays - fit + fit/index netconsole partitions cmdline @@ -25,12 +25,14 @@ Shell commands cmd/askenv cmd/base cmd/bdinfo + cmd/bind cmd/blkcache cmd/bootd cmd/bootdev cmd/bootefi cmd/bootflow cmd/booti + cmd/bootm cmd/bootmenu cmd/bootmeth cmd/button @@ -62,9 +64,11 @@ Shell commands cmd/fwu_mdata cmd/gpio cmd/host + cmd/imxtract cmd/load cmd/loadb cmd/loadm + cmd/loads cmd/loadx cmd/loady cmd/mbr @@ -81,6 +85,7 @@ Shell commands cmd/read cmd/reset cmd/rng + cmd/saves cmd/sbi cmd/sf cmd/scp03 @@ -96,6 +101,7 @@ Shell commands cmd/trace cmd/true cmd/ums + cmd/unbind cmd/ut cmd/wdt cmd/wget |
