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