mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-10-06 19:40:42 +09:00
83d290c56f
When U-Boot started using SPDX tags we were among the early adopters and there weren't a lot of other examples to borrow from. So we picked the area of the file that usually had a full license text and replaced it with an appropriate SPDX-License-Identifier: entry. Since then, the Linux Kernel has adopted SPDX tags and they place it as the very first line in a file (except where shebangs are used, then it's second line) and with slightly different comment styles than us. In part due to community overlap, in part due to better tag visibility and in part for other minor reasons, switch over to that style. This commit changes all instances where we have a single declared license in the tag as both the before and after are identical in tag contents. There's also a few places where I found we did not have a tag and have introduced one. Signed-off-by: Tom Rini <trini@konsulko.com>
230 lines
5.2 KiB
C
230 lines
5.2 KiB
C
// 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>
|
|
|
|
#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)
|
|
{
|
|
char *pfe_firmware_name;
|
|
const void *raw_image_addr;
|
|
size_t raw_image_size = 0;
|
|
u8 *pfe_firmware;
|
|
int ret = 0;
|
|
int fw_count;
|
|
|
|
ret = pfe_fit_check();
|
|
if (ret)
|
|
goto err;
|
|
|
|
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();
|
|
}
|