[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