soc/*: Explicitly include static.h for DEV_PTR
[coreboot.git] / util / amdfwtool / data_parse.c
blob64ec4d7e33589a3c913504b137740bdcd851da79
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <stdio.h>
4 #include <regex.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <assert.h>
10 #include "amdfwtool.h"
12 /* TODO: a empty line does not matched. */
13 static const char blank_or_comment_regex[] =
14 /* a blank line */
15 "(^[[:space:]]*$)"
16 "|" /* or ... */
17 /* a line consisting of: optional whitespace followed by */
18 "(^[[:space:]]*"
19 /* a '#' character and optionally, additional characters */
20 "#.*$)";
21 static regex_t blank_or_comment_expr;
23 static const char entries_line_regex[] =
24 /* optional whitespace */
25 "^[[:space:]]*"
26 /* followed by a chunk of nonwhitespace for macro field */
27 "([^[:space:]]+)"
28 /* followed by one or more whitespace characters */
29 "[[:space:]]+"
30 /* followed by a chunk of nonwhitespace for filename field */
31 "([^[:space:]]+)"
32 /* followed by an optional whitespace + chunk of nonwhitespace for level field
33 1st char L: Indicator of field "level"
34 2nd char:
35 Directory level to be dropped in.
36 1: Level 1
37 2: Level 2
38 b: Level both 1&2
39 x: use default value hardcoded in table
40 3rd char:
41 For A/B recovery. Defined same as 2nd char.
43 Examples:
44 L2: Level 2 for normal mode
45 L12: Level 1 for normal mode, level 2 for A/B mode
46 Lx1: Use default value for normal mode, level 1 for A/B mode
48 "([[:space:]]+([Ll][12bxBX]{1,2}))?"
49 /* followed by an optional whitespace + chunk of nonwhitespace for hash table field
50 1st char H: Indicator of field "Hash Table ID"
51 2nd char:
52 Table ID to be dropped in.
53 0: Table 0 / Default Unified Table
54 1: Table 1
55 ...
56 9: Table 9
58 Examples:
59 H2: Put the hash for the concerned entry in Hash Table 2
61 "([[:space:]]+([Hh][0-9]+))?"
62 /* followed by an optional whitespace + "UUID" to indicate the binary is using 16 bytes
63 UUID as firmware identity. In the absence of this field, the binary is using 2 bytes
64 FWID as firmware identity.
66 "([[:space:]]+(UUID))?"
67 /* followed by optional whitespace */
68 "[[:space:]]*$";
69 static regex_t entries_line_expr;
71 enum match_id {
72 FW_TYPE = 1,
73 FW_FILE,
74 OPT_SPACE1,
75 OPT_LEVEL,
76 OPT_SPACE2,
77 OPT_HASH_TABLE_ID,
78 OPT_SPACE3,
79 OPT_FWID_TYPE,
80 N_MATCHES,
83 void compile_reg_expr(int cflags, const char *expr, regex_t *reg)
85 static const size_t ERROR_BUF_SIZE = 256;
86 char error_msg[ERROR_BUF_SIZE];
87 int result;
89 result = regcomp(reg, expr, cflags);
90 if (result != 0) {
91 regerror(result, reg, error_msg, ERROR_BUF_SIZE);
92 fprintf(stderr, "%s\n", error_msg);
96 static enum platform identify_platform(char *soc_name)
98 if (!strcasecmp(soc_name, "Stoneyridge"))
99 return PLATFORM_STONEYRIDGE;
100 else if (!strcasecmp(soc_name, "Carrizo"))
101 return PLATFORM_CARRIZO;
102 else if (!strcasecmp(soc_name, "Raven"))
103 return PLATFORM_RAVEN;
104 else if (!strcasecmp(soc_name, "Picasso"))
105 return PLATFORM_PICASSO;
106 else if (!strcasecmp(soc_name, "Cezanne"))
107 return PLATFORM_CEZANNE;
108 else if (!strcasecmp(soc_name, "Mendocino"))
109 return PLATFORM_MENDOCINO;
110 else if (!strcasecmp(soc_name, "Renoir"))
111 return PLATFORM_RENOIR;
112 else if (!strcasecmp(soc_name, "Lucienne"))
113 return PLATFORM_LUCIENNE;
114 else if (!strcasecmp(soc_name, "Phoenix"))
115 return PLATFORM_PHOENIX;
116 else if (!strcasecmp(soc_name, "Glinda"))
117 return PLATFORM_GLINDA;
118 else if (!strcasecmp(soc_name, "Genoa"))
119 return PLATFORM_GENOA;
120 else
121 return PLATFORM_UNKNOWN;
124 #define SET_LEVEL(tableptr, l, TABLE, ab) \
125 do { \
126 switch ((l)) { \
127 case '1': \
128 (tableptr)->level = ab ? TABLE##_LVL1_AB : TABLE##_LVL1; \
129 break; \
130 case '2': \
131 (tableptr)->level = ab ? TABLE##_LVL2_AB : TABLE##_LVL2; \
132 break; \
133 case 'b': \
134 case 'B': \
135 (tableptr)->level = ab ? TABLE##_BOTH_AB : TABLE##_BOTH; \
136 break; \
137 default: \
138 /* use default value */ \
139 break; \
141 } while (0)
143 extern amd_fw_entry amd_psp_fw_table[];
144 extern amd_bios_entry amd_bios_table[];
146 static uint8_t find_register_fw_filename_psp_dir(char *fw_name, char *filename,
147 char level_to_set, uint8_t hash_tbl_id, fwid_type_t fwid_type,
148 amd_cb_config *cb_config)
150 amd_fw_type fw_type = AMD_FW_INVALID;
151 amd_fw_entry *psp_tableptr;
152 uint8_t subprog;
153 uint8_t instance = 0;
155 if (strcmp(fw_name, "PSPBTLDR_WL_FILE") == 0) {
156 if (cb_config->have_whitelist) {
157 fw_type = AMD_FW_PSP_BOOTLOADER_AB;
158 subprog = 0;
159 } else {
160 fw_type = AMD_FW_SKIP;
162 } else if (strcmp(fw_name, "PSPBTLDR_AB_STAGE1_FILE") == 0) {
163 if (cb_config->recovery_ab) {
164 fw_type = AMD_FW_PSP_BOOTLOADER;
165 subprog = 0;
166 } else {
167 fw_type = AMD_FW_SKIP;
169 } else if (strcmp(fw_name, "PSPBTLDR_FILE") == 0) {
170 if (!cb_config->recovery_ab) {
171 fw_type = AMD_FW_PSP_BOOTLOADER;
172 subprog = 0;
173 } else {
174 fw_type = AMD_FW_SKIP;
176 } else if (strcmp(fw_name, "AMD_PUBKEY_FILE") == 0) {
177 fw_type = AMD_FW_PSP_PUBKEY;
178 subprog = 0;
179 } else if (strcmp(fw_name, "AMD_FUSE_CHAIN") == 0) {
180 fw_type = AMD_PSP_FUSE_CHAIN;
181 subprog = 0;
182 } else if (strcmp(fw_name, "PSPRCVR_FILE") == 0) {
183 fw_type = AMD_FW_PSP_RECOVERY;
184 subprog = 0;
185 } else if (strcmp(fw_name, "PUBSIGNEDKEY_FILE") == 0) {
186 fw_type = AMD_FW_PSP_RTM_PUBKEY;
187 subprog = 0;
188 } else if (strcmp(fw_name, "PSPNVRAM_FILE") == 0) {
189 fw_type = AMD_FW_PSP_NVRAM;
190 subprog = 0;
191 } else if (strcmp(fw_name, "SMUSCS_FILE") == 0) {
192 fw_type = AMD_FW_PSP_SMUSCS;
193 subprog = 0;
194 } else if (strcmp(fw_name, "PSPTRUSTLETS_FILE") == 0) {
195 fw_type = AMD_FW_PSP_TRUSTLETS;
196 subprog = 0;
197 } else if (strcmp(fw_name, "PSPSECUREDEBUG_FILE") == 0) {
198 fw_type = AMD_FW_PSP_SECURED_DEBUG;
199 subprog = 0;
200 } else if (strcmp(fw_name, "PSP_SMUFW1_SUB0_FILE") == 0) {
201 fw_type = AMD_FW_PSP_SMU_FIRMWARE;
202 subprog = 0;
203 } else if (strcmp(fw_name, "PSP_HW_IPCFG_FILE_SUB0") == 0) {
204 fw_type = AMD_HW_IPCFG;
205 subprog = 0;
206 } else if (strcmp(fw_name, "PSP_HW_IPCFG_FILE_SUB1") == 0) {
207 fw_type = AMD_HW_IPCFG;
208 subprog = 1;
209 } else if (strcmp(fw_name, "PSP_SMUFW1_SUB1_FILE") == 0) {
210 fw_type = AMD_FW_PSP_SMU_FIRMWARE;
211 subprog = 1;
212 } else if (strcmp(fw_name, "PSP_SMUFW1_SUB2_FILE") == 0) {
213 fw_type = AMD_FW_PSP_SMU_FIRMWARE;
214 subprog = 2;
215 } else if (strcmp(fw_name, "PSP_SMUFW2_SUB0_FILE") == 0) {
216 fw_type = AMD_FW_PSP_SMU_FIRMWARE2;
217 subprog = 0;
218 } else if (strcmp(fw_name, "PSP_SMUFW2_SUB1_FILE") == 0) {
219 fw_type = AMD_FW_PSP_SMU_FIRMWARE2;
220 subprog = 1;
221 } else if (strcmp(fw_name, "PSP_SMUFW2_SUB2_FILE") == 0) {
222 fw_type = AMD_FW_PSP_SMU_FIRMWARE2;
223 subprog = 2;
224 } else if (strcmp(fw_name, "PSP_BOOT_DRIVER_FILE") == 0) {
225 fw_type = AMD_BOOT_DRIVER;
226 subprog = 0;
227 } else if (strcmp(fw_name, "PSP_SOC_DRIVER_FILE") == 0) {
228 fw_type = AMD_SOC_DRIVER;
229 subprog = 0;
230 } else if (strcmp(fw_name, "PSP_DEBUG_DRIVER_FILE") == 0) {
231 fw_type = AMD_DEBUG_DRIVER;
232 subprog = 0;
233 } else if (strcmp(fw_name, "PSP_INTERFACE_DRIVER_FILE") == 0) {
234 fw_type = AMD_INTERFACE_DRIVER;
235 subprog = 0;
236 } else if (strcmp(fw_name, "PSP_SEC_DBG_KEY_FILE") == 0) {
237 if (cb_config->unlock_secure) {
238 fw_type = AMD_FW_PSP_SECURED_DEBUG;
239 subprog = 0;
240 } else {
241 fw_type = AMD_FW_SKIP;
243 } else if (strcmp(fw_name, "PSP_SEC_DEBUG_FILE") == 0) {
244 if (cb_config->unlock_secure) {
245 fw_type = AMD_DEBUG_UNLOCK;
246 subprog = 0;
247 } else {
248 fw_type = AMD_FW_SKIP;
250 } else if (strcmp(fw_name, "PSP_ABL0_FILE") == 0) {
251 fw_type = AMD_ABL0;
252 subprog = 0;
253 } else if (strcmp(fw_name, "PSP_ABL1_FILE") == 0) {
254 fw_type = AMD_ABL1;
255 subprog = 0;
256 } else if (strcmp(fw_name, "PSP_ABL2_FILE") == 0) {
257 fw_type = AMD_ABL2;
258 subprog = 0;
259 } else if (strcmp(fw_name, "PSP_ABL3_FILE") == 0) {
260 fw_type = AMD_ABL3;
261 subprog = 0;
262 } else if (strcmp(fw_name, "PSP_ABL4_FILE") == 0) {
263 fw_type = AMD_ABL4;
264 subprog = 0;
265 } else if (strcmp(fw_name, "PSP_ABL5_FILE") == 0) {
266 fw_type = AMD_ABL5;
267 subprog = 0;
268 } else if (strcmp(fw_name, "PSP_ABL6_FILE") == 0) {
269 fw_type = AMD_ABL6;
270 subprog = 0;
271 } else if (strcmp(fw_name, "PSP_ABL7_FILE") == 0) {
272 fw_type = AMD_ABL7;
273 subprog = 0;
274 } else if (strcmp(fw_name, "PSPSECUREOS_FILE") == 0) {
275 if (cb_config->use_secureos) {
276 fw_type = AMD_FW_PSP_SECURED_OS;
277 subprog = 0;
278 } else {
279 fw_type = AMD_FW_SKIP;
281 } else if (strcmp(fw_name, "PSPTRUSTLETS_FILE") == 0) {
282 if (cb_config->use_secureos) {
283 fw_type = AMD_FW_PSP_TRUSTLETS;
284 subprog = 0;
285 } else {
286 fw_type = AMD_FW_SKIP;
288 } else if (strcmp(fw_name, "TRUSTLETKEY_FILE") == 0) {
289 if (cb_config->use_secureos) {
290 fw_type = AMD_FW_PSP_TRUSTLETKEY;
291 subprog = 0;
292 } else {
293 fw_type = AMD_FW_SKIP;
295 } else if (strcmp(fw_name, "PSP_IKEK_FILE") == 0) {
296 fw_type = AMD_WRAPPED_IKEK;
297 subprog = 0;
298 } else if (strcmp(fw_name, "PSP_SECG0_FILE") == 0) {
299 fw_type = AMD_SEC_GASKET;
300 subprog = 0;
301 } else if (strcmp(fw_name, "PSP_SECG1_FILE") == 0) {
302 fw_type = AMD_SEC_GASKET;
303 subprog = 1;
304 } else if (strcmp(fw_name, "PSP_SECG2_FILE") == 0) {
305 fw_type = AMD_SEC_GASKET;
306 subprog = 2;
307 } else if (strcmp(fw_name, "PSP_MP2FW0_FILE") == 0) {
308 if (cb_config->load_mp2_fw) {
309 fw_type = AMD_MP2_FW;
310 subprog = 0;
311 } else {
312 fw_type = AMD_FW_SKIP;
314 } else if (strcmp(fw_name, "PSP_MP2FW1_FILE") == 0) {
315 if (cb_config->load_mp2_fw) {
316 fw_type = AMD_MP2_FW;
317 subprog = 1;
318 } else {
319 fw_type = AMD_FW_SKIP;
321 } else if (strcmp(fw_name, "PSP_MP2FW2_FILE") == 0) {
322 if (cb_config->load_mp2_fw) {
323 fw_type = AMD_MP2_FW;
324 subprog = 2;
325 } else {
326 fw_type = AMD_FW_SKIP;
328 } else if (strcmp(fw_name, "PSP_C20MP_FILE") == 0) {
329 fw_type = AMD_FW_C20_MP;
330 subprog = 0;
331 } else if (strcmp(fw_name, "AMF_SRAM_FILE") == 0) {
332 fw_type = AMD_FW_AMF_SRAM;
333 subprog = 0;
334 } else if (strcmp(fw_name, "AMF_DRAM_FILE_INS0") == 0) {
335 fw_type = AMD_FW_AMF_DRAM;
336 subprog = 0;
337 instance = 0;
338 } else if (strcmp(fw_name, "AMF_DRAM_FILE_INS1") == 0) {
339 fw_type = AMD_FW_AMF_DRAM;
340 subprog = 0;
341 instance = 1;
342 } else if (strcmp(fw_name, "AMF_WLAN_FILE_INS0") == 0) {
343 fw_type = AMD_FW_AMF_WLAN;
344 subprog = 0;
345 instance = 0;
346 } else if (strcmp(fw_name, "AMF_WLAN_FILE_INS1") == 0) {
347 fw_type = AMD_FW_AMF_WLAN;
348 subprog = 0;
349 instance = 1;
350 } else if (strcmp(fw_name, "AMF_MFD_FILE") == 0) {
351 fw_type = AMD_FW_AMF_MFD;
352 subprog = 0;
353 } else if (strcmp(fw_name, "MPCCX_FILE") == 0) {
354 fw_type = AMD_FW_MPCCX;
355 subprog = 0;
356 } else if (strcmp(fw_name, "LSDMA_FILE") == 0) {
357 fw_type = AMD_FW_LSDMA;
358 subprog = 0;
359 } else if (strcmp(fw_name, "MINIMSMU_FILE") == 0) {
360 fw_type = AMD_FW_MINIMSMU;
361 instance = 0;
362 subprog = 0;
363 } else if (strcmp(fw_name, "MINIMSMU_FILE_INS1") == 0) {
364 fw_type = AMD_FW_MINIMSMU;
365 instance = 1;
366 subprog = 0;
367 } else if (strcmp(fw_name, "SRAM_FW_EXT_FILE") == 0) {
368 fw_type = AMD_FW_SRAM_FW_EXT;
369 subprog = 0;
370 } else if (strcmp(fw_name, "PSP_DRIVERS_FILE") == 0) {
371 fw_type = AMD_DRIVER_ENTRIES;
372 subprog = 0;
373 } else if (strcmp(fw_name, "PSP_S0I3_FILE") == 0) {
374 if (cb_config->s0i3) {
375 fw_type = AMD_S0I3_DRIVER;
376 subprog = 0;
377 } else {
378 fw_type = AMD_FW_SKIP;
380 } else if (strcmp(fw_name, "AMD_DRIVER_ENTRIES") == 0) {
381 fw_type = AMD_DRIVER_ENTRIES;
382 subprog = 0;
383 } else if (strcmp(fw_name, "VBIOS_BTLOADER_FILE") == 0) {
384 fw_type = AMD_VBIOS_BTLOADER;
385 subprog = 0;
386 } else if (strcmp(fw_name, "SECURE_POLICY_L1_FILE") == 0) {
387 fw_type = AMD_FW_TOS_SEC_POLICY;
388 subprog = 0;
389 } else if (strcmp(fw_name, "UNIFIEDUSB_FILE") == 0) {
390 fw_type = AMD_FW_USB_PHY;
391 subprog = 0;
392 } else if (strcmp(fw_name, "DRTMTA_FILE") == 0) {
393 fw_type = AMD_FW_DRTM_TA;
394 subprog = 0;
395 } else if (strcmp(fw_name, "KEYDBBL_FILE") == 0) {
396 fw_type = AMD_FW_KEYDB_BL;
397 subprog = 0;
398 } else if (strcmp(fw_name, "KEYDB_TOS_FILE") == 0) {
399 fw_type = AMD_FW_KEYDB_TOS;
400 subprog = 0;
401 } else if (strcmp(fw_name, "SPL_TABLE_FILE") == 0) {
402 if (cb_config->have_mb_spl) {
403 fw_type = AMD_FW_SKIP;
404 } else {
405 fw_type = AMD_FW_SPL;
406 subprog = 0;
408 } else if (strcmp(fw_name, "DMCUERAMDCN21_FILE") == 0) {
409 fw_type = AMD_FW_DMCU_ERAM;
410 subprog = 0;
411 } else if (strcmp(fw_name, "DMCUINTVECTORSDCN21_FILE") == 0) {
412 fw_type = AMD_FW_DMCU_ISR;
413 subprog = 0;
414 } else if (strcmp(fw_name, "MSMU_FILE") == 0) {
415 fw_type = AMD_FW_MSMU;
416 subprog = 0;
417 } else if (strcmp(fw_name, "DMCUB_FILE") == 0) {
418 fw_type = AMD_FW_DMCUB;
419 subprog = 0;
420 } else if (strcmp(fw_name, "SPIROM_CONFIG_FILE") == 0) {
421 fw_type = AMD_FW_SPIROM_CFG;
422 subprog = 0;
423 } else if (strcmp(fw_name, "MPIO_FILE") == 0) {
424 fw_type = AMD_FW_MPIO;
425 subprog = 0;
426 } else if (strcmp(fw_name, "TPMLITE_FILE") == 0) {
427 fw_type = AMD_FW_TPMLITE;
428 subprog = 0;
429 } else if (strcmp(fw_name, "PSP_KVM_ENGINE_DUMMY_FILE") == 0) {
430 fw_type = AMD_FW_KVM_IMAGE;
431 subprog = 0;
432 } else if (strcmp(fw_name, "RPMC_FILE") == 0) {
433 fw_type = AMD_RPMC_NVRAM;
434 subprog = 0;
435 } else if (strcmp(fw_name, "PSPBTLDR_AB_FILE") == 0) {
436 if (!cb_config->have_whitelist || cb_config->recovery_ab) {
437 fw_type = AMD_FW_PSP_BOOTLOADER_AB;
438 subprog = 0;
439 } else {
440 fw_type = AMD_FW_SKIP;
442 } else if (strcmp(fw_name, "TA_IKEK_FILE") == 0) {
443 fw_type = AMD_TA_IKEK;
444 subprog = 0;
445 } else if (strcmp(fw_name, "UMSMU_FILE") == 0) {
446 fw_type = AMD_FW_UMSMU;
447 subprog = 0;
448 } else if (strcmp(fw_name, "PSP_OEM_ABL_KEY_FILE") == 0) {
449 fw_type = AMD_FW_ABL_PUBKEY;
450 subprog = 0;
451 } else if (strcmp(fw_name, "PSP_MP5FW_SUB0_FILE") == 0) {
452 fw_type = AMD_FW_MP5;
453 subprog = 0;
454 } else if (strcmp(fw_name, "PSP_MP5FW_SUB1_FILE") == 0) {
455 fw_type = AMD_FW_MP5;
456 subprog = 1;
457 } else if (strcmp(fw_name, "PSP_MP5FW_SUB2_FILE") == 0) {
458 fw_type = AMD_FW_MP5;
459 subprog = 2;
460 } else if (strcmp(fw_name, "PSP_DXIOFW_FILE") == 0) {
461 fw_type = AMD_FW_DXIO;
462 subprog = 0;
463 } else if (strcmp(fw_name, "PSP_MPIOFW_FILE") == 0) {
464 fw_type = AMD_FW_MPIO;
465 subprog = 0;
466 } else if (strcmp(fw_name, "PSP_RIB_FILE_SUB0") == 0) {
467 fw_type = AMD_RIB;
468 subprog = 0;
469 } else if (strcmp(fw_name, "PSP_RIB_FILE_SUB1") == 0) {
470 fw_type = AMD_RIB;
471 subprog = 1;
472 } else if (strcmp(fw_name, "FEATURE_TABLE_FILE") == 0) {
473 fw_type = AMD_FW_FCFG_TABLE;
474 subprog = 0;
475 } else if (strcmp(fw_name, "PSP_MPDMATFFW_FILE") == 0) {
476 fw_type = AMD_FW_MPDMA_TF;
477 subprog = 0;
478 } else if (strcmp(fw_name, "PSP_GMI3PHYFW_FILE") == 0) {
479 fw_type = AMD_FW_GMI3_PHY;
480 subprog = 0;
481 } else if (strcmp(fw_name, "PSP_MPDMAPMFW_FILE") == 0) {
482 fw_type = AMD_FW_MPDMA_PM;
483 subprog = 0;
484 } else if (strcmp(fw_name, "PSP_TOKEN_UNLOCK_FILE") == 0) {
485 fw_type = AMD_TOKEN_UNLOCK;
486 subprog = 0;
487 } else if (strcmp(fw_name, "SEV_DATA_FILE") == 0) {
488 fw_type = AMD_SEV_DATA;
489 subprog = 0;
490 } else if (strcmp(fw_name, "SEV_CODE_FILE") == 0) {
491 fw_type = AMD_SEV_CODE;
492 subprog = 0;
493 } else {
494 fw_type = AMD_FW_INVALID;
495 /* TODO: Add more */
498 /* Search and fill the filename */
499 psp_tableptr = &amd_psp_fw_table[0];
500 if (fw_type != AMD_FW_SKIP && fw_type != AMD_FW_INVALID) {
501 while (psp_tableptr->type != AMD_FW_INVALID) {
502 /* instance are not used in PSP table */
503 if (psp_tableptr->type == fw_type && psp_tableptr->subprog == subprog
504 && psp_tableptr->inst == instance) {
505 if (psp_tableptr->type != AMD_PSP_FUSE_CHAIN) {
506 psp_tableptr->filename = filename;
507 psp_tableptr->hash_tbl_id = hash_tbl_id;
508 psp_tableptr->fwid_type = fwid_type;
510 SET_LEVEL(psp_tableptr, level_to_set, PSP,
511 cb_config->recovery_ab);
512 break;
514 psp_tableptr++;
517 if (fw_type == AMD_FW_INVALID)
518 return 0;
519 else
520 return 1;
522 #define PMUI_STR_BASE "PSP_PMUI_FILE"
523 #define PMUD_STR_BASE "PSP_PMUD_FILE"
524 #define PMU_STR_BASE_LEN strlen(PMUI_STR_BASE)
525 #define PMU_STR_SUB_INDEX strlen(PMUI_STR_BASE"_SUB")
526 #define PMU_STR_INS_INDEX strlen(PMUI_STR_BASE"_SUBx_INS")
527 #define PMU_STR_ALL_LEN strlen(PMUI_STR_BASE"_SUBx_INSx")
529 static uint8_t find_register_fw_filename_bios_dir(char *fw_name, char *filename,
530 char level_to_set, amd_cb_config *cb_config)
532 amd_bios_type fw_type = AMD_BIOS_INVALID;
533 amd_bios_entry *bhd_tableptr;
534 uint8_t subprog = 0;
535 uint8_t instance = 0;
537 (void) (cb_config); /* Remove warning and reserved for future. */
539 if (strncmp(fw_name, PMUI_STR_BASE, PMU_STR_BASE_LEN) == 0) {
540 assert(strlen(fw_name) == PMU_STR_ALL_LEN);
541 fw_type = AMD_BIOS_PMUI;
542 subprog = strtol(&fw_name[PMU_STR_SUB_INDEX], NULL, 16);
543 instance = strtol(&fw_name[PMU_STR_INS_INDEX], NULL, 16);
544 } else if (strncmp(fw_name, PMUD_STR_BASE, PMU_STR_BASE_LEN) == 0) {
545 assert(strlen(fw_name) == PMU_STR_ALL_LEN);
546 fw_type = AMD_BIOS_PMUD;
547 subprog = strtol(&fw_name[PMU_STR_SUB_INDEX], NULL, 16);
548 instance = strtol(&fw_name[PMU_STR_INS_INDEX], NULL, 16);
549 } else if (strcmp(fw_name, "RTM_PUBKEY_FILE") == 0) {
550 fw_type = AMD_BIOS_RTM_PUBKEY;
551 subprog = 0;
552 instance = 0;
553 } else if (strcmp(fw_name, "PSP_MP2CFG_FILE") == 0) {
554 if (cb_config->load_mp2_fw) {
555 fw_type = AMD_BIOS_MP2_CFG;
556 subprog = 0;
557 } else {
558 fw_type = AMD_BIOS_SKIP;
560 } else {
561 fw_type = AMD_BIOS_INVALID;
564 bhd_tableptr = amd_bios_table;
566 if (fw_type != AMD_BIOS_INVALID && fw_type != AMD_BIOS_SKIP) {
567 while (bhd_tableptr->type != AMD_BIOS_INVALID) {
568 if (bhd_tableptr->type == fw_type &&
569 bhd_tableptr->subpr == subprog &&
570 bhd_tableptr->inst == instance) {
571 bhd_tableptr->filename = filename;
572 SET_LEVEL(bhd_tableptr, level_to_set, BDT,
573 cb_config->recovery_ab);
574 break;
576 bhd_tableptr++;
579 if (fw_type == AMD_BIOS_INVALID)
580 return 0;
581 else
582 return 1;
585 #define MAX_LINE_SIZE 1024
587 int get_input_file_line(FILE *f, char line[], int line_buf_size)
589 if (fgets(line, line_buf_size, f) == NULL)
590 return LINE_EOF;
592 /* If the file contains a line that is too long, then it's best
593 * to let the user know right away rather than passing back a
594 * truncated result that will lead to problems later on.
596 line[strlen(line) - 1] = '\0';
598 if (strlen(line) == ((size_t) (line_buf_size - 1))) {
599 fprintf(stderr, "The line size in config file should be lower than %d bytes.\n",
600 MAX_LINE_SIZE);
601 exit(1);
604 return OK;
607 static int is_valid_entry(char *oneline, regmatch_t match[N_MATCHES])
609 int retval, index;
611 for (index = 0; index < N_MATCHES; index++) {
612 match[index].rm_so = -1;
613 match[index].rm_eo = -1;
615 if (regexec(&entries_line_expr, oneline, N_MATCHES, match, 0) == 0) {
616 /* match[1]: FW type
617 match[2]: FW filename
618 match[4]: Optional directory level to be dropped
619 match[6]: Optional hash table ID to put the hash for the entry
621 if (match[FW_TYPE].rm_eo != -1)
622 oneline[match[FW_TYPE].rm_eo] = '\0';
623 if (match[FW_FILE].rm_eo != -1)
624 oneline[match[FW_FILE].rm_eo] = '\0';
625 if (match[OPT_LEVEL].rm_eo != -1)
626 oneline[match[OPT_LEVEL].rm_eo] = '\0';
627 if (match[OPT_HASH_TABLE_ID].rm_eo != -1)
628 oneline[match[OPT_HASH_TABLE_ID].rm_eo] = '\0';
629 if (match[OPT_FWID_TYPE].rm_eo != -1)
630 oneline[match[OPT_FWID_TYPE].rm_eo] = '\0';
631 retval = 1;
632 } else {
633 retval = 0;
636 return retval;
639 static int skip_comment_blank_line(char *oneline)
641 int retval;
643 if (regexec(&blank_or_comment_expr, oneline, 0, NULL, 0) == 0) {
644 /* skip comment and blank */
645 retval = 1;
646 } else {
647 /* no match */
648 retval = 0;
651 return retval;
654 static char get_level_from_config(char *line, regoff_t level_index, amd_cb_config *cb_config)
656 char lvl = 'x';
657 /* If the optional level field is present, extract the level char. */
658 if (level_index != -1) {
659 if (cb_config->recovery_ab == 0)
660 lvl = line[level_index + 1];
661 else if (strlen(&line[level_index]) >= 3)
662 lvl = line[level_index + 2];
665 assert(lvl == 'x' || lvl == 'X' ||
666 lvl == 'b' || lvl == 'B' ||
667 lvl == '1' || lvl == '2');
669 return lvl;
672 static uint8_t get_hash_tbl_id(char *line, regoff_t hash_tbl_index)
674 uint8_t tbl = 0;
675 /* If the optional hash table field is present, extract the table id char. */
676 if (hash_tbl_index != -1)
677 tbl = (uint8_t)atoi(&line[hash_tbl_index + 1]);
679 assert(tbl < MAX_NUM_HASH_TABLES);
680 return tbl;
683 static fwid_type_t get_fwid_type(char *line, regoff_t fwid_type_index)
685 if (fwid_type_index != -1 && !strncmp(&line[fwid_type_index], "UUID", strlen("UUID")))
686 return FWID_TYPE_UUID;
688 return FWID_TYPE_FWID;
691 static uint8_t process_one_line(char *oneline, regmatch_t *match, char *dir,
692 amd_cb_config *cb_config)
694 char *path_filename, *fn = &(oneline[match[FW_FILE].rm_so]);
695 char *fw_type_str = &(oneline[match[FW_TYPE].rm_so]);
696 regoff_t ch_lvl_index = match[OPT_LEVEL].rm_so == match[OPT_LEVEL].rm_eo ?
697 -1 : match[OPT_LEVEL].rm_so;
698 regoff_t ch_hash_tbl_index =
699 match[OPT_HASH_TABLE_ID].rm_so == match[OPT_HASH_TABLE_ID].rm_eo ?
700 -1 : match[OPT_HASH_TABLE_ID].rm_so;
701 regoff_t ch_fwid_type_index = match[OPT_FWID_TYPE].rm_so == match[OPT_FWID_TYPE].rm_eo ?
702 -1 : match[OPT_FWID_TYPE].rm_so;
703 char ch_lvl = get_level_from_config(oneline, ch_lvl_index, cb_config);
704 uint8_t ch_hash_tbl = get_hash_tbl_id(oneline, ch_hash_tbl_index);
705 fwid_type_t ch_fwid_type = get_fwid_type(oneline, ch_fwid_type_index);
707 path_filename = malloc(MAX_LINE_SIZE * 2 + 2);
708 if (strchr(fn, '/'))
709 snprintf(path_filename, MAX_LINE_SIZE * 2 + 2, "%.*s",
710 MAX_LINE_SIZE, fn);
711 else
712 snprintf(path_filename, MAX_LINE_SIZE * 2 + 2, "%.*s/%.*s",
713 MAX_LINE_SIZE, dir, MAX_LINE_SIZE, fn);
715 if (find_register_fw_filename_psp_dir(fw_type_str, path_filename,
716 ch_lvl, ch_hash_tbl, ch_fwid_type, cb_config) == 0) {
717 if (find_register_fw_filename_bios_dir(fw_type_str, path_filename,
718 ch_lvl, cb_config) == 0) {
719 fprintf(stderr, "Module's name \"%s\" is not valid\n", fw_type_str);
720 return 0; /* Stop parsing. */
723 return 1;
726 bool needs_ish(enum platform platform_type)
728 if (platform_type == PLATFORM_MENDOCINO || platform_type == PLATFORM_PHOENIX || platform_type == PLATFORM_GLINDA)
729 return true;
730 else
731 return false;
734 static bool is_second_gen(enum platform platform_type)
736 switch (platform_type) {
737 case PLATFORM_CARRIZO:
738 case PLATFORM_STONEYRIDGE:
739 case PLATFORM_RAVEN:
740 case PLATFORM_PICASSO:
741 return false;
742 case PLATFORM_RENOIR:
743 case PLATFORM_LUCIENNE:
744 case PLATFORM_CEZANNE:
745 case PLATFORM_MENDOCINO:
746 case PLATFORM_PHOENIX:
747 case PLATFORM_GLINDA:
748 case PLATFORM_GENOA:
749 return true;
750 case PLATFORM_UNKNOWN:
751 default:
752 fprintf(stderr, "Error: Invalid SOC name.\n\n");
753 return false;
757 #define FW_LOCATION "FIRMWARE_LOCATION"
758 #define SOC_NAME "SOC_NAME"
760 return value:
761 0: The config file can not be parsed correctly.
762 1: The config file can be parsed correctly.
764 uint8_t process_config(FILE *config, amd_cb_config *cb_config)
766 char oneline[MAX_LINE_SIZE];
767 regmatch_t match[N_MATCHES];
768 char dir[MAX_LINE_SIZE] = {'\0'};
769 uint32_t dir_len;
770 int index;
772 for (index = 0; index < N_MATCHES; index++) {
773 match[index].rm_so = -1;
774 match[index].rm_eo = -1;
777 compile_reg_expr(REG_EXTENDED | REG_NEWLINE,
778 blank_or_comment_regex, &blank_or_comment_expr);
779 compile_reg_expr(REG_EXTENDED | REG_NEWLINE,
780 entries_line_regex, &entries_line_expr);
782 /* Get a line */
783 /* Get FIRMWARE_LOCATION in the first loop */
784 while (get_input_file_line(config, oneline, MAX_LINE_SIZE) == OK) {
785 /* get a line */
786 if (skip_comment_blank_line(oneline))
787 continue;
788 if (is_valid_entry(oneline, match)) {
789 if (strcmp(&(oneline[match[FW_TYPE].rm_so]), FW_LOCATION) == 0) {
790 dir_len = match[FW_FILE].rm_eo - match[FW_FILE].rm_so;
791 assert(dir_len < MAX_LINE_SIZE);
792 snprintf(dir, MAX_LINE_SIZE, "%.*s", dir_len,
793 &(oneline[match[FW_FILE].rm_so]));
794 } else if (strcmp(&(oneline[match[FW_TYPE].rm_so]), SOC_NAME) == 0) {
795 cb_config->soc_id = identify_platform(
796 &(oneline[match[FW_FILE].rm_so]));
801 cb_config->second_gen = is_second_gen(cb_config->soc_id);
803 if (needs_ish(cb_config->soc_id))
804 cb_config->need_ish = true;
806 if (cb_config->need_ish)
807 cb_config->recovery_ab = true;
809 if (cb_config->recovery_ab)
810 cb_config->multi_level = true;
812 if (dir[0] == '\0') {
813 fprintf(stderr, "No line with FIRMWARE_LOCATION\n");
814 return 0;
817 fseek(config, 0, SEEK_SET);
818 /* Get a line */
819 while (get_input_file_line(config, oneline, MAX_LINE_SIZE) == OK) {
820 /* get a line */
821 if (skip_comment_blank_line(oneline))
822 continue;
823 if (is_valid_entry(oneline, match)) {
824 if (strcmp(&(oneline[match[FW_TYPE].rm_so]), FW_LOCATION) == 0 ||
825 strcmp(&(oneline[match[FW_TYPE].rm_so]), SOC_NAME) == 0) {
826 continue;
827 } else {
828 if (process_one_line(oneline, match, dir,
829 cb_config) == 0)
830 return 0;
832 } else {
833 fprintf(stderr, "AMDFWTOOL config file line can't be parsed \"%s\"\n", oneline);
834 return 0;
837 return 1;