[coreboot] Patch set updated for coreboot: 153de55 Extend CBFS to arbitrary ROM source media.

Hung-Te Lin (hungte@chromium.org) gerrit at coreboot.org
Thu Jan 24 07:26: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/2182

-gerrit

commit 153de55cae77c7a7f6419f1d56e9f2a03eaf1a76
Author: Hung-Te Lin <hungte at chromium.org>
Date:   Tue Jan 22 18:57:56 2013 +0800

    Extend CBFS to arbitrary ROM source media.
    
    CBFS used to work on memory-mapped ROM (all x86). For some platforms like ARM,
    the ROM may come from USB, UART, or SPI ROM -- all working as serial device and
    not available for memory mapping.
    
    To support these devices (even allowing CBFS to read from multiple source
    media), the reading operation in CBFS is virtual-ized into a "cbfs_media".
    To simplify porting existing code, every media source must support both "reading
    into pre-allocated memory (read)" or "read and return an allocated buffer
    (map)".
    
    Each board can now declare its own media APIs, and then romstage / ramstage
    / bootblock can all share same CBFS implementation.
    
    Note: this CL DOES compile on ARM. Not runnable yet (need to setup proper media
    APIs).  X86 is also on-the-way.
    
    Change-Id: Iac911ded25a6f2feffbf3101a81364625bb07746
    Signed-off-by: Hung-Te Lin <hungte at chromium.org>
---
 src/arch/armv7/bootblock_simple.c     |  53 ++++++++++-
 src/arch/armv7/include/arch/cbfs.h    |  77 +---------------
 src/arch/x86/boot/smbios.c            |   2 +-
 src/cpu/samsung/exynos5250/Kconfig    |   8 ++
 src/include/cbfs.h                    |  15 ++-
 src/include/cbfs_core.h               |  72 +++++++++++----
 src/lib/cbfs.c                        |  37 +++++---
 src/lib/cbfs_core.c                   | 167 +++++++++++++++++-----------------
 src/lib/hardwaremain.c                |   5 +-
 src/lib/selfboot.c                    |   9 --
 src/mainboard/google/snow/bootblock.c |  81 +----------------
 11 files changed, 243 insertions(+), 283 deletions(-)

diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/armv7/bootblock_simple.c
index af76d4c..9d037ad 100644
--- a/src/arch/armv7/bootblock_simple.c
+++ b/src/arch/armv7/bootblock_simple.c
@@ -34,10 +34,60 @@ static int boot_cpu(void)
 	return 1;
 }
 
