1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2018-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #if MEASURED_BOOT 11*91f16700Schasinglulu #include <common/desc_image_load.h> 12*91f16700Schasinglulu #endif 13*91f16700Schasinglulu #include <common/fdt_wrappers.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <lib/fconf/fconf.h> 16*91f16700Schasinglulu #include <lib/fconf/fconf_dyn_cfg_getter.h> 17*91f16700Schasinglulu #include <libfdt.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu #include <plat/arm/common/arm_dyn_cfg_helpers.h> 20*91f16700Schasinglulu #include <plat/arm/common/plat_arm.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu #define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr" 23*91f16700Schasinglulu #define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size" 24*91f16700Schasinglulu 25*91f16700Schasinglulu #if MEASURED_BOOT 26*91f16700Schasinglulu #ifdef SPD_opteed 27*91f16700Schasinglulu /* 28*91f16700Schasinglulu * Currently OP-TEE does not support reading DTBs from Secure memory 29*91f16700Schasinglulu * and this property should be removed when this feature is supported. 30*91f16700Schasinglulu */ 31*91f16700Schasinglulu #define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr" 32*91f16700Schasinglulu #endif /* SPD_opteed */ 33*91f16700Schasinglulu #define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr" 34*91f16700Schasinglulu #define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size" 35*91f16700Schasinglulu #define DTB_PROP_HW_LOG_MAX_SIZE "tpm_event_log_max_size" 36*91f16700Schasinglulu #endif /* MEASURED_BOOT */ 37*91f16700Schasinglulu 38*91f16700Schasinglulu static size_t event_log_max_size __unused; 39*91f16700Schasinglulu 40*91f16700Schasinglulu /******************************************************************************* 41*91f16700Schasinglulu * Validate the tb_fw_config is a valid DTB file and returns the node offset 42*91f16700Schasinglulu * to "arm,tb_fw" property. 43*91f16700Schasinglulu * Arguments: 44*91f16700Schasinglulu * void *dtb - pointer to the TB_FW_CONFIG in memory 45*91f16700Schasinglulu * int *node - Returns the node offset to "arm,tb_fw" property if found. 46*91f16700Schasinglulu * 47*91f16700Schasinglulu * Returns 0 on success and -1 on error. 48*91f16700Schasinglulu ******************************************************************************/ 49*91f16700Schasinglulu int arm_dyn_tb_fw_cfg_init(void *dtb, int *node) 50*91f16700Schasinglulu { 51*91f16700Schasinglulu assert(dtb != NULL); 52*91f16700Schasinglulu assert(node != NULL); 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* Check if the pointer to DT is correct */ 55*91f16700Schasinglulu if (fdt_check_header(dtb) != 0) { 56*91f16700Schasinglulu WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG"); 57*91f16700Schasinglulu return -1; 58*91f16700Schasinglulu } 59*91f16700Schasinglulu 60*91f16700Schasinglulu /* Assert the node offset point to "arm,tb_fw" compatible property */ 61*91f16700Schasinglulu *node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"); 62*91f16700Schasinglulu if (*node < 0) { 63*91f16700Schasinglulu WARN("The compatible property '%s' not%s", "arm,tb_fw", 64*91f16700Schasinglulu " found in the config\n"); 65*91f16700Schasinglulu return -1; 66*91f16700Schasinglulu } 67*91f16700Schasinglulu 68*91f16700Schasinglulu VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n"); 69*91f16700Schasinglulu return 0; 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* 73*91f16700Schasinglulu * This function writes the Mbed TLS heap address and size in the DTB. When it 74*91f16700Schasinglulu * is called, it is guaranteed that a DTB is available. However it is not 75*91f16700Schasinglulu * guaranteed that the shared Mbed TLS heap implementation is used. Thus we 76*91f16700Schasinglulu * return error code from here and it's the responsibility of the caller to 77*91f16700Schasinglulu * determine the action upon error. 78*91f16700Schasinglulu * 79*91f16700Schasinglulu * This function is supposed to be called only by BL1. 80*91f16700Schasinglulu * 81*91f16700Schasinglulu * Returns: 82*91f16700Schasinglulu * 0 = success 83*91f16700Schasinglulu * -1 = error 84*91f16700Schasinglulu */ 85*91f16700Schasinglulu int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size) 86*91f16700Schasinglulu { 87*91f16700Schasinglulu int dtb_root; 88*91f16700Schasinglulu 89*91f16700Schasinglulu /* 90*91f16700Schasinglulu * Verify that the DTB is valid, before attempting to write to it, 91*91f16700Schasinglulu * and get the DTB root node. 92*91f16700Schasinglulu */ 93*91f16700Schasinglulu int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root); 94*91f16700Schasinglulu if (err < 0) { 95*91f16700Schasinglulu ERROR("Invalid%s loaded. Unable to get root node\n", 96*91f16700Schasinglulu " TB_FW_CONFIG"); 97*91f16700Schasinglulu return -1; 98*91f16700Schasinglulu } 99*91f16700Schasinglulu 100*91f16700Schasinglulu /* 101*91f16700Schasinglulu * Write the heap address and size in the DTB. 102*91f16700Schasinglulu * 103*91f16700Schasinglulu * NOTE: The variables heap_addr and heap_size are corrupted 104*91f16700Schasinglulu * by the "fdtw_write_inplace_cells" function. After the 105*91f16700Schasinglulu * function calls they must NOT be reused. 106*91f16700Schasinglulu */ 107*91f16700Schasinglulu err = fdtw_write_inplace_cells(dtb, dtb_root, 108*91f16700Schasinglulu DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr); 109*91f16700Schasinglulu if (err < 0) { 110*91f16700Schasinglulu ERROR("%sDTB property '%s'\n", 111*91f16700Schasinglulu "Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR); 112*91f16700Schasinglulu return -1; 113*91f16700Schasinglulu } 114*91f16700Schasinglulu 115*91f16700Schasinglulu err = fdtw_write_inplace_cells(dtb, dtb_root, 116*91f16700Schasinglulu DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size); 117*91f16700Schasinglulu if (err < 0) { 118*91f16700Schasinglulu ERROR("%sDTB property '%s'\n", 119*91f16700Schasinglulu "Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE); 120*91f16700Schasinglulu return -1; 121*91f16700Schasinglulu } 122*91f16700Schasinglulu 123*91f16700Schasinglulu return 0; 124*91f16700Schasinglulu } 125*91f16700Schasinglulu 126*91f16700Schasinglulu #if MEASURED_BOOT 127*91f16700Schasinglulu /* 128*91f16700Schasinglulu * Write the Event Log address and its size in the DTB. 129*91f16700Schasinglulu * 130*91f16700Schasinglulu * Returns: 131*91f16700Schasinglulu * 0 = success 132*91f16700Schasinglulu * < 0 = error 133*91f16700Schasinglulu */ 134*91f16700Schasinglulu static int arm_set_event_log_info(uintptr_t config_base, 135*91f16700Schasinglulu #ifdef SPD_opteed 136*91f16700Schasinglulu uintptr_t sm_log_addr, 137*91f16700Schasinglulu #endif 138*91f16700Schasinglulu uintptr_t log_addr, size_t log_size) 139*91f16700Schasinglulu { 140*91f16700Schasinglulu /* As libfdt uses void *, we can't avoid this cast */ 141*91f16700Schasinglulu void *dtb = (void *)config_base; 142*91f16700Schasinglulu const char *compatible = "arm,tpm_event_log"; 143*91f16700Schasinglulu int err, node; 144*91f16700Schasinglulu 145*91f16700Schasinglulu /* 146*91f16700Schasinglulu * Verify that the DTB is valid, before attempting to write to it, 147*91f16700Schasinglulu * and get the DTB root node. 148*91f16700Schasinglulu */ 149*91f16700Schasinglulu 150*91f16700Schasinglulu /* Check if the pointer to DT is correct */ 151*91f16700Schasinglulu err = fdt_check_header(dtb); 152*91f16700Schasinglulu if (err < 0) { 153*91f16700Schasinglulu WARN("Invalid DTB file passed\n"); 154*91f16700Schasinglulu return err; 155*91f16700Schasinglulu } 156*91f16700Schasinglulu 157*91f16700Schasinglulu /* Assert the node offset point to compatible property */ 158*91f16700Schasinglulu node = fdt_node_offset_by_compatible(dtb, -1, compatible); 159*91f16700Schasinglulu if (node < 0) { 160*91f16700Schasinglulu WARN("The compatible property '%s' not%s", compatible, 161*91f16700Schasinglulu " found in the config\n"); 162*91f16700Schasinglulu return node; 163*91f16700Schasinglulu } 164*91f16700Schasinglulu 165*91f16700Schasinglulu VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n"); 166*91f16700Schasinglulu 167*91f16700Schasinglulu #ifdef SPD_opteed 168*91f16700Schasinglulu if (sm_log_addr != 0UL) { 169*91f16700Schasinglulu err = fdtw_write_inplace_cells(dtb, node, 170*91f16700Schasinglulu DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr); 171*91f16700Schasinglulu if (err < 0) { 172*91f16700Schasinglulu ERROR("%sDTB property '%s'\n", 173*91f16700Schasinglulu "Unable to write ", DTB_PROP_HW_SM_LOG_ADDR); 174*91f16700Schasinglulu return err; 175*91f16700Schasinglulu } 176*91f16700Schasinglulu } 177*91f16700Schasinglulu #endif 178*91f16700Schasinglulu err = fdtw_write_inplace_cells(dtb, node, 179*91f16700Schasinglulu DTB_PROP_HW_LOG_ADDR, 2, &log_addr); 180*91f16700Schasinglulu if (err < 0) { 181*91f16700Schasinglulu ERROR("%sDTB property '%s'\n", 182*91f16700Schasinglulu "Unable to write ", DTB_PROP_HW_LOG_ADDR); 183*91f16700Schasinglulu return err; 184*91f16700Schasinglulu } 185*91f16700Schasinglulu 186*91f16700Schasinglulu assert(event_log_max_size != 0U); 187*91f16700Schasinglulu err = fdtw_write_inplace_cells(dtb, node, 188*91f16700Schasinglulu DTB_PROP_HW_LOG_MAX_SIZE, 1, 189*91f16700Schasinglulu &event_log_max_size); 190*91f16700Schasinglulu if (err < 0) { 191*91f16700Schasinglulu ERROR("%sDTB property '%s'\n", 192*91f16700Schasinglulu "Unable to write ", DTB_PROP_HW_LOG_MAX_SIZE); 193*91f16700Schasinglulu return err; 194*91f16700Schasinglulu } 195*91f16700Schasinglulu 196*91f16700Schasinglulu err = fdtw_write_inplace_cells(dtb, node, 197*91f16700Schasinglulu DTB_PROP_HW_LOG_SIZE, 1, &log_size); 198*91f16700Schasinglulu if (err < 0) { 199*91f16700Schasinglulu ERROR("%sDTB property '%s'\n", 200*91f16700Schasinglulu "Unable to write ", DTB_PROP_HW_LOG_SIZE); 201*91f16700Schasinglulu } else { 202*91f16700Schasinglulu /* 203*91f16700Schasinglulu * Ensure that the info written to the DTB is visible 204*91f16700Schasinglulu * to other images. 205*91f16700Schasinglulu */ 206*91f16700Schasinglulu flush_dcache_range(config_base, fdt_totalsize(dtb)); 207*91f16700Schasinglulu } 208*91f16700Schasinglulu 209*91f16700Schasinglulu return err; 210*91f16700Schasinglulu } 211*91f16700Schasinglulu 212*91f16700Schasinglulu /* 213*91f16700Schasinglulu * This function writes the Event Log address and its size 214*91f16700Schasinglulu * in the TOS_FW_CONFIG DTB. 215*91f16700Schasinglulu * 216*91f16700Schasinglulu * This function is supposed to be called only by BL2. 217*91f16700Schasinglulu * 218*91f16700Schasinglulu * Returns: 219*91f16700Schasinglulu * 0 = success 220*91f16700Schasinglulu * < 0 = error 221*91f16700Schasinglulu */ 222*91f16700Schasinglulu int arm_set_tos_fw_info(uintptr_t log_addr, size_t log_size) 223*91f16700Schasinglulu { 224*91f16700Schasinglulu uintptr_t config_base; 225*91f16700Schasinglulu const bl_mem_params_node_t *cfg_mem_params; 226*91f16700Schasinglulu int err; 227*91f16700Schasinglulu 228*91f16700Schasinglulu assert(log_addr != 0UL); 229*91f16700Schasinglulu 230*91f16700Schasinglulu /* Get the config load address and size of TOS_FW_CONFIG */ 231*91f16700Schasinglulu cfg_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID); 232*91f16700Schasinglulu assert(cfg_mem_params != NULL); 233*91f16700Schasinglulu 234*91f16700Schasinglulu config_base = cfg_mem_params->image_info.image_base; 235*91f16700Schasinglulu 236*91f16700Schasinglulu /* Write the Event Log address and its size in the DTB */ 237*91f16700Schasinglulu err = arm_set_event_log_info(config_base, 238*91f16700Schasinglulu #ifdef SPD_opteed 239*91f16700Schasinglulu 0UL, 240*91f16700Schasinglulu #endif 241*91f16700Schasinglulu log_addr, log_size); 242*91f16700Schasinglulu if (err < 0) { 243*91f16700Schasinglulu ERROR("%sEvent Log data to TOS_FW_CONFIG\n", 244*91f16700Schasinglulu "Unable to write "); 245*91f16700Schasinglulu } 246*91f16700Schasinglulu 247*91f16700Schasinglulu return err; 248*91f16700Schasinglulu } 249*91f16700Schasinglulu 250*91f16700Schasinglulu /* 251*91f16700Schasinglulu * This function writes the Event Log address and its size 252*91f16700Schasinglulu * in the NT_FW_CONFIG DTB. 253*91f16700Schasinglulu * 254*91f16700Schasinglulu * This function is supposed to be called only by BL2. 255*91f16700Schasinglulu * 256*91f16700Schasinglulu * Returns: 257*91f16700Schasinglulu * 0 = success 258*91f16700Schasinglulu * < 0 = error 259*91f16700Schasinglulu */ 260*91f16700Schasinglulu int arm_set_nt_fw_info( 261*91f16700Schasinglulu #ifdef SPD_opteed 262*91f16700Schasinglulu uintptr_t log_addr, 263*91f16700Schasinglulu #endif 264*91f16700Schasinglulu size_t log_size, uintptr_t *ns_log_addr) 265*91f16700Schasinglulu { 266*91f16700Schasinglulu uintptr_t config_base; 267*91f16700Schasinglulu uintptr_t ns_addr; 268*91f16700Schasinglulu const bl_mem_params_node_t *cfg_mem_params; 269*91f16700Schasinglulu int err; 270*91f16700Schasinglulu 271*91f16700Schasinglulu assert(ns_log_addr != NULL); 272*91f16700Schasinglulu 273*91f16700Schasinglulu /* Get the config load address and size from NT_FW_CONFIG */ 274*91f16700Schasinglulu cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); 275*91f16700Schasinglulu assert(cfg_mem_params != NULL); 276*91f16700Schasinglulu 277*91f16700Schasinglulu config_base = cfg_mem_params->image_info.image_base; 278*91f16700Schasinglulu 279*91f16700Schasinglulu /* Calculate Event Log address in Non-secure memory */ 280*91f16700Schasinglulu ns_addr = cfg_mem_params->image_info.image_base + 281*91f16700Schasinglulu cfg_mem_params->image_info.image_max_size; 282*91f16700Schasinglulu 283*91f16700Schasinglulu /* Check for memory space */ 284*91f16700Schasinglulu if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) { 285*91f16700Schasinglulu return -1; 286*91f16700Schasinglulu } 287*91f16700Schasinglulu 288*91f16700Schasinglulu /* Write the Event Log address and its size in the DTB */ 289*91f16700Schasinglulu err = arm_set_event_log_info(config_base, 290*91f16700Schasinglulu #ifdef SPD_opteed 291*91f16700Schasinglulu log_addr, 292*91f16700Schasinglulu #endif 293*91f16700Schasinglulu ns_addr, log_size); 294*91f16700Schasinglulu 295*91f16700Schasinglulu /* Return Event Log address in Non-secure memory */ 296*91f16700Schasinglulu *ns_log_addr = (err < 0) ? 0UL : ns_addr; 297*91f16700Schasinglulu return err; 298*91f16700Schasinglulu } 299*91f16700Schasinglulu 300*91f16700Schasinglulu /* 301*91f16700Schasinglulu * This function writes the Event Log address and its size 302*91f16700Schasinglulu * in the TB_FW_CONFIG DTB. 303*91f16700Schasinglulu * 304*91f16700Schasinglulu * This function is supposed to be called only by BL1. 305*91f16700Schasinglulu * 306*91f16700Schasinglulu * Returns: 307*91f16700Schasinglulu * 0 = success 308*91f16700Schasinglulu * < 0 = error 309*91f16700Schasinglulu */ 310*91f16700Schasinglulu int arm_set_tb_fw_info(uintptr_t log_addr, size_t log_size, size_t log_max_size) 311*91f16700Schasinglulu { 312*91f16700Schasinglulu /* 313*91f16700Schasinglulu * Read tb_fw_config device tree for Event Log properties 314*91f16700Schasinglulu * and write the Event Log address and its size in the DTB 315*91f16700Schasinglulu */ 316*91f16700Schasinglulu const struct dyn_cfg_dtb_info_t *tb_fw_config_info; 317*91f16700Schasinglulu uintptr_t tb_fw_cfg_dtb; 318*91f16700Schasinglulu int err; 319*91f16700Schasinglulu 320*91f16700Schasinglulu tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID); 321*91f16700Schasinglulu assert(tb_fw_config_info != NULL); 322*91f16700Schasinglulu 323*91f16700Schasinglulu tb_fw_cfg_dtb = tb_fw_config_info->config_addr; 324*91f16700Schasinglulu 325*91f16700Schasinglulu event_log_max_size = log_max_size; 326*91f16700Schasinglulu 327*91f16700Schasinglulu err = arm_set_event_log_info(tb_fw_cfg_dtb, 328*91f16700Schasinglulu #ifdef SPD_opteed 329*91f16700Schasinglulu 0UL, 330*91f16700Schasinglulu #endif 331*91f16700Schasinglulu log_addr, log_size); 332*91f16700Schasinglulu return err; 333*91f16700Schasinglulu } 334*91f16700Schasinglulu 335*91f16700Schasinglulu /* 336*91f16700Schasinglulu * This function reads the Event Log address and its size 337*91f16700Schasinglulu * properties present in TB_FW_CONFIG DTB. 338*91f16700Schasinglulu * 339*91f16700Schasinglulu * This function is supposed to be called only by BL2. 340*91f16700Schasinglulu * 341*91f16700Schasinglulu * Returns: 342*91f16700Schasinglulu * 0 = success 343*91f16700Schasinglulu * < 0 = error 344*91f16700Schasinglulu * Alongside returns Event Log address and its size. 345*91f16700Schasinglulu */ 346*91f16700Schasinglulu 347*91f16700Schasinglulu int arm_get_tb_fw_info(uint64_t *log_addr, size_t *log_size, 348*91f16700Schasinglulu size_t *log_max_size) 349*91f16700Schasinglulu { 350*91f16700Schasinglulu /* As libfdt uses void *, we can't avoid this cast */ 351*91f16700Schasinglulu const struct dyn_cfg_dtb_info_t *tb_fw_config_info; 352*91f16700Schasinglulu int node, rc; 353*91f16700Schasinglulu 354*91f16700Schasinglulu tb_fw_config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID); 355*91f16700Schasinglulu assert(tb_fw_config_info != NULL); 356*91f16700Schasinglulu 357*91f16700Schasinglulu void *dtb = (void *)tb_fw_config_info->config_addr; 358*91f16700Schasinglulu const char *compatible = "arm,tpm_event_log"; 359*91f16700Schasinglulu 360*91f16700Schasinglulu /* Assert the node offset point to compatible property */ 361*91f16700Schasinglulu node = fdt_node_offset_by_compatible(dtb, -1, compatible); 362*91f16700Schasinglulu if (node < 0) { 363*91f16700Schasinglulu WARN("The compatible property '%s'%s", compatible, 364*91f16700Schasinglulu " not specified in TB_FW config.\n"); 365*91f16700Schasinglulu return node; 366*91f16700Schasinglulu } 367*91f16700Schasinglulu 368*91f16700Schasinglulu VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n"); 369*91f16700Schasinglulu 370*91f16700Schasinglulu rc = fdt_read_uint64(dtb, node, DTB_PROP_HW_LOG_ADDR, log_addr); 371*91f16700Schasinglulu if (rc != 0) { 372*91f16700Schasinglulu ERROR("%s%s", DTB_PROP_HW_LOG_ADDR, 373*91f16700Schasinglulu " not specified in TB_FW config.\n"); 374*91f16700Schasinglulu return rc; 375*91f16700Schasinglulu } 376*91f16700Schasinglulu 377*91f16700Schasinglulu rc = fdt_read_uint32(dtb, node, DTB_PROP_HW_LOG_SIZE, (uint32_t *)log_size); 378*91f16700Schasinglulu if (rc != 0) { 379*91f16700Schasinglulu ERROR("%s%s", DTB_PROP_HW_LOG_SIZE, 380*91f16700Schasinglulu " not specified in TB_FW config.\n"); 381*91f16700Schasinglulu return rc; 382*91f16700Schasinglulu } 383*91f16700Schasinglulu 384*91f16700Schasinglulu rc = fdt_read_uint32(dtb, node, DTB_PROP_HW_LOG_MAX_SIZE, 385*91f16700Schasinglulu (uint32_t *)log_max_size); 386*91f16700Schasinglulu if (rc != 0) { 387*91f16700Schasinglulu ERROR("%s%s", DTB_PROP_HW_LOG_MAX_SIZE, 388*91f16700Schasinglulu " not specified in TB_FW config.\n"); 389*91f16700Schasinglulu return rc; 390*91f16700Schasinglulu } else { 391*91f16700Schasinglulu event_log_max_size = *log_max_size; 392*91f16700Schasinglulu } 393*91f16700Schasinglulu 394*91f16700Schasinglulu return rc; 395*91f16700Schasinglulu } 396*91f16700Schasinglulu #endif /* MEASURED_BOOT */ 397