main入口
在此文件中:
tfm/secure_fw/spm/cmsis_psa/main.c
Main()
->tfm_arch_set_msplim((uint32_t)®ION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base)); //设置堆栈限制
->fih_delay_init();
->tfm_core_init()
->tfm_hal_set_up_static_boundaries
->configure_mpu(rnr++, base, limit, XN_EXEC_OK, AP_RO_PRIV_UNPRIV); //配置各个内存边界的读写属性
->tfm_hal_platform_init() //核心函数,需要重点展开分析
->__enable_irq(); //使能中断
->stdio_init(); //初始化串口
-> corstone1000_watchdog_init() //初始化看门狗
-> fwu_metadata_init()
-> FWU_METADATA_FLASH_DEV.Initialize(NULL) //初始化FWU metadata所在的FLASH,就是 32MB 那个
-> flash_info = FWU_METADATA_FLASH_DEV.GetInfo()
-> corstone1000_host_watchdog_handler_init()
->tfm_plat_otp_init()
->tfm_plat_provisioning_perform()
-> tfm_plat_otp_read //读OTP值
->tfm_arch_config_extensions()
->SCB->NSACR |= SCB_NSACR_CP10_Msk | SCB_NSACR_CP11_Msk;
->SCnSCB->CPPWR |= SCnSCB_CPPWR_SUS11_Msk | SCnSCB_CPPWR_SUS10_Msk;
->SPMLOG_DBGMSGVAL("TF-M isolation level is: ", TFM_LVL);
->SPMLOG_INFMSG("\033[1;34m Booting TFM v"VERSION_FULLSTR"\033[0m\r\n"); /* Print the TF-M version */
->tfm_arch_clear_fp_status(); //汇编代码
->tfm_core_handler_mode(); //发送SVC命令,触发tfm_spm_init(),这个函数是PSA的重点
//tfm_core_handler_mode()函数定义如下,它会调用SVC命令,并且,传递一个参数 TFM_SVC_SPM_INIT,最终,会调用到SVC_Handler, 最后,根据ID,调用到 tfm_spm_init()函数,后面会重点讲到tfm_spm_init()函数
__attribute__ ((naked)) void tfm_core_handler_mode(void)
{
__ASM volatile("SVC %0 \n"
"BX LR \n"
: : "I" (TFM_SVC_SPM_INIT));
}
PendSV响应
PendSV(可悬起的系统调用),它和SVC 协同使用
SVC异常是必须立即得到响应的,应用程序执行SVC 时都是希望所需的请求立即得到响应。
PendSV 则不同,它是可以像普通的中断一样被抢占挂起的
PendSV_Handle
SVC响应
SVC_Handler
->BL tfm_core_svc_handler
->tfm_core_svc_handler
-> case TFM_SVC_SPM_INIT: tfm_spm_init() //初始化SPM
-> case TFM_SVC_GET_BOOT_DATA: tfm_core_get_boot_data_handler(svc_args);
-> case TFM_SVC_PREPARE_DEPRIV_FLIH: tfm_flih_prepare_depriv_flih (struct partition_t *)svc_args[0], (uintptr_t)svc_args[1]);
-> case TFM_SVC_FLIH_FUNC_RETURN: tfm_flih_return_to_isr(svc_args[0], (struct context_flih_ret_t *)msp);
-> default: svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, exc_return); //根据Client端调用SVC命令时,传入的ID,进入不同的case处理函数
tfm_spm_init
tfm_spm_init
->tfm_pool_init(conn_handle_pool,POOL_BUFFER_SIZE(conn_handle_pool),sizeof(struct conn_handle_t),
CONFIG_TFM_CONN_HANDLE_MAX_NUM)
->load_a_partition_assuredly //从 section: .part.load 段中,依次获取一个 一个的partition_load_info_t
-> p_ptldinf->psa_ff_ver //检查Magic是否是:0x5F5F0000
->UNI_LIST_INSERT_AFTER(head, partition, next) //加到链表头部
-> load_irqs_assuredly(partition) //从partition中,获取到struct irq_load_info_t
->p_irq_info->init(p_partition, p_irq_info)
-> mailbox_irq_init() //初始化mailbox中断
-> tfm_hal_irq_enable(p_irq_info->source) //使能中断
-> backend_instance.comp_init_assuredly(partition, service_setting) // backend_instance 定义在backend_ipc.c中
-> backend_instance.system_run() //开始调度
//如下所示,在section: .part.load 段中, 定义了一下 tfm_ns_mailbox_agent_load,该结构体是Cmake文件中,通过解析 yaml后,自动生成的:
const struct partition_tfm_ns_mailbox_agent_load_info_t tfm_ns_mailbox_agent_load
__attribute__((used, section(".part_load"))) = {
.load_info = {
.psa_ff_ver = 0x0101 | PARTITION_INFO_MAGIC,
.pid = TFM_NS_MAILBOX_AGENT,
.flags = 0
| PARTITION_MODEL_IPC
| PARTITION_MODEL_PSA_ROT
| PARTITION_PRI_LOW,
.entry = ENTRY_TO_POSITION(ns_agent_mailbox_entry), //这里关联到了mailbox
.stack_size = 0x800,
.heap_size = 0,
.ndeps = TFM_NS_MAILBOX_AGENT_NDEPS,
.nservices = TFM_NS_MAILBOX_AGENT_NSERVS,
.nassets = TFM_NS_MAILBOX_AGENT_NASSETS,
.nirqs = TFM_NS_MAILBOX_AGENT_NIRQS,
},
.stack_addr = (uintptr_t)tfm_ns_mailbox_agent_stack,
.heap_addr = 0,
#if TFM_LVL == 3
.assets = {
{
.mem.start = PART_REGION_ADDR(PT_TFM_NS_MAILBOX_AGENT_PRIVATE, _DATA_START$$Base),
.mem.limit = PART_REGION_ADDR(PT_TFM_NS_MAILBOX_AGENT_PRIVATE, _DATA_END$$Base),
.attr = ASSET_ATTR_READ_WRITE,
},
},
#else
#endif
.irqs = {
{
.init = mailbox_irq_init,
.flih_func = 0,
.pid = TFM_NS_MAILBOX_AGENT,
.source = MAILBOX_IRQ,
.signal = MAILBOX_SIGNAL,
},
},
};
//在链接脚本中,tfm/platform/ext/common/gcc/tfm_common_s.ld 有如下定义,可以看到Image$$TFM_SP_LOAD_LIST$$RO$$Base
指向了.part_load 这个section的起始地址
//在load_a_partition_assuredly ()中,将会通过 Image$$TFM_SP_LOAD_LIST$$RO$$Base
找到 所有的 load_info,并且去加载它们:
.TFM_SP_LOAD_LIST : ALIGN(4)
{
KEEP(*(.part_load))
} > FLASH
Image$$TFM_SP_LOAD_LIST$$RO$$Base = ADDR(.TFM_SP_LOAD_LIST);
Image$$TFM_SP_LOAD_LIST$$RO$$Limit = ADDR(.TFM_SP_LOAD_LIST) + SIZEOF(.TFM_SP_LOAD_LIST);
. = ALIGN(32);
//tfm/secure_fw/spm/ffm/backend_ipc.c
const struct backend_ops_t backend_instance = {
.comp_init_assuredly = ipc_comp_init_assuredly,
.system_run = ipc_system_run,
.messaging = ipc_messaging,
.replying = ipc_replying,
};
ipc_system_run
-> thrd_start_scheduler(&CURRENT_THREAD)
SVC_Handler_IPC
在M核的代码中调用SVC汇编指令,都会进入到这个处理中来:
static int32_t SVC_Handler_IPC(uint8_t svc_num, uint32_t *ctx,
uint32_t lr)
{
psa_status_t status = PSA_SUCCESS;
switch (svc_num) {
case TFM_SVC_PSA_FRAMEWORK_VERSION:
return tfm_spm_client_psa_framework_version();
case TFM_SVC_PSA_VERSION:
return tfm_spm_client_psa_version(ctx[0]);
case TFM_SVC_PSA_CALL:
status = tfm_spm_client_psa_call((psa_handle_t)ctx[0], ctx[1],
(const psa_invec *)ctx[2],
(psa_outvec *)ctx[3]);
break;
case TFM_SVC_PSA_WAIT:
return tfm_spm_partition_psa_wait((psa_signal_t)ctx[0], ctx[1]);
case TFM_SVC_PSA_GET:
return tfm_spm_partition_psa_get((psa_signal_t)ctx[0],
(psa_msg_t *)ctx[1]);
case TFM_SVC_PSA_READ:
return tfm_spm_partition_psa_read((psa_handle_t)ctx[0], ctx[1],
(void *)ctx[2], (size_t)ctx[3]);
case TFM_SVC_PSA_SKIP:
return tfm_spm_partition_psa_skip((psa_handle_t)ctx[0], ctx[1],
(size_t)ctx[2]);
case TFM_SVC_PSA_WRITE:
tfm_spm_partition_psa_write((psa_handle_t)ctx[0], ctx[1],
(void *)ctx[2], (size_t)ctx[3]);
break;
case TFM_SVC_PSA_REPLY:
tfm_spm_partition_psa_reply((psa_handle_t)ctx[0], (psa_status_t)ctx[1]);
break;
case TFM_SVC_PSA_NOTIFY:
tfm_spm_partition_psa_notify((int32_t)ctx[0]);
break;
…略
如何与A核通信ns_agent_mailbox_entry
ns_agent_mailbox_entry
->boot_ns_core(); //启动A核
->tfm_inter_core_comm_init()
->tfm_spe_openamp_lib_init //OpenAMP以及MHU相关初始化
->tfm_dual_core_hal_init
->initialize_host_to_secure_enclave_mhu(); //初始化MHU 驱动
->mhu_v2_x_driver_init(&MHU1_SE_TO_HOST_DEV, MHU_REV_READ_FROM_HW)
initialize_secure_enclave_to_host_mhu(); //初始化MHU 驱动
->mhu_v2_x_driver_init(&MHU1_HOST_TO_SE_DEV, MHU_REV_READ_FROM_HW)
->tfm_to_openamp_init(callback_from_openamp, notify_request_from_openamp)
-> metal_init(&metal_params) //调用metal params库
-> metal_register_generic_device(&shm_device)
-> metal_device_open("generic", SHM_DEVICE_NAME, &device)
-> metal_device_io_region(device, 0)
-> virtqueue_allocate(VRING_SIZE)
-> rpmsg_virtio_init_shm_pool(&shpool, (void *)SHM_START_VIRT_ADDR, SHM_SIZE);
-> rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, io, &shpool)
->init_dual_core_psa_client_secure_lib()
->tfm_rpc_register_ops(&openamp_rpc_ops)
->psa_irq_enable(MAILBOX_SIGNAL)
->psa_irq_enable_svc
-> tfm_spm_partition_psa_irq_enable((psa_signal_t)ctx[0]) //使能MHU中断
-> signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK) //进入while(1)循环,等待来信号
-> tfm_rpc_client_call_handler() //处理RPC消息
MHU中断处理
所有从外部host发来的安全服务调用请求,都会从MHU中断处理函数这里开始:
HSE1_RECEIVER_COMBINED_IRQHandler
->spm_handle_interrupt(mbox_irq_info.p_pt, mbox_irq_info.p_ildi);
-> spm_assert_signal(p_pt, p_ildi->signal)
->thrd_wake_up(&partition->waitobj, partition->signals_asserted & partition->signals_waiting)
->thrd_set_state(p_sync_obj->owner, THRD_STATE_RUNNABLE)
-> tfm_arch_trigger_pendsv() //唤醒mailbox 线程,进入到 ns_agent_mailbox_entry
->ns_agent_mailbox_entry
->psa_eoi(MAILBOX_SIGNAL);
->tfm_rpc_client_call_handler()
-> rpc_ops.handle_req() // rpc_ops指向static const struct tfm_rpc_ops_t openamp_rpc_ops,而不是默认的 static struct tfm_rpc_ops_t rpc_ops
->mhu_v2_x_channel_clear(&MHU1_HOST_TO_SE_DEV, 0);
->NVIC_ClearPendingIRQ(HSE1_RECEIVER_COMBINED_IRQn);
rpc_ops是在如下这里初始化的的:
ns_agent_mailbox_entry
->tfm_inter_core_comm_init
->tfm_spe_openamp_lib_init
->tfm_to_openamp_init(callback_from_openamp, notify_request_from_openamp)
->init_dual_core_psa_client_secure_lib()
->tfm_rpc_register_ops(&openamp_rpc_ops)
-> rpc_ops.handle_req = tfm_to_openamp_notify
openamp_rpc_ops 定义在这里:
static const struct tfm_rpc_ops_t openamp_rpc_ops = {
.handle_req = tfm_to_openamp_notify, /* notify openamp for pendsv/irq
* received from the non-secure */
.reply = service_reply,
.get_caller_data = get_caller_private_data,
};
所以在mhu中断处理中,rpc_ops.handle_req() 将会调用到这里来:
rpc_ops.handle_req() // rpc_ops指向static const struct tfm_rpc_ops_t openamp_rpc_ops,而不是默认的 static struct tfm_rpc_ops_t rpc_ops
-> tfm_to_openamp_notify
->virtqueue_notification(vq[0])
-> vq->callback(vq)
Callback 在哪里赋值的呢?
tfm_spe_openamp_lib_init
->tfm_callback = cb;
->tfm_notify = notify
->tfm_to_openamp_init
->rpmsg_init_vdev(&rvdev, &vdev, ns_bind_cb, io, &shpool)
->rpmsg_init_vdev
->callback[0] = rpmsg_virtio_rx_callback //前面的 vq->callback(),实际上对应于这里的 rpmsg_virtio_rx_callback
->rpmsg_virtio_create_virtqueues
->virtio_create_virtqueues
->virtqueue_create(vdev, i, names[i], vring_alloc,
callbacks[i], vdev->func->notify,
vring_info->vq)
-> vq->callback = callback //将rpmsg_virtio_rx_callback 赋值给了 vq->callback
-> vq->notify = notify
在哪里绑定endpoint?
rpmsg_init_vdev中,会先注册一个name service的内置的匿名端点的endpoint:
rpmsg_init_vdev
->rpmsg_initialize_ept(&rdev->ns_ept, "NS",
RPMSG_NS_EPT_ADDR, RPMSG_NS_EPT_ADDR,
rpmsg_virtio_ns_callback, NULL); //初始化name service端点
-> ept->cb = rpmsg_virtio_ns_callback //给ept->cb赋值为endpoint_cb
->rpmsg_register_endpoint(rdev, &rdev->ns_ept); //挂入全局链表
当MHU收到name service消息后,rpmsg_virtio_rx_callback会调用rpmsg_get_endpoint,通过发送端在消息中写入的地址:RPMSG_NS_EPT_ADDR,就能找到 NS端点对应的endpoint
然后,会调用到它对应的的callback,rpmsg_virtio_ns_callback在这里调用后,会去创建普通的端点:
rpmsg_virtio_rx_callback
->ept->cb(ept, RPMSG_LOCATE_DATA(rp_hdr), rp_hdr->len, rp_hdr->src, ept->priv) //NS对应的cb在前面已经被过了,所以会进入到rpmsg_virtio_ns_callback
->rpmsg_virtio_ns_callback
-》rdev->ns_bind_cb(rdev, name, dest) //调用到rpmsg_init_vdev传入的ns_bind_cb
->ns_bind_cb()
-》rpmsg_create_ept(ep, rdev, name, RPMSG_ADDR_ANY, dest, endpoint_cb, rpmsg_service_unbind) //创建普通端点
-》rpmsg_initialize_ept(ept, name, addr, dest, cb, unbind_cb)
-》ept->cb = endpoint_cb //给ept->cb赋值为endpoint_cb
-》rpmsg_register_endpoint(rdev, ept) //注册普通端点
普通的消息,也会由MHU中断入口,进入到rpmsg_virtio_rx_callback, 只不过,此时,普通消息的端点已经在rpmsg_virtio_ns_callback中帮忙创建好了,所以,vq->callback(vq) 会调用到这里来:
rpmsg_virtio_rx_callback
->ept->cb(ept, RPMSG_LOCATE_DATA(rp_hdr), rp_hdr->len, rp_hdr->src, ept->priv)
-> endpoint_cb //在rdev->ns_bind_cb 中赋值
-> tfm_callback(data, len) //在 tfm_to_openamp_init 中,会给tfm_callback赋值
-> callback_from_openamp // Process call from the other core
-> register_msg_to_spe_and_verify(&priv, ns_msg, len) //对消息进行检查
-> check_msg(&s_map_entry->msg) //进行更进一步的复杂检查
-> deliver_msg_to_tfm_spe(priv)
-> prepare_params_for_psa_call(&spm_params, s_map_entry)
// params中有一个 handle,它代表要调用哪个服务,对于 ctypto来说,是#define TFM_CRYPTO_HANDLE (0x40000100U)
->fm_rpc_psa_call(&spm_params)
-> tfm_spm_client_psa_call(params->handle, PARAM_PACK(params->type, params->in_len, params->out_len), params->in_vec, params->out_vec)
-> tfm_spm_get_client_id(ns_caller)
->index = GET_INDEX_FROM_STATIC_HANDLE(handle)
-> service = GET_STATELESS_SERVICE(index)
-> sid = service->p_ldinf->sid //找到是哪种服务的ID,比如,PS, ITS, CRYPTO, ATTESTION
-> spm_fill_message(conn_handle, service, handle, type, client_id, invecs, in_num, outvecs, out_num, outptr)
-> backend_instance.messaging(service, conn_handle)
-> ipc_messaging //唤醒当前正在等待信号的secure partition,并且阻塞住当前线程,下一次调度时,将会进入正在等待信号的partition
->p_owner = service->partition; //得到要调用的服务对应的parttion
->signal = service->p_ldinf->signal
->thrd_wake_up(&p_owner->waitobj, (p_owner->signals_asserted & p_owner->signals_waiting)) //唤醒正在等待当前要调用的这个服务对应的partition
->thrd_set_state(p_sync_obj->owner, THRD_STATE_RUNNABLE); //设置为running ,下次调度会进入这个partition, 该partition会处理对应的信号
->tfm_arch_set_context_ret_code(p_sync_obj->owner->p_context_ctrl, ret_val)
向远程发送消息时,如果要通知对端的其他核,则会调用到这里来:
rpmsg_virtio_send_offchannel_nocopy
-》metal_io_block_write(io, metal_io_virt_to_offset(io, hdr), &rp_hdr, sizeof(rp_hdr)) //将要发送的数据 写入 SHM
-》virtqueue_get_buffer_length(rvdev->svq, idx)
-》rpmsg_virtio_enqueue_buffer(rvdev, hdr, buff_len, idx)
-》virtqueue_kick
-》vq_ring_notify(vq)
-》virtio_notify
-》tfm_notify
-》notify_request_from_openamp //通过MHU通知对端
->tfm_hal_notify_peer()
->dev = &MHU1_SE_TO_HOST_DEV //这里用到了 MHU DEV
->mhu_v2_x_channel_send(dev, MHU1_SEH_NOTIFY_CH, MHU1_SEH_NOTIFY_VAL) //给HOST发MHU消息
->mhu_v2_x_reset_access_request(dev)
virtio_notify定义在这里:
static struct virtio_dispatch dispatch = {
.get_status = virtio_get_status,
.set_status = virtio_set_status,
.get_features = virtio_get_features,
.notify = virtio_notify,
};
几个重要的partitons
(1) Ns agent
"entry_point": "ns_agent_mailbox_entry",
ns_agent_mailbox_entry
->boot_ns_core();
->LOG_DBGFMT("Enabling non-secure core...\r\n");
->tfm_hal_boot_ns_cpu(tfm_hal_get_ns_VTOR());
->tfm_hal_wait_for_ns_cpu_ready()
->tfm_inter_core_comm_init();
->psa_irq_enable(MAILBOX_SIGNAL)
->psa_wait(PSA_WAIT_ANY, PSA_BLOCK) //等待信号到来
->tfm_rpc_client_call_handler()
(2) Sp init
“entry_point”: “platform_sp_init”,
//流程如下:
platform_sp_init
->tfm_plat_init_nv_counter()
->psa_wait(PSA_WAIT_ANY, PSA_BLOCK) //等待信号到来
->platform_signal_handle(TFM_SP_PLATFORM_IOCTL_SIGNAL, platform_sp_ioctl_ipc)
->platform_sp_ioctl_ipc
->tfm_platform_hal_ioctl
->corstone1000_fwu_host_ack()
(3) Fwu(firmware update)
“entry_point”: “tfm_fwu_init”,
//流程如下:
tfm_fwu_init
->fwu_bootloader_init()
->psa_wait(PSA_WAIT_ANY, PSA_BLOCK) //等待信号到来
->fwu_signal_handle(TFM_FWU_INSTALL_SIGNAL, tfm_fwu_install_ipc)
-> tfm_fwu_install_ipc
->get_image_index(image_id, &image_index)
->tfm_internal_fwu_install(image_id, &dependency_id, &dependency_version)
(4) crypto
“entry_point”: “tfm_crypto_init”,
//流程如下:
tfm_crypto_init
->tfm_crypto_module_init()
->tfm_crypto_engine_init()
-> mbedtls_memory_buffer_alloc_init(mbedtls_mem_buf, TFM_CRYPTO_ENGINE_BUF_SIZE) //初始化crypto堆
->psa_crypto_init()
mbedtls_psa_random_init( &global_data.rng )
mbedtls_psa_random_seed( &global_data.rng )
psa_initialize_key_slots( )
psa_driver_wrapper_init( )
->tfm_crypto_ipc_handler()
->psa_wait(PSA_WAIT_ANY, PSA_BLOCK) //等待信号到来
->psa_get(TFM_CRYPTO_SIGNAL, &msg)
->status = tfm_crypto_parse_msg(&msg, &iov, &srv_id); //要调用的加解密函数的ID
->status = tfm_crypto_call_srv(&msg, &iov, srv_id); //调用到具体的加解密函数
->psa_reply(msg.handle, status);
Crypto的heap size定义如下:
set(CRYPTO_ENGINE_BUF_SIZE 0x4000 CACHE STRING "Heap size for the crypto backend")
所有的加解密API定义在这个数组中:
static const tfm_crypto_us_t sfid_func_table[TFM_CRYPTO_SID_MAX] = {
#define X(api_name) api_name,
LIST_TFM_CRYPTO_UNIFORM_SIGNATURE_API
#undef X
};
#define LIST_TFM_CRYPTO_UNIFORM_SIGNATURE_API \
X(tfm_crypto_get_key_attributes) \
X(tfm_crypto_reset_key_attributes) \
X(tfm_crypto_open_key) \
X(tfm_crypto_close_key) \
X(tfm_crypto_import_key) \
X(tfm_crypto_destroy_key) \
X(tfm_crypto_export_key) \
X(tfm_crypto_export_public_key) \
X(tfm_crypto_purge_key) \
X(tfm_crypto_copy_key) \
X(tfm_crypto_hash_compute) \
X(tfm_crypto_hash_compare) \
X(tfm_crypto_hash_setup) \
X(tfm_crypto_hash_update) \
X(tfm_crypto_hash_finish) \
X(tfm_crypto_hash_verify) \
X(tfm_crypto_hash_abort) \
X(tfm_crypto_hash_clone) \
X(tfm_crypto_mac_compute) \
X(tfm_crypto_mac_verify) \
X(tfm_crypto_mac_sign_setup) \
X(tfm_crypto_mac_verify_setup) \
X(tfm_crypto_mac_update) \
X(tfm_crypto_mac_sign_finish) \
X(tfm_crypto_mac_verify_finish) \
X(tfm_crypto_mac_abort) \
X(tfm_crypto_cipher_encrypt) \
X(tfm_crypto_cipher_decrypt) \
X(tfm_crypto_cipher_encrypt_setup) \
X(tfm_crypto_cipher_decrypt_setup) \
tfm_crypto_hash_compute在哪里定义的呢?
tfm_crypto_hash_compute
-》psa_hash_compute(alg, input, input_length, hash, hash_size, &out_vec[0].len)
又根据如下定义,可知psa_hash_compute 等价于 mbedcrypto__psa_hash_compute
#define psa_hash_compute PSA_FUNCTION_NAME(psa_hash_compute)
#define PSA_FUNCTION_NAME(x) mbedcrypto__ ## x
mbedcrypto__psa_hash_compute()这个接口,又是在哪里定义的呢?
git/mbedtls/library/psa_crypto.c
psa_status_t psa_hash_compute() // psa_hash_compute 通过 宏转换,变成 mbedcrypto__psa_hash_compute,所以,真实的函数名是:mbedcrypto__psa_hash_compute
->psa_driver_wrapper_hash_compute( alg, input, input_length, hash, hash_size, hash_length ) );
-> cc3xx_hash_compute(alg, input, input_length, hash, hash_size, hash_length) //如果定义了CC312,将会调用到这里来
->cc3xx_hash_setup(&operation, alg)
->cc3xx_hash_update(&operation, input, input_length)
->cc3xx_hash_finish(&operation, hash, hash_size, hash_length)
->cc3xx_hash_abort(&operation)
-> mbedtls_psa_hash_compute( alg, input, input_length, hash, hash_size, hash_length )
->mbedtls_psa_hash_setup( &operation, alg )
->mbedtls_sha256_init( &operation->ctx.sha256 )
->mbedtls_psa_hash_update( &operation, input, input_length ) //根据选择的加密硬件类型,或者 纯软件加密,决定后面的调用流程
->mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) //mbedtls纯软件方式
->mbedtls_sha_update_internal( ctx, input, ilen ) //用CC312硬件时
->dubhe_sha256_update(ctx, input, ilen) //用 ShanHai 硬件 时
->mbedtls_psa_hash_finish( &operation, hash, hash_size, hash_length )
->mbedtls_psa_hash_abort( &operation )
(5) ps
“entry_point”: “tfm_ps_req_mngr_init”,
//流程如下:
tfm_ps_req_mngr_init
-> tfm_ps_init() //ps FLASH相关的设置,已经在 its 的初始化过程中完成了
-> ps_system_prepare()
->psa_wait(PSA_WAIT_ANY, PSA_BLOCK) //等待信号到来
->ps_signal_handle(TFM_PROTECTED_STORAGE_SERVICE_SIGNAL)
ps所在的flash地址,是在这里赋值的:
init_fs_cfg
tfm_hal_ps_fs_info
->fs_info->flash_area_addr = TFM_HAL_PS_FLASH_AREA_ADDR;
->fs_info->flash_area_size = TFM_HAL_PS_FLASH_AREA_SIZE;
->fs_info->sectors_per_block = TFM_HAL_PS_SECTORS_PER_BLOCK;
(6) Proxy sp
“entry_point”: “psa_proxy_sp_init”,
(7) attest
“entry_point”: “attest_partition_init”,
7.7.8 its
“entry_point”: “tfm_its_req_mngr_init”,
//流程如下:
tfm_its_req_mngr_init
->tfm_its_init()
->init_fs_cfg()
->tfm_hal_its_fs_info(&its_fs_info)
->fs_info->flash_area_addr = TFM_HAL_ITS_FLASH_AREA_ADDR //(0x2000000 + 0x40000)
->its_flash_fs_init_ctx(&fs_ctx_its, &fs_cfg_its, &ITS_FLASH_OPS)
->its_flash_fs_prepare(&fs_ctx_its)
->psa_wait(PSA_WAIT_ANY, PSA_BLOCK) //等待信号到来
->its_signal_handle(TFM_INTERNAL_TRUSTED_STORAGE_SERVICE_SIGNAL)
->status = psa_get(signal, &msg)
->case TFM_ITS_SET: //设置 its
status = tfm_its_set_ipc();
psa_read(msg.handle, 0, &uid, sizeof(uid))
tfm_its_set(msg.client_id, uid, data_length, create_flags)
its_req_mngr_read(asset_data, write_size)
its_flash_fs_file_write
psa_reply(msg.handle, status);
break;
case TFM_ITS_GET: //读取 its
status = tfm_its_get_ipc();
psa_reply(msg.handle, status);
break;
case TFM_ITS_GET_INFO:
status = tfm_its_get_info_ipc();
psa_reply(msg.handle, status);
break;
case TFM_ITS_REMOVE:
status = tfm_its_remove_ipc();
psa_reply(msg.handle, status);