Boot process for optee

Table of Contents

QEMU Platform Boot architecture

from official atf code at 34efb683 @ m/master Merge pull request #1724 from jbech-linaro/emmc_enumeration
build command:

make BL32=tee-header_v2.bin BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin BL33=bl33.bin PLAT=qemu ARM_TSP_RAM_LOCATION=tdram BL32_RAM_LOCATION=tdram SPD=opteed DEBUG=0 LOG_LEVEL=30

qemu optee boot architecture:

.optee-qemu-boot-arch.png

In qemu aarch64 platform, system will load & boot trust os before Nonsecure world os start.

BOOT analyze

ATF Part

arguments pass between different boot stages.

BL1

BL1 usually be used as bootrom and will pass one argument to Next stage bootloader.

/*******************************************************************************
 * Structure used for telling the next BL how much of a particular type of
 * memory is available for its use and how much is already used.
 ******************************************************************************/
typedef struct meminfo {
    uintptr_t total_base;
    size_t total_size;
} meminfo_t;
BL2

BL2 usually be used to load extra images, including BL31, BL32, BL33 etc.
When go to next stage image, it will pass image load information to next stage bootloaders.

Fellowing definition defined the struct format to pass.

/* BL image node in the BL image execution sequence */
typedef struct bl_params_node {
    unsigned int image_id;
    image_info_t *image_info;
    entry_point_info_t *ep_info;
    struct bl_params_node *next_params_info;
} bl_params_node_t;

/*
 * BL image head node in the BL image execution sequence
 * It is also used to pass information to next BL image.
 */
typedef struct bl_params {
    param_header_t h;
    bl_params_node_t *head;
} bl_params_t;
BL31

BL31 usually be used as secure monitor, it will be running on the whold system life cycle.
BL31 will pass different arguments from bl_params to next stage images
In BL31 case, It just bypass arguments from bl2 to bl31 in our case.

SPD

BL31 initial all runtime service registered using the DECLARE_RT_SVC()
for OPTEE, it will be opteed_setup()
opteed_setup will do:

  1. Get secure image ep_info (BL2 will pass it to bl31 via x0).
  2. arguments for opteed including:
    opteed_rw
    OPTEE execution state information i.e. aarch32 or aarch64
    opteed_pageable_part
    pass to optee os as arg0
    opteed_mem_limit
    pass to optee os as arg1
    dt_addr
    pass to optee os as arg2

OPTEE Part

we have learn about how bootloader pass arguments to optee os, next we will going to optee part.

  • process state

    In our case, it's OPTEE_AARCH64, secure world will be at MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS.
    Please notice, there is no secure EL2 at aarch64, only secure EL1.

  • arguments:
    x0
    opteed_pageable_part
    x1
    opteed_mem_limit
    x2
    dt_addr

Services in secure monitor

Owning entity number
arm smccc defined SMC function call number, and OEM [50, 63] is for Trusted OS.

FAST CALL

opteed register fellowing fastcall, and it's usage is shown as fellowing.

SMC function ID Usage
TEESMC_OPTEED_RETURN_ENTRY_DONE Called by OPTEE when optee os initial done
TEESMC_OPTEED_RETURN_ON_DONE psci stub
TEESMC_OPTEED_RETURN_RESUME_DONE psci stub
TEESMC_OPTEED_RETURN_OFF_DONE psci stub
TEESMC_OPTEED_RETURN_SUSPEND_DONE psci stub
TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE psci stub
TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE psci stub
TEESMC_OPTEED_RETURN_CALL_DONE Return to NON Secure World from function call
TEESMC_OPTEED_RETURN_FIQ_DONE Return to NON Secure World when S-EL1 FIQ done

calling optee_vector_table->fast_smc_entry

YIELD CALL

There is no handler in bl31 to handle yield call, bl31 only bypass this request to S-EL1.
calling optee_vector_table->yield_smc_entry

OPTEE code

optee image type

For information about optee image
https://optee.readthedocs.io/en/latest/architecture/core.html#pager
in our case, qemu aarch64 don't use pager, and only use paged image.
optee os main images: optee_os/out/arm/core/tee-pager_v2.bin

entry point

OPTEE service entry point

  1. init exception vector table.
  2. clear bss section
  3. setup stack pointer.
  4. dcache invalidation
  5. console initialize
  6. mmu initialize
  7. optee thread init
  8. setup nonsec memory
  9. add optee service node to device-tree
  10. config console driver according to device-tree
  11. init gic
  12. dcache clean & invalidation
  13. Call smc return to Secure Monitor

Finally, system will return a service vectory table to secure monitor.
From now, optee os boot complete.

Conclusions

  1. optee boot process is very light, and should consumes a very short time to boot.
  2. optee will register callbacks to secure monitor & add service node to device tree.
Contact me via :)
虚怀乃若谷,水深则流缓。