1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2015-2016 Freescale Semiconductor, Inc.
4 * Copyright 2017,2021 NXP
9 * Contains all the functions to handle parsing and loading of PE firmware
14 #include <dm/device-internal.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>
26 #define PFE_FIRMWARE_FIT_CNF_NAME "config@1"
28 static const void *pfe_fit_addr;
29 #ifdef CONFIG_CHAIN_OF_TRUST
30 static const void *pfe_esbc_hdr_addr;
34 * PFE elf firmware loader.
35 * Loads an elf firmware image into a list of PE's (specified using a bitmask)
37 * @param pe_mask Mask of PE id's to load firmware to
38 * @param pfe_firmware Pointer to the firmware image
40 * Return: 0 on success, a negative value on error
42 static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
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));
51 debug("%s: no of sections: %d\n", __func__, sections);
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__);
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]);
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]);
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));
77 for (section = 0; section < sections; section++, shdr++) {
78 if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
81 for (id = 0; id < MAX_PE; id++)
82 if (pe_mask & BIT(id)) {
83 ret = pe_load_elf_section(id,
96 * Get PFE firmware from FIT image
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
102 * Return: 0 on success, a negative value on error
104 static int pfe_get_fw(const void **data,
105 size_t *size, char *fw_name)
107 return fit_get_data_conf_prop(pfe_fit_addr, fw_name, data, size);
111 * Check PFE FIT image
113 * Return: 0 on success, a negative value on error
115 static int pfe_fit_check(void)
119 ret = fdt_check_header(pfe_fit_addr);
121 printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
125 if (fit_check_format(pfe_fit_addr, IMAGE_SIZE_INVAL)) {
126 printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
134 int pfe_spi_flash_init(void)
136 struct spi_flash *pfe_flash;
138 void *addr = malloc(CONFIG_SYS_LS_PFE_FW_LENGTH);
143 pfe_flash = spi_flash_probe(CONFIG_SYS_FSL_PFE_SPI_BUS,
144 CONFIG_SYS_FSL_PFE_SPI_CS,
145 CONFIG_SYS_FSL_PFE_SPI_MAX_HZ,
146 CONFIG_SYS_FSL_PFE_SPI_MODE);
149 printf("SF: probe for pfe failed\n");
154 ret = spi_flash_read(pfe_flash,
155 CONFIG_SYS_LS_PFE_FW_ADDR,
156 CONFIG_SYS_LS_PFE_FW_LENGTH,
159 printf("SF: read for pfe failed\n");
161 spi_flash_free(pfe_flash);
165 #ifdef CONFIG_CHAIN_OF_TRUST
166 void *hdr_addr = malloc(CONFIG_SYS_LS_PFE_ESBC_LENGTH);
170 spi_flash_free(pfe_flash);
174 ret = spi_flash_read(pfe_flash,
175 CONFIG_SYS_LS_PFE_ESBC_ADDR,
176 CONFIG_SYS_LS_PFE_ESBC_LENGTH,
179 printf("SF: failed to read pfe esbc header\n");
182 spi_flash_free(pfe_flash);
186 pfe_esbc_hdr_addr = hdr_addr;
189 spi_flash_free(pfe_flash);
195 * PFE firmware initialization.
196 * Loads different firmware files from FIT image.
197 * Initializes PE IMEM/DMEM and UTIL-PE DDR
198 * Initializes control path symbol addresses (by looking them up in the elf
200 * Takes PE's out of reset
202 * Return: 0 on success, a negative value on error
204 int pfe_firmware_init(void)
206 #define PFE_KEY_HASH NULL
207 char *pfe_firmware_name;
208 const void *raw_image_addr;
209 size_t raw_image_size = 0;
211 #ifdef CONFIG_CHAIN_OF_TRUST
212 uintptr_t pfe_esbc_hdr = 0;
213 uintptr_t pfe_img_addr = 0;
216 int fw_count, max_fw_count;
219 ret = pfe_spi_flash_init();
223 ret = pfe_fit_check();
227 #ifdef CONFIG_CHAIN_OF_TRUST
228 pfe_esbc_hdr = (uintptr_t)pfe_esbc_hdr_addr;
229 pfe_img_addr = (uintptr_t)pfe_fit_addr;
230 if (fsl_check_boot_mode_secure() != 0) {
232 * In case of failure in validation, fsl_secboot_validate
233 * would not return back in case of Production environment
234 * with ITS=1. In Development environment (ITS=0 and
235 * SB_EN=1), the function may return back in case of
236 * non-fatal failures.
238 ret = fsl_secboot_validate(pfe_esbc_hdr,
242 printf("PFE firmware(s) validation failed\n");
244 printf("PFE firmware(s) validation Successful\n");
248 p = env_get("load_util");
252 max_fw_count = dectoul(p, NULL);
259 for (fw_count = 0; fw_count < max_fw_count; fw_count++) {
262 pfe_firmware_name = "class_slowpath";
265 pfe_firmware_name = "tmu_slowpath";
268 pfe_firmware_name = "util_slowpath";
272 if (pfe_get_fw(&raw_image_addr, &raw_image_size,
273 pfe_firmware_name)) {
274 printf("%s firmware couldn't be found in FIT image\n",
278 pfe_firmware = malloc(raw_image_size);
281 memcpy((void *)pfe_firmware, (void *)raw_image_addr,
286 env_set_addr("class_elf_firmware", pfe_firmware);
287 env_set_addr("class_elf_size", (void *)raw_image_size);
290 env_set_addr("tmu_elf_firmware", pfe_firmware);
291 env_set_addr("tmu_elf_size", (void *)raw_image_size);
294 env_set_addr("util_elf_firmware", pfe_firmware);
295 env_set_addr("util_elf_size", (void *)raw_image_size);
300 raw_image_addr = NULL;
303 for (fw_count = 0; fw_count < 2; fw_count++) {
305 pfe_firmware_name = "class";
306 else if (fw_count == 1)
307 pfe_firmware_name = "tmu";
309 pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
310 pfe_firmware = malloc(raw_image_size);
313 memcpy((void *)pfe_firmware, (void *)raw_image_addr,
317 ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
318 else if (fw_count == 1)
319 ret = pfe_load_elf(TMU_MASK, pfe_firmware);
322 printf("%s: %s firmware load failed\n", __func__,
326 debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
332 gpi_enable(HGPI_BASE_ADDR);
339 * PFE firmware cleanup
342 void pfe_firmware_exit(void)
344 debug("%s\n", __func__);