xref: /rk3399_ARM-atf/services/std_svc/drtm/drtm_main.c (revision bd6cc0b2388c52f2b232427be61ff52c042d724a)
1 /*
2  * Copyright (c) 2022 Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier:    BSD-3-Clause
5  *
6  * DRTM service
7  *
8  * Authors:
9  *	Lucian Paul-Trifu <lucian.paultrifu@gmail.com>
10  *	Brian Nezvadovitz <brinez@microsoft.com> 2021-02-01
11  */
12 
13 #include <stdint.h>
14 
15 #include <arch.h>
16 #include <arch_helpers.h>
17 #include <common/bl_common.h>
18 #include <common/debug.h>
19 #include <common/runtime_svc.h>
20 #include <drivers/auth/crypto_mod.h>
21 #include "drtm_main.h"
22 #include <lib/psci/psci_lib.h>
23 #include <lib/xlat_tables/xlat_tables_v2.h>
24 #include <plat/common/platform.h>
25 #include <services/drtm_svc.h>
26 #include <platform_def.h>
27 
28 /* Structure to store DRTM features specific to the platform. */
29 static drtm_features_t plat_drtm_features;
30 
31 /* DRTM-formatted memory map. */
32 static drtm_memory_region_descriptor_table_t *plat_drtm_mem_map;
33 
34 int drtm_setup(void)
35 {
36 	bool rc;
37 	const plat_drtm_tpm_features_t *plat_tpm_feat;
38 	const plat_drtm_dma_prot_features_t *plat_dma_prot_feat;
39 	uint64_t dlme_data_min_size;
40 
41 	INFO("DRTM service setup\n");
42 
43 	/* Read boot PE ID from MPIDR */
44 	plat_drtm_features.boot_pe_id = read_mpidr_el1() & MPIDR_AFFINITY_MASK;
45 
46 	rc = drtm_dma_prot_init();
47 	if (rc) {
48 		return INTERNAL_ERROR;
49 	}
50 
51 	/*
52 	 * initialise the platform supported crypto module that will
53 	 * be used by the DRTM-service to calculate hash of DRTM-
54 	 * implementation specific components
55 	 */
56 	crypto_mod_init();
57 
58 	/* Build DRTM-compatible address map. */
59 	plat_drtm_mem_map = drtm_build_address_map();
60 	if (plat_drtm_mem_map == NULL) {
61 		return INTERNAL_ERROR;
62 	}
63 
64 	/* Get DRTM features from platform hooks. */
65 	plat_tpm_feat = plat_drtm_get_tpm_features();
66 	if (plat_tpm_feat == NULL) {
67 		return INTERNAL_ERROR;
68 	}
69 
70 	plat_dma_prot_feat = plat_drtm_get_dma_prot_features();
71 	if (plat_dma_prot_feat == NULL) {
72 		return INTERNAL_ERROR;
73 	}
74 
75 	/*
76 	 * Add up minimum DLME data memory.
77 	 *
78 	 * For systems with complete DMA protection there is only one entry in
79 	 * the protected regions table.
80 	 */
81 	if (plat_dma_prot_feat->dma_protection_support ==
82 			ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_COMPLETE) {
83 		dlme_data_min_size =
84 			sizeof(drtm_memory_region_descriptor_table_t) +
85 			sizeof(drtm_mem_region_t);
86 	} else {
87 		/*
88 		 * TODO set protected regions table size based on platform DMA
89 		 * protection configuration
90 		 */
91 		panic();
92 	}
93 
94 	dlme_data_min_size += (drtm_get_address_map_size() +
95 			       PLAT_DRTM_EVENT_LOG_MAX_SIZE +
96 			       plat_drtm_get_tcb_hash_table_size() +
97 			       plat_drtm_get_imp_def_dlme_region_size());
98 
99 	dlme_data_min_size = page_align(dlme_data_min_size, UP)/PAGE_SIZE;
100 
101 	/* Fill out platform DRTM features structure */
102 	/* Only support default PCR schema (0x1) in this implementation. */
103 	ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(plat_drtm_features.tpm_features,
104 		ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_DEFAULT);
105 	ARM_DRTM_TPM_FEATURES_SET_TPM_HASH(plat_drtm_features.tpm_features,
106 		plat_tpm_feat->tpm_based_hash_support);
107 	ARM_DRTM_TPM_FEATURES_SET_FW_HASH(plat_drtm_features.tpm_features,
108 		plat_tpm_feat->firmware_hash_algorithm);
109 	ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(plat_drtm_features.minimum_memory_requirement,
110 		dlme_data_min_size);
111 	ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(plat_drtm_features.minimum_memory_requirement,
112 		plat_drtm_get_min_size_normal_world_dce());
113 	ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(plat_drtm_features.dma_prot_features,
114 		plat_dma_prot_feat->max_num_mem_prot_regions);
115 	ARM_DRTM_DMA_PROT_FEATURES_SET_DMA_SUPPORT(plat_drtm_features.dma_prot_features,
116 		plat_dma_prot_feat->dma_protection_support);
117 	ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(plat_drtm_features.tcb_hash_features,
118 		plat_drtm_get_tcb_hash_features());
119 
120 	return 0;
121 }
122 
123 static inline uint64_t drtm_features_tpm(void *ctx)
124 {
125 	SMC_RET2(ctx, 1ULL, /* TPM feature is supported */
126 		 plat_drtm_features.tpm_features);
127 }
128 
129 static inline uint64_t drtm_features_mem_req(void *ctx)
130 {
131 	SMC_RET2(ctx, 1ULL, /* memory req Feature is supported */
132 		 plat_drtm_features.minimum_memory_requirement);
133 }
134 
135 static inline uint64_t drtm_features_boot_pe_id(void *ctx)
136 {
137 	SMC_RET2(ctx, 1ULL, /* Boot PE feature is supported */
138 		 plat_drtm_features.boot_pe_id);
139 }
140 
141 static inline uint64_t drtm_features_dma_prot(void *ctx)
142 {
143 	SMC_RET2(ctx, 1ULL, /* DMA protection feature is supported */
144 		 plat_drtm_features.dma_prot_features);
145 }
146 
147 static inline uint64_t drtm_features_tcb_hashes(void *ctx)
148 {
149 	SMC_RET2(ctx, 1ULL, /* TCB hash feature is supported */
150 		 plat_drtm_features.tcb_hash_features);
151 }
152 
153 static enum drtm_retc drtm_dl_check_caller_el(void *ctx)
154 {
155 	uint64_t spsr_el3 = read_ctx_reg(get_el3state_ctx(ctx), CTX_SPSR_EL3);
156 	uint64_t dl_caller_el;
157 	uint64_t dl_caller_aarch;
158 
159 	dl_caller_el = spsr_el3 >> MODE_EL_SHIFT & MODE_EL_MASK;
160 	dl_caller_aarch = spsr_el3 >> MODE_RW_SHIFT & MODE_RW_MASK;
161 
162 	/* Caller's security state is checked from drtm_smc_handle function */
163 
164 	/* Caller can be NS-EL2/EL1 */
165 	if (dl_caller_el == MODE_EL3) {
166 		ERROR("DRTM: invalid launch from EL3\n");
167 		return DENIED;
168 	}
169 
170 	if (dl_caller_aarch != MODE_RW_64) {
171 		ERROR("DRTM: invalid launch from non-AArch64 execution state\n");
172 		return DENIED;
173 	}
174 
175 	return SUCCESS;
176 }
177 
178 static enum drtm_retc drtm_dl_check_cores(void)
179 {
180 	bool running_on_single_core;
181 	uint64_t this_pe_aff_value = read_mpidr_el1() & MPIDR_AFFINITY_MASK;
182 
183 	if (this_pe_aff_value != plat_drtm_features.boot_pe_id) {
184 		ERROR("DRTM: invalid launch on a non-boot PE\n");
185 		return DENIED;
186 	}
187 
188 	running_on_single_core = psci_is_last_on_cpu_safe();
189 	if (!running_on_single_core) {
190 		ERROR("DRTM: invalid launch due to non-boot PE not being turned off\n");
191 		return DENIED;
192 	}
193 
194 	return SUCCESS;
195 }
196 
197 static uint64_t drtm_dynamic_launch(uint64_t x1, void *handle)
198 {
199 	enum drtm_retc ret = SUCCESS;
200 
201 	/* Ensure that only boot PE is powered on */
202 	ret = drtm_dl_check_cores();
203 	if (ret != SUCCESS) {
204 		SMC_RET1(handle, ret);
205 	}
206 
207 	/*
208 	 * Ensure that execution state is AArch64 and the caller
209 	 * is highest non-secure exception level
210 	 */
211 	ret = drtm_dl_check_caller_el(handle);
212 	if (ret != SUCCESS) {
213 		SMC_RET1(handle, ret);
214 	}
215 
216 	SMC_RET1(handle, ret);
217 }
218 
219 uint64_t drtm_smc_handler(uint32_t smc_fid,
220 			  uint64_t x1,
221 			  uint64_t x2,
222 			  uint64_t x3,
223 			  uint64_t x4,
224 			  void *cookie,
225 			  void *handle,
226 			  uint64_t flags)
227 {
228 	/* Check that the SMC call is from the Normal World. */
229 	if (!is_caller_non_secure(flags)) {
230 		SMC_RET1(handle, NOT_SUPPORTED);
231 	}
232 
233 	switch (smc_fid) {
234 	case ARM_DRTM_SVC_VERSION:
235 		INFO("DRTM service handler: version\n");
236 		/* Return the version of current implementation */
237 		SMC_RET1(handle, ARM_DRTM_VERSION);
238 		break;	/* not reached */
239 
240 	case ARM_DRTM_SVC_FEATURES:
241 		if (((x1 >> ARM_DRTM_FUNC_SHIFT) & ARM_DRTM_FUNC_MASK) ==
242 		    ARM_DRTM_FUNC_ID) {
243 			/* Dispatch function-based queries. */
244 			switch (x1 & FUNCID_MASK) {
245 			case ARM_DRTM_SVC_VERSION:
246 				SMC_RET1(handle, SUCCESS);
247 				break;	/* not reached */
248 
249 			case ARM_DRTM_SVC_FEATURES:
250 				SMC_RET1(handle, SUCCESS);
251 				break;	/* not reached */
252 
253 			case ARM_DRTM_SVC_UNPROTECT_MEM:
254 				SMC_RET1(handle, SUCCESS);
255 				break;	/* not reached */
256 
257 			case ARM_DRTM_SVC_DYNAMIC_LAUNCH:
258 				SMC_RET1(handle, SUCCESS);
259 				break;	/* not reached */
260 
261 			case ARM_DRTM_SVC_CLOSE_LOCALITY:
262 				WARN("ARM_DRTM_SVC_CLOSE_LOCALITY feature %s",
263 				     "is not supported\n");
264 				SMC_RET1(handle, NOT_SUPPORTED);
265 				break;	/* not reached */
266 
267 			case ARM_DRTM_SVC_GET_ERROR:
268 				SMC_RET1(handle, SUCCESS);
269 				break;	/* not reached */
270 
271 			case ARM_DRTM_SVC_SET_ERROR:
272 				SMC_RET1(handle, SUCCESS);
273 				break;	/* not reached */
274 
275 			case ARM_DRTM_SVC_SET_TCB_HASH:
276 				WARN("ARM_DRTM_SVC_TCB_HASH feature %s",
277 				     "is not supported\n");
278 				SMC_RET1(handle, NOT_SUPPORTED);
279 				break;	/* not reached */
280 
281 			case ARM_DRTM_SVC_LOCK_TCB_HASH:
282 				WARN("ARM_DRTM_SVC_LOCK_TCB_HASH feature %s",
283 				     "is not supported\n");
284 				SMC_RET1(handle, NOT_SUPPORTED);
285 				break;	/* not reached */
286 
287 			default:
288 				ERROR("Unknown DRTM service function\n");
289 				SMC_RET1(handle, NOT_SUPPORTED);
290 				break;	/* not reached */
291 			}
292 		} else {
293 			/* Dispatch feature-based queries. */
294 			switch (x1 & ARM_DRTM_FEAT_ID_MASK) {
295 			case ARM_DRTM_FEATURES_TPM:
296 				INFO("++ DRTM service handler: TPM features\n");
297 				return drtm_features_tpm(handle);
298 				break;	/* not reached */
299 
300 			case ARM_DRTM_FEATURES_MEM_REQ:
301 				INFO("++ DRTM service handler: Min. mem."
302 				     " requirement features\n");
303 				return drtm_features_mem_req(handle);
304 				break;	/* not reached */
305 
306 			case ARM_DRTM_FEATURES_DMA_PROT:
307 				INFO("++ DRTM service handler: "
308 				     "DMA protection features\n");
309 				return drtm_features_dma_prot(handle);
310 				break;	/* not reached */
311 
312 			case ARM_DRTM_FEATURES_BOOT_PE_ID:
313 				INFO("++ DRTM service handler: "
314 				     "Boot PE ID features\n");
315 				return drtm_features_boot_pe_id(handle);
316 				break;	/* not reached */
317 
318 			case ARM_DRTM_FEATURES_TCB_HASHES:
319 				INFO("++ DRTM service handler: "
320 				     "TCB-hashes features\n");
321 				return drtm_features_tcb_hashes(handle);
322 				break;	/* not reached */
323 
324 			default:
325 				ERROR("Unknown ARM DRTM service feature\n");
326 				SMC_RET1(handle, NOT_SUPPORTED);
327 				break;	/* not reached */
328 			}
329 		}
330 
331 	case ARM_DRTM_SVC_UNPROTECT_MEM:
332 		INFO("DRTM service handler: unprotect mem\n");
333 		SMC_RET1(handle, SMC_OK);
334 		break;	/* not reached */
335 
336 	case ARM_DRTM_SVC_DYNAMIC_LAUNCH:
337 		INFO("DRTM service handler: dynamic launch\n");
338 		return drtm_dynamic_launch(x1, handle);
339 		break;	/* not reached */
340 
341 	case ARM_DRTM_SVC_CLOSE_LOCALITY:
342 		WARN("DRTM service handler: close locality %s\n",
343 		     "is not supported");
344 		SMC_RET1(handle, NOT_SUPPORTED);
345 		break;	/* not reached */
346 
347 	case ARM_DRTM_SVC_GET_ERROR:
348 		INFO("DRTM service handler: get error\n");
349 		SMC_RET2(handle, SMC_OK, 0);
350 		break;	/* not reached */
351 
352 	case ARM_DRTM_SVC_SET_ERROR:
353 		INFO("DRTM service handler: set error\n");
354 		SMC_RET1(handle, SMC_OK);
355 		break;	/* not reached */
356 
357 	case ARM_DRTM_SVC_SET_TCB_HASH:
358 		WARN("DRTM service handler: set TCB hash %s\n",
359 		     "is not supported");
360 		SMC_RET1(handle, NOT_SUPPORTED);
361 		break;  /* not reached */
362 
363 	case ARM_DRTM_SVC_LOCK_TCB_HASH:
364 		WARN("DRTM service handler: lock TCB hash %s\n",
365 		     "is not supported");
366 		SMC_RET1(handle, NOT_SUPPORTED);
367 		break;  /* not reached */
368 
369 	default:
370 		ERROR("Unknown DRTM service function: 0x%x\n", smc_fid);
371 		SMC_RET1(handle, SMC_UNK);
372 		break;	/* not reached */
373 	}
374 
375 	/* not reached */
376 	SMC_RET1(handle, SMC_UNK);
377 }
378