Last edited 3 months ago

How to build OP-TEE components

Applicable for STM32MP13x lines, STM32MP15x lines, STM32MP25x lines


1. Purpose[edit | edit source]

This article describes the process used for building several OP-TEE components from sources and deploying them to the target.
The configuration part, passed to OP-TEE during the build process, is introduced in the section below. See the referred articles for more details.

The build example is based on the OpenSTLinux Developer Package or the Distribution Package, and also presents build instructions for a bare environment.

2. Overview[edit | edit source]

It is recommended to first read the STM32MPU OP-TEE overview for a presentation of OP-TEE in STM32MPU distribution.

OP-TEE solution is made of several components described in OP-TEE architecture overview. As described in this article, OP-TEE in STM32MP software deliveries can be used either as a resource manager only or also as a secure services provider. The article STM32MPU OP-TEE configuration profiles details these profiles.

OP-TEE components generate boot images and files stored in the filesystem embedded in the target.

  • OP-TEE OS generates three image files to be loaded in the platform boot mass storage device, as part of the TF-A FIP image that provides image authentication support, managed by the TF-A/BL2 boot stage. Refer to How to configure TF-A FIP for more information on TF-A FIP image.
  • OP-TEE client (package optee_client) can be built to generate nonsecure services for the OP-TEE OS. The files generated from optee_client build are stored in the embedded filesystem.
    This component is required only when OP-TEE configuration enables secure services. That means when STM32MPU OP-TEE is used only as a resource manager (Resource Manager profile), OP-TEE client library and tools do not need to be embedded in the Linux based OS.
  • OP-TEE project releases other packages intended for test and demonstration of the secure services. These can be built and embedded in the target filesystem. Building optee_examples and optee_test generates client and trusted applications together with libraries which are all stored in the target filesystem. Note the OP-TEE Linux driver is built into the Linux kernel image and is part of the OP-TEE ecosystem.

OP-TEE images are embedded in the STM32MPU OpenSTLinux boot firmware FIP image. Refer to TF-A Architecture for more information.

Warning white.png Warning
OP-TEE boot images must be embedded in the FIP binary that is loaded by BL2 and can be automatically authenticated

3. OP-TEE core configuration[edit | edit source]

OP-TEE configuration is defined at build time. The build sequence uses CFG_xxx makefile variables to define the target OP-TEE OS configuration. The build process generates a conf.mk file (and few other) that shows all the CFG_xxx configuration switch used to generic OP-TEE core image. Article OP-TEE configuration switches presents the configuration switch that can be tuned. Article STM32MPU OP-TEE profiles details how OpenSTLinux OP-TEE configuration can be tuned.

4. Build with the Distribution Package[edit | edit source]

The Distribution Package provides means to build the following OP-TEE components from their related bitbake target:

 bitbake optee-os-stm32mp                # OP-TEE core firmware
 bitbake optee-os-sdk-stm32mp            # OP-TEE development kit for Trusted Applications
 bitbake optee-client                    # OP-TEE client
 bitbake optee-test                      # OP-TEE test suite (optional)
 bitbake optee-examples                  # TA and CA examples

Distribution Package build process includes fetching the source files, compiling them and installing them to the target images.

The Yocto recipes for the OP-TEE packages can be found in:

meta-st/meta-st-stm32mp/recipes-security/optee/optee-os-stm32mp*
meta-st/meta-st-openstlinux/recipes-security/optee/optee-client*
meta-st/meta-st-openstlinux/recipes-security/optee/optee-examples*
meta-st/meta-st-openstlinux/recipes-security/optee/optee-test*

5. Build with the Developer Package or a bare environment[edit | edit source]

Both Developer Package and bare build environments expect the user to fetch/download the OP-TEE package source file trees in order to build the embedded binary images.

The instruction set below assumes all OP-TEE package source trees are available in the base directory referred as <sources>/. The source files are available from the Github repositories:

 cd <sources>/
 git clone https://github.com/STMicroelectronics/optee_os.git
 git clone https://github.com/OP-TEE/optee_client.git
 git clone https://github.com/OP-TEE/optee_test.git
 git clone https://github.com/linaro-swg/optee_examples.git
 ls -1 <sources>/
optee_client
optee_examples
optee_os
optee_test
 
Warning white.png Warning
Pay attention to use a consistent tag version for OP-TEE client, test and examples components, e.g.:
- OP-TEE tag 3.12.0 for STM32 MPU ecosystem release 3.x
- OP-TEE tag 3.16.0 for STM32 MPU ecosystem release 4.x,
- OP-TEE tag 3.19.0 for STM32 MPU ecosystem release 5.x
Warning white.png Warning
The STM32 MPU platform may not be fully merged in the official OP-TEE OS repository [1] hence the URL provided above for OP-TEE OS refers to the ST distribution [2]


STM32MP25x lines More info.png may also need an extra source tree for some device tree files (DTS file) that define specific board configuration settings:

 git clone https://github.com/STMicroelectronics/dt-stm32mp.git

