Aaron Durbin (adurbin@chromium.org) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/13479
-gerrit
commit 95b7a687ff5cdfd7157076d880f92427ee5467e1 Author: Aaron Durbin adurbin@chromium.org Date: Tue Jan 26 17:08:56 2016 -0600
util/cbfstool: add 'compact' command
While assembling CBFS images within the RW slots on Chrome OS machines the current approach is to 'cbfstool copy' from the RO CBFS to each RW CBFS. Additional fixups are required such as removing unneeded files from the RW CBFS (e.g. verstage) as well as removing and adding back files with the proper arguments (FSP relocation as well as romstage XIP relocation). This ends up leaving holes in the RW CBFS. To speed up RW CBFS slot hashing it's beneficial to pack all non-empty files together at the beginning of the CBFS. Therefore, provide the 'compact' command which bubbles all the empty entries to the end of the CBFS.
Before: Name Offset Type Size cmos_layout.bin 0x0 cmos_layout 1164 dmic-2ch-48khz-16b.bin 0x500 raw 2920 dmic-2ch-48khz-32b.bin 0x10c0 raw 2920 nau88l25-2ch-48khz-24b.bin 0x1c80 raw 84 ssm4567-render-2ch-48khz-24b.bin 0x1d40 raw 84 ssm4567-capture-4ch-48khz-32b.bin 0x1e00 raw 84 vbt.bin 0x1ec0 optionrom 4096 spd.bin 0x2f00 spd 1536 config 0x3540 raw 6839 revision 0x5040 raw 606 font.bin 0x5300 raw 1919 (57892 after LZMA decompression) vbgfx.bin 0x5ac0 raw 13048 (936784 after LZMA decompression) locales 0x8e00 raw 2 locale_en.bin 0x8e40 raw 10742 (180754 after LZMA decompression) u-boot.dtb 0xb880 mrc_cache 4081 (empty) 0xc8c0 null 44532 fallback/ramstage 0x17740 stage 86597 (empty) 0x2c9c0 null 54052 fallback/payload 0x39d80 payload 74309 cpu_microcode_blob.bin 0x4c000 microcode 94208 (empty) 0x63080 null 3657496
After: Name Offset Type Size cmos_layout.bin 0x0 cmos_layout 1164 dmic-2ch-48khz-16b.bin 0x500 raw 2920 dmic-2ch-48khz-32b.bin 0x10c0 raw 2920 nau88l25-2ch-48khz-24b.bin 0x1c80 raw 84 ssm4567-render-2ch-48khz-24b.bin 0x1d40 raw 84 ssm4567-capture-4ch-48khz-32b.bin 0x1e00 raw 84 vbt.bin 0x1ec0 optionrom 4096 spd.bin 0x2f00 spd 1536 config 0x3540 raw 6839 revision 0x5040 raw 606 font.bin 0x5300 raw 1919 (57892 after LZMA decompression) vbgfx.bin 0x5ac0 raw 13048 (936784 after LZMA decompression) locales 0x8e00 raw 2 locale_en.bin 0x8e40 raw 10742 (180754 after LZMA decompression) u-boot.dtb 0xb880 mrc_cache 4081 fallback/ramstage 0xc8c0 stage 86597 fallback/payload 0x21b40 payload 74309 cpu_microcode_blob.bin 0x33dc0 microcode 94208 (empty) 0x4ae40 null 3756376
Change-Id: I8311172d71a2ccfccab384f8286cf9f21a17dec9 Signed-off-by: Aaron Durbin adurbin@chromium.org --- util/cbfstool/cbfs_image.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ util/cbfstool/cbfs_image.h | 4 +++ util/cbfstool/cbfstool.c | 10 ++++++ 3 files changed, 97 insertions(+)
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c index 8425095..325b4b8 100644 --- a/util/cbfstool/cbfs_image.c +++ b/util/cbfstool/cbfs_image.c @@ -440,6 +440,89 @@ int cbfs_copy_instance(struct cbfs_image *image, struct buffer *dst) return 0; }
+static size_t cbfs_file_entry_size(const struct cbfs_file *f) +{ + return ntohl(f->offset) + ntohl(f->len); +} + +int cbfs_compact_instance(struct cbfs_image *image) +{ + assert(image); + + struct cbfs_file *prev; + struct cbfs_file *cur; + + /* The prev entry will always be an empty entry. */ + prev = NULL; + + /* + * Note: this function does not honor alignment or fixed location files. + * It's behavior is akin to cbfs_copy_instance() in that it expects + * the caller to understand the ramifications of compacting a + * fragmented CBFS image. + */ + + for (cur = cbfs_find_first_entry(image); + cur && cbfs_is_valid_entry(image, cur); + cur = cbfs_find_next_entry(image, cur)) { + size_t prev_size; + size_t cur_size; + void *empty_file_and_data; + uint32_t type = htonl(cur->type); + + /* Current entry is empty. Kepp track of it. */ + if ((type == htonl(CBFS_COMPONENT_NULL)) || + (type == htonl(CBFS_COMPONENT_DELETED))) { + prev = cur; + continue; + } + + /* Need to ensure the previous entry is an empty one. */ + if (prev == NULL) + continue; + + /* At this point prev is an empty entry. Put the non-empty + * file in prev's location. Then add a new emptry entry. This + * essentialy bubbles empty entries to the end. */ + + prev_size = cbfs_file_entry_size(prev); + cur_size = cbfs_file_entry_size(cur); + + /* Save empty file contents temporarily. */ + empty_file_and_data = malloc(prev_size); + assert(empty_file_and_data); + memcpy(empty_file_and_data, prev, prev_size); + + /* Copy the non-empty file over the empty file. */ + memcpy(prev, cur, cur_size); + + /* + * Get location of next file to copy in the empty one. Note + * that since prev was overwritten with the non-empty file + * it needs to be used to obtain the new current (which is + * the empty file). + */ + cur = cbfs_find_next_entry(image, prev); + + memcpy(cur, empty_file_and_data, prev_size); + + free(empty_file_and_data); + + /* Merge any potential empty entries together. */ + cbfs_walk(image, cbfs_merge_empty_entry, NULL); + + /* + * Since current switched to an empty file keep track of it. + * Even if any empty files were merged the empty entry still + * starts at previously calculated location. + */ + prev = cur; + } + + + return 0; +} + int cbfs_image_delete(struct cbfs_image *image) { if (image == NULL) diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h index 38510d2..0d7877a 100644 --- a/util/cbfstool/cbfs_image.h +++ b/util/cbfstool/cbfs_image.h @@ -76,6 +76,10 @@ int cbfs_image_from_buffer(struct cbfs_image *out, struct buffer *in, * Will not succeed on new-style images without a master header. */ int cbfs_copy_instance(struct cbfs_image *image, struct buffer *dst);
+/* Compact a fragmented CBFS image by placing all the non-empty files at the + * beginning of the image. Returns 0 on success, otherwise non-zero. */ +int cbfs_compact_instance(struct cbfs_image *image); + /* Releases the CBFS image. Returns 0 on success, otherwise non-zero. */ int cbfs_image_delete(struct cbfs_image *image);
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c index 13a9956..af68385 100644 --- a/util/cbfstool/cbfstool.c +++ b/util/cbfstool/cbfstool.c @@ -1054,6 +1054,15 @@ static int cbfs_copy(void) return cbfs_copy_instance(&src_image, param.image_region); }
+static int cbfs_compact(void) +{ + struct cbfs_image image; + if (cbfs_image_from_buffer(&image, param.image_region, + param.headeroffset)) + return 1; + return cbfs_compact_instance(&image); +} + static const struct command commands[] = { {"add", "H:r:f:n:t:c:b:a:vA:gh?", cbfs_add, true, true}, {"add-flat-binary", "H:r:f:n:l:e:c:b:vA:gh?", cbfs_add_flat_binary, @@ -1064,6 +1073,7 @@ static const struct command commands[] = { true, true}, {"add-int", "H:r:i:n:b:vgh?", cbfs_add_integer, true, true}, {"add-master-header", "H:r:vh?", cbfs_add_master_header, true, true}, + {"compact", "r:h?", cbfs_compact, true, true}, {"copy", "r:R:h?", cbfs_copy, true, true}, {"create", "M:r:s:B:b:H:o:m:vh?", cbfs_create, true, true}, {"hashcbfs", "r:R:A:vh?", cbfs_hash, true, true},