[coreboot-gerrit] Patch set updated for coreboot: amdfwtool: Add amdfwtool to combine AMD firmware

Zheng Bao (zheng.bao@amd.com) gerrit at coreboot.org
Fri Nov 13 18:08:22 CET 2015


Zheng Bao (zheng.bao at amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/12419

-gerrit

commit 018b9604ee36b64f2d604c020202fc7f46bf3ce7
Author: Zheng Bao <fishbaozi at gmail.com>
Date:   Fri Nov 13 04:27:12 2015 +0800

    amdfwtool: Add amdfwtool to combine AMD firmware
    
    Combine all needed AMD firmware into one single firmware, which going to
    be added as one single CBFS module.
    
    Change-Id: Ib044098c1837592b8f7e9c6a7da4ba3a32117e25
    Signed-off-by: Zheng Bao <fishbaozi at gmail.com>
---
 util/amdfwtool/Makefile    |  69 +++++++++
 util/amdfwtool/amdfwtool.c | 366 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 435 insertions(+)

diff --git a/util/amdfwtool/Makefile b/util/amdfwtool/Makefile
new file mode 100644
index 0000000..db802b2
--- /dev/null
+++ b/util/amdfwtool/Makefile
@@ -0,0 +1,69 @@
+#*****************************************************************************
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#     * Redistributions of source code must retain the above copyright
+#       notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above copyright
+#       notice, this list of conditions and the following disclaimer in the
+#       documentation and/or other materials provided with the distribution.
+#     * Neither the name of Advanced Micro Devices, Inc. nor the names of
+#       its contributors may be used to endorse or promote products derived
+#       from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#*****************************************************************************
+HOSTCC ?= cc
+
+amdfwtool_exe : amdfwtool.c
+	$(HOSTCC) amdfwtool.c -o amdfwtool
+
+amdfwtool : amdfwtool_exe
+
+clean:
+	@rm -f amdfwtool.o amdfwtool amdfwtool.exe
+
+#$(obj)/amdfw.rom:	$(call strip_quotes, $(CONFIG_HUDSON_XHCI_FWM_FILE)) \
+#			$(call strip_quotes, $(CONFIG_HUDSON_IMC_FWM_FILE)) \
+#			$(call strip_quotes, $(CONFIG_HUDSON_GEC_FWM_FILE)) \
+#			$(call strip_quotes, $(CONFIG_AMDPUBKEY_FILE)) \
+#			$(call strip_quotes, $(CONFIG_PUBSIGNEDKEY_FILE)) \
+#			$(call strip_quotes, $(CONFIG_PSPBTLDR_FILE)) \
+#			$(call strip_quotes, $(CONFIG_PSPRCVR_FILE)) \
+#			$(call strip_quotes, $(CONFIG_PSPSCUREOS_FILE)) \
+#			$(call strip_quotes, $(CONFIG_PSPNVRAM_FILE)) \
+#			$(call strip_quotes, $(CONFIG_SMUFWM_FILE)) \
+#			$(call strip_quotes, $(CONFIG_SMUSCS_FILE)) \
+#			$(call strip_quotes, $(CONFIG_PSPSECUREDEBUG_FILE)) \
+#			$(call strip_quotes, $(CONFIG_PSPTRUSTLETS_FILE)) \
+#			$(call strip_quotes, $(CONFIG_TRUSTLETKEY_FILE)) \
+#			$(call strip_quotes, $(CONFIG_SMUFIRMWARE2_FILE)) \
+#			$(AMDFWTOOL)
+#	$(AMDFWTOOL) \
+#		--xhci		$(call strip_quotes, $(CONFIG_HUDSON_XHCI_FWM_FILE))         \
+#		--imc		$(call strip_quotes, $(CONFIG_HUDSON_IMC_FWM_FILE))          \
+#		--pubkey	$(call strip_quotes, $(CONFIG_AMDPUBKEY_FILE)) \
+#		--bootloader	$(call strip_quotes, $(CONFIG_PSPBTLDR_FILE)) \
+#		--smufirmware	$(call strip_quotes, $(CONFIG_SMUFWM_FILE)) \
+#		--recovery	$(call strip_quotes, $(CONFIG_PSPRCVR_FILE)) \
+#		--rtmpubkey	$(call strip_quotes, $(CONFIG_PUBSIGNEDKEY_FILE)) \
+#		--secureos	$(call strip_quotes, $(CONFIG_PSPSCUREOS_FILE)) \
+#		--nvram		$(call strip_quotes, $(CONFIG_PSPNVRAM_FILE)) \
+#		--securedebug	$(call strip_quotes, $(CONFIG_PSPSECUREDEBUG_FILE)) \
+#		--trustlets	$(call strip_quotes, $(CONFIG_PSPTRUSTLETS_FILE)) \
+#		--trustletkey	$(call strip_quotes, $(CONFIG_TRUSTLETKEY_FILE)) \
+#		--smufirmware2	$(call strip_quotes, $(CONFIG_SMUFIRMWARE2_FILE)) \
+#		--smuscs	$(call strip_quotes, $(CONFIG_SMUSCS_FILE)) \
+#		--output	$@
diff --git a/util/amdfwtool/amdfwtool.c b/util/amdfwtool/amdfwtool.c
new file mode 100644
index 0000000..3a068e0
--- /dev/null
+++ b/util/amdfwtool/amdfwtool.c
@@ -0,0 +1,366 @@
+/*
+ * All Rights Reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code
+ * distributions retain the above copyright notice and this paragraph
+ * in its entirety, and (2) distributions including binary code include
+ * the above copyright notice and this paragraph in its entirety in
+ * the documentation or other materials provided with the distribution.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
+ * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
+ * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+
+#ifndef CONFIG_ROM_SIZE
+#define CONFIG_ROM_SIZE 0x400000
+#endif
+
+#define ROM_BASE_ADDRESS  (0xFFFFFFFF - CONFIG_ROM_SIZE + 1)
+#define AMD_ROMSIG_OFFSET 0x20000
+
+#define ALIGN(val, by) (((val) + (by)-1)&~((by)-1))
+
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+
+/*
+ * Creates the OSI Fletcher checksum. See 8473-1, Appendix C, section C.3.
+ * The checksum field of the passed PDU does not need to be reset to zero.
+ *
+ * The "Fletcher Checksum" was proposed in a paper by John G. Fletcher of
+ * Lawrence Livermore Labs.  The Fletcher Checksum was proposed as an
+ * alternative to cyclical redundancy checks because it provides error-
+ * detection properties similar to cyclical redundancy checks but at the
+ * cost of a simple summation technique.  Its characteristics were first
+ * published in IEEE Transactions on Communications in January 1982.  One
+ * version has been adopted by ISO for use in the class-4 transport layer
+ * of the network protocol.
+ *
+ * This program expects:
+ *    stdin:    The input file to compute a checksum for.  The input file
+ *              not be longer than 256 bytes.
+ *    stdout:   Copied from the input file with the Fletcher's Checksum
+ *              inserted 8 bytes after the beginning of the file.
+ *    stderr:   Used to print out error messages.
+ */
+
+uint32_t fletcher32 (const uint16_t *pptr, int length)
+{
+
+	uint32_t c0;
+	uint32_t c1;
+	uint32_t checksum;
+	int index;
+
+	c0 = 0xFFFF;
+	c1 = 0xFFFF;
+
+	for (index = 0; index < length; index++) {
+		/*
+		* Ignore the contents of the checksum field.
+		*/
+		c0 += *(pptr++);
+		c1 += c0;
+		if ((index % 360) == 0) {
+			c0 = (c0 & 0xFFFF) + (c0 >> 16);	// Sum0 modulo 65535 + the overflow
+			c1 = (c1 & 0xFFFF) + (c1 >> 16);	// Sum1 modulo 65535 + the overflow
+		}
+
+	}
+
+	c0 = (c0 & 0xFFFF) + (c0 >> 16);	// Sum0 modulo 65535 + the overflow
+	c1 = (c1 & 0xFFFF) + (c1 >> 16);	// Sum1 modulo 65535 + the overflow
+	checksum = (c1 << 16) | c0;
+
+	return checksum;
+}
+
+void usage()
+{
+	printf("Create AMD Firmware combination\n");
+}
+
+typedef enum _amd_fw_type {
+	AMD_FW_PSP_PUBKEY = 0,
+	AMD_FW_PSP_BOOTLOADER = 1,
+	AMD_FW_PSP_SMU_FIRMWARE = 8,
+	AMD_FW_PSP_RECOVERY = 3,
+	AMD_FW_PSP_RTM_PUBKEY = 5,
+	AMD_FW_PSP_SECURED_OS = 2,
+	AMD_FW_PSP_NVRAM = 4,
+	AMD_FW_PSP_SECURED_DEBUG = 9,
+	AMD_FW_PSP_TRUSTLETS = 12,
+	AMD_FW_PSP_TRUSTLETKEY = 13,
+	AMD_FW_PSP_SMU_FIRMWARE2 = 18,
+	AMD_PSP_FUSE_CHAIN = 11,
+	AMD_FW_PSP_SMUSCS = 95,
+
+	AMD_FW_IMC,
+	AMD_FW_GEC,
+	AMD_FW_XHCI,
+} amd_fw_type;
+
+typedef struct _amd_fw_entry {
+	amd_fw_type type;
+	char *filename;
+} amd_fw_entry;
+
+amd_fw_entry amd_psp_fw_table[] = {
+	{ .type = AMD_FW_PSP_PUBKEY },
+	{ .type = AMD_FW_PSP_BOOTLOADER },
+	{ .type = AMD_FW_PSP_SMU_FIRMWARE },
+	{ .type = AMD_FW_PSP_RECOVERY },
+	{ .type = AMD_FW_PSP_RTM_PUBKEY },
+	{ .type = AMD_FW_PSP_SECURED_OS },
+	{ .type = AMD_FW_PSP_NVRAM },
+	{ .type = AMD_FW_PSP_SECURED_DEBUG },
+	{ .type = AMD_FW_PSP_TRUSTLETS },
+	{ .type = AMD_FW_PSP_TRUSTLETKEY },
+	{ .type = AMD_FW_PSP_SMU_FIRMWARE2 },
+	{ .type = AMD_FW_PSP_SMUSCS },
+	{ .type = AMD_PSP_FUSE_CHAIN },
+};
+
+amd_fw_entry amd_fw_table[] = {
+	{ .type = AMD_FW_XHCI },
+	{ .type = AMD_FW_IMC },
+	{ .type = AMD_FW_GEC },
+};
+
+void fill_psp_head(uint32_t *pspdir, int count)
+{
+	pspdir[0] = 'PSP$';  /* 1347637284 */
+	pspdir[2] = count;		/* size */
+	pspdir[3] = 0;
+	pspdir[1] = fletcher32((uint16_t *)&pspdir[1], (count *16 + 16)/2 - 2);
+}
+
+uint32_t integerate_one_fw(void *base, uint32_t pos, uint32_t *romsig, int i)
+{
+	int fd;
+	struct stat fd_stat;
+
+	if (amd_fw_table[i].filename != NULL) {
+		fd = open (amd_fw_table[i].filename, O_RDONLY);
+		fstat(fd, &fd_stat);
+
+		switch (amd_fw_table[i].type) {
+		case AMD_FW_IMC:
+			romsig[1] = pos + ROM_BASE_ADDRESS;
+			break;
+		case AMD_FW_GEC:
+			romsig[2] = pos + ROM_BASE_ADDRESS;
+			break;
+		case AMD_FW_XHCI:
+			romsig[3] = pos + ROM_BASE_ADDRESS;
+			break;
+		default:
+			/* Error */
+			break;
+		}
+		read (fd, base+pos, fd_stat.st_size);
+
+		pos += fd_stat.st_size;
+		pos = ALIGN(pos, 0x100);
+		close (fd);
+	}
+
+	return pos;
+}
+
+uint32_t integerate_one_psp(void *base, uint32_t pos, uint32_t *pspdir, int i)
+{
+	int fd;
+	struct stat fd_stat;
+
+	pspdir[4+4*i+0] = amd_psp_fw_table[i].type;
+
+	if (amd_psp_fw_table[i].type == AMD_PSP_FUSE_CHAIN) {
+		pspdir[4+4*i+1] = 0xFFFFFFFF;
+		pspdir[4+4*i+2] = 1;
+		pspdir[4+4*i+3] = 0;
+	} else if (amd_psp_fw_table[i].filename != NULL) {
+		fd = open (amd_psp_fw_table[i].filename, O_RDONLY);
+		fstat(fd, &fd_stat);
+		pspdir[4+4*i+1] = fd_stat.st_size;
+
+		pspdir[4+4*i+2] = pos + ROM_BASE_ADDRESS;
+		pspdir[4+4*i+3] = 0;
+
+		read (fd, base+pos, fd_stat.st_size);
+
+		pos += fd_stat.st_size;
+		pos = ALIGN(pos, 0x100);
+		close (fd);
+	}
+	return pos;
+}
+
+static const char *optstring  = "x:i:g:p:b:s:r:k:o:n:d:t:u:w:m:h";
+static struct option long_options[] = {
+	{"xhci",         required_argument, 0, 'x' },
+	{"imc",          required_argument, 0, 'i' },
+	{"gec",          required_argument, 0, 'g' },
+	/* PSP */
+	{"pubkey",       required_argument, 0, 'p' },
+	{"bootloader",   required_argument, 0, 'b' },
+	{"smufirmware",  required_argument, 0, 's' },
+	{"recovery",     required_argument, 0, 'r' },
+	{"rtmpubkey",    required_argument, 0, 'k' },
+	{"secureos",     required_argument, 0, 'c' },
+	{"nvram",        required_argument, 0, 'n' },
+	{"securedebug",  required_argument, 0, 'd' },
+	{"trustlets",    required_argument, 0, 't' },
+	{"trustletkey",  required_argument, 0, 'u' },
+	{"smufirmware2", required_argument, 0, 'w' },
+	{"smuscs",       required_argument, 0, 'm' },
+	{"output",       required_argument, 0, 'o' },
+	{"help",         no_argument,       0, 'h' },
+	{NULL,           0,                 0,  0  }
+};
+
+void register_fw_filename(amd_fw_type type, char filename[])
+{
+	int i;
+
+	for (i = 0; i < sizeof(amd_psp_fw_table)/sizeof(amd_fw_entry); i++) {
+		if (amd_psp_fw_table[i].type == type) {
+			amd_psp_fw_table[i].filename = filename;
+		}
+	}
+	for (i = 0; i < sizeof(amd_fw_table)/sizeof(amd_fw_entry); i++) {
+		if (amd_fw_table[i].type == type) {
+			amd_fw_table[i].filename = filename;
+		}
+	}
+}
+
+int main(int argc, char **argv)
+{
+	int c, count;
+
+	void *rom = NULL;
+	uint32_t current;
+	uint32_t *amd_romsig, *pspdir;
+
+	int targetfd;
+	char *output;
+
+	rom = malloc(CONFIG_ROM_SIZE);
+	memset (rom, 0xFF, CONFIG_ROM_SIZE);
+	if (!rom) {
+		return 1;
+	}
+
+	current = AMD_ROMSIG_OFFSET;
+	amd_romsig = rom + AMD_ROMSIG_OFFSET;
+	amd_romsig[0] = 0x55AA55AA; /* romsig */
+	amd_romsig[1] = 0;	    /* IMC */
+	amd_romsig[2] = 0;	    /* GEC */
+	amd_romsig[3] = 0;	    /* XHCI */
+	amd_romsig[4] = 0;	    /* PSP */
+
+	current += 0x20;	    /* size of ROMSIG */
+
+	while (1) {
+		int optindex = 0;
+
+		c = getopt_long(argc, argv, optstring, long_options, &optindex);
+
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'x':
+			register_fw_filename(AMD_FW_XHCI, optarg);
+			break;
+		case 'i':
+			register_fw_filename(AMD_FW_IMC, optarg);
+			break;
+		case 'g':
+			register_fw_filename(AMD_FW_GEC, optarg);
+			break;
+		case 'p':
+			register_fw_filename(AMD_FW_PSP_PUBKEY, optarg);
+			break;
+		case 'b':
+			register_fw_filename(AMD_FW_PSP_BOOTLOADER, optarg);
+			break;
+		case 's':
+			register_fw_filename(AMD_FW_PSP_SMU_FIRMWARE, optarg);
+			break;
+		case 'r':
+			register_fw_filename(AMD_FW_PSP_RECOVERY, optarg);
+			break;
+		case 'k':
+			register_fw_filename(AMD_FW_PSP_RTM_PUBKEY, optarg);
+			break;
+		case 'c':
+			register_fw_filename(AMD_FW_PSP_SECURED_OS, optarg);
+			break;
+		case 'n':
+			register_fw_filename(AMD_FW_PSP_NVRAM, optarg);
+			break;
+		case 'd':
+			register_fw_filename(AMD_FW_PSP_SECURED_DEBUG, optarg);
+			break;
+		case 't':
+			register_fw_filename(AMD_FW_PSP_TRUSTLETS, optarg);
+			break;
+		case 'u':
+			register_fw_filename(AMD_FW_PSP_TRUSTLETKEY, optarg);
+			break;
+		case 'w':
+			register_fw_filename(AMD_FW_PSP_SMU_FIRMWARE2, optarg);
+			break;
+		case 'm':
+			register_fw_filename(AMD_FW_PSP_SMUSCS, optarg);
+			break;
+
+		case 'o':
+			output = optarg;
+			break;
+		case 'h':
+			usage();
+			return 1;
+		default:
+			break;
+		}
+	}
+
+	current = ALIGN(current, 0x100);
+	for (count = 0; count < sizeof(amd_fw_table) / sizeof(amd_fw_entry); count ++) {
+		current = integerate_one_fw(rom, current, amd_romsig, count);
+	}
+
+	current = ALIGN(current, 0x10000);
+	pspdir = rom + current;
+	amd_romsig[4] = current + ROM_BASE_ADDRESS;
+
+	current += 0x400;	/* Conservative size of pspdir */
+	for (count = 0; count < sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); count ++) {
+		current = integerate_one_psp(rom, current, pspdir, count);
+	}
+
+	fill_psp_head(pspdir, count);
+
+	targetfd = open(output, O_RDWR | O_CREAT, 0666);
+	write(targetfd, amd_romsig, current - AMD_ROMSIG_OFFSET);
+	close(targetfd);
+	free(rom);
+	return 0;
+}



More information about the coreboot-gerrit mailing list