diff options
-rw-r--r-- | util/cbfstool/cbfs_image.c | 8 | ||||
-rw-r--r-- | util/cbfstool/cbfstool.c | 108 |
2 files changed, 73 insertions, 43 deletions
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c index 05fdc8aae6..7b8da42a6a 100644 --- a/util/cbfstool/cbfs_image.c +++ b/util/cbfstool/cbfs_image.c @@ -267,14 +267,6 @@ int cbfs_legacy_image_create(struct cbfs_image *image, bootblock_offset, bootblock->size, header_offset, sizeof(image->header), entries_offset); - // Adjust legacy top-aligned address to ROM offset. - if (IS_TOP_ALIGNED_ADDRESS(entries_offset)) - entries_offset = size + (int32_t)entries_offset; - if (IS_TOP_ALIGNED_ADDRESS(bootblock_offset)) - bootblock_offset = size + (int32_t)bootblock_offset; - if (IS_TOP_ALIGNED_ADDRESS(header_offset)) - header_offset = size + (int32_t)header_offset; - DEBUG("cbfs_create_image: (real offset) bootblock=0x%x, " "header=0x%x, entries_offset=0x%x\n", bootblock_offset, header_offset, entries_offset); diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 6936d57ece..d6f4e98621 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -48,15 +48,30 @@ static struct param { uint64_t u64val; uint32_t type; uint32_t baseaddress; + /* + * Input can be negative. It will be transformed to offset from start of region (if + * negative) and stored in baseaddress. + */ + long long int baseaddress_input; uint32_t baseaddress_assigned; uint32_t loadaddress; uint32_t headeroffset; + /* + * Input can be negative. It will be transformed to offset from start of region (if + * negative) and stored in baseaddress. + */ + long long int headeroffset_input; uint32_t headeroffset_assigned; uint32_t entrypoint; uint32_t size; uint32_t alignment; uint32_t pagesize; uint32_t cbfsoffset; + /* + * Input can be negative. It will be transformed to corresponding region offset (if + * negative) and stored in baseaddress. + */ + long long int cbfsoffset_input; uint32_t cbfsoffset_assigned; uint32_t arch; uint32_t padding; @@ -103,8 +118,7 @@ static bool region_is_modern_cbfs(const char *region) /* * Converts between offsets from the start of the specified image region and - * "top-aligned" offsets from the top of the entire boot media. See comment - * below for convert_to_from_top_aligned() about forming addresses. + * "top-aligned" offsets from the top of the entire boot media. */ static unsigned convert_to_from_absolute_top_aligned( const struct buffer *region, unsigned offset) @@ -117,25 +131,27 @@ static unsigned convert_to_from_absolute_top_aligned( } /* - * Converts between offsets from the start of the specified image region and - * "top-aligned" offsets from the top of the image region. Works in either - * direction: pass in one type of offset and receive the other type. - * N.B. A top-aligned offset is always a positive number, and should not be - * confused with a top-aligned *address*, which is its arithmetic inverse. */ -static unsigned convert_to_from_top_aligned(const struct buffer *region, - unsigned offset) + * This function takes offset value which represents the offset from one end of the region and + * converts it to offset from the other end of the region. offset is expected to be positive. + */ +static int convert_region_offset(unsigned int offset, uint32_t *region_offset) { - assert(region); + size_t size; - /* Cover the situation where a negative base address is given by the - * user. Callers of this function negate it, so it'll be a positive - * number smaller than the region. - */ - if ((offset > 0) && (offset < region->size)) { - return region->size - offset; + if (param.size) { + size = param.size; + } else { + assert(param.image_region); + size = param.image_region->size; } - return convert_to_from_absolute_top_aligned(region, offset); + if (size < offset) { + ERROR("Cannot convert region offset (size=0x%zx, offset=0x%x)\n", size, offset); + return 1; + } + + *region_offset = size - offset; + return 0; } static int do_cbfs_locate(int32_t *cbfs_addr, size_t metadata_size, @@ -243,10 +259,6 @@ static int cbfs_add_integer_component(const char *name, goto done; } - if (IS_TOP_ALIGNED_ADDRESS(offset)) - offset = convert_to_from_top_aligned(param.image_region, - -offset); - header = cbfs_create_file_header(CBFS_TYPE_RAW, buffer.size, name); if (cbfs_add_entry(&image, &buffer, offset, header, 0) != 0) { @@ -435,10 +447,7 @@ static int add_topswap_bootblock(struct buffer *buffer, uint32_t *offset) buffer_clone(buffer, &new_bootblock); /* Update the location (offset) of bootblock in the region */ - *offset = convert_to_from_top_aligned(param.image_region, - buffer_size(buffer)); - - return 0; + return convert_region_offset(buffer_size(buffer), offset); } static int cbfs_add_component(const char *filename, @@ -520,11 +529,9 @@ static int cbfs_add_component(const char *filename, /* to the cbfs file and therefore set the position */ /* the real beginning of the data. */ if (type == CBFS_TYPE_STAGE) - attrs->position = htonl(offset + - sizeof(struct cbfs_stage)); + attrs->position = htonl(offset - sizeof(struct cbfs_stage)); else if (type == CBFS_TYPE_SELF) - attrs->position = htonl(offset + - sizeof(struct cbfs_payload)); + attrs->position = htonl(offset - sizeof(struct cbfs_payload)); else attrs->position = htonl(offset); } @@ -565,8 +572,7 @@ static int cbfs_add_component(const char *filename, } if (IS_TOP_ALIGNED_ADDRESS(offset)) - offset = convert_to_from_top_aligned(param.image_region, - -offset); + offset = convert_to_from_absolute_top_aligned(param.image_region, -offset); if (cbfs_add_entry(&image, &buffer, offset, header, len_align) != 0) { ERROR("Failed to add '%s' into ROM image.\n", filename); free(header); @@ -1345,6 +1351,32 @@ static struct option long_options[] = { {NULL, 0, 0, 0 } }; +static int get_region_offset(long long int offset, uint32_t *region_offset) +{ + /* If offset is not negative, no transformation required. */ + if (offset >= 0) { + *region_offset = offset; + return 0; + } + + /* Calculate offset from start of region. */ + return convert_region_offset(-offset, region_offset); +} + +static int calculate_region_offsets(void) +{ + int ret = 0; + + if (param.baseaddress_assigned) + ret |= get_region_offset(param.baseaddress_input, ¶m.baseaddress); + if (param.headeroffset_assigned) + ret |= get_region_offset(param.headeroffset_input, ¶m.headeroffset); + if (param.cbfsoffset_assigned) + ret |= get_region_offset(param.cbfsoffset_input, ¶m.cbfsoffset); + + return ret; +} + static int dispatch_command(struct command command) { if (command.accesses_region) { @@ -1382,6 +1414,13 @@ static int dispatch_command(struct command command) return 1; } } + + /* + * Once image region is read, input offsets can be adjusted accordingly if the + * inputs are provided as negative integers i.e. offsets from end of region. + */ + if (calculate_region_offsets()) + return 1; } if (command.function()) { @@ -1598,7 +1637,7 @@ int main(int argc, char **argv) param.source_region = optarg; break; case 'b': - param.baseaddress = strtoul(optarg, &suffix, 0); + param.baseaddress_input = strtoll(optarg, &suffix, 0); if (!*optarg || (suffix && *suffix)) { ERROR("Invalid base address '%s'.\n", optarg); @@ -1649,8 +1688,7 @@ int main(int argc, char **argv) param.bootblock = optarg; break; case 'H': - param.headeroffset = strtoul( - optarg, &suffix, 0); + param.headeroffset_input = strtoll(optarg, &suffix, 0); if (!*optarg || (suffix && *suffix)) { ERROR("Invalid header offset '%s'.\n", optarg); @@ -1686,7 +1724,7 @@ int main(int argc, char **argv) param.force_pow2_pagesize = 1; break; case 'o': - param.cbfsoffset = strtoul(optarg, &suffix, 0); + param.cbfsoffset_input = strtoll(optarg, &suffix, 0); if (!*optarg || (suffix && *suffix)) { ERROR("Invalid cbfs offset '%s'.\n", optarg); |