[coreboot-gerrit] New patch to review for coreboot: libpayload: allow compression at file header level

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Wed Jul 15 21:53:15 CEST 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 7284d14edd5b4b5c65c641be7a29b93a55e6d3fb
Author: Daisuke Nojiri <dnojiri at chromium.org>
Date:   Thu Jul 9 15:07:45 2015 -0700

    libpayload: allow compression at file header level
    
    Sample call sequence for loading a compressed file is as follows:
    
    	const char *name = "foo.bmp";
    	struct cbfs_file *file = cbfs_get_file(media, name);
    	struct cbfs_file_attributes *attr = CBFS_FILE_ATTRIBUTES(file);
    	if (attr) {
    		void *dst = malloc(ntohl(attr->uncompressed_size));
    		dst = cbfs_get_file_content(media, name, type, NULL, file, dst);
    	}
    
    cbfs_stage and cbfs_payload_segment continue to support compression at
    subheader level because stages and payloads have to be decompressed to the load
    address, which is stored in the subheader. For these, file level compression
    should be turned off.
    
    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_core.h | 19 +++++++++++++++---
 payloads/libpayload/libcbfs/cbfs.c      | 14 +++++++++-----
 payloads/libpayload/libcbfs/cbfs_core.c | 34 +++++++++++++++++++++++++--------
 3 files changed, 51 insertions(+), 16 deletions(-)

diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h
index 26730c9..eee587e 100644
--- a/payloads/libpayload/include/cbfs_core.h
+++ b/payloads/libpayload/include/cbfs_core.h
@@ -138,6 +138,8 @@ struct cbfs_file {
 
 struct cbfs_file_attributes {
 	uint32_t len;
+	uint32_t compression;
+	uint32_t decompressed_size;
 } __attribute__((packed));
 
 #define CBFS_FILE_ATTRIBUTES(_p) (((_p)->attributes == 0) ? NULL : \
@@ -220,12 +222,23 @@ 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 file content inside CBFS after if type is correct
+ * or NULL on error.
+ *
+ * if the file is compressed, it's decompressed and copied to dst allocated by
+ * the caller.
+ *
+ * it can be invoked using previously mapped file content pointed by *file.
+ * if *file is not NULL, loading file will be skipped, assuming the file has
+ * not been unmapped.
+ */
 void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
-			    int type, size_t *sz);
+			    int type, size_t *sz,
+			    struct cbfs_file *file, void *dst);
 
 /* returns decompressed size on success, 0 on failure */
 int cbfs_decompress(int algo, void *src, void *dst, int len);
diff --git a/payloads/libpayload/libcbfs/cbfs.c b/payloads/libpayload/libcbfs/cbfs.c
index 9d7d2f1..6b0e11c 100644
--- a/payloads/libpayload/libcbfs/cbfs.c
+++ b/payloads/libpayload/libcbfs/cbfs.c
@@ -89,7 +89,8 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
 	tohex16(device, name+8);
 
 	orom = (struct cbfs_optionrom *)
-		cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM, NULL);
+		cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM,
+			NULL, NULL, NULL);
 
 	if (orom == NULL)
 		return NULL;
@@ -119,7 +120,8 @@ void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
 void * cbfs_load_stage(struct cbfs_media *media, const char *name)
 {
 	struct cbfs_stage *stage = (struct cbfs_stage *)
-		cbfs_get_file_content(media, name, CBFS_TYPE_STAGE, NULL);
+		cbfs_get_file_content(media, name, CBFS_TYPE_STAGE,
+			NULL, NULL, NULL);
 	/* this is a mess. There is no ntohll. */
 	/* for now, assume compatible byte order until we solve this. */
 	uintptr_t entry;
@@ -155,7 +157,8 @@ void * cbfs_load_stage(struct cbfs_media *media, const char *name)
 int cbfs_execute_stage(struct cbfs_media *media, const char *name)
 {
 	struct cbfs_stage *stage = (struct cbfs_stage *)
-		cbfs_get_file_content(media, name, CBFS_TYPE_STAGE, NULL);
+		cbfs_get_file_content(media, name, CBFS_TYPE_STAGE,
+			NULL, NULL, NULL);
 
 	if (stage == NULL)
 		return 1;
@@ -173,7 +176,7 @@ int cbfs_execute_stage(struct cbfs_media *media, const char *name)
 void *cbfs_load_payload(struct cbfs_media *media, const char *name)
 {
 	return (struct cbfs_payload *)cbfs_get_file_content(
-		media, name, CBFS_TYPE_PAYLOAD, NULL);
+		media, name, CBFS_TYPE_PAYLOAD, NULL, NULL, NULL);
 }
 
 struct cbfs_file *cbfs_find(const char *name) {
@@ -181,7 +184,8 @@ struct cbfs_file *cbfs_find(const char *name) {
 }
 
 void *cbfs_find_file(const char *name, int type) {
-	return cbfs_get_file_content(CBFS_DEFAULT_MEDIA, name, type, NULL);
+	return cbfs_get_file_content(CBFS_DEFAULT_MEDIA, name, type,
+		NULL, NULL, NULL);
 }
 
 const struct cbfs_header *get_cbfs_header(void) {
diff --git a/payloads/libpayload/libcbfs/cbfs_core.c b/payloads/libpayload/libcbfs/cbfs_core.c
index 7926d9d..eec244a 100644
--- a/payloads/libpayload/libcbfs/cbfs_core.c
+++ b/payloads/libpayload/libcbfs/cbfs_core.c
@@ -189,18 +189,20 @@ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name)
 }
 
 void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
-			    int type, size_t *sz)
+			    int type, size_t *sz, struct cbfs_file *file,
+			    void *dst)
 {
-	struct cbfs_file *file = cbfs_get_file(media, name);
+	if (file == NULL) {
+		file = cbfs_get_file(media, name);
+		if (file == NULL) {
+			ERROR("Could not find file '%s'.\n", name);
+			return NULL;
+		}
+	}
 
 	if (sz)
 		*sz = 0;
 
-	if (file == NULL) {
-		ERROR("Could not find file '%s'.\n", name);
-		return NULL;
-	}
-
 	if (ntohl(file->type) != type) {
 		ERROR("File '%s' is of type %x, but we requested %x.\n", name,
 		      ntohl(file->type), type);
@@ -210,7 +212,23 @@ 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_attributes *attr = CBFS_FILE_ATTRIBUTES(file);
+	if (attr && attr->compression) {
+		uint32_t alg = ntohl(attr->compression);
+		DEBUG("File '%s' is compressed (alg=%d)\n", alg);
+		if (!dst) {
+			ERROR("Memory for decompressed data not provided\n");
+			return NULL;
+		}
+		if (cbfs_decompress(alg, file_content, dst,
+				    ntohl(attr->decompressed_size)))
+			return NULL;
+		file_content = dst;
+	}
+
+	return file_content;
 }
 
 int cbfs_decompress(int algo, void *src, void *dst, int len)



More information about the coreboot-gerrit mailing list