amdfwtool: Move some funtions to other categorized source files

To reduce the size of amdfwtool.c which is already too big.

Change-Id: Ib80eeb42f59a3dda04402b2feaadc1d178ed989e
Signed-off-by: Zheng Bao <fishbaozi@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/73910
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Fred Reitberger <reitbergerfred@gmail.com>
diff --git a/util/amdfwtool/Makefile b/util/amdfwtool/Makefile
index 53dce4c..8ec4e9b 100644
--- a/util/amdfwtool/Makefile
+++ b/util/amdfwtool/Makefile
@@ -9,7 +9,7 @@
 
 READ_SRC = amdfwread.c
 READ_OBJ = $(READ_SRC:%.c=%.o)
-TOOL_SRC = amdfwtool.c data_parse.c
+TOOL_SRC = amdfwtool.c data_parse.c signed_psp.c handle_file.c
 TOOL_OBJ = $(TOOL_SRC:%.c=%.o)
 HEADER=amdfwtool.h
 TARGETS = amdfwread amdfwtool
diff --git a/util/amdfwtool/Makefile.inc b/util/amdfwtool/Makefile.inc
index b9c3ced..7d96155 100644
--- a/util/amdfwtool/Makefile.inc
+++ b/util/amdfwtool/Makefile.inc
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: BSD-3-Clause
 
-amdfwtoolobj = amdfwtool.o data_parse.o
+amdfwtoolobj = amdfwtool.o data_parse.o signed_psp.o handle_file.o
 amdfwreadobj = amdfwread.o
 
 AMDFWTOOLCFLAGS=-O2 -Wall -Wextra -Wshadow -Werror
diff --git a/util/amdfwtool/amdfwtool.c b/util/amdfwtool/amdfwtool.c
index 9312be6..8190b8d 100644
--- a/util/amdfwtool/amdfwtool.c
+++ b/util/amdfwtool/amdfwtool.c
@@ -73,7 +73,6 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <limits.h>
-#include <openssl/sha.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <sys/stat.h>
@@ -91,24 +90,9 @@
 #define MIN_ROM_KB		256
 
 #define _MAX(A, B) (((A) > (B)) ? (A) : (B))
-#define ERASE_ALIGNMENT 0x1000U
-#define TABLE_ALIGNMENT 0x1000U
-#define BLOB_ALIGNMENT 0x100U
-#define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
-#define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
 
 #define DEFAULT_SOFT_FUSE_CHAIN "0x1"
 
-/* Defines related to hashing signed binaries */
-enum hash_header_ver {
-	HASH_HDR_V1 = 1,
-};
-/* Signature ID enums are defined by PSP based on the algorithm used. */
-enum signature_id {
-	SIG_ID_RSA2048,
-	SIG_ID_RSA4096 = 2,
-};
-#define HASH_FILE_SUFFIX ".hash"
 #define EFS_FILE_SUFFIX ".efs"
 #define TMP_FILE_SUFFIX ".tmp"
 #define BODY_FILE_SUFFIX ".body"
@@ -776,66 +760,6 @@
 	return bytes;
 }
 
-static ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
-{
-	ssize_t bytes;
-	size_t total_bytes = 0;
-
-	do {
-		bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
-		if (bytes == 0) {
-			fprintf(stderr, "Reached EOF probably\n");
-			break;
-		}
-
-		if (bytes < 0 && errno == EAGAIN)
-			bytes = 0;
-
-		if (bytes < 0) {
-			fprintf(stderr, "Read failure %s\n", strerror(errno));
-			return bytes;
-		}
-
-		total_bytes += bytes;
-	} while (total_bytes < buf_size);
-
-	if (total_bytes != buf_size) {
-		fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
-								total_bytes, buf_size);
-		return -1;
-	}
-	return buf_size;
-}
-
-static ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
-{
-	ssize_t bytes;
-	size_t total_bytes = 0;
-
-	do {
-		bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
-		if (bytes < 0 && errno == EAGAIN)
-			bytes = 0;
-
-		if (bytes < 0) {
-			fprintf(stderr, "Write failure %s\n", strerror(errno));
-			lseek(fd, SEEK_CUR, -total_bytes);
-			return bytes;
-		}
-
-		total_bytes += bytes;
-	} while (total_bytes < buf_size);
-
-	if (total_bytes != buf_size) {
-		fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
-								total_bytes, buf_size);
-		lseek(fd, SEEK_CUR, -total_bytes);
-		return -1;
-	}
-
-	return buf_size;
-}
-
 static uint32_t get_psp_id(enum platform soc_id)
 {
 	uint32_t psp_id;
@@ -871,99 +795,6 @@
 	return psp_id;
 }
 
