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