i.MX 95 signed AHAB with U-BOOT#

This notebook describes how to build a bootable signed AHAB image with ELE firmware and U-BOOT bootloader.

1. Prerequisites#

  • SPSDK is needed with examples extension. pip install spsdk[examples] (Please refer to the installation documentation.)

  • This demo was tested with i.MX 95 EVK board with LPDDR5 memory and A1 chip revision.

1.1 Images preparation#

  • To create resulting binary containing AHAB containers, we need to prepare the binaries

  • In this section we reproduce the process which is done by the imx-mkimage tool

  • Obtain all the necessary binaries and put them into inputs directory

1.2 U-Boot#

In order to use the nxpele app, U-Boot must be built with AHAB support. CONFIG_AHAB_BOOT=y If you want to use the nxpele over fastboot, also multiplexing of console output to fastboot must be enabled by setting CONFIG_CONSOLE_MUX=y.

1.3 Requirements#

Download these files from the https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/<package name> and put them into the inputs directory.

Primary image container set:

  • ELE firmware

  • LPDDR5 or LPDDR5 firmware files with OEI firmware

  • CM33 OEI TCM

  • CM33 System manager image

  • U-Boot SPL

  • [Optional] M7 application image

  • Four ECC keys (In this example we use ECC384). Might be created with nxpcrypto tool.

Secondary image container set

  • bl31.bin binary (ARM Trusted Firmware)

  • U-Boot (built with AHAB support)

  • TEE binary

  • Four ECC keys (Same as in the primary container).

2. AHAB Image#

2.1 AHAB Template#

We can generate the template using the nxpimage ahab get-template command. The command will generate a template. The template is a YAML file that contains the AHAB header and the AHAB container. The AHAB header contains the information about the image, such as the version, the number of containers, and the signature. The AHAB container contains the information about the image, such as the image type, the image version, the image size, and the image signature.

The following command generates the template:

nxpimage ahab get-template -f mimx9596 -o ahab_template.yaml

2.2 Exporting of the AHAB image#

The AHAB image can be exported using the nxpimage ahab export command. The command will create the AHAB image from the template. The following command creates the AHAB image:

nxpimage ahab export -c ahab_template.yaml 

2.4 Primary image container set#

Primary image container set consists of the following images:

  • ELE firmware

  • DDR firmware with OEI

  • System manager

  • U-Boot SPL

  • [Optional] M7 application image

nxpimage ahab get-template -r a1 -f mimx9596 -o workspace/ahab_template.yaml --force 
Creating workspace/ahab_template.yaml template file.

Configuration Differences

2.5 Secondary image container set#

Secondary image container set consists of the following images:

  • bl31.bin binary (ARM Trusted Firmware)

  • U-Boot (built with AHAB support)

  • TEE binary

YamlDiffWidget("inputs/mx95_signed_ahab_secondary.diffc").html
nxpimage ahab get-template -r a1 -f mimx9596 -o workspace/ahab_template.yaml --force 
Creating workspace/ahab_template.yaml template file.

Configuration Differences

2.6 Exporting of full AHAB image (container set)#

U-Boot image consist from two image container sets. The first one contains ELE firmware, DDR firmware with OEI, system manager and U-Boot SPL. This image is loaded using the SDPS protocol. Once the U-Boot SPL is loaded to OCRAM the fastboot is opened and the second container is loaded using the fastboot protocol.

If the image is intended for loading using the UUU, the memory type should be set to serial_downloader. However the type of each individual AHAB should be set to standard, because it will be stored in flash memory.

nxpimage -v bootable-image merge -c u-boot-flash_template.yaml -o flash.bin
YamlDiffWidget("inputs/mx95_signed_ahab_bimg.diffc").html
nxpimage bootable-image get-templates -f mimx9596 -o workspace --force 
Creating workspace/bootimg_mimx9596_serial_downloader.yaml template file.
Creating workspace/bootimg_mimx9596_flexspi_nor.yaml template file.
Creating workspace/bootimg_mimx9596_emmc.yaml template file.
Creating workspace/bootimg_mimx9596_sd.yaml template file.
Creating workspace/bootimg_mimx9596_recovery_spi.yaml template file.

Configuration Differences

U_BOOT_PRIMARY = "inputs/mx95_signed_uboot_primary.yaml"
U_BOOT_SECONDARY = "inputs/mx95_signed_uboot_secondary.yaml"
U_BOOT_FLASH_BOOT_CFG = "inputs/bootimg_signed_mx95_serial_downloader.yaml"
U_BOOT_FLASH_BOOT = "outputs/flash.bin"

