         +=======================================================+
         +     i.MX8M, i.MX8MM Secure Boot guide using HABv4     +
         +=======================================================+

1. HABv4 secure boot process
-----------------------------

This document describes a step-by-step procedure on how to sign and securely
boot a bootloader image on i.MX8M and i.MX8MM devices. It is assumed that
the reader is familiar with basic HAB concepts and with the PKI tree generation.

Details about HAB can be found in the application note AN4581[1] and in the
introduction_habv4.txt document.

1.1 Understanding the i.MX8M and i.MX8MM flash.bin image layout
----------------------------------------------------------------

Due to the new the architecture, multiple firmwares and softwares are required
to boot i.MX8M and i.MX8MM devices. In order to store all the images in a
single binary the FIT (Flattened Image Tree) image structure is used.

The final image is generated by the imx-mkimage project, the tool combines all
the input images in a FIT structure, generating a flash.bin image with an
appropriate IVT set.

For a secure boot process users should ensure all images included in flash.bin
file are covered by a digital signature.

- The diagram below illustrate a signed flash.bin image layout:

                     +-----------------------------+
                     |                             |
                     |     *Signed HDMI/DP FW      |
                     |                             |
                     +-----------------------------+
                     |           Padding           |
             ------- +-----------------------------+ --------
                 ^   |          IVT - SPL          |   ^
          Signed |   +-----------------------------+   |
           Data  |   |        u-boot-spl.bin       |   |
                 |   |              +              |   |  SPL
                 v   |           DDR FW            |   | Image
             ------- +-----------------------------+   |
                     |      CSF - SPL + DDR FW     |   v
                     +-----------------------------+ --------
                     |           Padding           |
             ------- +-----------------------------+ --------
          Signed ^   |          FDT - FIT          |   ^
           Data  |   +-----------------------------+   |
                 v   |          IVT - FIT          |   |
             ------- +-----------------------------+   |
                     |          CSF - FIT          |   |
             ------- +-----------------------------+   |
                 ^   |       u-boot-nodtb.bin      |   |  FIT
                 |   |               +             |   | Image
                 |   |          u-boot.bin         |   |
          Signed |   +-----------------------------+   |
           Data  |   |       OP-TEE (Optional)     |   |
                 |   +-----------------------------+   |
                 |   |        bl31.bin (ATF)       |   |
                 |   +-----------------------------+   |
                 v   |          u-boot.dtb         |   v
             ------- +-----------------------------+ --------
  * Only supported on i.MX8M series

The boot flow on i.MX8M and i.MX8MM devices are slightly different when compared
with i.MX6 and i.MX7 series, the diagram below illustrate the boot sequence
overview:

- i.MX8M and i.MX8MM devices boot flow:

                  Secure World                     Non-Secure World
                                         |
                                         |
  +------------+      +------------+     |
  |     SPL    |      | i.MX 8M/MM |     |
  |      +     | ---> |    ROM     |     |
  |   DDR FW   |      |   + HAB    |     |
  +------------+      +------------+     |
                             |           |
                             v           |
                      +------------+     |
                      |  *Signed   |     |
                      | HDMI/DP FW |     |
                      +------------+     |
                             |           |
                             v           |
  +------------+      +------------+     |
  | FIT Image: |      |     SPL    |     |
  | ATF + TEE  | ---> |      +     |     |
  |  + U-Boot  |      |   DDR FW   |     |      +-----------+
  +------------+      +------------+     |      |   Linux   |
                             |           |      +-----------+
                             v           |            ^
                      +------------+     |            |             +-------+
                      |    ARM     |     |      +-----------+       | Linux |
                      |  Trusted   | ----+--->  |   U-Boot  |  <--- |   +   |
                      |  Firmware  |     |      +-----------+       |  DTB  |
                      +------------+     |                          +-------+
                             |           |
                             v           |
                       +----------+      |
                       | **OP-TEE |      |
                       +----------+      |
  * Only supported on i.MX8M series
  ** Optional

On i.MX8M devices the HDMI firmware or DisplayPort firmware are the first image
to boot on the device. These firmwares are signed and distributed by NXP, and
are always authenticated regardless of security configuration. In case not
required by the application the HDMI or DisplayPort controllers can be disabled
by eFuses and the firmwares are not required anymore.

The next images are not signed by NXP and users should follow the signing
procedure as described in this document.

