OPTEE Support on IMX7D

Intro

Hello Alex,

Some time has passed and I tried to add the board manually myself. I did so according to this Porting Guide from nxp as I found no porting guide from toradex.

Expected behavior

automatic boot

When booting the colibri-imx7d-emmc-eval-v3 som on board i expect it to boot first into optee which starts linux (rich os). When I type xtest in the shell I get correct test-Results for the Trustzone.

manual boot

When I boot uTee manually with following script in uBoot I expect it to boot into Optee-OS and then jump to the linux os.

fatload mmc 0:1 ${ramdisk_addr_r} uTee-;
fatload mmc 0:1 ${fdt_addr_r} imx7d-colibri-emmc-eval-v3.dtb;
fatload mmc 0:1 ${kernel_addr_r} zImage;
bootm ${ramdisk_addr_r} - ${fdt_addr_r};

Actual behavior

automatic boot

Xtest failes with error TEEC_InitializeContext failed with code 0xffff0008

manual boot

When I try to boot manualy with mentioned script in u-boot I the System freezes at Loading Kernel

Reproduction

On page 18 of the porting guide stands the predetermined porting route. It is divided into two Tasks:

  1. configuring u-boot
  2. configuring optee-os

U-Boot conf

Configuring Device Configuration Data (DCD)

  • Configuring the DCD is needed because the board does bypass the TZASC Registers by default. One should that by “setting bits” in the IOMUXC_GPR9/10. But it does not say which bits to set what value to, nor does it state the adress of the gpr9/10. I tried to orient myself on the other GPRs which are already present in the dcd (gpr1 and gpr8) but I could not find the right values.
  • the path to the dcd is board/toradex/colibri_imx7/imximage.cfg
  • It is instructed to add the following code there:
#ifdef CONFIG_IMX_OPTEE
DATA 4 <register addr> <value>
CHECK_BITS_SET 4 <register addr> <value>
#endif

Configuring the u-boot-environment

  • Configuring the U-Boot-Env is necessary to get the following option on boot: tee=y
  • This is done by editing board/toradex/colibri_imx7/colibri_imx7.c
  • This Code has to be added:
env_set("tee", "no");
#ifdef CONFIG_IMX_OPTEE
env_set("tee", "yes");
#endif

Later I found out that the option in the 2.nd line is wrong. It has to be CONFIG_OPTEE not CONFIG_IMG_OPTEE to get the option into the environment.

OPTEE-OS conf

adding a poard function identifier

  • adding a board funciton identifier is needed fot optee-os to run. one has to add a function with following signature in this file core/arch/arm/plat-imx/imx-common.c:
bool soc_is_<soc>(void)

it has to return if the soc type is in a list of defined soc-types. for me one was already there. so i skipped that.

adding in the header

One has to add a config.h in the following folder:
core/arch/arm/plat-imx/config/ to specify constants for the soc. After that this config has to be added to core/arch/arm/plat-imx/platform_config.h

In neither one of these folders was there a file for the imx7, but I figured if it was already supported by optee-os. After all I just wanted to add a config for the imx7d, not imx7 in general because this was already supported. So to speak the platform-flavor, not the platform.

registers

One has to eventually add board-specific registers in core/arch/arm/plat-imx/registers/. Also skipped because of the same reasons as in header adding.

conf.mk

This one was bit more. In core/arch/arm/plat-imx/conf.mk the platform flavor has to be added. I named it mx7dcolibri and later mentionied this flavor in my local.conf in bitbake.

I added a filter with the following options:

ifneq (,$(filter $(PLATFORM_FLAVOR),mx7dcolibri))
CFG_DDR_SIZE ?= 0x40000000
CFG_NS_ENTRY_ADDR ?= 0x84200000
CFG_DT_ADDR ?= 0x88200000
endif
  • CFG_DDR_SIZE is 1 GB because imx7d-emmc has 1GB of RAM
  • CFG_NS_ENTRY_ADDR is 0x84200000 because that’s the kernel_addr_r. As far as I understood this is the adress optee jumps to, after running on startup asuming NS == Next Stage.
  • CFG_DT_ADDR ?= 0x88200000 is the Device Tree Adress.

I got all these adresses from the u-boot-config and from the inital-env file of the image.

tzasc.c

  • In core/arch/arm/plat-imx/tzasc.c a secure memory mapping has to be added. But the file was not present so I skipped it.

Additional Configs

  • These configs were not stated in the porting Guide

optee-os

link.mk

  • core/arch/arm/plat-imx/link.mk defines how the uTee Image is built. It is built with mkimage using the same address as the load- and entry-addr:
mkimage -A arm -O linux -C none -a $$ADDR -e $$ADDR -d $< $@

this has to be wrong. In the optee-manual it is defined that the entry-adress is 28 Bytes after the load-adress because of the headersize.

I tried changing it to an arbitrary adress like the ramdisk_addr (loadaddress: 0x88400000, entry: 0x8840001C), which would have fitted to the optee-size for booting. But that did not work.

I’ve read multiple times, that according to optee and it’s configuration the last 32M of the RAM a reserved for optee so I changed it to 0xbd000000 for load and 0xbd00001C for entry but it did not boot.

Even with the same mentioned adresses (0x88400000, 0xbd000000) for load and entry adress (as it was initially defined in the script) did not change boot behavior.

linux-toradex-mainline

It was also not mentioned that the device-tree of the colibri-eval board was not derived from the u-boot package but rather from the linux-toradex-mainline package.

In arch/arm/boot/dts/imx7d-colibri-emmc-eval-v3.dts i added the following node in the module-scope (scope starting with /{)

firmware {
    	optee {
    		compatible = "linaro,optee-tz";
    		method = "smc";
    	};
	};

But that also did not change boot behavior.

u-boot

I also edited configs/colibri_imx7_emmc_defconfig with nconfig and added following flags:

CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_BOOTM_OPTEE=y

But that also did not change boot behavior.

conclusion

I still can’t load optee and need additional information for what is wrong with my config.