diff options
author | Michael Karcher <flashrom@mkarcher.dialup.fu-berlin.de> | 2010-01-14 16:23:23 +0100 |
---|---|---|
committer | Luc Verhaegen <libv@skynet.be> | 2010-01-14 16:23:23 +0100 |
commit | 703c6b95bc2f6de2a3a0a4a600c48fa37359752a (patch) | |
tree | e36369371775a72ea115ede586b1d563ba60be6f | |
parent | a794e6bab69dda9df7895f6343605df18634fd1e (diff) |
Add AMI SLAB extractor.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | ami_slab.c | 153 |
3 files changed, 160 insertions, 1 deletions
@@ -1,5 +1,6 @@ bios_extract lh5_test +ami_slab bcpvpd *.o *~ @@ -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); +} |