[coreboot-gerrit] Patch set updated for coreboot: cbfstool: decompress stage files on extraction

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Sat Oct 24 22:19:44 CEST 2015


Aaron Durbin (adurbin at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/12174

-gerrit

commit 154bbdab42b97f506d7ef3fddb83bb5cdcd8ceb4
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Fri Oct 23 17:42:32 2015 -0500

    cbfstool: decompress stage files on extraction
    
    In order to actually do something useful with the
    resulting file after being extracted decompress stage
    files' content. That way one can interrogate the
    resulting w/o having to decompress on the fly.
    
    Note: This change will cause an unexpected change to
    Chrome OS devices which package up individual stage
    files in the RW slots w/o using cbfs. The result will
    be that compressed stages are now decompressed.
    
    Longer term is to turn these files into proper ELF
    files on the way out.
    
    Change-Id: I373ecc7b924ea21af8d891a8cb8f01fd64467360
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 util/cbfstool/cbfs_image.c | 92 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 88 insertions(+), 4 deletions(-)

diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c
index bf01c96..6f9b2ec 100644
--- a/util/cbfstool/cbfs_image.c
+++ b/util/cbfstool/cbfs_image.c
@@ -657,6 +657,73 @@ struct cbfs_file *cbfs_get_entry(struct cbfs_image *image, const char *name)
 	return NULL;
 }
 
+static int cbfs_stage_decompress(struct buffer *buff)
+{
+	struct buffer reader;
+	struct buffer writer;
+	struct cbfs_stage metadata;
+	char *orig_buffer;
+	char *new_buffer;
+	size_t new_buff_sz;
+	decomp_func_ptr decompress;
+
+	buffer_clone(&reader, buff);
+
+	/* The stage metadata is in little endian. */
+	metadata.compression = xdr_le.get32(&reader);
+	metadata.entry = xdr_le.get64(&reader);
+	metadata.load = xdr_le.get64(&reader);
+	metadata.len = xdr_le.get32(&reader);
+	metadata.memlen = xdr_le.get32(&reader);
+
+	if (metadata.compression == CBFS_COMPRESS_NONE)
+		return 0;
+
+	decompress = decompression_function(metadata.compression);
+	if (decompress == NULL)
+		return -1;
+
+	orig_buffer = buffer_get(buff);
+
+	/* This can be too big of a buffer needed, but there's no current
+	 * field indicating decompressed size of data. */
+	new_buff_sz = metadata.memlen + sizeof(struct cbfs_stage);
+	new_buffer = calloc(1, new_buff_sz);
+
+	if (decompress(orig_buffer + sizeof(struct cbfs_stage),
+			(int)(buffer_size(buff) - sizeof(struct cbfs_stage)),
+			new_buffer + sizeof(struct cbfs_stage),
+			(int)(new_buff_sz - sizeof(struct cbfs_stage)),
+			&new_buff_sz)) {
+		ERROR("Couldn't decompress stage.\n");
+		free(new_buffer);
+		return -1;
+	}
+
+	/* Include correct size for full stage info. */
+	new_buff_sz += sizeof(struct cbfs_stage);
+	buffer_init(buff, buff->name, new_buffer, new_buff_sz);
+	buffer_clone(&writer, buff);
+	/* Set size to 0 to please xdr. */
+	buffer_set_size(&writer, 0);
+
+	/* True decompressed size is just the data size -- no metadata. */
+	metadata.len = new_buff_sz - sizeof(struct cbfs_stage);
+	/* Stage is not compressed. */
+	metadata.compression = CBFS_COMPRESS_NONE;
+
+	/* Write back out the stage metadata. */
+	xdr_le.put32(&writer, metadata.compression);
+	xdr_le.put32(&writer, metadata.entry);
+	xdr_le.put32(&writer, metadata.load);
+	xdr_le.put32(&writer, metadata.len);
+	xdr_le.put32(&writer, metadata.memlen);
+
+	free(orig_buffer);
+
+	return 0;
+}
+
 int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 		      const char *filename)
 {
@@ -689,6 +756,8 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 		WARN("Payloads are extracted in SELF format.\n");
 	}
 
+	buffer_init(&buffer, strdup("(cbfs_export_entry)"), NULL, 0);
+
 	buffer.data = malloc(decompressed_size);
 	buffer.size = decompressed_size;
 	if (decompress(CBFS_SUBHEADER(entry), ntohl(entry->len),
@@ -696,15 +765,30 @@ int cbfs_export_entry(struct cbfs_image *image, const char *entry_name,
 		ERROR("decompression failed for %s\n", entry_name);
 		return -1;
 	}
-	buffer.name = strdup("(cbfs_export_entry)");
+
+	/*
+	 * The stage metadata is never compressed proper for cbfs_stage
+	 * files. The contents of the stage data can be though. Therefore
+	 * one has to do a second pass for stages to potentially decompress
+	 * the stage data to make it more meaningful.
+	 */
+	if (ntohl(entry->type) == CBFS_COMPONENT_STAGE) {
+		if (cbfs_stage_decompress(&buffer)) {
+			ERROR("Failed to write %s into %s.\n",
+			      entry_name, filename);
+			buffer_delete(&buffer);
+			return -1;
+		}
+	}
+
 	if (buffer_write_file(&buffer, filename) != 0) {
 		ERROR("Failed to write %s into %s.\n",
 		      entry_name, filename);
-		free(buffer.name);
+		buffer_delete(&buffer);
 		return -1;
 	}
-	free(buffer.data);
-	free(buffer.name);
+
+	buffer_delete(&buffer);
 	INFO("Successfully dumped the file to: %s\n", filename);
 	return 0;
 }



More information about the coreboot-gerrit mailing list