The Second Program Loader (SPL) and DDR firmware are loaded and authenticated
by the ROM code, these images are executed in the internal RAM and responsible
for initializing essential features such as DDR, UART, PMIC and clock
enablement.

Once the DDR is available, the SPL code loads all the images included in the
FIT structure to their specific execution addresses, the HAB APIs are called
to extend the root of trust, authenticating the U-Boot, ARM trusted firmware
(ATF) and OP-TEE (If included).

The root of trust can be extended again at U-Boot level to authenticate Kernel
and M4 images.

1.2 Enabling the secure boot support in U-Boot
-----------------------------------------------

The first step is to generate an U-Boot image supporting the HAB features,
similar to i.MX6 and i.MX7 series the U-Boot provides extra functions for
HAB, such as the HAB status logs retrievement through the hab_status command
and support to extend the root of trust.

The support is enabled by adding the CONFIG_SECURE_BOOT to the build
configuration:

- Defconfig:

  CONFIG_SECURE_BOOT=y

- Kconfig:

  ARM architecture -> Support i.MX HAB features

1.3 Preparing the fit image
----------------------------

The imx-mkimage project is used to combines all the images in a single
flash.bin binary, the following files are required:

- U-Boot:
  u-boot.bin
  u-boot-nodtb.bin
  u-boot-spl.bin
  U-Boot DTB file (e.g. fsl-imx8mq-evk.dtb)

- ATF image:
  bl31.bin

- DDR firmware:
  lpddr4_pmu_train_1d_dmem.bin
  lpddr4_pmu_train_1d_imem.bin
  lpddr4_pmu_train_2d_dmem.bin
  lpddr4_pmu_train_2d_imem.bin

- HDMI firmware (Only in i.MX8M):
  signed_hdmi_imx8m.bin

- DisplayPort firmware (Only in i.MX8M):
  signed_dp_imx8m.bin

- OP-TEE (Optional):
  tee.bin

The procedure to build ATF and download the firmwares are out of the scope
of this document, please refer to the Linux BSP Release Notes and AN12212[2]
for further details.

Copy all files to iMX8M directory and run the following command according to
the target device, on this example we are building a HDMI target and also
including the OP-TEE binary:

- Assembly flash.bin binary:

  $ make SOC=<SoC Name> flash_hdmi_spl_uboot

The mkimage log can be used to calculate the authenticate image command
parameters and CSF offsets:

- imx-mkimage build log:

  Loader IMAGE:
   header_image_off 	0x1a000
   dcd_off 		0x0
   image_off 		0x1a040
   csf_off 		0x44600
   spl hab block: 	0x7e0fd0 0x1a000 0x2e600

  Second Loader IMAGE:
   sld_header_off 	0x57c00
   sld_csf_off 		0x58c20
   sld hab block: 	0x401fcdc0 0x57c00 0x1020

Additional HAB information is provided by running the following command:

- Printing HAB FIT information:

  $ make SOC=<SoC Name> print_fit_hab

  TEE_LOAD_ADDR=0xfe000000 ATF_LOAD_ADDR=0x00910000 ./print_fit_hab.sh \
  0x60000 fsl-imx8mq-evk.dtb
  0x40200000 0x5AC00 0x9AAC8
  0x910000 0xF56C8 0x9139
  0xFE000000 0xFE804 0x4D268
  0x4029AAC8 0x14BA6C 0x6DCF

1.4 Creating the CSF description file
--------------------------------------

The CSF contains all the commands that the ROM executes during the secure
boot. These commands instruct the HAB code on which memory areas of the image
to authenticate, which keys to install, use and etc.

CSF examples are available under doc/imx/hab/habv4/csf_examples/ directory.

As explained in sections above the SPL is first authenticated by the ROM code
and the root of trust is extended to the FIT image, hence two CSF files are
necessary to completely sign an flash.bin image.

The build log provided by imx-mkimage can be used to define the "Authenticate
Data" parameter in CSF.

- SPL "Authenticate Data" addresses in flash.bin build log:

  spl hab block: 0x7e0fd0 0x1a000 0x2e600

- "Authenticate Data" command in csf_spl.txt file:

  Blocks = 0x7e0fd0 0x1a000 0x2e600 "flash.bin"

- FIT image "Authenticate Data" addresses in flash.bin build log:

  sld hab block: 0x401fcdc0 0x57c00 0x1020

- FIT image "Authenticate Data" addresses in print_fit_hab build log:

  0x40200000 0x5AC00 0x9AAC8
  0x910000 0xF56C8 0x9139
  0xFE000000 0xFE804 0x4D268
  0x4029AAC8 0x14BA6C 0x6DCF

