[coreboot] New patch to review for coreboot: d998509 cbfstool: Use cbfs_image API for "create" command.

Hung-Te Lin (hungte@chromium.org) gerrit at coreboot.org
Tue Jan 29 02:55:34 CET 2013


Hung-Te Lin (hungte at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2214

-gerrit

commit d998509fa241d6609cfc82e096ed902e9a548976
Author: Hung-Te Lin <hungte at chromium.org>
Date:   Tue Jan 29 09:45:12 2013 +0800

    cbfstool: Use cbfs_image API for "create" command.
    
    To support platforms with different memory layout, "create" takes two extra
    optional params:
    
        "-b": base address (or offset) for bootblock. When omitted, put bootblock in
              end of ROM (x86  style).
        "-H": header offset. When omitted, put header right before bootblock,
              and update a top-aligned virtual address reference in end of ROM.
    
      Example: (can be found in ARM MAkefile):
        cbfstool coreboot.rom create -m armv7 -s 4096K -B bootblock.bin \
                 -a 64 -b 0x0000 -H 0x2040 -o 0x5000
    
    Verified to boot on ARM (Snow) and X86 (QEMU).
    
    Change-Id: Ida2a9e32f9a459787b577db5e6581550d9d7017b
    Signed-off-by: Hung-Te Lin <hungte at chromium.org>
---
 src/arch/armv7/Makefile.inc |  3 +-
 util/cbfstool/cbfs_image.c  | 88 +++++++++++++++++++++++++++++++++++++++++++++
 util/cbfstool/cbfs_image.h  | 16 +++++++++
 util/cbfstool/cbfstool.c    | 66 +++++++++++++++++++++++++++++++---
 4 files changed, 168 insertions(+), 5 deletions(-)

diff --git a/src/arch/armv7/Makefile.inc b/src/arch/armv7/Makefile.inc
index 37b56c3..a70d077 100644
--- a/src/arch/armv7/Makefile.inc
+++ b/src/arch/armv7/Makefile.inc
@@ -46,9 +46,10 @@ prebuild-files = \
 	$(if $(call extract_nth,4,$(file)),-b $(call extract_nth,4,$(file))) &&)
 prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file)))
 
+# TODO Change -b, -H, -o to Kconfig variables.
 $(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL)
 	$(CBFSTOOL) $@.tmp create -m armv7 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \
-		-B $(objcbfs)/bootblock.bin -a 64
+		-B $(objcbfs)/bootblock.bin -a 64 -b 0x0000 -H 0x2040 -o 0x5000
 	$(prebuild-files) true
 	mv $@.tmp $@
 else
diff --git a/util/cbfstool/cbfs_image.c b/util/cbfstool/cbfs_image.c
index fafbd7f..b10054e 100644
--- a/util/cbfstool/cbfs_image.c
+++ b/util/cbfstool/cbfs_image.c
@@ -129,6 +129,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;
diff --git a/util/cbfstool/cbfs_image.h b/util/cbfstool/cbfs_image.h
index 53944b9..e1a5cc2 100644
--- a/util/cbfstool/cbfs_image.h
+++ b/util/cbfstool/cbfs_image.h
@@ -22,6 +22,8 @@
 #include "common.h"
 #include "cbfs.h"
 
