The initial step would be to embed OP-TEE OS into our firmware boot package and re-configure (and recompile) ARM Trusted Firmware-A to load it.
But first, we need to understand the memory organization of our board. This is required since BL31 (TF-A) has to configure the TZASC peripheral to reserve a trusted region inside the main memory (DRAM) for use by our Secure OS & TAs.
In the figure to the right, we use the upper end of the DDR1 memory (36 MB) for the TrustZone OS (BL32). We will need to calculate the addresses and supply them as configuration parameters when compiling the software.
In order to get the actual physical addresses, one needs to check out the official NXP iMX8MQ Reference Manual, Chapter 2.1.2 (Cortex-A53 Memory Map, pg. 20).
We note that the first DRAM (DDR1) is mapped at 0x40000000
(exactly 1GB from the beginning the address space) and ends at 0xFFFFFFFF
(the difference of the two addresses totals to 3072MB == 3 * 1024MB == 3GB
).
But, since our boards only come with 2GB of LPDDR chips installed, we need to recalculate the end of our DRAM memory region:
DRAM_END = 0x40000000 + 2*1024^3 == 0xC0000000 (in hex)
).
Next, you must do the math to find out the beginning of the TrustZone space: subtract 32 + 4 = 36 MB = 36 * 1024^2
from the end of the RAM!
Finally, we split the TEE space in two: first 32MB
are reserved as secure memory (OP-TEE uses the term TZDRAM to describe this region), the last 4MB
are used as shared memory between the TEE and the Secure Monitor (thus, it is called SHMEM).
Write those values out as Makefile variables (use the hexadecimal format for the calculation results, no spaces inside the number since space is the shell argument separator!), e.g.:
TEE_TZDRAM_START = 0xbdc00000 TEE_TZDRAM_SIZE = <32MB as number of bytes, hex is accepted!> TEE_SHMEM_START = <calc TEE_TZDRAM_START + 32MB, resulting value as hex please> TEE_SHMEM_SIZE = <4MB in bytes please> TEE_RAM_TOTAL_SIZE = <36MB as number of bytes>
These will be passed as compilation flags to the OP-TEE + TF-A build scripts (also makefile-based!) and will get inserted as C expressions into their code (thus, you can use valid mathematical expressions, but we recommend against it due to arcane makefile ↔ shell argument passing issues).
(oh, the angular brackets, <…>
, are NOT PART OF THE Makefile syntax, they are used as commentary placeholder and should be removed, too!)
Now we're ready to run some compilation commands!
Clone the official OP-TEE OS repository inside your working directory's root (where you have all other projects like U-Boot, ATF/TF-A, Linux kernel etc.). Suggested directory name: optee_os
(well… git automatically implies it, since it's also the name of the project).
Now cd
into OP-TEE's freshly downloaded source dir and compile it using GNU Make!
Here's the official build documentation: https://optee.readthedocs.io/en/latest/building/gits/optee_os.html.
Well, not really… since the official instructions lack many of the required configuration flags (especially for our platform) and figuring them out requires some time-consuming source code studying, here are some pointers:
CROSS_COMPILE
as in the labs before!DEBUG
, CFG_TEE_BENCHMARK
and CFG_TEE_CORE_LOG_LEVEL
values from the official example; set the O=…
(output directory) to wherever you like;PLATFORM
is imx-mx8mqevk
; well, not really, but it's the closest one available, we start from here and override some of its configuration defaults, see next vars ;) CFG_TZDRAM_START
, CFG_TZDRAM_SIZE
, CFG_TEE_SHMEM_START
, CFG_TEE_SHMEM_SIZE
configuration flags to the values calculated above (reminder: you can reference another Makefile variable using $(VARIABLE_NAME)
syntax);CFG_DDR_SIZE=0x80000000
(yep, that's 2GB, our board's actual installed memory).
After a successful build, check the output (O
) directory's core
subdirectory for the tee.bin
, tee-raw.bin
and many other files!
We will keep the raw one for later inclusion into the firmware package using mkimage
;)
Remember the TF-A component (BL31) from Lab 1? We need to re-configure + rebuild it (hopefully, you still got the Makefile script)!
This should be straightforward, since you've done it before ;) You need to set the following additional configuration variables to its make invocation:
SPD=opteed
– this is the Secure Payload Dispatcher module, aka: who does ATF's Secure Monitor need to talk with? Our OP-TEE, of course!BL32_BASE
variable to lower limit, in hexadecimal); we also need to specify its total size: BL32_SIZE
(remember: we allocated 36MB
, but give it in bytes, either in base 10 or 16 using C integer notation);LOG_LEVEL=40
and IMX_BOOT_UART_BASE=0x30860000
(if you look in iMX8MQ's Memory Map (the Reference Manual), this is the physical address of our Universal Asynchronous Transmitter/Receiver - i.e. our serial communication module!).Before we can take a look at the fruits of our effort so far, we need to re-build the firmware package with these last two components.
This is easy if you saved your mkimage script (in your Makefile). You will need JUST one additional file copied: tee-raw.bin
from optee_os
build output directory, core
subdirectory (as mentioned in the subtask above!) inside mkimage
's build directory, but rename it as tee.bin
.
The bundled scripts will see that this file exists and add it to the image automatically!
TEE_LOAD_ADDR=<TrustZone DRAM start address>
.
The default value is wrong for our SoC.
Also make sure to replace bl31.bin
with the newly recompiled one from ARM Trusted Firmware-A!
Proceed to load this image over the serial boot protocol using the IMX uuu
utility.
Check the serial console (the one provided by the board's Micro USB port) for confirmation!