/ util / amdfwtool / data_parse.c
data_parse.c
  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  
 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  
 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  
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  
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  
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  
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  
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  
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  
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  
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  
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  
726  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  
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   */
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  }