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