5.1. Initialize the cross compile environment[edit | edit source]

It is possible to use the compilation toolchain provided by the Developer Package. Refer to Setup Cross Compile Environment.

Alternatively other bare toolchains can be used to build the OP-TEE secure parts. In such case, the instructions below expect the toolchain to be part of the PATH and its prefix is defined by CROSS_COMPILE:

 export PATH=<path-to-toolchain>:$PATH
 export CROSS_COMPILE=<toolchain-prefix>-

5.2. Build OP-TEE OS[edit | edit source]

5.2.1. Developer Package SDK[edit | edit source]

The OP-TEE OS can be built from the Developer Package Makefile.sdk script that is present in the tarball. It automatically sets the proper configuration for the OP-TEE OS build. To build from shell command:

 make -f $PWD/../Makefile.sdk CFG_EMBED_DTB_SOURCE_FILE=<board_dts_file_name>.dts

5.2.2. Bare environment[edit | edit source]

Alternatively, one can also build OP-TEE OS outside of the distribution package and developer package, using a bare cross compilation toolchain and OP-TEE OS component native Makefile. OP-TEE OS builds with a Makefile and needs some configuration directives, in first place PLATFORM and CFG_EMBED_DTB_SOURCE_FILE.

PLATFORM defines the OP-TEE platform, stm32mp1 or stm32mp2.

CFG_EMBED_DTB_SOURCE_FILE defines the target platform device tree file name, from <optee-os>/core/arch/arm/dts/.

For example, building for stm32mp157c-ev1 target with an OP-TEE core log level of 2 (info level):

 cd <optee-os>
 make PLATFORM=stm32mp1 \
           CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts \
           CFG_TEE_CORE_LOG_LEVEL=2 O=build all

For some boards, ST provides extra device tree configurations in a dedicated git repository: optee/stm32mp257f-ev1-ca35tdcid-ostl.dts . It's possible to use the git submodule command or simply clone the repository below:

 git clone https://github.com/STMicroelectronics/dt-stm32mp.git

or

 git submodule add https://github.com/STMicroelectronics/dt-stm32mp.git core/arch/arm/dts/external-dt

If the external device tree source tree is located at core/arch/arm/dts/external-dt, ignore the paragraph below, this is the default path for the external device tree.

It is then required to compile OP-TEE and specify the external device tree path in the CFG_EXT_DTS config switch. Example for the STM32MP257F-EV1 Evaluation board More info green.png with OSTL config:

 make PLATFORM=stm32mp2 ARCH=arm \
           CFG_EXT_DTS=<PATH_TO_EXTERNAL_DT>/optee
           CFG_EMBED_DTB_SOURCE_FILE=stm32mp257f-ev1-ca35tdcid-ostl.dts \
           CFG_TEE_CORE_LOG_LEVEL=2 \
           O=build all

5.2.3. Generated Files[edit | edit source]

The three OP-TEE boot images are generated at following paths:

<optee-os>/build/core/tee-header_v2.bin
<optee-os>/build/core/tee-pageable_v2.bin
<optee-os>/build/core/tee-pager_v2.bin

The configuration directives used for the build are available in this file:

<optee-os>/build/conf.mk

The build also generates a development kit used to build Trusted Application binaries, in 32 bits and/or 64 bits:

<optee-os>/build/export-ta_arm32/
<optee-os>/build/export-ta_arm64/

5.2.4. Troubleshooting[edit | edit source]

The Developer Package toolchain may report dependency error in the traces such as:

 make PLATFORM=stm32mp1 ...
arm-ostl-linux-gnueabi-ld.bfd: unrecognized option '-Wl,-O1' 
arm-ostl-linux-gnueabi-ld.bfd: use the --help option for usage information
core/arch/arm/kernel/link.mk:165: recipe for target 'build/arm-plat-stm32mp1/core/tee.elf' failed
make: *** [build/arm-plat-stm32mp1/core/tee.elf] Error 1

This is linked to default CFLAGS and LDFLAGS exported by SDK. Remove them from the environment and rebuild

 unset -v CFLAGS LDFLAGS 

Other reported issues:

 make PLATFORM=stm32mp1 ...
arm-openstlinux_weston-linux-gnueabi-ld.bfd: cannot find libgcc.a: No such file or directory

To overcome the issue, add the directive CFLAGS32=--sysroot=$SDKTARGETSYSROOT or CFLAGS64=--sysroot=$SDKTARGETSYSROOT, depending on target architecture. For example:

 cd <optee-os>
 make PLATFORM=stm32mp1 \
           CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts \
           CFG_TEE_CORE_LOG_LEVEL=2 \
           CFLAGS32=--sysroot=${SDKTARGETSYSROOT} \
           O=build all

5.3. Build commands for other OP-TEE components[edit | edit source]

