diff options
author | Adrian Reber <adrian@lisas.de> | 2016-07-25 17:08:53 +1000 |
---|---|---|
committer | Alexey Kardashevskiy <aik@ozlabs.ru> | 2016-07-27 15:56:26 +1000 |
commit | 54f14f328b311537bd53df505aa61cc7c7c86d48 (patch) | |
tree | d19301724fa1626a63976131ff604a69da7552e1 /tools | |
parent | e290ccc93282bc2b5432f8d075c1b490091345c5 (diff) | |
download | SLOF-54f14f328b311537bd53df505aa61cc7c7c86d48.zip SLOF-54f14f328b311537bd53df505aa61cc7c7c86d48.tar.gz SLOF-54f14f328b311537bd53df505aa61cc7c7c86d48.tar.bz2 |
tools: added initial version of sloffs
sloffs is a tool to get information about the flash images
created by the SLOF build process and it will also be able
to modify those flash images
(cherry picked from commit ec9f4acc3977a81289704fae0ad8bb62f3a93ab1)
Cherry picked from https://lisas.de/~adrian/slof/slof.git/
Signed-off-by: Adrian Reber <adrian@lisas.de>
[aik: squashed e1e52adb5, e6369bb10b, 4d6f40c47d, 82532ec08; fixed warnings]
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Diffstat (limited to 'tools')
-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; +} |