[coreboot] Patch set updated for coreboot: 814a13c Extend CBFS to support arbitrary ROM source media.

Hung-Te Lin (hungte@chromium.org) gerrit at coreboot.org
Fri Jan 25 01:57:02 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 814a13c9c6033fb338a52086fef3df42b45de591
Author: Hung-Te Lin <hungte at chromium.org>
Date:   Tue Jan 22 18:57:56 2013 +0800

    Extend CBFS to support arbitrary ROM source media.
    
    Summary:
    	CBFS functions now all take a new "media source" parameter; use
    	CBFS_DEFAULT_MEDIA if you simply want to load from main firmware.
    	API Changes:
    		cbfs_find => cbfs_get_file
    		cbfs_find_file => cbfs_get_file_content
    
    CBFS used to work only on memory-mapped ROM (all x86). For platforms like ARM,
    the ROM may come from USB, UART, or SPI -- any serial devices and not available
    for memory mapping.
    
    To support these devices (or allowing CBFS to read from multiple source
    at the same time), CBFS operations are now virtual-ized into "cbfs_media".  To
    simplify porting existing code, every media source must support both "reading
    into pre-allocated memory (read)" and "read and return an allocated buffer
    (map)". For devices without native memory-mapped ROM, "cbfs_simple_buffer*"
    provides simple memory mapping simulation.
    
    Every CBFS function now takes a cbfs_media* as parameter. CBFS_DEFAULT_MEDIA
    is defined for CBFS functions to automatically initialize a per-board default
    media (CBFS will internally calls init_default_cbfs_media).  Also revised CBFS
    function names relying on memory mapped backend (ex, "cbfs_find" => actually
    loads files). Now we only have two getters:
    	struct cbfs_file *entry = cbfs_get_file(media, name);
    	void *data = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, name, type);
    
    Test results:
     - Verified to work on ARM (loaded romstage properly for Google/Snow).
     - Verified to work on x86/qemu.
    
    Change-Id: Iac911ded25a6f2feffbf3101a81364625bb07746
    Signed-off-by: Hung-Te Lin <hungte at chromium.org>
---
 src/arch/armv7/boot/coreboot_table.c               |   4 +-
 src/arch/armv7/bootblock_simple.c                  |   4 +-
 src/arch/armv7/include/arch/cbfs.h                 | 101 +++----
 src/arch/x86/boot/coreboot_table.c                 |   4 +-
 src/arch/x86/boot/smbios.c                         |  14 +-
 src/arch/x86/lib/Makefile.inc                      |   3 +
 src/arch/x86/lib/cbfs_and_run.c                    |   2 +-
 src/arch/x86/lib/rom_media.c                       |  62 +++++
 src/cpu/intel/microcode/microcode.c                |   5 +-
 src/cpu/samsung/exynos5-common/Makefile.inc        |   4 +-
 src/cpu/samsung/exynos5-common/spi.c               | 233 +++++++++++++++++
 src/cpu/samsung/exynos5-common/spi.h               |  13 +
 src/cpu/samsung/exynos5-common/spl_boot.c          | 291 ---------------------
 src/cpu/samsung/exynos5250/Kconfig                 |   8 +
 src/cpu/via/nano/update_ucode.c                    |   2 +-
 src/device/oprom/realmode/x86.c                    |   8 +-
 src/device/oprom/yabel/vbe.c                       |   4 +-
 src/device/pci_rom.c                               |   9 +-
 src/drivers/pc80/mc146818rtc.c                     |   6 +-
 src/include/cbfs.h                                 |  32 ++-
 src/include/cbfs_core.h                            |  69 +++--
 src/lib/cbfs.c                                     |  75 +++++-
 src/lib/cbfs_core.c                                | 196 ++++++++------
 src/lib/hardwaremain.c                             |   5 +-
 src/lib/selfboot.c                                 |   9 -
 src/mainboard/google/snow/bootblock.c              | 253 +-----------------
 src/mainboard/samsung/lumpy/romstage.c             |   2 +-
 .../amd/agesa/family15tn/fam15tn_callouts.c        |   4 +-
 src/northbridge/intel/i82830/vga.c                 |   2 +-
 src/northbridge/intel/sandybridge/raminit.c        |   4 +-
 30 files changed, 669 insertions(+), 759 deletions(-)

