xref: /rk3399_ARM-atf/services/std_svc/drtm/drtm_main.c (revision e9467afb2d483ccec8f816902624d848e8f21d86)
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/xlat_tables/xlat_tables_v2.h>
23 #include <plat/common/platform.h>
24 #include <services/drtm_svc.h>
25 #include <platform_def.h>
26 
27 /* Structure to store DRTM features specific to the platform. */
28 static drtm_features_t plat_drtm_features;
29 
30 /* DRTM-formatted memory map. */
31 static drtm_memory_region_descriptor_table_t *plat_drtm_mem_map;
32 
33 int drtm_setup(void)
34 {
35 	bool rc;
36 	const plat_drtm_tpm_features_t *plat_tpm_feat;
37 	const plat_drtm_dma_prot_features_t *plat_dma_prot_feat;
38 	uint64_t dlme_data_min_size;
39 
40 	INFO("DRTM service setup\n");
41 
42 	/* Read boot PE ID from MPIDR */
43 	plat_drtm_features.boot_pe_id = read_mpidr_el1() & MPIDR_AFFINITY_MASK;
44 
45 	rc = drtm_dma_prot_init();
46 	if (rc) {
47 		return INTERNAL_ERROR;
48 	}
49 
50 	/*
51 	 * initialise the platform supported crypto module that will
52 	 * be used by the DRTM-service to calculate hash of DRTM-
53 	 * implementation specific components
54 	 */
55 	crypto_mod_init();
56 
57 	/* Build DRTM-compatible address map. */
58 	plat_drtm_mem_map = drtm_build_address_map();
59 	if (plat_drtm_mem_map == NULL) {
60 		return INTERNAL_ERROR;
61 	}
62 
63 	/* Get DRTM features from platform hooks. */
64 	plat_tpm_feat = plat_drtm_get_tpm_features();
65 	if (plat_tpm_feat == NULL) {
66 		return INTERNAL_ERROR;
67 	}
68 
69 	plat_dma_prot_feat = plat_drtm_get_dma_prot_features();
70 	if (plat_dma_prot_feat == NULL) {
71 		return INTERNAL_ERROR;
72 	}
73 
74 	/*
75 	 * Add up minimum DLME data memory.
76 	 *
77 	 * For systems with complete DMA protection there is only one entry in
78 	 * the protected regions table.
79 	 */
80 	if (plat_dma_prot_feat->dma_protection_support ==
81 			ARM_DRTM_DMA_PROT_FEATURES_DMA_SUPPORT_COMPLETE) {
82 		dlme_data_min_size =
83 			sizeof(drtm_memory_region_descriptor_table_t) +
84 			sizeof(drtm_mem_region_t);
85 	} else {
86 		/*
87 		 * TODO set protected regions table size based on platform DMA
88 		 * protection configuration
89 		 */
90 		panic();
91 	}
92 
93 	dlme_data_min_size += (drtm_get_address_map_size() +
94 			       PLAT_DRTM_EVENT_LOG_MAX_SIZE +
95 			       plat_drtm_get_tcb_hash_table_size() +
96 			       plat_drtm_get_imp_def_dlme_region_size());
97 
98 	dlme_data_min_size = page_align(dlme_data_min_size, UP)/PAGE_SIZE;
99 
100 	/* Fill out platform DRTM features structure */
101 	/* Only support default PCR schema (0x1) in this implementation. */
102 	ARM_DRTM_TPM_FEATURES_SET_PCR_SCHEMA(plat_drtm_features.tpm_features,
103 		ARM_DRTM_TPM_FEATURES_PCR_SCHEMA_DEFAULT);
104 	ARM_DRTM_TPM_FEATURES_SET_TPM_HASH(plat_drtm_features.tpm_features,
105 		plat_tpm_feat->tpm_based_hash_support);
106 	ARM_DRTM_TPM_FEATURES_SET_FW_HASH(plat_drtm_features.tpm_features,
107 		plat_tpm_feat->firmware_hash_algorithm);
108 	ARM_DRTM_MIN_MEM_REQ_SET_MIN_DLME_DATA_SIZE(plat_drtm_features.minimum_memory_requirement,
109 		dlme_data_min_size);
110 	ARM_DRTM_MIN_MEM_REQ_SET_DCE_SIZE(plat_drtm_features.minimum_memory_requirement,
111 		plat_drtm_get_min_size_normal_world_dce());
112 	ARM_DRTM_DMA_PROT_FEATURES_SET_MAX_REGIONS(plat_drtm_features.dma_prot_features,
113 		plat_dma_prot_feat->max_num_mem_prot_regions);
114 	ARM_DRTM_DMA_PROT_FEATURES_SET_DMA_SUPPORT(plat_drtm_features.dma_prot_features,
115 		plat_dma_prot_feat->dma_protection_support);
116 	ARM_DRTM_TCB_HASH_FEATURES_SET_MAX_NUM_HASHES(plat_drtm_features.tcb_hash_features,
117 		plat_drtm_get_tcb_hash_features());
118 
119 	return 0;
120 }
121 
122 static inline uint64_t drtm_features_tpm(void *ctx)
123 {
124 	SMC_RET2(ctx, 1ULL, /* TPM feature is supported */
125 		 plat_drtm_features.tpm_features);
126 }
127 
128 static inline uint64_t drtm_features_mem_req(void *ctx)
129 {
130 	SMC_RET2(ctx, 1ULL, /* memory req Feature is supported */
131 		 plat_drtm_features.minimum_memory_requirement);
132 }
133 
134 static inline uint64_t drtm_features_boot_pe_id(void *ctx)
135 {
136 	SMC_RET2(ctx, 1ULL, /* Boot PE feature is supported */
137 		 plat_drtm_features.boot_pe_id);
138 }
139 
140 static inline uint64_t drtm_features_dma_prot(void *ctx)
141 {
142 	SMC_RET2(ctx, 1ULL, /* DMA protection feature is supported */
143 		 plat_drtm_features.dma_prot_features);
144 }
145 
146 static inline uint64_t drtm_features_tcb_hashes(void *ctx)
147 {
148 	SMC_RET2(ctx, 1ULL, /* TCB hash feature is supported */
149 		 plat_drtm_features.tcb_hash_features);
150 }
151 
152 uint64_t drtm_smc_handler(uint32_t smc_fid,
153 			  uint64_t x1,
154 			  uint64_t x2,
155 			  uint64_t x3,
156 			  uint64_t x4,
157 			  void *cookie,
158 			  void *handle,
159 			  uint64_t flags)
160 {
161 	/* Check that the SMC call is from the Normal World. */
162 	if (!is_caller_non_secure(flags)) {
163 		SMC_RET1(handle, NOT_SUPPORTED);
164 	}
165 
166 	switch (smc_fid) {
167 	case ARM_DRTM_SVC_VERSION:
168 		INFO("DRTM service handler: version\n");
169 		/* Return the version of current implementation */
170 		SMC_RET1(handle, ARM_DRTM_VERSION);
171 		break;	/* not reached */
172 
173 	case ARM_DRTM_SVC_FEATURES:
174 		if (((x1 >> ARM_DRTM_FUNC_SHIFT) & ARM_DRTM_FUNC_MASK) ==
175 		    ARM_DRTM_FUNC_ID) {
176 			/* Dispatch function-based queries. */
177 			switch (x1 & FUNCID_MASK) {
178 			case ARM_DRTM_SVC_VERSION:
179 				SMC_RET1(handle, SUCCESS);
180 				break;	/* not reached */
181 
182 			case ARM_DRTM_SVC_FEATURES:
183 				SMC_RET1(handle, SUCCESS);
184 				break;	/* not reached */
185 
186 			case ARM_DRTM_SVC_UNPROTECT_MEM:
187 				SMC_RET1(handle, SUCCESS);
188 				break;	/* not reached */
189 
190 			case ARM_DRTM_SVC_DYNAMIC_LAUNCH:
191 				SMC_RET1(handle, SUCCESS);
192 				break;	/* not reached */
193 
194 			case ARM_DRTM_SVC_CLOSE_LOCALITY:
195 				WARN("ARM_DRTM_SVC_CLOSE_LOCALITY feature %s",
196 				     "is not supported\n");
197 				SMC_RET1(handle, NOT_SUPPORTED);
198 				break;	/* not reached */
199 
200 			case ARM_DRTM_SVC_GET_ERROR:
201 				SMC_RET1(handle, SUCCESS);
202 				break;	/* not reached */
203 
204 			case ARM_DRTM_SVC_SET_ERROR:
205 				SMC_RET1(handle, SUCCESS);
206 				break;	/* not reached */
207 
208 			case ARM_DRTM_SVC_SET_TCB_HASH:
209 				WARN("ARM_DRTM_SVC_TCB_HASH feature %s",
210 				     "is not supported\n");
211 				SMC_RET1(handle, NOT_SUPPORTED);
212 				break;	/* not reached */
213 
214 			case ARM_DRTM_SVC_LOCK_TCB_HASH:
215 				WARN("ARM_DRTM_SVC_LOCK_TCB_HASH feature %s",
216 				     "is not supported\n");
217 				SMC_RET1(handle, NOT_SUPPORTED);
218 				break;	/* not reached */
219 
220 			default:
221 				ERROR("Unknown DRTM service function\n");
222 				SMC_RET1(handle, NOT_SUPPORTED);
223 				break;	/* not reached */
224 			}
225 		} else {
226 			/* Dispatch feature-based queries. */
227 			switch (x1 & ARM_DRTM_FEAT_ID_MASK) {
228 			case ARM_DRTM_FEATURES_TPM:
229 				INFO("++ DRTM service handler: TPM features\n");
230 				return drtm_features_tpm(handle);
231 				break;	/* not reached */
232 
233 			case ARM_DRTM_FEATURES_MEM_REQ:
234 				INFO("++ DRTM service handler: Min. mem."
235 				     " requirement features\n");
236 				return drtm_features_mem_req(handle);
237 				break;	/* not reached */
238 
239 			case ARM_DRTM_FEATURES_DMA_PROT:
240 				INFO("++ DRTM service handler: "
241 				     "DMA protection features\n");
242 				return drtm_features_dma_prot(handle);
243 				break;	/* not reached */
244 
245 			case ARM_DRTM_FEATURES_BOOT_PE_ID:
246 				INFO("++ DRTM service handler: "
247 				     "Boot PE ID features\n");
248 				return drtm_features_boot_pe_id(handle);
249 				break;	/* not reached */
250 
251 			case ARM_DRTM_FEATURES_TCB_HASHES:
252 				INFO("++ DRTM service handler: "
253 				     "TCB-hashes features\n");
254 				return drtm_features_tcb_hashes(handle);
255 				break;	/* not reached */
256 
257 			default:
258 				ERROR("Unknown ARM DRTM service feature\n");
259 				SMC_RET1(handle, NOT_SUPPORTED);
260 				break;	/* not reached */
261 			}
262 		}
263 
264 	case ARM_DRTM_SVC_UNPROTECT_MEM:
265 		INFO("DRTM service handler: unprotect mem\n");
266 		SMC_RET1(handle, SMC_OK);
267 		break;	/* not reached */
268 
269 	case ARM_DRTM_SVC_DYNAMIC_LAUNCH:
270 		INFO("DRTM service handler: dynamic launch\n");
271 		SMC_RET1(handle, SMC_OK);
272 		break;	/* not reached */
273 
274 	case ARM_DRTM_SVC_CLOSE_LOCALITY:
275 		WARN("DRTM service handler: close locality %s\n",
276 		     "is not supported");
277 		SMC_RET1(handle, NOT_SUPPORTED);
278 		break;	/* not reached */
279 
280 	case ARM_DRTM_SVC_GET_ERROR:
281 		INFO("DRTM service handler: get error\n");
282 		SMC_RET2(handle, SMC_OK, 0);
283 		break;	/* not reached */
284 
285 	case ARM_DRTM_SVC_SET_ERROR:
286 		INFO("DRTM service handler: set error\n");
287 		SMC_RET1(handle, SMC_OK);
288 		break;	/* not reached */
289 
290 	case ARM_DRTM_SVC_SET_TCB_HASH:
291 		WARN("DRTM service handler: set TCB hash %s\n",
292 		     "is not supported");
293 		SMC_RET1(handle, NOT_SUPPORTED);
294 		break;  /* not reached */
295 
296 	case ARM_DRTM_SVC_LOCK_TCB_HASH:
297 		WARN("DRTM service handler: lock TCB hash %s\n",
298 		     "is not supported");
299 		SMC_RET1(handle, NOT_SUPPORTED);
300 		break;  /* not reached */
301 
302 	default:
303 		ERROR("Unknown DRTM service function: 0x%x\n", smc_fid);
304 		SMC_RET1(handle, SMC_UNK);
305 		break;	/* not reached */
306 	}
307 
308 	/* not reached */
309 	SMC_RET1(handle, SMC_UNK);
310 }
311