+// TODO(hungte) Find a better way to enable cbfs code here.
+// mem* and ulzma are now workarounds for bootblock compilation.
+
+#include "lib/cbfs.c"
+
+void *memcpy(void *dest, const void *src, size_t n) {
+	char *d = (char *)dest;
+	const char *s = (const char*)src;
+	while (n-- > 0)
+		*d++ = *s++;
+	return dest;
+}
+
+void *memset(void *dest, int c, size_t n) {
+	char *d = (char*)dest;
+	while (n-- > 0)
+		*d++ = c;
+	return dest;
+}
+
+int memcmp(const void *ptr1, const void *ptr2, size_t n) {
+	const char *s1 = (const char*)ptr1, *s2 = (const char*)ptr2;
+	int c;
+	while (n-- > 0)
+		if ((c = *s1++ - *s2++))
+			return c;
+	return 0;
+}
+
+unsigned long ulzma(unsigned char *src, unsigned char *dest) {
+	// TODO remove this.
+	return -1;
+}
+
+// end of stubs
+
+// ROM media implementation.
+static int snow_rom_open(struct cbfs_media *media) {
+	return 0;
+}
+
+static int snow_rom_close(struct cbfs_media *media) {
+	return 0;
+}
+
 void main(unsigned long bist)
 {
 	const char *target1 = "fallback/romstage";
 	unsigned long romstage_entry;
+	struct cbfs_media media = {
+		.context = NULL,
+		.open = snow_rom_open,
+		.close = snow_rom_close,
+	};
 
 	if (boot_cpu()) {
 		bootblock_cpu_init();
@@ -45,7 +95,8 @@ void main(unsigned long bist)
 	}
 
 	printk(BIOS_INFO, "bootblock main(): loading romstage\n");
-	romstage_entry = loadstage(target1);
+	romstage_entry = (unsigned long)cbfs_load_stage(&media, target1);
+
 	printk(BIOS_INFO, "bootblock main(): jumping to romstage\n");
 	if (romstage_entry) bootblock_exit(romstage_entry);
 	hlt();
diff --git a/src/arch/armv7/include/arch/cbfs.h b/src/arch/armv7/include/arch/cbfs.h
index f060643..505fff9 100644
--- a/src/arch/armv7/include/arch/cbfs.h
+++ b/src/arch/armv7/include/arch/cbfs.h
@@ -20,82 +20,7 @@
 #ifndef __INCLUDE_ARCH_CBFS__
 #define __INCLUDE_ARCH_CBFS__
 
-#include <string.h>
-#include <types.h>
 #include <cbfs_core.h>
 #include <arch/byteorder.h>
-#include <arch/cbfs.h>
 
-
-static int cbfs_check_magic(struct cbfs_file *file)
-{
-	return strcmp(file->magic, CBFS_FILE_MAGIC) ? 0 : 1;
-}
-
-static unsigned long loadstage(const char* target)
-{
-	unsigned long offset, align;
-	struct cbfs_header *header = (struct cbfs_header *)(CONFIG_BOOTBLOCK_BASE + 0x40);
-	/* FIXME: magic offsets */
-	// if (ntohl(header->magic) != CBFS_HEADER_MAGIC)
-	// 	printk(BIOS_ERR, "ERROR: No valid CBFS header found!\n");
-
-	offset = ntohl(header->offset);
-	align = ntohl(header->align);
-	printk(BIOS_INFO, "cbfs header (0x%p)\n", header);
-	printk(BIOS_INFO, "\tmagic: 0x%08x\n", ntohl(header->magic));
-	printk(BIOS_INFO, "\tversion: 0x%08x\n", ntohl(header->version));
-	printk(BIOS_INFO, "\tromsize: 0x%08x\n", ntohl(header->romsize));
-	printk(BIOS_INFO, "\tbootblocksize: 0x%08x\n", ntohl(header->bootblocksize));
-	printk(BIOS_INFO, "\talign: 0x%08x\n", ntohl(header->align));
-	printk(BIOS_INFO, "\toffset: 0x%08x\n", ntohl(header->offset));
-	while(1) {
-		struct cbfs_file *file;
-		struct cbfs_stage *stage;
-		/* FIXME: SPI image hack */
-		file = (struct cbfs_file *)(offset + CONFIG_SPI_IMAGE_HACK);
-		if (!cbfs_check_magic(file)) {
-			printk(BIOS_INFO, "magic is wrong, file: %p\n", file);
-			return 0;
-		}
-		if (!strcmp(CBFS_NAME(file), target)) {
-			uint32_t  load, entry;
-			printk(BIOS_INFO, "CBFS name matched, offset: %p\n", file);
-			printk(BIOS_INFO, "\tmagic: %02x%02x%02x%02x%02x%02x%02x%02x\n",
-				file->magic[0], file->magic[1], file->magic[2], file->magic[3],
-				file->magic[4], file->magic[5], file->magic[6], file->magic[7]);
-			printk(BIOS_INFO, "\tlen: 0x%08x\n", ntohl(file->len));
-			printk(BIOS_INFO, "\ttype: 0x%08x\n", ntohl(file->type));
-			printk(BIOS_INFO, "\tchecksum: 0x%08x\n", ntohl(file->checksum));
-			printk(BIOS_INFO, "\toffset: 0x%08x\n", ntohl(file->offset));
-			/* exploit the fact that this is all word-aligned. */
-			stage = CBFS_SUBHEADER(file);
-			load = stage->load;
-			entry = stage->entry;
-			int i;
-			u32 *to = (void *)load;
-			u32 *from = (void *)((u8 *)stage+sizeof(*stage));
-			/* we could do memmove/memset here. But the math gets messy. 
-			 * far easier just to do what we want.
-			 */
-			 printk(BIOS_INFO, "entry: 0x%08x, load: 0x%08x, "
-			 	"len: 0x%08x, memlen: 0x%08x\n", entry,
-				 load, stage->len, stage->memlen);
-			for(i = 0; i < stage->len; i += 4)
-				*to++ = *from++;
-			for(; i < stage->memlen; i += 4)
-				*to++ = 0;
-			return entry;
-		}
-		int flen = ntohl(file->len);
-		int foffset = ntohl(file->offset);
-		unsigned long oldoffset = offset;
-		offset = ALIGN(offset + foffset + flen, align);
-		printk(BIOS_INFO, "offset: 0x%08lx\n", offset);
-		if (offset <= oldoffset)
-			return 0;
-		if (offset > CONFIG_ROMSTAGE_SIZE)
-			return 0;
-	}
-}
-#endif
+#endif // __INCLUDE_ARCH_CBFS__
diff --git a/src/arch/x86/boot/smbios.c b/src/arch/x86/boot/smbios.c
index 72e70ba..c47df2d 100644
--- a/src/arch/x86/boot/smbios.c
+++ b/src/arch/x86/boot/smbios.c
@@ -143,7 +143,7 @@ static int smbios_write_type0(unsigned long *current, int handle)
 	vboot_data->vbt10 = (u32)t->eos + (version_offset - 1);
 #endif
 
-	if ((hdr = get_cbfs_header()) != (struct cbfs_header *)0xffffffff)
+	if (cbfs_get_header(&hdr) != -1)
 		t->bios_rom_size = (ntohl(hdr->romsize) / 65535) - 1;
 	t->system_bios_major_release = 4;
 	t->bios_characteristics =
diff --git a/src/cpu/samsung/exynos5250/Kconfig b/src/cpu/samsung/exynos5250/Kconfig
index f5beddc..2c417cb 100644
--- a/src/cpu/samsung/exynos5250/Kconfig
+++ b/src/cpu/samsung/exynos5250/Kconfig
@@ -48,6 +48,14 @@ config ROMSTAGE_SIZE
 	hex
 	default 0x10000
 
+config CBFS_HEADER_ROM_OFFSET
+	hex "offset of master CBFS header in ROM"
+	default 0x2040
+
+config CBFS_CACHE_ADDRESS
+	hex "memory address to put CBFS cache data"
+	default 0x02060000
+
 # FIXME: This is for copying SPI content into SRAM temporarily and
 # will be removed when we have the SPI streaming driver implemented.
 config SPI_IMAGE_HACK
diff --git a/src/include/cbfs.h b/src/include/cbfs.h
index b33e932..216d81d 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -52,11 +52,18 @@
 #include "cbfs_core.h"
 #include <boot/coreboot_tables.h>
 
-void *cbfs_load_payload(struct lb_memory *lb_mem, const char *name);
-void *cbfs_load_stage(const char *name);
-int cbfs_execute_stage(const char *name);
-void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest);
+int cbfs_execute_stage(struct cbfs_media *media, const char *name);
+void *cbfs_load_stage(struct cbfs_media *media, const char *name);
+void *cbfs_load_optionrom(struct cbfs_media *media, u16 vendor, u16 device,
+			  void * dest);
+void *cbfs_load_payload(struct cbfs_media *media, struct lb_memory *lb_mem,
+			const char *name);
+
+// Utility functions
 int run_address(void *f);