- "Authenticate Data" command in csf_fit.txt file:

  Blocks = 0x401fcdc0 0x057c00 0x01020 "flash.bin", \
           0x40200000 0x05AC00 0x9AAC8 "flash.bin", \
           0x00910000 0x0F56C8 0x09139 "flash.bin", \
           0xFE000000 0x0FE804 0x4D268 "flash.bin", \
           0x4029AAC8 0x14BA6C 0x06DCF "flash.bin"

1.4.1 Avoiding Kernel crash in closed devices
----------------------------------------------

For devices prior to HAB v4.4.0, the HAB code locks the Job Ring and DECO
master ID registers in closed configuration. In case the user specific
application requires any changes in CAAM MID registers it's necessary to
add the "Unlock CAAM MID" command in CSF file.

The current NXP BSP implementation expects the CAAM registers to be unlocked
when configuring CAAM to operate in non-secure TrustZone world.

The Unlock command is already included by default in the signed HDMI and
DisplayPort firmwares, on i.MX8MM devices or in case the HDMI or DisplayPort
controllers are disabled, users must ensure this command is included in SPL CSF.

- Add Unlock MID command in csf_spl.txt:

  [Unlock]
      Engine = CAAM
      Features = MID

1.5 Signing the flash.bin binary
---------------------------------

The CST tool is used for singing the flash.bin image and generating the CSF
binary. Users should input the CSF description file created in the step above
and receive a CSF binary, which contains the CSF commands, SRK table,
signatures and certificates.

- Create SPL CSF binary file:

 $ ./cst -i csf_spl.txt -o csf_spl.bin

- Create FIT CSF binary file:

 $ ./cst -i csf_fit.txt -o csf_fit.bin

1.6 Assembling the CSF in flash.bin binary
-------------------------------------------

The CSF binaries generated in the step above have to be inserted into the
flash.bin image.

The CSF offsets can be obtained from the flash.bin build log:

- SPL CSF offset:

  csf_off 0x44600

- FIT CSF offset:

  sld_csf_off 0x58c20

The signed flash.bin image can be then assembled:

- Create a flash.bin copy:

  $ cp flash.bin signed_flash.bin

- Insert csf_spl.bin in signed_flash.bin at 0x44600 offset:

  $ dd if=csf_spl.bin of=signed_flash.bin seek=$((0x44600)) bs=1 conv=notrunc

- Insert csf_fit.bin in signed_flash.bin at 0x58c20 offset:

  $ dd if=csf_fit.bin of=signed_flash.bin seek=$((0x58c20)) bs=1 conv=notrunc

- Flash signed flash.bin image:

  $ sudo dd if=signed_flash.bin of=/dev/sd<x> bs=1K seek=33 && sync

1.7 Programming SRK Hash
-------------------------

As explained in AN4581[1] and in introduction_habv4.txt document the SRK Hash
fuse values are generated by the srktool and should be programmed in the
SoC SRK_HASH[255:0] fuses.

Be careful when programming these values, as this data is the basis for the
root of trust. An error in SRK Hash results in a part that does not boot.

The U-Boot fuse tool can be used for programming eFuses on i.MX SoCs.

- Dump SRK Hash fuses values in host machine:

  $ hexdump -e '/4 "0x"' -e '/4 "%X""\n"' SRK_1_2_3_4_fuse.bin
  0x20593752
  0x6ACE6962
  0x26E0D06C
  0xFC600661
  0x1240E88F
  0x1209F144
  0x831C8117
  0x1190FD4D

- Program SRK_HASH[255:0] fuses on i.MX8MQ and i.MX8MM devices:

  => fuse prog 6 0 0x20593752
  => fuse prog 6 1 0x6ACE6962
  => fuse prog 6 2 0x26E0D06C
  => fuse prog 6 3 0xFC600661
  => fuse prog 7 0 0x1240E88F
  => fuse prog 7 1 0x1209F144
  => fuse prog 7 2 0x831C8117
  => fuse prog 7 3 0x1190FD4D


1.8 Verifying HAB events
-------------------------

The next step is to verify that the signatures included in flash.bin image is
successfully processed without errors. HAB generates events when processing
the commands if it encounters issues.

The hab_status U-Boot command call the hab_report_event() and hab_status()
HAB API functions to verify the processor security configuration and status.
This command displays any events that were generated during the process.