-static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header)
-{
-	switch (soc_id) {
-	case PLATFORM_MENDOCINO:
-	case PLATFORM_PHOENIX:
-	case PLATFORM_GLINDA:
-		/* Fallback to fw_type if fw_id is not populated, which serves the same
-		   purpose on older SoCs. */
-		return header->fw_id ? header->fw_id : header->fw_type;
-	default:
-		return header->fw_type;
-	}
-}
-
-static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id)
-{
-	uint8_t hash[SHA384_DIGEST_LENGTH];
-	struct amd_fw_header *header = (struct amd_fw_header *)buf;
-	/* Include only signed part for hash calculation. */
-	size_t len = header->fw_size_signed + sizeof(struct amd_fw_header);
-	uint8_t *body = (uint8_t *)buf;
-
-	if (len > header->size_total)
-		return -1;
-
-	if (header->sig_id == SIG_ID_RSA4096) {
-		SHA384(body, len, hash);
-		entry->sha_len = SHA384_DIGEST_LENGTH;
-	} else if (header->sig_id == SIG_ID_RSA2048) {
-		SHA256(body, len, hash);
-		entry->sha_len = SHA256_DIGEST_LENGTH;
-	} else {
-		fprintf(stderr, "%s: Unknown signature id: 0x%08x\n",
-						__func__, header->sig_id);
-		return -1;
-	}
-
-	memcpy(entry->sha, hash, entry->sha_len);
-	entry->fw_id = get_psp_fw_type(soc_id, header);
-	entry->subtype = header->fw_subtype;
-
-	return 0;
-}
-
-static int get_num_binaries(void *buf, size_t buf_size)
-{
-	struct amd_fw_header *header = (struct amd_fw_header *)buf;
-	size_t total_len = 0;
-	int num_binaries = 0;
-
-	while (total_len < buf_size) {
-		num_binaries++;
-		total_len += header->size_total;
-		header = (struct amd_fw_header *)(buf + total_len);
-	}
-
-	if (total_len != buf_size) {
-		fprintf(stderr, "Malformed binary\n");
-		return -1;
-	}
-	return num_binaries;
-}
-
-static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platform soc_id)
-{
-	struct amd_fw_header *header = (struct amd_fw_header *)buf;
-	/* Include only signed part for hash calculation. */
-	size_t total_len = 0;
-	int num_binaries = get_num_binaries(buf, buf_size);
-
-	if (num_binaries <= 0)
-		return num_binaries;
-
-	entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash));
-	if (!entry->hash_entries) {
-		fprintf(stderr, "Error allocating memory to add FW hash\n");
-		return -1;
-	}
-	entry->num_hash_entries = num_binaries;
-
-	/* 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)) {
-			free(entry->hash_entries);
-			return -1;
-		}
-		total_len += header->size_total;
-		header = (struct amd_fw_header *)(buf + total_len);
-	}
-
-	return 0;
-}
-
 static void integrate_firmwares(context *ctx,
 				embedded_firmware *romsig,
 				amd_fw_entry *fw_table)
@@ -1026,247 +857,6 @@
 	}
 }
 
-static void write_or_fail(int fd, void *ptr, size_t size)
-{
-	ssize_t written;
-
-	written = write_from_buf_to_file(fd, ptr, size);
-	if (written < 0 || (size_t)written != size) {
-		fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
-								__func__, size, written);
-		exit(-1);
-	}
-}
-
-static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry)
-{
-	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));
-	write_or_fail(fd, entry->sha, entry->sha_len);
-}
-
-static void write_psp_firmware_hash(const char *filename,
-		amd_fw_entry *fw_table)
-{
-	struct psp_fw_hash_table hash_header = {0};
-	int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
-
-	if (fd < 0) {
-		fprintf(stderr, "Error opening file: %s: %s\n",
-				filename, strerror(errno));
-		exit(-1);
-	}
-
-	hash_header.version = HASH_HDR_V1;
-	for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
-		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) {
-				hash_header.no_of_entries_256++;
-			} else if (fw_table[i].hash_entries[j].sha_len ==
-								SHA384_DIGEST_LENGTH) {
-				hash_header.no_of_entries_384++;
-			} else if (fw_table[i].hash_entries[j].sha_len) {
-				fprintf(stderr, "%s: Error invalid sha_len %d\n",
-						__func__, fw_table[i].hash_entries[j].sha_len);
-				exit(-1);
-			}
-		}
-	}
-
-	write_or_fail(fd, &hash_header, sizeof(hash_header));
-
-	/* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage
-	   processes the table in that order. Mixing and matching SHA256 and SHA384 entries
-	   will cause the hash verification failure at run-time. */
-	for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
-		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(fd,
-						&fw_table[i].hash_entries[j]);
-		}
-	}
-
-	for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
-		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(fd,
-						&fw_table[i].hash_entries[j]);
-		}
-	}
-
-	close(fd);
-	for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
-		if (!fw_table[i].num_hash_entries || !fw_table[i].hash_entries)
-			continue;
-
-		free(fw_table[i].hash_entries);
-		fw_table[i].hash_entries = NULL;
-		fw_table[i].num_hash_entries = 0;
-	}
-}
-
-/**
- * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate
- * @signed_rom:	Output file path grouping all the signed PSP binaries.
- * @fw_table:	Table of all the PSP firmware entries/binaries to be processed.
- * @signed_start_addr:	Offset of the FMAP section, within the flash device, to hold
- *                      the signed PSP binaries.
- * @soc_id:	SoC ID of the PSP binaries.
- */
-static void process_signed_psp_firmwares(const char *signed_rom,
-		amd_fw_entry *fw_table,
-		uint64_t signed_start_addr,
-		enum platform soc_id)
-{
-	unsigned int i;
-	int fd;
-	int signed_rom_fd;
-	ssize_t bytes, align_bytes;
-	uint8_t *buf;
-	char *signed_rom_hash;
-	size_t signed_rom_hash_strlen;
-	struct amd_fw_header header;
-	struct stat fd_stat;
-	/* Every blob in amdfw*.rom has to start at address aligned to 0x100. Prepare an
-	   alignment data with 0xff to pad the blobs and meet the alignment requirement. */
-	uint8_t align_data[BLOB_ALIGNMENT - 1];
-
-	memset(align_data, 0xff, sizeof(align_data));
-	signed_rom_fd = open(signed_rom, O_RDWR | O_CREAT | O_TRUNC,
-				S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
-	if (signed_rom_fd < 0) {
-		fprintf(stderr, "Error opening file: %s: %s\n",
-				signed_rom, strerror(errno));
-		return;
-	}
-
-	for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
-		fw_table[i].num_hash_entries = 0;
-		fw_table[i].hash_entries = NULL;
-
-		if (!(fw_table[i].filename) || fw_table[i].skip_hashing)
-			continue;
-
-		memset(&header, 0, sizeof(header));
-
-		fd = open(fw_table[i].filename, O_RDONLY);
-		if (fd < 0) {
-			/* Keep the file along with set of unsigned PSP binaries & continue. */
-			fprintf(stderr, "Error opening file: %s: %s\n",
-					fw_table[i].filename, strerror(errno));
-			continue;
-		}
-
-		if (fstat(fd, &fd_stat)) {
-			/* Keep the file along with set of unsigned PSP binaries & continue. */
-			fprintf(stderr, "fstat error: %s\n", strerror(errno));
-			close(fd);
-			continue;
-		}
-
-		bytes = read_from_file_to_buf(fd, &header, sizeof(struct amd_fw_header));
-		if (bytes != (ssize_t)sizeof(struct amd_fw_header)) {
-			/* Keep the file along with set of unsigned PSP binaries & continue. */
-			fprintf(stderr, "%s: Error reading header from %s\n",
-						__func__, fw_table[i].filename);
-			close(fd);
-			continue;
-		}
-
-		/* If firmware header looks like invalid, assume it's not signed */
-		if (!header.fw_type && !header.fw_id) {
-			fprintf(stderr, "%s: Invalid FWID for %s\n",
-					__func__, fw_table[i].filename);
-			close(fd);
-			continue;
-		}
-
-
-		/* PSP binary is not signed and should not be part of signed PSP binaries
-		   set. */
-		if (header.sig_opt != 1) {
-			close(fd);
-			continue;
-		}
-
-		buf = malloc(fd_stat.st_size);
-		if (!buf) {
-			/* Keep the file along with set of unsigned PSP binaries & continue. */
-			fprintf(stderr, "%s: failed to allocate memory with size %lld\n",
-							__func__, (long long)fd_stat.st_size);
-			close(fd);
-			continue;
-		}
-
-		lseek(fd, SEEK_SET, 0);
-		bytes = read_from_file_to_buf(fd, buf, fd_stat.st_size);
-		if (bytes != fd_stat.st_size) {
-			/* Keep the file along with set of unsigned PSP binaries & continue. */
-			fprintf(stderr, "%s: failed to read %s\n",
-					__func__, fw_table[i].filename);
-			free(buf);
-			close(fd);
-			continue;
-		}
-
-		bytes = write_from_buf_to_file(signed_rom_fd, buf, fd_stat.st_size);
-		if (bytes != fd_stat.st_size) {
-			/* Keep the file along with set of unsigned PSP binaries & continue. */
-			fprintf(stderr, "%s: failed to write %s\n",
-					__func__, fw_table[i].filename);
-			free(buf);
-			close(fd);
-			continue;
-		}
-
-		/* Write Blob alignment bytes */
-		align_bytes = 0;
-		if (fd_stat.st_size & (BLOB_ALIGNMENT - 1)) {
-			align_bytes = BLOB_ALIGNMENT -
-				(fd_stat.st_size & (BLOB_ALIGNMENT - 1));
-			bytes = write_from_buf_to_file(signed_rom_fd, align_data, align_bytes);
-			if (bytes != align_bytes) {
-				fprintf(stderr, "%s: failed to write alignment data for %s\n",
-								__func__, fw_table[i].filename);
-				lseek(signed_rom_fd, SEEK_CUR, -fd_stat.st_size);
-				free(buf);
-				close(fd);
-				continue;
-			}
-		}
-
-		if (add_sha(&fw_table[i], buf, fd_stat.st_size, soc_id))
-			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;
-
-		signed_start_addr += fd_stat.st_size + align_bytes;
-
-		free(buf);
-		close(fd);
-	}
-
-	close(signed_rom_fd);
-
-	/* signed_rom file name + ".hash" + '\0' */
-	signed_rom_hash_strlen = strlen(signed_rom) + strlen(HASH_FILE_SUFFIX) + 1;
-	signed_rom_hash = malloc(signed_rom_hash_strlen);
-	if (!signed_rom_hash) {
-		fprintf(stderr, "malloc(%lu) failed\n", signed_rom_hash_strlen);
-		exit(-1);
-	}
-	strcpy(signed_rom_hash, signed_rom);
-	strcat(signed_rom_hash, HASH_FILE_SUFFIX);
-	write_psp_firmware_hash(signed_rom_hash, fw_table);
-	free(signed_rom_hash);
-}
-
 static void integrate_psp_ab(context *ctx, psp_directory_table *pspdir,
 		psp_directory_table *pspdir2, ish_directory_table *ish,
 		amd_fw_type ab, enum platform soc_id)