diff --git a/src/arch/armv7/boot/coreboot_table.c b/src/arch/armv7/boot/coreboot_table.c
index 86a004d..b2d88aa 100644
--- a/src/arch/armv7/boot/coreboot_table.c
+++ b/src/arch/armv7/boot/coreboot_table.c
@@ -640,7 +640,9 @@ unsigned long write_coreboot_table(
 
 #if CONFIG_USE_OPTION_TABLE
 	{
-		struct cmos_option_table *option_table = cbfs_find_file("cmos_layout.bin", 0x1aa);
+		struct cmos_option_table *option_table = cbfs_get_file_content(
+				CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
+				CBFS_COMPONENT_CMOS_LAYOUT);
 		if (option_table) {
 			struct lb_record *rec_dest = lb_new_record(head);
 			/* Copy the option config table, it's already a lb_record... */
diff --git a/src/arch/armv7/bootblock_simple.c b/src/arch/armv7/bootblock_simple.c
index af76d4c..d97075e 100644
--- a/src/arch/armv7/bootblock_simple.c
+++ b/src/arch/armv7/bootblock_simple.c
@@ -45,7 +45,9 @@ void main(unsigned long bist)
 	}
 
 	printk(BIOS_INFO, "bootblock main(): loading romstage\n");
-	romstage_entry = loadstage(target1);
+	romstage_entry = (unsigned long)cbfs_load_stage(
+			CBFS_DEFAULT_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..e34a0d2 100644
--- a/src/arch/armv7/include/arch/cbfs.h
+++ b/src/arch/armv7/include/arch/cbfs.h
@@ -20,82 +20,41 @@
 #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>
 
+// TODO FIXME This file is only for providing CBFS function in bootblock.
+// Should be removed once bootblock can link lib/* files.
+#include "lib/cbfs.c"
 
-static int cbfs_check_magic(struct cbfs_file *file)
-{
-	return strcmp(file->magic, CBFS_FILE_MAGIC) ? 0 : 1;
+// mem* and ulzma are now workarounds for bootblock compilation.
+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;
 }
 
-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");
+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;
+}
 
-	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;
-	}
+unsigned long ulzma(unsigned char *src, unsigned char *dest) {
+	// TODO remove this.
+	return -1;
 }
-#endif
+
+#endif // __INCLUDE_ARCH_CBFS__
diff --git a/src/arch/x86/boot/coreboot_table.c b/src/arch/x86/boot/coreboot_table.c
index 8dccd77..04fba47 100644
--- a/src/arch/x86/boot/coreboot_table.c
+++ b/src/arch/x86/boot/coreboot_table.c
@@ -638,7 +638,9 @@ unsigned long write_coreboot_table(
 
 #if CONFIG_USE_OPTION_TABLE
 	{
-		struct cmos_option_table *option_table = cbfs_find_file("cmos_layout.bin", 0x1aa);
+		struct cmos_option_table *option_table = cbfs_get_file_content(
+				CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
+				CBFS_COMPONENT_CMOS_LAYOUT);
 		if (option_table) {
 			struct lb_record *rec_dest = lb_new_record(head);
 			/* Copy the option config table, it's already a lb_record... */
diff --git a/src/arch/x86/boot/smbios.c b/src/arch/x86/boot/smbios.c
index 72e70ba..314816e 100644
--- a/src/arch/x86/boot/smbios.c
+++ b/src/arch/x86/boot/smbios.c
@@ -120,7 +120,6 @@ static int smbios_processor_name(char *start)
 
 static int smbios_write_type0(unsigned long *current, int handle)
 {
-	struct cbfs_header *hdr;
 	struct smbios_type0 *t = (struct smbios_type0 *)*current;
 	int len = sizeof(struct smbios_type0);
 
@@ -143,8 +142,17 @@ 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)
-		t->bios_rom_size = (ntohl(hdr->romsize) / 65535) - 1;
+	// TODO cache the value or always trust CONFIG_ROM_SIZE?
+	{
+		const struct cbfs_header *header;
+		header = cbfs_get_header(CBFS_DEFAULT_MEDIA);
+		if (header != CBFS_HEADER_INVALID_ADDRESS)
+			t->bios_rom_size = (ntohl(header->romsize) / 65535) - 1;
+		else
+			t->bios_rom_size = (CONFIG_ROM_SIZE / 65535) - 1;
+	}
+
+
 	t->system_bios_major_release = 4;
 	t->bios_characteristics =
 		BIOS_CHARACTERISTICS_PCI_SUPPORTED |
diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc
index 2186072..f4dc8b8 100644
--- a/src/arch/x86/lib/Makefile.inc
+++ b/src/arch/x86/lib/Makefile.inc
@@ -8,13 +8,16 @@ ramstage-$(CONFIG_IOAPIC) += ioapic.c
 ramstage-y += memset.c
 ramstage-y += memcpy.c
 ramstage-y += ebda.c
+ramstage-y += rom_media.c
 
 romstage-y += romstage_console.c
 romstage-y += cbfs_and_run.c
 romstage-y += memset.c
 romstage-y += memcpy.c
+romstage-y += rom_media.c
 
 smm-y += memset.c
 smm-y += memcpy.c
+smm-y += rom_media.c
 
 $(obj)/arch/x86/lib/console.ramstage.o :: $(obj)/build.h
diff --git a/src/arch/x86/lib/cbfs_and_run.c b/src/arch/x86/lib/cbfs_and_run.c
index 1f87e7a..a023141 100644
--- a/src/arch/x86/lib/cbfs_and_run.c
+++ b/src/arch/x86/lib/cbfs_and_run.c
@@ -28,7 +28,7 @@ static void cbfs_and_run_core(const char *filename, unsigned ebp)
 
 	timestamp_add_now(TS_START_COPYRAM);
 	print_debug("Loading image.\n");
-	dst = cbfs_load_stage(filename);
+	dst = cbfs_load_stage(CBFS_DEFAULT_MEDIA, filename);
 	if ((void *)dst == (void *) -1)
 		die("FATAL: Essential component is missing.\n");
 
diff --git a/src/arch/x86/lib/rom_media.c b/src/arch/x86/lib/rom_media.c
new file mode 100644
index 0000000..707b7f4
--- /dev/null
+++ b/src/arch/x86/lib/rom_media.c
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 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 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 <stdint.h>
+#include <string.h>
+#include <cbfs.h>
+
+// Implementation of memory-mapped ROM media source on X86.
+
+static int x86_rom_open(struct cbfs_media *media) {
+	return 0;
+}
+
+static void *x86_rom_map(struct cbfs_media *media, size_t offset, size_t count) {
+	void *ptr = (void*)((uint32_t)0x0 - CONFIG_ROM_SIZE + offset);
+	return ptr;
+}
+
+static void *x86_rom_unmap(struct cbfs_media *media, const void *address) {
+	return NULL;
+}
+
+static size_t x86_rom_read(struct cbfs_media *media, void *dest, size_t offset,
+			   size_t count) {
+	void *ptr = x86_rom_map(media, offset, count);
+	memcpy(dest, ptr, count);
+	x86_rom_unmap(media, ptr);
+	return count;
+}
+
+static int x86_rom_close(struct cbfs_media *media) {
+	return 0;
+}
+
+int init_default_cbfs_media(struct cbfs_media *media) {
+	media->context = (void*)CONFIG_ROM_SIZE;
+	media->open = x86_rom_open;
+	media->close = x86_rom_close;
+	media->map = x86_rom_map;
+	media->unmap = x86_rom_unmap;
+	media->read = x86_rom_read;
+	// TODO revise rom size by searching for cbfs_header->romsize.
+	return 0;
+}
diff --git a/src/cpu/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c
index 15d6513..713a6df 100644
--- a/src/cpu/intel/microcode/microcode.c
+++ b/src/cpu/intel/microcode/microcode.c
@@ -166,8 +166,9 @@ void intel_update_microcode_from_cbfs(void)
 #ifdef __PRE_RAM__
 	microcode_blob = walkcbfs((char *) MICROCODE_CBFS_FILE);
 #else
-	microcode_blob = cbfs_find_file(MICROCODE_CBFS_FILE,
-					CBFS_TYPE_MICROCODE);
+	microcode_blob = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
+					       MICROCODE_CBFS_FILE,
+					       CBFS_TYPE_MICROCODE);
 #endif
 	intel_update_microcode(microcode_blob);
 }
diff --git a/src/cpu/samsung/exynos5-common/Makefile.inc b/src/cpu/samsung/exynos5-common/Makefile.inc
index cad6cb3..d919347 100644
--- a/src/cpu/samsung/exynos5-common/Makefile.inc
+++ b/src/cpu/samsung/exynos5-common/Makefile.inc
@@ -1,2 +1,2 @@
-#romstage-y += soc.c
-romstage-y += spl_boot.c
+romstage-y += spi.c
+ramstage-y += spi.c
diff --git a/src/cpu/samsung/exynos5-common/spi.c b/src/cpu/samsung/exynos5-common/spi.c
new file mode 100644
index 0000000..ce64b5f
--- /dev/null
+++ b/src/cpu/samsung/exynos5-common/spi.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* FIXME(dhendrix): pulled in a lot of extra crap such as partition and string
+   libs*/
+#include <assert.h>
+#include <common.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <console/console.h>
+#include <console/loglevel.h>
+
+#include <config.h>
+#include <spi.h>
+
+#include <cpu/samsung/exynos5250/gpio.h>
+#include <cpu/samsung/exynos5250/clk.h>
+#include <cpu/samsung/exynos5250/cpu.h>
+#include <cpu/samsung/exynos5250/periph.h>
+#include <cpu/samsung/exynos5250/pinmux.h>
+
+#include <cpu/samsung/exynos5-common/cpu.h>
+#include <cpu/samsung/exynos5-common/exynos5-common.h>
+#include <cpu/samsung/exynos5-common/spi.h>
+
+#include <system.h>
+#include <arch/io.h>
+#include <lib.h>
+
+#define OM_STAT		(0x1f << 1)
+#define EXYNOS_BASE_SPI1 ((void *)0x12d30000)
+
+static void exynos_spi_rx_tx(struct exynos_spi *regs, int todo,
+			     void *dinp, void const *doutp, int i)
+{
+	int rx_lvl, tx_lvl;
+	uint *rxp = (uint *)(dinp + (i * (32 * 1024)));
+	uint out_bytes, in_bytes;
+
+	out_bytes = in_bytes = todo;
+	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
+	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+	writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
+
+	while (in_bytes) {
+		uint32_t spi_sts;
+		int temp;
+
+		spi_sts = readl(&regs->spi_sts);
+		rx_lvl = ((spi_sts >> 15) & 0x7f);
+		tx_lvl = ((spi_sts >> 6) & 0x7f);
+		while (tx_lvl < 32 && out_bytes) {
+			temp = 0xffffffff;
+			writel(temp, &regs->tx_data);
+			out_bytes -= 4;
+			tx_lvl += 4;
+		}
+		while (rx_lvl >= 4 && in_bytes) {
+			temp = readl(&regs->rx_data);
+			if (rxp)
+				*rxp++ = temp;
+			in_bytes -= 4;
+			rx_lvl -= 4;
+		}
+	}
+}
+
+int exynos_spi_open(struct exynos_spi *regs)
+{
+	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 */
+	return 0;
+}
+
+int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off)
+{
+	int upto, todo;
+	int i;
+	/* Send read instruction (0x3h) followed by a 24 bit addr */
+	writel((SF_READ_DATA_CMD << 24) | off, &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));
+		exynos_spi_rx_tx(regs, todo, dest, (void *)(off), 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);
+
+	return len;
+}
+
+int exynos_spi_close(struct exynos_spi *regs)
+{
+	/*
+	 * 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);
+	return 0;
+}
+
+// SPI as CBFS media.
+struct exynos_spi_media {
+	struct exynos_spi *regs;
+	struct cbfs_simple_buffer buffer;
+};
+
+static int exynos_spi_cbfs_open(struct cbfs_media *media) {
+	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
+	printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_open\n");
+	return exynos_spi_open(spi->regs);
+}
+
+static int exynos_spi_cbfs_close(struct cbfs_media *media) {
+	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
+	printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_close\n");
+	return exynos_spi_close(spi->regs);
+}
+
+static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest,
+				   size_t offset, size_t count) {
+	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
+	int bytes;
+	printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_read\n");
+	bytes = exynos_spi_read(spi->regs, dest, count, offset);
+	// Flush and re-open the device.
+	exynos_spi_close(spi->regs);
+	exynos_spi_open(spi->regs);
+	return bytes;
+}
+
+static void *exynos_spi_cbfs_map(struct cbfs_media *media, size_t offset,
+				 size_t count) {
+	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
+	printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_map\n");
+	return cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
+}
+
+static void *exynos_spi_cbfs_unmap(struct cbfs_media *media,
+				   const void *address) {
+	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
+	printk(BIOS_SPEW, "SPI: exynos_spi_cbfs_unmap\n");
+	return cbfs_simple_buffer_unmap(&spi->buffer, address);
+}
+
+int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
+				     void *buffer_address,
+				     size_t buffer_size) {
+	// TODO Replace static variable to support multiple streams.
+	static struct exynos_spi_media context;
+	printk(BIOS_SPEW, "SPI: initialize_exynos_spi_cbfs_media\n");
+
+	context.regs = EXYNOS_BASE_SPI1;
+	context.buffer.allocated = context.buffer.last_allocate = 0;
+	context.buffer.buffer = buffer_address;
+	context.buffer.size = buffer_size;
+	media->context = (void*)&context;
+	media->open = exynos_spi_cbfs_open;
+	media->close = exynos_spi_cbfs_close;
+	media->read = exynos_spi_cbfs_read;
+	media->map = exynos_spi_cbfs_map;
+	media->unmap = exynos_spi_cbfs_unmap;
+
+	return 0;
+}
+
+int init_default_cbfs_media(struct cbfs_media *media) {
+	// TODO make 0x17000 (size of cache) a Kconfig variable, or calculate by
+	// top of IRAM.
+	return initialize_exynos_spi_cbfs_media(
+			media, (void*)CONFIG_CBFS_CACHE_ADDRESS, 0x17000);
+}
diff --git a/src/cpu/samsung/exynos5-common/spi.h b/src/cpu/samsung/exynos5-common/spi.h
index 3f36759..e021888 100644
--- a/src/cpu/samsung/exynos5-common/spi.h
+++ b/src/cpu/samsung/exynos5-common/spi.h
@@ -22,6 +22,9 @@
 
 #ifndef __ASSEMBLER__
 
+// This driver serves as a CBFS media source.
+#include <cbfs.h>
+
 /* SPI peripheral register map; padded to 64KB */
 struct exynos_spi {
 	unsigned int		ch_cfg;		/* 0x00 */
@@ -85,5 +88,15 @@ struct exynos_spi {
 #define SPI_RX_BYTE_SWAP	(1 << 6)
 #define SPI_RX_HWORD_SWAP	(1 << 7)
 
+/* API */
+int exynos_spi_open(struct exynos_spi *regs);
+int exynos_spi_read(struct exynos_spi *regs, void *dest, u32 len, u32 off);
+int exynos_spi_close(struct exynos_spi *regs);
+
+/* Serve as CBFS Media */
+int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
+				     void *buffer_address,
+				     size_t buffer_size);
+
 #endif /* __ASSEMBLER__ */
 #endif
diff --git a/src/cpu/samsung/exynos5-common/spl_boot.c b/src/cpu/samsung/exynos5-common/spl_boot.c
index ecff871..1e264e3 100644
--- a/src/cpu/samsung/exynos5-common/spl_boot.c
+++ b/src/cpu/samsung/exynos5-common/spl_boot.c
@@ -55,9 +55,6 @@
 
 #include <arch/io.h>
 
-/* FIXME(dhendrix): clean out u-boot global data stuff */
-//DECLARE_GLOBAL_DATA_PTR;
-
 #define OM_STAT		(0x1f << 1)
 
 /**
@@ -102,117 +99,6 @@ static int config_branch_prediction(int set_cr_z)
 	return cr & CR_Z;
 }
 
-#if 0
-static void spi_rx_tx(struct exynos_spi *regs, int todo,
-			void *dinp, void const *doutp, int i)
-{
-	uint *rxp = (uint *)(dinp + (i * (32 * 1024)));
-	int rx_lvl, tx_lvl;
-	uint out_bytes, in_bytes;
-
-	out_bytes = in_bytes = todo;
-	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
-
-	while (in_bytes) {
-		uint32_t spi_sts;
-		int temp;
-
-		spi_sts = readl(&regs->spi_sts);
-		rx_lvl = ((spi_sts >> 15) & 0x7f);
-		tx_lvl = ((spi_sts >> 6) & 0x7f);
-		while (tx_lvl < 32 && out_bytes) {
-			temp = 0xffffffff;
-			writel(temp, &regs->tx_data);
-			out_bytes -= 4;
-			tx_lvl += 4;
-		}
-		while (rx_lvl >= 4 && in_bytes) {
-			temp = readl(&regs->rx_data);
-			if (rxp)
-				*rxp++ = temp;
-			in_bytes -= 4;
-			rx_lvl -= 4;
-		}
-	}
-}
-#endif
-
-/* FIXME(dhendrix): feels like exynos_spi_copy should go somewhere else... */
-#if 0
-/**
- * Copy uboot from spi flash to RAM
- *
- * @parma uboot_size	size of u-boot to copy
- */
-static void exynos_spi_copy(unsigned int uboot_size)
-{
-	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);
-
-	/* 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_FLASH_UBOOT_POS, &regs->tx_data);
-
-	/* waiting for TX done */
-	while (!(readl(&regs->spi_sts) & SPI_ST_TX_DONE));
-
-	for (upto = 0, i = 0; upto < uboot_size; upto += todo, i++) {
-		todo = MIN(uboot_size - upto, (1 << 15));
-		spi_rx_tx(regs, todo, (void *)(CONFIG_SYS_TEXT_BASE),
-					(void *)(SPI_FLASH_UBOOT_POS), 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);
-}
-#endif
-
 /* Copy U-Boot image to RAM */
 static void copy_uboot_to_ram(void)
 {
@@ -272,34 +158,6 @@ static void copy_uboot_to_ram(void)
 	debug("U-Boot copied\n");
 }
 
-#if 0
-/**
- * Set up the U-Boot global_data pointer
- *
- * This sets the address of the global data, and sets up basic values.
- *
- * @param gdp	Value to give to gd
- */
-static void setup_global_data(gd_t *gdp)
-{
-	gd = gdp;
-	memzero((void *)gd, sizeof(gd_t));
-	gd->flags |= GD_FLG_RELOC;
-	gd->baudrate = CONFIG_BAUDRATE;
-	gd->have_console = 1;
-}
-#endif
-
-#if 0
-/* Tell the loaded U-Boot that it was loaded from SPL */
-static void exynos5_set_spl_marker(void)
-{
-	uint32_t *marker = (uint32_t *)CONFIG_SPL_MARKER;
-
-	*marker = EXYNOS5_SPL_MARKER;
-}
-#endif
-
 /* Board-specific call to see if wakeup is allowed. */
 static int __def_board_wakeup_permitted(void)
 {
@@ -308,152 +166,3 @@ static int __def_board_wakeup_permitted(void)
 int board_wakeup_permitted(void)
 	__attribute__((weak, alias("__def_board_wakeup_permitted")));
 
-void board_init_f(void)
-{
-	/*
-	 * The gd struct is only needed for serial initialization. Since this
-	 * function is called in SPL u-boot. We store the gd struct in the
-	 * stack instead of the default memory region which may not be
-	 * initialized.
-	 */
-//	__attribute__((aligned(8))) gd_t local_gd;
-//	__attribute__((noreturn)) void (*uboot)(void);
-
-//	exynos5_set_spl_marker();
-//	setup_global_data(&local_gd);
-
-	/*
-	 * Init subsystems, and resume if required. For a normal boot this
-	 * will set up the UART and display a message.
-	 */
-	if (lowlevel_init_subsystems()) {
-		if (!board_wakeup_permitted())
-			power_reset();
-		power_exit_wakeup();
-	}
-
-//	printk(BIOS_INFO, "\n\nU-Boot SPL, board rev %u\n", board_get_revision());
-
-	copy_uboot_to_ram();
-	/* Jump to U-Boot image */
-//	uboot = (void *)CONFIG_SYS_TEXT_BASE;
-//	uboot();
-	/* Never returns Here */
-//	printk(BIOS_ERR, "%s: u-boot jump failed", __func__);
-	printk(BIOS_INFO, "%s: we should not be here...", __func__);
-	hlt();
-}
-
-/* Place Holders */
-void board_init_r(gd_t *id, ulong dest_addr)
-{
-	/* Function attribute is no-return */
-	/* This Function never executes */
-	while (1)
-		;
-}
-
-//void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) {}
-
-#if 0
-/*
- * The following functions are required when linking console library to SPL.
- *
- * Enabling UART in SPL u-boot requires console library. But some
- * functions we needed in the console library depends on a bunch
- * of library in libgeneric, like lib/ctype.o, lib/div64.o, lib/string.o,
- * and lib/vsprintf.o. Adding them makes the SPL u-boot too large and not
- * fit into the expected size.
- *
- * So we mock these functions in SPL, i.e. vsprintf(), panic(), etc.,
- * in order to cut its dependency.
- */
-int vsprintf(char *buf, const char *fmt, va_list args)
-{
-	char *str = buf, *s;
-	ulong u;
-
-	/*
-	 * We won't implement all full functions of vsprintf().
-	 * We only implement %s and %u, and ignore others and directly use
-	 * the original format string as its result.
-	 */
-
-	while (*fmt) {
-		if (*fmt != '%') {
-			*str++ = *fmt++;
-			continue;
-		}
-		fmt++;
-		switch (*fmt) {
-		case '%':
-			*str++ = *fmt++;
-			break;
-		case 's':
-			fmt++;
-			s = va_arg(args, char *);
-			while (*s)
-				*str++ = *s++;
-			break;
-		case 'u':
-			fmt++;
-			u = va_arg(args, ulong);
-			s = simple_itoa(u);
-			while (*s)
-				*str++ = *s++;
-			break;
-		default:
-			/* Print the original string for unsupported formats */
-			*str++ = '%';
-			*str++ = *fmt++;
-		}
-	}
-	*str = '\0';
-	return str - buf;
-}
-#endif
-
-#if 0
-void panic(const char *fmt, ...)
-{
-	va_list args;
-	va_start(args, fmt);
-	vprintf(fmt, args);
-	putc('\n');
-	va_end(args);
-#if defined(CONFIG_PANIC_HANG)
-	hang();
-#else
-	udelay(100000);		/* allow messages to go out */
-	do_reset(NULL, 0, 0, NULL);
-#endif
-	while (1)
-		;
-}
-#endif
-
-#if 0
-void __assert_fail(const char *assertion, const char *file, unsigned line,
-		const char *function)
-{
-	/* This will not return */
-	panic("%s:%u: %s: Assertion `%s' failed.", file, line, function,
-			assertion);
-}
-#endif
-
-#if 0
-char *simple_itoa(ulong i)
-{
-	/* 21 digits plus null terminator, good for 64-bit or smaller ints */
-	static char local[22] __attribute__((section(".data")));
-	char *p = &local[21];
-
-	*p-- = '\0';
-	do {
-		*p-- = '0' + i % 10;
-		i /= 10;
-	} while (i > 0);
-	return p + 1;
-}
-#endif
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/cpu/via/nano/update_ucode.c b/src/cpu/via/nano/update_ucode.c
index 8f7ee22..d5757f8 100644
--- a/src/cpu/via/nano/update_ucode.c
+++ b/src/cpu/via/nano/update_ucode.c
@@ -105,7 +105,7 @@ unsigned int nano_update_ucode(void)
 	const struct cbfs_file *cbfs_ucode;
 	u32 fms = cpuid_eax(0x1);
 
-	cbfs_ucode = cbfs_find("cpu_microcode_blob.bin");
+	cbfs_ucode = cbfs_get_file(CBFS_DEFAULT_MEDIA, "cpu_microcode_blob.bin");
 	/* Oops, did you forget to include the microcode ? */
 	if(cbfs_ucode == NULL) {
 		printk(BIOS_ALERT, "WARNING: No microcode file found in CBFS. "
diff --git a/src/device/oprom/realmode/x86.c b/src/device/oprom/realmode/x86.c
index 697d869..07eff0d 100644
--- a/src/device/oprom/realmode/x86.c
+++ b/src/device/oprom/realmode/x86.c
@@ -248,8 +248,9 @@ void vbe_set_graphics(void)
 #if CONFIG_BOOTSPLASH
 	struct jpeg_decdata *decdata;
 	decdata = malloc(sizeof(*decdata));
-	unsigned char *jpeg = cbfs_find_file("bootsplash.jpg",
-						CBFS_TYPE_BOOTSPLASH);
+	unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
+						    "bootsplash.jpg",
+						    CBFS_TYPE_BOOTSPLASH);
 	if (!jpeg) {
 		printk(BIOS_DEBUG, "VBE: No bootsplash found.\n");
 		return;
@@ -366,7 +367,8 @@ void do_vsmbios(void)
 	printk(BIOS_SPEW, "VSA: Real mode stub @%p: %d bytes\n", REALMODE_BASE,
 			(u32)&__realmode_code_size);
 
-	if ((unsigned int)cbfs_load_stage("vsa") != VSA2_ENTRY_POINT) {
+	if ((unsigned int)cbfs_load_stage(CBFS_DEFAULT_MEDIA, "vsa") !=
+	    VSA2_ENTRY_POINT) {
 		printk(BIOS_ERR, "Failed to load VSA.\n");
 		return;
 	}
diff --git a/src/device/oprom/yabel/vbe.c b/src/device/oprom/yabel/vbe.c
index 9dbe07c..5952dae 100644
--- a/src/device/oprom/yabel/vbe.c
+++ b/src/device/oprom/yabel/vbe.c
@@ -725,7 +725,9 @@ void vbe_set_graphics(void)
 	 * cares. */
 	// int imagesize = 1024*768*2;
 
-	unsigned char *jpeg = cbfs_find_file("bootsplash.jpg", CBFS_TYPE_BOOTSPLASH);
+	unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
+						    "bootsplash.jpg",
+						    CBFS_TYPE_BOOTSPLASH);
 	if (!jpeg) {
 		DEBUG_PRINTF_VBE("Could not find bootsplash.jpg\n");
 		return;
diff --git a/src/device/pci_rom.c b/src/device/pci_rom.c
index fe67515..bb0d760 100644
--- a/src/device/pci_rom.c
+++ b/src/device/pci_rom.c
@@ -35,7 +35,8 @@ struct rom_header *pci_rom_probe(struct device *dev)
 	struct pci_data *rom_data;
 
 	/* If it's in FLASH, then don't check device for ROM. */
-	rom_header = cbfs_load_optionrom(dev->vendor, dev->device, NULL);
+	rom_header = cbfs_load_optionrom(CBFS_DEFAULT_MEDIA, dev->vendor,
+					 dev->device, NULL);
 
 	u32 vendev = (dev->vendor << 16) | dev->device;
 	u32 mapped_vendev = vendev;
@@ -45,8 +46,10 @@ struct rom_header *pci_rom_probe(struct device *dev)
 
 	if (!rom_header) {
 		if (vendev != mapped_vendev) {
-			rom_header = cbfs_load_optionrom(mapped_vendev >> 16,
-					mapped_vendev & 0xffff , NULL);
+			rom_header = cbfs_load_optionrom(
+					CBFS_DEFAULT_MEDIA,
+					mapped_vendev >> 16,
+					mapped_vendev & 0xffff, NULL);
 		}
 	}
 
diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c
index d8d1778..5ffa9d7 100644
--- a/src/drivers/pc80/mc146818rtc.c
+++ b/src/drivers/pc80/mc146818rtc.c
@@ -190,7 +190,8 @@ int get_option(void *dest, const char *name)
 	namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
 
 	/* find the requested entry record */
-	ct=cbfs_find_file("cmos_layout.bin", CBFS_COMPONENT_CMOS_LAYOUT);
+	ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
+				   CBFS_COMPONENT_CMOS_LAYOUT);
 	if (!ct) {
 		printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. "
 						"Options are disabled\n");
@@ -268,7 +269,8 @@ int set_option(const char *name, void *value)
 	namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
 
 	/* find the requested entry record */
-	ct=cbfs_find_file("cmos_layout.bin", CBFS_COMPONENT_CMOS_LAYOUT);
+	ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
+				   CBFS_COMPONENT_CMOS_LAYOUT);
 	if (!ct) {
 		printk(BIOS_ERR, "cmos_layout.bin could not be found. Options are disabled\n");
 		return(-2);
diff --git a/src/include/cbfs.h b/src/include/cbfs.h
index b33e932..c194538 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -52,11 +52,35 @@
 #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_optionrom(struct cbfs_media *media, u16 vendor, u16 device,
+			  void * dest);
+void *cbfs_load_payload(struct cbfs_media *media, const char *name);
+void *cbfs_load_stage(struct cbfs_media *media, const char *name);
+
+/* Simple buffer for streaming media. */
+struct cbfs_simple_buffer {
+	char *buffer;
+	size_t allocated;
+	size_t size;
+	size_t last_allocate;
+};
+
+void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer,
+			     struct cbfs_media *media,
+			     size_t offset, size_t count);
+
+void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer,
+			       const void *address);
+
+// Utility functions
 int run_address(void *f);
+
+/* Defined in src/lib/selfboot.c */
 int selfboot(struct lb_memory *mem, struct cbfs_payload *payload);
+
+/* Defined in individual arch / board implementation. */
+int init_default_cbfs_media(struct cbfs_media *media);
+
 #endif
 
diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h
index a3c54b1..a90a8cf 100644
--- a/src/include/cbfs_core.h
+++ b/src/include/cbfs_core.h
@@ -50,6 +50,8 @@
 #ifndef _CBFS_CORE_H_
 #define _CBFS_CORE_H_
 
+#include <stddef.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
@@ -74,24 +76,18 @@
 #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
 
+#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 +177,49 @@ 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))
+#define CBFS_DEFAULT_MEDIA		((void*)(0x0))
+
+/* 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.
+	 * Note: mapped data can't be free unless unmap is called, even if you
+	 * do close first. */
+	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. */
+	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..04efefd 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -28,18 +28,25 @@
 #ifndef __SMM__
 #define CBFS_CORE_WITH_LZMA
 #endif
-#define phys_to_virt(x) (void*)(x)
-#define virt_to_phys(x) (uint32_t)(x)
+#ifndef ERROR
 #define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
+#endif
+#ifndef LOG
 #define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
+#endif
 #if CONFIG_DEBUG_CBFS
 #define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x)
 #else
 #define DEBUG(x...)
 #endif
-// FIXME: romstart/romend are fine on x86, but not on ARM
-#define romstart() 0xffffffff
-#define romend() 0
+
+#if CONFIG_CBFS_HEADER_ROM_OFFSET
+# define CBFS_HEADER_ROM_ADDRESS (CONFIG_CBFS_HEADER_ROM_OFFSET)
+#else
+// Indirect address: only works on 32bit top-aligned systems.
+# define CBFS_HEADER_ROM_ADDRESS \
+		((uint32_t)CONFIG_ROM_SIZE + *(uint32_t*)0xfffffffc)
+#endif
 
 #include "cbfs_core.c"
 
@@ -57,7 +64,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 +75,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 +102,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 +134,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 +153,50 @@ int cbfs_execute_stage(const char *name)
 	return run_address((void *) (intptr_t)ntohll(stage->entry));
 }
 
+void *cbfs_load_payload(struct cbfs_media *media, const char *name)
+{
+	return (struct cbfs_payload *)cbfs_get_file_content(
+			media, name, CBFS_TYPE_PAYLOAD);
+}
+
+/* Simple buffer */
+
+void *cbfs_simple_buffer_map(struct cbfs_simple_buffer *buffer,
+			     struct cbfs_media *media,
+			     size_t offset, size_t count) {
+	void *address = buffer->buffer + buffer->allocated;;
+	DEBUG("simple_buffer_map(offset=%d, count=%d): "
+	      "allocated=%d, size=%d, last_allocate=%d\n",
+	    offset, count, buffer->allocated, buffer->size,
+	    buffer->last_allocate);
+	if (buffer->allocated + count >= buffer->size)
+		return CBFS_MEDIA_INVALID_MAP_ADDRESS;
+	if (media->read(media, address, offset, count) != count) {
+		ERROR("simple_buffer: fail to read %zd bytes from 0x%zx\n",
+		      count, offset);
+		return CBFS_MEDIA_INVALID_MAP_ADDRESS;
+	}
+	buffer->allocated += count;
+	buffer->last_allocate = count;
+	return address;
+}
+
+void *cbfs_simple_buffer_unmap(struct cbfs_simple_buffer *buffer,
+			       const void *address) {
+	// TODO Add simple buffer management so we can free more than last
+	// allocated one.
+	DEBUG("simple_buffer_unmap(address=0x%p): "
+	      "allocated=%d, size=%d, last_allocate=%d\n",
+	    address, buffer->allocated, buffer->size,
+	    buffer->last_allocate);
+	if ((buffer->buffer + buffer->allocated - buffer->last_allocate) ==
+	    address) {
+		buffer->allocated -= buffer->last_allocate;
+		buffer->last_allocate = 0;
+	}
+	return NULL;
+}
+
 /**
  * run_address is passed the address of a function taking no parameters and
  * jumps to it, returning the result.
@@ -158,4 +210,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..95cb0bd 100644
--- a/src/lib/cbfs_core.c
+++ b/src/lib/cbfs_core.c
@@ -27,14 +27,15 @@
  * 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 (offset) of CBFS header. Underlying CBFS media may interpret
+ *	it in other way so we call this "address".
  *
  * ERROR(x...)
  *      print an error message x (in printf format)
@@ -45,105 +46,135 @@
  * 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 <cbfs.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;
+	struct cbfs_media default_media;
+
+	if (media == CBFS_DEFAULT_MEDIA) {
+		media = &default_media;
+		if (init_default_cbfs_media(media) != 0) {
+			ERROR("Failed to initializee default media.\n");
+			return NULL;
+		}
+	}
+
+	media->open(media);
+	DEBUG("CBFS_HEADER_ROM_ADDRESS: 0x%x/0x%x\n", CBFS_HEADER_ROM_ADDRESS,
+	      CONFIG_ROM_SIZE);
+	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));
-			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);
+	const char *file_name;
+	uint32_t offset, align, romsize, name_len;
+	const struct cbfs_header *header;
+	struct cbfs_file file, *file_ptr;
+	struct cbfs_media default_media;
+
+	if (media == CBFS_DEFAULT_MEDIA) {
+		media = &default_media;
+		if (init_default_cbfs_media(media) != 0) {
+			ERROR("Failed to initializee default media.\n");
 			return NULL;
 		}
 	}
-	return NULL;
-}
-
-void *cbfs_get_file(const char *name)
-{
-	struct cbfs_file *file = cbfs_find(name);
 
-	if (file == NULL) {
-		ERROR("Could not find file '%s'.\n", name);
+	if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media)))
 		return NULL;
-	}
 
-	return (void*)CBFS_SUBHEADER(file);
+	// 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
+	DEBUG("offset: 0x%x, 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) {
+			uint32_t new_align = align;
+			if (offset % align)
+				new_align += align - (offset % align);
+			ERROR("ERROR: No file header found at 0x%xx - "
+			      "try next aligned address: 0x%x.\n", offset,
+			      offset + new_align);
+			offset += new_align;
+			continue;
+		}
+		name_len = ntohl(file.offset) - sizeof(file);
+		DEBUG(" - load entry 0x%x file name (%d bytes)...\n", offset,
+		      name_len);
+
+		// load file name (arbitrary length).
+		file_name = (const char*)media->map(
+				media, offset + sizeof(file), name_len);
+		if (file_name == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
+			ERROR("ERROR: Failed to get filename: 0x%x.\n", offset);
+		} else if (strcmp(file_name, name) == 0) {
+			int file_offset = ntohl(file.offset),
+			    file_len = ntohl(file.len);
+			LOG("Found file (offset=0x%x, len=%d).\n",
+			    offset + file_offset, file_len);
+			media->unmap(media, file_name);
+			file_ptr = media->map(media, offset,
+					      file_offset + file_len);
+			media->close(media);
+			return file_ptr;
+		} else {
+			LOG(" (unmatched file @0x%x: %s)\n", offset, file_name);
+			media->unmap(media, file_name);
+		}
+
+		// Move to next file.
+		offset += ntohl(file.len) + ntohl(file.offset);
+		if (offset % align)
+			offset += align - (offset % align);
+	}
+	media->close(media);
+	ERROR("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 +182,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 +204,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..85c05f5 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");
+	payload = cbfs_load_payload(CBFS_DEFAULT_MEDIA,
+				    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..e9fc13e 100644
--- a/src/mainboard/google/snow/bootblock.c
+++ b/src/mainboard/google/snow/bootblock.c
@@ -17,11 +17,10 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#define uchar unsigned char
-#define uint  unsigned int
-
 #include <stdlib.h>
 #include <types.h>
+#include <assert.h>
+#include <arch/armv7/include/common.h>
 #include <arch/io.h>
 #include "cpu/samsung/exynos5250/clk.h"
 #include "cpu/samsung/exynos5250/cpu.h"
@@ -34,6 +33,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,87 +42,9 @@
 
 #define EXYNOS5_CLOCK_BASE		0x10010000
 
-/* 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)
-{
-	unsigned int *rxp = (unsigned int *)(dinp + (i * (32 * 1024)));
-	int rx_lvl, tx_lvl;
-	unsigned int out_bytes, in_bytes;
-
-	out_bytes = in_bytes = todo;
-	setbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
-	writel(((todo * 8) / 32) | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
-
-	while (in_bytes) {
-		uint32_t spi_sts;
-		int temp;
-
-		spi_sts = readl(&regs->spi_sts);
-		rx_lvl = ((spi_sts >> 15) & 0x7f);
-		tx_lvl = ((spi_sts >> 6) & 0x7f);
-		while (tx_lvl < 32 && out_bytes) {
-			temp = 0xffffffff;
-			writel(temp, &regs->tx_data);
-			out_bytes -= 4;
-			tx_lvl += 4;
-		}
-		while (rx_lvl >= 4 && in_bytes) {
-			temp = readl(&regs->rx_data);
-			if (rxp)
-				*rxp++ = temp;
-			in_bytes -= 4;
-			rx_lvl -= 4;
-		}
-	}
-}
+// TODO Move this to Makefile.inc once we support adding bootblock stage files.
+#include "cpu/samsung/exynos5-common/spi.c"
 
-#if 0
-void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor)
-{
-	struct exynos5_clock *clk =
-		(struct exynos5_clock *)samsung_get_base_clock();
-	unsigned shift;
-	unsigned mask = 0xff;
-	u32 *reg;
-
-	/*
-	 * For now we only handle a very small subset of peipherals here.
-	 * Others will need to (and do) mangle the clock registers
-	 * themselves, At some point it is hoped that this function can work
-	 * from a table or calculated register offset / mask. For now this
-	 * is at least better than spreading clock control code around
-	 * U-Boot.
-	 */
-	switch (periph_id) {
-	case PERIPH_ID_SPI0:
-		reg = &clk->div_peric1;
-		shift = 8;
-		break;
-	case PERIPH_ID_SPI1:
-		reg = &clk->div_peric1;
-		shift = 24;
-		break;
-	case PERIPH_ID_SPI2:
-		reg = &clk->div_peric2;
-		shift = 8;
-		break;
-	case PERIPH_ID_SPI3:
-		reg = &clk->sclk_div_isp;
-		shift = 4;
-		break;
-	case PERIPH_ID_SPI4:
-		reg = &clk->sclk_div_isp;
-		shift = 16;
-		break;
-	default:
-		debug("%s: Unsupported peripheral ID %d\n", __func__,
-		      periph_id);
-		return;
-	}
-}
-#endif
 void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor)
 {
 	struct exynos5_clock *clk =
@@ -136,43 +58,6 @@ void clock_ll_set_pre_ratio(enum periph_id periph_id, unsigned divisor)
 	clrsetbits_le32(reg, mask << shift, (divisor & mask) << shift);
 }
 
