diff options
-rw-r--r-- | util/amdfwtool/Makefile | 1 | ||||
-rw-r--r-- | util/amdfwtool/Makefile.inc | 1 | ||||
-rw-r--r-- | util/amdfwtool/amdfwtool.h | 7 | ||||
-rw-r--r-- | util/amdfwtool/signed_psp.c | 65 |
4 files changed, 56 insertions, 18 deletions
diff --git a/util/amdfwtool/Makefile b/util/amdfwtool/Makefile index 8ec4e9bb6f..e9bc1ab761 100644 --- a/util/amdfwtool/Makefile +++ b/util/amdfwtool/Makefile @@ -16,6 +16,7 @@ TARGETS = amdfwread amdfwtool WERROR=-Werror CFLAGS=-O2 -Wall -Wextra -Wshadow ${WERROR} CFLAGS += -I $(top)/src/commonlib/bsd/include +CFLAGS += -D_GNU_SOURCE # memmem() from string.h ifneq ($(PKG_CONFIG),) HOSTPKGCONFIG ?= $(PKG_CONFIG) diff --git a/util/amdfwtool/Makefile.inc b/util/amdfwtool/Makefile.inc index 7d96155736..067a137090 100644 --- a/util/amdfwtool/Makefile.inc +++ b/util/amdfwtool/Makefile.inc @@ -5,6 +5,7 @@ amdfwreadobj = amdfwread.o AMDFWTOOLCFLAGS=-O2 -Wall -Wextra -Wshadow -Werror AMDFWTOOLCFLAGS += -I $(top)/src/commonlib/bsd/include +AMDFWTOOLCFLAGS += -D_GNU_SOURCE # memmem() from string.h HOSTPKGCONFIG ?= pkg-config diff --git a/util/amdfwtool/amdfwtool.h b/util/amdfwtool/amdfwtool.h index aa5a98a131..5558f5b7d9 100644 --- a/util/amdfwtool/amdfwtool.h +++ b/util/amdfwtool/amdfwtool.h @@ -335,8 +335,13 @@ typedef enum _fwid_type { FWID_TYPE_UUID, } fwid_type_t; +#define UUID_LEN_BYTES 16 typedef struct _amd_fw_entry_hash { - uint16_t fw_id; + fwid_type_t fwid_type; + union { + uint16_t fw_id; + uint8_t uuid[UUID_LEN_BYTES]; + }; uint16_t subtype; uint32_t sha_len; uint8_t sha[SHA384_DIGEST_LENGTH]; diff --git a/util/amdfwtool/signed_psp.c b/util/amdfwtool/signed_psp.c index 738c588d10..24f76e8762 100644 --- a/util/amdfwtool/signed_psp.c +++ b/util/amdfwtool/signed_psp.c @@ -16,6 +16,7 @@ /* Defines related to hashing signed binaries */ enum hash_header_ver { HASH_HDR_V1 = 1, + HASH_HDR_V2, }; /* Signature ID enums are defined by PSP based on the algorithm used. */ enum signature_id { @@ -31,6 +32,8 @@ struct psp_fw_hash_file_info { }; static struct psp_fw_hash_file_info hash_files[MAX_NUM_HASH_TABLES]; +#define UUID_MAGIC "gpd.ta.appID" + static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header) { switch (soc_id) { @@ -45,7 +48,17 @@ static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *head } } -static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id) +static void get_psp_fw_uuid(void *buf, size_t buf_len, uint8_t *uuid) +{ + void *ptr = memmem(buf, buf_len, UUID_MAGIC, strlen(UUID_MAGIC)); + + assert(ptr != NULL); + + memcpy(uuid, ptr + strlen(UUID_MAGIC), UUID_LEN_BYTES); +} + +static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id, + fwid_type_t fwid_type) { uint8_t hash[SHA384_DIGEST_LENGTH]; struct amd_fw_header *header = (struct amd_fw_header *)buf; @@ -69,7 +82,11 @@ static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc } memcpy(entry->sha, hash, entry->sha_len); - entry->fw_id = get_psp_fw_type(soc_id, header); + entry->fwid_type = fwid_type; + if (fwid_type == FWID_TYPE_UUID) + get_psp_fw_uuid(buf, header->size_total, entry->uuid); + else + entry->fw_id = get_psp_fw_type(soc_id, header); entry->subtype = header->fw_subtype; return 0; @@ -104,7 +121,7 @@ static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platfor if (num_binaries <= 0) return num_binaries; - entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash)); + entry->hash_entries = calloc(num_binaries, sizeof(amd_fw_entry_hash)); if (!entry->hash_entries) { fprintf(stderr, "Error allocating memory to add FW hash\n"); return -1; @@ -113,7 +130,8 @@ static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platfor /* Iterate through each binary */ for (int i = 0; i < num_binaries; i++) { - if (add_single_sha(&entry->hash_entries[i], buf + total_len, soc_id)) { + if (add_single_sha(&entry->hash_entries[i], buf + total_len, soc_id, + entry->fwid_type)) { free(entry->hash_entries); return -1; } @@ -124,13 +142,17 @@ static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platfor return 0; } -static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry) +static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry, + uint8_t hash_tbl_id) { - uint16_t type = entry->fw_id; uint16_t subtype = entry->subtype; - write_or_fail(fd, &type, sizeof(type)); - write_or_fail(fd, &subtype, sizeof(subtype)); + if (hash_files[hash_tbl_id].hash_header.version == HASH_HDR_V2) { + write_or_fail(fd, entry->uuid, UUID_LEN_BYTES); + } else { + write_or_fail(fd, &entry->fw_id, sizeof(entry->fw_id)); + write_or_fail(fd, &subtype, sizeof(subtype)); + } write_or_fail(fd, entry->sha, entry->sha_len); } @@ -190,12 +212,6 @@ static void write_psp_firmware_hash(amd_fw_entry *fw_table) { uint8_t hash_tbl_id; - for (unsigned int i = 0; i < MAX_NUM_HASH_TABLES; i++) { - if (!hash_files[i].present) - continue; - hash_files[i].hash_header.version = HASH_HDR_V1; - } - for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) { hash_tbl_id = fw_table[i].hash_tbl_id; assert(hash_files[hash_tbl_id].present); @@ -219,6 +235,12 @@ static void write_psp_firmware_hash(amd_fw_entry *fw_table) continue; write_or_fail(hash_files[i].fd, &hash_files[i].hash_header, sizeof(hash_files[i].hash_header)); + /* Add a reserved field as expected by version 2 header */ + if (hash_files[i].hash_header.version == HASH_HDR_V2) { + uint16_t reserved = 0; + + write_or_fail(hash_files[i].fd, &reserved, sizeof(reserved)); + } } /* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage @@ -229,7 +251,7 @@ static void write_psp_firmware_hash(amd_fw_entry *fw_table) for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) { if (fw_table[i].hash_entries[j].sha_len == SHA256_DIGEST_LENGTH) write_one_psp_firmware_hash_entry(hash_files[hash_tbl_id].fd, - &fw_table[i].hash_entries[j]); + &fw_table[i].hash_entries[j], hash_tbl_id); } } @@ -238,7 +260,7 @@ static void write_psp_firmware_hash(amd_fw_entry *fw_table) for (unsigned int j = 0; j < fw_table[i].num_hash_entries; j++) { if (fw_table[i].hash_entries[j].sha_len == SHA384_DIGEST_LENGTH) write_one_psp_firmware_hash_entry(hash_files[hash_tbl_id].fd, - &fw_table[i].hash_entries[j]); + &fw_table[i].hash_entries[j], hash_tbl_id); } } @@ -252,6 +274,15 @@ static void write_psp_firmware_hash(amd_fw_entry *fw_table) } } +static void update_hash_files_config(amd_fw_entry *fw_table) +{ + uint16_t version = fw_table->fwid_type == FWID_TYPE_UUID ? HASH_HDR_V2 : HASH_HDR_V1; + + hash_files[fw_table->hash_tbl_id].present = true; + if (version > hash_files[fw_table->hash_tbl_id].hash_header.version) + hash_files[fw_table->hash_tbl_id].hash_header.version = version; +} + /** * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate * @signed_rom: Output file path grouping all the signed PSP binaries. @@ -386,7 +417,7 @@ void process_signed_psp_firmwares(const char *signed_rom, /* File is successfully processed and is part of signed PSP binaries set. */ 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; + update_hash_files_config(&fw_table[i]); signed_start_addr += fd_stat.st_size + align_bytes; |