VERBOSITY = "-v"
# EXPORT PRIMARY AHAB IMAGE
%! nxpimage $VERBOSITY ahab export --config $U_BOOT_PRIMARY
nxpimage -v ahab export --config inputs/mx95_signed_uboot_primary.yaml 
INFO:spsdk.apps.nxpimage:Created AHAB Image:
Name:      AHAB Image
Starts:    0x0
Ends:      0xe2fff
Size:      Size: 908.0 kiB; 929,792 B
Alignment: 512 B
Execution Start Address: Not defined
Pattern:zeros
AHAB Image for mimx9596_a1

INFO:spsdk.apps.nxpimage:Created AHAB Image memory map:

+==0x0000_0000= AHAB Image ==========================+
|             Size: 908.0 kiB; 929,792 B             |
|             AHAB Image for mimx9596_a1             |
|                   Pattern: zeros                   |
|+==0x0000_0000= AHAB Containers ===================+|
||              Size: 8.0 kiB; 8,192 B              ||
||              AHAB Containers block               ||
||                  Pattern: zeros                  ||
||+==0x0000_0000= AHAB Container 0 ================+||
|||                  Size: 544 B                   |||
|||         AHAB Container for nxp_SWver:0         |||
||+==0x0000_021f===================================+||
||                    Gap: 480 B                    ||
||+==0x0000_0400= AHAB Container 1 ================+||
|||                  Size: 832 B                   |||
|||         AHAB Container for oem_SWver:0         |||
||+==0x0000_073f===================================+||
||                    Gap: 192 B                    ||
||+==0x0000_0800= AHAB Container 2 ================+||
|||             Size: 1.3 kiB; 1,344 B             |||
|||         AHAB Container for oem_SWver:0         |||
||+==0x0000_0d3f===================================+||
|+==0x0000_1fff=====================================+|
|+==0x0000_2000= Container 0 AHAB Data Image 0 =====+|
||            Size: 104.6 kiB; 107,072 B            ||
||  AHAB encrypted data block for ele core and ele  ||
||                   Image Type.                    ||
|+==0x0001_c23f=====================================+|
|                   Gap: 15.4 kiB                    |
|+==0x0002_0000= Container 1 AHAB Data Image 0 =====+|
||             Size: 56.0 kiB; 57,344 B             ||
||  AHAB data block for v2x-1 core and v2x_primary  ||
||                   Image Type.                    ||
|+==0x0002_dfff=====================================+|
|+==0x0002_e000= Container 1 AHAB Data Image 1 =====+|
||             Size: 28.0 kiB; 28,672 B             ||
|| AHAB data block for v2x-2 core and v2x_secondary ||
||                   Image Type.                    ||
|+==0x0003_4fff=====================================+|
|+==0x0003_5000= OEI DDR ===========================+|
||            Size: 315.0 kiB; 322,560 B            ||
||AHAB data block for cortex-m33 core and oei Image ||
||                      Type.                       ||
|+==0x0008_3bff=====================================+|
|                   Gap: 64.0 kiB                    |
|+==0x0009_3c00= OEI TCM ===========================+|
||              Size: 5.0 kiB; 5,120 B              ||
||AHAB data block for cortex-m33 core and oei Image ||
||                      Type.                       ||
|+==0x0009_4fff=====================================+|
|+==0x0009_5000= System manager ====================+|
||            Size: 151.0 kiB; 154,624 B            ||
||AHAB data block for cortex-m33 core and executable||
||                   Image Type.                    ||
|+==0x000b_abff=====================================+|
|+==0x000b_ac00= Additional Cortex M7 application ==+|
||             Size: 15.0 kiB; 15,360 B             ||
||     AHAB data block for cortex-m7-1 core and     ||
||              executable Image Type.              ||
|+==0x000b_e7ff=====================================+|
|+==0x000b_e800= U-Boot SPL ========================+|
||            Size: 146.0 kiB; 149,504 B            ||
||AHAB data block for cortex-a55 core and executable||
||                   Image Type.                    ||
|+==0x000e_2fff=====================================+|
|+==0x000e_3000= V2X core Dummy record =============+|
||                    Size: 0 B                     ||
||AHAB data block for cortex-m33 core and v2x_dummy ||
||                   Image Type.                    ||
|+==0x000e_2fff=====================================+|
+==0x000e_2fff=======================================+

