[coreboot-gerrit] New patch to review for coreboot: amdfwtool: Add amdfwtool to combine AMD firmware

Zheng Bao (zheng.bao@amd.com) gerrit at coreboot.org
Thu Nov 12 16:58:12 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 5c98efff267b880f5df3efd692c1c4b4d60ab1c8
Author: Zheng Bao <fishbaozi at gmail.com>
Date:   Thu Nov 12 23:54: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>
---
 Makefile.inc               |   7 +-
 util/amdfwtool/Makefile    |  70 +++++++++
 util/amdfwtool/amdfwtool.c | 358 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 434 insertions(+), 1 deletion(-)

diff --git a/Makefile.inc b/Makefile.inc
index 5b8e4dc..84a7e45 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -290,7 +290,7 @@ CFLAGS_common += -Os
 endif
 
 additional-dirs := $(objutil)/cbfstool $(objutil)/romcc $(objutil)/ifdtool \
-		   $(objutil)/ifdfake $(objutil)/options $(objutil)/fletcher \
+		   $(objutil)/ifdfake $(objutil)/options $(objutil)/fletcher $(objutil)/amdfwtool \
 		   $(objutil)/cbootimage $(objutil)/bimgtool
 
 #######################################################################
@@ -353,6 +353,11 @@ $(FLETCHER): $(top)/util/fletcher/fletcher.c
 	@printf "    HOSTCC     $(subst $(obj)/,,$(@))\n"
 	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
 
+AMDFWTOOL:=$(objutil)/amdfwtool/amdfwtool
+$(AMDFWTOOL): $(top)/util/amdfwtool/amdfwtool.c
+	@printf "    HOSTCC     $(subst $(obj)/,,$(@))\n"
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
+
 CBOOTIMAGE:=$(objutil)/cbootimage/cbootimage
 
 subdirs-y += util/nvidia
diff --git a/util/amdfwtool/Makefile b/util/amdfwtool/Makefile
new file mode 100644
index 0000000..bef2615
--- /dev/null
+++ b/util/amdfwtool/Makefile
@@ -0,0 +1,70 @@
+#*****************************************************************************
+#
+# 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..efbf058
--- /dev/null
+++ b/util/amdfwtool/amdfwtool.c
@@ -0,0 +1,358 @@
+/*
+ * 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>
+
+#define MAX_PSP_DIRECTORY_SIZE 512
+#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");
+}
+
+#define CONFIG_ROM_SIZE 0x800000
+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 + 0xFF800000;
+			break;
+		case AMD_FW_GEC:
+			romsig[2] = pos + 0xFF800000;
+			break;
+		case AMD_FW_XHCI:
+			romsig[3] = pos + 0xFF800000;
+			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 + 0xFF800000;
+		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, i;
+
+	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) {
+		//ERROR("Couldn't allocate memory for microcode update entries.\n");
+		return 1;
+	}
+	amd_romsig = rom + 0x20000; /* TODO: Remove hardcode */
+	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 = 0x20100; /* TODO: Remove hardcode */
+
+	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;
+		}
+	}
+
+	for (i=0; i< sizeof(amd_fw_table) / sizeof(amd_fw_entry); i ++) {
+		current = integerate_one_fw(rom, current, amd_romsig, i);
+	}
+
+	current = ALIGN(current, 0x10000);
+	pspdir = rom + current;
+	amd_romsig[4] = current + 0xFF800000;
+	current += 0x400;
+	for (i=0; i< sizeof(amd_psp_fw_table) / sizeof(amd_fw_entry); i ++) {
+		current = integerate_one_psp(rom, current, pspdir, i);
+	}
+
+	fill_psp_head(pspdir, i);
+
+	targetfd = open(output, O_RDWR | O_CREAT, 0666);
+	write(targetfd, amd_romsig, current - 0x20000);
+	close(targetfd);
+	free(rom);
+	return 0;
+}



More information about the coreboot-gerrit mailing list