This section describes how the several OP-TEE components (excluding OP-TEE OS described in above section) can be built. All those components generate files targeting the embedded Linux OS based filesystem (i.e the rootfs). These files are the secure Trusted Applications (TAs) binaries as well as nonsecure Client Applications (CAs), libraries, and test files.

There are several ways to build the OP-TEE components. The examples given below refer to OP-TEE client, test, and examples source file tree paths as <optee-client>, <optee-test> and <optee-examples>.

Building these components expect, at least for the trusted applications, that the OP-TEE OS was built. The generated TA development kit is available at <optee-os>/build/export-ta_arm32/.

It is recommended to use CMake for building the Linux userland part whereas secure world binaries (TAs) must be built from their GNU makefiles as the OP-TEE project has not yet ported the secure world binaries build process over CMake.

5.3.1. Build the secure components[edit | edit source]

Build the TAs: This step expects that OP-TEE OS is built in order to generate the 32-bit TA development kit. Assuming that OP-TEE OS was built at path <optee-os>/build. The TA development kit is available from path <optee-os>/build/export-ta_arm32/.

Instructions below build and copy the Trusted Application binaries to a local ./target/ directory that can be used to populate the target filesystem.

 export TA_DEV_KIT_DIR=$PWD/optee_os/build/export-ta_arm32
 mkdir -p ./target/lib/optee_armtz
 for f in optee_test/ta/*/Makefile; do \
            make -C `dirname $f` O=build; \
            cp -f `dirname $f`/build/*.ta ./target/lib/optee_armtz; \
      done

Content in local directory ./target/ are the TA binary files:

 tree target/
target
└── lib
  └── optee_armtz
   ├── 614789f2-39c0-4ebf-b235-92b32ac107ed.ta
   ├── 731e279e-aafb-4575-a771-38caa6f0cca6.ta
   └── (...)

These files need to be copied to the the target filesystem.

5.3.2. Build the nonsecure components[edit | edit source]

Download the OP-TEE source files in a base directory, and create a CMakeLists.txt file in the base directory that lists all package to be built through CMake. For example:

 ls
optee_client
optee_examples
optee_os
optee_test
CMakeLists.txt
 cat CMakeLists.txt
add_subdirectory (optee_client)
add_subdirectory (optee_test)
add_subdirectory (optee_examples)
 

From base directory, run cmake then make. The example below also creates the tree file system ./target/ that is populated with files generated that need to be installed in the target file system.
Note that this examples also sets the toolchain environment:

 cmake -DOPTEE_TEST_SDK=$PWD/optee_os/build/export-ta_arm32 \
            -DCMAKE_INSTALL_PREFIX=  -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=y
 make
 make DESTDIR=target install 

Note that the empty CMAKE_INSTALL_PREFIX value to get thing installed from root /, not from /usr/. DESTDIR=target makes the embedded files be populated in the local ./target/ directory.

Note also that stm32mp1 expects tool tee-supplicant to be located in directory /usr/bin whereas CMake installs it in directory /usr/sbin. To overcome this issue, one can build a link to the effective location, i.e:

 ln -s ../bin/tee-supplicant target/sbin/tee-supplicant

Once done, local directory ./target/ contains the files to be copied in the target filesystem.

 tree target/
target/
├── bin
│   ├── benchmark
│   ├── optee_example_acipher
│   ├── optee_example_aes
│   ├── optee_example_hello_world
│   ├── optee_example_hotp
│   ├── optee_example_random
│   ├── optee_example_secure_storage
│   ├── tee-supplicant
│   └── xtest
├── include
│   ├── tee_bench.h
│   ├── tee_client_api_extensions.h
│   ├── tee_client_api.h
│   └── teec_trace.h
├── lib
│   ├── libteec.so -> libteec.so.1
│   ├── libteec.so.1 -> libteec.so.1.0.0
│   └── libteec.so.1.0.0
│   └── optee_armtz
│       └── (...)                 # This directory was previously filled with TAs
└── sbin
    └── tee-supplicant -> ../bin/tee-supplicant

6. Update OP-TEE boot images[edit | edit source]

OP-TEE boot images are part of the FIP binary.
The next step to deploy the OP-TEE OS is to update the FIP binary following the FIP update process.

7. Update OP-TEE Linux files[edit | edit source]

7.1. Update on board[edit | edit source]

The other OP-TEE images are stored in the target filesystem.

For example, if an SD card is used as a target boot media, it is possible to plug it in a PC card reader and copy the images. The files can be simply copied into the mounted rootfs.

7.2. Update in a SD card[edit | edit source]

The OP-TEE files that need to be copied to the target filesystem were installed in a local directory ./target/.

They can now be copied to the target SD card rootfs partition once the SD card is plugged to the host computer and its filesystems are mounted in the host, i.e

 cp -ar target/* /media/$USERNAME/rootfs/

8. Update the boot device (including SD card on the target)[edit | edit source]

Refer to the STM32CubeProgrammer documentation to update the target.

9. References[edit | edit source]