[coreboot] Patch set updated for coreboot: 0227862 Add multi-architecture support to cbfstool

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Fri Nov 30 00:20:42 CET 2012


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/1944

-gerrit

commit 0227862be6c72329fa378469201eb51d2a841608
Author: David Hendricks <dhendrix at chromium.org>
Date:   Fri Nov 16 14:48:22 2012 -0800

    Add multi-architecture support to cbfstool
    
    This is an initial re-factoring of CBFS code to enable multiple
    architectures. To achieve a clean solution, an additional field
    describing the architecture has to be added to the master header.
    Hence we also increase the version number in the master header.
    
    Change-Id: Icda681673221f8c27efbc46f16c2c5682b16a265
    Signed-off-by: Stefan Reinauer <reinauer at google.com>
    Signed-off-by: Hung-Te Lin <hungte at chromium.org>
    Signed-off-by: David Hendricks <dhendrix at chromium.org>
---
 documentation/cbfs.txt                  |  24 +++-
 payloads/coreinfo/cbfs_module.c         |   3 +-
 payloads/libpayload/include/cbfs_core.h |  24 +++-
 src/arch/x86/Makefile.inc               |   2 +-
 src/include/cbfs_core.h                 |  26 ++--
 util/cbfstool/cbfs-mkpayload.c          |  12 +-
 util/cbfstool/cbfs-mkstage.c            |   9 +-
 util/cbfstool/cbfs.h                    |  15 ++-
 util/cbfstool/cbfstool.c                |  32 +++--
 util/cbfstool/common.c                  | 211 +++++++++++++++++++++++++++-----
 util/cbfstool/common.h                  |   5 +
 11 files changed, 290 insertions(+), 73 deletions(-)

diff --git a/documentation/cbfs.txt b/documentation/cbfs.txt
index 61f9f79..4b266f2 100644
--- a/documentation/cbfs.txt
+++ b/documentation/cbfs.txt
@@ -144,11 +144,15 @@ need to read the pointer and do the appropriate math to locate the header.
 The following is the structure of the master header:
 
 struct cbfs_header {
-	unsigned int magic;
-	unsigned int size;
-	unsigned int align;
-	unsigned int offset;
-};
+        u32 magic;
+        u32 version;
+        u32 romsize;
+        u32 bootblocksize;
+        u32 align;
+        u32 offset;
+        u32 architecture;
+        u32 pad[1];
+} __attribute__((packed));
 
 The meaning of each member is as follows:
 
@@ -156,9 +160,14 @@ The meaning of each member is as follows:
 magic
 number is 0x4F524243, which is 'ORBC' in ASCII.
 
-'size' is the size of the ROM in bytes.  Coreboot will subtract 'size' from
+'version' is a version number for CBFS header. cbfs_header structure may be
+different if version is not matched.
+
+'romsize' is the size of the ROM in bytes.  Coreboot will subtract 'size' from
 0xFFFFFFFF to locate the beginning of the ROM in memory.
 
+'bootblocksize' is the size of bootblock reserved in firmware image.
+
 'align' is the number of bytes that each component is aligned to within the
 ROM.  This is used to make sure that each component is aligned correctly
 with
@@ -169,6 +178,9 @@ component at runtime without disturbing the others.
 the ROM).  This is to allow for arbitrary space to be left at the beginning
 of the ROM for things like embedded controller firmware.
 
+'architecture' describes which architecture (x86, arm, ...) this CBFS is created
+for.
+
 = Bootblock =
 The bootblock is a mandatory component in the ROM.  It is located in the
 last
