xref: /aosp_15_r20/external/coreboot/util/amdfwtool/data_parse.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdio.h>
4 #include <regex.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdint.h>
8 #include <assert.h>
9 
10 #include "amdfwtool.h"
11 
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;
22 
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.
42 
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
47 	 */
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
57 
58 	   Examples:
59 	      H2: Put the hash for the concerned entry in Hash Table 2
60 	 */
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.
65 	*/
66 	"([[:space:]]+(UUID))?"
67 	/* followed by optional whitespace */
68 	"[[:space:]]*$";
69 static regex_t entries_line_expr;
70 
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,
81 };
82 
compile_reg_expr(int cflags,const char * expr,regex_t * reg)83 void compile_reg_expr(int cflags, const char *expr, regex_t *reg)
84 {
85 	static const size_t ERROR_BUF_SIZE = 256;
86 	char error_msg[ERROR_BUF_SIZE];
87 	int result;
88 
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);
93 	}
94 }
95 
identify_platform(char * soc_name)96 static enum platform identify_platform(char *soc_name)
97 {
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;
122 }
123 
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;                           \
140 		}                                        \
141 	} while (0)
142 
143 extern amd_fw_entry amd_psp_fw_table[];
144 extern amd_bios_entry amd_bios_table[];
145 
find_register_fw_filename_psp_dir(char * fw_name,char * filename,char level_to_set,uint8_t hash_tbl_id,fwid_type_t fwid_type,amd_cb_config * cb_config)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)
149 {
150 	amd_fw_type fw_type = AMD_FW_INVALID;
151 	amd_fw_entry *psp_tableptr;
152 	uint8_t subprog;
153 	uint8_t instance = 0;
154 
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;
161 		}
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;
168 		}
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;
175 		}
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;
242 		}
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;
249 		}
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;
280 		}
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;
287 		}
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;
294 		}
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;
313 		}
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;
320 		}
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;
327 		}
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;
379 		}
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;
407 		}
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;
441 		}
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 */
496 	}
497 
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;
509 				}
510 				SET_LEVEL(psp_tableptr, level_to_set, PSP,
511 					cb_config->recovery_ab);
512 				break;
513 			}
514 			psp_tableptr++;
515 		}
516 	}
517 	if (fw_type == AMD_FW_INVALID)
518 		return 0;
519 	else
520 		return 1;
521 }
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")
528 
find_register_fw_filename_bios_dir(char * fw_name,char * filename,char level_to_set,amd_cb_config * cb_config)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)
531 {
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;
536 
537 	(void) (cb_config);	/* Remove warning and reserved for future. */
538 
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;
559 		}
560 	} else {
561 		fw_type = AMD_BIOS_INVALID;
562 	}
563 
564 	bhd_tableptr = amd_bios_table;
565 
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;
575 			}
576 			bhd_tableptr++;
577 		}
578 	}
579 	if (fw_type == AMD_BIOS_INVALID)
580 		return 0;
581 	else
582 		return 1;
583 }
584 
585 #define MAX_LINE_SIZE 1024
586 
get_input_file_line(FILE * f,char line[],int line_buf_size)587 int get_input_file_line(FILE *f, char line[], int line_buf_size)
588 {
589 	if (fgets(line, line_buf_size, f) == NULL)
590 		return LINE_EOF;
591 
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.
595 	 */
596 	line[strlen(line) - 1] = '\0';
597 
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);
602 	}
603 
604 	return OK;
605 }
606 
is_valid_entry(char * oneline,regmatch_t match[N_MATCHES])607 static int is_valid_entry(char *oneline, regmatch_t match[N_MATCHES])
608 {
609 	int retval, index;
610 
611 	for (index = 0; index < N_MATCHES; index++) {
612 		match[index].rm_so = -1;
613 		match[index].rm_eo = -1;
614 	}
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
620 		 */
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;
634 	}
635 
636 	return retval;
637 }
638 
skip_comment_blank_line(char * oneline)639 static int skip_comment_blank_line(char *oneline)
640 {
641 	int retval;
642 
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;
649 	}
650 
651 	return retval;
652 }
653 
get_level_from_config(char * line,regoff_t level_index,amd_cb_config * cb_config)654 static char get_level_from_config(char *line, regoff_t level_index, amd_cb_config *cb_config)
655 {
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];
663 	}
664 
665 	assert(lvl == 'x' || lvl == 'X' ||
666 		lvl == 'b' || lvl == 'B' ||
667 		lvl == '1' || lvl == '2');
668 
669 	return lvl;
670 }
671 
get_hash_tbl_id(char * line,regoff_t hash_tbl_index)672 static uint8_t get_hash_tbl_id(char *line, regoff_t hash_tbl_index)
673 {
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]);
678 
679 	assert(tbl < MAX_NUM_HASH_TABLES);
680 	return tbl;
681 }
682 
get_fwid_type(char * line,regoff_t fwid_type_index)683 static fwid_type_t get_fwid_type(char *line, regoff_t fwid_type_index)
684 {
685 	if (fwid_type_index != -1 && !strncmp(&line[fwid_type_index], "UUID", strlen("UUID")))
686 		return FWID_TYPE_UUID;
687 
688 	return FWID_TYPE_FWID;
689 }
690 
process_one_line(char * oneline,regmatch_t * match,char * dir,amd_cb_config * cb_config)691 static uint8_t process_one_line(char *oneline, regmatch_t *match, char *dir,
692 	amd_cb_config *cb_config)
693 {
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);
706 
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);
714 
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. */
721 		}
722 	}
723 	return 1;
724 }
725 
needs_ish(enum platform platform_type)726 static bool needs_ish(enum platform platform_type)
727 {
728 	if (platform_type == PLATFORM_MENDOCINO || platform_type == PLATFORM_PHOENIX || platform_type == PLATFORM_GLINDA)
729 		return true;
730 	else
731 		return false;
732 }
733 
is_second_gen(enum platform platform_type)734 static bool is_second_gen(enum platform platform_type)
735 {
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;
754 	}
755 }
756 
757 #define FW_LOCATION "FIRMWARE_LOCATION"
758 #define SOC_NAME "SOC_NAME"
759 /*
760   return value:
761 	0: The config file can not be parsed correctly.
762 	1: The config file can be parsed correctly.
763  */
process_config(FILE * config,amd_cb_config * cb_config)764 uint8_t process_config(FILE *config, amd_cb_config *cb_config)
765 {
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;
771 
772 	for (index = 0; index < N_MATCHES; index++) {
773 		match[index].rm_so = -1;
774 		match[index].rm_eo = -1;
775 	}
776 
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);
781 
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]));
797 			}
798 		}
799 	}
800 
801 	cb_config->second_gen = is_second_gen(cb_config->soc_id);
802 
803 	if (needs_ish(cb_config->soc_id))
804 		cb_config->need_ish = true;
805 
806 	if (cb_config->need_ish)
807 		cb_config->recovery_ab = true;
808 
809 	if (cb_config->recovery_ab)
810 		cb_config->multi_level = true;
811 
812 	if (dir[0] == '\0') {
813 		fprintf(stderr, "No line with FIRMWARE_LOCATION\n");
814 		return 0;
815 	}
816 
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;
831 			}
832 		} else {
833 			fprintf(stderr, "AMDFWTOOL config file line can't be parsed \"%s\"\n", oneline);
834 			return 0;
835 		}
836 	}
837 	return 1;
838 }
839