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