aboutsummaryrefslogtreecommitdiff
path: root/util/cbfstool/cbfs_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/cbfstool/cbfs_image.c')
-rw-r--r--util/cbfstool/cbfs_image.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c
index 2f38cec0b4..83e8a9d1fd 100644
--- a/util/cbfstool/cbfs_image.c
+++ b/util/cbfstool/cbfs_image.c
@@ -130,6 +130,94 @@ static int cbfs_fix_legacy_size(struct cbfs_image *image) {
return 0;
}
+int cbfs_image_create(struct cbfs_image *image,
+ uint32_t arch,
+ size_t size,
+ uint32_t align,
+ struct buffer *bootblock,
+ int32_t bootblock_offset,
+ int32_t header_offset,
+ int32_t entries_offset)
+{
+ struct cbfs_header *header;
+ struct cbfs_file *entry;
+ uint32_t cbfs_len;
+
+ DEBUG("cbfs_image_create: bootblock=0x%x+0x%zx, "
+ "header=0x%x+0x%zx, entries_offset=0x%x\n",
+ bootblock_offset, bootblock->size,
+ header_offset, sizeof(*header), entries_offset);
+
+ if (buffer_create(&image->buffer, size, "(new)") != 0)
+ return -1;
+ image->header = NULL;
+ memset(image->buffer.data, CBFS_CONTENT_DEFAULT_VALUE, size);
+
+ // Adjust legcay top-aligned address to ROM offset.
+ if (IS_TOP_ALIGNED_ADDRESS(entries_offset))
+ entries_offset += (int32_t)size;
+ if (IS_TOP_ALIGNED_ADDRESS(bootblock_offset))
+ bootblock_offset += (int32_t)size;
+ if (IS_TOP_ALIGNED_ADDRESS(header_offset))
+ header_offset += (int32_t) size;
+
+ DEBUG("cbfs_create_image: (real offset) bootblock=0x%x, "
+ "header=0x%x, entries_offset=0x%x\n",
+ bootblock_offset, header_offset, entries_offset);
+
+ if (align == 0)
+ align = 64; // default align size.
+
+ // Prepare bootblock
+ if (bootblock_offset + bootblock->size > size) {
+ ERROR("Bootblock (0x%x+0x%zx) exceed ROM size (0x%zx)\n",
+ bootblock_offset, bootblock->size, size);
+ return -1;
+ }
+ memcpy(image->buffer.data + bootblock_offset, bootblock->data,
+ bootblock->size);
+
+ // Prepare header
+ if (header_offset + sizeof(*header) > size) {
+ ERROR("Header (0x%x+0x%zx) exceed ROM size (0x%zx)\n",
+ header_offset, sizeof(*header), size);
+ return -1;
+ }
+ header = (struct cbfs_header *)(image->buffer.data + header_offset);
+ image->header = header;
+ header->magic = htonl(CBFS_HEADER_MAGIC);
+ header->version = htonl(CBFS_HEADER_VERSION);
+ header->romsize = htonl(size);
+ header->bootblocksize = htonl(bootblock->size);
+ header->align = htonl(align);
+ header->offset = htonl(entries_offset);
+ header->architecture = htonl(arch);
+
+ // Prepare entries
+ if (align_up(entries_offset, align) != entries_offset) {
+ ERROR("Offset (0x%x) must be aligned to 0x%x.\n",
+ entries_offset, align);
+ return -1;
+ }
+ if (entries_offset + sizeof(*entry) > size) {
+ ERROR("Offset (0x%x+0x%zx) exceed ROM size(0x%zx)\n",
+ entries_offset, sizeof(*entry), size);
+ return -1;
+ }
+ entry = (struct cbfs_file *)(image->buffer.data + entries_offset);
+ // To calculate available length, find
+ // e = min(bootblock, header, size) where e > entries_offset.
+ cbfs_len = size;
+ if (bootblock_offset > entries_offset && bootblock_offset < cbfs_len)
+ cbfs_len = bootblock_offset;
+ if (header_offset > entries_offset && header_offset < cbfs_len)
+ cbfs_len = header_offset;
+ cbfs_len -= entries_offset + align;
+ cbfs_create_empty_entry(image, entry, cbfs_len, "");
+ LOG("Created CBFS image (capacity = %d bytes)\n", cbfs_len);
+ return 0;
+}
+
int cbfs_image_from_file(struct cbfs_image *image, const char *filename) {
if (buffer_from_file(&image->buffer, filename) != 0)
return -1;