diff --git a/source/reference-manual/security/boot-software-updates-imx.rst b/source/reference-manual/security/boot-software-updates-imx.rst index a68836b4c..384f54e9c 100644 --- a/source/reference-manual/security/boot-software-updates-imx.rst +++ b/source/reference-manual/security/boot-software-updates-imx.rst @@ -5,49 +5,42 @@ Boot Software Updates on iMX ============================ -Boot artifacts +Boot Artifacts -------------- SPL ~~~ -SPL is the first software loader generated by the i.MX U-Boot build. It -is signed via the NXP CST tool which fills in various IVT header fields. -SPL binaries from CI **cannot** be added directly to OTA due to the missing -signature data which must be added by the subscriber. +SPL is the first software loader generated by the i.MX U-Boot build. +It is signed via the NXP® CST tool, filling in various IVT header fields. +SPL binaries from CI **cannot** be added directly to OTA due to missing signature data, which must be added by you. -In some cases, an SoC may require additional firmware to be loaded (such as -DDR firmware for i.MX 8M). This firmware is loaded prior to the load / -verification of U-Boot FIT-image. +In some cases, an SoC may require additional firmware to be loaded (such as DDR firmware for i.MX 8M). +This firmware is loaded prior to the load/verification of U-Boot FIT-image. -U-Boot FIT image +U-Boot FIT Image ~~~~~~~~~~~~~~~~ -U-boot FIT-image is a generic name for the signed FIT-image that -contains U-Boot proper (u-boot.bin) and a host of other firmware. +"U-boot FIT-image" is a generic name for the signed FIT-image containing U-Boot proper (``u-boot.bin``) and a host of other firmware. This file is verified by SPL via a public key stored in SPL’s dtb. -This artifact may be signed (on closed boards) as a part of CI and -can be included automatically in a boot software OTA package. +This artifact may be signed—on closed boards—as a part of CI, and can be included automatically in a boot software OTA package. -- U-boot-nodtb.bin -- U-boot.dtb +- ``U-boot-nodtb.bin`` +- ``U-boot.dtb`` - OP-TEE - Arm Trusted Firmware (ARMv8) - Possibly other firmwares -If the CI signing key has been rotated since the last OTA, then -the SPL.dtb verification data needs to be updated prior to booting the -new U-Boot FIT-image. +If the CI signing key has been rotated since the last OTA, then the SPL.dtb verification data needs to be updated prior to booting the new U-Boot FIT-image. -MMC boot image layout +MMC Boot Image Layout --------------------- |image of iMX6 layout| |image of iMX8M layout| -The Secondary Image Table (SIT) is a 20 byte long structure containing 5 -32-bit words. These encode the bootloader B-copy area offset (called -**firstSectorNumber**), magic value (called **tag**) that is always -**0x00112233**, and three unused words set to 0. Example SIT: +The Secondary Image Table (SIT) is a 20 byte long structure containing 5 32-bit words. +These encode the bootloader B-copy area offset (``firstSectorNumber``), the magic value (``tag``) which is always ``0x00112233``, and three unused words set to ``0``. +Example SIT: :: @@ -84,7 +77,7 @@ OP-TEE #. Driver init #. Load TAs #. Drop to EL-2 secure world -#. Jump to u-boot.bin +#. Jump to ``u-boot.bin`` U-Boot ~~~~~~ @@ -96,69 +89,54 @@ U-Boot #. Extract components #. Jump to Linux kernel -Update procedure +Update Procedure ---------------- -Primary vs Secondary boot paths +Primary vs Secondary Boot Paths ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -There are some i.MX SoC which could be configured to have two copies of -the bootloader in SD/eMMC and switch between them. The switch can be -triggered either by the BootROM in case the bootloader image is faulty -OR can be enforced by the user. +There are some i.MX SoCs which can be configured to have two copies of the bootloader in SD/eMMC, and switch between them. +The switch can be triggered either by the BootROM—in case the bootloader image is faulty—or can be enforced by the user. The bootloader A-copy must be placed at a predetermined offset in SD/eMMC. -The bootloader B-copy area offset is determined by an offset stored in -The Secondary Image Table (SIT). The SIT must be placed at predetermined -offset in SD/eMMC. - -To enforce BootROM to boot the secondary boot image, -**PERSIST\_SECONDARY\_BOOT** must be set in **SRC\_GPR10** register and a -warm reset has to be performed. After reboot, BootROM will boot the image -using the offset specified in the SIT table. For additional details about -the SIT format and SIT offsets, please refer to your the SoC Reference Manual, -section *Redundant boot support for expansion device*. - -libaktualizr and aktualizr-lite -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The bootloader B-copy area offset is determined by an offset stored in The Secondary Image Table (SIT). +The SIT must be placed at the predetermined offset in SD/eMMC. + +To enforce BootROM to boot the secondary boot image, ``PERSIST\_SECONDARY\_BOOT`` must be set in the ``SRC\_GPR10`` register, and a warm reset performed. +After reboot, BootROM will boot the image using the offset specified in the SIT table. +For additional details about the SIT format and SIT offsets, please refer to your the SoC Reference Manual, section *Redundant boot support for expansion device*. + +``libaktualizr`` and ``aktualizr-lite`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -1. aktualizr-lite decides if boot firmware needs to be updated based - on the contents of **${ostree\_root}/usr/lib/firmware/version.txt**, - where ostree\_root is root of newly deployed ostree sysroot. Example - of contents: **bootfirmware\_version=10** -2. After parsing bootfirmware\_version, it compares the new version number - with the existing one, which is obtained via **fiovb** or **ubootenv**. -3. If bootfirmware\_version from version.txt is higher than the existing - one, aktualizr-lite sets **bootupgrade\_available** via **fiovb** or - **ubootenv**. +1. Aktualizr-lite decides if boot firmware needs to be updated based on ``${ostree\_root}/usr/lib/firmware/version.txt``, where ``ostree\_root`` is the root of newly deployed ostree sysroot. + Example of contents: ``bootfirmware\_version=10`` +2. After parsing ``bootfirmware\_version``, it compares the new version number with the existing one. + This is obtained via ``fiovb`` or ``ubootenv``. +3. If ``bootfirmware\_version`` from ``version.txt`` is higher than the existing one, aktualizr-lite sets ``bootupgrade\_available`` via ``fiovb`` or ``ubootenv``. 4. Reboot should be performed. -U-Boot boot.cmd script -~~~~~~~~~~~~~~~~~~~~~~ +U-Boot ``boot.cmd`` Script +~~~~~~~~~~~~~~~~~~~~~~~~~~ .. figure:: boot-software-updates/upgrade-flow.png :alt: Boot firmware upgrade flow Boot firmware upgrade flow -1. Actual update is done via U-Boot **boot.cmd** (boot.scr) script. -2. **boot.cmd** script checks if booting secondary path is booted -3. In case **upgrade\_available** is set, check if boot firmware - upgrade is needed is by checking the **bootupgrade\_available** flag. - If both are true, obtain boot firmware images from the newly - deployed ostree sysroot and write them to secondary boot path offsets. - After the secondary boot bit is set, warm reset is performed to - enforce BootROM to boot secondary boot path. -4. After rebooting secondary boot path is executed, perform condition - verification from step 2. It should evaluate as false so just - regular boot of Linux having taken place. -5. After Linux is booted, aktualizr-lite confirms a successful update by - clearing the **upgrade\_available** flag. At this point, new boot firmware - images are validated and need to be flashed to the stable primary path. +1. Actual update is done via U-Boot ``boot.cmd`` script (``boot.scr``). +2. ``boot.cmd`` checks if the booting secondary path is booted. +3. In case ``upgrade\_available`` is set, check if boot firmware upgrade is needed is by checking the ``bootupgrade\_available`` flag. + If both are true, obtain boot firmware images from the newly deployed ostree sysroot and write them to secondary boot path offsets. + After the secondary boot bit is set, warm reset is performed to enforce BootROM to boot secondary boot path. +4. After executing rebooting secondary boot path, perform condition verification from step 2. + It should evaluate as false, so regular booting of Linux having taken place. +5. After Linux is booted, aktualizr-lite confirms a successful update by clearing the **upgrade\_available** flag. + At this point, new boot firmware images are validated and need to be flashed to the stable primary path. Additional reboot is needed after this step. 6. Regular POR cold reset is performed. -Add a new board +Add a New Board --------------- .. _ref-sec-tfa-optee: @@ -166,13 +144,10 @@ Add a new board TF-A/OP-TEE ~~~~~~~~~~~ -TF-A on ARMv8 or OP-TEE on ARMv7, provides PSCI services to the -Linux OS and should support the **`SYSTEM\_RESET2`**, which implements -a internal warm reset, resetting only the CPU. This is needed for -retaining the values of special registers after reboot. This -behavior differs from a regular SYSTEM\_RESET, which causes -POR, removing power for the whole board (resets CPU, DDR and -peripherals, on some boards it also resets external PMIC). +TF-A on ARMv8, or OP-TEE on ARMv7, provides PSCI services to the Linux® OS and should support the ``SYSTEM\_RESET2``. +This implements a internal warm reset, resetting only the CPU. +This is needed for retaining the values of special registers after reboot. +This behavior differs from a regular ``SYSTEM\_RESET``, which causes ``POR``, removing power for the whole board (resets CPU, DDR and peripherals, on some boards it also resets external PMIC). U-Boot ~~~~~~ @@ -180,12 +155,10 @@ U-Boot SPL: FIT Image Offset Calculation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -U-Boot SPL automatically detects which image to boot next based on -the SECONDARY\_BOOT value. Every board has the configuration -**CONFIG\_SYS\_MMCSD\_RAW\_MODE\_U\_BOOT\_SECTOR**, which contains the -offset of the U-Boot FIT image beginning from the boot media -sectors (512 bytes each). Below is an example of how the final offset is -calculated on iMX SoCs (extract from *./arch/arm/mach-imx/spl.c*): +U-Boot SPL automatically detects which image to boot next based on the SECONDARY\_BOOT value. +Every board has the configuration ``CONFIG\_SYS\_MMCSD\_RAW\_MODE\_U\_BOOT\_SECTOR``. +This contains the offset of the U-Boot FIT image, beginning from the boot media sectors (512 bytes each). +Below is an example of how the final offset is calculated on iMX SoCs (extract from ``./arch/arm/mach-imx/spl.c``): :: @@ -213,27 +186,22 @@ calculated on iMX SoCs (extract from *./arch/arm/mach-imx/spl.c*): Fastboot: Support of Secondary Boot Image Offsets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The required offsets for the secondary boot images (**SPL**, **U-Boot.itb**, -and **SIT**) for iMX6, iMX6ULL, iMX7 and iMX8M SoCs, are defined by the FSL -fastboot driver. To change SIT offset used for -an SoC, adjust the **secondary\_image\_table\_mmc\_offset()** and -**bootloader\_mmc\_offset()** functions within the U-Boot fastboot driver -source (*drivers/fastboot/fb\_fsl/fb\_fsl\_partitions.c*). +The required offsets for the secondary boot images (**SPL**, **U-Boot.itb**, and **SIT**) for iMX6, iMX6ULL, iMX7, and iMX8M SoCs are defined by the FSL fastboot driver. +To change the SIT offset used for an SoC, +adjust the ``secondary\_image\_table\_mmc\_offset()`` and ``bootloader\_mmc\_offset()`` functions within the U-Boot fastboot driver source (``drivers/fastboot/fb\_fsl/fb\_fsl\_partitions.c``). Secondary Image Table Generation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -SIT image binary is generated automatically if U-Boot is being -built with the correct value of **CONFIG\_SECONDARY\_BOOT\_SECTOR\_OFFSET** -config option. +SIT image binary is generated automatically if U-Boot is being built with the correct value for the ``CONFIG\_SECONDARY\_BOOT\_SECTOR\_OFFSET`` config option. Watchdog ^^^^^^^^ -As secondary boot path is mainly used for boot firmware update image -validation, in exceptional cases it will behave incorrectly, -such as the system not responding. To cover such cases, watchdog support has -to be enabled in SPL by adding the following config options to **lmp.cfg**: +The secondary boot path is mainly used for boot firmware update image validation. +In exceptional cases it will behave incorrectly, such as the system not responding. +To address such cases, watchdog support has to be enabled in SPL. +This is done by adding the following config options to ``lmp.cfg``: :: @@ -242,18 +210,16 @@ to be enabled in SPL by adding the following config options to **lmp.cfg**: # CONFIG_SPL_WDT is not set CONFIG_SPL_WATCHDOG_SUPPORT=y -meta-lmp -~~~~~~~~ +``meta-lmp`` +~~~~~~~~~~~~ -mfgtool scripts +MfgTool Scripts ^^^^^^^^^^^^^^^ To deploy boot images to the destination board, the mfgtools package is used. -It uses a special configuration file with uuu extensions, which contains -all needed instructions for the deployment of boot images. Default -uuu files do not support flashing images for secondary boot path. Doing so -requiring the following adjustments: adding SIT image, secondary SPL -and U-Boot FIT deployment steps: +It uses a special configuration file with ``uuu`` extensions, which contains all instructions needed for the deployment of boot images. +Default uuu files do not support flashing images for secondary boot path. +Doing so requires the following adjustments: adding SIT image, secondary SPL, and U-Boot FIT deployment steps: :: @@ -285,13 +251,11 @@ The final uuu script looks like: FB: ucmd mmc partconf ${mmcdev} ${emmc_ack} 1 0 FB: done -lmp.cfg files -^^^^^^^^^^^^^ +``lmp.cfg`` Files +^^^^^^^^^^^^^^^^^ -To enable support for flashing/booting secondary boot images, -adjust the default **lmp.cfg** and the one for mfgtools for the device, -enabling support for the secondary boot path. -The following config options need to be added to the default **lmp.cfg**: +To enable support for flashing/booting secondary boot images, adjust both the default ``lmp.cfg`` ,and the one for mfgtools. +The following config options need to be added to the default ``lmp.cfg``: :: @@ -299,54 +263,47 @@ The following config options need to be added to the default **lmp.cfg**: CONFIG_SECONDARY_BOOT_SECTOR_OFFSET=0x1000 CONFIG_CMD_SECONDARY_BOOT=y -And to mfgtool **lmp.cfg**: +And to mfgtool ``lmp.cfg``: :: CONFIG_FSL_FASTBOOT_BOOTLOADER_SECONDARY=y CONFIG_SECONDARY_BOOT_SECTOR_OFFSET=0x1000 -Pre-load boot.cmd by SPL -^^^^^^^^^^^^^^^^^^^^^^^^ +Pre-Load ``boot.cmd`` by SPL +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -As boot.cmd script depends on U-Boot cmds for booting Linux, it should be -aligned with U-Boot version. By default in regular setups without boot firmware -update support boot.cmd is stored in first FAT partition in eMMC/SD. -So to get boot.cmd updates together with other boot software images, -it should be moved from FAT partition to U-Boot FIT image. To do that edit -**lmp-machine-custom.inc** adding this line for your board (imx8mqevk as -an example): +As ``boot.cmd`` depends on U-Boot commands for booting Linux, it should be aligned with the U-Boot version. +By default, in setups without boot firmware update support, ``boot.cmd`` is stored in the first FAT partition in eMMC/SD. +To get ``boot.cmd`` updates—together with other boot software images—it should be moved from the FAT partition, to the U-Boot FIT image. +To do this, edit ``lmp-machine-custom.inc``, adding this line for your board (imx8mqevk used as an example): :: BOOTSCR_LOAD_ADDR_imx8mqevk = "0x44800000" -This change will include Linux **boot.cmd** into U-Boot FIT image -alongside with TF-A/OP-TEE/U-Boot proper/U-Boot dtb images. When SPL -parses U-Boot FIT image (u-boot.itb) will pre-load **boot.itb** -(compiled and wrapped **boot.cmd**) to the address specified in -**BOOTSCR\_LOAD\_ADDR** variable. +This change will include Linux ``boot.cmd`` into the U-Boot FIT image, alongside TF-A/OP-TEE/U-Boot proper/U-Boot dtb images. +When SPL parses the U-Boot FIT image (``u-boot.itb``) it will pre-load ``boot.itb`` (compiled and wrapped ``boot.cmd``) to the address specified in ``BOOTSCR\_LOAD\_ADDR`` variable. -To let U-Boot know where to take boot script from, you should also -adjust **CONFIG\_BOOTCOMMAND** param in your U-Boot **lmp.cfg** of your -board. +To let U-Boot know where to get the boot script from, you should also adjust ``CONFIG\_BOOTCOMMAND`` in the U-Boot ``lmp.cfg`` of your board. :: CONFIG_BOOTCOMMAND="setenv verify 1; source 0x44800000; reset" -Test basic API +Test Basic API ~~~~~~~~~~~~~~ -After applying all updates from previous steps, we should validate that -everything is in place. Basically this consists of two basic steps: +After applying all the updates from previous steps, we should validate that everything is in place. +This consists of two steps: - Cold/Warm resets from U-Boot are functional - Obtain board security state (open/closed states) -So to test cold/warm resets and booting primary/secondary boot path use -these two U-Boot commands **imx\_secondary\_boot** and **reset** (for -regular reset, usually it's does POR)/\ **reset -w** (warm reset). +To test cold/warm resets and booting primary/secondary boot path, use these two U-Boot commands ``imx\_secondary\_boot`` and ``reset``\ ``reset -w`` (warm reset). + + .. tip:: + For regular reset, usually it does ``POR``. Example of test: @@ -367,28 +324,24 @@ Example of test: ... Hit any key to stop autoboot: 0 -From output you can see that after setting secondary boot and performing -warm reset, BootROM boots images from secondary boot path (*SPL: Booting -secondary boot path: using 0x1300 offset for next boot image*). +From the output, you can see that after setting secondary boot and performing warm reset, +BootROM boots images from secondary boot path (``SPL: Booting secondary boot path: using 0x1300 offset for next boot image``). -To check if the security status of your board is detected correctly, use -**imx\_is\_closed** command: +To check if the security status of your board is detected correctly, use the ``imx\_is\_closed`` command: :: u-boot=> imx_is_closed Board is in open state -boot.cmd -~~~~~~~~ +``boot.cmd`` +~~~~~~~~~~~~ -Currently LmP uses template-based way of generation of final boot.cmd. -It's constructed from common boot files -(``./meta-lmp-base/recipes-bsp/u-boot/u-boot-ostree-scr-fit``), -which contains all SoC agnostic DEFINEs and common functionality, and board -specific boot.cmd, which includes the common scripts. +Currently, LmP uses template-based generation for the final ``boot.cmd``. +It is constructed from common boot files (``./meta-lmp-base/recipes-bsp/u-boot/u-boot-ostree-scr-fit``), +which contains all SoC agnostic ``DEFINE`` statements and common functionality, and board specific ``boot.cmd``, which includes the common scripts. -Example of board boot.cmd +Example of board ``boot.cmd`` (``./meta-lmp-bsp/recipes-bsp/u-boot/u-boot-ostree-scr-fit/imx8mm-lpddr4-evk/boot.cmd``): :: @@ -423,32 +376,27 @@ Example of board boot.cmd @@INCLUDE_COMMON_IMX@@ @@INCLUDE_COMMON@@ -From the list above you can find that the only needed variables that -should be defined are: boot/root partition indexes, mmc device index and -**fdt\_file**. For boot firmware updates functionality also bootloader -image offsets and names should be provided. +Above you can find that the only needed variables that should be defined are: boot/root partition indexes, mmc device index, and ``fdt\_file``. +For boot firmware update functionality, bootloader image offsets and names should also be provided. -sysroot and signed boot artifacts +Sysroot and Signed Boot Artifacts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -All boot artifacts (SPL/imx-boot and U-Boot FIT) are automatically deployed -to sysroot during build time, however on closed boards, where initial boot -image has to be signed in advance by a subscriber private key, there is way to -add signed binary instead of automatic inclusion of unsigned boot artifacts. - -To do that, just add ``lmp-boot-firmware.bbappend`` to your *meta-subscriber-overrides* -layer, adding the path to the signed binary and the signed binary itself. +All boot artifacts (SPL/imx-boot and U-Boot FIT) are automatically deployed to sysroot during build time. +However, on closed boards where the initial boot image has to be signed in advance by a subscriber private key, +there is way to add a signed binary instead of automatic inclusion of unsigned boot artifacts. -Then define boot firmware version number by setting ``LMP_BOOT_FIRMWARE_VERSION`` -global variable in your ``lmp-factory-custom.inc``. Boot firmware version -information will be automatically added to `${osroot}/usr/lib/firmware/version.txt` -file and U-Boot Device Tree Blob. +To do this, add ``lmp-boot-firmware.bbappend`` to your ``meta-subscriber-overrides`` layer, adding the path to the signed binary and the signed binary itself. +Next, define the boot firmware version by setting the ``LMP_BOOT_FIRMWARE_VERSION`` global variable in your ``lmp-factory-custom.inc``. +Boot firmware version information will be automatically added to ``${osroot}/usr/lib/firmware/version.txt`` and the U-Boot Device Tree Blob. .. note:: - The signed binary is called ``SPL`` for i.MX 6/7 and ``imx-boot`` for i.MX 8* platforms. No need to append ``.signed`` to the binary name. + The signed binary is called ``SPL`` for i.MX 6/7, and ``imx-boot`` for i.MX 8* platforms. + No need to append ``.signed`` to the binary name. Example: + :: diff --git a/recipes-bsp/lmp-boot-firmware/lmp-boot-firmware.bbappend b/recipes-bsp/lmp-boot-firmware/lmp-boot-firmware.bbappend @@ -478,9 +426,8 @@ Example: .. note:: - As ``LMP_BOOT_FIRMWARE_VERSION`` is now a preferable way to set boot firmware version, defining ``PV`` in ``lmp-boot-firmware.bbappend`` - is deprecated and should not be used. To switch to a new approach just remove ``PV = ""`` line from - ``lmp-boot-firmware.bbappend`` and define ``LMP_BOOT_FIRMWARE_VERSION`` with appropriate version value as shown above in the example. + As ``LMP_BOOT_FIRMWARE_VERSION`` is now the preferred way to set boot firmware version, defining ``PV`` in ``lmp-boot-firmware.bbappend`` is deprecated and should not be used. + To switch to the newew approach, remove ``PV = ""`` from ``lmp-boot-firmware.bbappend``, and define ``LMP_BOOT_FIRMWARE_VERSION`` with the appropriate version value as shown above in the example. .. seealso:: * :ref:`ref-secure-boot-imx-habv4`