1 /* 2 * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 9 #if MEASURED_BOOT 10 #include <common/desc_image_load.h> 11 #endif 12 #include <common/fdt_wrappers.h> 13 14 #include <libfdt.h> 15 16 #include <plat/arm/common/arm_dyn_cfg_helpers.h> 17 #include <plat/arm/common/plat_arm.h> 18 19 #define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr" 20 #define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size" 21 22 #if MEASURED_BOOT 23 #define DTB_PROP_BL2_HASH_DATA "bl2_hash_data" 24 #ifdef SPD_opteed 25 /* 26 * Currently OP-TEE does not support reading DTBs from Secure memory 27 * and this property should be removed when this feature is supported. 28 */ 29 #define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr" 30 #endif 31 #define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr" 32 #define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size" 33 34 static int dtb_root = -1; 35 #endif /* MEASURED_BOOT */ 36 37 /******************************************************************************* 38 * Validate the tb_fw_config is a valid DTB file and returns the node offset 39 * to "arm,tb_fw" property. 40 * Arguments: 41 * void *dtb - pointer to the TB_FW_CONFIG in memory 42 * int *node - Returns the node offset to "arm,tb_fw" property if found. 43 * 44 * Returns 0 on success and -1 on error. 45 ******************************************************************************/ 46 int arm_dyn_tb_fw_cfg_init(void *dtb, int *node) 47 { 48 assert(dtb != NULL); 49 assert(node != NULL); 50 51 /* Check if the pointer to DT is correct */ 52 if (fdt_check_header(dtb) != 0) { 53 WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG"); 54 return -1; 55 } 56 57 /* Assert the node offset point to "arm,tb_fw" compatible property */ 58 *node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"); 59 if (*node < 0) { 60 WARN("The compatible property '%s' not%s", "arm,tb_fw", 61 " found in the config\n"); 62 return -1; 63 } 64 65 VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n"); 66 return 0; 67 } 68 69 /* 70 * This function writes the Mbed TLS heap address and size in the DTB. When it 71 * is called, it is guaranteed that a DTB is available. However it is not 72 * guaranteed that the shared Mbed TLS heap implementation is used. Thus we 73 * return error code from here and it's the responsibility of the caller to 74 * determine the action upon error. 75 * 76 * This function is supposed to be called only by BL1. 77 * 78 * Returns: 79 * 0 = success 80 * -1 = error 81 */ 82 int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size) 83 { 84 #if !MEASURED_BOOT 85 int dtb_root; 86 #endif 87 /* 88 * Verify that the DTB is valid, before attempting to write to it, 89 * and get the DTB root node. 90 */ 91 int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root); 92 if (err < 0) { 93 ERROR("Invalid%s loaded. Unable to get root node\n", 94 " TB_FW_CONFIG"); 95 return -1; 96 } 97 98 /* 99 * Write the heap address and size in the DTB. 100 * 101 * NOTE: The variables heap_addr and heap_size are corrupted 102 * by the "fdtw_write_inplace_cells" function. After the 103 * function calls they must NOT be reused. 104 */ 105 err = fdtw_write_inplace_cells(dtb, dtb_root, 106 DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr); 107 if (err < 0) { 108 ERROR("%sDTB property '%s'\n", 109 "Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR); 110 return -1; 111 } 112 113 err = fdtw_write_inplace_cells(dtb, dtb_root, 114 DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size); 115 if (err < 0) { 116 ERROR("%sDTB property '%s'\n", 117 "Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE); 118 return -1; 119 } 120 121 return 0; 122 } 123 124 #if MEASURED_BOOT 125 /* 126 * This function writes the BL2 hash data in HW_FW_CONFIG DTB. 127 * When it is called, it is guaranteed that a DTB is available. 128 * 129 * This function is supposed to be called only by BL1. 130 * 131 * Returns: 132 * 0 = success 133 * < 0 = error 134 */ 135 int arm_set_bl2_hash_info(void *dtb, void *data) 136 { 137 assert(dtb_root >= 0); 138 139 /* 140 * Write the BL2 hash data in the DTB. 141 */ 142 return fdtw_write_inplace_bytes(dtb, dtb_root, 143 DTB_PROP_BL2_HASH_DATA, 144 TCG_DIGEST_SIZE, data); 145 } 146 147 /* 148 * Write the Event Log address and its size in the DTB. 149 * 150 * This function is supposed to be called only by BL2. 151 * 152 * Returns: 153 * 0 = success 154 * < 0 = error 155 */ 156 static int arm_set_event_log_info(uintptr_t config_base, 157 #ifdef SPD_opteed 158 uintptr_t sm_log_addr, 159 #endif 160 uintptr_t log_addr, size_t log_size) 161 { 162 /* As libfdt uses void *, we can't avoid this cast */ 163 void *dtb = (void *)config_base; 164 const char *compatible = "arm,tpm_event_log"; 165 int err, node; 166 167 /* 168 * Verify that the DTB is valid, before attempting to write to it, 169 * and get the DTB root node. 170 */ 171 172 /* Check if the pointer to DT is correct */ 173 err = fdt_check_header(dtb); 174 if (err < 0) { 175 WARN("Invalid DTB file passed\n"); 176 return err; 177 } 178 179 /* Assert the node offset point to compatible property */ 180 node = fdt_node_offset_by_compatible(dtb, -1, compatible); 181 if (node < 0) { 182 WARN("The compatible property '%s' not%s", compatible, 183 " found in the config\n"); 184 return node; 185 } 186 187 VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n"); 188 189 #ifdef SPD_opteed 190 if (sm_log_addr != 0UL) { 191 err = fdtw_write_inplace_cells(dtb, node, 192 DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr); 193 if (err < 0) { 194 ERROR("%sDTB property '%s'\n", 195 "Unable to write ", DTB_PROP_HW_SM_LOG_ADDR); 196 return err; 197 } 198 } 199 #endif 200 err = fdtw_write_inplace_cells(dtb, node, 201 DTB_PROP_HW_LOG_ADDR, 2, &log_addr); 202 if (err < 0) { 203 ERROR("%sDTB property '%s'\n", 204 "Unable to write ", DTB_PROP_HW_LOG_ADDR); 205 return err; 206 } 207 208 err = fdtw_write_inplace_cells(dtb, node, 209 DTB_PROP_HW_LOG_SIZE, 1, &log_size); 210 if (err < 0) { 211 ERROR("%sDTB property '%s'\n", 212 "Unable to write ", DTB_PROP_HW_LOG_SIZE); 213 } else { 214 /* 215 * Ensure that the info written to the DTB is visible 216 * to other images. 217 */ 218 flush_dcache_range(config_base, fdt_totalsize(dtb)); 219 } 220 221 return err; 222 } 223 224 /* 225 * This function writes the Event Log address and its size 226 * in the TOS_FW_CONFIG DTB. 227 * 228 * This function is supposed to be called only by BL2. 229 * 230 * Returns: 231 * 0 = success 232 * < 0 = error 233 */ 234 int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr, 235 size_t log_size) 236 { 237 int err; 238 239 assert(config_base != 0UL); 240 assert(log_addr != 0UL); 241 242 /* Write the Event Log address and its size in the DTB */ 243 err = arm_set_event_log_info(config_base, 244 #ifdef SPD_opteed 245 0UL, 246 #endif 247 log_addr, log_size); 248 if (err < 0) { 249 ERROR("%sEvent Log data to TOS_FW_CONFIG\n", 250 "Unable to write "); 251 } 252 253 return err; 254 } 255 256 /* 257 * This function writes the Event Log address and its size 258 * in the NT_FW_CONFIG DTB. 259 * 260 * This function is supposed to be called only by BL2. 261 * 262 * Returns: 263 * 0 = success 264 * < 0 = error 265 */ 266 int arm_set_nt_fw_info(uintptr_t config_base, 267 #ifdef SPD_opteed 268 uintptr_t log_addr, 269 #endif 270 size_t log_size, uintptr_t *ns_log_addr) 271 { 272 uintptr_t ns_addr; 273 const bl_mem_params_node_t *cfg_mem_params; 274 int err; 275 276 assert(config_base != 0UL); 277 assert(ns_log_addr != NULL); 278 279 /* Get the config load address and size from NT_FW_CONFIG */ 280 cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); 281 assert(cfg_mem_params != NULL); 282 283 /* Calculate Event Log address in Non-secure memory */ 284 ns_addr = cfg_mem_params->image_info.image_base + 285 cfg_mem_params->image_info.image_max_size; 286 287 /* Check for memory space */ 288 if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) { 289 return -1; 290 } 291 292 /* Write the Event Log address and its size in the DTB */ 293 err = arm_set_event_log_info(config_base, 294 #ifdef SPD_opteed 295 log_addr, 296 #endif 297 ns_addr, log_size); 298 299 /* Return Event Log address in Non-secure memory */ 300 *ns_log_addr = (err < 0) ? 0UL : ns_addr; 301 return err; 302 } 303 #endif /* MEASURED_BOOT */ 304