Prior to closing the device users should ensure no HAB events were found, as
the example below:

- Verify HAB events:

  => hab_status

  Secure boot disabled

  HAB Configuration: 0xf0, HAB State: 0x66

1.9 Closing the device
-----------------------

After the device successfully boots a signed image without generating any HAB
events, it is safe to close the device. This is the last step in the HAB
process, and is achieved by programming the SEC_CONFIG[1] fuse bit.

Once the fuse is programmed, the chip does not load an image that has not been
signed using the correct PKI tree.

- Program SEC_CONFIG[1] fuse on i.MX8MQ and i.MX8MM devices:

  => fuse prog 1 3 0x2000000

1.10 Completely secure the device
----------------------------------

Additional fuses can be programmed for completely secure the device, more
details about these fuses and their possible impact can be found at AN4581[1].

- Program SRK_LOCK:

  => fuse prog 0 0 0x200

- Program DIR_BT_DIS:

  => fuse prog 1 3 0x8000000

- Program SJC_DISABLE:

  => fuse prog 1 3 0x200000

- JTAG_SMODE:

  => fuse prog 1 3 0xC00000

2. Authenticating additional boot images
-----------------------------------------

The High Assurance Boot (HAB) code located in the on-chip ROM provides an
Application Programming Interface (API) making it possible to call back
into the HAB code for authenticating additional boot images.

The U-Boot is running in non-secure TrustZone world and to make use of this
feature it's necessary to use a SIP call to the ATF, this is already
implemented in hab.c code and it's transparent to the user.

The process of signing an additional image is similar as in i.MX6 and i.MX7
series devices, the steps below are using the Linux Kernel image as example.

The diagram below illustrate the Image layout:

            ------- +-----------------------------+ <-- *load_address
                ^   |                             |
                |   |                             |
                |   |                             |
                |   |                             |
                |   |            Image            |
         Signed |   |                             |
          Data  |   |                             |
                |   |                             |
                |   +-----------------------------+
                |   |    Padding to Image size    |
                |   |          in header          |
                |   +-----------------------------+ <-- *ivt
                v   |     Image Vector Table      |
            ------- +-----------------------------+ <-- *csf
                    |                             |
                    | Command Sequence File (CSF) |
                    |                             |
                    +-----------------------------+
                    |     Padding (optional)      |
                    +-----------------------------+

2.1 Padding the image
----------------------

The Image must be padded to the size specified in the Image header, this can be
achieved by using the od command.

- Read Image size:

  $ od -x -j 0x10 -N 0x4 --endian=little Image
  0000020 5000 0145
  0000024

The tool objcopy can be used for padding the image.

- Pad the Image:

  $ objcopy -I binary -O binary --pad-to 0x1455000 --gap-fill=0x00 \
	Image Image_pad.bin

2.2 Generating Image Vector Table
----------------------------------

The HAB code requires an Image Vector Table (IVT) for determining the image
length and the CSF location. Since Image does not include an IVT this has
to be manually created and appended to the end of the padded Image, the
script genIVT.pl in script_examples directory can be used as reference.

- Generate IVT:

  $ genIVT.pl

Note: The load Address may change depending on the device.

- Append the ivt.bin at the end of the padded Image:

  $ cat Image_pad.bin ivt.bin > Image_pad_ivt.bin

2.3 Signing the image
----------------------

A CSF file has to be created to sign the image. HAB does not allow to change
the SRK once the first image is authenticated, so the same SRK key used in
the initial image must be used when extending the root of trust.

CSF examples are available in ../csf_examples/additional_images/ directory.

- Create CSF binary file:

  $ ./cst --i csf_additional_images.txt --o csf_Image.bin

- Attach the CSF binary to the end of the image:

  $ cat Image_pad_ivt.bin csf_Image.bin > Image_signed.bin

2.4 Verifying HAB events
-------------------------

The U-Boot includes the hab_auth_img command which can be used for
authenticating and troubleshooting the signed image, the Image must be
loaded at the load address specified in the IVT.

- Authenticate additional image:

  => hab_auth_img <Load Address> <Image Size> <IVT Offset>

If no HAB events were found the Image is successfully signed.

References:
[1] AN4581: "Secure Boot on i.MX 50, i.MX 53, i.MX 6 and i.MX 7 Series using
 HABv4" - Rev 2.
[2] AN12212: "Software Solutions for Migration Guide from Aarch32 to
Aarch64" - Rev 0.
