[coreboot-gerrit] Patch set updated for coreboot: libpayload: allow compression at file header level

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Thu Sep 17 18:46:53 CET 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10938

-gerrit

commit 076277f82204b8644c6dc03bd126f8045d416d57
Author: Daisuke Nojiri <dnojiri at chromium.org>
Date:   Thu Jul 9 15:07:45 2015 -0700

    libpayload: allow compression at file header level
    
    Decompression is handled transparently within cbfs_get_file_content:
    
    	const char *name = "foo.bmp";
    	void *dst = cbfs_get_file_content(media, name, type, NULL);
    
    To keep things consistent, a couple of API changes were necessary:
    - cbfs_get_file_content always returns a copy of the data, even for
      uncompressed files. It's the callers responsibility to free the
      memory.
    - same for cbfs_load_payload and cbfs_find_file.
    - cbfs_load_optionrom doesn't take a "dest" argument anymore but always
      returns a copy of the data, for compressed and uncompressed files.
      Like with cbfs_get_file_content, the caller is responsible to free it.
      It also decompresses based on extended file attributes instead of the
      cbfs_optionrom subheader that libpayload specified but that (AFAIK)
      nobody ever used, given that there's not even tooling for that.
    
    Change-Id: If959e3dff9b93c6ae45ec7358afcc7840bc17218
    Signed-off-by: Daisuke Nojiri <dnojiri at chromium.org>
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
---
 payloads/libpayload/include/cbfs.h      |  2 +-
 payloads/libpayload/include/cbfs_core.h | 18 ++++++++++++++--
 payloads/libpayload/libcbfs/cbfs.c      | 37 +++++++--------------------------
 payloads/libpayload/libcbfs/cbfs_core.c | 33 ++++++++++++++++++++++++++++-
 4 files changed, 56 insertions(+), 34 deletions(-)

diff --git a/payloads/libpayload/include/cbfs.h b/payloads/libpayload/include/cbfs.h
index 59c31db..f57dce0 100644
--- a/payloads/libpayload/include/cbfs.h
+++ b/payloads/libpayload/include/cbfs.h
@@ -59,7 +59,7 @@ void *cbfs_find_file(const char *name, int type);
 
 int cbfs_execute_stage(struct cbfs_media *media, const char *name);
 void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
-			  uint16_t device, void * dest);
+			  uint16_t device);
 void *cbfs_load_payload(struct cbfs_media *media, const char *name);
 void *cbfs_load_stage(struct cbfs_media *media, const char *name);
 
diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h
index a2ee744..3878e55 100644
--- a/payloads/libpayload/include/cbfs_core.h
+++ b/payloads/libpayload/include/cbfs_core.h
@@ -53,6 +53,7 @@
 #include <endian.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <stdlib.h>
 
 /** These are standard values for the known compression
     alogrithms that coreboot knows about for stages and
@@ -141,6 +142,7 @@ struct cbfs_file {
  * 0xff. Support both. */
 #define CBFS_FILE_ATTR_TAG_UNUSED 0
 #define CBFS_FILE_ATTR_TAG_UNUSED2 0xffffffff
+#define CBFS_FILE_ATTR_TAG_COMPRESSION 0x42435a4c
 
 /* The common fields of extended cbfs file attributes.
    Attributes are expected to start with tag/len, then append their
@@ -152,6 +154,14 @@ struct cbfs_file_attribute {
 	uint8_t data[0];
 } __attribute__((packed));
 
+struct cbfs_file_attr_compression {
+	uint32_t tag;
+	uint32_t len;
+	/* whole file compression format. 0 if no compression. */
+	uint32_t compression;
+	uint32_t decompressed_size;
+} __attribute__((packed));
+
 /* Given a cbfs_file, return the first file attribute, or NULL. */
 struct cbfs_file_attribute *cbfs_file_first_attr(struct cbfs_file *file);
 
@@ -237,10 +247,14 @@ struct cbfs_media {
 	int (*close)(struct cbfs_media *media);
 };
 
-/* returns pointer to a file entry inside CBFS or NULL */
+/* returns pointer to a file entry inside CBFS or NULL on error */
 struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name);
 
-/* returns pointer to file content inside CBFS after if type is correct */
+/*
+ * Returns pointer to a copy of the file content or NULL on error.
+ * If the file is compressed, data will be decompressed.
+ * The caller owns the returned memory.
+ */
 void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
 			    int type, size_t *sz);
 
