Prepare v2023.10
[platform/kernel/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,2021 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 <dm.h>
14 #include <dm/device-internal.h>
15 #include <image.h>
16 #include <log.h>
17 #include <malloc.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>
24 #endif
25
26 #define PFE_FIRMWARE_FIT_CNF_NAME       "config@1"
27
28 static const void *pfe_fit_addr;
29 #ifdef CONFIG_CHAIN_OF_TRUST
30 static const void *pfe_esbc_hdr_addr;
31 #endif
32
33 /*
34  * PFE elf firmware loader.
35  * Loads an elf firmware image into a list of PE's (specified using a bitmask)
36  *
37  * @param pe_mask       Mask of PE id's to load firmware to
38  * @param pfe_firmware  Pointer to the firmware image
39  *
40  * Return:              0 on success, a negative value on error
41  */
42 static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
43 {
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));
48         int id, section;
49         int ret;
50
51         debug("%s: no of sections: %d\n", __func__, sections);
52
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__);
56                 return -1;
57         }
58
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]);
62                 return -1;
63         }
64
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]);
68                 return -1;
69         }
70
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));
74                 return -1;
75         }
76
77         for (section = 0; section < sections; section++, shdr++) {
78                 if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
79                         SHF_EXECINSTR)))
80                         continue;
81                 for (id = 0; id < MAX_PE; id++)
82                         if (pe_mask & BIT(id)) {
83                                 ret = pe_load_elf_section(id,
84                                                           pfe_firmware, shdr);
85                                 if (ret < 0)
86                                         goto err;
87                         }
88         }
89         return 0;
90
91 err:
92         return ret;
93 }
94
95 /*
96  * Get PFE firmware from FIT image
97  *
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
101  *
102  * Return: 0 on success, a negative value on error
103  */
104 static int pfe_get_fw(const void **data,
105                       size_t *size, char *fw_name)
106 {
107         return fit_get_data_conf_prop(pfe_fit_addr, fw_name, data, size);
108 }
109
110 /*
111  * Check PFE FIT image
112  *
113  * Return: 0 on success, a negative value on error
114  */
115 static int pfe_fit_check(void)
116 {
117         int ret = 0;
118
119         ret = fdt_check_header(pfe_fit_addr);
120         if (ret) {
121                 printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
122                 return ret;
123         }
124
125         if (fit_check_format(pfe_fit_addr, IMAGE_SIZE_INVAL)) {
126                 printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
127                 ret = -1;
128                 return ret;
129         }
130
131         return ret;
132 }
133
134 int pfe_spi_flash_init(void)
135 {
136         struct spi_flash *pfe_flash;
137         int ret = 0;
138         void *addr = malloc(CONFIG_SYS_LS_PFE_FW_LENGTH);
139
140         if (!addr)
141                 return -ENOMEM;
142
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);
147
148         if (!pfe_flash) {
149                 printf("SF: probe for pfe failed\n");
150                 free(addr);
151                 return -ENODEV;
152         }
153
154         ret = spi_flash_read(pfe_flash,
155                              CONFIG_SYS_LS_PFE_FW_ADDR,
156                              CONFIG_SYS_LS_PFE_FW_LENGTH,
157                              addr);
158         if (ret) {
159                 printf("SF: read for pfe failed\n");
160                 free(addr);
161                 spi_flash_free(pfe_flash);
162                 return ret;
163         }
164
165 #ifdef CONFIG_CHAIN_OF_TRUST
166         void *hdr_addr = malloc(CONFIG_SYS_LS_PFE_ESBC_LENGTH);
167
168         if (!hdr_addr) {
169                 free(addr);
170                 spi_flash_free(pfe_flash);
171                 return -ENOMEM;
172         }
173
174         ret = spi_flash_read(pfe_flash,
175                              CONFIG_SYS_LS_PFE_ESBC_ADDR,
176                              CONFIG_SYS_LS_PFE_ESBC_LENGTH,
177                              hdr_addr);
178         if (ret) {
179                 printf("SF: failed to read pfe esbc header\n");
180                 free(addr);
181                 free(hdr_addr);
182                 spi_flash_free(pfe_flash);
183                 return ret;
184         }
185
186         pfe_esbc_hdr_addr = hdr_addr;
187 #endif
188         pfe_fit_addr = addr;
189         spi_flash_free(pfe_flash);
190
191         return ret;
192 }
193
194 /*
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
199  * firmware files
200  * Takes PE's out of reset
201  *
202  * Return: 0 on success, a negative value on error
203  */
204 int pfe_firmware_init(void)
205 {
206 #define PFE_KEY_HASH    NULL
207         char *pfe_firmware_name;
208         const void *raw_image_addr;
209         size_t raw_image_size = 0;
210         u8 *pfe_firmware;
211 #ifdef CONFIG_CHAIN_OF_TRUST
212         uintptr_t pfe_esbc_hdr = 0;
213         uintptr_t pfe_img_addr = 0;
214 #endif
215         int ret = 0;
216         int fw_count, max_fw_count;
217         const char *p;
218
219         ret = pfe_spi_flash_init();
220         if (ret)
221                 goto err;
222
223         ret = pfe_fit_check();
224         if (ret)
225                 goto err;
226
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) {
231                 /*
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.
237                  */
238                 ret = fsl_secboot_validate(pfe_esbc_hdr,
239                                            PFE_KEY_HASH,
240                                            &pfe_img_addr);
241                 if (ret != 0)
242                         printf("PFE firmware(s) validation failed\n");
243                 else
244                         printf("PFE firmware(s) validation Successful\n");
245         }
246 #endif
247
248         p = env_get("load_util");
249         if (!p) {
250                 max_fw_count = 2;
251         } else {
252                 max_fw_count = dectoul(p, NULL);
253                 if (max_fw_count)
254                         max_fw_count = 3;
255                 else
256                         max_fw_count = 2;
257         }
258
259         for (fw_count = 0; fw_count < max_fw_count; fw_count++) {
260                 switch (fw_count) {
261                 case 0:
262                         pfe_firmware_name = "class_slowpath";
263                         break;
264                 case 1:
265                         pfe_firmware_name = "tmu_slowpath";
266                         break;
267                 case 2:
268                         pfe_firmware_name = "util_slowpath";
269                         break;
270                 }
271
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",
275                                pfe_firmware_name);
276                         break;
277                 }
278                 pfe_firmware = malloc(raw_image_size);
279                 if (!pfe_firmware)
280                         return -ENOMEM;
281                 memcpy((void *)pfe_firmware, (void *)raw_image_addr,
282                        raw_image_size);
283
284                 switch (fw_count) {
285                 case 0:
286                         env_set_addr("class_elf_firmware", pfe_firmware);
287                         env_set_addr("class_elf_size", (void *)raw_image_size);
288                         break;
289                 case 1:
290                         env_set_addr("tmu_elf_firmware", pfe_firmware);
291                         env_set_addr("tmu_elf_size", (void *)raw_image_size);
292                         break;
293                 case 2:
294                         env_set_addr("util_elf_firmware", pfe_firmware);
295                         env_set_addr("util_elf_size", (void *)raw_image_size);
296                         break;
297                 }
298         }
299
300         raw_image_addr = NULL;
301         pfe_firmware = NULL;
302         raw_image_size = 0;
303         for (fw_count = 0; fw_count < 2; fw_count++) {
304                 if (fw_count == 0)
305                         pfe_firmware_name = "class";
306                 else if (fw_count == 1)
307                         pfe_firmware_name = "tmu";
308
309                 pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
310                 pfe_firmware = malloc(raw_image_size);
311                 if (!pfe_firmware)
312                         return -ENOMEM;
313                 memcpy((void *)pfe_firmware, (void *)raw_image_addr,
314                        raw_image_size);
315
316                 if (fw_count == 0)
317                         ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
318                 else if (fw_count == 1)
319                         ret = pfe_load_elf(TMU_MASK, pfe_firmware);
320
321                 if (ret < 0) {
322                         printf("%s: %s firmware load failed\n", __func__,
323                                pfe_firmware_name);
324                         goto err;
325                 }
326                 debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
327                 free(pfe_firmware);
328         }
329
330         tmu_enable(0xb);
331         class_enable();
332         gpi_enable(HGPI_BASE_ADDR);
333
334 err:
335         return ret;
336 }
337
338 /*
339  * PFE firmware cleanup
340  * Puts PE's in reset
341  */
342 void pfe_firmware_exit(void)
343 {
344         debug("%s\n", __func__);
345
346         class_disable();
347         tmu_disable(0xf);
348         hif_tx_disable();
349         hif_rx_disable();
350 }