diff options
author | Vadim Bendebury <vbendeb@chromium.org> | 2014-11-04 16:17:33 -0800 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2015-04-10 12:03:35 +0200 |
commit | f44319c12d4dc228cc193233b422c4afafe480bd (patch) | |
tree | bb165d6e0e7382fb430a2eee41097fee87261d72 | |
parent | 1e83536f8ca529b88bdd75108a2f991d5c93c6b3 (diff) |
util/bimgtool: Add verification mode
When only one argument is passed on the command line, consider this
argument the name of the BIMG formatted file, and verify its
integrity.
Update the help/usage text to match new behavior.
BRANCH=none
BUG=none
TEST=when the corrupted coreboot BIMG image is passed as the only
argument, this utility reports the problem. With the build fixed,
the check passes without errors (the second invocation below).
$ build/util/bimgtool/bimgtool /build/urara/firmware/coreboot.rom.serial
Data header CRC mismatch at 0
$ build/util/bimgtool/bimgtool /build/urara/firmware/coreboot.rom.serial
$
Change-Id: I9f0672caa38e3d27917471fc5137ede4ca466e9a
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 3e631c311dbf2fb04714e437f95c41629155527f
Original-Change-Id: Ie56f87f99838891d8e341d7989c614efbcabe0cd
Original-Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/227522
Original-Reviewed-by: Zdenko Pulitika <zdenko.pulitika@imgtec.com>
Original-Tested-by: Ionela Voinescu <ionela.voinescu@imgtec.com>
Reviewed-on: http://review.coreboot.org/9452
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
-rw-r--r-- | util/bimgtool/bimgtool.c | 164 |
1 files changed, 146 insertions, 18 deletions
diff --git a/util/bimgtool/bimgtool.c b/util/bimgtool/bimgtool.c index acbfdfb758..b7b64912f0 100644 --- a/util/bimgtool/bimgtool.c +++ b/util/bimgtool/bimgtool.c @@ -23,6 +23,7 @@ #include <stdint.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/stat.h> #include <sys/types.h> @@ -59,6 +60,9 @@ struct crc_t { #define BIMG_OP_EXEC_NO_RETURN (0x2 << 0) #define BIMG_DATA_CHECKSUM (0x1 << 4) +/* Typical use case for this utility. */ +#define BIMG_FLAGS (BIMG_OP_EXEC_NO_RETURN | BIMG_DATA_CHECKSUM) + #define MAX_RECORD_BYTES 0x8000 #define CRC_16 @@ -140,8 +144,7 @@ static uint16_t crc_16(uint16_t crc, void *void_buf, size_t size) } - -static struct crc_t crc_type = { +static const struct crc_t crc_type = { #if defined(CRC_16) .crc_f = crc_16, .crc_init = 0, @@ -211,20 +214,141 @@ static int write_final(FILE *out, struct bimg_header *hdr) return 0; } +static const char *help_message = + "Usage: bimgtool <input> [<output> <base-address>]\n" + "\n" + "This is a simple tool which generates and verifies boot images in\n" + "the BIMG format, used in systems designed by Imagination\n" + "Technologies, for example the Pistachio SoC. This version of the\n" + "tool works with BIMG images version %d.\n" + "\n" + " input: The binary file to be converted to a BIMG\n" + " or verified\n" + " output: The name of the output BIMG file\n" + " base-address: The address in memory at which you wish the " + " input binary to be loaded.\n"; + static void usage(FILE *f) { - fprintf(f, - "Usage: bimgtool <input> <output> <base-address>\n" - "\n" - "bimgtool is a simple tool which generates boot images in the " - "BIMG format used in systems designed by Imagination " - "Technologies, for example the Pistachio SoC. This version of the " - "tool generates BIMG version 1.0 images.\n" - "\n" - " input: The binary file to be converted to a BIMG\n" - " output: The name of the output BIMG file\n" - " base-address: The address in memory at which you wish the " - "input binary to be loaded.\n"); + fprintf(f, help_message, crc_type.ver_major); +} + +static int verify_file(FILE *f) +{ + struct bimg_header file_header; + struct bimg_data_header data_header; + char *file_pointer; + char *file_data; + struct stat buf; + int data_size; + int fd = fileno(f); + uint32_t data_crc = crc_type.crc_init; + uint32_t crc_result; + + if (fread(&file_header, 1, sizeof(struct bimg_header), f) != + sizeof(struct bimg_header)) { + perror("Problems trying to read input file header\n"); + return -1; + } + + if (fstat(fd, &buf)) { + perror("Problems trying to stat input file\n"); + return -1; + } + + if (file_header.magic != BIMG_MAGIC) { + fprintf(stderr, "Wrong magic value %#x\n", file_header.magic); + return -1; + } + + crc_result = crc_type.crc_f(crc_type.crc_init, &file_header, + sizeof(file_header) - + sizeof(file_header.crc)); + if (file_header.crc != crc_result) { + fprintf(stderr, "File header CRC mismatch\n"); + return -1; + } + + if ((file_header.data_size + sizeof(struct bimg_header)) > + buf.st_size) { + fprintf(stderr, "Data size too big: %d > %d\n", + file_header.data_size, buf.st_size); + return -1; + } + + if (file_header.ver_major != crc_type.ver_major) { + fprintf(stderr, "Image version mismatch: %d\n", + file_header.ver_major); + return -1; + } + + if ((file_header.flags & BIMG_FLAGS) != BIMG_FLAGS) { + fprintf(stderr, "Unexpected file header flags: %#x\n", + file_header.flags); + return -1; + } + + if (file_header.ver_minor != crc_type.ver_minor) { + fprintf(stderr, + "Minor version mismatch: %d, will try anyways\n", + file_header.ver_minor); + } + + data_size = file_header.data_size; + file_pointer = malloc(data_size); + if (!file_pointer) { + fprintf(stderr, "Failed to allocate %d bytes\n", + file_header.data_size); + return -1; + } + + if (fread(file_pointer, 1, data_size, f) != data_size) { + fprintf(stderr, "Failed to read %d bytes\n", data_size); + free(file_pointer); + return -1; + } + + file_data = file_pointer; + while (data_size > 0) { + memcpy(&data_header, file_data, sizeof(data_header)); + + /* Check the data block header integrity. */ + crc_result = crc_type.crc_f(crc_type.crc_init, &data_header, + sizeof(data_header) - + sizeof(data_header.crc)); + if (data_header.crc != crc_result) { + fprintf(stderr, "Data header CRC mismatch at %d\n", + file_header.data_size - data_size); + free(file_pointer); + return -1; + } + + /* + * Add the block data to the CRC stream, the last block size + * will be zero. + */ + file_data += sizeof(data_header); + data_crc = crc_type.crc_f(data_crc, + file_data, data_header.size); + + data_size -= data_header.size + sizeof(data_header); + file_data += data_header.size; + } + + if (data_size) { + fprintf(stderr, "File size mismatch\n"); + free(file_pointer); + return -1; + } + + if (data_crc != file_header.data_crc) { + fprintf(stderr, "File data CRC mismatch\n"); + free(file_pointer); + return -1; + } + + free(file_pointer); + return 0; } int main(int argc, char *argv[]) @@ -236,18 +360,16 @@ int main(int argc, char *argv[]) .magic = BIMG_MAGIC, .ver_major = crc_type.ver_major, .ver_minor = crc_type.ver_minor, - .flags = BIMG_OP_EXEC_NO_RETURN | BIMG_DATA_CHECKSUM, + .flags = BIMG_FLAGS, .data_crc = crc_type.crc_init, }; - if (argc != 4) { + if ((argc != 4) && (argc != 2)) { usage(stderr); goto out_err; } in_filename = argv[1]; - out_filename = argv[2]; - hdr.entry_addr = strtoul(argv[3], NULL, 16); in_file = fopen(in_filename, "r"); if (!in_file) { @@ -255,6 +377,12 @@ int main(int argc, char *argv[]) goto out_err; } + if (argc == 2) + return verify_file(in_file); + + out_filename = argv[2]; + hdr.entry_addr = strtoul(argv[3], NULL, 16); + out_file = fopen(out_filename, "w"); if (!out_file) { error("Failed to open output file '%s'\n", out_filename); |