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