-#if 0
-void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor)
-{
-	struct exynos5_clock *clk =
-		(struct exynos5_clock *)samsung_get_base_clock();
-	unsigned shift;
-	unsigned mask = 0xff;
-	u32 *reg;
-
-	switch (periph_id) {
-	case PERIPH_ID_SPI0:
-		reg = &clk->div_peric1;
-		shift = 0;
-		break;
-	case PERIPH_ID_SPI1:
-		reg = &clk->div_peric1;
-		shift = 16;
-		break;
-	case PERIPH_ID_SPI2:
-		reg = &clk->div_peric2;
-		shift = 0;
-		break;
-	case PERIPH_ID_SPI3:
-		reg = &clk->sclk_div_isp;
-		shift = 0;
-		break;
-	case PERIPH_ID_SPI4:
-		reg = &clk->sclk_div_isp;
-		shift = 12;
-		break;
-	default:
-		debug("%s: Unsupported peripheral ID %d\n", __func__,
-		      periph_id);
-		return;
-	}
-}
-#endif
 void clock_ll_set_ratio(enum periph_id periph_id, unsigned divisor)
 {
 	struct exynos5_clock *clk =
@@ -249,44 +134,6 @@ static int clock_calc_best_scalar(unsigned int main_scaler_bits,
 	return best_main_scalar;
 }
 
-#if 0
-int clock_set_rate(enum periph_id periph_id, unsigned int rate)
-{
-	int main;
-	unsigned int fine;
-
-	switch (periph_id) {
-	case PERIPH_ID_SPI0:
-	case PERIPH_ID_SPI1:
-	case PERIPH_ID_SPI2:
-	case PERIPH_ID_SPI3:
-	case PERIPH_ID_SPI4:
-		main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
-		if (main < 0) {
-			debug("%s: Cannot set clock rate for periph %d",
-					__func__, periph_id);
-			return -1;
-		}
-		clock_ll_set_ratio(periph_id, main - 1);
-		clock_ll_set_pre_ratio(periph_id, fine - 1);
-		break;
-	default:
-		debug("%s: Unsupported peripheral ID %d\n", __func__,
-		      periph_id);
-		return -1;
-	}
-	main = clock_calc_best_scalar(4, 8, 400000000, rate, &fine);
-	if (main < 0) {
-		debug("%s: Cannot set clock rate for periph %d",
-				__func__, periph_id);
-		return -1;
-	}
-	clock_ll_set_ratio(PERIPH_ID_SPI1, main - 1);
-	clock_ll_set_pre_ratio(PERIPH_ID_SPI1, fine - 1);
-
-	return 0;
-}
-#endif
 int clock_set_rate(enum periph_id periph_id, unsigned int rate)
 {
 	int main;
@@ -358,77 +205,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
@@ -850,21 +626,15 @@ void do_barriers(void)
 	);
 }
 
