1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2020-2021, Arm Limited. 4 */ 5 #include <crypto/crypto.h> 6 #include <initcall.h> 7 #include <kernel/embedded_ts.h> 8 #include <kernel/ldelf_loader.h> 9 #include <kernel/secure_partition.h> 10 #include <kernel/thread_spmc.h> 11 #include <kernel/ts_store.h> 12 #include <ldelf.h> 13 #include <mm/core_mmu.h> 14 #include <mm/fobj.h> 15 #include <mm/mobj.h> 16 #include <mm/vm.h> 17 #include <optee_ffa.h> 18 #include <stdio.h> 19 #include <string.h> 20 #include <tee_api_types.h> 21 #include <trace.h> 22 #include <types_ext.h> 23 #include <utee_defines.h> 24 #include <util.h> 25 #include <zlib.h> 26 27 static const struct ts_ops *_sp_ops; 28 29 /* List that holds all of the loaded SP's */ 30 static struct sp_sessions_head open_sp_sessions = 31 TAILQ_HEAD_INITIALIZER(open_sp_sessions); 32 33 static const struct ts_ops sp_ops __rodata_unpaged = { 34 }; 35 36 static const struct embedded_ts *find_secure_partition(const TEE_UUID *uuid) 37 { 38 const struct embedded_ts *sp = NULL; 39 40 for_each_secure_partition(sp) { 41 if (!memcmp(&sp->uuid, uuid, sizeof(*uuid))) 42 return sp; 43 } 44 return NULL; 45 } 46 47 bool is_sp_ctx(struct ts_ctx *ctx) 48 { 49 return ctx && (ctx->ops == _sp_ops); 50 } 51 52 static void set_sp_ctx_ops(struct ts_ctx *ctx) 53 { 54 ctx->ops = _sp_ops; 55 } 56 57 struct sp_session *sp_get_session(uint32_t session_id) 58 { 59 struct sp_session *s = NULL; 60 61 TAILQ_FOREACH(s, &open_sp_sessions, link) { 62 if (s->endpoint_id == session_id) 63 return s; 64 } 65 66 return NULL; 67 } 68 69 static void sp_init_info(struct sp_ctx *ctx) 70 { 71 struct sp_ffa_init_info *info = NULL; 72 73 ctx->uctx.stack_ptr -= ROUNDUP(sizeof(*info), STACK_ALIGNMENT); 74 75 ctx->sp_regs.x[0] = (uintptr_t)ctx->uctx.stack_ptr; 76 info = (struct sp_ffa_init_info *)ctx->uctx.stack_ptr; 77 78 info->magic = 0; 79 info->count = 0; 80 } 81 82 static uint16_t new_session_id(struct sp_sessions_head *open_sessions) 83 { 84 struct sp_session *last = NULL; 85 uint16_t id = SPMC_ENDPOINT_ID + 1; 86 87 last = TAILQ_LAST(open_sessions, sp_sessions_head); 88 if (last) 89 id = last->endpoint_id + 1; 90 91 assert(id > SPMC_ENDPOINT_ID); 92 return id; 93 } 94 95 static TEE_Result sp_create_ctx(const TEE_UUID *uuid, struct sp_session *s) 96 { 97 TEE_Result res = TEE_SUCCESS; 98 struct sp_ctx *spc = NULL; 99 100 /* Register context */ 101 spc = calloc(1, sizeof(struct sp_ctx)); 102 if (!spc) 103 return TEE_ERROR_OUT_OF_MEMORY; 104 105 spc->uctx.ts_ctx = &spc->ts_ctx; 106 spc->open_session = s; 107 s->ts_sess.ctx = &spc->ts_ctx; 108 spc->ts_ctx.uuid = *uuid; 109 110 res = vm_info_init(&spc->uctx); 111 if (res) 112 goto err; 113 114 set_sp_ctx_ops(&spc->ts_ctx); 115 116 return TEE_SUCCESS; 117 118 err: 119 free(spc); 120 return res; 121 } 122 123 static TEE_Result sp_create_session(struct sp_sessions_head *open_sessions, 124 const TEE_UUID *uuid, 125 struct sp_session **sess) 126 { 127 TEE_Result res = TEE_SUCCESS; 128 struct sp_session *s = calloc(1, sizeof(struct sp_session)); 129 130 if (!s) 131 return TEE_ERROR_OUT_OF_MEMORY; 132 133 s->endpoint_id = new_session_id(open_sessions); 134 if (!s->endpoint_id) { 135 res = TEE_ERROR_OVERFLOW; 136 goto err; 137 } 138 139 DMSG("Loading Secure Partition %pUl", (void *)uuid); 140 res = sp_create_ctx(uuid, s); 141 if (res) 142 goto err; 143 144 TAILQ_INSERT_TAIL(open_sessions, s, link); 145 *sess = s; 146 return TEE_SUCCESS; 147 148 err: 149 free(s); 150 return res; 151 } 152 153 static TEE_Result sp_init_set_registers(struct sp_ctx *ctx) 154 { 155 struct thread_ctx_regs *sp_regs = &ctx->sp_regs; 156 uint64_t x0 = sp_regs->x[0]; 157 158 /* Clear all addresses except x0, x0 contains the info address. */ 159 memset(sp_regs, 0, sizeof(*sp_regs)); 160 sp_regs->sp = ctx->uctx.stack_ptr; 161 sp_regs->x[0] = x0; 162 sp_regs->pc = ctx->uctx.entry_func; 163 164 return TEE_SUCCESS; 165 } 166 167 static TEE_Result sp_open_session(struct sp_session **sess, 168 struct sp_sessions_head *open_sessions, 169 const TEE_UUID *uuid) 170 { 171 TEE_Result res = TEE_SUCCESS; 172 struct sp_session *s = NULL; 173 struct sp_ctx *ctx = NULL; 174 175 if (!find_secure_partition(uuid)) 176 return TEE_ERROR_ITEM_NOT_FOUND; 177 178 res = sp_create_session(open_sessions, uuid, &s); 179 if (res != TEE_SUCCESS) { 180 DMSG("sp_create_session failed %#"PRIx32, res); 181 return res; 182 } 183 184 ctx = to_sp_ctx(s->ts_sess.ctx); 185 assert(ctx); 186 if (!ctx) 187 return TEE_ERROR_TARGET_DEAD; 188 *sess = s; 189 190 ts_push_current_session(&s->ts_sess); 191 /* Load the SP using ldelf. */ 192 ldelf_load_ldelf(&ctx->uctx); 193 res = ldelf_init_with_ldelf(&s->ts_sess, &ctx->uctx); 194 195 if (res != TEE_SUCCESS) { 196 EMSG("Failed. loading SP using ldelf %#"PRIx32, res); 197 ts_pop_current_session(); 198 return TEE_ERROR_TARGET_DEAD; 199 } 200 201 /* Make the SP ready for its first run */ 202 s->state = sp_idle; 203 s->caller_id = 0; 204 sp_init_info(ctx); 205 sp_init_set_registers(ctx); 206 ts_pop_current_session(); 207 208 return TEE_SUCCESS; 209 } 210 211 static TEE_Result sp_init_uuid(const TEE_UUID *uuid) 212 { 213 TEE_Result res = TEE_SUCCESS; 214 struct sp_session *sess = NULL; 215 216 res = sp_open_session(&sess, 217 &open_sp_sessions, 218 uuid); 219 if (res) 220 return res; 221 222 return res; 223 } 224 225 static TEE_Result sp_init_all(void) 226 { 227 TEE_Result res = TEE_SUCCESS; 228 const struct embedded_ts *sp = NULL; 229 char __maybe_unused msg[60] = { '\0', }; 230 231 _sp_ops = &sp_ops; 232 233 for_each_secure_partition(sp) { 234 if (sp->uncompressed_size) 235 snprintf(msg, sizeof(msg), 236 " (compressed, uncompressed %u)", 237 sp->uncompressed_size); 238 else 239 msg[0] = '\0'; 240 DMSG("SP %pUl size %u%s", (void *)&sp->uuid, sp->size, msg); 241 242 res = sp_init_uuid(&sp->uuid); 243 244 if (res != TEE_SUCCESS) { 245 EMSG("Failed initializing SP(%pUl) err:%#"PRIx32, 246 &sp->uuid, res); 247 if (!IS_ENABLED(CFG_SP_SKIP_FAILED)) 248 panic(); 249 } 250 } 251 252 return TEE_SUCCESS; 253 } 254 255 boot_final(sp_init_all); 256 257 static TEE_Result secure_partition_open(const TEE_UUID *uuid, 258 struct ts_store_handle **h) 259 { 260 return emb_ts_open(uuid, h, find_secure_partition); 261 } 262 263 REGISTER_SP_STORE(2) = { 264 .description = "SP store", 265 .open = secure_partition_open, 266 .get_size = emb_ts_get_size, 267 .get_tag = emb_ts_get_tag, 268 .read = emb_ts_read, 269 .close = emb_ts_close, 270 }; 271