Patrick Georgi (pgeorgi@google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9452
-gerrit
commit a4cff8dcc41ba20064b3c87ffce6e3b57a350f46 Author: Vadim Bendebury vbendeb@chromium.org Date: Tue Nov 4 16:17:33 2014 -0800
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 --- util/bimgtool/bimgtool.c | 164 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 146 insertions(+), 18 deletions(-)
diff --git a/util/bimgtool/bimgtool.c b/util/bimgtool/bimgtool.c index acbfdfb..b7b6491 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);