[coreboot-gerrit] New patch to review for coreboot: util/cbfstool: add 'compact' command

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Wed Jan 27 00:18:36 CET 2016


Aaron Durbin (adurbin at 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 at 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 at 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},



More information about the coreboot-gerrit mailing list