+
+/* Defined in src/lib/selfboot.c */
 int selfboot(struct lb_memory *mem, struct cbfs_payload *payload);
+
 #endif
 
diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h
index a3c54b1..acc640c 100644
--- a/src/include/cbfs_core.h
+++ b/src/include/cbfs_core.h
@@ -74,24 +74,24 @@
 #define CBFS_COMPONENT_CMOS_DEFAULT 0xaa
 #define CBFS_COMPONENT_CMOS_LAYOUT 0x01aa
 
-
-/** this is the master cbfs header - it need to be
-    located somewhere in the bootblock.  Where 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
-#if CONFIG_ARCH_X86
-#define CBFS_HEADPTR_ADDR 0xFFFFFFFC
-#elif CONFIG_ARCH_ARMV7
-/* FIXME: This could also be 0xFFFF0000 with HIVECS enabled */
-#define CBFS_HEADPTR_ADDR 0x0000000C
-#endif
 #define CBFS_HEADER_VERSION1 0x31313131
 #define CBFS_HEADER_VERSION2 0x31313132
 #define CBFS_HEADER_VERSION  CBFS_HEADER_VERSION2
 
+#ifdef CONFIG_CBFS_HEADER_ROM_OFFSET
+# define CBFS_HEADER_ROM_ADDRESS (CONFIG_CBFS_HEADER_ROM_OFFSET)
+#else
+# define CBFS_HEADER_ROM_ADDRESS (*(uint32_t*)0xfffffffc)
+#endif
+
+#define CBFS_HEADER_INVALID_ADDRESS	((void*)(0xffffffff))
+
+/** this is the master cbfs header - it need to be located somewhere available
+    to bootblock (to load romstage).  Where it actually lives is up to coreboot.
+    On x86, a pointer to this header will live at 0xFFFFFFFC.
+    For other platforms, you need to define CONFIG_CBFS_HEADER_ROM_OFFSET */
+
 struct cbfs_header {
 	uint32_t magic;
 	uint32_t version;
@@ -181,16 +181,48 @@ struct cbfs_optionrom {
 #define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file))
 #define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
 
-/* returns pointer to file inside CBFS or NULL */
-struct cbfs_file *cbfs_find(const char *name);
+#define CBFS_MEDIA_INVALID_MAP_ADDRESS	(void*)(0xffffffff)
+
+/* Media for CBFS to load files. */
+struct cbfs_media {
+
+	/* implementation dependent context, to hold resource references */
+	void *context;
 
-/* returns pointer to file data inside CBFS */
-void *cbfs_get_file(const char *name);
+	/* opens media and returns 0 on success, -1 on failure */
+	int (*open)(struct cbfs_media *media);
 
-/* returns pointer to file data inside CBFS after if type is correct */
-void *cbfs_find_file(const char *name, int type);
+	/* returns number of bytes read from media into dest, starting from
+	 * offset for count of bytes */
+	size_t (*read)(struct cbfs_media *media, void *dest, size_t offset,
+		       size_t count);
+
+	/* returns a pointer to memory with count of bytes from media source
+	 * starting from offset, or CBFS_MEDIA_INVALID_MAP_ADDRESS on failure */
+	void * (*map)(struct cbfs_media *media, size_t offset, size_t count);
+
+	/* returns NULL and releases the memory by address, which was allocated
+	 * by map */
+	void * (*unmap)(struct cbfs_media *media, const void *address);
+
+	/* closes media and returns 0 on success, -1 on failure.
+	 * Note closing media won't free mapped data unless unmap is called
+	 * explicitly. */
+	int (*close)(struct cbfs_media *media);
+};
+
+/* returns pointer to a file entry inside CBFS or NULL */
+struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name);
+
+/* returns pointer to file content inside CBFS after if type is correct */
+void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
+			    int type);
 
 /* returns 0 on success, -1 on failure */
 int cbfs_decompress(int algo, void *src, void *dst, int len);
