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

Hung-Te Lin (hungte@chromium.org) gerrit at coreboot.org
Thu Jan 24 16:16:08 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 d862ab4c8343f950e8c217abe6112f852e7e75d5
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.
    
    CBFS used to work only on memory-mapped ROM (all x86). For platforms like ARM,
    the ROM may come from USB, UART, or SPI -- all working as serial device and
    not available for memory mapping.
    
    To support these devices (even allowing CBFS to read from multiple source
    at the same time), reading operation in CBFS is now 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)". For device without native memory-mapped ROM, a
    "cbfs_simple_buffer*" provides simple memory mapping simulation.
    
    Every CBFS function now takes a cbfs_media* as parameter. A 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).
     - Not verified on x86 platforms yet.
    
    Change-Id: Iac911ded25a6f2feffbf3101a81364625bb07746
    Signed-off-by: Hung-Te Lin <hungte at chromium.org>
---
 src/arch/armv7/boot/coreboot_table.c               |   3 +-
 src/arch/armv7/bootblock_simple.c                  |   4 +-
 src/arch/armv7/include/arch/cbfs.h                 | 101 +++-----
 src/arch/x86/boot/coreboot_table.c                 |   3 +-
 src/arch/x86/boot/smbios.c                         |  16 +-
 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        |   3 +-
 src/cpu/samsung/exynos5-common/spi.c               | 233 +++++++++++++++++++
 src/cpu/samsung/exynos5-common/spi.h               |  13 ++
 src/cpu/samsung/exynos5-common/spl_boot.c          | 247 +-------------------
 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                                 |  33 ++-
 src/include/cbfs_core.h                            |  76 +++++--
 src/lib/cbfs.c                                     |  79 ++++++-
 src/lib/cbfs_core.c                                | 190 +++++++++-------
 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        |   3 +-
 30 files changed, 674 insertions(+), 714 deletions(-)

diff --git a/src/arch/armv7/boot/coreboot_table.c b/src/arch/armv7/boot/coreboot_table.c
index 86a004d..dc7ec97 100644
--- a/src/arch/armv7/boot/coreboot_table.c
+++ b/src/arch/armv7/boot/coreboot_table.c
@@ -640,7 +640,8 @@ 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", 0x1aa);
 		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..3ef4432 100644
--- a/src/arch/x86/boot/coreboot_table.c
+++ b/src/arch/x86/boot/coreboot_table.c
@@ -638,7 +638,8 @@ 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", 0x1aa);
 		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..7d449fc 100644
--- a/src/arch/x86/boot/smbios.c
+++ b/src/arch/x86/boot/smbios.c
@@ -27,7 +27,7 @@
 #include <device/device.h>
 #include <arch/cpu.h>
 #include <cpu/x86/name.h>
-#include <cbfs_core.h>
+#include <cbfs.h>
 #include <arch/byteorder.h>
 #include <elog.h>
 #if CONFIG_CHROMEOS
@@ -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..5e9787e
--- /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) {
+	// TODO cache rom size by searching for cbfs_header->romsize.
+	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;
+	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..baed0cc 100644
--- a/src/cpu/samsung/exynos5-common/Makefile.inc
+++ b/src/cpu/samsung/exynos5-common/Makefile.inc
@@ -1,2 +1,3 @@
-#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..f2a0b99 100644
--- a/src/cpu/samsung/exynos5-common/spl_boot.c
+++ b/src/cpu/samsung/exynos5-common/spl_boot.c
@@ -102,117 +102,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 +161,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)
 {
@@ -335,11 +196,8 @@ void board_init_f(void)
 //	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();
 }
@@ -354,106 +212,3 @@ void board_init_r(gd_t *id, ulong dest_addr)
 }
 
 //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..3f94fe4 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -52,11 +52,36 @@
 #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);
+
+/* 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..832f85b 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,25 @@
 #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 \
+		(0 - CONFIG_ROM_SIZE - *(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 +184,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 {
 
-/* returns pointer to file data inside CBFS */
-void *cbfs_get_file(const char *name);
+	/* implementation dependent context, to hold resource references */
+	void *context;
 
-/* returns pointer to file data inside CBFS after if type is correct */
-void *cbfs_find_file(const char *name, int type);
+	/* opens media and returns 0 on success, -1 on failure */
+	int (*open)(struct cbfs_media *media);
+
+	/* 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..f2a4220 100644
--- a/src/lib/cbfs.c
+++ b/src/lib/cbfs.c
@@ -28,18 +28,24 @@
 #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
+
+#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 +63,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 +74,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 +101,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 +133,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 +152,55 @@ 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;
+}
+
+/* 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 +214,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..e84b96f 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,130 @@
  * 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(&default_media) != 0) {
+			ERROR("Failed to initializee default media.\n");
+			return NULL;
+		}
+	}
+
+	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));
-			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(&default_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) {
+			ERROR("ERROR: No file header found at 0x%xx - "
+			      "try next aligned address: 0x%x.\n", offset,
+			      offset + align);
+			offset += 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 at 0x%x: %s)", 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 +176,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 +198,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..3c6b338 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, 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..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..7b165e3 100644
--- a/src/northbridge/intel/sandybridge/raminit.c
+++ b/src/northbridge/intel/sandybridge/raminit.c
@@ -252,7 +252,8 @@ 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);
+	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