blob: 36d37f8f66069ae4091d765eeb9a59e3a1b2e3bb [file] [log] [blame]
Soby Mathew96a1c6b2018-01-15 14:45:33 +00001/*
2 * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +00008
Soby Mathew96a1c6b2018-01-15 14:45:33 +00009#include <libfdt.h>
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010
11#include <common/desc_image_load.h>
12#include <common/fdt_wrappers.h>
Antonio Nino Diazbd7b7402019-01-25 14:30:04 +000013#include <plat/arm/common/arm_dyn_cfg_helpers.h>
14#include <plat/arm/common/plat_arm.h>
Soby Mathew96a1c6b2018-01-15 14:45:33 +000015
John Tsichritzisc34341a2018-07-30 13:41:52 +010016#define DTB_PROP_MBEDTLS_HEAP_ADDR "mbedtls_heap_addr"
17#define DTB_PROP_MBEDTLS_HEAP_SIZE "mbedtls_heap_size"
Soby Mathewb6814842018-04-04 09:40:32 +010018
19typedef struct config_load_info_prop {
20 unsigned int config_id;
21 const char *config_addr;
22 const char *config_max_size;
23} config_load_info_prop_t;
24
25static const config_load_info_prop_t prop_names[] = {
26 {HW_CONFIG_ID, "hw_config_addr", "hw_config_max_size"},
27 {SOC_FW_CONFIG_ID, "soc_fw_config_addr", "soc_fw_config_max_size"},
28 {TOS_FW_CONFIG_ID, "tos_fw_config_addr", "tos_fw_config_max_size"},
29 {NT_FW_CONFIG_ID, "nt_fw_config_addr", "nt_fw_config_max_size"}
30};
31
Soby Mathew96a1c6b2018-01-15 14:45:33 +000032/*******************************************************************************
Soby Mathewb6814842018-04-04 09:40:32 +010033 * Helper to read the load information corresponding to the `config_id` in
34 * TB_FW_CONFIG. This function expects the following properties to be defined :
35 * <config>_addr size : 2 cells
36 * <config>_max_size size : 1 cell
Soby Mathew96a1c6b2018-01-15 14:45:33 +000037 *
38 * Arguments:
39 * void *dtb - pointer to the TB_FW_CONFIG in memory
40 * int node - The node offset to appropriate node in the
41 * DTB.
Soby Mathewb6814842018-04-04 09:40:32 +010042 * unsigned int config_id - The configuration id
43 * uint64_t *config_addr - Returns the `config` load address if read
Soby Mathew96a1c6b2018-01-15 14:45:33 +000044 * is successful.
Soby Mathewb6814842018-04-04 09:40:32 +010045 * uint32_t *config_size - Returns the `config` size if read is
Soby Mathew96a1c6b2018-01-15 14:45:33 +000046 * successful.
47 *
48 * Returns 0 on success and -1 on error.
49 ******************************************************************************/
Soby Mathewb6814842018-04-04 09:40:32 +010050int arm_dyn_get_config_load_info(void *dtb, int node, unsigned int config_id,
51 uint64_t *config_addr, uint32_t *config_size)
Soby Mathew96a1c6b2018-01-15 14:45:33 +000052{
53 int err;
Soby Mathewb6814842018-04-04 09:40:32 +010054 unsigned int i;
Soby Mathew96a1c6b2018-01-15 14:45:33 +000055
Soby Mathewcc364842018-02-21 01:16:39 +000056 assert(dtb != NULL);
Soby Mathewb6814842018-04-04 09:40:32 +010057 assert(config_addr != NULL);
58 assert(config_size != NULL);
59
60 for (i = 0; i < ARRAY_SIZE(prop_names); i++) {
61 if (prop_names[i].config_id == config_id)
62 break;
63 }
64
65 if (i == ARRAY_SIZE(prop_names)) {
66 WARN("Invalid config id %d\n", config_id);
67 return -1;
68 }
Soby Mathew96a1c6b2018-01-15 14:45:33 +000069
70 /* Check if the pointer to DT is correct */
71 assert(fdt_check_header(dtb) == 0);
72
73 /* Assert the node offset point to "arm,tb_fw" compatible property */
74 assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
75
Soby Mathewb6814842018-04-04 09:40:32 +010076 err = fdtw_read_cells(dtb, node, prop_names[i].config_addr, 2,
77 (void *) config_addr);
Soby Mathew96a1c6b2018-01-15 14:45:33 +000078 if (err < 0) {
Soby Mathewb6814842018-04-04 09:40:32 +010079 WARN("Read cell failed for %s\n", prop_names[i].config_addr);
Soby Mathew96a1c6b2018-01-15 14:45:33 +000080 return -1;
81 }
82
Soby Mathewb6814842018-04-04 09:40:32 +010083 err = fdtw_read_cells(dtb, node, prop_names[i].config_max_size, 1,
84 (void *) config_size);
Soby Mathew96a1c6b2018-01-15 14:45:33 +000085 if (err < 0) {
Soby Mathewb6814842018-04-04 09:40:32 +010086 WARN("Read cell failed for %s\n", prop_names[i].config_max_size);
Soby Mathew96a1c6b2018-01-15 14:45:33 +000087 return -1;
88 }
89
Soby Mathewb6814842018-04-04 09:40:32 +010090 VERBOSE("Dyn cfg: Read config_id %d load info from TB_FW_CONFIG 0x%llx 0x%x\n",
91 config_id, (unsigned long long)*config_addr, *config_size);
Soby Mathew96a1c6b2018-01-15 14:45:33 +000092
93 return 0;
94}
95
96/*******************************************************************************
Soby Mathew45e39e22018-03-26 15:16:46 +010097 * Helper to read the `disable_auth` property in config DTB. This function
98 * expects the following properties to be present in the config DTB.
99 * name : disable_auth size : 1 cell
100 *
101 * Arguments:
102 * void *dtb - pointer to the TB_FW_CONFIG in memory
103 * int node - The node offset to appropriate node in the
104 * DTB.
105 * uint64_t *disable_auth - The value of `disable_auth` property on
106 * successful read. Must be 0 or 1.
107 *
108 * Returns 0 on success and -1 on error.
109 ******************************************************************************/
110int arm_dyn_get_disable_auth(void *dtb, int node, uint32_t *disable_auth)
111{
112 int err;
113
114 assert(dtb != NULL);
115 assert(disable_auth != NULL);
116
117 /* Check if the pointer to DT is correct */
118 assert(fdt_check_header(dtb) == 0);
119
120 /* Assert the node offset point to "arm,tb_fw" compatible property */
121 assert(node == fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw"));
122
123 /* Locate the disable_auth cell and read the value */
124 err = fdtw_read_cells(dtb, node, "disable_auth", 1, disable_auth);
125 if (err < 0) {
126 WARN("Read cell failed for `disable_auth`\n");
127 return -1;
128 }
129
130 /* Check if the value is boolean */
Soby Mathewb6814842018-04-04 09:40:32 +0100131 if ((*disable_auth != 0U) && (*disable_auth != 1U)) {
Soby Mathew45e39e22018-03-26 15:16:46 +0100132 WARN("Invalid value for `disable_auth` cell %d\n", *disable_auth);
133 return -1;
134 }
135
136 VERBOSE("Dyn cfg: `disable_auth` cell found with value = %d\n",
137 *disable_auth);
138 return 0;
139}
140
141/*******************************************************************************
Soby Mathew96a1c6b2018-01-15 14:45:33 +0000142 * Validate the tb_fw_config is a valid DTB file and returns the node offset
143 * to "arm,tb_fw" property.
144 * Arguments:
145 * void *dtb - pointer to the TB_FW_CONFIG in memory
146 * int *node - Returns the node offset to "arm,tb_fw" property if found.
147 *
148 * Returns 0 on success and -1 on error.
149 ******************************************************************************/
150int arm_dyn_tb_fw_cfg_init(void *dtb, int *node)
151{
Soby Mathewcc364842018-02-21 01:16:39 +0000152 assert(dtb != NULL);
153 assert(node != NULL);
Soby Mathew96a1c6b2018-01-15 14:45:33 +0000154
155 /* Check if the pointer to DT is correct */
156 if (fdt_check_header(dtb) != 0) {
157 WARN("Invalid DTB file passed as TB_FW_CONFIG\n");
158 return -1;
159 }
160
161 /* Assert the node offset point to "arm,tb_fw" compatible property */
162 *node = fdt_node_offset_by_compatible(dtb, -1, "arm,tb_fw");
163 if (*node < 0) {
164 WARN("The compatible property `arm,tb_fw` not found in the config\n");
165 return -1;
166 }
167
168 VERBOSE("Dyn cfg: Found \"arm,tb_fw\" in the config\n");
169 return 0;
170}
John Tsichritzisc34341a2018-07-30 13:41:52 +0100171
John Tsichritzisc34341a2018-07-30 13:41:52 +0100172/*
173 * Reads and returns the Mbed TLS shared heap information from the DTB.
174 * This function is supposed to be called *only* when a DTB is present.
175 * This function is supposed to be called only by BL2.
176 *
177 * Returns:
178 * 0 = success
179 * -1 = error. In this case the values of heap_addr, heap_size should be
180 * considered as garbage by the caller.
181 */
182int arm_get_dtb_mbedtls_heap_info(void *dtb, void **heap_addr,
183 size_t *heap_size)
184{
185 int err, dtb_root;
186
187 /* Verify the DTB is valid and get the root node */
188 err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
189 if (err < 0) {
John Tsichritzis3a20a732018-09-07 10:38:01 +0100190 ERROR("Invalid TB_FW_CONFIG. Cannot retrieve Mbed TLS heap information from DTB\n");
John Tsichritzisc34341a2018-07-30 13:41:52 +0100191 return -1;
192 }
193
194 /* Retrieve the Mbed TLS heap details from the DTB */
195 err = fdtw_read_cells(dtb, dtb_root,
196 DTB_PROP_MBEDTLS_HEAP_ADDR, 2, heap_addr);
197 if (err < 0) {
John Tsichritzis3a20a732018-09-07 10:38:01 +0100198 ERROR("Error while reading %s from DTB\n",
John Tsichritzisc34341a2018-07-30 13:41:52 +0100199 DTB_PROP_MBEDTLS_HEAP_ADDR);
200 return -1;
201 }
202 err = fdtw_read_cells(dtb, dtb_root,
203 DTB_PROP_MBEDTLS_HEAP_SIZE, 1, heap_size);
204 if (err < 0) {
John Tsichritzis3a20a732018-09-07 10:38:01 +0100205 ERROR("Error while reading %s from DTB\n",
John Tsichritzisc34341a2018-07-30 13:41:52 +0100206 DTB_PROP_MBEDTLS_HEAP_SIZE);
207 return -1;
208 }
209 return 0;
210}
211
212
213/*
214 * This function writes the Mbed TLS heap address and size in the DTB. When it
215 * is called, it is guaranteed that a DTB is available. However it is not
216 * guaranteed that the shared Mbed TLS heap implementation is used. Thus we
217 * return error code from here and it's the responsibility of the caller to
218 * determine the action upon error.
219 *
220 * This function is supposed to be called only by BL1.
221 *
222 * Returns:
223 * 0 = success
224 * 1 = error
225 */
226int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, size_t heap_size)
227{
228 int err, dtb_root;
229
230 /*
231 * Verify that the DTB is valid, before attempting to write to it,
232 * and get the DTB root node.
233 */
234 err = arm_dyn_tb_fw_cfg_init(dtb, &dtb_root);
235 if (err < 0) {
John Tsichritzis3a20a732018-09-07 10:38:01 +0100236 ERROR("Invalid TB_FW_CONFIG loaded. Unable to get root node\n");
John Tsichritzisc34341a2018-07-30 13:41:52 +0100237 return -1;
238 }
239
240 /*
241 * Write the heap address and size in the DTB.
242 *
243 * NOTE: The variables heap_addr and heap_size are corrupted
244 * by the "fdtw_write_inplace_cells" function. After the
245 * function calls they must NOT be reused.
246 */
247 err = fdtw_write_inplace_cells(dtb, dtb_root,
248 DTB_PROP_MBEDTLS_HEAP_ADDR, 2, &heap_addr);
249 if (err < 0) {
John Tsichritzis3a20a732018-09-07 10:38:01 +0100250 ERROR("Unable to write DTB property %s\n",
251 DTB_PROP_MBEDTLS_HEAP_ADDR);
John Tsichritzisc34341a2018-07-30 13:41:52 +0100252 return -1;
253 }
254
255 err = fdtw_write_inplace_cells(dtb, dtb_root,
256 DTB_PROP_MBEDTLS_HEAP_SIZE, 1, &heap_size);
257 if (err < 0) {
John Tsichritzis3a20a732018-09-07 10:38:01 +0100258 ERROR("Unable to write DTB property %s\n",
259 DTB_PROP_MBEDTLS_HEAP_SIZE);
John Tsichritzisc34341a2018-07-30 13:41:52 +0100260 return -1;
261 }
262
263 return 0;
264}