-struct cbfs_header *get_cbfs_header(void);
+
+/* returns a pointer to CBFS master header, or CBFS_HEADER_INVALID_ADDRESS
+ *  on failure */
+const struct cbfs_header *cbfs_get_header(struct cbfs_media *media);
+
 #endif
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
index 98672d4..f8ddaa1 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -28,8 +28,6 @@
 #ifndef __SMM__
 #define CBFS_CORE_WITH_LZMA
 #endif
-#define phys_to_virt(x) (void*)(x)
-#define virt_to_phys(x) (uint32_t)(x)
 #define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
 #define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
 #if CONFIG_DEBUG_CBFS
@@ -37,9 +35,13 @@
 #else
 #define DEBUG(x...)
 #endif
-// FIXME: romstart/romend are fine on x86, but not on ARM
-#define romstart() 0xffffffff
-#define romend() 0
+
+#ifdef CONFIG_CBFS_HEADER_ROM_OFFSET
+# define CBFS_HEADER_ROM_ADDRESS (CONFIG_CBFS_HEADER_ROM_OFFSET)
+#else
+// Indirect ROM address
+# define CBFS_HEADER_ROM_ADDRESS *(uint32_t*)0xfffffffc
+#endif
 
 #include "cbfs_core.c"
 
@@ -57,7 +59,8 @@ static void tohex16(unsigned int val, char* dest)
 	dest[3]=tohex4(val & 0xf);
 }
 
-void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest)
+void *cbfs_load_optionrom(struct cbfs_media *media,
+			  u16 vendor, u16 device, void *dest)
 {
 	char name[17]="pciXXXX,XXXX.rom";
 	struct cbfs_optionrom *orom;
@@ -67,7 +70,7 @@ void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest)
 	tohex16(device, name+8);
 
 	orom = (struct cbfs_optionrom *)
-		cbfs_find_file(name, CBFS_TYPE_OPTIONROM);
+		cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM);
 
 	if (orom == NULL)
 		return NULL;
@@ -94,10 +97,10 @@ void *cbfs_load_optionrom(u16 vendor, u16 device, void * dest)
 	return dest;
 }
 
