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