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