-void * cbfs_load_stage(const char *name)
+void * cbfs_load_stage(struct cbfs_media *media, const char *name)
 {
 	struct cbfs_stage *stage = (struct cbfs_stage *)
-		cbfs_find_file(name, CBFS_TYPE_STAGE);
+		cbfs_get_file_content(media, name, CBFS_TYPE_STAGE);
 	/* this is a mess. There is no ntohll. */
 	/* for now, assume compatible byte order until we solve this. */
 	u32 entry;
@@ -126,10 +129,10 @@ void * cbfs_load_stage(const char *name)
 	return (void *) entry;
 }
 
-int cbfs_execute_stage(const char *name)
+int cbfs_execute_stage(struct cbfs_media *media, const char *name)
 {
 	struct cbfs_stage *stage = (struct cbfs_stage *)
-		cbfs_find_file(name, CBFS_TYPE_STAGE);
+		cbfs_get_file_content(media, name, CBFS_TYPE_STAGE);
 
 	if (stage == NULL)
 		return 1;
@@ -145,6 +148,17 @@ int cbfs_execute_stage(const char *name)
 	return run_address((void *) (intptr_t)ntohll(stage->entry));
 }
 
+void *cbfs_load_payload(struct cbfs_media *media, struct lb_memory *lb_mem,
+			const char *name)
+{
+	struct cbfs_payload *payload;
+
+	payload = (struct cbfs_payload *)cbfs_get_file_content(
+			media, name, CBFS_TYPE_PAYLOAD);
+
+	return payload;
+}
+
 /**
  * run_address is passed the address of a function taking no parameters and
  * jumps to it, returning the result.
@@ -158,4 +172,5 @@ int run_address(void *f)
 	v = f;
 	return v();
 }
+
 #endif
diff --git a/src/lib/cbfs_core.c b/src/lib/cbfs_core.c
index 15cb68e..084a15e 100644
--- a/src/lib/cbfs_core.c
+++ b/src/lib/cbfs_core.c
@@ -27,14 +27,14 @@
  * SUCH DAMAGE.
  */
 
-/* The CBFS core requires a couple of #defines or functions to adapt it to the target environment:
+/* The CBFS core requires a couple of #defines or functions to adapt it to the
+ * target environment:
  *
  * CBFS_CORE_WITH_LZMA (must be #define)
  *      if defined, ulzma() must exist for decompression of data streams
  *
- * phys_to_virt(x), virt_to_phys(x)
- *      translate physical addresses to virtual and vice versa
- *      can be idempotent if no mapping is necessary.
+ * CBFS_HEADER_ROM_ADDRESS
+ *	ROM address of CBFS header.
  *
  * ERROR(x...)
  *      print an error message x (in printf format)
@@ -45,105 +45,107 @@
  * DEBUG(x...)
  *      print a debug message x (in printf format)
  *
- * romstart()
- *      returns the start address of the ROM image, or 0xffffffff if ROM is
- *      top-aligned. This is a physical address.
- *
- * romend()
- *      returns the highest address of the ROM image + 1, for use if
- *      romstart() == 0xffffffff. This is a physical address.
  */
 
 #include <cbfs_core.h>
+#include <assert.h>
 
