aboutsummaryrefslogtreecommitdiff
path: root/util/amdfwtool/data_parse.c
diff options
context:
space:
mode:
authorZheng Bao <fishbaozi@gmail.com>2020-10-28 11:38:09 +0800
committerFelix Held <felix-coreboot@felixheld.de>2020-10-30 12:10:04 +0000
commitc5e28abaf803465ae4bfec1904618497e077ca50 (patch)
tree84463d41d4bf44c1a05efd456c03e94b6779dfa5 /util/amdfwtool/data_parse.c
parent1cd013bec5967ca1d0203de0f506a8af984f814e (diff)
amdfwtool: Take a config file instead of command line parameters
To verify the consistency, see if timeless builds with and without this patch result in identical coreboot.rom files. BUG=b:154032833 TEST=Build & boot on mandolin Change-Id: Icae73d0730106aab687486e555ba947796e5e757 Signed-off-by: Zheng Bao <fishbaozi@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/42859 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Nikolai Vyssotski <nikolai.vyssotski@amd.corp-partner.google.com> Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
Diffstat (limited to 'util/amdfwtool/data_parse.c')
-rw-r--r--util/amdfwtool/data_parse.c418
1 files changed, 418 insertions, 0 deletions
diff --git a/util/amdfwtool/data_parse.c b/util/amdfwtool/data_parse.c
new file mode 100644
index 0000000000..bb616d3405
--- /dev/null
+++ b/util/amdfwtool/data_parse.c
@@ -0,0 +1,418 @@
+#include <stdio.h>
+#include <regex.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "amdfwtool.h"
+
+/* TODO: a empty line does not matched. */
+static const char blank_or_comment_regex[] =
+ /* a blank line */
+ "(^[[:space:]]*$)"
+ "|" /* or ... */
+ /* a line consisting of: optional whitespace followed by */
+ "(^[[:space:]]*"
+ /* a '#' character and optionally, additional characters */
+ "#.*$)";
+static regex_t blank_or_comment_expr;
+
+static const char entries_line_regex[] =
+ /* optional whitespace */
+ "^[[:space:]]*"
+ /* followed by a chunk of nonwhitespace for macro field */
+ "([^[:space:]]+)"
+ /* followed by one or more whitespace characters */
+ "[[:space:]]+"
+ /* followed by a chunk of nonwhitespace for filename field */
+ "([^[:space:]]+)"
+ /* followed by optional whitespace */
+ "[[:space:]]*$";
+static regex_t entries_line_expr;
+
+void compile_reg_expr(int cflags, const char *expr, regex_t *reg)
+{
+ static const size_t ERROR_BUF_SIZE = 256;
+ char error_msg[ERROR_BUF_SIZE];
+ int result;
+
+ result = regcomp(reg, expr, cflags);
+ if (result != 0) {
+ regerror(result, reg, error_msg, ERROR_BUF_SIZE);
+ printf("%s\n", error_msg);
+ }
+}
+
+extern amd_fw_entry amd_psp_fw_table[];
+extern amd_bios_entry amd_bios_table[];
+
+static uint8_t find_register_fw_filename_psp_dir(char *fw_name, char *filename,
+ amd_cb_config *cb_config)
+{
+ amd_fw_type fw_type = AMD_FW_INVALID;
+ amd_fw_entry *psp_tableptr;
+ uint8_t subprog;
+
+ if (strcmp(fw_name, "PSPBTLDR_WL_FILE") == 0) {
+ if (cb_config->have_whitelist == 1) {
+ fw_type = AMD_FW_PSP_BOOTLOADER;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "PSPBTLDR_FILE") == 0) {
+ if (cb_config->have_whitelist == 0) {
+ fw_type = AMD_FW_PSP_BOOTLOADER;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "AMD_PUBKEY_FILE") == 0) {
+ fw_type = AMD_FW_PSP_PUBKEY;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSPRCVR_FILE") == 0) {
+ fw_type = AMD_FW_PSP_RECOVERY;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PUBSIGNEDKEY_FILE") == 0) {
+ fw_type = AMD_FW_PSP_RTM_PUBKEY;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSPNVRAM_FILE") == 0) {
+ fw_type = AMD_FW_PSP_NVRAM;
+ subprog = 0;
+ } else if (strcmp(fw_name, "SMUSCS_FILE") == 0) {
+ fw_type = AMD_FW_PSP_SMUSCS;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSPTRUSTLETS_FILE") == 0) {
+ fw_type = AMD_FW_PSP_TRUSTLETS;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSPSECUREDEBUG_FILE") == 0) {
+ fw_type = AMD_FW_PSP_SECURED_DEBUG;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_SMUFW1_SUB0_FILE") == 0) {
+ fw_type = AMD_FW_PSP_SMU_FIRMWARE;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_SMUFW1_SUB1_FILE") == 0) {
+ fw_type = AMD_FW_PSP_SMU_FIRMWARE;
+ subprog = 1;
+ } else if (strcmp(fw_name, "PSP_SMUFW1_SUB2_FILE") == 0) {
+ fw_type = AMD_FW_PSP_SMU_FIRMWARE;
+ subprog = 2;
+ } else if (strcmp(fw_name, "PSP_SMUFW2_SUB0_FILE") == 0) {
+ fw_type = AMD_FW_PSP_SMU_FIRMWARE2;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_SMUFW2_SUB1_FILE") == 0) {
+ fw_type = AMD_FW_PSP_SMU_FIRMWARE2;
+ subprog = 1;
+ } else if (strcmp(fw_name, "PSP_SMUFW2_SUB2_FILE") == 0) {
+ fw_type = AMD_FW_PSP_SMU_FIRMWARE2;
+ subprog = 2;
+ } else if (strcmp(fw_name, "PSP_SEC_DBG_KEY_FILE") == 0) {
+ if (cb_config->unlock_secure == 1) {
+ fw_type = AMD_FW_PSP_SECURED_DEBUG;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "PSP_SEC_DEBUG_FILE") == 0) {
+ if (cb_config->unlock_secure == 1) {
+ fw_type = AMD_DEBUG_UNLOCK;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "PSP_ABL0_FILE") == 0) {
+ fw_type = AMD_ABL0;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_ABL1_FILE") == 0) {
+ fw_type = AMD_ABL1;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_ABL2_FILE") == 0) {
+ fw_type = AMD_ABL2;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_ABL3_FILE") == 0) {
+ fw_type = AMD_ABL3;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_ABL4_FILE") == 0) {
+ fw_type = AMD_ABL4;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_ABL5_FILE") == 0) {
+ fw_type = AMD_ABL5;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_ABL6_FILE") == 0) {
+ fw_type = AMD_ABL6;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_ABL7_FILE") == 0) {
+ fw_type = AMD_ABL7;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSPSECUREOS_FILE") == 0) {
+ if (cb_config->use_secureos == 1) {
+ fw_type = AMD_FW_PSP_SECURED_OS;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "PSPTRUSTLETS_FILE") == 0) {
+ if (cb_config->use_secureos) {
+ fw_type = AMD_FW_PSP_TRUSTLETS;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "TRUSTLETKEY_FILE") == 0) {
+ if (cb_config->use_secureos) {
+ fw_type = AMD_FW_PSP_TRUSTLETKEY;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "PSP_IKEK_FILE") == 0) {
+ fw_type = AMD_WRAPPED_IKEK;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_SECG1_FILE") == 0) {
+ fw_type = AMD_SEC_GASKET;
+ subprog = 1;
+ } else if (strcmp(fw_name, "PSP_SECG2_FILE") == 0) {
+ fw_type = AMD_SEC_GASKET;
+ subprog = 2;
+ } else if (strcmp(fw_name, "PSP_MP2FW1_FILE") == 0) {
+ if (cb_config->load_mp2_fw == 1) {
+ fw_type = AMD_MP2_FW;
+ subprog = 1;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "PSP_MP2FW2_FILE") == 0) {
+ if (cb_config->load_mp2_fw == 1) {
+ fw_type = AMD_MP2_FW;
+ subprog = 2;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "PSP_MP2CFG_FILE") == 0) {
+ if (cb_config->load_mp2_fw == 1) {
+ fw_type = AMD_BIOS_MP2_CFG;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else if (strcmp(fw_name, "PSP_DRIVERS_FILE") == 0) {
+ fw_type = AMD_DRIVER_ENTRIES;
+ subprog = 0;
+ } else if (strcmp(fw_name, "PSP_S0I3_FILE") == 0) {
+ if (cb_config->s0i3 == 1) {
+ fw_type = AMD_S0I3_DRIVER;
+ subprog = 0;
+ } else {
+ fw_type = AMD_FW_SKIP;
+ }
+ } else {
+ fw_type = AMD_FW_INVALID;
+ /* TODO: Add more */
+ }
+ /* Search and fill the filename */
+ psp_tableptr = &amd_psp_fw_table[0];
+ if (fw_type != AMD_FW_SKIP && fw_type != AMD_FW_INVALID) {
+ while (psp_tableptr->type != AMD_FW_INVALID) {
+ /* instance are not used in PSP table */
+ if (psp_tableptr->type == fw_type && psp_tableptr->subprog == subprog) {
+ psp_tableptr->filename = filename;
+ break;
+ }
+ psp_tableptr++;
+ }
+ }
+ if (fw_type == AMD_FW_INVALID)
+ return 0;
+ else
+ return 1;
+}
+
+static uint8_t find_register_fw_filename_bios_dir(char *fw_name, char *filename,
+ amd_cb_config *cb_config)
+{
+ amd_bios_type fw_type = AMD_BIOS_INVALID;
+ amd_bios_entry *bhd_tableptr;
+ uint8_t subprog, instance = 0;
+
+ (void) (cb_config); /* Remove warning and reserved for future. */
+
+ if (strcmp(fw_name, "PSP_PMUI_FILE1") == 0) {
+ fw_type = AMD_BIOS_PMUI;
+ subprog = 0;
+ instance = 1;
+ } else if (strcmp(fw_name, "PSP_PMUI_FILE2") == 0) {
+ fw_type = AMD_BIOS_PMUI;
+ subprog = 0;
+ instance = 4;
+ } else if (strcmp(fw_name, "PSP_PMUI_FILE3") == 0) {
+ fw_type = AMD_BIOS_PMUI;
+ subprog = 1;
+ instance = 1;
+ } else if (strcmp(fw_name, "PSP_PMUI_FILE4") == 0) {
+ fw_type = AMD_BIOS_PMUI;
+ subprog = 1;
+ instance = 4;
+ } else if (strcmp(fw_name, "PSP_PMUD_FILE1") == 0) {
+ fw_type = AMD_BIOS_PMUD;
+ subprog = 0;
+ instance = 1;
+ } else if (strcmp(fw_name, "PSP_PMUD_FILE2") == 0) {
+ fw_type = AMD_BIOS_PMUD;
+ subprog = 0;
+ instance = 4;
+ } else if (strcmp(fw_name, "PSP_PMUD_FILE3") == 0) {
+ fw_type = AMD_BIOS_PMUD;
+ subprog = 1;
+ instance = 1;
+ } else if (strcmp(fw_name, "PSP_PMUD_FILE4") == 0) {
+ fw_type = AMD_BIOS_PMUD;
+ subprog = 1;
+ instance = 4;
+ } else {
+ fw_type = AMD_BIOS_INVALID;
+ }
+
+ bhd_tableptr = amd_bios_table;
+
+ if (fw_type != AMD_BIOS_INVALID && fw_type != AMD_BIOS_SKIP) {
+ while (bhd_tableptr->type != AMD_BIOS_INVALID) {
+ if (bhd_tableptr->type == fw_type &&
+ bhd_tableptr->subpr == subprog &&
+ bhd_tableptr->inst == instance) {
+ bhd_tableptr->filename = filename;
+ break;
+ }
+ bhd_tableptr++;
+ }
+ }
+ if (fw_type == AMD_BIOS_INVALID)
+ return 0;
+ else
+ return 1;
+}
+
+#define MAX_LINE_SIZE 1024
+
+int get_input_file_line(FILE *f, char line[], int line_buf_size)
+{
+ if (fgets(line, line_buf_size, f) == NULL)
+ return LINE_EOF;
+
+ /* If the file contains a line that is too long, then it's best
+ * to let the user know right away rather than passing back a
+ * truncated result that will lead to problems later on.
+ */
+ line[strlen(line) - 1] = '\0';
+
+ if (strlen(line) == ((size_t) (line_buf_size - 1))) {
+ printf("The line size in config file should be lower than %d bytes.\n",
+ MAX_LINE_SIZE);
+ exit(1);
+ }
+
+ return OK;
+}
+
+static int is_valid_entry(char *oneline, regmatch_t *match)
+{
+ int retval;
+
+ if (regexec(&entries_line_expr, oneline, 3, match, 0) == 0) {
+ oneline[match[1].rm_eo] = '\0';
+ oneline[match[2].rm_eo] = '\0';
+ retval = 1;
+ } else
+ retval = 0;
+
+ return retval;
+}
+
+static int skip_comment_blank_line(char *oneline)
+{
+ int retval;
+
+ if (regexec(&blank_or_comment_expr, oneline, 0, NULL, 0) == 0) {
+ /* skip comment and blank */
+ retval = 1;
+ } else {
+ /* no match */
+ retval = 0;
+ }
+
+ return retval;
+}
+
+#define N_MATCHES 4
+/*
+ return value:
+ 0: The config file can not be parsed correctly.
+ 1: The config file can be parsed correctly.
+ */
+uint8_t process_config(FILE *config, amd_cb_config *cb_config, uint8_t print_deps)
+{
+ char oneline[MAX_LINE_SIZE], *path_filename;
+ regmatch_t match[N_MATCHES];
+ char dir[MAX_LINE_SIZE] = {'\0'};
+
+ compile_reg_expr(REG_EXTENDED | REG_NEWLINE,
+ blank_or_comment_regex, &blank_or_comment_expr);
+ compile_reg_expr(REG_EXTENDED | REG_NEWLINE,
+ entries_line_regex, &entries_line_expr);
+
+ /* Get a line */
+ /* Get FIRMWARE_LOCATE in the first loop */
+ while (get_input_file_line(config, oneline, MAX_LINE_SIZE) == OK) {
+ /* get a line */
+ if (skip_comment_blank_line(oneline))
+ continue;
+ if (is_valid_entry(oneline, match)) {
+ if (strcmp(&(oneline[match[1].rm_so]), "FIRMWARE_LOCATE") == 0) {
+ strcpy(dir, &(oneline[match[2].rm_so]));
+ break;
+ }
+ }
+ }
+
+ if (dir[0] == '\0') {
+ fprintf(stderr, "No line with FIRMWARE_LOCATION\n");
+ return 0;
+ }
+
+ fseek(config, 0, SEEK_SET);
+ /* Get a line */
+ while (get_input_file_line(config, oneline, MAX_LINE_SIZE) == OK) {
+ /* get a line */
+ if (skip_comment_blank_line(oneline))
+ continue;
+ if (is_valid_entry(oneline, match)) {
+ if (strcmp(&(oneline[match[1].rm_so]), "FIRMWARE_LOCATE") == 0) {
+ continue;
+ } else {
+ path_filename = malloc(MAX_LINE_SIZE);
+ strcpy(path_filename, dir);
+ strcat(path_filename, "/");
+ strcat(path_filename, &(oneline[match[2].rm_so]));
+
+ if (find_register_fw_filename_psp_dir(
+ &(oneline[match[1].rm_so]),
+ path_filename, cb_config) == 0) {
+ if (find_register_fw_filename_bios_dir(
+ &(oneline[match[1].rm_so]),
+ path_filename, cb_config) == 0) {
+ fprintf(stderr, "Module's name \"%s\" is not valid\n", oneline);
+ return 0; /* Stop parsing. */
+ } else {
+ if (print_deps)
+ printf(" %s ", path_filename);
+ }
+ } else {
+ if (print_deps)
+ printf(" %s ", path_filename);
+ }
+ }
+ } else {
+ fprintf(stderr, "AMDFWTOOL config file line can't be parsed \"%s\"\n", oneline);
+ return 0;
+ }
+ }
+ return 1;
+}