]> Git Repo - J-u-boot.git/blob - drivers/net/pfe_eth/pfe_firmware.c
common: Drop image.h from common header
[J-u-boot.git] / drivers / net / pfe_eth / pfe_firmware.c
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 <image.h>
14 #include <malloc.h>
15 #include <net/pfe_eth/pfe_eth.h>
16 #include <net/pfe_eth/pfe_firmware.h>
17 #ifdef CONFIG_CHAIN_OF_TRUST
18 #include <fsl_validate.h>
19 #endif
20
21 #define PFE_FIRMWARE_FIT_CNF_NAME       "config@1"
22
23 static const void *pfe_fit_addr = (void *)CONFIG_SYS_LS_PFE_FW_ADDR;
24
25 /*
26  * PFE elf firmware loader.
27  * Loads an elf firmware image into a list of PE's (specified using a bitmask)
28  *
29  * @param pe_mask       Mask of PE id's to load firmware to
30  * @param pfe_firmware  Pointer to the firmware image
31  *
32  * @return              0 on success, a negative value on error
33  */
34 static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
35 {
36         Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *)pfe_firmware;
37         Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum);
38         Elf32_Shdr *shdr = (Elf32_Shdr *)(pfe_firmware +
39                                                 be32_to_cpu(elf_hdr->e_shoff));
40         int id, section;
41         int ret;
42
43         debug("%s: no of sections: %d\n", __func__, sections);
44
45         /* Some sanity checks */
46         if (strncmp((char *)&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
47                 printf("%s: incorrect elf magic number\n", __func__);
48                 return -1;
49         }
50
51         if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
52                 printf("%s: incorrect elf class(%x)\n", __func__,
53                        elf_hdr->e_ident[EI_CLASS]);
54                 return -1;
55         }
56
57         if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) {
58                 printf("%s: incorrect elf data(%x)\n", __func__,
59                        elf_hdr->e_ident[EI_DATA]);
60                 return -1;
61         }
62
63         if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) {
64                 printf("%s: incorrect elf file type(%x)\n", __func__,
65                        be16_to_cpu(elf_hdr->e_type));
66                 return -1;
67         }
68
69         for (section = 0; section < sections; section++, shdr++) {
70                 if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
71                         SHF_EXECINSTR)))
72                         continue;
73                 for (id = 0; id < MAX_PE; id++)
74                         if (pe_mask & BIT(id)) {
75                                 ret = pe_load_elf_section(id,
76                                                           pfe_firmware, shdr);
77                                 if (ret < 0)
78                                         goto err;
79                         }
80         }
81         return 0;
82
83 err:
84         return ret;
85 }
86
87 /*
88  * Get PFE firmware from FIT image
89  *
90  * @param data pointer to PFE firmware
91  * @param size pointer to size of the firmware
92  * @param fw_name pfe firmware name, either class or tmu
93  *
94  * @return 0 on success, a negative value on error
95  */
96 static int pfe_get_fw(const void **data,
97                       size_t *size, char *fw_name)
98 {
99         int conf_node_off, fw_node_off;
100         char *conf_node_name = NULL;
101         char *desc;
102         int ret = 0;
103
104         conf_node_name = PFE_FIRMWARE_FIT_CNF_NAME;
105
106         conf_node_off = fit_conf_get_node(pfe_fit_addr, conf_node_name);
107         if (conf_node_off < 0) {
108                 printf("PFE Firmware: %s: no such config\n", conf_node_name);
109                 return -ENOENT;
110         }
111
112         fw_node_off = fit_conf_get_prop_node(pfe_fit_addr, conf_node_off,
113                                              fw_name);
114         if (fw_node_off < 0) {
115                 printf("PFE Firmware: No '%s' in config\n",
116                        fw_name);
117                 return -ENOLINK;
118         }
119
120         if (!(fit_image_verify(pfe_fit_addr, fw_node_off))) {
121                 printf("PFE Firmware: Bad firmware image (bad CRC)\n");
122                 return -EINVAL;
123         }
124
125         if (fit_image_get_data(pfe_fit_addr, fw_node_off, data, size)) {
126                 printf("PFE Firmware: Can't get %s subimage data/size",
127                        fw_name);
128                 return -ENOENT;
129         }
130
131         ret = fit_get_desc(pfe_fit_addr, fw_node_off, &desc);
132         if (ret)
133                 printf("PFE Firmware: Can't get description\n");
134         else
135                 printf("%s\n", desc);
136
137         return ret;
138 }
139
140 /*
141  * Check PFE FIT image
142  *
143  * @return 0 on success, a negative value on error
144  */
145 static int pfe_fit_check(void)
146 {
147         int ret = 0;
148
149         ret = fdt_check_header(pfe_fit_addr);
150         if (ret) {
151                 printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
152                 return ret;
153         }
154
155         if (!fit_check_format(pfe_fit_addr)) {
156                 printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
157                 ret = -1;
158                 return ret;
159         }
160
161         return ret;
162 }
163
164 /*
165  * PFE firmware initialization.
166  * Loads different firmware files from FIT image.
167  * Initializes PE IMEM/DMEM and UTIL-PE DDR
168  * Initializes control path symbol addresses (by looking them up in the elf
169  * firmware files
170  * Takes PE's out of reset
171  *
172  * @return 0 on success, a negative value on error
173  */
174 int pfe_firmware_init(void)
175 {
176 #define PFE_KEY_HASH    NULL
177         char *pfe_firmware_name;
178         const void *raw_image_addr;
179         size_t raw_image_size = 0;
180         u8 *pfe_firmware;
181 #ifdef CONFIG_CHAIN_OF_TRUST
182         uintptr_t pfe_esbc_hdr = 0;
183         uintptr_t pfe_img_addr = 0;
184 #endif
185         int ret = 0;
186         int fw_count;
187
188         ret = pfe_fit_check();
189         if (ret)
190                 goto err;
191
192 #ifdef CONFIG_CHAIN_OF_TRUST
193         pfe_esbc_hdr = CONFIG_SYS_LS_PFE_ESBC_ADDR;
194         pfe_img_addr = (uintptr_t)pfe_fit_addr;
195         if (fsl_check_boot_mode_secure() != 0) {
196                 /*
197                  * In case of failure in validation, fsl_secboot_validate
198                  * would not return back in case of Production environment
199                  * with ITS=1. In Development environment (ITS=0 and
200                  * SB_EN=1), the function may return back in case of
201                  * non-fatal failures.
202                  */
203                 ret = fsl_secboot_validate(pfe_esbc_hdr,
204                                            PFE_KEY_HASH,
205                                            &pfe_img_addr);
206                 if (ret != 0)
207                         printf("PFE firmware(s) validation failed\n");
208                 else
209                         printf("PFE firmware(s) validation Successful\n");
210         }
211 #endif
212
213         for (fw_count = 0; fw_count < 2; fw_count++) {
214                 if (fw_count == 0)
215                         pfe_firmware_name = "class";
216                 else if (fw_count == 1)
217                         pfe_firmware_name = "tmu";
218
219                 pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
220                 pfe_firmware = malloc(raw_image_size);
221                 if (!pfe_firmware)
222                         return -ENOMEM;
223                 memcpy((void *)pfe_firmware, (void *)raw_image_addr,
224                        raw_image_size);
225
226                 if (fw_count == 0)
227                         ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
228                 else if (fw_count == 1)
229                         ret = pfe_load_elf(TMU_MASK, pfe_firmware);
230
231                 if (ret < 0) {
232                         printf("%s: %s firmware load failed\n", __func__,
233                                pfe_firmware_name);
234                         goto err;
235                 }
236                 debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
237                 free(pfe_firmware);
238         }
239
240         tmu_enable(0xb);
241         class_enable();
242         gpi_enable(HGPI_BASE_ADDR);
243
244 err:
245         return ret;
246 }
247
248 /*
249  * PFE firmware cleanup
250  * Puts PE's in reset
251  */
252 void pfe_firmware_exit(void)
253 {
254         debug("%s\n", __func__);
255
256         class_disable();
257         tmu_disable(0xf);
258         hif_tx_disable();
259         hif_rx_disable();
260 }
This page took 0.039727 seconds and 4 git commands to generate.