aboutsummaryrefslogtreecommitdiff
path: root/plat/arm/common/arm_dyn_cfg_helpers.c
blob: 5f20c8d481089f6d5904ccc1b21ed1f440068109 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/*
 * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <assert.h>

#if MEASURED_BOOT
#include <common/desc_image_load.h>
#endif
#include <common/fdt_wrappers.h>

#include <libfdt.h>

#include <plat/arm/common/arm_dyn_cfg_helpers.h>
#include <plat/arm/common/plat_arm.h>

#define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr"
#define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size"

#if MEASURED_BOOT
#define DTB_PROP_BL2_HASH_DATA	"bl2_hash_data"
#ifdef SPD_opteed
/*
 * Currently OP-TEE does not support reading DTBs from Secure memory
 * and this property should be removed when this feature is supported.
 */
#define DTB_PROP_HW_SM_LOG_ADDR	"tpm_event_log_sm_addr"
#endif
#define DTB_PROP_HW_LOG_ADDR	"tpm_event_log_addr"
#define DTB_PROP_HW_LOG_SIZE    "tpm_event_log_size"

static int dtb_root = -1;
#endif /* MEASURED_BOOT */

/*******************************************************************************
 * Validate the tb_fw_config is a valid DTB file and returns the node offset
 * to "arm,tb_fw" property.
 * Arguments:
 *	void *dtb - pointer to the TB_FW_CONFIG in memory
 *	int *node - Returns the node offset to "arm,tb_fw" property if found.
 *
 * Returns 0 on success and -1 on error.
 ******************************************************************************/
int arm_dyn_tb_fw_cfg_init(void *dtb, int *node)
{
	assert(dtb != NULL);
	assert(node != NULL);

	/* Check if the pointer to DT is correct */
	if (fdt_check_header(dtb) != 0) {
		WARN("Invalid DTB file passed as%s\n", " TB_FW_CONFIG");
		return -1;
	}

	/* Assert the node offset point to "arm,tb_fw" compatible property */
	*node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
	if (*node < 0) {
		WARN("The compatible property '%s' not%s", "arm,tb_fw",
			" found in the config\n");
		return -1;
	}

	VERBOSE("Dyn cfg: '%s'%s", "arm,tb_fw", " found in the config\n");
	return 0;
}

/*
 * This function writes the Mbed TLS heap address and size in the DTB. When it
 * is called, it is guaranteed that a DTB is available. However it is not
 * guaranteed that the shared Mbed TLS heap implementation is used. Thus we
 * return error code from here and it's the responsibility of the caller to
 * determine the action upon error.
 *
 * This function is supposed to be called only by BL1.
 *
 * Returns:
 *	0 = success
 *     -1 = error
 */
int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size)
{
#if !MEASURED_BOOT
	int dtb_root;
#endif
	/*
	 * Verify that the DTB is valid, before attempting to write to it,
	 * and get the DTB root node.
	 */
	int err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
	if (err < 0) {
		ERROR("Invalid%s loaded. Unable to get root node\n",
			" TB_FW_CONFIG");
		return -1;
	}

	/*
	 * Write the heap address and size in the DTB.
	 *
	 * NOTE: The variables heap_addr and heap_size are corrupted
	 * by the "fdtw_write_inplace_cells" function. After the
	 * function calls they must NOT be reused.
	 */
	err = fdtw_write_inplace_cells(dtb, dtb_root,
		DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr);
	if (err < 0) {
		ERROR("%sDTB property '%s'\n",
			"Unable to write ", DTB_PROP_MBEDTLS_HEAP_ADDR);
		return -1;
	}

	err = fdtw_write_inplace_cells(dtb, dtb_root,
		DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size);
	if (err < 0) {
		ERROR("%sDTB property '%s'\n",
			"Unable to write ", DTB_PROP_MBEDTLS_HEAP_SIZE);
		return -1;
	}

	return 0;
}

#if MEASURED_BOOT
/*
 * This function writes the BL2 hash data in HW_FW_CONFIG DTB.
 * When it is called, it is guaranteed that a DTB is available.
 *
 * This function is supposed to be called only by BL1.
 *
 * Returns:
 *	0 = success
 *    < 0 = error
 */
int arm_set_bl2_hash_info(void *dtb, void *data)
{
	assert(dtb_root >= 0);

	/*
	 * Write the BL2 hash data in the DTB.
	 */
	return fdtw_write_inplace_bytes(dtb, dtb_root,
					DTB_PROP_BL2_HASH_DATA,
					TCG_DIGEST_SIZE, data);
}