-
-/* returns pointer to master header or 0xffffffff if not found */
-struct cbfs_header *get_cbfs_header(void)
+/* returns a pointer to CBFS master header, or CBFS_HEADER_INVALID_ADDRESS
+ *  on failure */
+const struct cbfs_header *cbfs_get_header(struct cbfs_media *media)
 {
-	struct cbfs_header *header;
-
-	/* find header */
-	if (romstart() == 0xffffffff) {
-		header = (struct cbfs_header*)phys_to_virt(*(uint32_t*)phys_to_virt(romend() + CBFS_HEADPTR_ADDR));
-	} else {
-		// FIXME: where's the master header on ARM (our current bottom-aligned platform)?
-		header = NULL;
+	const struct cbfs_header *header;
+
+	media->open(media);
+	header = media->map(media, CBFS_HEADER_ROM_ADDRESS, sizeof(*header));
+	media->close(media);
+
+	if (header == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
+		ERROR("Failed to load CBFS header from 0x%x\n",
+		      CBFS_HEADER_ROM_ADDRESS);
+		return CBFS_HEADER_INVALID_ADDRESS;
 	}
+
 	if (CBFS_HEADER_MAGIC != ntohl(header->magic)) {
-		ERROR("Could not find valid CBFS master header at %p: %x vs %x.\n", header, CBFS_HEADER_MAGIC, ntohl(header->magic));
+		ERROR("Could not find valid CBFS master header at %x: "
+		      "%x vs %x.\n", CBFS_HEADER_ROM_ADDRESS, CBFS_HEADER_MAGIC,
+		      ntohl(header->magic));
 		if (header->magic == 0xffffffff) {
 			ERROR("Maybe ROM is not mapped properly?\n");
 		}
-		return (void*)0xffffffff;
+		return CBFS_HEADER_INVALID_ADDRESS;
 	}
 	return header;
 }
 
-// by must be power-of-two
-#define CBFS_ALIGN(val, by) (typeof(val))((uint32_t)(val + by - 1) & (uint32_t)~(by - 1))
-#define CBFS_ALIGN_UP(val, by) CBFS_ALIGN(val + 1, by)
-
 /* public API starts here*/
-struct cbfs_file *cbfs_find(const char *name)
+struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name)
 {
-	struct cbfs_header *header = get_cbfs_header();
-	if (header == (void*)0xffffffff) return NULL;
-
-	LOG("Looking for '%s'\n", name);
-
-	void *data, *dataend, *origdata;
-	/* find first entry */
-	if (romstart() == 0xffffffff) {
-		data = (void*)phys_to_virt(romend()) - ntohl(header->romsize) + ntohl(header->offset);
-		dataend = (void*)phys_to_virt(romend());
-	} else {
-		data = (void*)phys_to_virt(romstart()) + ntohl(header->offset);
-		dataend = (void*)phys_to_virt(romstart()) + ntohl(header->romsize);
-	}
-	dataend -= ntohl(header->bootblocksize);
-
-	int align = ntohl(header->align);
-
-	origdata = data;
-	while ((data < (dataend - 1)) && (data >= origdata)) {
-		struct cbfs_file *file = data;
-		if (memcmp(CBFS_FILE_MAGIC, file->magic, strlen(CBFS_FILE_MAGIC)) != 0) {
-			// no file header found. corruption?
-			// proceed in aligned steps to resynchronize
-			LOG("ERROR: No file header found at %p, attempting to recover by searching for header\n", data);
-			data = phys_to_virt(CBFS_ALIGN_UP(virt_to_phys(data), align));
+	const struct cbfs_header *header;
+	struct cbfs_file file, *file_ptr;
+	const char *file_name;
+	uint32_t offset, align, romsize;
+
+	if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media)))
+		return NULL;
+
+	// Logical offset (for source media) of first file.
+	offset = ntohl(header->offset);
+	align = ntohl(header->align);
+
+	// TODO header->romsize seems broken now on ARM.
+	// Let's trust CONFIG_ROM_SIZE.
+#if CONFIG_ROM_SIZE
+	romsize = CONFIG_ROM_SIZE;
+#else
+	romsize = ntohl(header->romsize);
+#endif
+	LOG("offset: %d, align: %d, romsize: %d\n", offset, align, romsize);
+
+	LOG("Looking for '%s' starting from 0x%x.\n", name, offset);
+	media->open(media);
+	while (offset < romsize && media->read(media, &file, offset,
+					       sizeof(file)) == sizeof(file)) {
+		if (memcmp(CBFS_FILE_MAGIC, file.magic,
+			   sizeof(file.magic)) != 0) {
+			// No file header found. Corruption?  Proceed in aligned
+			// steps to resynchronize.
+			LOG("ERROR: No file header found at 0x%x.", offset);
+			offset += align;
 			continue;
 		}
-		DEBUG("Check '%s'\n", CBFS_NAME(file));
-		if (strcmp(CBFS_NAME(file), name) == 0) {
-			LOG("found.\n");
-			return file;
-		}
-		void *olddata = data;
-		data = phys_to_virt(CBFS_ALIGN(virt_to_phys(data) + ntohl(file->len) + ntohl(file->offset), align));
-		if (olddata > data) {
-			LOG("Something is wrong here. File chain moved from %p to %p\n", olddata, data);
-			return NULL;
-		}
-	}
-	return NULL;
-}
 