diff --git a/payloads/libpayload/libcbfs/cbfs.c b/payloads/libpayload/libcbfs/cbfs.c
index 3e614b6..49e4941 100644
--- a/payloads/libpayload/libcbfs/cbfs.c
+++ b/payloads/libpayload/libcbfs/cbfs.c
@@ -79,41 +79,14 @@ static void tohex16(unsigned int val, char* dest)
 }
 
 void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
-			  uint16_t device, void *dest)
+			  uint16_t device)
 {
 	char name[17] = "pciXXXX,XXXX.rom";
-	struct cbfs_optionrom *orom;
-	uint8_t *src;
 
 	tohex16(vendor, name+3);
 	tohex16(device, name+8);
 
-	orom = (struct cbfs_optionrom *)
-		cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM, NULL);
-
-	if (orom == NULL)
-		return NULL;
-
-	/* They might have specified a dest address. If so, we can decompress.
-	 * If not, there's not much hope of decompressing or relocating the rom.
-	 * in the common case, the expansion rom is uncompressed, we
-	 * pass 0 in for the dest, and all we have to do is find the rom and
-	 * return a pointer to it.
-	 */
-
-	/* BUG: the cbfstool is (not yet) including a cbfs_optionrom header */
-	src = (uint8_t*)orom; // + sizeof(struct cbfs_optionrom);
-
-	if (! dest)
-		return src;
-
-	if (!cbfs_decompress(ntohl(orom->compression),
-			     src,
-			     dest,
-			     ntohl(orom->len)))
-		return NULL;
-
-	return dest;
+	return cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM, NULL);
 }
 
 void * cbfs_load_stage(struct cbfs_media *media, const char *name)
@@ -149,6 +122,7 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name)
 	entry = stage->entry;
 	// entry = ntohll(stage->entry);
 
+	free(stage);
 	return (void *) entry;
 }
 
@@ -163,11 +137,14 @@ int cbfs_execute_stage(struct cbfs_media *media, const char *name)
 	if (ntohl(stage->compression) != CBFS_COMPRESS_NONE) {
 		LOG("Unable to run %s:  Compressed file"
 		       "Not supported for in-place execution\n", name);
+		free(stage);
 		return 1;
 	}
 
 	LOG("run @ %p\n", (void *) (uintptr_t)ntohll(stage->entry));
-	return run_address((void *)(uintptr_t)ntohll(stage->entry));
+	int result = run_address((void *)(uintptr_t)ntohll(stage->entry));
+	free(stage);
+	return result;
 }
 
 void *cbfs_load_payload(struct cbfs_media *media, const char *name)
diff --git a/payloads/libpayload/libcbfs/cbfs_core.c b/payloads/libpayload/libcbfs/cbfs_core.c
index 5541f02..5a46af8 100644
--- a/payloads/libpayload/libcbfs/cbfs_core.c
+++ b/payloads/libpayload/libcbfs/cbfs_core.c
@@ -210,7 +210,38 @@ void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
 	if (sz)
 		*sz = ntohl(file->len);
 
-	return (void *)CBFS_SUBHEADER(file);
+	void *file_content = (void *)CBFS_SUBHEADER(file);
+
+	struct cbfs_file_attribute *attr = cbfs_file_first_attr(file);
+	while (attr) {
+		if (ntohl(attr->tag) == CBFS_FILE_ATTR_TAG_COMPRESSION)
+			break;
+		attr = cbfs_file_next_attr(file, attr);
+	}
+
+	int compression_algo = CBFS_COMPRESS_NONE;
+	if (attr) {
+		struct cbfs_file_attr_compression *comp =
+			(struct cbfs_file_attr_compression *)attr;
+		compression_algo = ntohl(comp->compression);
+		DEBUG("File '%s' is compressed (alg=%d)\n", compression_algo);
+		*sz = ntohl(comp->decompressed_size);
+	}
+
+	void *dst = malloc(*sz);
+	if (dst == NULL)
+		goto err;
+
+	if (!cbfs_decompress(compression_algo, file_content, dst, *sz))
+		goto err;
+
+	media->unmap(media, file);
+	return dst;
+
+err:
+	media->unmap(media, file);
+	free(dst);
+	return NULL;
 }
 
 struct cbfs_file_attribute *cbfs_file_first_attr(struct cbfs_file *file)



More information about the coreboot-gerrit mailing list