/*
 * Write the Event Log address and its size in the DTB.
 *
 * This function is supposed to be called only by BL2.
 *
 * Returns:
 *	0 = success
 *    < 0 = error
 */
static int arm_set_event_log_info(uintptr_t config_base,
#ifdef SPD_opteed
				  uintptr_t sm_log_addr,
#endif
				  uintptr_t log_addr, size_t log_size)
{
	/* As libfdt uses void *, we can't avoid this cast */
	void *dtb = (void *)config_base;
	const char *compatible = "arm,tpm_event_log";
	int err, node;

	/*
	 * Verify that the DTB is valid, before attempting to write to it,
	 * and get the DTB root node.
	 */

	/* Check if the pointer to DT is correct */
	err = fdt_check_header(dtb);
	if (err < 0) {
		WARN("Invalid DTB file passed\n");
		return err;
	}

	/* Assert the node offset point to compatible property */
	node = fdt_node_offset_by_compatible(dtb, -1, compatible);
	if (node < 0) {
		WARN("The compatible property '%s' not%s", compatible,
			" found in the config\n");
		return node;
	}

	VERBOSE("Dyn cfg: '%s'%s", compatible, " found in the config\n");

#ifdef SPD_opteed
	if (sm_log_addr != 0UL) {
		err = fdtw_write_inplace_cells(dtb, node,
			DTB_PROP_HW_SM_LOG_ADDR, 2, &sm_log_addr);
		if (err < 0) {
			ERROR("%sDTB property '%s'\n",
				"Unable to write ", DTB_PROP_HW_SM_LOG_ADDR);
			return err;
		}
	}
#endif
	err = fdtw_write_inplace_cells(dtb, node,
		DTB_PROP_HW_LOG_ADDR, 2, &log_addr);
	if (err < 0) {
		ERROR("%sDTB property '%s'\n",
			"Unable to write ", DTB_PROP_HW_LOG_ADDR);
		return err;
	}

	err = fdtw_write_inplace_cells(dtb, node,
		DTB_PROP_HW_LOG_SIZE, 1, &log_size);
	if (err < 0) {
		ERROR("%sDTB property '%s'\n",
			"Unable to write ", DTB_PROP_HW_LOG_SIZE);
	} else {
		/*
		 * Ensure that the info written to the DTB is visible
		 * to other images.
		 */
		flush_dcache_range(config_base, fdt_totalsize(dtb));
	}

	return err;
}

/*
 * This function writes the Event Log address and its size
 * in the TOS_FW_CONFIG DTB.
 *
 * This function is supposed to be called only by BL2.
 *
 * Returns:
 *	0 = success
 *    < 0 = error
 */
int arm_set_tos_fw_info(uintptr_t config_base, uintptr_t log_addr,
			size_t log_size)
{
	int err;

	assert(config_base != 0UL);
	assert(log_addr != 0UL);

	/* Write the Event Log address and its size in the DTB */
	err = arm_set_event_log_info(config_base,
#ifdef SPD_opteed
					0UL,
#endif
					log_addr, log_size);
	if (err < 0) {
		ERROR("%sEvent Log data to TOS_FW_CONFIG\n",
					"Unable to write ");
	}

	return err;
}

/*
 * This function writes the Event Log address and its size
 * in the NT_FW_CONFIG DTB.
 *
 * This function is supposed to be called only by BL2.
 *
 * Returns:
 *	0 = success
 *    < 0 = error
 */
int arm_set_nt_fw_info(uintptr_t config_base,
#ifdef SPD_opteed
			uintptr_t log_addr,
#endif
			size_t log_size, uintptr_t *ns_log_addr)
{
	uintptr_t ns_addr;
	const bl_mem_params_node_t *cfg_mem_params;
	int err;

	assert(config_base != 0UL);
	assert(ns_log_addr != NULL);

	/* Get the config load address and size from NT_FW_CONFIG */
	cfg_mem_params = get_bl_mem_params_node(NT_FW_CONFIG_ID);
	assert(cfg_mem_params != NULL);

	/* Calculate Event Log address in Non-secure memory */
	ns_addr = cfg_mem_params->image_info.image_base +
			cfg_mem_params->image_info.image_max_size;

	/* Check for memory space */
	if ((uint64_t)(ns_addr + log_size) > ARM_NS_DRAM1_END) {
		return -1;
	}

	/* Write the Event Log address and its size in the DTB */
	err = arm_set_event_log_info(config_base,
#ifdef SPD_opteed
					log_addr,
#endif
					ns_addr, log_size);

	/* Return Event Log address in Non-secure memory */
	*ns_log_addr = (err < 0) ? 0UL : ns_addr;
	return err;
}
#endif /* MEASURED_BOOT */