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

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Thu Jul 16 15:36:20 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 cd73033d955d5bcae7e8f2ac4684af69d85c7b35
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 | 58 +++++++++++++++++++++------------
 3 files changed, 63 insertions(+), 28 deletions(-)

diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h
index 2dbaaf4..48a6fcd 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_offset <= sizeof(_p)) ? 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..75ded46 100644
--- a/payloads/libpayload/libcbfs/cbfs_core.c
+++ b/payloads/libpayload/libcbfs/cbfs_core.c
@@ -97,8 +97,8 @@ const struct cbfs_header *cbfs_get_header(struct cbfs_media *media)
 /* public API starts here*/
 struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name)
 {
-	const char *file_name;
-	uint32_t offset, romsize, name_len;
+	const char *vardata;
+	uint32_t offset, romsize, vardata_len;
 	const struct cbfs_header *header;
 	struct cbfs_file file, *file_ptr;
 	struct cbfs_media default_media;
@@ -153,29 +153,29 @@ struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name)
 			offset += new_align;
 			continue;
 		}
-		name_len = ntohl(file.offset) - sizeof(file);
-		DEBUG(" - load entry 0x%x file name (%d bytes)...\n", offset,
-		      name_len);
+		vardata_len = ntohl(file.offset) - sizeof(file);
+		DEBUG(" - load entry 0x%x variable data (%d bytes)...\n",
+			offset, vardata_len);
 
 		// load file name (arbitrary length).
-		file_name = (const char*)media->map(
-				media, offset + sizeof(file), name_len);
-		if (file_name == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
+		vardata = (const char*)media->map(
+				media, offset + sizeof(file), vardata_len);
+		if (vardata == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
 			ERROR("ERROR: Failed to get filename: 0x%x.\n", offset);
-		} else if (strcmp(file_name, name) == 0) {
+		} else if (strcmp(vardata, name) == 0) {
 			int file_offset = ntohl(file.offset),
 			    file_len = ntohl(file.len);
 			DEBUG("Found file (offset=0x%x, len=%d).\n",
 			    offset + file_offset, file_len);
-			media->unmap(media, file_name);
+			media->unmap(media, vardata);
 			file_ptr = media->map(media, offset,
 					      file_offset + file_len);
 			media->close(media);
 			return file_ptr;
 		} else {
 			DEBUG(" (unmatched file @0x%x: %s)\n", offset,
-			      file_name);
-			media->unmap(media, file_name);
+			      vardata);
+			media->unmap(media, vardata);
 		}
 
 		// Move to next file.
@@ -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