1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2015-2016 Freescale Semiconductor, Inc.
9 * Contains all the functions to handle parsing and loading of PE firmware
16 #include <linux/bitops.h>
17 #include <net/pfe_eth/pfe_eth.h>
18 #include <net/pfe_eth/pfe_firmware.h>
19 #include <spi_flash.h>
20 #ifdef CONFIG_CHAIN_OF_TRUST
21 #include <fsl_validate.h>
24 #define PFE_FIRMWARE_FIT_CNF_NAME "config@1"
26 static const void *pfe_fit_addr;
29 * PFE elf firmware loader.
30 * Loads an elf firmware image into a list of PE's (specified using a bitmask)
32 * @param pe_mask Mask of PE id's to load firmware to
33 * @param pfe_firmware Pointer to the firmware image
35 * @return 0 on success, a negative value on error
37 static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
39 Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *)pfe_firmware;
40 Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum);
41 Elf32_Shdr *shdr = (Elf32_Shdr *)(pfe_firmware +
42 be32_to_cpu(elf_hdr->e_shoff));
46 debug("%s: no of sections: %d\n", __func__, sections);
48 /* Some sanity checks */
49 if (strncmp((char *)&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
50 printf("%s: incorrect elf magic number\n", __func__);
54 if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
55 printf("%s: incorrect elf class(%x)\n", __func__,
56 elf_hdr->e_ident[EI_CLASS]);
60 if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) {
61 printf("%s: incorrect elf data(%x)\n", __func__,
62 elf_hdr->e_ident[EI_DATA]);
66 if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) {
67 printf("%s: incorrect elf file type(%x)\n", __func__,
68 be16_to_cpu(elf_hdr->e_type));
72 for (section = 0; section < sections; section++, shdr++) {
73 if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
76 for (id = 0; id < MAX_PE; id++)
77 if (pe_mask & BIT(id)) {
78 ret = pe_load_elf_section(id,
91 * Get PFE firmware from FIT image
93 * @param data pointer to PFE firmware
94 * @param size pointer to size of the firmware
95 * @param fw_name pfe firmware name, either class or tmu
97 * @return 0 on success, a negative value on error
99 static int pfe_get_fw(const void **data,
100 size_t *size, char *fw_name)
102 int conf_node_off, fw_node_off;
103 char *conf_node_name = NULL;
107 conf_node_name = PFE_FIRMWARE_FIT_CNF_NAME;
109 conf_node_off = fit_conf_get_node(pfe_fit_addr, conf_node_name);
110 if (conf_node_off < 0) {
111 printf("PFE Firmware: %s: no such config\n", conf_node_name);
115 fw_node_off = fit_conf_get_prop_node(pfe_fit_addr, conf_node_off,
117 if (fw_node_off < 0) {
118 printf("PFE Firmware: No '%s' in config\n",
123 if (!(fit_image_verify(pfe_fit_addr, fw_node_off))) {
124 printf("PFE Firmware: Bad firmware image (bad CRC)\n");
128 if (fit_image_get_data(pfe_fit_addr, fw_node_off, data, size)) {
129 printf("PFE Firmware: Can't get %s subimage data/size",
134 ret = fit_get_desc(pfe_fit_addr, fw_node_off, &desc);
136 printf("PFE Firmware: Can't get description\n");
138 printf("%s\n", desc);
144 * Check PFE FIT image
146 * @return 0 on success, a negative value on error
148 static int pfe_fit_check(void)
152 ret = fdt_check_header(pfe_fit_addr);
154 printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
158 if (!fit_check_format(pfe_fit_addr)) {
159 printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
167 int pfe_spi_flash_init(void)
169 struct spi_flash *pfe_flash;
171 void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
173 #ifdef CONFIG_DM_SPI_FLASH
176 /* speed and mode will be read from DT */
177 ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS,
178 CONFIG_ENV_SPI_CS, 0, 0, &new);
180 pfe_flash = dev_get_uclass_priv(new);
182 pfe_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
184 CONFIG_ENV_SPI_MAX_HZ,
185 CONFIG_ENV_SPI_MODE);
188 printf("SF: probe for pfe failed\n");
192 ret = spi_flash_read(pfe_flash,
193 CONFIG_SYS_LS_PFE_FW_ADDR,
194 CONFIG_SYS_QE_FMAN_FW_LENGTH,
197 printf("SF: read for pfe failed\n");
200 spi_flash_free(pfe_flash);
206 * PFE firmware initialization.
207 * Loads different firmware files from FIT image.
208 * Initializes PE IMEM/DMEM and UTIL-PE DDR
209 * Initializes control path symbol addresses (by looking them up in the elf
211 * Takes PE's out of reset
213 * @return 0 on success, a negative value on error
215 int pfe_firmware_init(void)
217 #define PFE_KEY_HASH NULL
218 char *pfe_firmware_name;
219 const void *raw_image_addr;
220 size_t raw_image_size = 0;
222 #ifdef CONFIG_CHAIN_OF_TRUST
223 uintptr_t pfe_esbc_hdr = 0;
224 uintptr_t pfe_img_addr = 0;
229 ret = pfe_spi_flash_init();
233 ret = pfe_fit_check();
237 #ifdef CONFIG_CHAIN_OF_TRUST
238 pfe_esbc_hdr = CONFIG_SYS_LS_PFE_ESBC_ADDR;
239 pfe_img_addr = (uintptr_t)pfe_fit_addr;
240 if (fsl_check_boot_mode_secure() != 0) {
242 * In case of failure in validation, fsl_secboot_validate
243 * would not return back in case of Production environment
244 * with ITS=1. In Development environment (ITS=0 and
245 * SB_EN=1), the function may return back in case of
246 * non-fatal failures.
248 ret = fsl_secboot_validate(pfe_esbc_hdr,
252 printf("PFE firmware(s) validation failed\n");
254 printf("PFE firmware(s) validation Successful\n");
258 for (fw_count = 0; fw_count < 2; fw_count++) {
260 pfe_firmware_name = "class";
261 else if (fw_count == 1)
262 pfe_firmware_name = "tmu";
264 pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
265 pfe_firmware = malloc(raw_image_size);
268 memcpy((void *)pfe_firmware, (void *)raw_image_addr,
272 ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
273 else if (fw_count == 1)
274 ret = pfe_load_elf(TMU_MASK, pfe_firmware);
277 printf("%s: %s firmware load failed\n", __func__,
281 debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
287 gpi_enable(HGPI_BASE_ADDR);
294 * PFE firmware cleanup
297 void pfe_firmware_exit(void)
299 debug("%s\n", __func__);