util/amdfwtool: Support multiple firmware identifier types

Currently this tool generates a hash table to verify signed binaries,
with a 2 byte FWID as the only kind of identifier. Going forward some
binaries are going to adopt 16 byte UUID identifiers and more binaries
will follow in the future SoCs. Hence add support for handling multiple
firmware identifier types. While at this remove the unused fwid from the
PSP FW table.

BUG=b:277292697
TEST=Build BIOS image and boot to OS in Myst & Skyrim.

Change-Id: I5180dc0fe812b174b1d40fea9f00a85d6ef00f2f
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/76585
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
diff --git a/util/amdfwtool/amdfwtool.h b/util/amdfwtool/amdfwtool.h
index 24e48eb..aa5a98a 100644
--- a/util/amdfwtool/amdfwtool.h
+++ b/util/amdfwtool/amdfwtool.h
@@ -330,6 +330,11 @@
 #define PSP_BOTH (PSP_LVL1 | PSP_LVL2)
 #define PSP_BOTH_AB (PSP_LVL1_AB | PSP_LVL2_AB)
 
+typedef enum _fwid_type {
+	FWID_TYPE_FWID = 0,
+	FWID_TYPE_UUID,
+} fwid_type_t;
+
 typedef struct _amd_fw_entry_hash {
 	uint16_t fw_id;
 	uint16_t subtype;
@@ -339,9 +344,6 @@
 
 typedef struct _amd_fw_entry {
 	amd_fw_type type;
-	/* Mendocino and later SoCs use fw_id instead of fw_type. fw_type is still around
-	   for backwards compatibility. fw_id can be populated from the PSP binary file. */
-	uint16_t fw_id;
 	char *filename;
 	uint8_t subprog;
 	uint8_t inst;
@@ -358,6 +360,7 @@
 	   include but not limited to: *iKek*, *.tkn, *.stkn */
 	bool skip_hashing;
 	uint8_t hash_tbl_id;
+	fwid_type_t fwid_type;
 	uint32_t num_hash_entries;
 	amd_fw_entry_hash *hash_entries;
 	bool generate_manifest;
diff --git a/util/amdfwtool/data_parse.c b/util/amdfwtool/data_parse.c
index c2dc3e2..9adaa5d 100644
--- a/util/amdfwtool/data_parse.c
+++ b/util/amdfwtool/data_parse.c
@@ -59,6 +59,11 @@
 	      H2: Put the hash for the concerned entry in Hash Table 2
 	 */
 	"([[:space:]]+([Hh][0-9]+))?"
+	/* followed by an optional whitespace + "UUID" to indicate the binary is using 16 bytes
+	   UUID as firmware identity. In the absence of this field, the binary is using 2 bytes
+	   FWID as firmware identity.
+	*/
+	"([[:space:]]+(UUID))?"
 	/* followed by optional whitespace */
 	"[[:space:]]*$";
 static regex_t entries_line_expr;
@@ -70,6 +75,8 @@
 	OPT_LEVEL,
 	OPT_SPACE2,
 	OPT_HASH_TABLE_ID,
+	OPT_SPACE3,
+	OPT_FWID_TYPE,
 	N_MATCHES,
 };
 
@@ -135,7 +142,8 @@
 extern amd_bios_entry amd_bios_table[];
 
 static uint8_t find_register_fw_filename_psp_dir(char *fw_name, char *filename,
-		char level_to_set, uint8_t hash_tbl_id, amd_cb_config *cb_config)
+		char level_to_set, uint8_t hash_tbl_id, fwid_type_t fwid_type,
+		amd_cb_config *cb_config)
 {
 	amd_fw_type fw_type = AMD_FW_INVALID;
 	amd_fw_entry *psp_tableptr;
@@ -493,6 +501,7 @@
 				SET_LEVEL(psp_tableptr, level_to_set, PSP,
 					cb_config->recovery_ab);
 				psp_tableptr->hash_tbl_id = hash_tbl_id;
+				psp_tableptr->fwid_type = fwid_type;
 				break;
 			}
 			psp_tableptr++;
@@ -606,6 +615,7 @@
 		oneline[match[FW_FILE].rm_eo] = '\0';
 		oneline[match[OPT_LEVEL].rm_eo] = '\0';
 		oneline[match[OPT_HASH_TABLE_ID].rm_eo] = '\0';
+		oneline[match[OPT_FWID_TYPE].rm_eo] = '\0';
 		retval = 1;
 	} else {
 		retval = 0;
@@ -658,6 +668,14 @@
 	return tbl;
 }
 
+static fwid_type_t get_fwid_type(char *line, regoff_t fwid_type_index)
+{
+	if (fwid_type_index != -1 && !strncmp(&line[fwid_type_index], "UUID", strlen("UUID")))
+		return FWID_TYPE_UUID;
+
+	return FWID_TYPE_FWID;
+}
+
 static uint8_t process_one_line(char *oneline, regmatch_t *match, char *dir,
 	amd_cb_config *cb_config)
 {
@@ -668,8 +686,11 @@
 	regoff_t ch_hash_tbl_index =
 		match[OPT_HASH_TABLE_ID].rm_so == match[OPT_HASH_TABLE_ID].rm_eo ?
 							-1 : match[OPT_HASH_TABLE_ID].rm_so;
+	regoff_t ch_fwid_type_index = match[OPT_FWID_TYPE].rm_so == match[OPT_FWID_TYPE].rm_eo ?
+								-1 : match[OPT_FWID_TYPE].rm_so;
 	char ch_lvl = get_level_from_config(oneline, ch_lvl_index, cb_config);
 	uint8_t ch_hash_tbl = get_hash_tbl_id(oneline, ch_hash_tbl_index);
+	fwid_type_t ch_fwid_type = get_fwid_type(oneline, ch_fwid_type_index);
 
 	path_filename = malloc(MAX_LINE_SIZE * 2 + 2);
 	if (strchr(fn, '/'))
@@ -679,10 +700,10 @@
 		snprintf(path_filename, MAX_LINE_SIZE * 2 + 2, "%.*s/%.*s",
 				MAX_LINE_SIZE, dir, MAX_LINE_SIZE, fn);
 
-	if (find_register_fw_filename_psp_dir(
-			fw_type_str, path_filename, ch_lvl, ch_hash_tbl, cb_config) == 0) {
-		if (find_register_fw_filename_bios_dir(
-				fw_type_str, path_filename, ch_lvl, cb_config) == 0) {
+	if (find_register_fw_filename_psp_dir(fw_type_str, path_filename,
+				ch_lvl, ch_hash_tbl, ch_fwid_type, cb_config) == 0) {
+		if (find_register_fw_filename_bios_dir(fw_type_str, path_filename,
+								ch_lvl, cb_config) == 0) {
 			fprintf(stderr, "Module's name \"%s\" is not valid\n", fw_type_str);
 			return 0; /* Stop parsing. */
 		}
diff --git a/util/amdfwtool/signed_psp.c b/util/amdfwtool/signed_psp.c
index 2e19f72..738c588 100644
--- a/util/amdfwtool/signed_psp.c
+++ b/util/amdfwtool/signed_psp.c
@@ -384,7 +384,6 @@
 			exit(-1);
 
 		/* File is successfully processed and is part of signed PSP binaries set. */
-		fw_table[i].fw_id = get_psp_fw_type(soc_id, &header);
 		fw_table[i].addr_signed = signed_start_addr;
 		fw_table[i].file_size = (uint32_t)fd_stat.st_size;
 		hash_files[fw_table[i].hash_tbl_id].present = true;