[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 02:04:33 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 ee603b7964b8685b40c6d2ef907e598d914385df
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