blob: e102a8a51037cd032bf71fc62abf915936392328 [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 Peng43160d52022-02-11 13:35:56 +080011#include "runtime_defs.h"
Kevin Pengb288c522021-09-26 16:18:23 +080012#include "tfm_hal_platform.h"
Ken Liuf39d8eb2021-10-07 12:55:33 +080013#include "ffm/backend.h"
14#include "load/partition_defs.h"
15#include "load/service_defs.h"
16#include "load/spm_load_api.h"
17#include "psa/error.h"
18#include "psa/service.h"
19#include "spm_ipc.h"
20
21/* SFN Partition state */
22#define SFN_PARTITION_STATE_NOT_INITED 0
23#define SFN_PARTITION_STATE_INITED 1
24
Ken Liuf39d8eb2021-10-07 12:55:33 +080025/* Declare the global component list */
26struct partition_head_t partition_listhead;
27
Ken Liuf39d8eb2021-10-07 12:55:33 +080028/*
29 * Send message and wake up the SP who is waiting on message queue, block the
30 * current component state and activate the next component.
31 */
32static psa_status_t sfn_messaging(struct service_t *service,
Mingyang Suna09adda2022-02-16 18:11:33 +080033 struct conn_handle_t *handle)
Ken Liuf39d8eb2021-10-07 12:55:33 +080034{
35 struct partition_t *p_target;
36 psa_status_t status;
37
Mingyang Suna09adda2022-02-16 18:11:33 +080038 if (!handle || !service || !service->p_ldinf || !service->partition) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +080039 return PSA_ERROR_PROGRAMMER_ERROR;
Ken Liuf39d8eb2021-10-07 12:55:33 +080040 }
41
Mingyang Suna09adda2022-02-16 18:11:33 +080042 handle->sfn_magic = TFM_MSG_MAGIC_SFN;
Ken Liuf39d8eb2021-10-07 12:55:33 +080043 p_target = service->partition;
Mingyang Suna09adda2022-02-16 18:11:33 +080044 p_target->p_handles = handle;
Ken Liuf39d8eb2021-10-07 12:55:33 +080045
46 SET_CURRENT_COMPONENT(p_target);
47
48 if (p_target->state == SFN_PARTITION_STATE_NOT_INITED) {
49 if (p_target->p_ldinf->entry != 0) {
50 status = ((sfn_init_fn_t)p_target->p_ldinf->entry)();
51 /* Negative value indicates errors. */
52 if (status < PSA_SUCCESS) {
Mingyang Sunbb4a42a2021-12-14 15:18:52 +080053 return PSA_ERROR_PROGRAMMER_ERROR;
Ken Liuf39d8eb2021-10-07 12:55:33 +080054 }
55 }
56 p_target->state = SFN_PARTITION_STATE_INITED;
57 }
58
Mingyang Suna09adda2022-02-16 18:11:33 +080059 status = ((service_fn_t)service->p_ldinf->sfn)(&handle->msg);
Ken Liuf39d8eb2021-10-07 12:55:33 +080060
61 return status;
62}
63
Mingyang Suna09adda2022-02-16 18:11:33 +080064static psa_status_t sfn_replying(struct conn_handle_t *handle, int32_t status)
Ken Liuf39d8eb2021-10-07 12:55:33 +080065{
Mingyang Suna09adda2022-02-16 18:11:33 +080066 SET_CURRENT_COMPONENT(handle->p_client);
Ken Liuf39d8eb2021-10-07 12:55:33 +080067
68 /*
69 * Returning a value here is necessary, because 'psa_reply' is absent
70 * for SFN clients, the 'reply' method is performed by SPM internally
71 * when SFN case, to forward the 'status' to the caller.
72 *
73 * For example:
74 * 'status' MAY contain a 'psa_handle_t' returned by SPM 'connect' and
75 * SPM needs to 'reply' it back to the caller. Treat 'psa_handle_t' value
76 * as SPM specific return value and represnent it as 'psa_status_t'.
77 */
78 return status;
79}
80
Ken Liuef229a22022-02-11 11:15:43 +080081static void spm_thread_fn(void)
Ken Liuf39d8eb2021-10-07 12:55:33 +080082{
83 struct partition_t *p_part, *p_curr;
84
85 p_curr = GET_CURRENT_COMPONENT();
86 /* Call partition initialization routine one by one. */
Ken Liu5a28da32022-01-19 14:37:05 +080087 UNI_LIST_FOREACH(p_part, PARTITION_LIST_ADDR, next) {
Kevin Peng56c571e2022-01-10 14:06:05 +080088 if (IS_PARTITION_IPC_MODEL(p_part->p_ldinf)) {
Ken Liuf39d8eb2021-10-07 12:55:33 +080089 continue;
90 }
91
92 if (p_part->state == SFN_PARTITION_STATE_INITED) {
93 continue;
94 }
95
96 SET_CURRENT_COMPONENT(p_part);
97
98 if (p_part->p_ldinf->entry != 0) {
99 if (((sfn_init_fn_t)p_part->p_ldinf->entry)() < PSA_SUCCESS) {
100 tfm_core_panic();
101 }
102 }
103
104 p_part->state = SFN_PARTITION_STATE_INITED;
105 }
106
107 SET_CURRENT_COMPONENT(p_curr);
Ken Liuef229a22022-02-11 11:15:43 +0800108}
Ken Liuf39d8eb2021-10-07 12:55:33 +0800109
Ken Liuef229a22022-02-11 11:15:43 +0800110/* Parameters are treated as assuredly */
111void sfn_comp_init_assuredly(struct partition_t *p_pt, uint32_t service_set)
112{
113 const struct partition_load_info_t *p_pldi = p_pt->p_ldinf;
Ken Liuf39d8eb2021-10-07 12:55:33 +0800114
Ken Liuef229a22022-02-11 11:15:43 +0800115 p_pt->p_handles = NULL;
116 p_pt->state = SFN_PARTITION_STATE_NOT_INITED;
117
118 THRD_SYNC_INIT(&p_pt->waitobj);
119
120 ARCH_CTXCTRL_INIT(&p_pt->ctx_ctrl,
121 LOAD_ALLOCED_STACK_ADDR(p_pldi),
122 p_pldi->stack_size);
123
124 /*
125 * Built-in partitions still have thread instances: NS Agent (TZ) and
126 * IDLE partition, and NS Agent (TZ) needs to be specific cared here.
127 */
128 if (p_pldi->pid == TFM_SP_NON_SECURE_ID) {
129 THRD_INIT(&p_pt->thrd, &p_pt->ctx_ctrl,
130 TO_THREAD_PRIORITY(PARTITION_PRIORITY(p_pldi->flags)));
131
132 thrd_start(&p_pt->thrd,
133 POSITION_TO_ENTRY(spm_thread_fn, thrd_fn_t),
134 POSITION_TO_ENTRY(p_pldi->entry, thrd_fn_t));
135 }
Ken Liuf39d8eb2021-10-07 12:55:33 +0800136}
137
138uint32_t sfn_system_run(void)
139{
Ken Liuf39d8eb2021-10-07 12:55:33 +0800140 return thrd_start_scheduler(&CURRENT_THREAD);
141}
142
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800143static psa_signal_t sfn_wait(struct partition_t *p_pt, psa_signal_t signal_mask)
Kevin Pengdef92de2021-11-10 16:14:48 +0800144{
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800145 while (!(p_pt->signals_asserted & signal_mask))
Kevin Pengdef92de2021-11-10 16:14:48 +0800146 ;
147
Mingyang Sun5c9529f2022-03-15 17:51:56 +0800148 return p_pt->signals_asserted & signal_mask;
Kevin Pengdef92de2021-11-10 16:14:48 +0800149}
150
151static void sfn_wake_up(struct partition_t *p_pt, psa_signal_t signals)
152{
153 (void)p_pt;
154 (void)signals;
155}
156
Ken Liuf39d8eb2021-10-07 12:55:33 +0800157const struct backend_ops_t backend_instance = {
158 .comp_init_assuredly = sfn_comp_init_assuredly,
159 .system_run = sfn_system_run,
160 .messaging = sfn_messaging,
Kevin Pengdef92de2021-11-10 16:14:48 +0800161 .replying = sfn_replying,
162 .wait = sfn_wait,
163 .wake_up = sfn_wake_up,
Ken Liuf39d8eb2021-10-07 12:55:33 +0800164};