-void *cbfs_get_file(const char *name)
-{
-	struct cbfs_file *file = cbfs_find(name);
+		// load file name (arbitrary length).
+		file_name = (const char*)media->map(
+				media, offset + sizeof(file),
+				ntohl(file.offset) - sizeof(file));
+		if (file_name == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
+			LOG("ERROR: Failed to get file name at 0x%x.", offset);
+		} else if (strcmp(file_name, name) == 0) {
+			media->unmap(media, file_name);
+			file_ptr = media->map(
+					media, offset,
+					ntohl(file.offset) + ntohl(file.len));
+			media->close(media);
+			return file_ptr;
+		} else {
+			DEBUG("Incorrect - %s at 0x%x\n", file_name, offset);
+			media->unmap(media, file_name);
+		}
 
-	if (file == NULL) {
-		ERROR("Could not find file '%s'.\n", name);
-		return NULL;
+		// Move to next file.
+		offset += ntohl(file.len) + ntohl(file.offset);
+		if (offset % align)
+			offset += align - (offset % align);
 	}
-
-	return (void*)CBFS_SUBHEADER(file);
+	media->close(media);
+	LOG("ERROR: Not found.\n");
+	return NULL;
 }
 
-void *cbfs_find_file(const char *name, int type)
+void *cbfs_get_file_content(struct cbfs_media *media, const char *name, int type)
 {
-	struct cbfs_file *file = cbfs_find(name);
+	struct cbfs_file *file = cbfs_get_file(media, name);
 
 	if (file == NULL) {
 		ERROR("Could not find file '%s'.\n", name);
@@ -151,7 +153,8 @@ void *cbfs_find_file(const char *name, int type)
 	}
 
 	if (ntohl(file->type) != type) {
-		ERROR("File '%s' is of type %x, but we requested %x.\n", name, ntohl(file->type), type);
+		ERROR("File '%s' is of type %x, but we requested %x.\n", name,
+		      ntohl(file->type), type);
 		return NULL;
 	}
 
@@ -172,7 +175,9 @@ int cbfs_decompress(int algo, void *src, void *dst, int len)
 			return -1;
 #endif
 		default:
-			ERROR("tried to decompress %d bytes with algorithm #%x, but that algorithm id is unsupported.\n", len, algo);
+			ERROR("tried to decompress %d bytes with algorithm #%x,"
+			      "but that algorithm id is unsupported.\n", len,
+			      algo);
 			return -1;
 	}
 }
diff --git a/src/lib/hardwaremain.c b/src/lib/hardwaremain.c
index eed243a..10ccd14 100644
--- a/src/lib/hardwaremain.c
+++ b/src/lib/hardwaremain.c
@@ -59,6 +59,7 @@ void hardwaremain(int boot_complete);
 void hardwaremain(int boot_complete)
 {
 	struct lb_memory *lb_mem;
+	void *payload;
 
 	timestamp_stash(TS_START_RAMSTAGE);
 	post_code(POST_ENTRY_RAMSTAGE);
@@ -141,8 +142,8 @@ void hardwaremain(int boot_complete)
 
 	timestamp_add_now(TS_LOAD_PAYLOAD);
 
-	void *payload;
-	payload = cbfs_load_payload(lb_mem, CONFIG_CBFS_PREFIX "/payload");
+	// TODO FIXME replace NULL by default stream.
+	payload = cbfs_load_payload(NULL, lb_mem, CONFIG_CBFS_PREFIX "/payload");
 	if (! payload)
 		die("Could not find a payload\n");
 
diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c
index c5fb62a..56124da 100644
--- a/src/lib/selfboot.c
+++ b/src/lib/selfboot.c
@@ -536,12 +536,3 @@ out:
 	return 0;
 }
 
-void *cbfs_load_payload(struct lb_memory *lb_mem, const char *name)
-{
-	struct cbfs_payload *payload;
-
-	payload = (struct cbfs_payload *)cbfs_find_file(name, CBFS_TYPE_PAYLOAD);
-
-	return payload;
-}
-
diff --git a/src/mainboard/google/snow/bootblock.c b/src/mainboard/google/snow/bootblock.c
index d5ee0a3..a53c913 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -34,6 +34,7 @@
 #include "cpu/samsung/s5p-common/s3c24x0_i2c.h"
 #include "cpu/samsung/exynos5-common/spi.h"
 #include "cpu/samsung/exynos5-common/uart.h"
+#include "cbfs_core.h"
 
 #include <device/i2c.h>
 #include <drivers/maxim/max77686/max77686.h>
@@ -42,6 +43,7 @@
 
 #define EXYNOS5_CLOCK_BASE		0x10010000
 
+#if 0
 /* FIXME(dhendrix): Can we move this SPI stuff elsewhere? */
 static void spi_rx_tx(struct exynos_spi *regs, int todo,
 			void *dinp, void const *doutp, int i)
