diff options
author | Julius Werner <jwerner@chromium.org> | 2016-08-19 15:24:54 -0700 |
---|---|---|
committer | Julius Werner <jwerner@chromium.org> | 2016-08-27 01:16:16 +0200 |
commit | 71885a49600db1df58060406c0bb8a5b976c554c (patch) | |
tree | 53ef1292e7659e99a43c33cf6f1dfa7a4f734eaa /src/commonlib/cbfs.c | |
parent | 2a1847ea125b4b867f435635173acb39c9d75292 (diff) |
commonlib: cbfs: Add CBFS attribute support
This patch adds support for the CBFS attributes that were already
introduced in cbfstool and libpayload. I'm only copy&pasting the header
definitions needed for this once more. Really, we should be unifying the
definitions (and possibly part of the code) from cbfstool with
commonlib, but apparently that hadn't been done when this feature was
introduced and I don't really have time to do it cleanly now.
Also add a function to extract info from the compression attribute,
which can then be used to run cbfs_load_and_decompress() on the file.
Change-Id: I7b6463597757122cfe84f006c946a1658bb3acc6
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://review.coreboot.org/16271
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/commonlib/cbfs.c')
-rw-r--r-- | src/commonlib/cbfs.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/commonlib/cbfs.c b/src/commonlib/cbfs.c index 56faf286ef..1db8d31acf 100644 --- a/src/commonlib/cbfs.c +++ b/src/commonlib/cbfs.c @@ -108,6 +108,54 @@ int cbfs_for_each_file(const struct region_device *cbfs, return -1; } +size_t cbfs_for_each_attr(void *metadata, size_t metadata_size, + size_t last_offset) +{ + struct cbfs_file_attribute *attr; + + if (!last_offset) { + struct cbfs_file *file = metadata; + size_t start_offset = read_be32(&file->attributes_offset); + if (start_offset <= sizeof(struct cbfs_file) || + start_offset + sizeof(*attr) > metadata_size) + return 0; + return start_offset; + } + + attr = metadata + last_offset; + size_t next_offset = last_offset + read_be32(&attr->len); + + if (next_offset + sizeof(*attr) > metadata_size) + return 0; + return next_offset; +} + +int cbfsf_decompression_info(struct cbfsf *fh, uint32_t *algo, size_t *size) +{ + size_t metadata_size = region_device_sz(&fh->metadata); + void *metadata = rdev_mmap_full(&fh->metadata); + size_t offs = 0; + + if (!metadata) + return -1; + + while ((offs = cbfs_for_each_attr(metadata, metadata_size, offs))) { + struct cbfs_file_attr_compression *attr = metadata + offs; + if (read_be32(&attr->tag) != CBFS_FILE_ATTR_TAG_COMPRESSION) + continue; + + *algo = read_be32(&attr->compression); + *size = read_be32(&attr->decompressed_size); + rdev_munmap(&fh->metadata, metadata); + return 0; + } + + *algo = CBFS_COMPRESS_NONE; + *size = region_device_sz(&fh->data); + rdev_munmap(&fh->metadata, metadata); + return 0; +} + static int cbfsf_file_type(struct cbfsf *fh, uint32_t *ftype) { const size_t sz = sizeof(*ftype); |