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