Patrick Georgi (pgeorgi@google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10935
-gerrit
commit e80a3fe38c5fd065559366a4ffc55a686adeb9e2 Author: Daisuke Nojiri dnojiri@chromium.org Date: Thu Jul 9 15:07:45 2015 -0700
cbfstool: allow compression at file header level
Currently, compression is only allowed at subheader level (e.g. cbfs_stage, cbfs_payload_segment). This change adds compression field to each file's header so that any cbfs file can be compressed.
With the necessary additions in coreboot and libpayload, the following sample code can load a compressed file:
const char *name = "foo.bmp"; struct cbfs_file *file = cbfs_get_file(media, name); void *dst = malloc(ntohl(file->uncompressed_size)); dst = cbfs_get_file_content(media, name, type, file, dst);
cbfs_stage and cbfs_payload_segment continue to support compression at subheader level because stages and payloads have to be decompressed to the load address, which is stored in the subheader. For these, file level compression should be turned off.
Change-Id: I9a00ec99dfc68ffb2771bb4a3cc5ba6ba8a326f4 Signed-off-by: Daisuke Nojiri dnojiri@chromium.org Signed-off-by: Patrick Georgi pgeorgi@chromium.org --- util/cbfstool/cbfs.h | 3 +++ util/cbfstool/cbfs_image.c | 9 ++++++++- util/cbfstool/cbfs_image.h | 3 ++- util/cbfstool/cbfstool.c | 40 ++++++++++++++++++++++++++++++++++------ 4 files changed, 47 insertions(+), 8 deletions(-)
diff --git a/util/cbfstool/cbfs.h b/util/cbfstool/cbfs.h index c53ac0e..c32ce2d 100644 --- a/util/cbfstool/cbfs.h +++ b/util/cbfstool/cbfs.h @@ -85,6 +85,9 @@ _Static_assert(sizeof(struct cbfs_file) == 24, "cbfs_file size mismatch");
struct cbfs_file_attributes { uint32_t len; + /* whole file compression format. 0 if no compression. */ + uint32_t compression; + uint32_t decompressed_size; } __PACKED;
struct cbfs_stage { diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c index 9724543..c4b4c01 100644 --- a/util/cbfstool/cbfs_image.c +++ b/util/cbfstool/cbfs_image.c @@ -537,7 +537,8 @@ static int cbfs_add_entry_at(struct cbfs_image *image, }
int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer, - const char *name, uint32_t type, uint32_t content_offset) + const char *name, uint32_t type, uint32_t content_offset, + enum comp_algo compression, uint32_t decompressed_size) { assert(image); assert(buffer); @@ -587,6 +588,10 @@ int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer, buffer->size); cbfs_create_empty_entry(entry, buffer->size, name); entry->type = htonl(type); + struct cbfs_file_attributes *attr = + CBFS_FILE_ATTRIBUTES(entry); + attr->compression = htonl(compression); + attr->decompressed_size = htonl(decompressed_size); memcpy(CBFS_SUBHEADER(entry), buffer->data, buffer->size); if (verbose) cbfs_print_entry_info(image, entry, stderr); @@ -1047,6 +1052,8 @@ int cbfs_create_empty_entry(struct cbfs_file *entry,
struct cbfs_file_attributes *attr = CBFS_FILE_ATTRIBUTES(entry); attr->len = sizeof(struct cbfs_file_attributes); + attr->compression = 0; + attr->decompressed_size = 0; return 0; }
diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h index cb2935b..7da7621 100644 --- a/util/cbfstool/cbfs_image.h +++ b/util/cbfstool/cbfs_image.h @@ -93,7 +93,8 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name, * Never pass this function a top-aligned address: convert it to an offset. * Returns 0 on success, otherwise non-zero. */ int cbfs_add_entry(struct cbfs_image *image, struct buffer *buffer, - const char *name, uint32_t type, uint32_t content_offset); + const char *name, uint32_t type, uint32_t content_offset, + enum comp_algo algo, uint32_t decompressed_size);
/* Removes an entry from CBFS image. Returns 0 on success, otherwise non-zero. */ int cbfs_remove_entry(struct cbfs_image *image, const char *name); diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index b6a486f..1637089 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -76,6 +76,8 @@ static struct param { bool show_immutable; int fit_empty_entries; enum comp_algo compression; + enum comp_algo file_compression; + uint32_t decompressed_size; /* for linux payloads */ char *initrd; char *cmdline; @@ -83,6 +85,7 @@ static struct param { /* All variables not listed are initialized as zero. */ .arch = CBFS_ARCHITECTURE_UNKNOWN, .compression = CBFS_COMPRESS_NONE, + .file_compression = CBFS_COMPRESS_NONE, .headeroffset = ~0, .region_name = SECTION_NAME_PRIMARY_CBFS, }; @@ -150,8 +153,8 @@ static int cbfs_add_integer_component(const char *name, offset = convert_to_from_top_aligned(param.image_region, -offset);
- if (cbfs_add_entry(&image, &buffer, name, CBFS_COMPONENT_RAW, offset) != - 0) { + if (cbfs_add_entry(&image, &buffer, name, CBFS_COMPONENT_RAW, offset, + 0, 0) != 0) { ERROR("Failed to add %llu into ROM image as '%s'.\n", (long long unsigned)u64val, name); goto done; @@ -212,7 +215,9 @@ static int cbfs_add_component(const char *filename, offset = convert_to_from_top_aligned(param.image_region, -offset);
- if (cbfs_add_entry(&image, &buffer, name, type, offset) != 0) { + if (cbfs_add_entry(&image, &buffer, name, type, offset, + param.file_compression, + param.decompressed_size) != 0) { ERROR("Failed to add '%s' into ROM image.\n", filename); buffer_delete(&buffer); return 1; @@ -222,6 +227,29 @@ static int cbfs_add_component(const char *filename, return 0; }
+static int cbfstool_convert_raw(struct buffer *buffer, unused uint32_t *offset) +{ + char *compressed; + int compressed_size; + + comp_func_ptr compress = compression_function(param.compression); + if (!compress) + return -1; + compressed = calloc(buffer->size, 1); + + if (compress(buffer->data, buffer->size, + compressed, &compressed_size)) { + WARN("Compression failed - disabled\n"); + } else { + param.file_compression = param.compression; + free(buffer->data); + buffer->data = compressed; + param.decompressed_size = buffer->size; + buffer->size = compressed_size; + } + return 0; +} + static int cbfstool_convert_mkstage(struct buffer *buffer, uint32_t *offset) { struct buffer output; @@ -289,7 +317,7 @@ static int cbfs_add(void) param.type, param.baseaddress, param.headeroffset, - NULL); + cbfstool_convert_raw); }
static int cbfs_add_stage(void) @@ -735,7 +763,7 @@ static bool cbfs_is_legacy_format(struct buffer *buffer) }
static const struct command commands[] = { - {"add", "H:r:f:n:t:b:vh?", cbfs_add, true, true}, + {"add", "H:r:f:n:t:c:b:vh?", cbfs_add, true, true}, {"add-flat-binary", "H:r:f:n:l:e:c:b:vh?", cbfs_add_flat_binary, true, true}, {"add-payload", "H:r:f:n:t:c:b:C:I:vh?", cbfs_add_payload, true, true}, @@ -850,7 +878,7 @@ static void usage(char *name) " -h Display this help message\n\n" "COMMANDs:\n" " add [-r image,regions] -f FILE -n NAME -t TYPE \\n" - " [-b base-address] " + " [-c compression] [-b base-address] " "Add a component\n" " add-payload [-r image,regions] -f FILE -n NAME \\n" " [-c compression] [-b base-address] "