123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- // SPDX-License-Identifier: GPL-2.0+
- /*
- * Copyright 2015-2016 Freescale Semiconductor, Inc.
- * Copyright 2017 NXP
- */
- /*
- * @file
- * Contains all the functions to handle parsing and loading of PE firmware
- * files.
- */
- #include <net/pfe_eth/pfe_eth.h>
- #include <net/pfe_eth/pfe_firmware.h>
- #ifdef CONFIG_CHAIN_OF_TRUST
- #include <fsl_validate.h>
- #endif
- #define PFE_FIRMEWARE_FIT_CNF_NAME "config@1"
- static const void *pfe_fit_addr = (void *)CONFIG_SYS_LS_PFE_FW_ADDR;
- /*
- * PFE elf firmware loader.
- * Loads an elf firmware image into a list of PE's (specified using a bitmask)
- *
- * @param pe_mask Mask of PE id's to load firmware to
- * @param pfe_firmware Pointer to the firmware image
- *
- * @return 0 on success, a negative value on error
- */
- static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
- {
- Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *)pfe_firmware;
- Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum);
- Elf32_Shdr *shdr = (Elf32_Shdr *)(pfe_firmware +
- be32_to_cpu(elf_hdr->e_shoff));
- int id, section;
- int ret;
- debug("%s: no of sections: %d\n", __func__, sections);
- /* Some sanity checks */
- if (strncmp((char *)&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
- printf("%s: incorrect elf magic number\n", __func__);
- return -1;
- }
- if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
- printf("%s: incorrect elf class(%x)\n", __func__,
- elf_hdr->e_ident[EI_CLASS]);
- return -1;
- }
- if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) {
- printf("%s: incorrect elf data(%x)\n", __func__,
- elf_hdr->e_ident[EI_DATA]);
- return -1;
- }
- if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) {
- printf("%s: incorrect elf file type(%x)\n", __func__,
- be16_to_cpu(elf_hdr->e_type));
- return -1;
- }
- for (section = 0; section < sections; section++, shdr++) {
- if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
- SHF_EXECINSTR)))
- continue;
- for (id = 0; id < MAX_PE; id++)
- if (pe_mask & BIT(id)) {
- ret = pe_load_elf_section(id,
- pfe_firmware, shdr);
- if (ret < 0)
- goto err;
- }
- }
- return 0;
- err:
- return ret;
- }
- /*
- * Get PFE firmware from FIT image
- *
- * @param data pointer to PFE firmware
- * @param size pointer to size of the firmware
- * @param fw_name pfe firmware name, either class or tmu
- *
- * @return 0 on success, a negative value on error
- */
- static int pfe_get_fw(const void **data,
- size_t *size, char *fw_name)
- {
- int conf_node_off, fw_node_off;
- char *conf_node_name = NULL;
- char *desc;
- int ret = 0;
- conf_node_name = PFE_FIRMEWARE_FIT_CNF_NAME;
- conf_node_off = fit_conf_get_node(pfe_fit_addr, conf_node_name);
- if (conf_node_off < 0) {
- printf("PFE Firmware: %s: no such config\n", conf_node_name);
- return -ENOENT;
- }
- fw_node_off = fit_conf_get_prop_node(pfe_fit_addr, conf_node_off,
- fw_name);
- if (fw_node_off < 0) {
- printf("PFE Firmware: No '%s' in config\n",
- fw_name);
- return -ENOLINK;
- }
- if (!(fit_image_verify(pfe_fit_addr, fw_node_off))) {
- printf("PFE Firmware: Bad firmware image (bad CRC)\n");
- return -EINVAL;
- }
- if (fit_image_get_data(pfe_fit_addr, fw_node_off, data, size)) {
- printf("PFE Firmware: Can't get %s subimage data/size",
- fw_name);
- return -ENOENT;
- }
- ret = fit_get_desc(pfe_fit_addr, fw_node_off, &desc);
- if (ret)
- printf("PFE Firmware: Can't get description\n");
- else
- printf("%s\n", desc);
- return ret;
- }
- /*
- * Check PFE FIT image
- *
- * @return 0 on success, a negative value on error
- */
- static int pfe_fit_check(void)
- {
- int ret = 0;
- ret = fdt_check_header(pfe_fit_addr);
- if (ret) {
- printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
- return ret;
- }
- if (!fit_check_format(pfe_fit_addr)) {
- printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
- ret = -1;
- return ret;
- }
- return ret;
- }
- /*
- * PFE firmware initialization.
- * Loads different firmware files from FIT image.
- * Initializes PE IMEM/DMEM and UTIL-PE DDR
- * Initializes control path symbol addresses (by looking them up in the elf
- * firmware files
- * Takes PE's out of reset
- *
- * @return 0 on success, a negative value on error
- */
- int pfe_firmware_init(void)
- {
- #define PFE_KEY_HASH NULL
- char *pfe_firmware_name;
- const void *raw_image_addr;
- size_t raw_image_size = 0;
- u8 *pfe_firmware;
- #ifdef CONFIG_CHAIN_OF_TRUST
- uintptr_t pfe_esbc_hdr = 0;
- uintptr_t pfe_img_addr = 0;
- #endif
- int ret = 0;
- int fw_count;
- ret = pfe_fit_check();
- if (ret)
- goto err;
- #ifdef CONFIG_CHAIN_OF_TRUST
- pfe_esbc_hdr = CONFIG_SYS_LS_PFE_ESBC_ADDR;
- pfe_img_addr = (uintptr_t)pfe_fit_addr;
- if (fsl_check_boot_mode_secure() != 0) {
- /*
- * In case of failure in validation, fsl_secboot_validate
- * would not return back in case of Production environment
- * with ITS=1. In Development environment (ITS=0 and
- * SB_EN=1), the function may return back in case of
- * non-fatal failures.
- */
- ret = fsl_secboot_validate(pfe_esbc_hdr,
- PFE_KEY_HASH,
- &pfe_img_addr);
- if (ret != 0)
- printf("PFE firmware(s) validation failed\n");
- else
- printf("PFE firmware(s) validation Successful\n");
- }
- #endif
- for (fw_count = 0; fw_count < 2; fw_count++) {
- if (fw_count == 0)
- pfe_firmware_name = "class";
- else if (fw_count == 1)
- pfe_firmware_name = "tmu";
- pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
- pfe_firmware = malloc(raw_image_size);
- if (!pfe_firmware)
- return -ENOMEM;
- memcpy((void *)pfe_firmware, (void *)raw_image_addr,
- raw_image_size);
- if (fw_count == 0)
- ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
- else if (fw_count == 1)
- ret = pfe_load_elf(TMU_MASK, pfe_firmware);
- if (ret < 0) {
- printf("%s: %s firmware load failed\n", __func__,
- pfe_firmware_name);
- goto err;
- }
- debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
- free(pfe_firmware);
- }
- tmu_enable(0xb);
- class_enable();
- gpi_enable(HGPI_BASE_ADDR);
- err:
- return ret;
- }
- /*
- * PFE firmware cleanup
- * Puts PE's in reset
- */
- void pfe_firmware_exit(void)
- {
- debug("%s\n", __func__);
- class_disable();
- tmu_disable(0xf);
- hif_tx_disable();
- hif_rx_disable();
- }
|