Success. (AHAB: outputs/primary_signed_ahab.bin created.)
Generated file containing SRK hash: outputs/primary_signed_ahab_oem2_srk0_hash.txt
INFO:spsdk.image.ahab.utils:
Fuses info:

 --== Grouped register name: SRKH ==-- 
OTP ID: 128, Value: 0xc0b2eb69
OTP ID: 129, Value: 0xb1801c9f
OTP ID: 130, Value: 0x97c6d49f
OTP ID: 131, Value: 0xb2580b27
OTP ID: 132, Value: 0x8703c1a4
OTP ID: 133, Value: 0xdf20e0ea
OTP ID: 134, Value: 0xdc7f62d9
OTP ID: 135, Value: 0xea117f8e

Generated script for writing fuses for container 2: outputs/primary_signed_ahab_oem2_srk0_hash_nxpele.bcf
# EXPORT SECONDARY AHAB IMAGE
%! nxpimage $VERBOSITY ahab export --config $U_BOOT_SECONDARY
nxpimage -v ahab export --config inputs/mx95_signed_uboot_secondary.yaml 
INFO:spsdk.apps.nxpimage:Created AHAB Image:
Name:      AHAB Image
Starts:    0x0
Ends:      0x196fff
Size:      Size: 1.6 MiB; 1,667,072 B
Alignment: 512 B
Execution Start Address: Not defined
Pattern:zeros
AHAB Image for mimx9596_a1

INFO:spsdk.apps.nxpimage:Created AHAB Image memory map:

+==0x0000_0000= AHAB Image ====================================+
|                  Size: 1.6 MiB; 1,667,072 B                  |
|                  AHAB Image for mimx9596_a1                  |
|                        Pattern: zeros                        |
|+==0x0000_0000= AHAB Containers =============================+|
||                   Size: 8.0 kiB; 8,192 B                   ||
||                   AHAB Containers block                    ||
||                       Pattern: zeros                       ||
||+==0x0000_0000= AHAB Container 0 ==========================+||
|||                       Size: 960 B                        |||
|||              AHAB Container for oem_SWver:0              |||
||+==0x0000_03bf=============================================+||
|+==0x0000_1fff===============================================+|
|+==0x0000_2000= ATF - ARM Trusted Firmware ==================+|
||                  Size: 38.0 kiB; 38,912 B                  ||
||  AHAB data block for cortex-a55 core and executable Image  ||
||                           Type.                            ||
|+==0x0000_b7ff===============================================+|
|+==0x0000_b800= U-Boot Firmware =============================+|
||                 Size: 1.0 MiB; 1,091,584 B                 ||
||  AHAB data block for cortex-a55 core and executable Image  ||
||                           Type.                            ||
|+==0x0011_5fff===============================================+|
|+==0x0011_6000= U-Boot TEE - Trusted Execution Environment ==+|
||                 Size: 516.0 kiB; 528,384 B                 ||
||  AHAB data block for cortex-a55 core and executable Image  ||
||                           Type.                            ||
|+==0x0019_6fff===============================================+|
+==0x0019_6fff=================================================+

Success. (AHAB: outputs/secondary_signed_ahab.bin created.)
Generated file containing SRK hash: outputs/secondary_signed_ahab_oem0_srk0_hash.txt
INFO:spsdk.image.ahab.utils:
Fuses info:

 --== Grouped register name: SRKH ==-- 
OTP ID: 128, Value: 0xc0b2eb69
OTP ID: 129, Value: 0xb1801c9f
OTP ID: 130, Value: 0x97c6d49f
OTP ID: 131, Value: 0xb2580b27
OTP ID: 132, Value: 0x8703c1a4
OTP ID: 133, Value: 0xdf20e0ea
OTP ID: 134, Value: 0xdc7f62d9
OTP ID: 135, Value: 0xea117f8e

Generated script for writing fuses for container 0: outputs/secondary_signed_ahab_oem0_srk0_hash_nxpele.bcf
# EXPORT U-BOOT IMAGE
%! nxpimage $VERBOSITY bootable-image merge --config $U_BOOT_FLASH_BOOT_CFG --output $U_BOOT_FLASH_BOOT
nxpimage -v bootable-image merge --config inputs/bootimg_signed_mx95_serial_downloader.yaml --output outputs/flash.bin 
INFO:spsdk.apps.nxpimage:Created Bootable Image:
Name:      Bootable Image for mimx9596
Starts:    0x0
Ends:      0x279fff
Size:      Size: 2.5 MiB; 2,596,864 B
Alignment: 1 B
Execution Start Address: Not defined
Pattern:zeros
Memory type: MemoryType.SERIAL_DOWNLOADER
Revision: a1

