1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright 2015-2016 Freescale Semiconductor, Inc.
4 * Copyright 2017,2021 NXP
5 */
6
7 /*
8 * @file
9 * Contains all the functions to handle parsing and loading of PE firmware
10 * files.
11 */
12
13 #include <dm.h>
14 #include <dm/device-internal.h>
15 #include <env.h>
16 #include <image.h>
17 #include <log.h>
18 #include <malloc.h>
19 #include <linux/bitops.h>
20 #include <net/pfe_eth/pfe_eth.h>
21 #include <net/pfe_eth/pfe_firmware.h>
22 #include <spi_flash.h>
23 #ifdef CONFIG_CHAIN_OF_TRUST
24 #include <fsl_validate.h>
25 #endif
26
27 #define PFE_FIRMWARE_FIT_CNF_NAME "config@1"
28
29 static const void *pfe_fit_addr;
30 #ifdef CONFIG_CHAIN_OF_TRUST
31 static const void *pfe_esbc_hdr_addr;
32 #endif
33
34 /*
35 * PFE elf firmware loader.
36 * Loads an elf firmware image into a list of PE's (specified using a bitmask)
37 *
38 * @param pe_mask Mask of PE id's to load firmware to
39 * @param pfe_firmware Pointer to the firmware image
40 *
41 * Return: 0 on success, a negative value on error
42 */
pfe_load_elf(int pe_mask,uint8_t * pfe_firmware)43 static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
44 {
45 Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *)pfe_firmware;
46 Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum);
47 Elf32_Shdr *shdr = (Elf32_Shdr *)(pfe_firmware +
48 be32_to_cpu(elf_hdr->e_shoff));
49 int id, section;
50 int ret;
51
52 debug("%s: no of sections: %d\n", __func__, sections);
53
54 /* Some sanity checks */
55 if (strncmp((char *)&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
56 printf("%s: incorrect elf magic number\n", __func__);
57 return -1;
58 }
59
60 if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
61 printf("%s: incorrect elf class(%x)\n", __func__,
62 elf_hdr->e_ident[EI_CLASS]);
63 return -1;
64 }
65
66 if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) {
67 printf("%s: incorrect elf data(%x)\n", __func__,
68 elf_hdr->e_ident[EI_DATA]);
69 return -1;
70 }
71
72 if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) {
73 printf("%s: incorrect elf file type(%x)\n", __func__,
74 be16_to_cpu(elf_hdr->e_type));
75 return -1;
76 }
77
78 for (section = 0; section < sections; section++, shdr++) {
79 if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
80 SHF_EXECINSTR)))
81 continue;
82 for (id = 0; id < MAX_PE; id++)
83 if (pe_mask & BIT(id)) {
84 ret = pe_load_elf_section(id,
85 pfe_firmware, shdr);
86 if (ret < 0)
87 goto err;
88 }
89 }
90 return 0;
91
92 err:
93 return ret;
94 }
95
96 /*
97 * Get PFE firmware from FIT image
98 *
99 * @param data pointer to PFE firmware
100 * @param size pointer to size of the firmware
101 * @param fw_name pfe firmware name, either class or tmu
102 *
103 * Return: 0 on success, a negative value on error
104 */
pfe_get_fw(const void ** data,size_t * size,char * fw_name)105 static int pfe_get_fw(const void **data,
106 size_t *size, char *fw_name)
107 {
108 return fit_get_data_conf_prop(pfe_fit_addr, fw_name, data, size);
109 }
110
111 /*
112 * Check PFE FIT image
113 *
114 * Return: 0 on success, a negative value on error
115 */
pfe_fit_check(void)116 static int pfe_fit_check(void)
117 {
118 int ret = 0;
119
120 ret = fdt_check_header(pfe_fit_addr);
121 if (ret) {
122 printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
123 return ret;
124 }
125
126 if (fit_check_format(pfe_fit_addr, IMAGE_SIZE_INVAL)) {
127 printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
128 ret = -1;
129 return ret;
130 }
131
132 return ret;
133 }
134
pfe_spi_flash_init(void)135 int pfe_spi_flash_init(void)
136 {
137 struct spi_flash *pfe_flash;
138 int ret = 0;
139 void *addr = malloc(CONFIG_SYS_LS_PFE_FW_LENGTH);
140
141 if (!addr)
142 return -ENOMEM;
143
144 pfe_flash = spi_flash_probe(CONFIG_SYS_FSL_PFE_SPI_BUS,
145 CONFIG_SYS_FSL_PFE_SPI_CS,
146 CONFIG_SYS_FSL_PFE_SPI_MAX_HZ,
147 CONFIG_SYS_FSL_PFE_SPI_MODE);
148
149 if (!pfe_flash) {
150 printf("SF: probe for pfe failed\n");
151 free(addr);
152 return -ENODEV;
153 }
154
155 ret = spi_flash_read(pfe_flash,
156 CONFIG_SYS_LS_PFE_FW_ADDR,
157 CONFIG_SYS_LS_PFE_FW_LENGTH,
158 addr);
159 if (ret) {
160 printf("SF: read for pfe failed\n");
161 free(addr);
162 spi_flash_free(pfe_flash);
163 return ret;
164 }
165
166 #ifdef CONFIG_CHAIN_OF_TRUST
167 void *hdr_addr = malloc(CONFIG_SYS_LS_PFE_ESBC_LENGTH);
168
169 if (!hdr_addr) {
170 free(addr);
171 spi_flash_free(pfe_flash);
172 return -ENOMEM;
173 }
174
175 ret = spi_flash_read(pfe_flash,
176 CONFIG_SYS_LS_PFE_ESBC_ADDR,
177 CONFIG_SYS_LS_PFE_ESBC_LENGTH,
178 hdr_addr);
179 if (ret) {
180 printf("SF: failed to read pfe esbc header\n");
181 free(addr);
182 free(hdr_addr);
183 spi_flash_free(pfe_flash);
184 return ret;
185 }
186
187 pfe_esbc_hdr_addr = hdr_addr;
188 #endif
189 pfe_fit_addr = addr;
190 spi_flash_free(pfe_flash);
191
192 return ret;
193 }
194
195 /*
196 * PFE firmware initialization.
197 * Loads different firmware files from FIT image.
198 * Initializes PE IMEM/DMEM and UTIL-PE DDR
199 * Initializes control path symbol addresses (by looking them up in the elf
200 * firmware files
201 * Takes PE's out of reset
202 *
203 * Return: 0 on success, a negative value on error
204 */
pfe_firmware_init(void)205 int pfe_firmware_init(void)
206 {
207 #define PFE_KEY_HASH NULL
208 char *pfe_firmware_name;
209 const void *raw_image_addr;
210 size_t raw_image_size = 0;
211 u8 *pfe_firmware;
212 #ifdef CONFIG_CHAIN_OF_TRUST
213 uintptr_t pfe_esbc_hdr = 0;
214 uintptr_t pfe_img_addr = 0;
215 #endif
216 int ret = 0;
217 int fw_count, max_fw_count;
218 const char *p;
219
220 ret = pfe_spi_flash_init();
221 if (ret)
222 goto err;
223
224 ret = pfe_fit_check();
225 if (ret)
226 goto err;
227
228 #ifdef CONFIG_CHAIN_OF_TRUST
229 pfe_esbc_hdr = (uintptr_t)pfe_esbc_hdr_addr;
230 pfe_img_addr = (uintptr_t)pfe_fit_addr;
231 if (fsl_check_boot_mode_secure() != 0) {
232 /*
233 * In case of failure in validation, fsl_secboot_validate
234 * would not return back in case of Production environment
235 * with ITS=1. In Development environment (ITS=0 and
236 * SB_EN=1), the function may return back in case of
237 * non-fatal failures.
238 */
239 ret = fsl_secboot_validate(pfe_esbc_hdr,
240 PFE_KEY_HASH,
241 &pfe_img_addr);
242 if (ret != 0)
243 printf("PFE firmware(s) validation failed\n");
244 else
245 printf("PFE firmware(s) validation Successful\n");
246 }
247 #endif
248
249 p = env_get("load_util");
250 if (!p) {
251 max_fw_count = 2;
252 } else {
253 max_fw_count = dectoul(p, NULL);
254 if (max_fw_count)
255 max_fw_count = 3;
256 else
257 max_fw_count = 2;
258 }
259
260 for (fw_count = 0; fw_count < max_fw_count; fw_count++) {
261 switch (fw_count) {
262 case 0:
263 pfe_firmware_name = "class_slowpath";
264 break;
265 case 1:
266 pfe_firmware_name = "tmu_slowpath";
267 break;
268 case 2:
269 pfe_firmware_name = "util_slowpath";
270 break;
271 }
272
273 if (pfe_get_fw(&raw_image_addr, &raw_image_size,
274 pfe_firmware_name)) {
275 printf("%s firmware couldn't be found in FIT image\n",
276 pfe_firmware_name);
277 break;
278 }
279 pfe_firmware = malloc(raw_image_size);
280 if (!pfe_firmware)
281 return -ENOMEM;
282 memcpy((void *)pfe_firmware, (void *)raw_image_addr,
283 raw_image_size);
284
285 switch (fw_count) {
286 case 0:
287 env_set_addr("class_elf_firmware", pfe_firmware);
288 env_set_addr("class_elf_size", (void *)raw_image_size);
289 break;
290 case 1:
291 env_set_addr("tmu_elf_firmware", pfe_firmware);
292 env_set_addr("tmu_elf_size", (void *)raw_image_size);
293 break;
294 case 2:
295 env_set_addr("util_elf_firmware", pfe_firmware);
296 env_set_addr("util_elf_size", (void *)raw_image_size);
297 break;
298 }
299 }
300
301 raw_image_addr = NULL;
302 pfe_firmware = NULL;
303 raw_image_size = 0;
304 for (fw_count = 0; fw_count < 2; fw_count++) {
305 if (fw_count == 0)
306 pfe_firmware_name = "class";
307 else if (fw_count == 1)
308 pfe_firmware_name = "tmu";
309
310 pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
311 pfe_firmware = malloc(raw_image_size);
312 if (!pfe_firmware)
313 return -ENOMEM;
314 memcpy((void *)pfe_firmware, (void *)raw_image_addr,
315 raw_image_size);
316
317 if (fw_count == 0)
318 ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
319 else if (fw_count == 1)
320 ret = pfe_load_elf(TMU_MASK, pfe_firmware);
321
322 if (ret < 0) {
323 printf("%s: %s firmware load failed\n", __func__,
324 pfe_firmware_name);
325 goto err;
326 }
327 debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
328 free(pfe_firmware);
329 }
330
331 tmu_enable(0xb);
332 class_enable();
333 gpi_enable(HGPI_BASE_ADDR);
334
335 err:
336 return ret;
337 }
338
339 /*
340 * PFE firmware cleanup
341 * Puts PE's in reset
342 */
pfe_firmware_exit(void)343 void pfe_firmware_exit(void)
344 {
345 debug("%s\n", __func__);
346
347 class_disable();
348 tmu_disable(0xf);
349 hif_tx_disable();
350 hif_rx_disable();
351 }
352