diff --git a/util/amdfwtool/amdfwtool.h b/util/amdfwtool/amdfwtool.h
index 5d6047c..03cc056 100644
--- a/util/amdfwtool/amdfwtool.h
+++ b/util/amdfwtool/amdfwtool.h
@@ -9,6 +9,12 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#define ERASE_ALIGNMENT 0x1000U
+#define TABLE_ALIGNMENT 0x1000U
+#define BLOB_ALIGNMENT 0x100U
+#define TABLE_ERASE_ALIGNMENT _MAX(TABLE_ALIGNMENT, ERASE_ALIGNMENT)
+#define BLOB_ERASE_ALIGNMENT _MAX(BLOB_ALIGNMENT, ERASE_ALIGNMENT)
+
 enum platform {
 	PLATFORM_UNKNOWN,
 	PLATFORM_CARRIZO,
@@ -408,7 +414,13 @@
 
 void register_fw_fuse(char *str);
 uint8_t process_config(FILE *config, amd_cb_config *cb_config);
-
+void process_signed_psp_firmwares(const char *signed_rom,
+		amd_fw_entry *fw_table,
+		uint64_t signed_start_addr,
+		enum platform soc_id);
+void write_or_fail(int fd, void *ptr, size_t size);
+ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size);
+ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size);
 #define OK 0
 
 #define LINE_EOF (1)