INFO:spsdk.apps.nxpimage:Created Bootable Image memory map:

+==0x0000_0000= Bootable Image for mimx9596 ======+
|           Size: 2.5 MiB; 2,596,864 B            |
|    Memory type: MemoryType.SERIAL_DOWNLOADER    |
|                  Revision: a1                   |
|                 Pattern: zeros                  |
|+==0x0000_0000= primary_image_container_set ====+|
||          Size: 908.0 kiB; 929,792 B           ||
|+==0x000e_2fff==================================+|
|+==0x000e_3000= secondary_image_container_set ==+|
||          Size: 1.6 MiB; 1,667,072 B           ||
|+==0x0027_9fff==================================+|
+==0x0027_9fff====================================+

Success. (Bootable Image: outputs/flash.bin created) 

3 Download image#

3.1 Download AHAB image#

Set the boot mode to Cortex-M Serial Downloader (1001 on EVK boot switch) and download the files using the UUU tool

%! nxpuuu $VERBOSITY write -f mimx9596 -b emmc $U_BOOT_FLASH_BOOT
nxpuuu -v write -f mimx9596 -b emmc outputs/flash.bin 
SDPS: boot -f outputs/flash.bin


SDPV: write -f outputs/flash.bin -skipspl


SDPV: jump


Done

4. Write fuses#

We need to write SRKH (Super root key hash) to fuses. This might be done using the nxpele tool. When the signed AHAB Image is exported, the “.bcf” script is generated.

The script might look like this:

# nxpele AHAB SRK fuses programming script
# Generated by SPSDK 2.6.0.dev45+gbb9e767b
# Family: mimx9596 Revision: a1

# Value: 0x69ebb2c09f1c80b19fd4c697270b58b2a4c10387eae020dfd9627fdc8e7f11ea
# Description: SHA256 hash digest of hash of four SRK keys
# Grouped register name: SRKH

# OTP ID: 128, Value: 0xc0b2eb69
write-fuse --index 128 --data 0xC0B2EB69
# OTP ID: 129, Value: 0xb1801c9f
write-fuse --index 129 --data 0xB1801C9F
# OTP ID: 130, Value: 0x97c6d49f
write-fuse --index 130 --data 0x97C6D49F
# OTP ID: 131, Value: 0xb2580b27
write-fuse --index 131 --data 0xB2580B27
# OTP ID: 132, Value: 0x8703c1a4
write-fuse --index 132 --data 0x8703C1A4
# OTP ID: 133, Value: 0xdf20e0ea
write-fuse --index 133 --data 0xDF20E0EA
# OTP ID: 134, Value: 0xdc7f62d9
write-fuse --index 134 --data 0xDC7F62D9
# OTP ID: 135, Value: 0xea117f8e
write-fuse --index 135 --data 0xEA117F8E

The script might be executed using nxpele batch command:

nxpele -f mimx9596 batch ./outputs/primary_signed_ahab_oem2_srk0_hash_nxpele.bcf

5. Boot and test#

Now change the boot mode to Cortex-M eMMC (1010 on EVK boot switch) and reset the board. Find the serial port that belongs to U-Boot console and interrupt the boot. When the console is switched to U-Boot menu, we can use the nxpele tool to communicate with the ELE.

%! nxpele -f mimx9596 -p COM138 -d uboot_serial get-info
nxpele -f mimx9596 -p COM138 -d uboot_serial get-info 
ELE get info ends successfully:
Command:          0xda
Version:          2
Length:           160
SoC ID:           MX95 - 0x9500
SoC version:      A100
Life Cycle:       OEM_CLSD - 0x0040
SSSM state:       4
UUID:             8225b4b22ee24782b66bce6f05c08d1f
SHA256 ROM PATCH: 2063bc6261856eb33e2962120641cd099a83c80393fa6a31d66b36960dcaf727
SHA256 FW:        36d658981d5cb8ec5bea4bd57b5a4231ccf8b95489efc965d383b1ca844e6135
Advanced information:
  OEM SRKH:       69ebb2c09f1c80b19fd4c697270b58b2a4c10387eae020dfd9627fdc8e7f11ea
  IMEM state:     This is non-existing tag(0x0) from enum: EleImemState - 0x00
  CSAL state:     EdgeLock secure enclave random context initialization succeed - 0x02
  TRNG state:     TRNG entropy is valid and ready to be read - 0x03
  OEM PQC SRKH:  00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000