-void sdelay(unsigned long loops);
-void sdelay(unsigned long loops)
-{
-	__asm__ volatile ("1:\n" "subs %0, %1, #1\n"
-			  "bne 1b":"=r" (loops):"0"(loops));
-}
-
 /* is this right? meh, it seems to work well enough... */
 void my_udelay(unsigned int n);
 void my_udelay(unsigned int n)
 {
-	sdelay(n * 1000);
+	n *= 1000;
+	__asm__ volatile ("1:\n" "subs %0, %1, #1\n"
+			  "bne 1b":"=r" (n):"0"(n));
 }
 
-
 void i2c_init(int speed, int slaveadd)
 {
 	struct s3c24x0_i2c_bus *i2c = &i2c0;
@@ -2141,13 +1911,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;
diff --git a/src/mainboard/samsung/lumpy/romstage.c b/src/mainboard/samsung/lumpy/romstage.c
index 5600cf6..9bc193b 100644
--- a/src/mainboard/samsung/lumpy/romstage.c
+++ b/src/mainboard/samsung/lumpy/romstage.c
@@ -301,7 +301,7 @@ void main(unsigned long bist)
 		break;
 	}
 
-	spd_file = cbfs_find("spd.bin");
+	spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin");
 	if (!spd_file)
 		die("SPD data not found.");
 	if (spd_file->len < (spd_index + 1) * 256)
