OP-TEE SPMC supports two methods for finding and loading the SP executable images. Currently only ELF executables are supported. In our buildsystem the method can be selected with the SP_PACKAGING_METHOD option .
1. Embedded SP
In this case the early TA mechanism of optee_os is reused: the SP ELF files are embedded into the main OP-TEE binary. Each ELF should start with a specific section (.sp_head) containing a struct which describes the SP (UUID, stack size, etc.). The images can be added to optee_os using the `EARLY_TA_PATHS` config option, but our buildsystem should set this up automatically when `SP_PACKAGING_METHOD=embedded` is selected. The images passed in `EARLY_TA_PATHS` are processed by a script in optee_os and linked into the main binary. At runtime the `for_each_early_ta()` macro  can iterate through these images (both TAs and SPs), so a particular SP can be found by UUID and then loaded by ldelf.
The SP manifest file  used by the SPMC to setup SPs is not included with the individual SP images. The manifest DTs should be concatenated into one DT and passed to optee_os in the `CFG_EMBED_DTB_SOURCE_FILE` option. Again, when selecting the embedded SP option in  this will be done automatically by our buildsystem.
2. FIP SP
In this case the SP ELF files and the corresponding SP manifest DTs are encapsulated into SP packages and packed into the FIP. The goal of providing this alternative flow is to make updating SPs easier (independent of the main OP-TEE binary) and to get aligned with Hafnium (S-EL2 SPMC). For more information about the FIP, please refer to the TF-A documentation . The SP packaging process and the package format is provided by TF-A (Hafnium), detailed description is available at . In our buildsystem this method can be selected by `SP_PACKAGING_METHOD=fip`, it covers all the necessary setup automatically. In case of using another buildsystem, the following steps should be implemented:
- TF-A config `SP_LAYOUT_FILE`: provide a JSON file which describes the SPs (path to SP executable and corresponding DT), the TF-A buildsystem will create the SP packages (using sptool) based on this and pack them into the FIP.
- TF-A config `ARM_BL2_SP_LIST_DTS`: provide a DT snippet which describes the SPs' UUIDs and load addresses (example: ). This will be injected into the SP list in `TB_FW_CONFIG` DT of TF-A, and BL2 will load the SPs to the address specified here. Note that BL2 doesn't automatically load all images from the FIP: it's necessary to explicitly define them in `TB_FW_CONFIG` (using this injected snippet or manually editing the DT).
- TF-A config `ARM_SPMC_MANIFEST_DTS`: provide the SPMC manifest (example: ). This DT contains information about the SPMC itself which gets processed by the SPMD, but it's also passed to the SPMC as a boot argument (in the TF-A naming convention this is the `TOS_FW_CONFIG`, passed to BL32). This should contain the the list of SP packages and the load addresses in the `compatible = "arm,optee-spmc"` node.
- optee_os config: set `CFG_FIP_SP=y`.
At boot optee_os will parse the SP load addresses in the SPMC manifest and find the SP packages already loaded by BL2. Iterating through the SP packages, based on the SP package header in each package it will map the SP manifest DTs and load the executables using ldelf.
Note that in the process described above there are some redundancies:
- the SP UUID has to be provided twice, once in the SP manifest DT and once in the `ARM_BL2_SP_LIST_DTS` DT snippet,
- the SP load address has to be provided twice, once in the SPMC manifest DT and once in the `ARM_BL2_SP_LIST_DTS` DT snippet.
This could be improved in the future to have a more streamlined solution.