cbfstool: add extended file attributes for cbfs_file
cbfs_file_first_attr(struct cbfs_file *) and cbfs_file_next_attr(struct cbfs_file *, struct cbfs_file_attribute *) help navigate through extended attributes. cbfs_add_file_attr(header, tag, size) adds a new file attribute to header. Change-Id: I325965286c44f31abd95df684d340cebb0e68b75 Signed-off-by: Patrick Georgi <pgeorgi@chromium.org> Reviewed-on: http://review.coreboot.org/10934 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
committed by
Patrick Georgi
parent
4a666423c6
commit
2c61506630
@@ -21,6 +21,10 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* cbfstool will fail when trying to build a cbfs_file header that's larger
|
||||||
|
* than MAX_CBFS_FILE_HEADER_BUFFER. 1K should give plenty of room. */
|
||||||
|
#define MAX_CBFS_FILE_HEADER_BUFFER 1024
|
||||||
|
|
||||||
/* create a magic number in host-byte order.
|
/* create a magic number in host-byte order.
|
||||||
* b3 is the high order byte.
|
* b3 is the high order byte.
|
||||||
* in the coreboot tools, we go with the 32-bit
|
* in the coreboot tools, we go with the 32-bit
|
||||||
@@ -77,6 +81,7 @@ struct cbfs_file {
|
|||||||
/* length of file data */
|
/* length of file data */
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
/* offset to struct cbfs_file_attribute or 0 */
|
||||||
uint32_t attributes_offset;
|
uint32_t attributes_offset;
|
||||||
/* length of header incl. variable data */
|
/* length of header incl. variable data */
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
@@ -95,6 +100,11 @@ struct cbfs_file_attribute {
|
|||||||
uint8_t data[0];
|
uint8_t data[0];
|
||||||
} __PACKED;
|
} __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
|
||||||
|
|
||||||
struct cbfs_stage {
|
struct cbfs_stage {
|
||||||
uint32_t compression;
|
uint32_t compression;
|
||||||
uint64_t entry;
|
uint64_t entry;
|
||||||
@@ -155,6 +165,7 @@ struct cbfs_payload {
|
|||||||
#define CBFS_COMPONENT_NULL 0xFFFFFFFF
|
#define CBFS_COMPONENT_NULL 0xFFFFFFFF
|
||||||
|
|
||||||
#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
|
#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
|
||||||
|
|
||||||
/* cbfs_image.c */
|
/* cbfs_image.c */
|
||||||
uint32_t get_cbfs_entry_type(const char *name, uint32_t default_value);
|
uint32_t get_cbfs_entry_type(const char *name, uint32_t default_value);
|
||||||
uint32_t get_cbfs_compression(const char *name, uint32_t unknown);
|
uint32_t get_cbfs_compression(const char *name, uint32_t unknown);
|
||||||
|
@@ -997,11 +997,8 @@ int cbfs_is_valid_entry(struct cbfs_image *image, struct cbfs_file *entry)
|
|||||||
struct cbfs_file *cbfs_create_file_header(int type,
|
struct cbfs_file *cbfs_create_file_header(int type,
|
||||||
size_t len, const char *name)
|
size_t len, const char *name)
|
||||||
{
|
{
|
||||||
// assume that there won't be file names of ~1000 bytes
|
struct cbfs_file *entry = malloc(MAX_CBFS_FILE_HEADER_BUFFER);
|
||||||
const int bufsize = 1024;
|
memset(entry, CBFS_CONTENT_DEFAULT_VALUE, MAX_CBFS_FILE_HEADER_BUFFER);
|
||||||
|
|
||||||
struct cbfs_file *entry = malloc(bufsize);
|
|
||||||
memset(entry, CBFS_CONTENT_DEFAULT_VALUE, bufsize);
|
|
||||||
memcpy(entry->magic, CBFS_FILE_MAGIC, sizeof(entry->magic));
|
memcpy(entry->magic, CBFS_FILE_MAGIC, sizeof(entry->magic));
|
||||||
entry->type = htonl(type);
|
entry->type = htonl(type);
|
||||||
entry->len = htonl(len);
|
entry->len = htonl(len);
|
||||||
@@ -1022,6 +1019,86 @@ int cbfs_create_empty_entry(struct cbfs_file *entry, int type,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cbfs_file_attribute *cbfs_add_file_attr(struct cbfs_file *header,
|
||||||
|
uint32_t tag,
|
||||||
|
uint32_t size)
|
||||||
|
{
|
||||||
|
struct cbfs_file_attribute *attr, *next;
|
||||||
|
next = cbfs_file_first_attr(header);
|
||||||
|
do {
|
||||||
|
attr = next;
|
||||||
|
next = cbfs_file_next_attr(header, attr);
|
||||||
|
} while (next != NULL);
|
||||||
|
uint32_t header_size = ntohl(header->offset) + size;
|
||||||
|
if (header_size > MAX_CBFS_FILE_HEADER_BUFFER) {
|
||||||
|
DEBUG("exceeding allocated space for cbfs_file headers");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* attr points to the last valid attribute now.
|
||||||
|
* If NULL, we have to create the first one. */
|
||||||
|
if (attr == NULL) {
|
||||||
|
/* New attributes start where the header ends.
|
||||||
|
* header->offset is later set to accomodate the
|
||||||
|
* additional structure.
|
||||||
|
* No endianess translation necessary here, because both
|
||||||
|
* fields are encoded the same way. */
|
||||||
|
header->attributes_offset = header->offset;
|
||||||
|
attr = (struct cbfs_file_attribute *)
|
||||||
|
(((uint8_t *)header) +
|
||||||
|
ntohl(header->attributes_offset));
|
||||||
|
} else {
|
||||||
|
attr = (struct cbfs_file_attribute *)
|
||||||
|
(((uint8_t *)attr) +
|
||||||
|
ntohl(attr->len));
|
||||||
|
}
|
||||||
|
header->offset = htonl(header_size);
|
||||||
|
memset(attr, CBFS_CONTENT_DEFAULT_VALUE, size);
|
||||||
|
attr->tag = htonl(tag);
|
||||||
|
attr->len = htonl(size);
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
/* Finds a place to hold whole data in same memory page. */
|
/* Finds a place to hold whole data in same memory page. */
|
||||||
static int is_in_same_page(uint32_t start, uint32_t size, uint32_t page)
|
static int is_in_same_page(uint32_t start, uint32_t size, uint32_t page)
|
||||||
{
|
{
|
||||||
|
@@ -170,4 +170,18 @@ int cbfs_merge_empty_entry(struct cbfs_image *image, struct cbfs_file *entry,
|
|||||||
|
|
||||||
/* Returns the size of a cbfs file header with no extensions */
|
/* Returns the size of a cbfs file header with no extensions */
|
||||||
size_t cbfs_calculate_file_header_size(const char *name);
|
size_t cbfs_calculate_file_header_size(const char *name);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
/* Adds to header a new extended attribute tagged 'tag', sized 'size'.
|
||||||
|
* Returns pointer to the new attribute, or NULL on error. */
|
||||||
|
struct cbfs_file_attribute *cbfs_add_file_attr(struct cbfs_file *header,
|
||||||
|
uint32_t tag,
|
||||||
|
uint32_t size);
|
||||||
#endif
|
#endif
|
||||||
|
Reference in New Issue
Block a user