diff options
-rw-r--r-- | util/cbfstool/cbfs_image.c | 40 | ||||
-rw-r--r-- | util/cbfstool/cbfs_image.h | 6 | ||||
-rw-r--r-- | util/cbfstool/cbfstool.c | 58 |
3 files changed, 69 insertions, 35 deletions
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c index 0230d8032e..621a35d16f 100644 --- a/util/cbfstool/cbfs_image.c +++ b/util/cbfstool/cbfs_image.c @@ -267,7 +267,8 @@ int cbfs_image_create(struct cbfs_image *image, return 0; } -int cbfs_image_from_file(struct cbfs_image *image, const char *filename) +int cbfs_image_from_file(struct cbfs_image *image, + const char *filename, uint32_t offset) { void *header_loc; @@ -275,7 +276,9 @@ int cbfs_image_from_file(struct cbfs_image *image, const char *filename) return -1; DEBUG("read_cbfs_image: %s (%zd bytes)\n", image->buffer.name, image->buffer.size); - header_loc = cbfs_find_header(image->buffer.data, image->buffer.size); + header_loc = cbfs_find_header(image->buffer.data, + image->buffer.size, + offset); if (!header_loc) { ERROR("%s does not have CBFS master header.\n", filename); cbfs_image_delete(image); @@ -767,21 +770,41 @@ int cbfs_walk(struct cbfs_image *image, cbfs_entry_callback callback, return count; } -struct cbfs_header *cbfs_find_header(char *data, size_t size) +static int cbfs_header_valid(struct cbfs_header *header, size_t size) +{ + if ((ntohl(header->magic) == CBFS_HEADER_MAGIC) && + ((ntohl(header->version) == CBFS_HEADER_VERSION1) || + (ntohl(header->version) == CBFS_HEADER_VERSION2)) && + (ntohl(header->romsize) <= size) && + (ntohl(header->offset) < ntohl(header->romsize))) + return 1; + return 0; +} + +struct cbfs_header *cbfs_find_header(char *data, size_t size, + uint32_t forced_offset) { size_t offset; int found = 0; int32_t rel_offset; struct cbfs_header *header, *result = NULL; + if (forced_offset < (size - sizeof(struct cbfs_header))) { + /* Check if the forced header is valid. */ + header = (struct cbfs_header *)(data + forced_offset); + if (cbfs_header_valid(header, size)) + return header; + return NULL; + } + // Try finding relative offset of master header at end of file first. rel_offset = *(int32_t *)(data + size - sizeof(int32_t)); offset = size + rel_offset; DEBUG("relative offset: %#zx(-%#zx), offset: %#zx\n", (size_t)rel_offset, (size_t)-rel_offset, offset); + if (offset >= size - sizeof(*header) || - ntohl(((struct cbfs_header *)(data + offset))->magic) != - CBFS_HEADER_MAGIC) { + !cbfs_header_valid((struct cbfs_header *)(data + offset), size)) { // Some use cases append non-CBFS data to the end of the ROM. DEBUG("relative offset seems wrong, scanning whole image...\n"); offset = 0; @@ -789,13 +812,8 @@ struct cbfs_header *cbfs_find_header(char *data, size_t size) for (; offset + sizeof(*header) < size; offset++) { header = (struct cbfs_header *)(data + offset); - if (ntohl(header->magic) !=(CBFS_HEADER_MAGIC)) - continue; - if (ntohl(header->version) != CBFS_HEADER_VERSION1 && - ntohl(header->version) != CBFS_HEADER_VERSION2) { - // Probably not a real CBFS header? + if (!cbfs_header_valid(header, size)) continue; - } if (!found++) result = header; } diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h index 0a05eb2841..2c1be3da1c 100644 --- a/util/cbfstool/cbfs_image.h +++ b/util/cbfstool/cbfs_image.h @@ -52,7 +52,8 @@ int cbfs_image_create(struct cbfs_image *image, int32_t entries_offset); /* Loads a CBFS image from file. Returns 0 on success, otherwise non-zero. */ -int cbfs_image_from_file(struct cbfs_image *image, const char *filename); +int cbfs_image_from_file(struct cbfs_image *image, + const char *filename, uint32_t offset); /* Writes a CBFS image into file. Returns 0 on success, otherwise non-zero. */ int cbfs_image_write_file(struct cbfs_image *image, const char *filename); @@ -106,7 +107,8 @@ int cbfs_walk(struct cbfs_image *image, cbfs_entry_callback callback, void *arg) * NULL (including when multiple headers were found). If there is a X86 ROM * style signature (pointer at 0xfffffffc) found in ROM, it will be selected as * the only header.*/ -struct cbfs_header *cbfs_find_header(char *data, size_t size); +struct cbfs_header *cbfs_find_header(char *data, size_t size, + uint32_t forced_offset); /* Returns the first cbfs_file entry in CBFS image by CBFS header (no matter if * the entry has valid content or not), otherwise NULL. */ diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 9c611197cf..20e5e0c78a 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -66,6 +66,7 @@ static struct param { /* All variables not listed are initialized as zero. */ .arch = CBFS_ARCHITECTURE_UNKNOWN, .algo = CBFS_COMPRESS_NONE, + .headeroffset = ~0, }; typedef int (*convert_buffer_t)(struct buffer *buffer, uint32_t *offset); @@ -73,7 +74,8 @@ typedef int (*convert_buffer_t)(struct buffer *buffer, uint32_t *offset); static int cbfs_add_integer_component(const char *cbfs_name, const char *name, uint64_t u64val, - uint32_t offset) { + uint32_t offset, + uint32_t headeroffset) { struct cbfs_image image; struct buffer buffer; int i, ret = 1; @@ -89,7 +91,7 @@ static int cbfs_add_integer_component(const char *cbfs_name, for (i = 0; i < 8; i++) buffer.data[i] = (u64val >> i*8) & 0xff; - if (cbfs_image_from_file(&image, cbfs_name) != 0) { + if (cbfs_image_from_file(&image, cbfs_name, headeroffset) != 0) { ERROR("Could not load ROM image '%s'.\n", cbfs_name); buffer_delete(&buffer); return 1; @@ -119,6 +121,7 @@ static int cbfs_add_component(const char *cbfs_name, const char *name, uint32_t type, uint32_t offset, + uint32_t headeroffset, convert_buffer_t convert) { struct cbfs_image image; @@ -139,7 +142,7 @@ static int cbfs_add_component(const char *cbfs_name, return 1; } - if (cbfs_image_from_file(&image, cbfs_name) != 0) { + if (cbfs_image_from_file(&image, cbfs_name, headeroffset) != 0) { ERROR("Could not load ROM image '%s'.\n", cbfs_name); return 1; } @@ -249,6 +252,7 @@ static int cbfs_add(void) param.name, param.type, param.baseaddress, + param.headeroffset, NULL); } @@ -259,6 +263,7 @@ static int cbfs_add_stage(void) param.name, CBFS_COMPONENT_STAGE, param.baseaddress, + param.headeroffset, cbfstool_convert_mkstage); } @@ -269,6 +274,7 @@ static int cbfs_add_payload(void) param.name, CBFS_COMPONENT_PAYLOAD, param.baseaddress, + param.headeroffset, cbfstool_convert_mkpayload); } @@ -289,6 +295,7 @@ static int cbfs_add_flat_binary(void) param.name, CBFS_COMPONENT_PAYLOAD, param.baseaddress, + param.headeroffset, cbfstool_convert_mkflatpayload); } @@ -297,7 +304,8 @@ static int cbfs_add_integer(void) return cbfs_add_integer_component(param.cbfs_name, param.name, param.u64val, - param.baseaddress); + param.baseaddress, + param.headeroffset); } static int cbfs_remove(void) @@ -309,7 +317,8 @@ static int cbfs_remove(void) return 1; } - if (cbfs_image_from_file(&image, param.cbfs_name) != 0) { + if (cbfs_image_from_file(&image, param.cbfs_name, + param.headeroffset) != 0) { ERROR("Could not load ROM image '%s'.\n", param.cbfs_name); return 1; @@ -433,7 +442,8 @@ static int cbfs_locate(void) return 1; } - if (cbfs_image_from_file(&image, param.cbfs_name) != 0) { + if (cbfs_image_from_file(&image, param.cbfs_name, + param.headeroffset) != 0) { ERROR("Failed to load %s.\n", param.cbfs_name); return 1; } @@ -469,7 +479,8 @@ static int cbfs_locate(void) static int cbfs_print(void) { struct cbfs_image image; - if (cbfs_image_from_file(&image, param.cbfs_name) != 0) { + if (cbfs_image_from_file(&image, param.cbfs_name, + param.headeroffset) != 0) { ERROR("Could not load ROM image '%s'.\n", param.cbfs_name); return 1; @@ -494,7 +505,8 @@ static int cbfs_extract(void) return 1; } - if (cbfs_image_from_file(&image, param.cbfs_name) != 0) { + if (cbfs_image_from_file(&image, param.cbfs_name, + param.headeroffset) != 0) { ERROR("Could not load ROM image '%s'.\n", param.cbfs_name); result = 1; @@ -523,7 +535,8 @@ static int cbfs_update_fit(void) return 1; } - if (cbfs_image_from_file(&image, param.cbfs_name) != 0) { + if (cbfs_image_from_file(&image, param.cbfs_name, + param.headeroffset) != 0) { ERROR("Could not load ROM image '%s'.\n", param.cbfs_name); return 1; @@ -538,17 +551,17 @@ static int cbfs_update_fit(void) } static const struct command commands[] = { - {"add", "f:n:t:b:vh?", cbfs_add}, - {"add-payload", "f:n:t:c:b:vh?C:I:", cbfs_add_payload}, - {"add-stage", "f:n:t:c:b:S:vh?", cbfs_add_stage}, - {"add-flat-binary", "f:n:l:e:c:b:vh?", cbfs_add_flat_binary}, - {"add-int", "i:n:b:vh?", cbfs_add_integer}, - {"remove", "n:vh?", cbfs_remove}, + {"add", "H;f:n:t:b:vh?", cbfs_add}, + {"add-payload", "H:f:n:t:c:b:vh?C:I:", cbfs_add_payload}, + {"add-stage", "H:f:n:t:c:b:S:vh?", cbfs_add_stage}, + {"add-flat-binary", "H:f:n:l:e:c:b:vh?", cbfs_add_flat_binary}, + {"add-int", "H:i:n:b:vh?", cbfs_add_integer}, + {"remove", "H:n:vh?", cbfs_remove}, {"create", "s:B:b:H:a:o:m:vh?", cbfs_create}, - {"locate", "f:n:P:a:Tvh?", cbfs_locate}, - {"print", "vh?", cbfs_print}, - {"extract", "n:f:vh?", cbfs_extract}, - {"update-fit", "n:x:vh?", cbfs_update_fit}, + {"locate", "H:f:n:P:a:Tvh?", cbfs_locate}, + {"print", "H:vh?", cbfs_print}, + {"extract", "H:n:f:vh?", cbfs_extract}, + {"update-fit", "H:n:x:vh?", cbfs_update_fit}, }; static struct option long_options[] = { @@ -583,9 +596,10 @@ static void usage(char *name) ("cbfstool: Management utility for CBFS formatted ROM images\n\n" "USAGE:\n" " %s [-h]\n" " %s FILE COMMAND [-v] [PARAMETERS]...\n\n" "OPTIONs:\n" - " -T Output top-aligned memory address\n" - " -v Provide verbose output\n" - " -h Display this help message\n\n" + " -H header_offset Do not search for header, use this offset\n" + " -T Output top-aligned memory address\n" + " -v Provide verbose output\n" + " -h Display this help message\n\n" "COMMANDs:\n" " add -f FILE -n NAME -t TYPE [-b base-address] " "Add a component\n" |