+#define IS_TOP_ALIGNED_ADDRESS(x)	((uint32_t)(x) > 0x80000000)
+
 /* CBFS image processing */
 
 struct cbfs_image {
@@ -29,6 +31,20 @@ struct cbfs_image {
 	struct cbfs_header *header;
 };
 
+/* Creates an empty CBFS image by given size, and description to its content
+ * (bootblock, align, header location, starting offset of CBFS entries.
+ * The output image will contain a valid cbfs_header, with one cbfs_file
+ * entry with type CBFS_COMPONENT_NULL, with max available size.
+ * Returns 0 on success, otherwise none-zero. */
+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);
+
 /* 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);
 
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c
index 148e80a..9b6f27d 100644
--- a/util/cbfstool/cbfstool.c
+++ b/util/cbfstool/cbfstool.c
@@ -43,7 +43,10 @@ static struct param {
 	char *bootblock;
 	uint32_t type;
 	uint32_t baseaddress;
+	uint32_t baseaddress_assigned;
 	uint32_t loadaddress;
+	uint32_t headeroffset;
+	uint32_t headeroffset_assigned;
 	uint32_t entrypoint;
 	uint32_t size;
 	uint32_t alignment;
@@ -345,23 +348,69 @@ static int cbfstool_remove(void)
 
 static int cbfstool_create(void)
 {
+	struct cbfs_image image;
+	struct buffer bootblock;
+
 	if (param.size == 0) {
 		ERROR("You need to specify a valid -s/--size.\n");
 		return 1;
 	}
 
 	if (!param.bootblock) {
-		ERROR("You need to specify -b/--bootblock.\n");
+		ERROR("You need to specify -B/--bootblock.\n");
 		return 1;
 	}
 
+	// TODO Remove arch or pack into param.
 	if (arch == CBFS_ARCHITECTURE_UNKNOWN) {
 		ERROR("You need to specify -m/--machine arch\n");
 		return 1;
 	}
 
-	return create_cbfs_image(param.cbfs_name, param.size, param.bootblock,
-						param.alignment, param.offset);
+	if (buffer_from_file(&bootblock, param.bootblock) != 0) {
+		return 1;
+	}
+
+	// Setup default boot offset and header offset.
+	if (!param.baseaddress_assigned) {
+		// put boot block before end of ROM.
+		param.baseaddress = param.size - bootblock.size;
+		DEBUG("bootblock in end of ROM.\n");
+	}
+	if (!param.headeroffset_assigned) {
+		// Put header before bootblock, and make a reference in end of
+		// bootblock.
+		param.headeroffset = (
+				param.baseaddress -
+				sizeof(struct cbfs_header));
+		if (bootblock.size >= sizeof(uint32_t)) {
+			// TODO this only works for 32b top-aligned system now...
+			uint32_t ptr = param.headeroffset - param.size;
+			uint32_t *sig = (uint32_t *)(bootblock.data +
+						     bootblock.size -
+						     sizeof(ptr));
+			*sig = ptr;
+			DEBUG("CBFS header reference in end of bootblock.\n");
+		}
+	}
+
+	if (cbfs_image_create(&image,
+			      arch,
+			      param.size,
+			      param.alignment,
+			      &bootblock,
+			      param.baseaddress,
+			      param.headeroffset,
+			      param.offset) != 0) {
+		ERROR("Failed to create %s.\n", param.cbfs_name);
+		return 1;
+	}
+	if (cbfs_image_write_file(&image, param.cbfs_name) != 0) {
+		ERROR("Failed to write %s.\n", param.cbfs_name);
+		return 1;
+	}
+	cbfs_image_delete(&image);
+	return 0;
 }
 
 static int cbfstool_locate_stage(void)
@@ -465,7 +514,7 @@ static const struct command commands[] = {
 	{"add-stage", "f:n:t:c:b:vh?", cbfstool_add_stage},
 	{"add-flat-binary", "f:n:l:e:c:b:vh?", cbfstool_add_flat_binary},
 	{"remove", "n:vh?", cbfstool_remove},
-	{"create", "s:B:a:o:m:vh?", cbfstool_create},
+	{"create", "s:B:b:H:a:o:m:vh?", cbfstool_create},
 	{"locate-stage", "Tf:n:a:vh?", cbfstool_locate_stage},
 	{"print", "vh?", cbfstool_print},
 	{"extract", "n:f:vh?", cbfstool_extract},
@@ -583,6 +632,10 @@ int main(int argc, char **argv)
 				break;
 			case 'b':
 				param.baseaddress = strtoul(optarg, NULL, 0);
+				// baseaddress may be zero on non-x86, so we
+				// need an explicit "baseaddress_assigned".
+				param.baseaddress = strtoul(optarg, NULL, 0);
+				param.baseaddress_assigned = 1;
 				break;
 			case 'l':
 				param.loadaddress = strtoul(optarg, NULL, 0);
@@ -602,6 +655,11 @@ int main(int argc, char **argv)
 			case 'B':
 				param.bootblock = optarg;
 				break;
+			case 'H':
+				param.headeroffset = strtoul(
+						optarg, NULL, 0);
+				param.headeroffset_assigned = 1;
+				break;
 			case 'a':
 				param.alignment = strtoul(optarg, NULL, 0);
 				break;



More information about the coreboot mailing list