summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--util/cbfstool/Makefile2
-rw-r--r--util/cbfstool/Makefile.inc1
-rw-r--r--util/cbfstool/cbfs.h2
-rw-r--r--util/cbfstool/cbfs_image.c128
-rw-r--r--util/cbfstool/cbfs_image.h65
5 files changed, 197 insertions, 1 deletions
diff --git a/util/cbfstool/Makefile b/util/cbfstool/Makefile
index 17b00a77f281..3ace744905ab 100644
--- a/util/cbfstool/Makefile
+++ b/util/cbfstool/Makefile
@@ -7,7 +7,7 @@ CFLAGS += -D_7ZIP_ST
BINARY:=$(obj)/cbfstool
-COMMON:=cbfstool.o common.o compress.o
+COMMON:=cbfstool.o common.o cbfs_image.o compress.o
COMMON+=cbfs-mkstage.o cbfs-mkpayload.o
# LZMA
COMMON+=lzma/lzma.o
diff --git a/util/cbfstool/Makefile.inc b/util/cbfstool/Makefile.inc
index 5795507377f9..2cee794572a3 100644
--- a/util/cbfstool/Makefile.inc
+++ b/util/cbfstool/Makefile.inc
@@ -2,6 +2,7 @@ cbfsobj :=
cbfsobj += cbfstool.o
cbfsobj += common.o
cbfsobj += compress.o
+cbfsobj += cbfs_image.o
cbfsobj += cbfs-mkstage.o
cbfsobj += cbfs-mkpayload.o
# LZMA
diff --git a/util/cbfstool/cbfs.h b/util/cbfstool/cbfs.h
index 3dbeefd38d9e..4a3ff94f2010 100644
--- a/util/cbfstool/cbfs.h
+++ b/util/cbfstool/cbfs.h
@@ -42,6 +42,8 @@ struct cbfs_header {
#define CBFS_ARCHITECTURE_X86 0x00000001
#define CBFS_ARCHITECTURE_ARMV7 0x00000010
+#define CBFS_FILE_MAGIC "LARCHIVE"
+
struct cbfs_file {
uint8_t magic[8];
uint32_t len;
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c
new file mode 100644
index 000000000000..5754453b1cfc
--- /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);
+}
+
diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h
new file mode 100644
index 000000000000..9535c2d95f2a
--- /dev/null
+++ b/util/cbfstool/cbfs_image.h
@@ -0,0 +1,65 @@
+/*
+ * 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
+ */
+
+#ifndef __CBFS_IMAGE_H
+#define __CBFS_IMAGE_H
+#include "common.h"
+#include "cbfs.h"
+
+/* CBFS image processing */
+
+struct cbfs_image {
+ struct buffer buffer;
+ struct cbfs_header *header;
+};
+
+/* Loads a CBFS image from file. Returns 0 on success, otherwise non-zero. */
+int cbfs_image_from_file(struct cbfs_image *image, const char *filename);
+
+/* Writes a CBFS image into file. Returns 0 on success, otherwise non-zero. */
+int cbfs_image_write_file(struct cbfs_image *image, const char *filename);
+
+/* Releases the CBFS image. Returns 0 on success, otherwise non-zero. */
+int cbfs_image_delete(struct cbfs_image *image);
+
+/* Primitive CBFS utilities */
+
+/* Returns a pointer to the only valid CBFS header in give buffer, otherwise
+ * NULL (including when multiple headers were found). If there is a X86 ROM
+ * style signature (pointer at 0xfffffffc) found in ROM, it will be selected as
+ * the only header.*/
+struct cbfs_header *cbfs_find_header(char *data, size_t size);
+
+/* Returns the first cbfs_file entry in CBFS image by CBFS header (no matter if
+ * the entry has valid content or not), otherwise NULL. */
+struct cbfs_file *cbfs_find_first_entry(struct cbfs_image *image);
+
+/* Returns next cbfs_file entry (no matter if its content is valid or not), or
+ * NULL on failure. */
+struct cbfs_file *cbfs_find_next_entry(struct cbfs_image *image,
+ struct cbfs_file *entry);
+
+/* Returns ROM address (offset) of entry.
+ * This is different from entry->offset (pointer to content). */
+uint32_t cbfs_get_entry_addr(struct cbfs_image *image, struct cbfs_file *entry);
+
+/* Returns 1 if entry has valid data (by checking magic number), otherwise 0. */
+int cbfs_is_valid_entry(struct cbfs_file *entry);
+
+#endif