summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>2010-01-14 16:23:23 +0100
committerLuc Verhaegen <libv@skynet.be>2010-01-14 16:23:23 +0100
commit703c6b95bc2f6de2a3a0a4a600c48fa37359752a (patch)
treee36369371775a72ea115ede586b1d563ba60be6f
parenta794e6bab69dda9df7895f6343605df18634fd1e (diff)
Add AMI SLAB extractor.
-rw-r--r--.gitignore1
-rw-r--r--Makefile7
-rw-r--r--ami_slab.c153
3 files changed, 160 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 9825689..49ddf84 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
bios_extract
lh5_test
+ami_slab
bcpvpd
*.o
*~
diff --git a/Makefile b/Makefile
index b17af78..d381c1d 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ MAKE = make
CFLAGS = -g -fpack-struct -Wall -O0
CC = gcc
-all: bios_extract bcpvpd
+all: bios_extract bcpvpd ami_slab
BIOS_EXTRACT_OBJS = lh5_extract.o ami.o award.o phoenix.o bios_extract.o
bios_extract: $(BIOS_EXTRACT_OBJS)
@@ -12,6 +12,10 @@ BCPVPD_OBJS = lzss_extract.o bcpvpd.o
bcpvpd: $(BCPVPD_OBJS)
$(CC) $(CFLAGS) $(BCPVPD_OBJS) -o bcpvpd
+AMISLAB_OBJS = ami_slab.o
+ami_slab: $(AMISLAB_OBJS)
+ $(CC) $(CFLAGS) $(AMISLAB_OBJS) -o ami_slab
+
# just here to easily verify the functionality of the lh5 routine
LH5_TEST_OBJS = lh5_extract.o lh5_test.o
lh5_test: $(LH5_TEST_OBJS)
@@ -22,3 +26,4 @@ clean:
rm -f bios_extract
rm -f bcpvpd
rm -f lh5_test
+ rm -f ami_slab
diff --git a/ami_slab.c b/ami_slab.c
new file mode 100644
index 0000000..4a47651
--- /dev/null
+++ b/ami_slab.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2010 Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+struct slabentry {
+ uint32_t destaddr;
+ uint32_t length_flag;
+};
+
+struct slabheader {
+ uint16_t entries;
+ uint16_t headersize;
+ struct slabentry blocks[0];
+};
+
+struct nameentry {
+ uint8_t segtype;
+ uint16_t dtor_offset;
+ char name[0];
+};
+
+int slabextract(const unsigned char *buffer, int bufferlen)
+{
+ const struct slabheader *h = (const void *) buffer;
+ const unsigned char *listpointer;
+ const unsigned char *datapointer;
+ int i, count;
+
+
+ count = le16toh(h->entries);
+ printf("%d entries\n", count);
+
+ /* FIXME: Is the 37 really constant? */
+ if (8 * count + 37 < le32toh(h->headersize)) {
+ listpointer = buffer + 8 * count + 37;
+ printf("Name Tp ");
+ } else {
+ listpointer = NULL; /* No names present */
+ printf("Name ");
+ }
+
+ datapointer = buffer + le32toh(h->headersize);
+
+ printf("LoadAddr size initialized\n");
+
+ for (i = 0; i < count; i++) {
+ const struct slabentry *block;
+ char filename[25];
+ uint32_t len;
+ int has_data;
+
+ if (listpointer) {
+ const struct nameentry *entry = (const void *) listpointer;
+ block = (const void *) (buffer + le16toh(entry->dtor_offset));
+ sprintf(filename, "%.20s.bin", entry->name);
+ listpointer += strlen(entry->name) + 4;
+ printf("%-15s %02x ", entry->name, entry->segtype);
+ } else {
+ block = (const void *) (buffer + 4 + 8 * i);
+ sprintf(filename, "block%02d.bin", i);
+ printf("block%02d ", i);
+ }
+
+ len = le32toh(block->length_flag);
+ if (len & 0x80000000)
+ has_data = 1;
+ else
+ has_data = 0;
+ len &= 0x7fffffff;
+
+ printf("%08x %8d\t %s\n", le32toh(block->destaddr), len,
+ has_data ? "yes" : "no");
+
+ if (has_data) {
+ int outfd = open(filename, O_WRONLY | O_CREAT | O_TRUNC);
+ if (outfd != -1) {
+ if (write(outfd, datapointer, len) != len)
+ fprintf(stderr, "Can't write %s: %s\n", filename,
+ strerror(errno));
+ close(outfd);
+ } else
+ fprintf(stderr, "Can't create output file %s: %s\n", filename,
+ strerror(errno));
+ datapointer += len;
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int infd;
+ unsigned char *InputBuffer;
+ int InputBufferSize;
+
+ if (argc != 2) {
+ printf("usage: %s <input file>\n", argv[0]);
+ return 1;
+ }
+
+ infd = open(argv[1], O_RDONLY);
+ if (infd < 0) {
+ fprintf(stderr, "Error: Failed to open %s: %s\n",
+ argv[1], strerror(errno));
+ return 1;
+ }
+
+ InputBufferSize = lseek(infd, 0, SEEK_END);
+ if (InputBufferSize < 0) {
+ fprintf(stderr, "Error: Failed to lseek \"%s\": %s\n",
+ argv[1], strerror(errno));
+ return 1;
+ }
+
+ InputBuffer = mmap(NULL, InputBufferSize, PROT_READ, MAP_PRIVATE, infd, 0);
+ if (InputBuffer < 0) {
+ fprintf(stderr, "Error: Failed to mmap %s: %s\n",
+ argv[1], strerror(errno));
+ return 1;
+ }
+
+ if (InputBufferSize < 0x52) { /* probably incorrect */
+ fprintf(stderr, "Error: \"%s\" is too small to be a SLAB file.\n",
+ argv[1]);
+ return 1;
+ }
+
+ return slabextract(InputBuffer, InputBufferSize);
+}