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