diff --git a/util/amdfwtool/handle_file.c b/util/amdfwtool/handle_file.c
new file mode 100644
index 0000000..884f1ba
--- /dev/null
+++ b/util/amdfwtool/handle_file.c
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "amdfwtool.h"
+
+void write_or_fail(int fd, void *ptr, size_t size)
+{
+	ssize_t written;
+
+	written = write_from_buf_to_file(fd, ptr, size);
+	if (written < 0 || (size_t)written != size) {
+		fprintf(stderr, "%s: Error writing %zu bytes - written %zd bytes\n",
+								__func__, size, written);
+		exit(-1);
+	}
+}
+
+ssize_t read_from_file_to_buf(int fd, void *buf, size_t buf_size)
+{
+	ssize_t bytes;
+	size_t total_bytes = 0;
+
+	do {
+		bytes = read(fd, buf + total_bytes, buf_size - total_bytes);
+		if (bytes == 0) {
+			fprintf(stderr, "Reached EOF probably\n");
+			break;
+		}
+
+		if (bytes < 0 && errno == EAGAIN)
+			bytes = 0;
+
+		if (bytes < 0) {
+			fprintf(stderr, "Read failure %s\n", strerror(errno));
+			return bytes;
+		}
+
+		total_bytes += bytes;
+	} while (total_bytes < buf_size);
+
+	if (total_bytes != buf_size) {
+		fprintf(stderr, "Read data size(%zu) != buffer size(%zu)\n",
+								total_bytes, buf_size);
+		return -1;
+	}
+	return buf_size;
+}
+
+ssize_t write_from_buf_to_file(int fd, const void *buf, size_t buf_size)
+{
+	ssize_t bytes;
+	size_t total_bytes = 0;
+
+	do {
+		bytes = write(fd, buf + total_bytes, buf_size - total_bytes);
+		if (bytes < 0 && errno == EAGAIN)
+			bytes = 0;
+
+		if (bytes < 0) {
+			fprintf(stderr, "Write failure %s\n", strerror(errno));
+			lseek(fd, SEEK_CUR, -total_bytes);
+			return bytes;
+		}
+
+		total_bytes += bytes;
+	} while (total_bytes < buf_size);
+
+	if (total_bytes != buf_size) {
+		fprintf(stderr, "Wrote more data(%zu) than buffer size(%zu)\n",
+								total_bytes, buf_size);
+		lseek(fd, SEEK_CUR, -total_bytes);
+		return -1;
+	}
+
+	return buf_size;
+}
diff --git a/util/amdfwtool/signed_psp.c b/util/amdfwtool/signed_psp.c
new file mode 100644
index 0000000..644e904
--- /dev/null
+++ b/util/amdfwtool/signed_psp.c
@@ -0,0 +1,346 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <openssl/sha.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "amdfwtool.h"
+
+/* Defines related to hashing signed binaries */
+enum hash_header_ver {
+	HASH_HDR_V1 = 1,
+};
+/* Signature ID enums are defined by PSP based on the algorithm used. */
+enum signature_id {
+	SIG_ID_RSA2048,
+	SIG_ID_RSA4096 = 2,
+};
+#define HASH_FILE_SUFFIX ".hash"
+
+static uint16_t get_psp_fw_type(enum platform soc_id, struct amd_fw_header *header)
+{
+	switch (soc_id) {
+	case PLATFORM_MENDOCINO:
+	case PLATFORM_PHOENIX:
+	case PLATFORM_GLINDA:
+		/* Fallback to fw_type if fw_id is not populated, which serves the same
+		   purpose on older SoCs. */
+		return header->fw_id ? header->fw_id : header->fw_type;
+	default:
+		return header->fw_type;
+	}
+}
+
+static int add_single_sha(amd_fw_entry_hash *entry, void *buf, enum platform soc_id)
+{
+	uint8_t hash[SHA384_DIGEST_LENGTH];
+	struct amd_fw_header *header = (struct amd_fw_header *)buf;
+	/* Include only signed part for hash calculation. */
+	size_t len = header->fw_size_signed + sizeof(struct amd_fw_header);
+	uint8_t *body = (uint8_t *)buf;
+
+	if (len > header->size_total)
+		return -1;
+
+	if (header->sig_id == SIG_ID_RSA4096) {
+		SHA384(body, len, hash);
+		entry->sha_len = SHA384_DIGEST_LENGTH;
+	} else if (header->sig_id == SIG_ID_RSA2048) {
+		SHA256(body, len, hash);
+		entry->sha_len = SHA256_DIGEST_LENGTH;
+	} else {
+		fprintf(stderr, "%s: Unknown signature id: 0x%08x\n",
+						__func__, header->sig_id);
+		return -1;
+	}
+
+	memcpy(entry->sha, hash, entry->sha_len);
+	entry->fw_id = get_psp_fw_type(soc_id, header);
+	entry->subtype = header->fw_subtype;
+
+	return 0;
+}
+
+static int get_num_binaries(void *buf, size_t buf_size)
+{
+	struct amd_fw_header *header = (struct amd_fw_header *)buf;
+	size_t total_len = 0;
+	int num_binaries = 0;
+
+	while (total_len < buf_size) {
+		num_binaries++;
+		total_len += header->size_total;
+		header = (struct amd_fw_header *)(buf + total_len);
+	}
+
+	if (total_len != buf_size) {
+		fprintf(stderr, "Malformed binary\n");
+		return -1;
+	}
+	return num_binaries;
+}
+
+static int add_sha(amd_fw_entry *entry, void *buf, size_t buf_size, enum platform soc_id)
+{
+	struct amd_fw_header *header = (struct amd_fw_header *)buf;
+	/* Include only signed part for hash calculation. */
+	size_t total_len = 0;
+	int num_binaries = get_num_binaries(buf, buf_size);
+
+	if (num_binaries <= 0)
+		return num_binaries;
+
+	entry->hash_entries = malloc(num_binaries * sizeof(amd_fw_entry_hash));
+	if (!entry->hash_entries) {
+		fprintf(stderr, "Error allocating memory to add FW hash\n");
+		return -1;
+	}
+	entry->num_hash_entries = num_binaries;
+
+	/* 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)) {
+			free(entry->hash_entries);
+			return -1;
+		}
+		total_len += header->size_total;
+		header = (struct amd_fw_header *)(buf + total_len);
+	}
+
+	return 0;
+}
+
+static void write_one_psp_firmware_hash_entry(int fd, amd_fw_entry_hash *entry)
+{
+	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));
+	write_or_fail(fd, entry->sha, entry->sha_len);
+}
+
+static void write_psp_firmware_hash(const char *filename,
+		amd_fw_entry *fw_table)
+{
+	struct psp_fw_hash_table hash_header = {0};
+	int fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666);
+
+	if (fd < 0) {
+		fprintf(stderr, "Error opening file: %s: %s\n",
+				filename, strerror(errno));
+		exit(-1);
+	}
+
+	hash_header.version = HASH_HDR_V1;
+	for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
+		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) {
+				hash_header.no_of_entries_256++;
+			} else if (fw_table[i].hash_entries[j].sha_len ==
+								SHA384_DIGEST_LENGTH) {
+				hash_header.no_of_entries_384++;
+			} else if (fw_table[i].hash_entries[j].sha_len) {
+				fprintf(stderr, "%s: Error invalid sha_len %d\n",
+						__func__, fw_table[i].hash_entries[j].sha_len);
+				exit(-1);
+			}
+		}
+	}
+
+	write_or_fail(fd, &hash_header, sizeof(hash_header));
+
+	/* Add all the SHA256 hash entries first followed by SHA384 entries. PSP verstage
+	   processes the table in that order. Mixing and matching SHA256 and SHA384 entries
+	   will cause the hash verification failure at run-time. */
+	for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
+		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(fd,
+						&fw_table[i].hash_entries[j]);
+		}
+	}
+
+	for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
+		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(fd,
+						&fw_table[i].hash_entries[j]);
+		}
+	}
+
+	close(fd);
+	for (unsigned int i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
+		if (!fw_table[i].num_hash_entries || !fw_table[i].hash_entries)
+			continue;
+
+		free(fw_table[i].hash_entries);
+		fw_table[i].hash_entries = NULL;
+		fw_table[i].num_hash_entries = 0;
+	}
+}
+
+/**
+ * process_signed_psp_firmwares() - Process the signed PSP binaries to keep them separate
+ * @signed_rom:	Output file path grouping all the signed PSP binaries.
+ * @fw_table:	Table of all the PSP firmware entries/binaries to be processed.
+ * @signed_start_addr:	Offset of the FMAP section, within the flash device, to hold
+ *                      the signed PSP binaries.
+ * @soc_id:	SoC ID of the PSP binaries.
+ */
+void process_signed_psp_firmwares(const char *signed_rom,
+		amd_fw_entry *fw_table,
+		uint64_t signed_start_addr,
+		enum platform soc_id)
+{
+	unsigned int i;
+	int fd;
+	int signed_rom_fd;
+	ssize_t bytes, align_bytes;
+	uint8_t *buf;
+	char *signed_rom_hash;
+	size_t signed_rom_hash_strlen;
+	struct amd_fw_header header;
+	struct stat fd_stat;
+	/* Every blob in amdfw*.rom has to start at address aligned to 0x100. Prepare an
+	   alignment data with 0xff to pad the blobs and meet the alignment requirement. */
+	uint8_t align_data[BLOB_ALIGNMENT - 1];
+
+	memset(align_data, 0xff, sizeof(align_data));
+	signed_rom_fd = open(signed_rom, O_RDWR | O_CREAT | O_TRUNC,
+				S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+	if (signed_rom_fd < 0) {
+		fprintf(stderr, "Error opening file: %s: %s\n",
+				signed_rom, strerror(errno));
+		return;
+	}
+
+	for (i = 0; fw_table[i].type != AMD_FW_INVALID; i++) {
+		fw_table[i].num_hash_entries = 0;
+		fw_table[i].hash_entries = NULL;
+
+		if (!(fw_table[i].filename) || fw_table[i].skip_hashing)
+			continue;
+
+		memset(&header, 0, sizeof(header));
+
+		fd = open(fw_table[i].filename, O_RDONLY);
+		if (fd < 0) {
+			/* Keep the file along with set of unsigned PSP binaries & continue. */
+			fprintf(stderr, "Error opening file: %s: %s\n",
+					fw_table[i].filename, strerror(errno));
+			continue;
+		}
+
+		if (fstat(fd, &fd_stat)) {
+			/* Keep the file along with set of unsigned PSP binaries & continue. */
+			fprintf(stderr, "fstat error: %s\n", strerror(errno));
+			close(fd);
+			continue;
+		}
+
+		bytes = read_from_file_to_buf(fd, &header, sizeof(struct amd_fw_header));
+		if (bytes != (ssize_t)sizeof(struct amd_fw_header)) {
+			/* Keep the file along with set of unsigned PSP binaries & continue. */
+			fprintf(stderr, "%s: Error reading header from %s\n",
+						__func__, fw_table[i].filename);
+			close(fd);
+			continue;
+		}
+
+		/* If firmware header looks like invalid, assume it's not signed */
+		if (!header.fw_type && !header.fw_id) {
+			fprintf(stderr, "%s: Invalid FWID for %s\n",
+					__func__, fw_table[i].filename);
+			close(fd);
+			continue;
+		}
+
+
+		/* PSP binary is not signed and should not be part of signed PSP binaries
+		   set. */
+		if (header.sig_opt != 1) {
+			close(fd);
+			continue;
+		}
+
+		buf = malloc(fd_stat.st_size);
+		if (!buf) {
+			/* Keep the file along with set of unsigned PSP binaries & continue. */
+			fprintf(stderr, "%s: failed to allocate memory with size %lld\n",
+							__func__, (long long)fd_stat.st_size);
+			close(fd);
+			continue;
+		}
+
+		lseek(fd, SEEK_SET, 0);
+		bytes = read_from_file_to_buf(fd, buf, fd_stat.st_size);
+		if (bytes != fd_stat.st_size) {
+			/* Keep the file along with set of unsigned PSP binaries & continue. */
+			fprintf(stderr, "%s: failed to read %s\n",
+					__func__, fw_table[i].filename);
+			free(buf);
+			close(fd);
+			continue;
+		}
+
+		bytes = write_from_buf_to_file(signed_rom_fd, buf, fd_stat.st_size);
+		if (bytes != fd_stat.st_size) {
+			/* Keep the file along with set of unsigned PSP binaries & continue. */
+			fprintf(stderr, "%s: failed to write %s\n",
+					__func__, fw_table[i].filename);
+			free(buf);
+			close(fd);
+			continue;
+		}
+
+		/* Write Blob alignment bytes */
+		align_bytes = 0;
+		if (fd_stat.st_size & (BLOB_ALIGNMENT - 1)) {
+			align_bytes = BLOB_ALIGNMENT -
+				(fd_stat.st_size & (BLOB_ALIGNMENT - 1));
+			bytes = write_from_buf_to_file(signed_rom_fd, align_data, align_bytes);
+			if (bytes != align_bytes) {
+				fprintf(stderr, "%s: failed to write alignment data for %s\n",
+								__func__, fw_table[i].filename);
+				lseek(signed_rom_fd, SEEK_CUR, -fd_stat.st_size);
+				free(buf);
+				close(fd);
+				continue;
+			}
+		}
+
+		if (add_sha(&fw_table[i], buf, fd_stat.st_size, soc_id))
+			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;
+
+		signed_start_addr += fd_stat.st_size + align_bytes;
+
+		free(buf);
+		close(fd);
+	}
+
+	close(signed_rom_fd);
+
+	/* signed_rom file name + ".hash" + '\0' */
+	signed_rom_hash_strlen = strlen(signed_rom) + strlen(HASH_FILE_SUFFIX) + 1;
+	signed_rom_hash = malloc(signed_rom_hash_strlen);
+	if (!signed_rom_hash) {
+		fprintf(stderr, "malloc(%lu) failed\n", signed_rom_hash_strlen);
+		exit(-1);
+	}
+	strcpy(signed_rom_hash, signed_rom);
+	strcat(signed_rom_hash, HASH_FILE_SUFFIX);
+	write_psp_firmware_hash(signed_rom_hash, fw_table);
+	free(signed_rom_hash);
+}