diff options
-rw-r--r-- | tools/.gitignore | 1 | ||||
-rw-r--r-- | tools/Makefile | 14 | ||||
-rw-r--r-- | tools/sloffs.c | 289 |
3 files changed, 299 insertions, 5 deletions
diff --git a/tools/.gitignore b/tools/.gitignore index e458413..e89174f 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1 +1,2 @@ gen_reloc_table +sloffs diff --git a/tools/Makefile b/tools/Makefile index 06cdaa7..a035960 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -12,7 +12,9 @@ include ../make.rules -all: gen_reloc_table +TARGETS = gen_reloc_table sloffs + +all: $(TARGETS) %.o: %.c $(HOSTCC) -W $(HOSTCFLAGS) -c $^ @@ -20,11 +22,13 @@ all: gen_reloc_table gen_reloc_table: gen_reloc_table.o $(HOSTCC) $(HOSTCFLAGS) -o $@ $^ -clean_here: - rm -f *.o gen_reloc_table +sloffs: sloffs.o + $(HOSTCC) $(HOSTCFLAGS) -o $@ $^ -clean: clean_here +clean_here: + rm -f *.o $(TARGETS) +clean: clean_here -distclean: clean_here +distclean: clean_here diff --git a/tools/sloffs.c b/tools/sloffs.c new file mode 100644 index 0000000..4b9ba5e --- /dev/null +++ b/tools/sloffs.c @@ -0,0 +1,289 @@ +/****************************************************************************** + * Copyright (c) 2008, 2009 Adrian Reber + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * Adrian Reber - initial implementation + *****************************************************************************/ + +#include <stdint.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> +#include <byteswap.h> +#include <getopt.h> + +#include <calculatecrc.h> + +#define VERSION 1 + +#ifdef _BIG_ENDIAN +#define cpu_to_be64(x) (x) +#define be64_to_cpu(x) (x) +#define be16_to_cpu(x) (x) +#define be32_to_cpu(x) (x) +#else +#define cpu_to_be64(x) bswap_64(x) +#define be64_to_cpu(x) bswap_64(x) +#define be16_to_cpu(x) bswap_16(x) +#define be32_to_cpu(x) bswap_32(x) +#endif + + +/* no board dependencies wanted here, let's hardcode SLOF's + * magic strings here */ + +#define FLASHFS_MAGIC "magic123" +#define FLASHFS_PLATFORM_MAGIC "JS2XBlade" +#define FLASHFS_PLATFORM_REVISION "1" + +/* there seems to be no structure defined anywhere in the code + * which resembles the actual sloffs/romfs file header; + * so defining it here for now */ + +struct sloffs { + uint64_t next; + uint64_t len; + uint64_t flags; + uint64_t data; + char *name; +}; + +static struct sloffs * +next_file(struct sloffs *sloffs) +{ + return (struct sloffs *)((unsigned char *)sloffs + + be64_to_cpu(sloffs->next)); +} + +static struct sloffs * +find_file(const void *data, const char *name) +{ + struct sloffs *sloffs = (struct sloffs *)data; + + for (;;) { + if (!strcmp((char *)&sloffs->name, name)) + return sloffs; + + if (be64_to_cpu(sloffs->next) == 0) + break; + sloffs = next_file(sloffs); + } + return NULL; +} + +static void +sloffs_dump(const void *data) +{ + struct stH *header; + struct sloffs *sloffs; + int i; + uint64_t crc; + uint64_t *datetmp; + + /* find the "header" file with all the information about + * the flash image */ + sloffs = find_file(data, "header"); + if (!sloffs) { + printf("sloffs file \"header\" not found. aborting...\n"); + return; + } + + header = (struct stH *)((unsigned char *)sloffs + + be64_to_cpu(sloffs->data)); + + if (memcmp(FLASHFS_MAGIC, header->magic, strlen(FLASHFS_MAGIC))) { + printf("sloffs magic not found. " + "probably not a valid SLOF flash image. aborting...\n"); + return; + } + printf(" Magic : %s\n", header->magic); + printf(" Platform : %s\n", header->platform_name); + printf(" Version : %s\n", header->version); + /* there is a bug in the date position; + * it should be at header->date, but it is at (header->date + 2) */ + printf(" Build Date : "); + datetmp = (void *)header->date; + if (be64_to_cpu(*datetmp)) { + printf("%04x", be16_to_cpu(*(uint16_t *)(header->date + 2))); + printf("-%02x", *(uint8_t *)(header->date + 4)); + printf("-%02x", *(uint8_t *)(header->date + 5)); + printf(" %02x:", *(uint8_t *)(header->date + 6)); + printf("%02x", *(uint8_t *)(header->date + 7)); + } else { + printf("N/A"); + } + printf("\n"); + printf(" Modify Date : "); + datetmp = (void *)header->mdate; + if (be64_to_cpu(*datetmp)) { + printf("%04x", be16_to_cpu(*(uint16_t *)(header->mdate + 2))); + printf("-%02x", *(uint8_t *)(header->mdate + 4)); + printf("-%02x", *(uint8_t *)(header->mdate + 5)); + printf(" %02x:", *(uint8_t *)(header->mdate + 6)); + printf("%02x", *(uint8_t *)(header->mdate + 7)); + } else { + printf("N/A"); + } + printf("\n"); + printf(" Image Length: %ld", be64_to_cpu(header->flashlen)); + printf(" (0x%lx) bytes\n", be64_to_cpu(header->flashlen)); + printf(" Revision : %s\n", header->platform_revision); + crc = be64_to_cpu(header->ui64CRC); + printf(" Header CRC : 0x%016lx\n", crc); + crc = be64_to_cpu(header->flashlen); + crc = *(uint64_t *)(unsigned char *)(data + crc - 8); + crc = be64_to_cpu(crc); + printf(" Image CRC : 0x%016lx\n", crc); + + /* count number of files */ + sloffs = (struct sloffs *)data; + i = 0; + for (;;) { + i++; + if (be64_to_cpu(sloffs->next) == 0) + break; + sloffs = next_file(sloffs); + } + printf(" Files : %d\n", i); +} + +static void +sloffs_list(const void *data) +{ + struct sloffs *sloffs = (struct sloffs *)data; + const char *name_header = "File Name"; + unsigned int i; + unsigned int max; + unsigned int line; + + /* find largest name */ + max = strlen(name_header);; + for (;;) { + if (max < strlen((char *)&sloffs->name)) + max = strlen((char *)&sloffs->name); + + if (be64_to_cpu(sloffs->next) == 0) + break; + sloffs = next_file(sloffs); + } + + /* have at least two spaces between name and size column */ + max += 2; + + /* header for listing */ + line = printf(" Offset "); + line += printf("%s", name_header); + for (i = 0; i < max - strlen(name_header); i++) + line += printf(" "); + line += printf("Size "); + line += printf("Flags\n"); + printf(" "); + for (i = 0; i <= line; i++) + printf("="); + printf("\n"); + + sloffs = (struct sloffs *)data; + for (;;) { + printf(" 0x%08lx", (void *)sloffs - (void *)data); + printf(" %s", (char *)&sloffs->name); + for (i = 0; i < max - strlen((char *)&sloffs->name); i++) + printf(" "); + + printf("%07ld ", be64_to_cpu(sloffs->len)); + printf("(0x%06lx)", be64_to_cpu(sloffs->len)); + printf(" 0x%08lx\n", be64_to_cpu(sloffs->flags)); + + if (be64_to_cpu(sloffs->next) == 0) + break; + sloffs = next_file(sloffs); + } +} + +static void +usage(void) +{ + printf("sloffs lists or changes a SLOF flash image\n\n"); + printf("Usage:\n"); + printf(" sloffs [OPTION]... [FILE]\n\n"); + printf("Options:\n"); + printf(" -h, --help show this help, then exit\n"); + printf(" -l, --list list all files in the flash image\n"); + printf(" -v, --version print the version, then exit\n"); + printf(" -d, --dump dump the information from the header\n"); + printf("\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int fd; + void *file; + struct stat stat; + const struct option loption[] = { + { "help", 0, NULL, 'h' }, + { "list", 0, NULL, 'l' }, + { "version", 0, NULL, 'v' }, + { "dump", 0, NULL, 'd' }, + { 0, 0, 0, 0 } + }; + const char *soption = "dhlv"; + int c; + char mode = 0; + + for (;;) { + c = getopt_long(argc, argv, soption, loption, NULL); + if (c == -1) + break; + switch (c) { + case 'l': + mode = 'l'; + break; + case 'v': + printf("sloffs (version %d)\n", VERSION); + exit(0); + case 'd': + mode = 'd'; + break; + case 'h': + default: + usage(); + } + } + + if (optind >= argc) + usage(); + + fd = open(argv[optind], O_RDONLY); + + if (fd == -1) { + perror(argv[optind]); + exit(1); + } + + fstat(fd, &stat); + file = mmap(NULL, stat.st_size, PROT_READ, MAP_SHARED, fd, 0); + + switch (mode) { + case 'l': + sloffs_list(file); + break; + case 'd': + sloffs_dump(file); + break; + } + + munmap(file, stat.st_size); + close(fd); + return 0; +} |