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 97b4e1fbbSAlexei Fedorov #if MEASURED_BOOT 107b4e1fbbSAlexei Fedorov #include <common/desc_image_load.h> 117b4e1fbbSAlexei Fedorov #endif 127b4e1fbbSAlexei Fedorov #include <common/fdt_wrappers.h> 137b4e1fbbSAlexei 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 237b4e1fbbSAlexei Fedorov #ifdef SPD_opteed 247b4e1fbbSAlexei Fedorov /* 257b4e1fbbSAlexei Fedorov * Currently OP-TEE does not support reading DTBs from Secure memory 267b4e1fbbSAlexei Fedorov * and this property should be removed when this feature is supported. 277b4e1fbbSAlexei Fedorov */ 287b4e1fbbSAlexei Fedorov #define DTB_PROP_HW_SM_LOG_ADDR "tpm_event_log_sm_addr" 29*eab78e9bSManish V Badarkhe #endif /* SPD_opteed */ 307b4e1fbbSAlexei Fedorov #define DTB_PROP_HW_LOG_ADDR "tpm_event_log_addr" 317b4e1fbbSAlexei Fedorov #define DTB_PROP_HW_LOG_SIZE "tpm_event_log_size" 320ab49645SAlexei Fedorov #endif /* MEASURED_BOOT */ 330ab49645SAlexei Fedorov 34cab0b5b0SSoby Mathew /******************************************************************************* 35cab0b5b0SSoby Mathew * Validate the tb_fw_config is a valid DTB file and returns the node offset 36cab0b5b0SSoby Mathew * to "arm,tb_fw" property. 37cab0b5b0SSoby Mathew * Arguments: 38cab0b5b0SSoby Mathew * void *dtb - pointer to the TB_FW_CONFIG in memory 39cab0b5b0SSoby Mathew * int *node - Returns the node offset to "arm,tb_fw" property if found. 40cab0b5b0SSoby Mathew * 41cab0b5b0SSoby Mathew * Returns 0 on success and -1 on error. 42cab0b5b0SSoby Mathew ******************************************************************************/ 43cab0b5b0SSoby Mathew int arm_dyn_tb_fw_cfg_init(void *dtb, int *node) 44cab0b5b0SSoby Mathew { 45da5f2745SSoby Mathew assert(dtb != NULL); 46da5f2745SSoby Mathew assert(node != NULL); 47cab0b5b0SSoby Mathew 48cab0b5b0SSoby Mathew /* Check if the pointer to DT is correct */ 49cab0b5b0SSoby Mathew if (fdt_check_header(dtb) != 0) { 507b4e1fbbSAlexei Fedorov WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG"); 51cab0b5b0SSoby Mathew return -1; 52cab0b5b0SSoby Mathew } 53cab0b5b0SSoby Mathew 54cab0b5b0SSoby Mathew /* Assert the node offset point to "arm,tb_fw" compatible property */ 55cab0b5b0SSoby Mathew *node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"); 56cab0b5b0SSoby Mathew if (*node < 0) { 577b4e1fbbSAlexei Fedorov WARN("The compatible property '%s' not%s", "arm,tb_fw", 587b4e1fbbSAlexei Fedorov " found in the config\n"); 59cab0b5b0SSoby Mathew return -1; 60cab0b5b0SSoby Mathew } 61cab0b5b0SSoby Mathew 627b4e1fbbSAlexei Fedorov VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n"); 63cab0b5b0SSoby Mathew return 0; 64cab0b5b0SSoby Mathew } 65ba597da7SJohn Tsichritzis 66ba597da7SJohn Tsichritzis /* 67ba597da7SJohn Tsichritzis * This function writes the Mbed TLS heap address and size in the DTB. When it 68ba597da7SJohn Tsichritzis * is called, it is guaranteed that a DTB is available. However it is not 69ba597da7SJohn Tsichritzis * guaranteed that the shared Mbed TLS heap implementation is used. Thus we 70ba597da7SJohn Tsichritzis * return error code from here and it's the responsibility of the caller to 71ba597da7SJohn Tsichritzis * determine the action upon error. 72ba597da7SJohn Tsichritzis * 73ba597da7SJohn Tsichritzis * This function is supposed to be called only by BL1. 74ba597da7SJohn Tsichritzis * 75ba597da7SJohn Tsichritzis * Returns: 76ba597da7SJohn Tsichritzis * 0 = success 770ab49645SAlexei Fedorov * -1 = error 78ba597da7SJohn Tsichritzis */ 79ba597da7SJohn Tsichritzis int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size) 80ba597da7SJohn Tsichritzis { 810ab49645SAlexei Fedorov int dtb_root; 82*eab78e9bSManish V Badarkhe 83ba597da7SJohn Tsichritzis /* 84ba597da7SJohn Tsichritzis * Verify that the DTB is valid, before attempting to write to it, 85ba597da7SJohn Tsichritzis * and get the DTB root node. 86ba597da7SJohn Tsichritzis */ 870ab49645SAlexei Fedorov int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root); 88ba597da7SJohn Tsichritzis if (err < 0) { 897b4e1fbbSAlexei Fedorov ERROR("Invalid%s loaded. Unable to get root node\n", 907b4e1fbbSAlexei Fedorov " TB_FW_CONFIG"); 91ba597da7SJohn Tsichritzis return -1; 92ba597da7SJohn Tsichritzis } 93ba597da7SJohn Tsichritzis 94ba597da7SJohn Tsichritzis /* 95ba597da7SJohn Tsichritzis * Write the heap address and size in the DTB. 96ba597da7SJohn Tsichritzis * 97ba597da7SJohn Tsichritzis * NOTE: The variables heap_addr and heap_size are corrupted 98ba597da7SJohn Tsichritzis * by the "fdtw_write_inplace_cells" function. After the 99ba597da7SJohn Tsichritzis * function calls they must NOT be reused. 100ba597da7SJohn Tsichritzis */ 101ba597da7SJohn Tsichritzis err = fdtw_write_inplace_cells(dtb, dtb_root, 102ba597da7SJohn Tsichritzis DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr); 103ba597da7SJohn Tsichritzis if (err < 0) { 1047b4e1fbbSAlexei Fedorov ERROR("%sDTB property '%s'\n", 1057b4e1fbbSAlexei Fedorov "Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR); 106ba597da7SJohn Tsichritzis return -1; 107ba597da7SJohn Tsichritzis } 108ba597da7SJohn Tsichritzis 109ba597da7SJohn Tsichritzis err = fdtw_write_inplace_cells(dtb, dtb_root, 110ba597da7SJohn Tsichritzis DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size); 111ba597da7SJohn Tsichritzis if (err < 0) { 1127b4e1fbbSAlexei Fedorov ERROR("%sDTB property '%s'\n", 1137b4e1fbbSAlexei Fedorov "Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE); 114ba597da7SJohn Tsichritzis return -1; 115ba597da7SJohn Tsichritzis } 116ba597da7SJohn Tsichritzis 117ba597da7SJohn Tsichritzis return 0; 118ba597da7SJohn Tsichritzis } 1190ab49645SAlexei Fedorov 1200ab49645SAlexei Fedorov #if MEASURED_BOOT 1210ab49645SAlexei Fedorov /* 1227b4e1fbbSAlexei Fedorov * Write the Event Log address and its size in the DTB. 1237b4e1fbbSAlexei Fedorov * 1247b4e1fbbSAlexei Fedorov * This function is supposed to be called only by BL2. 1257b4e1fbbSAlexei Fedorov * 1267b4e1fbbSAlexei Fedorov * Returns: 1277b4e1fbbSAlexei Fedorov * 0 = success 1287b4e1fbbSAlexei Fedorov * < 0 = error 1297b4e1fbbSAlexei Fedorov */ 1307b4e1fbbSAlexei Fedorov static int arm_set_event_log_info(uintptr_t config_base, 1317b4e1fbbSAlexei Fedorov #ifdef SPD_opteed 1327b4e1fbbSAlexei Fedorov uintptr_t sm_log_addr, 1337b4e1fbbSAlexei Fedorov #endif 1347b4e1fbbSAlexei Fedorov uintptr_t log_addr, size_t log_size) 1357b4e1fbbSAlexei Fedorov { 1367b4e1fbbSAlexei Fedorov /* As libfdt uses void *, we can't avoid this cast */ 1377b4e1fbbSAlexei Fedorov void *dtb = (void *)config_base; 1387b4e1fbbSAlexei Fedorov const char *compatible = "arm,tpm_event_log"; 1397b4e1fbbSAlexei Fedorov int err, node; 1407b4e1fbbSAlexei Fedorov 1417b4e1fbbSAlexei Fedorov /* 1427b4e1fbbSAlexei Fedorov * Verify that the DTB is valid, before attempting to write to it, 1437b4e1fbbSAlexei Fedorov * and get the DTB root node. 1447b4e1fbbSAlexei Fedorov */ 1457b4e1fbbSAlexei Fedorov 1467b4e1fbbSAlexei Fedorov /* Check if the pointer to DT is correct */ 1477b4e1fbbSAlexei Fedorov err = fdt_check_header(dtb); 1487b4e1fbbSAlexei Fedorov if (err < 0) { 1497b4e1fbbSAlexei Fedorov WARN("Invalid DTB file passed\n"); 1507b4e1fbbSAlexei Fedorov return err; 1517b4e1fbbSAlexei Fedorov } 1527b4e1fbbSAlexei Fedorov 1537b4e1fbbSAlexei Fedorov /* Assert the node offset point to compatible property */ 1547b4e1fbbSAlexei Fedorov node = fdt_node_offset_by_compatible(dtb, -1, compatible); 1557b4e1fbbSAlexei Fedorov if (node < 0) { 1567b4e1fbbSAlexei Fedorov WARN("The compatible property '%s' not%s", compatible, 1577b4e1fbbSAlexei Fedorov " found in the config\n"); 1587b4e1fbbSAlexei Fedorov return node; 1597b4e1fbbSAlexei Fedorov } 1607b4e1fbbSAlexei Fedorov 1617b4e1fbbSAlexei Fedorov VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n"); 1627b4e1fbbSAlexei Fedorov 1637b4e1fbbSAlexei Fedorov #ifdef SPD_opteed 1647b4e1fbbSAlexei Fedorov if (sm_log_addr != 0UL) { 1657b4e1fbbSAlexei Fedorov err = fdtw_write_inplace_cells(dtb, node, 1667b4e1fbbSAlexei Fedorov DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr); 1677b4e1fbbSAlexei Fedorov if (err < 0) { 1687b4e1fbbSAlexei Fedorov ERROR("%sDTB property '%s'\n", 1697b4e1fbbSAlexei Fedorov "Unable to write ", DTB_PROP_HW_SM_LOG_ADDR); 1707b4e1fbbSAlexei Fedorov return err; 1717b4e1fbbSAlexei Fedorov } 1727b4e1fbbSAlexei Fedorov } 1737b4e1fbbSAlexei Fedorov #endif 1747b4e1fbbSAlexei Fedorov err = fdtw_write_inplace_cells(dtb, node, 1757b4e1fbbSAlexei Fedorov DTB_PROP_HW_LOG_ADDR, 2, &log_addr); 1767b4e1fbbSAlexei Fedorov if (err < 0) { 1777b4e1fbbSAlexei Fedorov ERROR("%sDTB property '%s'\n", 1787b4e1fbbSAlexei Fedorov "Unable to write ", DTB_PROP_HW_LOG_ADDR); 1797b4e1fbbSAlexei Fedorov return err; 1807b4e1fbbSAlexei Fedorov } 1817b4e1fbbSAlexei Fedorov 1827b4e1fbbSAlexei Fedorov err = fdtw_write_inplace_cells(dtb, node, 1837b4e1fbbSAlexei Fedorov DTB_PROP_HW_LOG_SIZE, 1, &log_size); 1847b4e1fbbSAlexei Fedorov if (err < 0) { 1857b4e1fbbSAlexei Fedorov ERROR("%sDTB property '%s'\n", 1867b4e1fbbSAlexei Fedorov "Unable to write ", DTB_PROP_HW_LOG_SIZE); 1877b4e1fbbSAlexei Fedorov } else { 1887b4e1fbbSAlexei Fedorov /* 1897b4e1fbbSAlexei Fedorov * Ensure that the info written to the DTB is visible 1907b4e1fbbSAlexei Fedorov * to other images. 1917b4e1fbbSAlexei Fedorov */ 1927b4e1fbbSAlexei Fedorov flush_dcache_range(config_base, fdt_totalsize(dtb)); 1937b4e1fbbSAlexei Fedorov } 1947b4e1fbbSAlexei Fedorov 1957b4e1fbbSAlexei Fedorov return err; 1967b4e1fbbSAlexei Fedorov } 1977b4e1fbbSAlexei Fedorov 1987b4e1fbbSAlexei Fedorov /* 1997b4e1fbbSAlexei Fedorov * This function writes the Event Log address and its size 2007b4e1fbbSAlexei Fedorov * in the TOS_FW_CONFIG DTB. 2017b4e1fbbSAlexei Fedorov * 2027b4e1fbbSAlexei Fedorov * This function is supposed to be called only by BL2. 2037b4e1fbbSAlexei Fedorov * 2047b4e1fbbSAlexei Fedorov * Returns: 2057b4e1fbbSAlexei Fedorov * 0 = success 2067b4e1fbbSAlexei Fedorov * < 0 = error 2077b4e1fbbSAlexei Fedorov */ 2087b4e1fbbSAlexei Fedorov int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr, 2097b4e1fbbSAlexei Fedorov size_t log_size) 2107b4e1fbbSAlexei Fedorov { 2117b4e1fbbSAlexei Fedorov int err; 2127b4e1fbbSAlexei Fedorov 2137b4e1fbbSAlexei Fedorov assert(config_base != 0UL); 2147b4e1fbbSAlexei Fedorov assert(log_addr != 0UL); 2157b4e1fbbSAlexei Fedorov 2167b4e1fbbSAlexei Fedorov /* Write the Event Log address and its size in the DTB */ 2177b4e1fbbSAlexei Fedorov err = arm_set_event_log_info(config_base, 2187b4e1fbbSAlexei Fedorov #ifdef SPD_opteed 2197b4e1fbbSAlexei Fedorov 0UL, 2207b4e1fbbSAlexei Fedorov #endif 2217b4e1fbbSAlexei Fedorov log_addr, log_size); 2227b4e1fbbSAlexei Fedorov if (err < 0) { 2237b4e1fbbSAlexei Fedorov ERROR("%sEvent Log data to TOS_FW_CONFIG\n", 2247b4e1fbbSAlexei Fedorov "Unable to write "); 2257b4e1fbbSAlexei Fedorov } 2267b4e1fbbSAlexei Fedorov 2277b4e1fbbSAlexei Fedorov return err; 2287b4e1fbbSAlexei Fedorov } 2297b4e1fbbSAlexei Fedorov 2307b4e1fbbSAlexei Fedorov /* 2317b4e1fbbSAlexei Fedorov * This function writes the Event Log address and its size 2327b4e1fbbSAlexei Fedorov * in the NT_FW_CONFIG DTB. 2337b4e1fbbSAlexei Fedorov * 2347b4e1fbbSAlexei Fedorov * This function is supposed to be called only by BL2. 2357b4e1fbbSAlexei Fedorov * 2367b4e1fbbSAlexei Fedorov * Returns: 2377b4e1fbbSAlexei Fedorov * 0 = success 2387b4e1fbbSAlexei Fedorov * < 0 = error 2397b4e1fbbSAlexei Fedorov */ 2407b4e1fbbSAlexei Fedorov int arm_set_nt_fw_info(uintptr_t config_base, 2417b4e1fbbSAlexei Fedorov #ifdef SPD_opteed 2427b4e1fbbSAlexei Fedorov uintptr_t log_addr, 2437b4e1fbbSAlexei Fedorov #endif 2447b4e1fbbSAlexei Fedorov size_t log_size, uintptr_t *ns_log_addr) 2457b4e1fbbSAlexei Fedorov { 2467b4e1fbbSAlexei Fedorov uintptr_t ns_addr; 2477b4e1fbbSAlexei Fedorov const bl_mem_params_node_t *cfg_mem_params; 2487b4e1fbbSAlexei Fedorov int err; 2497b4e1fbbSAlexei Fedorov 2507b4e1fbbSAlexei Fedorov assert(config_base != 0UL); 2517b4e1fbbSAlexei Fedorov assert(ns_log_addr != NULL); 2527b4e1fbbSAlexei Fedorov 2537b4e1fbbSAlexei Fedorov /* Get the config load address and size from NT_FW_CONFIG */ 2547b4e1fbbSAlexei Fedorov cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID); 2557b4e1fbbSAlexei Fedorov assert(cfg_mem_params != NULL); 2567b4e1fbbSAlexei Fedorov 2577b4e1fbbSAlexei Fedorov /* Calculate Event Log address in Non-secure memory */ 2587b4e1fbbSAlexei Fedorov ns_addr = cfg_mem_params->image_info.image_base + 2597b4e1fbbSAlexei Fedorov cfg_mem_params->image_info.image_max_size; 2607b4e1fbbSAlexei Fedorov 2617b4e1fbbSAlexei Fedorov /* Check for memory space */ 2627b4e1fbbSAlexei Fedorov if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) { 2637b4e1fbbSAlexei Fedorov return -1; 2647b4e1fbbSAlexei Fedorov } 2657b4e1fbbSAlexei Fedorov 2667b4e1fbbSAlexei Fedorov /* Write the Event Log address and its size in the DTB */ 2677b4e1fbbSAlexei Fedorov err = arm_set_event_log_info(config_base, 2687b4e1fbbSAlexei Fedorov #ifdef SPD_opteed 2697b4e1fbbSAlexei Fedorov log_addr, 2707b4e1fbbSAlexei Fedorov #endif 2717b4e1fbbSAlexei Fedorov ns_addr, log_size); 2727b4e1fbbSAlexei Fedorov 2737b4e1fbbSAlexei Fedorov /* Return Event Log address in Non-secure memory */ 2747b4e1fbbSAlexei Fedorov *ns_log_addr = (err < 0) ? 0UL : ns_addr; 2757b4e1fbbSAlexei Fedorov return err; 2767b4e1fbbSAlexei Fedorov } 2770ab49645SAlexei Fedorov #endif /* MEASURED_BOOT */ 278