diff options
Diffstat (limited to 'util/cbfstool/cbfs_image.c')
-rw-r--r-- | util/cbfstool/cbfs_image.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c new file mode 100644 index 0000000000..5754453b1c --- /dev/null +++ b/util/cbfstool/cbfs_image.c @@ -0,0 +1,128 @@ +/* + * CBFS Image Manipulation + * + * Copyright (C) 2013 The Chromium OS Authors. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "common.h" +#include "cbfs_image.h" + +/* The file name align is not defined in CBFS spec -- only a preference by + * (old) cbfstool. */ +#define CBFS_FILENAME_ALIGN (16) + +/* To make CBFS more friendly to ROM, fill -1 (0xFF) instead of zero. */ +#define CBFS_CONTENT_DEFAULT_VALUE (-1) + +static uint32_t align_up(uint32_t value, uint32_t align) { + if (value % align) + value += align - (value % align); + return value; +} + +int cbfs_image_from_file(struct cbfs_image *image, const char *filename) { + if (buffer_from_file(&image->buffer, filename) != 0) + return -1; + DEBUG("read_cbfs_image: %s (%zd bytes)\n", image->buffer.name, + image->buffer.size); + image->header = cbfs_find_header(image->buffer.data, + image->buffer.size); + if (!image->header) { + ERROR("%s does not have CBFS master header.\n", filename); + cbfs_image_delete(image); + return -1; + } + + return 0; +} + +int cbfs_image_write_file(struct cbfs_image *image, const char *filename) { + assert(image && image->buffer.data); + return buffer_write_file(&image->buffer, filename); +} + +int cbfs_image_delete(struct cbfs_image *image) { + buffer_delete(&image->buffer); + image->header = NULL; + return 0; +} + +struct cbfs_header *cbfs_find_header(char *data, size_t size) { + size_t offset; + int found = 0; + uint32_t x86sig; + struct cbfs_header *header, *result = NULL; + + // Try x86 style (check signature in bottom) header first. + x86sig = *(uint32_t *)(data + size - sizeof(uint32_t)); + offset = (x86sig + (uint32_t)size); + DEBUG("x86sig: 0x%x, offset: 0x%zx\n", x86sig, offset); + if (offset >= size - sizeof(*header) || + ntohl(((struct cbfs_header *)(data + offset))->magic) != + CBFS_HEADER_MAGIC) + offset = 0; + + for (; offset + sizeof(*header) < size; offset++) { + header = (struct cbfs_header *)(data + offset); + if (ntohl(header->magic) !=(CBFS_HEADER_MAGIC)) + continue; + if (ntohl(header->version) != CBFS_HEADER_VERSION1 && + ntohl(header->version) != CBFS_HEADER_VERSION2) { + // Probably not a real CBFS header? + continue; + } + found++; + result = header; + } + if (found > 1) { + ERROR("multiple (%d) CBFS headers found!\n", + found); + result = NULL; + } + return result; +} + + +struct cbfs_file *cbfs_find_first_entry(struct cbfs_image *image) { + assert(image && image->header); + return (struct cbfs_file *)(image->buffer.data + + ntohl(image->header->offset)); +} + +struct cbfs_file *cbfs_find_next_entry(struct cbfs_image *image, + struct cbfs_file *entry) { + uint32_t addr = cbfs_get_entry_addr(image, entry); + int align = ntohl(image->header->align); + assert(entry && cbfs_is_valid_entry(entry)); + addr += ntohl(entry->offset) + ntohl(entry->len); + addr = align_up(addr, align); + return (struct cbfs_file *)(image->buffer.data + addr); +} + +uint32_t cbfs_get_entry_addr(struct cbfs_image *image, struct cbfs_file *entry) { + assert(image && image->buffer.data && entry); + return (int32_t)((char *)entry - image->buffer.data); +} + +int cbfs_is_valid_entry(struct cbfs_file *entry) { + return (entry &&memcmp(entry->magic, CBFS_FILE_MAGIC, + sizeof(entry->magic)) == 0); +} + |