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>
This commit is contained in:
Patrick Georgi 2015-09-16 18:53:40 +02:00 committed by Patrick Georgi
parent 81a4c85acf
commit 377d1db57d
2 changed files with 66 additions and 1 deletions

View File

@ -132,10 +132,34 @@ struct cbfs_file {
char magic[8]; char magic[8];
uint32_t len; uint32_t len;
uint32_t type; uint32_t type;
uint32_t checksum; uint32_t attributes_offset;
uint32_t offset; uint32_t offset;
char filename[];
} __attribute__((packed)); } __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 ***/ /*** Component sub-headers ***/
/* Following are component sub-headers for the "standard" /* Following are component sub-headers for the "standard"

View File

@ -213,6 +213,47 @@ void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
return (void *)CBFS_SUBHEADER(file); 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) int cbfs_decompress(int algo, void *src, void *dst, int len)
{ {
switch (algo) { switch (algo) {