1. Purpose of article[edit source]
This article describes how to update the STM32MPU Embedded Software distribution for a specific 256MB DDR mapping in a STM32MP13x lines based product.
Note that the 256MB software configuration can be performed on a STM32MP135F-DK Discovery kit (512MB of DDR), in order to prototype the new mapping memory, but for this exercise, further software updates are requested, that are highlight in the article with an information window and the label DDR512MB.
2. Pre-requesites[edit source]
You are already familiar with the Yocto build process and OpenSTLinux Distribution Package.
3. Introduction[edit source]
This article is a guideline for the user to update the STM32MPU Embedded Software distribution package of the OpenSTLinux, according to his 256MB hardware configuration. We keep the default memory mapping of the OpenSTlinux for the STM32MP135F-DK Discovery kit board (512MB of DDR) included in particular the OP-TEE framebuffer region used by the OP-TEE Trusted UI framework, and the size (32MB) of the memory allocated to OP-TEE and the share memory.
This is the following default DDR mapping :
0xe0000000 | End of DDR 512MB 0xde200000 | DDR_SEC_BASE/CFG_TZDRAM_START | size DDR_SEC_SIZE/STM32MP_DDR_S_SIZE/CFG_TZDRAM_SIZE (30MB) protected | Begin of OP-TEE mapping | Begin of DDR encrypted DDRMCE, size 30MB | End of SHMEM 0xde000000 | DDR_SHARE_BASE/CFG_SHMEM_START | size DDR_SHARE_SIZE/STM32MP_DDR_SHMEM_SIZE/CFG_SHMEM_SIZE (2MB no secure) | Begin of reserved memory optee, size 32MB 0xdd000000 | Begin of optee-framebuffer protected access by TZC 400, size 16MB 0xdc800000 | End of Linux CMA reserved 0xd4800000 | Begin of Linux CMA reserved, size CONFIG_CMA_SIZE_MBYTES 128MB 0xd0000000 | End of DDR cacheable in U-Boot 0xc0000000 | STM32MP_DDR_BASE/DDR_NS_BASE, size 464MB | Begin of DDR cacheable in U-Boot, size CONFIG_DDR_CACHEABLE_SIZE 256MB
The constants highlighted in green are the ones that we will modify to fit the 256MB mapping targeted:
0xd0000000 | End of DDR 256MB 0xce200000 | DDR_SEC_BASE/CFG_TZDRAM_START | size DDR_SEC_SIZE/STM32MP_DDR_S_SIZE/CFG_TZDRAM_SIZE (30MB) protected by TZC 400 | Begin of OP-TEE mapping | Begin of DDR encrypted DDRMCE, size 30MB | End of SHMEM 0xce000000 | DDR_SHARE_BASE/CFG_SHMEM_START | size DDR_SHARE_SIZE/STM32MP_DDR_SHMEM_SIZE/CFG_SHMEM_SIZE (2MB no secure) | Begin of reserved memory optee, size 32MB 0xcd000000 | Begin of optee-framebuffer protected access by TZC 400, size 16MB 0xcb000000 | End of Linux CMA reserved 0xc8000000 | End of DDR cacheable in U-Boot 0xc3000000 | Begin of Linux CMA reserved, size CONFIG_CMA_SIZE_MBYTES 128MB 0xc0000000 | STM32MP_DDR_BASE/DDR_NS_BASE, size 208MB | Begin of DDR cacheable in U-Boot, size CONFIG_DDR_CACHEABLE_SIZE 128MB
The software modifications, requested in the STM32MPU Embedded Software distribution, have been performed with devtool and bitbake tools. The following components need to be modified : TF-A, U-Boot, OP-TEE, Linux kernel.
4. DDR configuration[edit source]
The DDR is configured with the STM32CubeMX DDR tool, the tool creates the "device tree source include" file, see the wiki page STM32CubeMX for details.
5. TF-A updates[edit source]
To update the TF-A firmware in the STM32MPU Embedded Software distribution package, use the devtool tool:
tf-a-stm32mpdevtool modify
The updates requested according to the new mapping:
- Modify the DDR_SIZE (512MB->256MB) defined in file fdts/stm32mp135f-dk-fw-config.dts
DDR_SIZE 0x10000000#define
5.1. Description of the TF-A updates[edit source]
For some further description , read the How to configure TF-A FW CONFIG.
- Firewall configuration
The DDR firewall is configured to restrict access to specific areas.The TZC is configured at boot time to setup DDR accesses by the TF-A, completed by OP-TEE.
CPU Start address = 0xCE20 0000: 30-Mbyte (OP-TEE) region where only secure accesses are allowedThree regions are defined: Start address = 0xC000 0000: 251-Mbyte region where secure accesses are forbidden and to which all non-secure peripherals can access Start address = 0xCE00 0000: 2-Mbyte (SHM) region where secure accesses are forbidden and non-secure accesses are possible only from an A7
OP-TEE is the secure OS executed in DDR protected by TZC, the size allocated to OP-TEE depends on how the OP-TEE is configured and used, it includes the firmware Optee-os size, the stack and heap size, stack and heap are almost dedicated to Trusted Applications. SHM is the SHare Memory between non secure and secure OS.
The configuration of the MEM firewall is defined in the file fdts/stm32mp13-fw-config.dtsi
DDR_NS_BASE = STM32MP_DDR_BASE = 0xc0000000 (default OpenSTLinux RAM mapping)) DDR_SEC_SIZE = 0x01e00000 (30 MB allocated to OP-TEE). DDR_SEC_BASE = STM32MP_DDR_BASE + DDR_SIZE - DDR_SEC_SIZE = 0xc0000000 + 0x10000000 - 0x01e00000 = 0xce200000 DDR_SHARE_SIZE = 0x00200000 (2 MB allocated for Share memory) DDR_SHARE_BASE = DDR_SEC_BASE - DDR_SHARE_SIZE = 0xce200000 - 0x00200000 = 0xce000000 DDR_NS_SIZE = DDR_SHARE_BASE - DDR_NS_BASE = 0xce000000 - 0xc0000000 = 0x0e000000 (224MB dedicated to no secure world)
- DDR Encryption area
The memory region encrypted is defined in fdts/stm32mp13-fw-config-mem-encrypt.dtsi . The memory region defined by default in OpenSTLinux configuration is the region allocated to OP-TEE, so, set with parameters DDR_SEC_BASE and DDR_SEC_SIZE.
- Firmware configuration file
The FW_CONFIG defines all binaries to be loaded in internal RAM or DDR, with for each image the load address, the maximum binary size to be loaded, and the ID of the image. The FW_CONFIG and all binaries are embedded in a TF-A FIP binary. (Firmware Image Package). The TF-A FIP contains all boot binaries and, optionally, their certificates, installed by the TF-A. (U-Boot, U-Boot dtb, OP-TEE, FW_CONFIG)
The configuration is defined in the file fdts/stm32mp13-fw-config.dtsi . The structure of the tos-fw (secure os) depend on the parameters DDR_SEC_BASE and DDR_SEC_SIZE.
6. OP-TEE updates[edit source]
To update the OP-TEE firmware in the STM32MPU Embedded Software distribution package, use the devtool tool:
optee-os-stm32mpdevtool modify
The updates requested according to the new mapping:
- Modify the CFG_DRAM_SIZE (512MB->256MB) in the file core/arch/arm/plat-stm32mp1/conf.mk .
CFG_DRAM_SIZE ?= 0x10000000
- Modify the RAM memory size (512MB->256MB), the location of the secure framebuffer memory (0xdd000000->0xcd000000), in the file core/arch/arm/dts/stm32mp135f-dk.dts
0x10000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; optee_framebuffer: optee-framebuffer@cd000000 { /* Secure framebuffer memory */ reg = <0xcd000000 0x1000000>; st,protreg = <TZC_REGION_S_RDWR 0>; };memory@c0000000 { device_type = "memory"; reg = <0xc0000000
6.1. Description of the OP-TEE updates[edit source]
- Secure memory and share memory
The OP-TEE memory configuration is defined in the file core/arch/arm/plat-stm32mp1/conf.mk
CFG_TZDRAM_START ?= ($(CFG_DRAM_BASE) + $(CFG_DRAM_SIZE) - $(CFG_TZDRAM_SIZE)) = 0xc0000000 + 0x10000000 - 0x1e00000 = 0xce200000 CFG_SHMEM_START ?= ($(CFG_TZDRAM_START) - $(CFG_SHMEM_SIZE)) = 0xce200000 - 0x200000 = 0xce000000
The allocated memory includes the size of the Optee-os firmware, the stack and heap size, almost of stack and heap are reserved to the Trusted Applications.
See the FAQ in OP-TEE documentation.[1]
- OP-TEE frame buffer
The OP-TEE frame buffer is a secure memory region dedicated to the display, used by Trusted UI in OP-TEE, protected by TZC. The DDR firewall region is added to the three regions defined in TF-A .(see Description of the TF-A updates)
Start address = 0xCD00 0000: 16-Mbyte region where only secure accesses are allowed.
7. U-Boot updates[edit source]
For further description, read the U-Boot memory mapping.
To update the U-Boot firmware in the STM32MP1 Distribution Package, use the devtool tool:
u-boot-stm32mpdevtool modify
The updates requested according to the new mapping, is aligned with the updates done in the Linux device tree:
- Modify the RAM memory size (512MB->256MB), the location of the secure framebuffer memory (0xdd000000->0xcd000000), and the location (0xde000000->0xce000000) of secure memory allocated to OP-TEE and SHM in the file arch/arm/dts/stm32mp135f-dk.dts
0x10000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; optee_framebuffer@cd000000 { reg = <0xcd000000 0x1000000>; no-map; }; optee@ce000000 { reg = <0xce000000 0x02000000>; no-map; }; };memory@c0000000 { device_type = "memory"; reg = <0xc0000000
- Check the size of the DDR marked as-cacheable in U-Boot, in your defconfig file or for STM32MP135F-DK in configs/stm32mp13_defconfig , to avoid overlap with OP-TEE region:
CONFIG_DDR_CACHEABLE_SIZE 0x8000000
7.1. Description of the U-Boot updates[edit source]
- Secure memory reserved
The OP-TEE nodes in U-Boot device tree are aligned with Linux device tree. It is the memory reserved for secure "Optee-os" (optee@) and the OP-TEE framebuffer (optee_framebuffer@) dedicated to the display, used by Trusted UI in OP-TEE.
The size of the memory reserved for secure "Optee-os" (optee@) is calculated as the way:
CFG_TZDRAM_SIZE + CFG_SHMEM_SIZE = 32MB = 0x02000000.
- Size of the DDR marked cacheable before relocation
CONFIG_DDR_CACHEABLE_SIZE define the size of the DDR marked as-cacheable before relocation in your U-Boot defconfig file to avoid overlap with secured regions.
This value need to be set at 128MB (0x8000000) because OP-TEE is located in the last 128MB of the 256MB DDR; it is done by default only after ecosystem release v4.1.0 for STMicroelectronics boards (configs/stm32mp13_defconfig and configs/stm32mp15_defconfig ) and 128MB is enough to executed the relocation; see U-Boot memory mapping for DDR usage before relocation.
In case of overlap between the cacheable area before U-Boot relocation and the reserved and secured by OP-TEE region, the U-Boot code execution on Arm® Cortex®-A7 normal world can generate a speculative access to this secured area which cause a firewall error.
8. Linux kernel updates[edit source]
To update the Linux kernel in the STM32MP1 Distribution Package, use the devtool tool :
devtool modify linux-stm32mp
The updates requested according to the new mapping:
- Modify the RAM memory size (512MB->256MB), the location of the secure framebuffer memory (0xdd000000->0xcd000000), and the location (0xde000000->0xce000000) of secure memory allocated to OP-TEE and SHM in the file arch/arm/boot/dts/stm32mp135f-dk.dts
0x10000000>; }; reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; optee_framebuffer@cd000000 { reg = <0xcd000000 0x1000000>; no-map; }; optee@ce000000 { reg = <0xce000000 0x02000000>; no-map; }; };memory@c0000000 { device_type = "memory"; reg = <0xc0000000
- No more use the zImage file, included in generated uImage, as kernel image started by U-Boot.
For example, with GZIP compression:
Linux -d Image.gz uImagegzip Image mkimage -A arm -O linux -T kernel -C gzip -a 0xC0008000 -e 0xC0008000 -n
8.1. Description of the Linux kernel updates[edit source]
Refer to Description of the U-Boot updates.
8.2. zImage memory usage[edit source]
The zImage file cannot be used to boot the kernel because it use the first 256MB for the DDR.
This zImage file is the compressed version of the Linux kernel image that is self-extracting. The zImage file is used by default on ARM platform.
During the Linux kernel decompression, the MMU is activated to enable the data cache in generic code __setup_mmu :
RAM add r10, r9, #0x10000000 @ a reasonable RAM sizemov r9, r9, lsl #18 @ start of
The first 256MB of the DDR are mapped cacheable (the size = 0x10000000 is hard-coded in this generic ARM code) and, according the execution flow, the cortex core can request speculative access to any address in the DDR, including the OP-TEE reserved and protected memory.
To avoid any TZC Permission violation, the self-extracting feature of kernel must not be used.
You can use U-Boot FIT, as described in U-Boot documentation , or use pre-compressed Linux kernel Image and generated manually the uImage with the option -C [compression type]
of mkimage U-Boot tools . See mkimage documentation for details:
man mkimage
mkimage --help
8.3. Linux kernel memory usage[edit source]
The resulting DDR Non Secure memory allocated to the Linux kernel and userspace, according to the mapping chosen is: 0xcd000000 - 0xc0000000 = 0xd000000 (208 MB).
Purpose of this paragraph is to highlight you about some components size you can modify to share the non secure RAM according to your need, the Linux kernel and the Contiguous Memory Area (CMA).
We can estimate minimal amount of required RAM at system startup of the kernel image, we talk here about the static RAM used by the kernel image and filesystem. To know the kernel image size execute the command :
size vmlinux
Example of result with OpenSTLinux default image : 16,5MB
The size of the Contiguous Memory Area (CMA) is defined in the kernel configuration file CONFIG_CMA_SIZE_MBYTES. CONFIG_CMA_SIZE_MBYTES is set to 128MB in the OpenSTLinux distribution package.
9. Traces/Debug[edit source]
To verify your 256MB config, some traces can be checked. The following traces have been obtained with a ST_OPTEE_DEBUG_LOG_LEVEL = "3" for the OP-TEE and a ST_TF_A_LOG_LEVEL_RELEASE = "40" for the TF-A.
- Loading and boot of BL32 OP-TEE image.
0xce200000 INFO: Image id=4 loaded: 0xce200000 - 0xce20001c INFO: OPTEE ep=0xce200000 INFO: OPTEE header info: INFO: magic=0x4554504f INFO: version=0x2 INFO: arch=0x0 INFO: flags=0x0 INFO: nb_images=0x1 INFO: BL2: Loading image id 21 INFO: Loading image id=21 at address 0xce200000 NOTICE: BL2: Booting BL32 INFO: Entry point address = 0xce200000INFO: Loading image id=4 at address
- OP-TEE traces
TZC DDR access configuration by OP-TEE: D/TC:0 0 tzc_dump_state:473 region 0 D/TC:0 0 tzc_dump_state:476 region_base: 0x0000000000000000 D/TC:0 0 tzc_dump_state:479 region_top: 0x00000000ffffffff D/TC:0 0 tzc_dump_state:481 secure rw: TZC_REGION_S_NONE D/TC:0 0 tzc_dump_state:486 filter 0 enable Secure region (30MB) : OP-TEE D/TC:0 0 tzc_dump_state:473 region 1 D/TC:0 0 tzc_dump_state:476 region_base: 0x00000000ce200000 D/TC:0 0 tzc_dump_state:479 region_top: 0x00000000cfffffff D/TC:0 0 tzc_dump_state:481 secure rw: TZC_REGION_S_RDWR D/TC:0 0 tzc_dump_state:486 filter 0 enable Non secure region(2MB) : Share memory D/TC:0 0 tzc_dump_state:473 region 2 D/TC:0 0 tzc_dump_state:476 region_base: 0x00000000ce000000 D/TC:0 0 tzc_dump_state:479 region_top: 0x00000000ce1fffff D/TC:0 0 tzc_dump_state:481 secure rw: TZC_REGION_S_NONE D/TC:0 0 tzc_dump_state:486 filter 0 enable Secure region (16MB) : OP-TEE frame buffer D/TC:0 0 tzc_dump_state:473 region 3 D/TC:0 0 tzc_dump_state:476 region_base: 0x00000000cd000000 D/TC:0 0 tzc_dump_state:479 region_top: 0x00000000cdffffff D/TC:0 0 tzc_dump_state:481 secure rw: TZC_REGION_S_RDWR D/TC:0 0 tzc_dump_state:486 filter 0 enable Non secure region (208 MB) : linux D/TC:0 0 tzc_dump_state:473 region 4 D/TC:0 0 tzc_dump_state:476 region_base: 0x00000000c0000000 D/TC:0 0 tzc_dump_state:479 region_top: 0x00000000ccffffff D/TC:0 0 tzc_dump_state:481 secure rw: TZC_REGION_S_NONE
- U-Boot traces
U-Boot U-Boot 2021.10-stm32mp-r1 (Jan 27 2023 - 09:03:57 +0000) CPU: STM32MP135F Rev.Z Model: STMicroelectronics STM32MP135F-DK Discovery Board Board: stm32mp1 in trusted mode (st,stm32mp135f-dk) Board: MB1635 Var1.0 Rev.C-01 DRAM: 256 MiB Select the boot mode 1: OpenSTLinux 2: stm32mp135f-dk-a7-examples Enter choice: 1: OpenSTLinux Temporary file system and linux kernel compressed file loaded in RAM Retrieving file: /st-image-resize-initrd 21498257 bytes read in 909 ms (22.6 MiB/s) Retrieving file: /uImage 7701112 bytes read in 335 ms (21.9 MiB/s) append: root=PARTUUID=e91c4e10-16e6-4c0e-bd0e-77becf4a3582 rootwait rw console=ttySTM0,115200 Retrieving file: /stm32mp135f-dk.dtb 59732 bytes read in 16 ms (3.6 MiB/s)
- Linux kernel boot traces
The memory trace show the kernel part (16MB) and the cma reserved (128MB) CONFIG_CMA_SIZE_MBYTE [ 0.000000] Memory: 65704K/262144K available (12288K kernel code, 1242K rwdata, 3436K rodata, 1024K init, 186K bss, 65368K reserved, 131072K cma-reserved, 0K highmem)