<p>Philipp Deppenwiese <strong>merged</strong> this change.</p><p><a href="https://review.coreboot.org/18902">View Change</a></p><div style="white-space:pre-wrap">Approvals:
build bot (Jenkins): Verified
Philipp Deppenwiese: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">util/intelvbttool: Rewrite tool<br><br>* Add Makefile dependency to source file<br>* Add argument support<br>* Add help support<br>* Print usage on wrong arguments<br>* Add support for parsing VBT binary file<br>* Add support for parsing PCI Option ROM<br>* Add support for writing VBT binary file<br>* Add support for patching PCI Option ROM<br>* Keep support for accessing legacy VGA area Option ROM<br>* Keep support for dumping VBT contents to stdout<br><br>Allows to extract VBT, analyse VBT and patch PCI Option ROMs as needed.<br><br>The required arguments have been changed:<br><br>./intelvbttool --<SOURCECMD> [filename] --<DESTCMD> [filename]<br><br>SOURCECMD set the VBT source. Supported:<br> inlegacy : Legacy BIOS area at phys. memory 0xc0000<br> invbt : Read raw Intel VBT file<br> inoprom : Read VBT from Intel Option ROM file<br><br>DESTCMD set the VBT destination. Supported:<br> outdump : Print VBT in human readable form<br> outvbt : Write raw Intel VBT file<br> patchoprom: Patch existing Intel Option ROM<br><br>Any combination of SOURCECMD and DESTCMD is possible.<br><br>Change-Id: I8cbde042c7f5632f36648419becd23e248ba6f76<br>Signed-off-by: Patrick Rudolph <siro@das-labor.org><br>Reviewed-on: https://review.coreboot.org/18902<br>Tested-by: build bot (Jenkins) <no-reply@coreboot.org><br>Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com><br>---<br>M util/intelvbttool/Makefile<br>M util/intelvbttool/intelvbttool.c<br>2 files changed, 807 insertions(+), 113 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/util/intelvbttool/Makefile b/util/intelvbttool/Makefile</span><br><span>index 7d50d30..fb9aade 100644</span><br><span>--- a/util/intelvbttool/Makefile</span><br><span>+++ b/util/intelvbttool/Makefile</span><br><span>@@ -15,12 +15,13 @@</span><br><span> </span><br><span> PROGRAM = intelvbttool</span><br><span> CC ?= gcc</span><br><span style="color: hsl(0, 100%, 40%);">-CFLAGS ?= -O2</span><br><span style="color: hsl(120, 100%, 40%);">+CFLAGS ?= -O2 -g</span><br><span> CFLAGS += -Wall -Werror</span><br><span style="color: hsl(120, 100%, 40%);">+CFLAGS += -I../../src/commonlib/include</span><br><span> </span><br><span> all: $(PROGRAM)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-$(PROGRAM):</span><br><span style="color: hsl(120, 100%, 40%);">+$(PROGRAM): $(PROGRAM).c</span><br><span> $(CC) $(CFLAGS) $(CPPFLAGS) $(PROGRAM).c -o $(PROGRAM)</span><br><span> </span><br><span> clean:</span><br><span>diff --git a/util/intelvbttool/intelvbttool.c b/util/intelvbttool/intelvbttool.c</span><br><span>index f0216dd..c8b973e 100644</span><br><span>--- a/util/intelvbttool/intelvbttool.c</span><br><span>+++ b/util/intelvbttool/intelvbttool.c</span><br><span>@@ -20,7 +20,10 @@</span><br><span> #include <sys/types.h></span><br><span> #include <sys/stat.h></span><br><span> #include <fcntl.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <getopt.h></span><br><span> #include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdarg.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <commonlib/helpers.h></span><br><span> </span><br><span> typedef uint8_t u8;</span><br><span> typedef uint16_t u16;</span><br><span>@@ -30,11 +33,28 @@</span><br><span> typedef struct {</span><br><span> u16 signature;</span><br><span> u8 size;</span><br><span style="color: hsl(0, 100%, 40%);">- u8 reserved[21];</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 entrypoint[4];</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 checksum;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 reserved[16];</span><br><span> u16 pcir_offset;</span><br><span> u16 vbt_offset;</span><br><span> } __attribute__ ((packed)) optionrom_header_t;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+typedef struct {</span><br><span style="color: hsl(120, 100%, 40%);">+ u32 signature;</span><br><span style="color: hsl(120, 100%, 40%);">+ u16 vendor;</span><br><span style="color: hsl(120, 100%, 40%);">+ u16 device;</span><br><span style="color: hsl(120, 100%, 40%);">+ u16 reserved1;</span><br><span style="color: hsl(120, 100%, 40%);">+ u16 length;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 revision;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 classcode[3];</span><br><span style="color: hsl(120, 100%, 40%);">+ u16 imagelength;</span><br><span style="color: hsl(120, 100%, 40%);">+ u16 coderevision;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 codetype;</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 indicator;</span><br><span style="color: hsl(120, 100%, 40%);">+ u16 reserved2;</span><br><span style="color: hsl(120, 100%, 40%);">+} __attribute__((packed)) optionrom_pcir_t;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> struct vbt_header {</span><br><span> u8 signature[20];</span><br><span> u16 version;</span><br><span>@@ -221,6 +241,8 @@</span><br><span> } __attribute__ ((packed));</span><br><span> </span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static const size_t ignore_checksum = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define BDB_GENERAL_FEATURES 1</span><br><span> #define BDB_GENERAL_DEFINITIONS 2</span><br><span> </span><br><span>@@ -233,143 +255,370 @@</span><br><span> </span><br><span> #define BDB_SKIP 254</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void parse_vbt(const void *vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+/* print helpers */</span><br><span style="color: hsl(120, 100%, 40%);">+static void print(const char *format, ...)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- const struct vbt_header *head = vbt;</span><br><span style="color: hsl(120, 100%, 40%);">+ va_list args;</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stdout, "VBTTOOL: ");</span><br><span style="color: hsl(120, 100%, 40%);">+ va_start(args, format);</span><br><span style="color: hsl(120, 100%, 40%);">+ vfprintf(stdout, format, args);</span><br><span style="color: hsl(120, 100%, 40%);">+ va_end(args);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void printt(const char *format, ...)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ va_list args;</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stdout, "\t");</span><br><span style="color: hsl(120, 100%, 40%);">+ va_start(args, format);</span><br><span style="color: hsl(120, 100%, 40%);">+ vfprintf(stdout, format, args);</span><br><span style="color: hsl(120, 100%, 40%);">+ va_end(args);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void printwarn(const char *format, ...)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ va_list args;</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "VBTTOOL: WARN: ");</span><br><span style="color: hsl(120, 100%, 40%);">+ va_start(args, format);</span><br><span style="color: hsl(120, 100%, 40%);">+ vfprintf(stderr, format, args);</span><br><span style="color: hsl(120, 100%, 40%);">+ va_end(args);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void printerr(const char *format, ...)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ va_list args;</span><br><span style="color: hsl(120, 100%, 40%);">+ fprintf(stderr, "VBTTOOL: ERR: ");</span><br><span style="color: hsl(120, 100%, 40%);">+ va_start(args, format);</span><br><span style="color: hsl(120, 100%, 40%);">+ vfprintf(stderr, format, args);</span><br><span style="color: hsl(120, 100%, 40%);">+ va_end(args);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct fileobject {</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char *data;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t size;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* file object helpers */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Alloc a file object of given size.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns NULL on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct fileobject *malloc_fo(const size_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *fo;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fo = malloc(sizeof(*fo));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ fo->data = malloc(size);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo->data) {</span><br><span style="color: hsl(120, 100%, 40%);">+ free(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ fo->size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return fo;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Free a fileobject structure */</span><br><span style="color: hsl(120, 100%, 40%);">+static void free_fo(struct fileobject *fo)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ free(fo->data);</span><br><span style="color: hsl(120, 100%, 40%);">+ free(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Resize file object and keep memory content */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct fileobject *remalloc_fo(struct fileobject *old,</span><br><span style="color: hsl(120, 100%, 40%);">+ const size_t size)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *fo = old;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!old || !size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fo->data = realloc(fo->data, size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo->data)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fo->size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return fo;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Creates a new subregion copy of fileobject.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns NULL if offset is greater than fileobject size.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Returns NULL on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct fileobject *malloc_fo_sub(const struct fileobject *old,</span><br><span style="color: hsl(120, 100%, 40%);">+ const size_t off)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *fo;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!old || off > old->size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fo = malloc_fo(old->size - off);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo)</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(fo->data, old->data + off, fo->size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return fo;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* file helpers */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Create fileobject from file */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct fileobject *read_file(const char *filename)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ FILE *fd = fopen(filename, "rb");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("%s open failed: %s\n", filename, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fseek(fd, 0, SEEK_END)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("%s seek failed: %s\n", filename, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ fclose(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const off_t size = ftell(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (size < 0 || size > SIZE_MAX) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("%s tell failed: %s\n", filename, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ fclose(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fseek(fd, 0, SEEK_SET)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("%s seek failed: %s\n", filename, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ fclose(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *fo = malloc_fo(size);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("malloc failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ fclose(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fread(fo->data, 1, size, fd) != size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fclose(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fclose(fd)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("%s close failed: %s\n", filename, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fo->size = size;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return fo;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Create fileobject from physical memory at given address of size 64 KiB */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct fileobject *read_physmem(size_t addr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const int fd = open("/dev/mem", O_RDONLY);</span><br><span style="color: hsl(120, 100%, 40%);">+ const size_t size = 64 * 2 * KiB;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fd < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("/dev/mem open failed: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const void *data = mmap(0, size, PROT_READ, MAP_SHARED, fd, addr);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (data == MAP_FAILED) {</span><br><span style="color: hsl(120, 100%, 40%);">+ close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("mmap failed: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *fo = malloc_fo(size);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("malloc failed\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ munmap((void *)data, size);</span><br><span style="color: hsl(120, 100%, 40%);">+ close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(fo->data, data, size);</span><br><span style="color: hsl(120, 100%, 40%);">+ munmap((void *)data, size);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (close(fd)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("/dev/mem close failed: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return fo;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Write fileobject contents to file */</span><br><span style="color: hsl(120, 100%, 40%);">+static int write_file(const char *filename, const struct fileobject *fo)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ FILE *fd_out = fopen(filename, "wb");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fd_out) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("%s open failed: %s\n", filename, strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fwrite(fo->data, 1, fo->size, fd_out) != fo->size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fclose(fd_out);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return fclose(fd_out);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* dump VBT contents in human readable form */</span><br><span style="color: hsl(120, 100%, 40%);">+static void dump_vbt(const struct fileobject *fo)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fo->size < sizeof(struct vbt_header))</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct vbt_header *head = (const struct vbt_header *)fo->data;</span><br><span> const struct bdb_header *bdb;</span><br><span style="color: hsl(0, 100%, 40%);">- int i;</span><br><span> const u8 *ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span> int is_first_skip = 1;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (memcmp(head->signature, "$VBT", 4) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "invalid VBT signature\n");</span><br><span style="color: hsl(0, 100%, 40%);">- exit(1);</span><br><span style="color: hsl(0, 100%, 40%);">- }</span><br><span style="color: hsl(0, 100%, 40%);">- printf("signature: <%20.20s>\n", head->signature);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("version: %d.%02d\n", head->version / 100,</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("signature: <%20.20s>\n", head->signature);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("version: %d.%02d\n", head->version / 100,</span><br><span> head->version % 100);</span><br><span> if (head->header_size != sizeof(struct vbt_header))</span><br><span style="color: hsl(0, 100%, 40%);">- printf("header size: 0x%x\n", head->header_size);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("VBT size: 0x%x\n", head->vbt_size);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("VBT checksum: 0x%x\n", head->vbt_checksum);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("header size: 0x%x\n", head->header_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("VBT size: 0x%x\n", head->vbt_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("VBT checksum: 0x%x\n", head->vbt_checksum);</span><br><span> if (head->reserved0)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("header reserved0: 0x%x\n", head->reserved0);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("header reserved0: 0x%x\n", head->reserved0);</span><br><span> if (head->bdb_offset != sizeof(struct vbt_header))</span><br><span style="color: hsl(0, 100%, 40%);">- printf("BDB offset: 0x%x\n", head->bdb_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("BDB offset: 0x%x\n", head->bdb_offset);</span><br><span> </span><br><span> for (i = 0; i < 4; i++)</span><br><span> if (head->aim_offset[i])</span><br><span style="color: hsl(0, 100%, 40%);">- printf("AIM[%d] offset: 0x%x\n", i,</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("AIM[%d] offset: 0x%x\n", i,</span><br><span> head->aim_offset[i]);</span><br><span style="color: hsl(0, 100%, 40%);">- bdb = (const void *) ((const char *) vbt + head->bdb_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (head->bdb_offset + sizeof(*bdb) > fo->size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ bdb = (const void *) (fo->data + head->bdb_offset);</span><br><span> </span><br><span> if (memcmp("BIOS_DATA_BLOCK ", bdb->signature, 16) != 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "invalid BDB signature:%s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid BDB signature:%s\n",</span><br><span> bdb->signature);</span><br><span> exit(1);</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- printf("BDB version: %d.%02d\n", bdb->version / 100,</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("BDB version: %d.%02d\n", bdb->version / 100,</span><br><span> bdb->version % 100);</span><br><span> if (bdb->header_size != sizeof(struct bdb_header))</span><br><span style="color: hsl(0, 100%, 40%);">- printf("BDB header size: 0x%x\n", bdb->header_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("BDB header size: 0x%x\n", bdb->header_size);</span><br><span> if (bdb->bdb_size != head->vbt_size - head->bdb_offset)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("BDB size: 0x%x\n", bdb->bdb_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("BDB size: 0x%x\n", bdb->bdb_size);</span><br><span> for (ptr = (const u8 *) bdb + bdb->header_size;</span><br><span> ptr < (const u8 *) bdb + bdb->bdb_size;) {</span><br><span> u16 secsz = (ptr[1] | (ptr[2] << 8));</span><br><span> u8 sectype = ptr[0];</span><br><span> const u8 *section = ptr + 3;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- printf("section type %d, size 0x%x\n", sectype, secsz);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("section type %d, size 0x%x\n", sectype, secsz);</span><br><span> ptr += secsz + 3;</span><br><span> switch (sectype) {</span><br><span> case BDB_GENERAL_FEATURES:{</span><br><span> const struct bdb_general_features *sec =</span><br><span> (const void *) section;</span><br><span style="color: hsl(0, 100%, 40%);">- printf("General features:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("General features:\n");</span><br><span> </span><br><span> if (sec->panel_fitting)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tpanel_fitting = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tpanel_fitting = 0x%x\n",</span><br><span> sec->panel_fitting);</span><br><span> if (sec->flexaim)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tflexaim = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tflexaim = 0x%x\n",</span><br><span> sec->flexaim);</span><br><span> if (sec->msg_enable)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tmsg_enable = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tmsg_enable = 0x%x\n",</span><br><span> sec->msg_enable);</span><br><span> if (sec->clear_screen)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tclear_screen = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tclear_screen = 0x%x\n",</span><br><span> sec->clear_screen);</span><br><span> if (sec->color_flip)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tcolor_flip = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tcolor_flip = 0x%x\n",</span><br><span> sec->color_flip);</span><br><span> if (sec->download_ext_vbt)</span><br><span style="color: hsl(0, 100%, 40%);">- printf</span><br><span style="color: hsl(120, 100%, 40%);">+ printt</span><br><span> ("\tdownload_ext_vbt = 0x%x\n",</span><br><span> sec->download_ext_vbt);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*enable_ssc = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*enable_ssc = 0x%x\n",</span><br><span> sec->enable_ssc);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*ssc_freq = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*ssc_freq = 0x%x\n",</span><br><span> sec->ssc_freq);</span><br><span> if (sec->enable_lfp_on_override)</span><br><span style="color: hsl(0, 100%, 40%);">- printf</span><br><span style="color: hsl(120, 100%, 40%);">+ printt</span><br><span> ("\tenable_lfp_on_override = 0x%x\n",</span><br><span> sec->enable_lfp_on_override);</span><br><span> if (sec->disable_ssc_ddt)</span><br><span style="color: hsl(0, 100%, 40%);">- printf</span><br><span style="color: hsl(120, 100%, 40%);">+ printt</span><br><span> ("\tdisable_ssc_ddt = 0x%x\n",</span><br><span> sec->disable_ssc_ddt);</span><br><span> if (sec->rsvd7)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd7 = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd7 = 0x%x\n",</span><br><span> sec->rsvd7);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*display_clock_mode = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*display_clock_mode = 0x%x\n",</span><br><span> sec->display_clock_mode);</span><br><span> if (sec->rsvd8)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd8 = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd8 = 0x%x\n",</span><br><span> sec->rsvd8);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tdisable_smooth_vision = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tdisable_smooth_vision = 0x%x\n",</span><br><span> sec->disable_smooth_vision);</span><br><span> if (sec->single_dvi)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tsingle_dvi = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tsingle_dvi = 0x%x\n",</span><br><span> sec->single_dvi);</span><br><span> if (sec->rsvd9)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd9 = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd9 = 0x%x\n",</span><br><span> sec->rsvd9);</span><br><span style="color: hsl(0, 100%, 40%);">- printf</span><br><span style="color: hsl(120, 100%, 40%);">+ printt</span><br><span> ("\t*fdi_rx_polarity_inverted = 0x%x\n",</span><br><span> sec->fdi_rx_polarity_inverted);</span><br><span> if (sec->rsvd10)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd10 = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd10 = 0x%x\n",</span><br><span> sec->rsvd10);</span><br><span> if (sec->legacy_monitor_detect)</span><br><span style="color: hsl(0, 100%, 40%);">- printf</span><br><span style="color: hsl(120, 100%, 40%);">+ printt</span><br><span> ("\tlegacy_monitor_detect = 0x%x\n",</span><br><span> sec->legacy_monitor_detect);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*int_crt_support = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*int_crt_support = 0x%x\n",</span><br><span> sec->int_crt_support);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*int_tv_support = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*int_tv_support = 0x%x\n",</span><br><span> sec->int_tv_support);</span><br><span> if (sec->int_efp_support)</span><br><span style="color: hsl(0, 100%, 40%);">- printf</span><br><span style="color: hsl(120, 100%, 40%);">+ printt</span><br><span> ("\tint_efp_support = 0x%x\n",</span><br><span> sec->int_efp_support);</span><br><span> if (sec->dp_ssc_enb)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tdp_ssc_enb = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tdp_ssc_enb = 0x%x\n",</span><br><span> sec->dp_ssc_enb);</span><br><span> if (sec->dp_ssc_freq)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tdp_ssc_freq = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tdp_ssc_freq = 0x%x\n",</span><br><span> sec->dp_ssc_freq);</span><br><span> if (sec->rsvd11)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd11 = 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd11 = 0x%x\n",</span><br><span> sec->rsvd11);</span><br><span> break;</span><br><span> }</span><br><span> case BDB_DRIVER_FEATURES:{</span><br><span> const struct bdb_driver_features *sec =</span><br><span> (const void *) section;</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*LVDS config: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*LVDS config: %d\n",</span><br><span> sec->lvds_config);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*Dual frequency: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*Dual frequency: %d\n",</span><br><span> sec->dual_frequency);</span><br><span> </span><br><span> break;</span><br><span>@@ -377,7 +626,7 @@</span><br><span> case BDB_SDVO_LVDS_OPTIONS:{</span><br><span> const struct bdb_sdvo_lvds_options *sec =</span><br><span> (const void *) section;</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*Panel type: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*Panel type: %d\n",</span><br><span> sec->panel_type);</span><br><span> </span><br><span> break;</span><br><span>@@ -386,29 +635,29 @@</span><br><span> const struct bdb_general_definitions *sec =</span><br><span> (const void *) section;</span><br><span> int ndev;</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*CRT DDC GMBUS pin: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*CRT DDC GMBUS pin: %d\n",</span><br><span> sec->crt_ddc_gmbus_pin);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tDPMS ACPI: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tDPMS ACPI: %d\n",</span><br><span> sec->dpms_acpi);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tSkip boot CRT detect: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tSkip boot CRT detect: %d\n",</span><br><span> sec->skip_boot_crt_detect);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tDPMS aim: %d\n", sec->dpms_aim);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tDPMS aim: %d\n", sec->dpms_aim);</span><br><span> if (sec->rsvd1)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd1: 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd1: 0x%x\n",</span><br><span> sec->rsvd1);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tboot_display: { %x, %x }\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tboot_display: { %x, %x }\n",</span><br><span> sec->boot_display[0],</span><br><span> sec->boot_display[1]);</span><br><span> if (sec->child_dev_size !=</span><br><span> sizeof(struct common_child_dev_config))</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tchild_dev_size: %d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tchild_dev_size: %d\n",</span><br><span> sec->child_dev_size);</span><br><span> ndev = (secsz - sizeof(*sec)) /</span><br><span> sizeof(struct common_child_dev_config);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t%d devices\n", ndev);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t%d devices\n", ndev);</span><br><span> for (i = 0; i < ndev; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t*device type: %x ",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t*device type: %x ",</span><br><span> sec->devices[i].</span><br><span> device_type);</span><br><span> #define DEVICE_TYPE_INT_LFP 0x1022</span><br><span>@@ -416,35 +665,35 @@</span><br><span> #define DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR 0x6052</span><br><span> switch (sec->devices[i].device_type) {</span><br><span> case DEVICE_TYPE_INT_LFP:</span><br><span style="color: hsl(0, 100%, 40%);">- printf("(flat panel)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("(flat panel)\n");</span><br><span> break;</span><br><span> case DEVICE_TYPE_INT_TV:</span><br><span style="color: hsl(0, 100%, 40%);">- printf("(TV)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("(TV)\n");</span><br><span> break;</span><br><span> case DEVICE_TYPE_EFP_DVI_HOTPLUG_PWR:</span><br><span style="color: hsl(0, 100%, 40%);">- printf</span><br><span style="color: hsl(120, 100%, 40%);">+ printt</span><br><span> ("(DVI)\n");</span><br><span> break;</span><br><span> case 0:</span><br><span style="color: hsl(0, 100%, 40%);">- printf("(Empty)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("(Empty)\n");</span><br><span> break;</span><br><span> default:</span><br><span style="color: hsl(0, 100%, 40%);">- printf("(Unknown)\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("(Unknown)\n");</span><br><span> break;</span><br><span> }</span><br><span> if (!sec->devices[i].device_type)</span><br><span> continue;</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t *dvo_port: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t *dvo_port: %x\n",</span><br><span> sec->devices[i].dvo_port);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t *i2c_pin: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t *i2c_pin: %x\n",</span><br><span> sec->devices[i].i2c_pin);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t *slave_addr: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t *slave_addr: %x\n",</span><br><span> sec->devices[i].slave_addr);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t *ddc_pin: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t *ddc_pin: %x\n",</span><br><span> sec->devices[i].ddc_pin);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t *dvo_wiring: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t *dvo_wiring: %x\n",</span><br><span> sec->devices[i].dvo_wiring);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\t edid_ptr: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\t edid_ptr: %x\n",</span><br><span> sec->devices[i].edid_ptr);</span><br><span> }</span><br><span> </span><br><span>@@ -456,84 +705,528 @@</span><br><span> if (!is_first_skip)</span><br><span> break;</span><br><span> is_first_skip = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\ttype: %x\n", sec->type);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trelstage: %x\n", sec->relstage);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tchipset: %x\n", sec->chipset);</span><br><span style="color: hsl(0, 100%, 40%);">- printf(sec->lvds_present ? "\tLVDS\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\ttype: %x\n", sec->type);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trelstage: %x\n", sec->relstage);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tchipset: %x\n", sec->chipset);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt(sec->lvds_present ? "\tLVDS\n"</span><br><span> : "\tNo LVDS\n");</span><br><span style="color: hsl(0, 100%, 40%);">- printf(sec->tv_present ? "\tTV\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ printt(sec->tv_present ? "\tTV\n"</span><br><span> : "\tNo TV\n");</span><br><span> if (sec->rsvd2)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd2: 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd2: 0x%x\n",</span><br><span> sec->rsvd2);</span><br><span> for (i = 0; i < 4; i++)</span><br><span> if (sec->rsvd3[i])</span><br><span style="color: hsl(0, 100%, 40%);">- printf</span><br><span style="color: hsl(120, 100%, 40%);">+ printt</span><br><span> ("\trsvd3[%d]: 0x%x\n",</span><br><span> i, sec->rsvd3[i]);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tSignon: %.155s\n", sec->signon);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tCopyright: %.155s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tSignon: %.155s\n", sec->signon);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tCopyright: %.155s\n",</span><br><span> sec->copyright);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tCode segment: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tCode segment: %x\n",</span><br><span> sec->code_segment);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tDOS Boot mode: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tDOS Boot mode: %x\n",</span><br><span> sec->dos_boot_mode);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tBandwidth percent: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tBandwidth percent: %x\n",</span><br><span> sec->bandwidth_percent);</span><br><span> if (sec->rsvd4)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd4: 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd4: 0x%x\n",</span><br><span> sec->rsvd4);</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\tBandwidth percent: %x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\tBandwidth percent: %x\n",</span><br><span> sec->resize_pci_bios);</span><br><span> if (sec->rsvd5)</span><br><span style="color: hsl(0, 100%, 40%);">- printf("\trsvd5: 0x%x\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("\trsvd5: 0x%x\n",</span><br><span> sec->rsvd5);</span><br><span> break;</span><br><span> }</span><br><span> }</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void parse_vbios(const void *ptr)</span><br><span style="color: hsl(120, 100%, 40%);">+/* Returns a new fileobject containing a valid VBT */</span><br><span style="color: hsl(120, 100%, 40%);">+static void parse_vbt(const struct fileobject *fo,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject **vbt)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- const optionrom_header_t *oh;</span><br><span style="color: hsl(0, 100%, 40%);">- oh = ptr;</span><br><span style="color: hsl(120, 100%, 40%);">+ *vbt = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fo->size < sizeof(struct vbt_header)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("image is to small\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct vbt_header *head =</span><br><span style="color: hsl(120, 100%, 40%);">+ (const struct vbt_header *)fo->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (memcmp(head->signature, "$VBT", 4) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid VBT signature\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!head->vbt_size || head->vbt_size > fo->size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid VBT size\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!head->bdb_offset ||</span><br><span style="color: hsl(120, 100%, 40%);">+ head->bdb_offset > fo->size - sizeof(struct bdb_header)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid BDB offset\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!head->header_size || head->header_size > fo->size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid header size\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct bdb_header *const bdb_head =</span><br><span style="color: hsl(120, 100%, 40%);">+ (const struct bdb_header *)((const u8 *)head + head->bdb_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (memcmp(bdb_head->signature, "BIOS_DATA_BLOCK ", 16) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid BDB signature\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!bdb_head->header_size || bdb_head->header_size > fo->size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid BDB header size\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Duplicate fo as caller is owner and remalloc frees the object */</span><br><span style="color: hsl(120, 100%, 40%);">+ *vbt = remalloc_fo(malloc_fo_sub(fo, 0), head->vbt_size);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Option ROM checksum */</span><br><span style="color: hsl(120, 100%, 40%);">+static u8 checksum_vbios(const optionrom_header_t *oh)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const u8 *ptr = (const u8 *)oh;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ u8 cksum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < ((MIN(oh->size, 128)) * 512); i++)</span><br><span style="color: hsl(120, 100%, 40%);">+ cksum += ptr[i];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return cksum;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Verify Option ROM contents */</span><br><span style="color: hsl(120, 100%, 40%);">+static int is_valid_vbios(const struct fileobject *fo)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fo->size > 64 * 2 * KiB) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("VBIOS is to big\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fo->size < sizeof(optionrom_header_t)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("VBIOS is to small\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const optionrom_header_t *oh = (const optionrom_header_t *)fo->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (oh->signature != 0xaa55) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "bad oprom signature: %x\n",</span><br><span style="color: hsl(0, 100%, 40%);">- oh->signature);</span><br><span style="color: hsl(0, 100%, 40%);">- return;</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("bad oprom signature: 0x%x\n", oh->signature);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (oh->size == 0 || oh->size > 0x80 || oh->size * 512 > fo->size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("bad oprom size: 0x%x\n", oh->size);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const u8 cksum = checksum_vbios(oh);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (cksum) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ignore_checksum) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("bad oprom checksum: 0x%x\n", cksum);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ printwarn("bad oprom checksum: 0x%x\n", cksum);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (oh->pcir_offset + sizeof(optionrom_pcir_t) > fo->size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("bad pcir offset: 0x%x\n", oh->pcir_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (oh->pcir_offset) {</span><br><span style="color: hsl(120, 100%, 40%);">+ const optionrom_pcir_t *pcir;</span><br><span style="color: hsl(120, 100%, 40%);">+ pcir = (const optionrom_pcir_t *)</span><br><span style="color: hsl(120, 100%, 40%);">+ ((const u8 *)oh + oh->pcir_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pcir->signature != 0x52494350) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Invalid PCIR signature\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pcir->vendor != 0x8086) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Not an Intel VBIOS\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (pcir->classcode[0] != 0 || pcir->classcode[1] != 0 ||</span><br><span style="color: hsl(120, 100%, 40%);">+ pcir->classcode[2] != 3) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Not a VGA Option Rom\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ printwarn("no PCIR header found\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Parse Option ROM and return a valid VBT fileobject.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Caller has to make sure that it is a valid VBIOS.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return a NULL fileobject on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static void parse_vbios(const struct fileobject *fo,</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject **vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const optionrom_header_t *oh = (const optionrom_header_t *)fo->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct vbt_header *head;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ *vbt = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> if (!oh->vbt_offset) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "no VBT found\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("no VBT found\n");</span><br><span> return;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- parse_vbt((const char *) ptr + oh->vbt_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (oh->vbt_offset > (fo->size - sizeof(struct vbt_header))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid VBT offset\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ head = (const struct vbt_header *)fo->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (memcmp(head->signature, "$VBT", 4) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ parse_vbt(fo, vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (*vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printwarn("VBT wasn't found at specified offset\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = sizeof(optionrom_header_t);</span><br><span style="color: hsl(120, 100%, 40%);">+ i <= fo->size - sizeof(struct vbt_header); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *fo_vbt = malloc_fo_sub(fo, i);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo_vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ head = (const struct vbt_header *)fo_vbt->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (memcmp(head->signature, "$VBT", 4) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ parse_vbt(fo_vbt, vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo_vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (*vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Short VBT summary in human readable form */</span><br><span style="color: hsl(120, 100%, 40%);">+static void print_vbt(const struct fileobject *fo)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct bdb_header *bdb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fo->size < sizeof(struct vbt_header))</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct vbt_header *head = (const struct vbt_header *)fo->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Found VBT:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("signature: <%20.20s>\n", head->signature);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("version: %d.%02d\n", head->version / 100, head->version % 100);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (head->header_size != sizeof(struct vbt_header))</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("header size: 0x%x\n", head->header_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("VBT size: 0x%x\n", head->vbt_size);</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("VBT checksum: 0x%x\n", head->vbt_checksum);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (head->bdb_offset > (fo->size - sizeof(struct bdb_header))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid BDB offset\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ bdb = (const struct bdb_header *)</span><br><span style="color: hsl(120, 100%, 40%);">+ ((const char *)head + head->bdb_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (memcmp("BIOS_DATA_BLOCK ", bdb->signature, 16) != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("invalid BDB signature:%s\n", bdb->signature);</span><br><span style="color: hsl(120, 100%, 40%);">+ return;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ printt("BDB version: %u.%02u\n", bdb->version / 100,</span><br><span style="color: hsl(120, 100%, 40%);">+ bdb->version % 100);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void print_usage(const char *argv0, struct option *long_options)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("\nUsage:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("%s --<SOURCECMD> [filename] --<DESTCMD> [filename]\n\n", argv0);</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("SOURCECMD set the VBT source. Supported:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" %-10s: Legacy BIOS area at phys. memory 0xc0000\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ "inlegacy");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" %-10s: Read raw Intel VBT file\n", "invbt");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" %-10s: Read VBT from Intel Option ROM file\n\n", "inoprom");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("DESTCMD set the VBT destination. Supported:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" %-10s: Print VBT in human readable form\n", "outdump");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" %-10s: Write raw Intel VBT file\n", "outvbt");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" %-10s: Patch existing Intel Option ROM\n\n", "patchoprom");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("Supported arguments:\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ while (long_options[i].name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printf("\t-%c --%s %s\n", long_options[i].val,</span><br><span style="color: hsl(120, 100%, 40%);">+ long_options[i].name, long_options[i].has_arg ?</span><br><span style="color: hsl(120, 100%, 40%);">+ "<path>" : "");</span><br><span style="color: hsl(120, 100%, 40%);">+ i++;</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Open a VBIOS file, calculate the checksum and fix it */</span><br><span style="color: hsl(120, 100%, 40%);">+static int fix_vbios_checksum(const char *filename)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *fo = read_file(filename);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("%s open failed\n", filename);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fo->size < sizeof(optionrom_header_t))</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ optionrom_header_t *oh = (optionrom_header_t *)fo->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (oh->size * 512 > fo->size)</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* fix checksum */</span><br><span style="color: hsl(120, 100%, 40%);">+ oh->checksum = -(checksum_vbios(oh) - oh->checksum);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (write_file(filename, fo)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("%s write failed\n", filename);</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Return the VBT structure size in bytes */</span><br><span style="color: hsl(120, 100%, 40%);">+static size_t vbt_size(const struct fileobject *fo)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo || fo->size < sizeof(struct vbt_header))</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct vbt_header *head = (const struct vbt_header *)fo->data;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return head->vbt_size;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Patch an Intel Option ROM with new VBT.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Caller has to make sure that VBIOS and VBT are valid.</span><br><span style="color: hsl(120, 100%, 40%);">+ * Return 1 on error.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int patch_vbios(struct fileobject *fo,</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct fileobject *fo_vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ optionrom_header_t *oh = (optionrom_header_t *)fo->data;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct vbt_header *head;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *old_vbt = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ parse_vbios(fo, &old_vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (old_vbt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (oh->vbt_offset + vbt_size(old_vbt) == fo->size) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Located at the end of file - reduce file size */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fo->size < vbt_size(old_vbt))</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ fo = remalloc_fo(fo, fo->size - vbt_size(old_vbt));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to allocate memory\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ oh->vbt_offset = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (vbt_size(old_vbt) < vbt_size(fo_vbt)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* In the middle of the file - Remove old VBT */</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(fo->data + oh->vbt_offset, 0xff,</span><br><span style="color: hsl(120, 100%, 40%);">+ vbt_size(old_vbt));</span><br><span style="color: hsl(120, 100%, 40%);">+ oh->vbt_offset = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* New VBT overwrites existing one - Clear memory */</span><br><span style="color: hsl(120, 100%, 40%);">+ memset(fo->data + oh->vbt_offset, 0xff,</span><br><span style="color: hsl(120, 100%, 40%);">+ vbt_size(old_vbt));</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(old_vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!oh->vbt_offset) {</span><br><span style="color: hsl(120, 100%, 40%);">+ print("increasing VBIOS to append VBT\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((fo->size + vbt_size(fo_vbt)) >= 64 * KiB) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("VBT won't fit\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ oh->vbt_offset = fo->size;</span><br><span style="color: hsl(120, 100%, 40%);">+ fo = remalloc_fo(fo, fo->size + vbt_size(fo_vbt));</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to allocate memory\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ oh->size = (fo->size + 512 - 1) / 512;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ head = (struct vbt_header *)((u8 *)oh + oh->vbt_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(head, fo_vbt->data, vbt_size(fo_vbt));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span> }</span><br><span> </span><br><span> int main(int argc, char **argv)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- const void *ptr;</span><br><span style="color: hsl(0, 100%, 40%);">- int fd;</span><br><span style="color: hsl(0, 100%, 40%);">- off_t offset;</span><br><span style="color: hsl(0, 100%, 40%);">- if (argc == 2) {</span><br><span style="color: hsl(0, 100%, 40%);">- fd = open(argv[1], O_RDONLY);</span><br><span style="color: hsl(0, 100%, 40%);">- offset = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- } else {</span><br><span style="color: hsl(0, 100%, 40%);">- fd = open("/dev/mem", O_RDONLY);</span><br><span style="color: hsl(0, 100%, 40%);">- offset = 0xc0000;</span><br><span style="color: hsl(120, 100%, 40%);">+ int opt, option_index = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t has_input = 0, has_output = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ size_t dump = 0, in_legacy = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *in_vbt = NULL, *in_oprom = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *out_vbt = NULL, *patch_oprom = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ static struct option long_options[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ {"help", 0, 0, 'h'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"outdump", 0, 0, 'd'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"inlegacy", 0, 0, 'l'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"invbt", required_argument, 0, 'f'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"inoprom", required_argument, 0, 'o'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"outvbt", required_argument, 0, 'v'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"patchoprom", required_argument, 0, 'p'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {0, 0, 0, 0}</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ while ((opt = getopt_long(argc, argv, "hdlf:o:v:p:i",</span><br><span style="color: hsl(120, 100%, 40%);">+ long_options, &option_index)) != EOF) {</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (opt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'd':</span><br><span style="color: hsl(120, 100%, 40%);">+ dump = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ has_output = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'l':</span><br><span style="color: hsl(120, 100%, 40%);">+ in_legacy = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ has_input = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'f':</span><br><span style="color: hsl(120, 100%, 40%);">+ in_vbt = strdup(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ has_input = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'o':</span><br><span style="color: hsl(120, 100%, 40%);">+ in_oprom = strdup(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ has_input = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'v':</span><br><span style="color: hsl(120, 100%, 40%);">+ out_vbt = strdup(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ has_output = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'p':</span><br><span style="color: hsl(120, 100%, 40%);">+ patch_oprom = strdup(optarg);</span><br><span style="color: hsl(120, 100%, 40%);">+ has_output = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case '?':</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'h':</span><br><span style="color: hsl(120, 100%, 40%);">+ print_usage(argv[0], long_options);</span><br><span style="color: hsl(120, 100%, 40%);">+ exit(0);</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- if (fd < 0) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "open failed: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!has_input)</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("No input specified !\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!has_output)</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("No output specified !\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ if (argc < 2 || argc > 6 || !has_input || !has_output) {</span><br><span style="color: hsl(120, 100%, 40%);">+ print_usage(argv[0], long_options);</span><br><span> return 1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ptr = mmap(0, 65536, PROT_READ, MAP_SHARED, fd, offset);</span><br><span style="color: hsl(0, 100%, 40%);">- if (ptr == MAP_FAILED) {</span><br><span style="color: hsl(0, 100%, 40%);">- fprintf(stderr, "mmap failed: %s\n", strerror(errno));</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *fo;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (in_legacy)</span><br><span style="color: hsl(120, 100%, 40%);">+ fo = read_physmem(0xc0000);</span><br><span style="color: hsl(120, 100%, 40%);">+ else if (in_vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+ fo = read_file(in_vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ fo = read_file(in_oprom);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to read input file\n");</span><br><span> return 1;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- parse_vbios(ptr);</span><br><span style="color: hsl(0, 100%, 40%);">- close(fd);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct fileobject *vbt = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (in_legacy || in_oprom) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!is_valid_vbios(fo)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Invalid input file\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ parse_vbios(fo, &vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else</span><br><span style="color: hsl(120, 100%, 40%);">+ parse_vbt(fo, &vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!vbt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to find VBT.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!dump)</span><br><span style="color: hsl(120, 100%, 40%);">+ print_vbt(vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (dump) {</span><br><span style="color: hsl(120, 100%, 40%);">+ dump_vbt(vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (out_vbt) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (write_file(out_vbt, vbt))</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to write VBT\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ print("VBT written to %s\n", out_vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (patch_oprom) {</span><br><span style="color: hsl(120, 100%, 40%);">+ fo = read_file(patch_oprom);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!fo) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to read input file\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!is_valid_vbios(fo)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Invalid input file\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (patch_vbios(fo, vbt)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to patch VBIOS\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ if (write_file(patch_oprom, fo)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to write VBIOS\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(fo);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (fix_vbios_checksum(patch_oprom)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ printerr("Failed to fix checksum\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ print("VBIOS %s successfully patched\n", patch_oprom);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* cleanup */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (patch_oprom)</span><br><span style="color: hsl(120, 100%, 40%);">+ free(patch_oprom);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (out_vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+ free(out_vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (in_vbt)</span><br><span style="color: hsl(120, 100%, 40%);">+ free(in_vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (in_oprom)</span><br><span style="color: hsl(120, 100%, 40%);">+ free(in_oprom);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ free_fo(vbt);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> return 0;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://review.coreboot.org/18902">change 18902</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://review.coreboot.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://review.coreboot.org/18902"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: coreboot </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I8cbde042c7f5632f36648419becd23e248ba6f76 </div>
<div style="display:none"> Gerrit-Change-Number: 18902 </div>
<div style="display:none"> Gerrit-PatchSet: 17 </div>
<div style="display:none"> Gerrit-Owner: Patrick Rudolph <siro@das-labor.org> </div>
<div style="display:none"> Gerrit-Reviewer: Martin Roth <martinroth@google.com> </div>
<div style="display:none"> Gerrit-Reviewer: Nico Huber <nico.h@gmx.de> </div>
<div style="display:none"> Gerrit-Reviewer: Patrick Rudolph <patrick.rudolph@9elements.com> </div>
<div style="display:none"> Gerrit-Reviewer: Patrick Rudolph <siro@das-labor.org> </div>
<div style="display:none"> Gerrit-Reviewer: Paul Menzel <paulepanter@users.sourceforge.net> </div>
<div style="display:none"> Gerrit-Reviewer: Philipp Deppenwiese <zaolin.daisuki@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Samuel Holland <samuel@sholland.org> </div>
<div style="display:none"> Gerrit-Reviewer: Stefan Reinauer <stefan.reinauer@coreboot.org> </div>
<div style="display:none"> Gerrit-Reviewer: Vladimir Serbinenko <phcoder@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org> </div>