blob: ab427b29422f90326b2bf5bb7c5b466bf85313dc [file] [log] [blame]
Ken Liuf39d8eb2021-10-07 12:55:33 +08001/*
Mingyang Sunbb4a42a2021-12-14 15:18:52 +08002 * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
Ken Liuf39d8eb2021-10-07 12:55:33 +08003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include <stdint.h>
9#include "compiler_ext_defs.h"
10#include "current.h"
Kevin Pengb288c522021-09-26 16:18:23 +080011#include "tfm_hal_platform.h"
Ken Liuf39d8eb2021-10-07 12:55:33 +080012#include "ffm/backend.h"
13#include "load/partition_defs.h"
14#include "load/service_defs.h"
15#include "load/spm_load_api.h"
16#include "psa/error.h"
17#include "psa/service.h"
18#include "spm_ipc.h"
19
20/* SFN Partition state */
21#define SFN_PARTITION_STATE_NOT_INITED 0
22#define SFN_PARTITION_STATE_INITED 1
23
24typedef psa_status_t (*service_fn_t)(psa_msg_t *msg);
25typedef psa_status_t (*sfn_init_fn_t)(void);
26
27/* Declare the global component list */
28struct partition_head_t partition_listhead;
29
30/* TODO: To be checked with the RPC design. */
31static uintptr_t spm_stack_limit;
32static uintptr_t spm_stack_base;
33
34/*
35 * Send message and wake up the SP who is waiting on message queue, block the
36 * current component state and activate the next component.
37 */
38static psa_status_t sfn_messaging(struct service_t *service,
Ken Liu0bed7e02022-02-10 12:38:07 +080039 struct conn_handle_t *hdl)
Ken Liuf39d8eb2021-10-07 12:55:33 +080040{
41 struct partition_t *p_target;
42 psa_status_t status;
43
Ken Liu0bed7e02022-02-10 12:38:07 +080044 if (!hdl || !service || !service->p_ldinf || !service->partition) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +080045 return PSA_ERROR_PROGRAMMER_ERROR;
Ken Liuf39d8eb2021-10-07 12:55:33 +080046 }
47
Ken Liu0bed7e02022-02-10 12:38:07 +080048 hdl->sfn_magic = TFM_MSG_MAGIC_SFN;
Ken Liuf39d8eb2021-10-07 12:55:33 +080049 p_target = service->partition;
Ken Liu0bed7e02022-02-10 12:38:07 +080050 p_target->p_handles = hdl;
Ken Liuf39d8eb2021-10-07 12:55:33 +080051
52 SET_CURRENT_COMPONENT(p_target);
53
54 if (p_target->state == SFN_PARTITION_STATE_NOT_INITED) {
55 if (p_target->p_ldinf->entry != 0) {
56 status = ((sfn_init_fn_t)p_target->p_ldinf->entry)();
57 /* Negative value indicates errors. */
58 if (status < PSA_SUCCESS) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +080059 return PSA_ERROR_PROGRAMMER_ERROR;
Ken Liuf39d8eb2021-10-07 12:55:33 +080060 }
61 }
62 p_target->state = SFN_PARTITION_STATE_INITED;
63 }
64
Ken Liu0bed7e02022-02-10 12:38:07 +080065 status = ((service_fn_t)service->p_ldinf->sfn)(&hdl->msg);
Ken Liuf39d8eb2021-10-07 12:55:33 +080066
67 return status;
68}
69
Ken Liu0bed7e02022-02-10 12:38:07 +080070static int32_t sfn_replying(struct conn_handle_t *hdl, int32_t status)
Ken Liuf39d8eb2021-10-07 12:55:33 +080071{
Ken Liu0bed7e02022-02-10 12:38:07 +080072 SET_CURRENT_COMPONENT(hdl->p_client);
Ken Liuf39d8eb2021-10-07 12:55:33 +080073
74 /*
75 * Returning a value here is necessary, because 'psa_reply' is absent
76 * for SFN clients, the 'reply' method is performed by SPM internally
77 * when SFN case, to forward the 'status' to the caller.
78 *
79 * For example:
80 * 'status' MAY contain a 'psa_handle_t' returned by SPM 'connect' and
81 * SPM needs to 'reply' it back to the caller. Treat 'psa_handle_t' value
82 * as SPM specific return value and represnent it as 'psa_status_t'.
83 */
84 return status;
85}
86
87/* Parameters are treated as assuredly */
88void sfn_comp_init_assuredly(struct partition_t *p_pt, uint32_t service_set)
89{
90 const struct partition_load_info_t *p_pldi = p_pt->p_ldinf;
91
Ken Liu0bed7e02022-02-10 12:38:07 +080092 p_pt->p_handles = NULL;
Ken Liuf39d8eb2021-10-07 12:55:33 +080093 p_pt->state = SFN_PARTITION_STATE_NOT_INITED;
94
95 THRD_SYNC_INIT(&p_pt->waitobj);
96
97 /*
98 * Built-in partitions still have thread instances: NS Agent (TZ) and
99 * IDLE partition, and NS Agent (TZ) needs to be specific cared here.
100 */
Kevin Peng56c571e2022-01-10 14:06:05 +0800101 if (IS_PARTITION_IPC_MODEL(p_pldi)) {
Ken Liuf39d8eb2021-10-07 12:55:33 +0800102 THRD_INIT(&p_pt->thrd, &p_pt->ctx_ctrl,
103 TO_THREAD_PRIORITY(PARTITION_PRIORITY(p_pldi->flags)));
104
105 thrd_start(&p_pt->thrd,
106 POSITION_TO_ENTRY(p_pldi->entry, thrd_fn_t),
Summer Qin95444822022-01-27 11:22:00 +0800107 NULL,
Ken Liuf39d8eb2021-10-07 12:55:33 +0800108 LOAD_ALLOCED_STACK_ADDR(p_pldi),
109 LOAD_ALLOCED_STACK_ADDR(p_pldi) + p_pldi->stack_size);
110
111 /* SPM reuses the ns agent stack, use once only at initialization. */
Ken Liu897e8f12022-02-10 03:21:17 +0100112 if (p_pldi->pid == TFM_SP_NON_SECURE_ID) {
Ken Liuf39d8eb2021-10-07 12:55:33 +0800113 spm_stack_limit = p_pt->ctx_ctrl.sp_limit;
114 spm_stack_base = p_pt->ctx_ctrl.sp;
115 }
116 }
117
118 (void)service_set;
119}
120
121static void spm_thread_fn(void *p)
122{
123 struct partition_t *p_part, *p_curr;
124
125 p_curr = GET_CURRENT_COMPONENT();
126 /* Call partition initialization routine one by one. */
Ken Liu5a28da32022-01-19 14:37:05 +0800127 UNI_LIST_FOREACH(p_part, PARTITION_LIST_ADDR, next) {
Kevin Peng56c571e2022-01-10 14:06:05 +0800128 if (IS_PARTITION_IPC_MODEL(p_part->p_ldinf)) {
Ken Liuf39d8eb2021-10-07 12:55:33 +0800129 continue;
130 }
131
132 if (p_part->state == SFN_PARTITION_STATE_INITED) {
133 continue;
134 }
135
136 SET_CURRENT_COMPONENT(p_part);
137
138 if (p_part->p_ldinf->entry != 0) {
139 if (((sfn_init_fn_t)p_part->p_ldinf->entry)() < PSA_SUCCESS) {
140 tfm_core_panic();
141 }
142 }
143
144 p_part->state = SFN_PARTITION_STATE_INITED;
145 }
146
147 SET_CURRENT_COMPONENT(p_curr);
148
149 thrd_set_state(CURRENT_THREAD, THRD_STATE_DETACH);
150
151 tfm_arch_trigger_pendsv();
152}
153
154uint32_t sfn_system_run(void)
155{
156 struct thread_t *p_thrd = (struct thread_t *)spm_stack_limit;
157 struct context_ctrl_t *p_ctxctrl = (struct context_ctrl_t *)(p_thrd + 1);
158 uintptr_t sp_limit = (((uintptr_t)(p_ctxctrl + 1)) + 7) & ~0x7;
159 uintptr_t sp_base = spm_stack_base;
160
161 THRD_INIT(p_thrd, p_ctxctrl, THRD_PRIOR_HIGHEST);
162 thrd_start(p_thrd, spm_thread_fn, NULL, sp_limit, sp_base);
163
164 return thrd_start_scheduler(&CURRENT_THREAD);
165}
166
167const struct backend_ops_t backend_instance = {
168 .comp_init_assuredly = sfn_comp_init_assuredly,
169 .system_run = sfn_system_run,
170 .messaging = sfn_messaging,
171 .replying = sfn_replying
172};