Nico Huber has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/37674 )
Change subject: [WIP]util/fsp-defaults: Add tool to extract FSP UPDs from binaries ......................................................................
[WIP]util/fsp-defaults: Add tool to extract FSP UPDs from binaries
Change-Id: Ia1174e2df7a6b0a634ea6f784abae65137ffc8f7 Signed-off-by: Nico Huber nico.huber@secunet.com --- A util/fsp-defaults/.gitignore A util/fsp-defaults/Makefile A util/fsp-defaults/fspdef.awk A util/fsp-defaults/fspdef.h A util/fsp-defaults/main.c 5 files changed, 213 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/74/37674/1
diff --git a/util/fsp-defaults/.gitignore b/util/fsp-defaults/.gitignore new file mode 100644 index 0000000..1f5666f --- /dev/null +++ b/util/fsp-defaults/.gitignore @@ -0,0 +1,5 @@ +.fsp_inc +.udk_base +fspdef +fspm.c +fsps.c diff --git a/util/fsp-defaults/Makefile b/util/fsp-defaults/Makefile new file mode 100644 index 0000000..8adc0a9 --- /dev/null +++ b/util/fsp-defaults/Makefile @@ -0,0 +1,30 @@ +ifeq ($(UDK_BASE),) +$(warning Need to specify UDK_BASE=) +endif +$(shell if [ "$(UDK_BASE)" != "$$(cat .udk_base 2>/dev/null)" ]; then echo "$(UDK_BASE)" >.udk_base; fi) + +ifeq ($(FSP_INC),) +$(warning Need to specify FSP_INC=) +endif +$(shell if [ "$(FSP_INC)" != "$$(cat .fsp_inc 2>/dev/null)" ]; then echo "$(FSP_INC)" >.fsp_inc; fi) + +_CPPFLAGS = \ + -I../../src/commonlib/include/ \ + -I$(UDK_BASE)/MdePkg/Include/Ia32/ \ + -I$(UDK_BASE)/MdePkg/Include/ \ + -I$(UDK_BASE)/IntelFsp2Pkg/Include/ \ + -I$(FSP_INC)/ \ + +fspdef: main.c fspm.c fsps.c .fsp_inc .udk_base + gcc -m32 $(_CPPFLAGS) -o $@ $< fspm.c fsps.c + +fspm.c: $(FSP_INC)/FspmUpd.h fspdef.awk .fsp_inc .udk_base + gcc $(_CPPFLAGS) -E $< | gawk -f fspdef.awk > $@ + +fsps.c: $(FSP_INC)/FspsUpd.h fspdef.awk .fsp_inc .udk_base + gcc $(_CPPFLAGS) -E $< | gawk -f fspdef.awk > $@ + +clean: + rm -f fspm.c fsps.c fspdef + +.PHONY: clean diff --git a/util/fsp-defaults/fspdef.awk b/util/fsp-defaults/fspdef.awk new file mode 100644 index 0000000..07a9756 --- /dev/null +++ b/util/fsp-defaults/fspdef.awk @@ -0,0 +1,97 @@ +function process(field, width) { + printf("\tif (config->%s)\n", field); + printf("\t\tprintf("\t\t/* 0x%%04x */ .%s = 0x%%"PRIx%s",\n", offset + offsetof(typeof(*config), %s), config->%s);\n", + field, width, field, field); +} + +function process_array(field, width) { + printf("\tfor (i = 0; i < ARRAY_SIZE(config->%s); ++i) {\n", field); + printf("\t\tif (config->%s[i])\n", field); + printf("\t\t\tbreak;\n"); + printf("\t}\n"); + printf("\tif (i < ARRAY_SIZE(config->%s)) {\n", field); + printf("\t\tprintf("\t\t/* 0x%%04x */ .%s = {", offset + offsetof(typeof(*config), %s));\n", + field, field); + printf("\t\tfor (i = 0; i < ARRAY_SIZE(config->%s); ++i) {\n", field); + printf("\t\t\tif (i % 8 == 0)\n"); + printf("\t\t\t\tprintf("\n\t\t\t");\n"); + printf("\t\t\tprintf("0x%%"PRIx%s",", config->%s[i]);\n", width, field); + printf("\t\t\tif ((i + 1) % 8 != 0 && i != ARRAY_SIZE(config->%s) - 1)\n", field); + printf("\t\t\t\tprintf(" ");\n"); + printf("\t\t}\n"); + printf("\t\tprintf("\n\t\t},\n");\n"); + printf("\t}\n"); +} + +function process_struct(cname, tname) { + printf("void process_%s(const size_t offset, const %s *const config)\n{\n", cname, tname); + printf("\tunsigned int i;\n"); + printf("\tprintf("\tstatic const %s default_%s = {\n");\n\n", tname, cname); + for (field in fields) { + if (field in arrays) + process_array(fields[field], widths[field]); + else + process(fields[field], widths[field]); + printf("\n"); + } + printf("\tprintf("\t};\n\n");\n"); + printf("}\n\n"); +} + +BEGIN { + gather = 0; + + printf("#include <stdio.h>\n"); + printf("#include <stddef.h>\n"); + printf("#include <inttypes.h>\n"); + printf("#include <commonlib/helpers.h>\n"); + printf("#include <FspmUpd.h>\n"); + printf("#include <FspsUpd.h>\n\n"); + printf("#include "fspdef.h"\n\n"); +} + +/typedef struct {/ { + gather = 1; + field = 0; +} + +# match single identifiers +match($0, /(UINT|CHAR)([0-9]+) ([0-9a-zA-Z]+);/, matches) { + if (gather) { + fields[field] = matches[3]; + widths[field] = matches[2]; + ++field; + } +} + +# match array identifiers +match($0, /(UINT|CHAR)([0-9]+) ([0-9a-zA-Z]+)[([0-9]+)];/, matches) { + if (gather) { + fields[field] = matches[3]; + widths[field] = matches[2]; + arrays[field] = "dummy"; + ++field; + } +} + +/} FSP_M_CONFIG;/ { + process_struct("fsp_m_config", "FSP_M_CONFIG"); +} + +/} FSP_M_TEST_CONFIG;/ { + process_struct("fsp_m_tconfig", "FSP_M_TEST_CONFIG"); +} + +/} FSP_S_CONFIG;/ { + process_struct("fsp_s_config", "FSP_S_CONFIG"); +} + +/} FSP_S_TEST_CONFIG;/ { + process_struct("fsp_s_tconfig", "FSP_S_TEST_CONFIG"); +} + +/} .*;/ { + gather = 0; + delete fields; + delete arrays; +} diff --git a/util/fsp-defaults/fspdef.h b/util/fsp-defaults/fspdef.h new file mode 100644 index 0000000..72d99ad --- /dev/null +++ b/util/fsp-defaults/fspdef.h @@ -0,0 +1,12 @@ +#ifndef UTIL_FSP_DEFAULTS_FSPDEF_H +#define UTIL_FSP_DEFAULTS_FSPDEF_H + +#include <FspmUpd.h> +#include <FspsUpd.h> + +void process_fsp_m_config(size_t offset, const FSP_M_CONFIG *); +void process_fsp_m_tconfig(size_t offset, const FSP_M_TEST_CONFIG *); +void process_fsp_s_config(size_t offset, const FSP_S_CONFIG *); +void process_fsp_s_tconfig(size_t offset, const FSP_S_TEST_CONFIG *); + +#endif /* UTIL_FSP_DEFAULTS_FSPDEF_H */ diff --git a/util/fsp-defaults/main.c b/util/fsp-defaults/main.c new file mode 100644 index 0000000..eb4d2a9 --- /dev/null +++ b/util/fsp-defaults/main.c @@ -0,0 +1,69 @@ +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <FspUpd.h> +#include <FspmUpd.h> +#include <FspsUpd.h> + +#include "fspdef.h" + +int main(const int argc, const char *const argv[]) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s <path-to-FSP.fd>\n", argv[0]); + return 1; + } + + const int fd = open(argv[1], O_RDONLY); + if (fd == -1) { + perror("Failed to open FSP.fd"); + return 2; + } + + struct stat stat; + if (fstat(fd, &stat)) { + perror("Failed to stat FSP.fd"); + return 3; + } + + const void *const fsp = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); + close(fd); + if (fsp == MAP_FAILED) { + perror("Failed to map FSP.fd"); + return 3; + } + + const uint8_t *it, *const end = (const uint8_t *)fsp + stat.st_size; + for (it = fsp; it < end; ++it) { + const uint64_t *const sig = (const uint64_t *)it; + const FSPM_UPD *fspm; + const FSPS_UPD *fsps; + switch (*sig) { + case FSPM_UPD_SIGNATURE: + fspm = (const FSPM_UPD *)sig; + process_fsp_m_config( + offsetof(FSPM_UPD, FspmConfig), + &fspm->FspmConfig); + process_fsp_m_tconfig( + offsetof(FSPM_UPD, FspmTestConfig), + &fspm->FspmTestConfig); + break; + case FSPS_UPD_SIGNATURE: + fsps = (const FSPS_UPD *)sig; + process_fsp_s_config( + offsetof(FSPS_UPD, FspsConfig), + &fsps->FspsConfig); + process_fsp_s_tconfig( + offsetof(FSPS_UPD, FspsTestConfig), + &fsps->FspsTestConfig); + break; + } + } + + munmap((void *)fsp, stat.st_size); + return 0; +}