diff --git a/payloads/coreinfo/cbfs_module.c b/payloads/coreinfo/cbfs_module.c
index ceb0e3c..0635747 100644
--- a/payloads/coreinfo/cbfs_module.c
+++ b/payloads/coreinfo/cbfs_module.c
@@ -41,7 +41,8 @@ struct cbheader {
 	u32 bootblocksize;
 	u32 align;
 	u32 offset;
-	u32 pad[2];
+	u32 architecture;
+	u32 pad[1];
 } __attribute__ ((packed));
 
 struct cbfile {
diff --git a/payloads/libpayload/include/cbfs_core.h b/payloads/libpayload/include/cbfs_core.h
index 70368f8..32f2670 100644
--- a/payloads/libpayload/include/cbfs_core.h
+++ b/payloads/libpayload/include/cbfs_core.h
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2008 Jordan Crouse <jordan at cosmicpenguin.net>
+ * Copyright (C) 2012 Google, Inc.
  *
  * This file is dual-licensed. You can choose between:
  *   - The GNU GPL, version 2, as published by the Free Software Foundation
@@ -76,13 +77,17 @@
 
 /** this is the master cbfs header - it need to be
     located somewhere in the bootblock.  Where it
-    actually lives is up to coreboot. A pointer to
-    this header will live at 0xFFFFFFFc, so we can
-    easily find it. */
+    actually lives is up to coreboot. On x86, a
+    pointer to this header will live at 0xFFFFFFFC,
+    so we can easily find it. */
 
 #define CBFS_HEADER_MAGIC  0x4F524243
-#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
+#if CONFIG_ARCH_X86
+#define CBFS_HEADPTR_ADDR 0xFFFFFFFC
+#endif
 #define VERSION1 0x31313131
+#define VERSION2 0x31313132
+#define VERSION  VERSION2
 
 struct cbfs_header {
 	uint32_t magic;
@@ -91,9 +96,17 @@ struct cbfs_header {
 	uint32_t bootblocksize;
 	uint32_t align;
 	uint32_t offset;
-	uint32_t pad[2];
+	uint32_t architecture;
+	uint32_t pad[1];
 } __attribute__((packed));
 
+/* "Unknown" refers to CBFS headers version 1,
+ * before the architecture was defined (i.e., x86 only).
+ */
+#define CBFS_ARCHITECTURE_UNKNOWN  0xFFFFFFFF
+#define CBFS_ARCHITECTURE_X86      0x00000001
+#define CBFS_ARCHITECTURE_ARMV7    0x00000010
+
 /** This is a component header - every entry in the CBFS
     will have this header.
 
@@ -178,4 +191,3 @@ void *cbfs_find_file(const char *name, int type);
 int cbfs_decompress(int algo, void *src, void *dst, int len);
 struct cbfs_header *get_cbfs_header(void);
 #endif
-
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index 68e5dcd..4afa7d5 100644
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -65,7 +65,7 @@ prebuild-files = \
 prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file)))
 
 $(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL)
-	$(CBFSTOOL) $@.tmp create -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \
+	$(CBFSTOOL) $@.tmp create -m x86 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \
 		-B $(objcbfs)/bootblock.bin -a 64 \
 		-o $$(( $(CONFIG_ROM_SIZE) - $(CONFIG_CBFS_SIZE) ))
 	$(prebuild-files) true
diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h
index 43e6b9b..32f2670 100644
--- a/src/include/cbfs_core.h
+++ b/src/include/cbfs_core.h
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright (C) 2008 Jordan Crouse <jordan at cosmicpenguin.net>
+ * Copyright (C) 2012 Google, Inc.
  *
  * This file is dual-licensed. You can choose between:
  *   - The GNU GPL, version 2, as published by the Free Software Foundation
@@ -49,8 +50,6 @@
 #ifndef _CBFS_CORE_H_
 #define _CBFS_CORE_H_
 
-#include <arch/byteorder.h>
-
 /** These are standard values for the known compression
     alogrithms that coreboot knows about for stages and
     payloads.  Of course, other CBFS users can use whatever
@@ -78,13 +77,17 @@
 
 /** this is the master cbfs header - it need to be
     located somewhere in the bootblock.  Where it
-    actually lives is up to coreboot. A pointer to
-    this header will live at 0xFFFFFFFc, so we can
-    easily find it. */
+    actually lives is up to coreboot. On x86, a
+    pointer to this header will live at 0xFFFFFFFC,
+    so we can easily find it. */
 
 #define CBFS_HEADER_MAGIC  0x4F524243
-#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
+#if CONFIG_ARCH_X86
+#define CBFS_HEADPTR_ADDR 0xFFFFFFFC
+#endif
 #define VERSION1 0x31313131
+#define VERSION2 0x31313132
+#define VERSION  VERSION2
 
 struct cbfs_header {
 	uint32_t magic;
@@ -93,9 +96,17 @@ struct cbfs_header {
 	uint32_t bootblocksize;
 	uint32_t align;
 	uint32_t offset;
-	uint32_t pad[2];
+	uint32_t architecture;
+	uint32_t pad[1];
 } __attribute__((packed));
 
+/* "Unknown" refers to CBFS headers version 1,
+ * before the architecture was defined (i.e., x86 only).
+ */
+#define CBFS_ARCHITECTURE_UNKNOWN  0xFFFFFFFF
+#define CBFS_ARCHITECTURE_X86      0x00000001
+#define CBFS_ARCHITECTURE_ARMV7    0x00000010
+
 /** This is a component header - every entry in the CBFS
     will have this header.
 
@@ -180,4 +191,3 @@ void *cbfs_find_file(const char *name, int type);
 int cbfs_decompress(int algo, void *src, void *dst, int len);
 struct cbfs_header *get_cbfs_header(void);
 #endif
-
diff --git a/util/cbfstool/cbfs-mkpayload.c b/util/cbfstool/cbfs-mkpayload.c
index e4ef5c8..0d3986e 100644
--- a/util/cbfstool/cbfs-mkpayload.c
+++ b/util/cbfstool/cbfs-mkpayload.c
@@ -35,7 +35,7 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output,
 			 comp_algo algo)
 {
 	Elf32_Phdr *phdr;
-	Elf32_Ehdr *ehdr;
+	Elf32_Ehdr *ehdr = (Elf32_Ehdr *) input;
 	Elf32_Shdr *shdr;
 	char *header;
 	char *strtab;
@@ -48,16 +48,20 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output,
 	int i;
 
 	if(!iself(input)){
-		printf("Fatal error: the payload file is not in ELF format!\n");
-		exit(1);
+		fprintf(stderr, "E: The payload file is not in ELF format!\n");
+		return -1;
 	}
 
+	if (!((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) &&
+	    !((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) {
+		fprintf(stderr, "E: The payload file has the wrong architecture\n");
+		return -1;
+	}
 
 	comp_func_ptr compress = compression_function(algo);
 	if (!compress)
 		return -1;
 
-	ehdr = (Elf32_Ehdr *) input;
 	headers = ehdr->e_phnum;
 	header = (char *)ehdr;
 
diff --git a/util/cbfstool/cbfs-mkstage.c b/util/cbfstool/cbfs-mkstage.c
index 55c81c6..0541d4b 100644
--- a/util/cbfstool/cbfs-mkstage.c
+++ b/util/cbfstool/cbfs-mkstage.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2008 Jordan Crouse <jordan at cosmicpenguin.net>
  *               2009 coresystems GmbH
  *                 written by Patrick Georgi <patrick.georgi at coresystems.de>
+ * Copyright (C) 2012 Google, Inc.
  *
  * 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
@@ -67,7 +68,13 @@ int parse_elf_to_stage(unsigned char *input, unsigned char **output,
 		return -1;
 
 	if (!iself(input)) {
-		fprintf(stderr, "E:  The incoming file is not an ELF\n");
+		fprintf(stderr, "E: The stage file is not in ELF format!\n");
+		return -1;
+	}
+
+	if (!((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) &&
+	    !((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) {
+		fprintf(stderr, "E: The stage file has the wrong architecture\n");
 		return -1;
 	}
 
diff --git a/util/cbfstool/cbfs.h b/util/cbfstool/cbfs.h
index f161ed4..5251d65 100644
--- a/util/cbfstool/cbfs.h
+++ b/util/cbfstool/cbfs.h
@@ -21,6 +21,12 @@
 
 #include <stdint.h>
 
+#define CBFS_HEADER_MAGIC  0x4F524243
+#define CBFS_HEADPTR_ADDR_X86 0xFFFFFFFC
+#define VERSION1 0x31313131
+#define VERSION2 0x31313132
+#define VERSION  VERSION2
+
 struct cbfs_header {
 	uint32_t magic;
 	uint32_t version;
@@ -28,9 +34,14 @@ struct cbfs_header {
 	uint32_t bootblocksize;
 	uint32_t align;
 	uint32_t offset;
-	uint32_t pad[2];
+	uint32_t architecture;	/* Version 2 */
+	uint32_t pad[1];
 } __attribute__ ((packed));
 
+#define CBFS_ARCHITECTURE_UNKNOWN  0xFFFFFFFF
+#define CBFS_ARCHITECTURE_X86      0x00000001
+#define CBFS_ARCHITECTURE_ARMV7    0x00000010
+
 struct cbfs_file {
 	uint8_t magic[8];
 	uint32_t len;
@@ -94,7 +105,7 @@ struct cbfs_payload {
  */
 #define CBFS_COMPONENT_NULL 0xFFFFFFFF
 
-int cbfs_file_header(uint32_t physaddr);
+int cbfs_file_header(unsigned long physaddr);
 struct cbfs_file *cbfs_create_empty_file(uint32_t physaddr, uint32_t size);
 
 #endif
diff --git a/util/cbfstool/cbfstool.c b/util/cbfstool/cbfstool.c
index 66db379..a09e75b 100644
--- a/util/cbfstool/cbfstool.c
+++ b/util/cbfstool/cbfstool.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2009 coresystems GmbH
  *                 written by Patrick Georgi <patrick.georgi at coresystems.de>
+ * Copyright (C) 2012 Google, Inc.
  *
  * 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
@@ -372,6 +373,11 @@ static int cbfs_create(void)
 		return 1;
 	}
 
+	if (arch == CBFS_ARCHITECTURE_UNKNOWN) {
+		fprintf(stderr, "E: You need to specify -m/--machine arch\n");
+		return 1;
+	}
+
 	return create_cbfs_image(cbfs_name, rom_size, rom_bootblock,
 						rom_alignment, rom_offset);
 }
@@ -450,7 +456,7 @@ static const struct command commands[] = {
 	{"add-stage", "f:n:t:c:b:h?", cbfs_add_stage},
 	{"add-flat-binary", "f:n:l:e:c:b:h?", cbfs_add_flat_binary},
 	{"remove", "n:h?", cbfs_remove},
-	{"create", "s:B:a:o:h?", cbfs_create},
+	{"create", "s:B:a:o:m:h?", cbfs_create},
 	{"locate", "f:n:a:h?", cbfs_locate},
 	{"print", "h?", cbfs_print},
 	{"extract", "n:f:h?", cbfs_extract},
@@ -468,6 +474,7 @@ static struct option long_options[] = {
 	{"alignment",    required_argument, 0, 'a' },
 	{"offset",       required_argument, 0, 'o' },
 	{"file",         required_argument, 0, 'f' },
+	{"arch",         required_argument, 0, 'm' },
 	{"verbose",      no_argument,       0, 'v' },
 	{"help",         no_argument,       0, 'h' },
 	{NULL,           0,                 0,  0  }
@@ -481,26 +488,28 @@ static void usage(char *name)
 	     " %s FILE COMMAND [PARAMETERS]...\n\n" "OPTIONs:\n"
 	     "  -h		Display this help message\n\n"
 	     "COMMANDs:\n"
-	     " add -f FILE -n NAME -t TYPE [-b base-address]             "
+	     " add -f FILE -n NAME -t TYPE [-b base-address]               "
 			"Add a component\n"
-	     " add-payload -f FILE -n NAME [-c compression] [-b base]    "
+	     " add-payload -f FILE -n NAME [-c compression] [-b base]      "
 			"Add a payload to the ROM\n"
-	     " add-stage -f FILE -n NAME [-c compression] [-b base]      "
+	     " add-stage -f FILE -n NAME [-c compression] [-b base]        "
 			"Add a stage to the ROM\n"
 	     " add-flat-binary -f FILE -n NAME -l load-address \\\n"
-	     "        -e entry-point [-c compression] [-b base]          "
+	     "        -e entry-point [-c compression] [-b base]            "
 			"Add a 32bit flat mode binary\n"
-	     " remove -n NAME                                            "
+	     " remove -n NAME                                              "
 			"Remove a component\n"
-	     " create -s size -B bootblock [-a align] [-o offset]        "
+	     " create -s size -B bootblock -m ARCH [-a align] [-o offset]  "
 			"Create a ROM file\n"
-	     " locate -f FILE -n NAME -a align                           "
+	     " locate -f FILE -n NAME -a align                             "
 			"Find a place for a file of that size\n"
-	     " print                                                     "
+	     " print                                                       "
 			"Show the contents of the ROM\n"
-	     " extract -n NAME -f FILE                                   "
+	     " extract -n NAME -f FILE                                     "
 			"Extracts a raw payload from ROM\n"
 	     "\n"
+	     "ARCHes:\n"
+	     "  armv7, x86\n"
 	     "TYPEs:\n", name, name
 	    );
 	print_supported_filetypes();
@@ -610,6 +619,9 @@ int main(int argc, char **argv)
 			case 'v':
 				verbose++;
 				break;
+			case 'm':
+				arch = string_to_arch(optarg);
+				break;
 			case 'h':
 			case '?':
 				usage(argv[0]);
diff --git a/util/cbfstool/common.c b/util/cbfstool/common.c
index 6c67c39..d29df60 100644
--- a/util/cbfstool/common.c
+++ b/util/cbfstool/common.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2009 coresystems GmbH
  *                 written by Patrick Georgi <patrick.georgi at coresystems.de>
+ * Copyright (C) 2012 Google, Inc.
  *
  * 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
@@ -73,16 +74,101 @@ static struct cbfs_header *master_header;
 static uint32_t phys_start, phys_end, align;
 uint32_t romsize;
 void *offset;
+uint32_t arch = CBFS_ARCHITECTURE_UNKNOWN;
+
+static struct {
+	uint32_t arch;
+	const char *name;
+} arch_names[] = {
+	{ CBFS_ARCHITECTURE_ARMV7, "armv7" },
+	{ CBFS_ARCHITECTURE_X86, "x86" },
+	{ CBFS_ARCHITECTURE_UNKNOWN, "unknown" }
+};
+
+uint32_t string_to_arch(const char *arch_string)
+{
+	int i;
+	uint32_t ret = CBFS_ARCHITECTURE_UNKNOWN;
+
+	for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
+		if (!strcasecmp(arch_string, arch_names[i].name)) {
+			ret = arch_names[i].arch;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+const char *arch_to_string(uint32_t a)
+{
+	int i;
+	const char *ret = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
+		if (a == arch_names[i].arch) {
+			ret = arch_names[i].name;
+			break;
+		}
+	}
+
+	return ret;
+
+}
+
+int find_master_header(void *romarea, size_t size)
+{
+	size_t offset;
+
+	if (master_header)
+		return 0;
+
+	for (offset = 0; offset < size - sizeof(struct cbfs_header); offset++) {
+		struct cbfs_header *tmp = romarea + offset;
+
+		if (tmp->magic == ntohl(CBFS_HEADER_MAGIC)) {
+			master_header = tmp;
+			break;
+		}
+	}
+
+	return master_header ? 0 : 1;
+}
 
 void recalculate_rom_geometry(void *romarea)
 {
-	offset = romarea + romsize - 0x100000000ULL;
-	master_header = (struct cbfs_header *)
-	    phys_to_virt(*((uint32_t *) phys_to_virt(0xfffffffc)));
-	phys_start = (0 - romsize + ntohl(master_header->offset)) & 0xffffffff;
-	phys_end =
-	    (0 - ntohl(master_header->bootblocksize) -
-	     sizeof(struct cbfs_header)) & 0xffffffff;
+	if (find_master_header(romarea, romsize)) {
+		fprintf(stderr, "E: Cannot find master header\n");
+		exit(1);
+	}
+
+	/* Update old headers */
+	if (master_header->version == VERSION1 &&
+	    ntohl(master_header->architecture) == CBFS_ARCHITECTURE_UNKNOWN) {
+		printf("Updating CBFS master header to version 2\n");
+		master_header->architecture = htonl(CBFS_ARCHITECTURE_X86);
+	}
+
+	arch = ntohl(master_header->architecture);
+
+	switch (arch) {
+	case CBFS_ARCHITECTURE_ARMV7:
+		offset = romarea;
+		phys_start = (0 + ntohl(master_header->offset)) & 0xffffffff;
+		phys_end = romsize & 0xffffffff;
+		break;
+	case CBFS_ARCHITECTURE_X86:
+		offset = romarea + romsize - 0x100000000ULL;
+		phys_start = (0 - romsize + ntohl(master_header->offset)) &
+				0xffffffff;
+		phys_end = (0 - ntohl(master_header->bootblocksize) -
+		     sizeof(struct cbfs_header)) & 0xffffffff;
+		break;
+	default:
+		fprintf(stderr, "E: Unknown architecture\n");
+		exit(1);
+	}
+
 	align = ntohl(master_header->align);
 }
 
@@ -114,7 +200,7 @@ int writerom(const char *filename, void *start, uint32_t size)
 	return 0;
 }
 
-int cbfs_file_header(uint32_t physaddr)
+int cbfs_file_header(unsigned long physaddr)
 {
 	/* maybe improve this test */
 	return (strncmp(phys_to_virt(physaddr), "LARCHIVE", 8) == 0);
@@ -188,9 +274,10 @@ uint64_t intfiletype(const char *name)
 void print_cbfs_directory(const char *filename)
 {
 	printf
-	    ("%s: %d kB, bootblocksize %d, romsize %d, offset 0x%x\nAlignment: %d bytes\n\n",
+	    ("%s: %d kB, bootblocksize %d, romsize %d, offset 0x%x\n"
+	     "Alignment: %d bytes, architecture: %s\n\n",
 	     basename((char *)filename), romsize / 1024, ntohl(master_header->bootblocksize),
-	     romsize, ntohl(master_header->offset), align);
+	     romsize, ntohl(master_header->offset), align, arch_to_string(arch));
 	printf("%-30s %-10s %-12s Size\n", "Name", "Offset", "Type");
 	uint32_t current = phys_start;
 	while (current < phys_end) {
@@ -206,8 +293,8 @@ void print_cbfs_directory(const char *filename)
 			fname = "(empty)";
 
 		printf("%-30s 0x%-8x %-12s %d\n", fname,
-		       current - phys_start, strfiletype(ntohl(thisfile->type)),
-		       length);
+		       current - phys_start + ntohl(master_header->offset),
+		       strfiletype(ntohl(thisfile->type)), length);
 		current =
 		    ALIGN(current + ntohl(thisfile->len) +
 			  ntohl(thisfile->offset), align);
@@ -451,7 +538,7 @@ void *create_cbfs_file(const char *filename, void *data, uint32_t * datasize,
 }
 
 int create_cbfs_image(const char *romfile, uint32_t _romsize,
-		      const char *bootblock, uint32_t align, uint32_t offs)
+		const char *bootblock, uint32_t align, uint32_t offs)
 {
 	uint32_t bootblocksize = 0;
 	struct cbfs_header *master_header;
@@ -466,9 +553,6 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize,
 	}
 	memset(romarea, 0xff, romsize);
 
-	// Set up physical/virtual mapping
-	offset = romarea + romsize - 0x100000000ULL;
-
 	if (align == 0)
 		align = 64;
 
@@ -481,24 +565,83 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize,
 		return 1;
 	}
 
-	master_header =
-	    (struct cbfs_header *)(romarea + romsize - bootblocksize -
-				   sizeof(struct cbfs_header));
-	master_header->magic = ntohl(0x4f524243);
-	master_header->version = ntohl(0x31313131);
-	master_header->romsize = htonl(romsize);
-	master_header->bootblocksize = htonl(bootblocksize);
-	master_header->align = htonl(align);
-	master_header->offset = htonl(offs);
-	((uint32_t *) phys_to_virt(0xfffffffc))[0] =
-	    virt_to_phys(master_header);
-
-	recalculate_rom_geometry(romarea);
-
-	cbfs_create_empty_file((0 - romsize + offs) & 0xffffffff,
-				   romsize - offs - bootblocksize -
-				   sizeof(struct cbfs_header) -
-				   sizeof(struct cbfs_file) - 16);
+	// TODO(hungte) Replace magic numbers by named constants.
+	switch (arch) {
+	case CBFS_ARCHITECTURE_ARMV7:
+		/* Set up physical/virtual mapping */
+		offset = romarea;
+
+		// should be aligned to align but then we need to dynamically
+		// create the jump to the bootblock
+		loadfile(bootblock, &bootblocksize, romarea + 0x20 +
+			 sizeof(struct cbfs_header), SEEK_SET);
+		master_header = (struct cbfs_header *)(romarea + 0x20);
+		uint32_t *arm_vec = (uint32_t *)romarea;
+		/*
+		 * Encoding for this branch instruction is:
+		 * 31:28 - condition (0xe for always/unconditional)
+		 * 27:24 - 0xa
+		 * 23: 0 - sign-extended offset (in multiples of 4)
+		 *
+		 * When executing the branch, the PC will read as the address
+		 * of current instruction + 8.
+		 */
+		arm_vec[0] = htonl(0x0e0000ea);  // branch to . + 64 bytes
+
+		master_header->magic = ntohl(CBFS_HEADER_MAGIC);
+		master_header->version = ntohl(VERSION);
+		master_header->romsize = htonl(romsize);
+		master_header->bootblocksize = htonl(bootblocksize);
+		master_header->align = htonl(align);
+		master_header->offset = htonl(
+				ALIGN((0x40 + bootblocksize), align));
+		master_header->architecture = htonl(CBFS_ARCHITECTURE_ARMV7);
+
+		((uint32_t *) phys_to_virt(0x4))[0] =
+				virt_to_phys(master_header);
+
+		recalculate_rom_geometry(romarea);
+
+		cbfs_create_empty_file(
+				ALIGN((0x40 + bootblocksize), align),
+				romsize - ALIGN((bootblocksize + 0x40), align)
+				//- sizeof(struct cbfs_header)
+				- sizeof(struct cbfs_file) );
+		break;
+
+	case CBFS_ARCHITECTURE_X86:
+		// Set up physical/virtual mapping
+		offset = romarea + romsize - 0x100000000ULL;
+
+		loadfile(bootblock, &bootblocksize, romarea + romsize,
+			 SEEK_END);
+		master_header = (struct cbfs_header *)(romarea + romsize -
+				  bootblocksize - sizeof(struct cbfs_header));
+
+		master_header->magic = ntohl(CBFS_HEADER_MAGIC);
+		master_header->version = ntohl(VERSION);
+		master_header->romsize = htonl(romsize);
+		master_header->bootblocksize = htonl(bootblocksize);
+		master_header->align = htonl(align);
+		master_header->offset = htonl(offs);
+		master_header->architecture = htonl(CBFS_ARCHITECTURE_X86);
+
+		((uint32_t *) phys_to_virt(CBFS_HEADPTR_ADDR_X86))[0] =
+		    virt_to_phys(master_header);
+
+		recalculate_rom_geometry(romarea);
+
+		cbfs_create_empty_file((0 - romsize + offs) & 0xffffffff,
+				       romsize - offs - bootblocksize -
+				       sizeof(struct cbfs_header) -
+				       sizeof(struct cbfs_file) - 16);
+		break;
+
+	default:
+		// Should not happen.
+		fprintf(stderr, "E: You found a bug in cbfstool.\n");
+		exit(1);
+	}
 
 	writerom(romfile, romarea, romsize);
 	free(romarea);
diff --git a/util/cbfstool/common.h b/util/cbfstool/common.h
index 4fcc1ee..b5258a3 100644
--- a/util/cbfstool/common.h
+++ b/util/cbfstool/common.h
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2009 coresystems GmbH
  *                 written by Patrick Georgi <patrick.georgi at coresystems.de>
+ * Copyright (C) 2012 Google, Inc.
  *
  * 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
@@ -29,6 +30,10 @@
 extern void *offset;
 extern uint32_t romsize;
 extern int host_bigendian;
+extern uint32_t arch;
+
+const char *arch_to_string(uint32_t a);
+uint32_t string_to_arch(const char *arch_string);
 
 static inline void *phys_to_virt(uint32_t addr)
 {




More information about the coreboot mailing list