xref: /rk3399_ARM-atf/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c (revision f2de48cb143c20ccd7a9c141df3d34cae74049de)
1 /*
2  * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
3  * Copyright (c) 2022, Linaro.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <assert.h>
9 
10 #include <arch_helpers.h>
11 #if MEASURED_BOOT
12 #include <common/desc_image_load.h>
13 #endif
14 #include <common/fdt_wrappers.h>
15 #include <libfdt.h>
16 
17 #define DTB_PROP_HW_LOG_ADDR	"tpm_event_log_addr"
18 #define DTB_PROP_HW_LOG_SIZE	"tpm_event_log_size"
19 
20 #if MEASURED_BOOT
21 
22 static int imx8m_event_log_fdt_init_overlay(uintptr_t dt_base, int dt_size)
23 {
24 	int ret;
25 	int offset;
26 	void *dtb = (void *)dt_base;
27 
28 	ret = fdt_create_empty_tree(dtb, dt_size);
29 	if (ret < 0) {
30 		ERROR("cannot create empty dtb tree: %s\n",
31 		       fdt_strerror(ret));
32 		return ret;
33 	}
34 
35 	offset = fdt_path_offset(dtb, "/");
36 	if (offset < 0) {
37 		ERROR("cannot find root of the tree: %s\n",
38 		       fdt_strerror(offset));
39 		return offset;
40 	}
41 
42 	offset = fdt_add_subnode(dtb, offset, "fragment@0");
43 	if (offset < 0) {
44 		ERROR("cannot add fragment node: %s\n",
45 		       fdt_strerror(offset));
46 		return offset;
47 	}
48 
49 	ret = fdt_setprop_string(dtb, offset, "target-path", "/");
50 	if (ret < 0) {
51 		ERROR("cannot set target-path property: %s\n",
52 		       fdt_strerror(ret));
53 		return ret;
54 	}
55 
56 	offset = fdt_add_subnode(dtb, offset, "__overlay__");
57 	if (offset < 0) {
58 		ERROR("cannot add __overlay__ node: %s\n",
59 		       fdt_strerror(offset));
60 		return ret;
61 	}
62 
63 	offset = fdt_add_subnode(dtb, offset, "tpm_event_log");
64 	if (offset < 0) {
65 		ERROR("cannot add tpm_event_log node: %s\n",
66 		       fdt_strerror(offset));
67 		return offset;
68 	}
69 
70 	ret = fdt_setprop_string(dtb, offset, "compatible",
71 				 "arm,tpm_event_log");
72 	if (ret < 0) {
73 		ERROR("cannot set compatible property: %s\n",
74 		       fdt_strerror(ret));
75 		return ret;
76 	}
77 
78 	ret = fdt_setprop_u64(dtb, offset, "tpm_event_log_addr", 0);
79 	if (ret < 0) {
80 		ERROR("cannot set tpm_event_log_addr property: %s\n",
81 		       fdt_strerror(ret));
82 		return ret;
83 	}
84 
85 	ret = fdt_setprop_u32(dtb, offset, "tpm_event_log_size", 0);
86 	if (ret < 0) {
87 		ERROR("cannot set tpm_event_log_size property: %s\n",
88 		       fdt_strerror(ret));
89 		return ret;
90 	}
91 
92 	return ret;
93 }
94 
95 /*
96  * Write the Event Log address and its size in the DTB.
97  *
98  * This function is supposed to be called only by BL2.
99  *
100  * Returns:
101  *	0 = success
102  *    < 0 = error
103  */
104 static int imx8m_set_event_log_info(uintptr_t config_base,
105 				  uintptr_t log_addr, size_t log_size)
106 {
107 	/* As libfdt uses void *, we can't avoid this cast */
108 	void *dtb = (void *)config_base;
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_IMX8M_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 addr 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 QEMU 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 imx8m_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_IMX8M_DTO_BASE + PLAT_IMX8M_DTO_MAX_SIZE;
187 
188 	imx8m_event_log_fdt_init_overlay(PLAT_IMX8M_DTO_BASE,
189 					  PLAT_IMX8M_DTO_MAX_SIZE);
190 
191 	/* Write the Event Log address and its size in the DTB */
192 	err = imx8m_set_event_log_info(PLAT_IMX8M_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 
200 #endif /* MEASURED_BOOT */
201