xref: /rk3399_ARM-atf/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c (revision 2aaed8608004f7d29be5da49289bb16c1b0df20f)
1cb2c4f93SYing-Chun Liu (PaulLiu) /*
2cb2c4f93SYing-Chun Liu (PaulLiu)  * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
3cb2c4f93SYing-Chun Liu (PaulLiu)  * Copyright (c) 2022, Linaro.
4cb2c4f93SYing-Chun Liu (PaulLiu)  *
5cb2c4f93SYing-Chun Liu (PaulLiu)  * SPDX-License-Identifier: BSD-3-Clause
6cb2c4f93SYing-Chun Liu (PaulLiu)  */
7cb2c4f93SYing-Chun Liu (PaulLiu) 
8cb2c4f93SYing-Chun Liu (PaulLiu) #include <assert.h>
9cb2c4f93SYing-Chun Liu (PaulLiu) 
10cb2c4f93SYing-Chun Liu (PaulLiu) #include <arch_helpers.h>
11cb2c4f93SYing-Chun Liu (PaulLiu) #if MEASURED_BOOT
12cb2c4f93SYing-Chun Liu (PaulLiu) #include <common/desc_image_load.h>
13cb2c4f93SYing-Chun Liu (PaulLiu) #endif
14cb2c4f93SYing-Chun Liu (PaulLiu) #include <common/fdt_wrappers.h>
15cb2c4f93SYing-Chun Liu (PaulLiu) #include <libfdt.h>
16*885e2683SClaus Pedersen #include <platform_def.h>
17cb2c4f93SYing-Chun Liu (PaulLiu) 
18cb2c4f93SYing-Chun Liu (PaulLiu) #define DTB_PROP_HW_LOG_ADDR	"tpm_event_log_addr"
19cb2c4f93SYing-Chun Liu (PaulLiu) #define DTB_PROP_HW_LOG_SIZE	"tpm_event_log_size"
20cb2c4f93SYing-Chun Liu (PaulLiu) 
21cb2c4f93SYing-Chun Liu (PaulLiu) #if MEASURED_BOOT
22cb2c4f93SYing-Chun Liu (PaulLiu) 
imx8m_event_log_fdt_init_overlay(uintptr_t dt_base,int dt_size)23cb2c4f93SYing-Chun Liu (PaulLiu) static int imx8m_event_log_fdt_init_overlay(uintptr_t dt_base, int dt_size)
24cb2c4f93SYing-Chun Liu (PaulLiu) {
25cb2c4f93SYing-Chun Liu (PaulLiu) 	int ret;
26cb2c4f93SYing-Chun Liu (PaulLiu) 	int offset;
27cb2c4f93SYing-Chun Liu (PaulLiu) 	void *dtb = (void *)dt_base;
28cb2c4f93SYing-Chun Liu (PaulLiu) 
29cb2c4f93SYing-Chun Liu (PaulLiu) 	ret = fdt_create_empty_tree(dtb, dt_size);
30cb2c4f93SYing-Chun Liu (PaulLiu) 	if (ret < 0) {
31cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot create empty dtb tree: %s\n",
32cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(ret));
33cb2c4f93SYing-Chun Liu (PaulLiu) 		return ret;
34cb2c4f93SYing-Chun Liu (PaulLiu) 	}
35cb2c4f93SYing-Chun Liu (PaulLiu) 
36cb2c4f93SYing-Chun Liu (PaulLiu) 	offset = fdt_path_offset(dtb, "/");
37cb2c4f93SYing-Chun Liu (PaulLiu) 	if (offset < 0) {
38cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot find root of the tree: %s\n",
39cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(offset));
40cb2c4f93SYing-Chun Liu (PaulLiu) 		return offset;
41cb2c4f93SYing-Chun Liu (PaulLiu) 	}
42cb2c4f93SYing-Chun Liu (PaulLiu) 
43cb2c4f93SYing-Chun Liu (PaulLiu) 	offset = fdt_add_subnode(dtb, offset, "fragment@0");
44cb2c4f93SYing-Chun Liu (PaulLiu) 	if (offset < 0) {
45cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot add fragment node: %s\n",
46cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(offset));
47cb2c4f93SYing-Chun Liu (PaulLiu) 		return offset;
48cb2c4f93SYing-Chun Liu (PaulLiu) 	}
49cb2c4f93SYing-Chun Liu (PaulLiu) 
50cb2c4f93SYing-Chun Liu (PaulLiu) 	ret = fdt_setprop_string(dtb, offset, "target-path", "/");
51cb2c4f93SYing-Chun Liu (PaulLiu) 	if (ret < 0) {
52cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot set target-path property: %s\n",
53cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(ret));
54cb2c4f93SYing-Chun Liu (PaulLiu) 		return ret;
55cb2c4f93SYing-Chun Liu (PaulLiu) 	}
56cb2c4f93SYing-Chun Liu (PaulLiu) 
57cb2c4f93SYing-Chun Liu (PaulLiu) 	offset = fdt_add_subnode(dtb, offset, "__overlay__");
58cb2c4f93SYing-Chun Liu (PaulLiu) 	if (offset < 0) {
59cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot add __overlay__ node: %s\n",
60cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(offset));
61cb2c4f93SYing-Chun Liu (PaulLiu) 		return ret;
62cb2c4f93SYing-Chun Liu (PaulLiu) 	}
63cb2c4f93SYing-Chun Liu (PaulLiu) 
64cb2c4f93SYing-Chun Liu (PaulLiu) 	offset = fdt_add_subnode(dtb, offset, "tpm_event_log");
65cb2c4f93SYing-Chun Liu (PaulLiu) 	if (offset < 0) {
66cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot add tpm_event_log node: %s\n",
67cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(offset));
68cb2c4f93SYing-Chun Liu (PaulLiu) 		return offset;
69cb2c4f93SYing-Chun Liu (PaulLiu) 	}
70cb2c4f93SYing-Chun Liu (PaulLiu) 
71cb2c4f93SYing-Chun Liu (PaulLiu) 	ret = fdt_setprop_string(dtb, offset, "compatible",
72cb2c4f93SYing-Chun Liu (PaulLiu) 				 "arm,tpm_event_log");
73cb2c4f93SYing-Chun Liu (PaulLiu) 	if (ret < 0) {
74cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot set compatible property: %s\n",
75cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(ret));
76cb2c4f93SYing-Chun Liu (PaulLiu) 		return ret;
77cb2c4f93SYing-Chun Liu (PaulLiu) 	}
78cb2c4f93SYing-Chun Liu (PaulLiu) 
79cb2c4f93SYing-Chun Liu (PaulLiu) 	ret = fdt_setprop_u64(dtb, offset, "tpm_event_log_addr", 0);
80cb2c4f93SYing-Chun Liu (PaulLiu) 	if (ret < 0) {
81cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot set tpm_event_log_addr property: %s\n",
82cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(ret));
83cb2c4f93SYing-Chun Liu (PaulLiu) 		return ret;
84cb2c4f93SYing-Chun Liu (PaulLiu) 	}
85cb2c4f93SYing-Chun Liu (PaulLiu) 
86cb2c4f93SYing-Chun Liu (PaulLiu) 	ret = fdt_setprop_u32(dtb, offset, "tpm_event_log_size", 0);
87cb2c4f93SYing-Chun Liu (PaulLiu) 	if (ret < 0) {
88cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("cannot set tpm_event_log_size property: %s\n",
89cb2c4f93SYing-Chun Liu (PaulLiu) 		       fdt_strerror(ret));
90cb2c4f93SYing-Chun Liu (PaulLiu) 		return ret;
91cb2c4f93SYing-Chun Liu (PaulLiu) 	}
92cb2c4f93SYing-Chun Liu (PaulLiu) 
93cb2c4f93SYing-Chun Liu (PaulLiu) 	return ret;
94cb2c4f93SYing-Chun Liu (PaulLiu) }
95cb2c4f93SYing-Chun Liu (PaulLiu) 
96cb2c4f93SYing-Chun Liu (PaulLiu) /*
97cb2c4f93SYing-Chun Liu (PaulLiu)  * Write the Event Log address and its size in the DTB.
98cb2c4f93SYing-Chun Liu (PaulLiu)  *
99cb2c4f93SYing-Chun Liu (PaulLiu)  * This function is supposed to be called only by BL2.
100cb2c4f93SYing-Chun Liu (PaulLiu)  *
101cb2c4f93SYing-Chun Liu (PaulLiu)  * Returns:
102cb2c4f93SYing-Chun Liu (PaulLiu)  *	0 = success
103cb2c4f93SYing-Chun Liu (PaulLiu)  *    < 0 = error
104cb2c4f93SYing-Chun Liu (PaulLiu)  */
imx8m_set_event_log_info(uintptr_t config_base,uintptr_t log_addr,size_t log_size)105cb2c4f93SYing-Chun Liu (PaulLiu) static int imx8m_set_event_log_info(uintptr_t config_base,
106cb2c4f93SYing-Chun Liu (PaulLiu) 				  uintptr_t log_addr, size_t log_size)
107cb2c4f93SYing-Chun Liu (PaulLiu) {
108cb2c4f93SYing-Chun Liu (PaulLiu) 	/* As libfdt uses void *, we can't avoid this cast */
109cb2c4f93SYing-Chun Liu (PaulLiu) 	void *dtb = (void *)config_base;
110cb2c4f93SYing-Chun Liu (PaulLiu) 	const char *compatible_tpm = "arm,tpm_event_log";
111cb2c4f93SYing-Chun Liu (PaulLiu) 	uint64_t base = cpu_to_fdt64(log_addr);
112cb2c4f93SYing-Chun Liu (PaulLiu) 	uint32_t sz = cpu_to_fdt32(log_size);
113cb2c4f93SYing-Chun Liu (PaulLiu) 	int err, node;
114cb2c4f93SYing-Chun Liu (PaulLiu) 
115cb2c4f93SYing-Chun Liu (PaulLiu) 	err = fdt_open_into(dtb, dtb, PLAT_IMX8M_DTO_MAX_SIZE);
116cb2c4f93SYing-Chun Liu (PaulLiu) 	if (err < 0) {
117cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("Invalid Device Tree at %p: error %d\n", dtb, err);
118cb2c4f93SYing-Chun Liu (PaulLiu) 		return err;
119cb2c4f93SYing-Chun Liu (PaulLiu) 	}
120cb2c4f93SYing-Chun Liu (PaulLiu) 
121cb2c4f93SYing-Chun Liu (PaulLiu) 	/*
122cb2c4f93SYing-Chun Liu (PaulLiu) 	 * Verify that the DTB is valid, before attempting to write to it,
123cb2c4f93SYing-Chun Liu (PaulLiu) 	 * and get the DTB root node.
124cb2c4f93SYing-Chun Liu (PaulLiu) 	 */
125cb2c4f93SYing-Chun Liu (PaulLiu) 
126cb2c4f93SYing-Chun Liu (PaulLiu) 	/* Check if the pointer to DT is correct */
127cb2c4f93SYing-Chun Liu (PaulLiu) 	err = fdt_check_header(dtb);
128cb2c4f93SYing-Chun Liu (PaulLiu) 	if (err < 0) {
129cb2c4f93SYing-Chun Liu (PaulLiu) 		WARN("Invalid DTB file passed\n");
130cb2c4f93SYing-Chun Liu (PaulLiu) 		return err;
131cb2c4f93SYing-Chun Liu (PaulLiu) 	}
132cb2c4f93SYing-Chun Liu (PaulLiu) 
133cb2c4f93SYing-Chun Liu (PaulLiu) 	/*
134cb2c4f93SYing-Chun Liu (PaulLiu) 	 * Find the TPM node in device tree.
135cb2c4f93SYing-Chun Liu (PaulLiu) 	 */
136cb2c4f93SYing-Chun Liu (PaulLiu) 	node = fdt_node_offset_by_compatible(dtb, -1, compatible_tpm);
137cb2c4f93SYing-Chun Liu (PaulLiu) 	if (node < 0) {
138cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("The compatible property '%s' not%s", compatible_tpm,
139cb2c4f93SYing-Chun Liu (PaulLiu) 			" found in the config\n");
140cb2c4f93SYing-Chun Liu (PaulLiu) 		return node;
141cb2c4f93SYing-Chun Liu (PaulLiu) 	}
142cb2c4f93SYing-Chun Liu (PaulLiu) 
143cb2c4f93SYing-Chun Liu (PaulLiu) 	err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_ADDR, &base, 8);
144cb2c4f93SYing-Chun Liu (PaulLiu) 	if (err < 0) {
145cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("Failed to add log addr err %d\n", err);
146cb2c4f93SYing-Chun Liu (PaulLiu) 		return err;
147cb2c4f93SYing-Chun Liu (PaulLiu) 	}
148cb2c4f93SYing-Chun Liu (PaulLiu) 
149cb2c4f93SYing-Chun Liu (PaulLiu) 	err = fdt_setprop(dtb, node, DTB_PROP_HW_LOG_SIZE, &sz, 4);
150cb2c4f93SYing-Chun Liu (PaulLiu) 	if (err < 0) {
151cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("Failed to add log addr err %d\n", err);
152cb2c4f93SYing-Chun Liu (PaulLiu) 		return err;
153cb2c4f93SYing-Chun Liu (PaulLiu) 	}
154cb2c4f93SYing-Chun Liu (PaulLiu) 
155cb2c4f93SYing-Chun Liu (PaulLiu) 	err = fdt_pack(dtb);
156cb2c4f93SYing-Chun Liu (PaulLiu) 	if (err < 0) {
157cb2c4f93SYing-Chun Liu (PaulLiu) 		ERROR("Failed to pack Device Tree at %p: error %d\n", dtb, err);
158cb2c4f93SYing-Chun Liu (PaulLiu) 		return err;
159cb2c4f93SYing-Chun Liu (PaulLiu) 	}
160cb2c4f93SYing-Chun Liu (PaulLiu) 
161cb2c4f93SYing-Chun Liu (PaulLiu) 	/*
162cb2c4f93SYing-Chun Liu (PaulLiu) 	 * Ensure that the info written to the DTB is visible
163cb2c4f93SYing-Chun Liu (PaulLiu) 	 * to other images.
164cb2c4f93SYing-Chun Liu (PaulLiu) 	 */
165cb2c4f93SYing-Chun Liu (PaulLiu) 	flush_dcache_range(config_base, fdt_totalsize(dtb));
166cb2c4f93SYing-Chun Liu (PaulLiu) 
167cb2c4f93SYing-Chun Liu (PaulLiu) 	return err;
168cb2c4f93SYing-Chun Liu (PaulLiu) }
169cb2c4f93SYing-Chun Liu (PaulLiu) 
170cb2c4f93SYing-Chun Liu (PaulLiu) /*
171cb2c4f93SYing-Chun Liu (PaulLiu)  * This function writes the Event Log address and its size
172cb2c4f93SYing-Chun Liu (PaulLiu)  * in the QEMU DTB.
173cb2c4f93SYing-Chun Liu (PaulLiu)  *
174cb2c4f93SYing-Chun Liu (PaulLiu)  * This function is supposed to be called only by BL2.
175cb2c4f93SYing-Chun Liu (PaulLiu)  *
176cb2c4f93SYing-Chun Liu (PaulLiu)  * Returns:
177cb2c4f93SYing-Chun Liu (PaulLiu)  *	0 = success
178cb2c4f93SYing-Chun Liu (PaulLiu)  *    < 0 = error
179cb2c4f93SYing-Chun Liu (PaulLiu)  */
imx8m_set_nt_fw_info(size_t log_size,uintptr_t * ns_log_addr)180cb2c4f93SYing-Chun Liu (PaulLiu) int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr)
181cb2c4f93SYing-Chun Liu (PaulLiu) {
182cb2c4f93SYing-Chun Liu (PaulLiu) 	uintptr_t ns_addr;
183cb2c4f93SYing-Chun Liu (PaulLiu) 	int err;
184cb2c4f93SYing-Chun Liu (PaulLiu) 
185cb2c4f93SYing-Chun Liu (PaulLiu) 	assert(ns_log_addr != NULL);
186cb2c4f93SYing-Chun Liu (PaulLiu) 
187cb2c4f93SYing-Chun Liu (PaulLiu) 	ns_addr = PLAT_IMX8M_DTO_BASE + PLAT_IMX8M_DTO_MAX_SIZE;
188cb2c4f93SYing-Chun Liu (PaulLiu) 
189cb2c4f93SYing-Chun Liu (PaulLiu) 	imx8m_event_log_fdt_init_overlay(PLAT_IMX8M_DTO_BASE,
190cb2c4f93SYing-Chun Liu (PaulLiu) 					  PLAT_IMX8M_DTO_MAX_SIZE);
191cb2c4f93SYing-Chun Liu (PaulLiu) 
192cb2c4f93SYing-Chun Liu (PaulLiu) 	/* Write the Event Log address and its size in the DTB */
193cb2c4f93SYing-Chun Liu (PaulLiu) 	err = imx8m_set_event_log_info(PLAT_IMX8M_DTO_BASE,
194cb2c4f93SYing-Chun Liu (PaulLiu) 					ns_addr, log_size);
195cb2c4f93SYing-Chun Liu (PaulLiu) 
196cb2c4f93SYing-Chun Liu (PaulLiu) 	/* Return Event Log address in Non-secure memory */
197cb2c4f93SYing-Chun Liu (PaulLiu) 	*ns_log_addr = (err < 0) ? 0UL : ns_addr;
198cb2c4f93SYing-Chun Liu (PaulLiu) 	return err;
199cb2c4f93SYing-Chun Liu (PaulLiu) }
200cb2c4f93SYing-Chun Liu (PaulLiu) 
201cb2c4f93SYing-Chun Liu (PaulLiu) #endif /* MEASURED_BOOT */
202