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>
			
			
This commit is contained in:
		
				
					committed by
					
						
						Patrick Georgi
					
				
			
			
				
	
			
			
			
						parent
						
							1e83536f8c
						
					
				
				
					commit
					f44319c12d
				
			@@ -23,6 +23,7 @@
 | 
				
			|||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.h>
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
#include <sys/stat.h>
 | 
					#include <sys/stat.h>
 | 
				
			||||||
#include <sys/types.h>
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,6 +60,9 @@ struct crc_t {
 | 
				
			|||||||
#define BIMG_OP_EXEC_NO_RETURN	(0x2 << 0)
 | 
					#define BIMG_OP_EXEC_NO_RETURN	(0x2 << 0)
 | 
				
			||||||
#define BIMG_DATA_CHECKSUM	(0x1 << 4)
 | 
					#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 MAX_RECORD_BYTES	0x8000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CRC_16
 | 
					#define CRC_16
 | 
				
			||||||
@@ -140,8 +144,7 @@ static uint16_t crc_16(uint16_t crc, void *void_buf, size_t size)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct crc_t crc_type = {
 | 
				
			||||||
static struct crc_t crc_type = {
 | 
					 | 
				
			||||||
#if defined(CRC_16)
 | 
					#if defined(CRC_16)
 | 
				
			||||||
	.crc_f = crc_16,
 | 
						.crc_f = crc_16,
 | 
				
			||||||
	.crc_init = 0,
 | 
						.crc_init = 0,
 | 
				
			||||||
@@ -211,20 +214,141 @@ static int write_final(FILE *out, struct bimg_header *hdr)
 | 
				
			|||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void usage(FILE *f)
 | 
					static const char *help_message =
 | 
				
			||||||
{
 | 
						"Usage: bimgtool <input> [<output> <base-address>]\n"
 | 
				
			||||||
	fprintf(f,
 | 
					 | 
				
			||||||
		"Usage: bimgtool <input> <output> <base-address>\n"
 | 
					 | 
				
			||||||
	"\n"
 | 
						"\n"
 | 
				
			||||||
		"bimgtool is a simple tool which generates boot images in the "
 | 
						"This is a simple tool which generates and verifies boot images in\n"
 | 
				
			||||||
		"BIMG format used in systems designed by Imagination "
 | 
						"the BIMG format, used in systems designed by Imagination\n"
 | 
				
			||||||
		"Technologies, for example the Pistachio SoC. This version of the "
 | 
						"Technologies, for example the Pistachio SoC. This version of the\n"
 | 
				
			||||||
		"tool generates BIMG version 1.0 images.\n"
 | 
						"tool works with BIMG images version %d.\n"
 | 
				
			||||||
	"\n"
 | 
						"\n"
 | 
				
			||||||
	"  input:          The binary file to be converted to a BIMG\n"
 | 
						"  input:          The binary file to be converted to a BIMG\n"
 | 
				
			||||||
 | 
						"                  or verified\n"
 | 
				
			||||||
	"  output:         The name of the output BIMG file\n"
 | 
						"  output:         The name of the output BIMG file\n"
 | 
				
			||||||
	"  base-address:   The address in memory at which you wish the "
 | 
						"  base-address:   The address in memory at which you wish the "
 | 
				
			||||||
		"input binary to be loaded.\n");
 | 
						"                  input binary to be loaded.\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void usage(FILE *f)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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[])
 | 
					int main(int argc, char *argv[])
 | 
				
			||||||
@@ -236,18 +360,16 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
		.magic = BIMG_MAGIC,
 | 
							.magic = BIMG_MAGIC,
 | 
				
			||||||
		.ver_major = crc_type.ver_major,
 | 
							.ver_major = crc_type.ver_major,
 | 
				
			||||||
		.ver_minor = crc_type.ver_minor,
 | 
							.ver_minor = crc_type.ver_minor,
 | 
				
			||||||
		.flags = BIMG_OP_EXEC_NO_RETURN | BIMG_DATA_CHECKSUM,
 | 
							.flags = BIMG_FLAGS,
 | 
				
			||||||
		.data_crc = crc_type.crc_init,
 | 
							.data_crc = crc_type.crc_init,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (argc != 4) {
 | 
						if ((argc != 4) && (argc != 2)) {
 | 
				
			||||||
		usage(stderr);
 | 
							usage(stderr);
 | 
				
			||||||
		goto out_err;
 | 
							goto out_err;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	in_filename = argv[1];
 | 
						in_filename = argv[1];
 | 
				
			||||||
	out_filename = argv[2];
 | 
					 | 
				
			||||||
	hdr.entry_addr = strtoul(argv[3], NULL, 16);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	in_file = fopen(in_filename, "r");
 | 
						in_file = fopen(in_filename, "r");
 | 
				
			||||||
	if (!in_file) {
 | 
						if (!in_file) {
 | 
				
			||||||
@@ -255,6 +377,12 @@ int main(int argc, char *argv[])
 | 
				
			|||||||
		goto out_err;
 | 
							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");
 | 
						out_file = fopen(out_filename, "w");
 | 
				
			||||||
	if (!out_file) {
 | 
						if (!out_file) {
 | 
				
			||||||
		error("Failed to open output file '%s'\n", out_filename);
 | 
							error("Failed to open output file '%s'\n", out_filename);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user