diff --git a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
index 7c3b0ac..8c5605c 100644
--- a/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
+++ b/src/northbridge/amd/agesa/family15tn/fam15tn_callouts.c
@@ -398,7 +398,9 @@ AGESA_STATUS fam15tn_DefaultRet (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 AGESA_STATUS fam15tn_HookGfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt)
 {
 	GFX_VBIOS_IMAGE_INFO  *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
-	pVbiosImageInfo->ImagePtr = cbfs_find_file("pci"CONFIG_VGA_BIOS_ID".rom", CBFS_TYPE_OPTIONROM);
+	pVbiosImageInfo->ImagePtr = cbfs_get_file_content(
+			CBFS_DEFAULT_MEDIA, "pci"CONFIG_VGA_BIOS_ID".rom",
+			CBFS_TYPE_OPTIONROM);
 	/* printk(BIOS_DEBUG, "IMGptr=%x\n", pVbiosImageInfo->ImagePtr); */
 	return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS;
 }
diff --git a/src/northbridge/intel/i82830/vga.c b/src/northbridge/intel/i82830/vga.c
index 1ec7f87..40e7d9d 100644
--- a/src/northbridge/intel/i82830/vga.c
+++ b/src/northbridge/intel/i82830/vga.c
@@ -32,7 +32,7 @@
 static void vga_init(device_t dev)
 {
 	printk(BIOS_INFO, "Starting Graphics Initialization\n");
-	struct cbfs_file *file = cbfs_find("mbi.bin");
+	struct cbfs_file *file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "mbi.bin");
 	void *mbi = NULL;
 	unsigned int mbi_len = 0;
 
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c
index b5a1c23..f25aaa1 100644
--- a/src/northbridge/intel/sandybridge/raminit.c
+++ b/src/northbridge/intel/sandybridge/raminit.c
@@ -252,7 +252,9 @@ void sdram_initialize(struct pei_data *pei_data)
 	pei_data->tx_byte = console_tx_byte;
 
 	/* Locate and call UEFI System Agent binary. */
-	entry = (unsigned long)cbfs_find_file("mrc.bin", 0xab);
+	/* TODO make MRC blob (0xab?) defined in cbfs_core.h. */
+	entry = (unsigned long)cbfs_get_file_content(
+			CBFS_DEFAULT_MEDIA, "mrc.bin", 0xab);
 	if (entry) {
 		int rv;
 		asm volatile (



More information about the coreboot mailing list