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