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