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 }