libpayload: bring in file attribute support from cbfstool
This comes from cbfstool (GPL) into libpayload (BSD-l), but I could have
just as well written it in libpayload first.
Change-Id: I86baefe5c299125a4733fa20523efd5d06de7182
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Reviewed-on: http://review.coreboot.org/11675
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h
index a95cef7..a2ee744 100644
--- a/payloads/libpayload/include/cbfs_core.h
+++ b/payloads/libpayload/include/cbfs_core.h
@@ -132,10 +132,34 @@
char magic[8];
uint32_t len;
uint32_t type;
- uint32_t checksum;
+ uint32_t attributes_offset;
uint32_t offset;
+ char filename[];
} __attribute__((packed));
+/* Depending on how the header was initialized, it may be backed with 0x00 or
+ * 0xff. Support both. */
+#define CBFS_FILE_ATTR_TAG_UNUSED 0
+#define CBFS_FILE_ATTR_TAG_UNUSED2 0xffffffff
+
+/* The common fields of extended cbfs file attributes.
+ Attributes are expected to start with tag/len, then append their
+ specific fields. */
+struct cbfs_file_attribute {
+ uint32_t tag;
+ /* len covers the whole structure, incl. tag and len */
+ uint32_t len;
+ uint8_t data[0];
+} __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);
+
+/* Given a cbfs_file and a cbfs_file_attribute, return the attribute that
+ * follows it, or NULL. */
+struct cbfs_file_attribute *cbfs_file_next_attr(struct cbfs_file *file,
+ struct cbfs_file_attribute *attr);
+
/*** Component sub-headers ***/
/* Following are component sub-headers for the "standard"
diff --git a/payloads/libpayload/libcbfs/cbfs_core.c b/payloads/libpayload/libcbfs/cbfs_core.c
index 7926d9d..6a19b26 100644
--- a/payloads/libpayload/libcbfs/cbfs_core.c
+++ b/payloads/libpayload/libcbfs/cbfs_core.c
@@ -213,6 +213,47 @@
return (void *)CBFS_SUBHEADER(file);
}
+struct cbfs_file_attribute *cbfs_file_first_attr(struct cbfs_file *file)
+{
+ /* attributes_offset should be 0 when there is no attribute, but all
+ * values that point into the cbfs_file header are invalid, too. */
+ if (ntohl(file->attributes_offset) <= sizeof(*file))
+ return NULL;
+
+ /* There needs to be enough space for the file header and one
+ * attribute header for this to make sense. */
+ if (ntohl(file->offset) <=
+ sizeof(*file) + sizeof(struct cbfs_file_attribute))
+ return NULL;
+
+ return (struct cbfs_file_attribute *)
+ (((uint8_t *)file) + ntohl(file->attributes_offset));
+}
+
+struct cbfs_file_attribute *cbfs_file_next_attr(struct cbfs_file *file,
+ struct cbfs_file_attribute *attr)
+{
+ /* ex falso sequitur quodlibet */
+ if (attr == NULL)
+ return NULL;
+
+ /* Is there enough space for another attribute? */
+ if ((uint8_t *)attr + ntohl(attr->len) +
+ sizeof(struct cbfs_file_attribute) >=
+ (uint8_t *)file + ntohl(file->offset))
+ return NULL;
+
+ struct cbfs_file_attribute *next = (struct cbfs_file_attribute *)
+ (((uint8_t *)attr) + ntohl(attr->len));
+ /* If any, "unused" attributes must come last. */
+ if (ntohl(next->tag) == CBFS_FILE_ATTR_TAG_UNUSED)
+ return NULL;
+ if (ntohl(next->tag) == CBFS_FILE_ATTR_TAG_UNUSED2)
+ return NULL;
+
+ return next;
+}
+
int cbfs_decompress(int algo, void *src, void *dst, int len)
{
switch (algo) {