@@ -77,6 +79,7 @@ static void spi_rx_tx(struct exynos_spi *regs, int todo,
 		}
 	}
 }
+#endif
 
 #if 0
 void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor)
@@ -358,77 +361,6 @@ void gpio_cfg_pin(int gpio, int cfg)
 	writel(value, &bank->con);
 }
 
-//static void exynos_spi_copy(unsigned int uboot_size)
-static void copy_romstage(uint32_t spi_addr, uint32_t sram_addr, unsigned int len)
-{
-	int upto, todo;
-	int i;
-//	struct exynos_spi *regs = (struct exynos_spi *)samsung_get_base_spi1();
-	struct exynos_spi *regs = (struct exynos_spi *)0x12d30000;
-
-	clock_set_rate(PERIPH_ID_SPI1, 50000000); /* set spi clock to 50Mhz */
-	/* set the spi1 GPIO */
-//	exynos_pinmux_config(PERIPH_ID_SPI1, PINMUX_FLAG_NONE);
-	gpio_cfg_pin(GPIO_A24, 0x2);
-	gpio_cfg_pin(GPIO_A25, 0x2);
-	gpio_cfg_pin(GPIO_A26, 0x2);
-	gpio_cfg_pin(GPIO_A27, 0x2);
-
-	/* set pktcnt and enable it */
-	writel(4 | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
-	/* set FB_CLK_SEL */
-	writel(SPI_FB_DELAY_180, &regs->fb_clk);
-	/* set CH_WIDTH and BUS_WIDTH as word */
-	setbits_le32(&regs->mode_cfg, SPI_MODE_CH_WIDTH_WORD |
-					SPI_MODE_BUS_WIDTH_WORD);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_CPOL_L); /* CPOL: active high */
-
-	/* clear rx and tx channel if set priveously */
-	clrbits_le32(&regs->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON);
-
-	setbits_le32(&regs->swap_cfg, SPI_RX_SWAP_EN |
-		SPI_RX_BYTE_SWAP |
-		SPI_RX_HWORD_SWAP);
-
-	/* do a soft reset */
-	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
-
-	/* now set rx and tx channel ON */
-	setbits_le32(&regs->ch_cfg, SPI_RX_CH_ON | SPI_TX_CH_ON | SPI_CH_HS_EN);
-	clrbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT); /* CS low */
-
-	/* Send read instruction (0x3h) followed by a 24 bit addr */
-	writel((SF_READ_DATA_CMD << 24) | spi_addr, &regs->tx_data);
-
-	/* waiting for TX done */
-	while (!(readl(&regs->spi_sts) & SPI_ST_TX_DONE));
-
-	for (upto = 0, i = 0; upto < len; upto += todo, i++) {
-		todo = MIN(len - upto, (1 << 15));
-		spi_rx_tx(regs, todo, (void *)(sram_addr),
-					(void *)(spi_addr), i);
-	}
-
-	setbits_le32(&regs->cs_reg, SPI_SLAVE_SIG_INACT);/* make the CS high */
-
-	/*
-	 * Let put controller mode to BYTE as
-	 * SPI driver does not support WORD mode yet
-	 */
-	clrbits_le32(&regs->mode_cfg, SPI_MODE_CH_WIDTH_WORD |
-					SPI_MODE_BUS_WIDTH_WORD);
-	writel(0, &regs->swap_cfg);
-
-	/*
-	 * Flush spi tx, rx fifos and reset the SPI controller
-	 * and clear rx/tx channel
-	 */
-	clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
-}
-
 /* Pull mode */
 #define EXYNOS_GPIO_PULL_NONE	0x0
 #define EXYNOS_GPIO_PULL_DOWN	0x1
@@ -2141,13 +2073,6 @@ void bootblock_mainboard_init(void)
 	do_serial();
 	printk(BIOS_INFO, "%s: UART initialized\n", __func__);
 
-	/* Copy romstage data from SPI ROM to SRAM */
-	printk(BIOS_INFO, "Copying romstage:\n"
-			"\tSPI offset: 0x%06x\n"
-			"\tiRAM offset: 0x%08x\n"
-			"\tSize: 0x%x\n",
-			0, CONFIG_SPI_IMAGE_HACK, CONFIG_ROMSTAGE_SIZE);
-	copy_romstage(0x0, CONFIG_SPI_IMAGE_HACK, CONFIG_ROMSTAGE_SIZE);
 #if 0
 	/* FIXME: dump SRAM content for sanity checking */
 	uint32_t u;



More information about the coreboot mailing list