xref: /rk3399_ARM-atf/plat/arm/common/arm_dyn_cfg_helpers.c (revision eab78e9ba4e36da27941bac99d2de0d5228eca6c)
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