[coreboot-gerrit] Patch set updated for coreboot: 6c05f52 cbfs: add new API and boot_device support

Aaron Durbin (adurbin@chromium.org) gerrit at coreboot.org
Tue Apr 21 03:59:13 CEST 2015


Aaron Durbin (adurbin at chromium.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9134

-gerrit

commit 6c05f5261733b09288e95e94e1ec8f26095b5f76
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Fri Mar 27 00:23:49 2015 -0500

    cbfs: add new API and boot_device support
    
    A new CBFS API is introduced to allow making CBFS access
    easier for providing multiple CBFS sources. That is achieved
    by decoupling the cbfs source from a CBFS file. A CBFS
    source is described by a descriptor. It contains the necessary
    properties for walking a CBFS to locate a file. The CBFS
    file is then decoupled from the CBFS descriptor in that it's
    no longer needed to access the contents of the file.
    
    All of this is accomplished using the regions infrastructure
    by repsenting CBFS sources and files as region_devices. Because
    region_devices can be chained together forming subregions this
    allows one to decouple a CBFS source from a file. This also allows
    one to provide CBFS files that came from other sources for
    payload and/or stage loading.
    
    The last concept this change introduces is the boot device. The
    boot device is represented as a region_device that covers the
    entire media where the main CBFS is located. Using the boot
    media allows one to access the media through the region_device
    operations that don't fall within the CBFS proper. Previously,
    struct cbfs_media was being used for accessing content outside
    of the boot CBFS proper.
    
    Note: this change purposefully ignores the chromeos code.
    
    Change-Id: I339b84fce95f03d1dbb63a0f54a26be5eb07f7c8
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/arch/riscv/rom_media.c                   |  92 ++------
 src/arch/x86/lib/Makefile.inc                |   6 +-
 src/arch/x86/lib/mmap_boot.c                 |  76 +++++++
 src/arch/x86/lib/rom_media.c                 | 101 ---------
 src/cpu/allwinner/a10/bootblock_media.c      |   6 +-
 src/cpu/amd/microcode/microcode.c            |   4 +-
 src/cpu/intel/microcode/microcode.c          |  18 +-
 src/cpu/ti/am335x/bootblock_media.c          |  56 +----
 src/cpu/ti/am335x/nand.c                     |   8 +-
 src/cpu/via/nano/update_ucode.c              |   5 +-
 src/device/dram/spd_cache.c                  |   4 +-
 src/device/oprom/realmode/x86.c              |  14 +-
 src/device/oprom/yabel/vbe.c                 |   7 +-
 src/device/pci_rom.c                         |   8 +-
 src/drivers/intel/fsp/fastboot_cache.c       |   7 +-
 src/drivers/pc80/mc146818rtc.c               |   8 +-
 src/drivers/spi/spi_flash.c                  |   7 +-
 src/include/boot_device.h                    |  30 +++
 src/include/cbfs.h                           |  90 +++++++-
 src/include/cbfs_core.h                      | 128 -----------
 src/include/cbfs_declarations.h              |  87 -------
 src/include/rmodule.h                        |   4 +-
 src/lib/Makefile.inc                         |  16 +-
 src/lib/cbfs.c                               | 272 ++++++++++++++++++++++
 src/lib/cbfs_boot_props.c                    |  57 +++++
 src/lib/cbfs_core.c                          | 324 ---------------------------
 src/lib/cbfs_core.h                          |  45 ----
 src/lib/cbfs_gpl.c                           | 209 -----------------
 src/lib/cbfs_spi.c                           |  84 +++----
 src/lib/coreboot_table.c                     |   4 +-
 src/lib/loaders/cbfs_payload_loader.c        |   5 +-
 src/lib/loaders/cbfs_ramstage_loader.c       |   3 +-
 src/lib/loaders/load_and_run_romstage.c      |   2 +-
 src/lib/rmodule.c                            |  48 ++--
 src/mainboard/emulation/qemu-armv7/media.c   |  54 +----
 src/mainboard/google/bolt/romstage.c         |   4 +-
 src/mainboard/google/butterfly/mainboard.c   |   4 +-
 src/mainboard/google/falco/romstage.c        |   4 +-
 src/mainboard/google/link/romstage.c         |   4 +-
 src/mainboard/google/panther/lan.c           |   4 +-
 src/mainboard/google/peach_pit/romstage.c    |  17 +-
 src/mainboard/google/peppy/romstage.c        |   4 +-
 src/mainboard/google/rambi/romstage.c        |   9 +-
 src/mainboard/google/samus/spd/spd.c         |  13 +-
 src/mainboard/google/slippy/romstage.c       |   4 +-
 src/mainboard/samsung/lumpy/romstage.c       |   4 +-
 src/mainboard/siemens/mc_tcu3/modhwinfo.c    |   6 +-
 src/northbridge/amd/agesa/common/common.c    |   3 +-
 src/northbridge/amd/agesa/def_callouts.c     |   4 +-
 src/northbridge/amd/pi/def_callouts.c        |   4 +-
 src/northbridge/intel/haswell/mrccache.c     |   7 +-
 src/northbridge/intel/haswell/raminit.c      |   4 +-
 src/northbridge/intel/i82830/vga.c           |   3 +-
 src/northbridge/intel/sandybridge/mrccache.c |   7 +-
 src/northbridge/intel/sandybridge/raminit.c  |   3 +-
 src/soc/intel/baytrail/romstage/raminit.c    |   3 +-
 src/soc/intel/broadwell/romstage/raminit.c   |   3 +-
 src/soc/nvidia/tegra124/Makefile.inc         |   4 -
 src/soc/nvidia/tegra124/cbfs.c               |  29 ---
 src/soc/nvidia/tegra124/include/soc/spi.h    |   5 -
 src/soc/nvidia/tegra124/spi.c                | 106 +++------
 src/soc/nvidia/tegra132/Makefile.inc         |   3 -
 src/soc/nvidia/tegra132/cbfs.c               |  28 ---
 src/soc/nvidia/tegra132/ccplex.c             |  15 +-
 src/soc/nvidia/tegra132/include/soc/spi.h    |   5 -
 src/soc/nvidia/tegra132/spi.c                | 106 +++------
 src/soc/rockchip/rk3288/include/soc/spi.h    |   5 -
 src/soc/rockchip/rk3288/spi.c                |  59 ++++-
 src/soc/samsung/exynos5250/alternate_cbfs.c  |  77 +++----
 src/soc/samsung/exynos5250/include/soc/spi.h |   6 +-
 src/soc/samsung/exynos5250/spi.c             |  84 +++----
 src/soc/samsung/exynos5420/alternate_cbfs.c  |  77 +++----
 src/soc/samsung/exynos5420/include/soc/spi.h |   6 +-
 src/soc/samsung/exynos5420/spi.c             |  78 ++-----
 74 files changed, 996 insertions(+), 1704 deletions(-)

diff --git a/src/arch/riscv/rom_media.c b/src/arch/riscv/rom_media.c
index e00e0fb..f810c2a 100644
--- a/src/arch/riscv/rom_media.c
+++ b/src/arch/riscv/rom_media.c
@@ -1,7 +1,7 @@
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
+ * Copyright 2015 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
@@ -18,75 +18,31 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
  * MA 02110-1301 USA
  */
+#include <boot_device.h>
 #include <cbfs.h>
-#include <string.h>
+#include <endian.h>
+#include <region.h>
 
-#ifdef LIBPAYLOAD
-# define printk(x...)
-# define init_default_cbfs_media libpayload_init_default_cbfs_media
-  extern int libpayload_init_default_cbfs_media(struct cbfs_media *media);
-#else
-# include <console/console.h>
-#endif
-
-// Implementation of memory-mapped ROM media source on X86.
-
-static int rom_media_open(struct cbfs_media *media) {
-	return 0;
-}
-
-static void *rom_media_map(struct cbfs_media *media, size_t offset, size_t count) {
-	void *ptr;
-	printk(BIOS_INFO, "%s: media %p, offset %lx, size %ld.\n", __func__, media, offset, count);
-
-	ptr = (void*)offset;
-	return ptr;
-}
-
-static void *rom_media_unmap(struct cbfs_media *media, const void *address) {
-	return NULL;
-}
-
-static size_t rom_media_read(struct cbfs_media *media, void *dest, size_t offset,
-			   size_t count) {
-	void *ptr = rom_media_map(media, offset, count);
-	memcpy(dest, ptr, count);
-	rom_media_unmap(media, ptr);
-	return count;
-}
-
-static int rom_media_close(struct cbfs_media *media) {
-	return 0;
-}
+/*
+ * RISC-V emulation mainboard info and hexdump:
+ * CONFIG_CBFS_HEADER_ROM_OFFSET 0x10000
+ * CONFIG_CBFS_ROM_OFFSET 0x10040
+ * CONFIG_ROM_SIZE 0x400000
+ * CONFIG_BOOTBLOCK_ROM_OFFSET 0x0
+ *
+ *00010000  4f 52 42 43 31 31 31 32  00 40 00 00 00 00 64 e8  |ORBC1112. at ....d.|
+ *00010010  00 00 00 40 00 01 00 40  c0 01 d0 de ff ff ff ff  |... at ...@........|
+ *00010020  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
+ *00010030  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
+ *00010040  4c 41 52 43 48 49 56 45  00 00 3d 20 00 00 00 10  |LARCHIVE..= ....|
+ *00010050  00 00 00 00 00 00 00 38  66 61 6c 6c 62 61 63 6b  |.......8fallback|
+ *00010060  2f 72 6f 6d 73 74 61 67  65 00 00 00 00 00 00 00  |/romstage.......|
+ */
 
-static int init_rom_media_cbfs(struct cbfs_media *media) {
-	/* this assumes that the CBFS resides at 0x0,
-	 * which is true for the default configuration
-	 */
-	int32_t *cbfs_header_ptr = (int32_t*)(uintptr_t)(CONFIG_CBFS_SIZE - 4);
-	uint64_t cbfs_header_offset = CONFIG_CBFS_SIZE + *cbfs_header_ptr;
-	struct cbfs_header *header = (struct cbfs_header*) cbfs_header_offset;
-	if (CBFS_HEADER_MAGIC != ntohl(header->magic)) {
-		printk(BIOS_ERR, "Invalid CBFS master header at %p\n", header);
-		printk(BIOS_ERR, "Expected %08lx and got %08lx\n", (unsigned long) CBFS_HEADER_MAGIC, (unsigned long) ntohl(header->magic));
-		return -1;
-	} else {
-		uint32_t romsize = ntohl(header->romsize);
-		media->context = (void*)(uintptr_t)romsize;
-#if defined(CONFIG_ROM_SIZE)
-		if (CONFIG_ROM_SIZE != romsize)
-			printk(BIOS_INFO, "Warning: rom size unmatch (%d/%d)\n",
-			       CONFIG_ROM_SIZE, romsize);
-#endif
-	}
-	media->open = rom_media_open;
-	media->close = rom_media_close;
-	media->map = rom_media_map;
-	media->unmap = rom_media_unmap;
-	media->read = rom_media_read;
-	return 0;
-}
+static const struct mem_region_device boot_dev =
+	MEM_REGION_DEV_INIT(NULL, CONFIG_ROM_SIZE);
 
-int init_default_cbfs_media(struct cbfs_media *media) {
-	return init_rom_media_cbfs(media);
+const struct region_device *boot_device_ro(void)
+{
+	return &boot_dev.rdev;
 }
diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc
index c7e8b62..0d88a6da 100644
--- a/src/arch/x86/lib/Makefile.inc
+++ b/src/arch/x86/lib/Makefile.inc
@@ -5,7 +5,7 @@ romstage-y += cbfs_and_run.c
 romstage-y += memset.c
 romstage-y += memcpy.c
 romstage-y += memmove.c
-romstage-y += rom_media.c
+romstage-y += mmap_boot.c
 
 endif # CONFIG_ARCH_ROMSTAGE_X86_32
 
@@ -21,7 +21,7 @@ ramstage-y += memset.c
 ramstage-y += memcpy.c
 ramstage-y += memmove.c
 ramstage-y += ebda.c
-ramstage-y += rom_media.c
+ramstage-y += mmap_boot.c
 ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c
 ramstage-$(CONFIG_COOP_MULTITASKING) += thread_switch.S
 ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
@@ -31,7 +31,7 @@ romstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
 smm-y += memset.c
 smm-y += memcpy.c
 smm-y += memmove.c
-smm-y += rom_media.c
+smm-y += mmap_boot.c
 
 rmodules_x86_32-y += memset.c
 rmodules_x86_32-y += memcpy.c
diff --git a/src/arch/x86/lib/mmap_boot.c b/src/arch/x86/lib/mmap_boot.c
new file mode 100644
index 0000000..74f6f94
--- /dev/null
+++ b/src/arch/x86/lib/mmap_boot.c
@@ -0,0 +1,76 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 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.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <boot_device.h>
+#include <console/console.h>
+#include <cbfs.h>
+#include <endian.h>
+#include <region.h>
+
+/* The ROM is memory mapped just below 4GiB. Form a pointer for the base. */
+#define rom_base ((void *)(uintptr_t)(-(int32_t)CONFIG_ROM_SIZE))
+
+static const struct mem_region_device boot_dev =
+	MEM_REGION_DEV_INIT(rom_base, CONFIG_ROM_SIZE);
+
+const struct region_device *boot_device_ro(void)
+{
+	return &boot_dev.rdev;
+}
+
+int cbfs_boot_region_properties(struct cbfs_props *props)
+{
+	struct cbfs_header header;
+	int32_t offset;
+	const struct region_device *bdev;
+
+	bdev = boot_device_ro();
+
+	rdev_readat(bdev, &offset, CONFIG_ROM_SIZE - 4, sizeof(offset));
+
+	/* The offset is relative to the end of the media. */
+	offset += CONFIG_ROM_SIZE;
+
+	rdev_readat(bdev, &header , offset, sizeof(header));
+
+	header.magic = ntohl(header.magic);
+	header.romsize = ntohl(header.romsize);
+	header.bootblocksize = ntohl(header.bootblocksize);
+	header.align = ntohl(header.align);
+	header.offset = ntohl(header.offset);
+
+	if (header.magic != CBFS_HEADER_MAGIC)
+		return -1;
+
+	props->align = header.align;
+	props->offset = header.offset;
+	if (CONFIG_ROM_SIZE != header.romsize)
+		props->size = CONFIG_ROM_SIZE;
+	else
+		props->size = header.romsize;
+	props->size -= props->offset;
+	props->size -= header.bootblocksize;
+	props->size = ALIGN_DOWN(props->size, props->align);
+
+	printk(BIOS_DEBUG, "CBFS @ %zx size %zx\n", props->offset, props->size);
+
+	return 0;
+}
diff --git a/src/arch/x86/lib/rom_media.c b/src/arch/x86/lib/rom_media.c
deleted file mode 100644
index ed2122c..0000000
--- a/src/arch/x86/lib/rom_media.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
- *
- * 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 <cbfs.h>
-#include <string.h>
-
-#ifdef LIBPAYLOAD
-# define printk(x...)
-# define init_default_cbfs_media libpayload_init_default_cbfs_media
-  extern int libpayload_init_default_cbfs_media(struct cbfs_media *media);
-#else
-# include <console/console.h>
-#endif
-
-// 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;
-	// Some address (ex, pointer to master header) may be given in memory
-	// mapped location. To workaround that, we handle >0xf0000000 as real
-	// memory pointer.
-
-	if ((uint32_t)offset > (uint32_t)0xf0000000)
-		ptr = (void*)offset;
-	else
-		ptr = (void*)(0 - (uint32_t)media->context + 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_x86rom_cbfs_media(struct cbfs_media *media);
-int init_x86rom_cbfs_media(struct cbfs_media *media) {
-	// On X86, we always keep a reference of pointer to CBFS header in
-	// 0xfffffffc, and the pointer is still a memory-mapped address.
-	// Since the CBFS core always use ROM offset, we need to figure out
-	// header->romsize even before media is initialized.
-	struct cbfs_header *header = (struct cbfs_header*)
-			*(uint32_t*)(0xfffffffc);
-	if (CBFS_HEADER_MAGIC != ntohl(header->magic)) {
-#if defined(CONFIG_ROM_SIZE)
-		printk(BIOS_ERR, "Invalid CBFS master header at %p\n", header);
-		media->context = (void*)CONFIG_ROM_SIZE;
-#else
-		return -1;
-#endif
-	} else {
-		uint32_t romsize = ntohl(header->romsize);
-		media->context = (void*)romsize;
-#if defined(CONFIG_ROM_SIZE)
-		if (CONFIG_ROM_SIZE != romsize)
-			printk(BIOS_INFO, "Warning: rom size unmatch (%d/%d)\n",
-			       CONFIG_ROM_SIZE, romsize);
-#endif
-	}
-	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;
-}
-
-int init_default_cbfs_media(struct cbfs_media *media) {
-	return init_x86rom_cbfs_media(media);
-}
diff --git a/src/cpu/allwinner/a10/bootblock_media.c b/src/cpu/allwinner/a10/bootblock_media.c
index a5863b6..17c6039 100644
--- a/src/cpu/allwinner/a10/bootblock_media.c
+++ b/src/cpu/allwinner/a10/bootblock_media.c
@@ -4,11 +4,11 @@
  * Copyright (C) 2013  Alexandru Gagniuc <mr.nuke.me at gmail.com>
  * Subject to the GNU GPL v2, or (at your option) any later version.
  */
-#include <cbfs.h>
+#include <boot_device.h>
 #include <console/console.h>
 
-int init_default_cbfs_media(struct cbfs_media *media)
+const struct region_device *boot_device_ro(void)
 {
 	printk(BIOS_ERR, "Oh my! I don't know how to access CBFS yet.");
-	return 0;
+	return NULL;
 }
diff --git a/src/cpu/amd/microcode/microcode.c b/src/cpu/amd/microcode/microcode.c
index 938f5f6..d5bf756 100644
--- a/src/cpu/amd/microcode/microcode.c
+++ b/src/cpu/amd/microcode/microcode.c
@@ -105,8 +105,8 @@ void amd_update_microcode_from_cbfs(u32 equivalent_processor_rev_id)
 		return;
 	}
 
-	ucode = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, MICROCODE_CBFS_FILE,
-				      CBFS_TYPE_MICROCODE, &ucode_len);
+	ucode = cbfs_boot_map_with_leak(MICROCODE_CBFS_FILE,
+					CBFS_TYPE_MICROCODE, &ucode_len);
 	if (!ucode) {
 		UCODE_DEBUG("microcode file not found. Skipping updates.\n");
 		return;
diff --git a/src/cpu/intel/microcode/microcode.c b/src/cpu/intel/microcode/microcode.c
index 947dfd7..c4d2cd0 100644
--- a/src/cpu/intel/microcode/microcode.c
+++ b/src/cpu/intel/microcode/microcode.c
@@ -109,25 +109,29 @@ void intel_microcode_load_unlocked(const void *microcode_patch)
 
 const void *intel_microcode_find(void)
 {
-	struct cbfs_file *microcode_file;
 	const struct microcode *ucode_updates;
-	u32 eax, microcode_len;
+	size_t microcode_len;
+	u32 eax;
 	u32 pf, rev, sig, update_size;
 	unsigned int x86_model, x86_family;
 	msr_t msr;
 
 #ifdef __PRE_RAM__
-	microcode_file = walkcbfs_head((char *) MICROCODE_CBFS_FILE);
-#else
-	microcode_file = cbfs_get_file(CBFS_DEFAULT_MEDIA,
-					  MICROCODE_CBFS_FILE);
-#endif
+	struct cbfs_file *microcode_file;
 
+	microcode_file = walkcbfs_head((char *) MICROCODE_CBFS_FILE);
 	if (!microcode_file)
 		return NULL;
 
 	ucode_updates = CBFS_SUBHEADER(microcode_file);
 	microcode_len = ntohl(microcode_file->len);
+#else
+	ucode_updates = cbfs_boot_map_with_leak(MICROCODE_CBFS_FILE,
+						CBFS_TYPE_MICROCODE,
+						&microcode_len);
+	if (ucode_updates == NULL)
+		return NULL;
+#endif
 
 	/* CPUID sets MSR 0x8B iff a microcode update has been loaded. */
 	msr.lo = 0;
diff --git a/src/cpu/ti/am335x/bootblock_media.c b/src/cpu/ti/am335x/bootblock_media.c
index 93a2d18..4e3bbdc 100644
--- a/src/cpu/ti/am335x/bootblock_media.c
+++ b/src/cpu/ti/am335x/bootblock_media.c
@@ -17,56 +17,16 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <cbfs.h>
-#include <console/console.h>
-#include <string.h>
+#include <boot_device.h>
+#include <region.h>
 #include <symbols.h>
 
-static int dummy_open(struct cbfs_media *media)
-{
-	return 0;
-}
-
-static int dummy_close(struct cbfs_media *media)
-{
-	return 0;
-}
+/* FIXME: No idea how big the internal SRAM actually is. */
+static const struct mem_region_device boot_dev =
+	MEM_REGION_DEV_INIT(_dram + CONFIG_CBFS_HEADER_ROM_OFFSET,
+				CONFIG_ROM_SIZE);
 
-static void * on_chip_memory_map(struct cbfs_media *media, size_t offset,
-				 size_t count)
+const struct region_device *boot_device_ro(void)
 {
-	return _dram + offset;
-}
-
-static void * dummy_unmap(struct cbfs_media *media, const void *address)
-{
-	return NULL;
-}
-
-static size_t on_chip_memory_read(struct cbfs_media *media, void *dest,
-				  size_t offset, size_t count)
-{
-	void *ptr = media->map(media, offset, count);
-	memcpy(dest, ptr, count);
-	media->unmap(media, ptr);
-	return count;
-}
-
-int init_default_cbfs_media(struct cbfs_media *media)
-{
-	struct cbfs_header *header =
-		(struct cbfs_header *)(_dram + CONFIG_CBFS_HEADER_ROM_OFFSET);
-
-	if (CBFS_HEADER_MAGIC != ntohl(header->magic)) {
-		printk(BIOS_ERR, "Invalid CBFS master header at %p\n", header);
-		return -1;
-	}
-
-	media->open = dummy_open;
-	media->close = dummy_close;
-	media->map = on_chip_memory_map;
-	media->unmap = dummy_unmap;
-	media->read = on_chip_memory_read;
-
-	return 0;
+	return &boot_dev.rdev;
 }
diff --git a/src/cpu/ti/am335x/nand.c b/src/cpu/ti/am335x/nand.c
index ddab389..73dedbb 100644
--- a/src/cpu/ti/am335x/nand.c
+++ b/src/cpu/ti/am335x/nand.c
@@ -17,10 +17,10 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <cbfs.h>
+#include <boot_device.h>
 
-int init_default_cbfs_media(struct cbfs_media *media)
+const struct region_device *boot_device_ro(void)
 {
-        /* FIXME: add support for reading coreboot from NAND */
-	return 0;
+	/* FIXME: add support for reading coreboot from NAND */
+	return NULL;
 }
diff --git a/src/cpu/via/nano/update_ucode.c b/src/cpu/via/nano/update_ucode.c
index aa0adeb..a69a291 100644
--- a/src/cpu/via/nano/update_ucode.c
+++ b/src/cpu/via/nano/update_ucode.c
@@ -110,9 +110,8 @@ unsigned int nano_update_ucode(void)
 	u32 *ucode_data;
 	size_t ucode_len;
 
-	ucode_data = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-					   "cpu_microcode_blob.bin",
-					   CBFS_TYPE_MICROCODE, &ucode_len);
+	ucode_data = cbfs_boot_map_with_leak("cpu_microcode_blob.bin",
+					     CBFS_TYPE_MICROCODE, &ucode_len);
 	/* Oops, did you forget to include the microcode ? */
 	if(ucode_data == NULL) {
 		printk(BIOS_ALERT, "WARNING: No microcode file found in CBFS. "
diff --git a/src/device/dram/spd_cache.c b/src/device/dram/spd_cache.c
index 8abb791..fcb1391 100644
--- a/src/device/dram/spd_cache.c
+++ b/src/device/dram/spd_cache.c
@@ -36,8 +36,8 @@ int read_spd_from_cbfs(u8 *buf, int idx)
 	size_t min_len = (idx + 1) * SPD_SIZE;
 
 	printk(BIOS_DEBUG, "read SPD\n");
-	spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin",
-					 CBFS_TYPE_SPD, &spd_file_len);
+	spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD,
+						&spd_file_len);
 	if (!spd_file)
 		printk(BIOS_EMERG, "file [spd.bin] not found in CBFS");
 	if (spd_file_len < min_len)
diff --git a/src/device/oprom/realmode/x86.c b/src/device/oprom/realmode/x86.c
index 919fd6d..7f8c166 100644
--- a/src/device/oprom/realmode/x86.c
+++ b/src/device/oprom/realmode/x86.c
@@ -273,10 +273,9 @@ void vbe_set_graphics(void)
 	vbe_set_mode(&mode_info);
 #if CONFIG_BOOTSPLASH
 	struct jpeg_decdata *decdata;
-	unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-						    "bootsplash.jpg",
-						    CBFS_TYPE_BOOTSPLASH,
-						    NULL);
+	unsigned char *jpeg = cbfs_boot_map_with_leak("bootsplash.jpg",
+							CBFS_TYPE_BOOTSPLASH,
+							NULL);
 	if (!jpeg) {
 		printk(BIOS_DEBUG, "VBE: No bootsplash found.\n");
 		return;
@@ -379,6 +378,9 @@ static u32 VSA_vrRead(u16 classIndex)
 
 void do_vsmbios(void)
 {
+	struct prog vsa = {
+		.name = "vsa",
+	};
 	printk(BIOS_DEBUG, "Preparing for VSA...\n");
 
 	/* Set up C interrupt handlers */
@@ -390,8 +392,8 @@ void do_vsmbios(void)
 	/* Make sure the code is placed. */
 	setup_realmode_code();
 
-	if ((unsigned int)cbfs_load_stage(CBFS_DEFAULT_MEDIA, "vsa") !=
-	    VSA2_ENTRY_POINT) {
+	if (cbfs_boot_load_stage(&vsa) ||
+	    (uintptr_t)prog_entry(&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 6354afe..322bc6c 100644
--- a/src/device/oprom/yabel/vbe.c
+++ b/src/device/oprom/yabel/vbe.c
@@ -724,10 +724,9 @@ void vbe_set_graphics(void)
 	 * cares. */
 	// int imagesize = 1024*768*2;
 
-	unsigned char *jpeg = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-						    "bootsplash.jpg",
-						    CBFS_TYPE_BOOTSPLASH,
-						    NULL);
+	unsigned char *jpeg = cbfs_boot_map_with_leak("bootsplash.jpg",
+							CBFS_TYPE_BOOTSPLASH,
+							NULL);
 	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 dbc05ac..dd70770 100644
--- a/src/device/pci_rom.c
+++ b/src/device/pci_rom.c
@@ -38,8 +38,7 @@ 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(CBFS_DEFAULT_MEDIA, dev->vendor,
-					 dev->device, NULL);
+	rom_header = cbfs_boot_map_optionrom(dev->vendor, dev->device);
 
 	u32 vendev = (dev->vendor << 16) | dev->device;
 	u32 mapped_vendev = vendev;
@@ -48,10 +47,9 @@ struct rom_header *pci_rom_probe(struct device *dev)
 
 	if (!rom_header) {
 		if (vendev != mapped_vendev) {
-			rom_header = cbfs_load_optionrom(
-					CBFS_DEFAULT_MEDIA,
+			rom_header = cbfs_boot_map_optionrom(
 					mapped_vendev >> 16,
-					mapped_vendev & 0xffff, NULL);
+					mapped_vendev & 0xffff);
 		}
 	}
 
diff --git a/src/drivers/intel/fsp/fastboot_cache.c b/src/drivers/intel/fsp/fastboot_cache.c
index bcf39ab..0377ba8 100644
--- a/src/drivers/intel/fsp/fastboot_cache.c
+++ b/src/drivers/intel/fsp/fastboot_cache.c
@@ -63,10 +63,9 @@ static int is_mrc_cache(struct mrc_data_container *mrc_cache)
 static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr)
 {
 	size_t region_size;
-	*mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-						"mrc.cache",
-						CBFS_TYPE_MRC_CACHE,
-						&region_size);
+	*mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache",
+							CBFS_TYPE_MRC_CACHE,
+							&region_size);
 
 	return region_size;
 }
diff --git a/src/drivers/pc80/mc146818rtc.c b/src/drivers/pc80/mc146818rtc.c
index 4f034a2..fe2e1f3 100644
--- a/src/drivers/pc80/mc146818rtc.c
+++ b/src/drivers/pc80/mc146818rtc.c
@@ -212,8 +212,8 @@ enum cb_err get_option(void *dest, const char *name)
 	namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
 
 	/* find the requested entry record */
-	ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
-				   CBFS_COMPONENT_CMOS_LAYOUT, NULL);
+	ct = cbfs_boot_map_with_leak("cmos_layout.bin",
+					CBFS_COMPONENT_CMOS_LAYOUT, NULL);
 	if (!ct) {
 		printk(BIOS_ERR, "RTC: cmos_layout.bin could not be found. "
 						"Options are disabled\n");
@@ -295,8 +295,8 @@ enum cb_err set_option(const char *name, void *value)
 	namelen = strnlen(name, CMOS_MAX_NAME_LENGTH);
 
 	/* find the requested entry record */
-	ct = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
-				   CBFS_COMPONENT_CMOS_LAYOUT, NULL);
+	ct = cbfs_boot_map_with_leak("cmos_layout.bin",
+					CBFS_COMPONENT_CMOS_LAYOUT, NULL);
 	if (!ct) {
 		printk(BIOS_ERR, "cmos_layout.bin could not be found. "
 				 "Options are disabled\n");
diff --git a/src/drivers/spi/spi_flash.c b/src/drivers/spi/spi_flash.c
index d40f72a..20b9b35 100644
--- a/src/drivers/spi/spi_flash.c
+++ b/src/drivers/spi/spi_flash.c
@@ -7,6 +7,7 @@
  * Licensed under the GPL-2 or later.
  */
 
+#include <boot_device.h>
 #include <cbfs.h>
 #include <cpu/x86/smm.h>
 #include <delay.h>
@@ -407,10 +408,8 @@ void lb_spi_flash(struct lb_header *header)
 	flash->size = sizeof(*flash);
 
 	/* Try to get the flash device if not loaded yet */
-	if (!spi_flash_dev) {
-		struct cbfs_media media;
-		init_default_cbfs_media(&media);
-	}
+	if (!spi_flash_dev)
+		boot_device_init();
 
 	if (spi_flash_dev) {
 		flash->flash_size = spi_flash_dev->size;
diff --git a/src/include/boot_device.h b/src/include/boot_device.h
new file mode 100644
index 0000000..b5bca0f
--- /dev/null
+++ b/src/include/boot_device.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 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.
+ */
+
+#ifndef _BOOT_DEVICE_H_
+#define _BOOT_DEVICE_H_
+
+#include <region.h>
+
+/* Return the region_device for the read-only boot device. */
+const struct region_device *boot_device_ro(void);
+/* Initialize the boot device. */
+void boot_device_init(void);
+
+#endif /* _BOOT_DEVICE_H_ */
diff --git a/src/include/cbfs.h b/src/include/cbfs.h
index 315684e..15b08f6 100644
--- a/src/include/cbfs.h
+++ b/src/include/cbfs.h
@@ -14,12 +14,98 @@
  *
  * 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
+ * Foundation, Inc.
  */
 
 #ifndef _CBFS_H_
 #define _CBFS_H_
 
-#include <cbfs_declarations.h>
+#include <cbfs_serialized.h>
+#include <program_loading.h>
+#include <region.h>
+
+/*
+ * CBFS operations consist of the following concepts:
+ * - region_device for the boot media
+ * - cbfsd which is a descriptor for representing a cbfs instance
+ * - cbfsf which is a file handle for manipulating cbfs files
+ */
+
+/* Descriptor for cbfs lookup operations. */
+struct cbfsd;
+/* File handle representing a cbfs file. */
+struct cbfsf;
+
+/***********************************************
+ * Perform CBFS operations on the boot device. *
+ ***********************************************/
+
+/* Return mapping of option rom found in boot device. NULL on error. */
+void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device);
+/* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */
+int cbfs_boot_load_stage(struct prog *prog);
+/* Locate file by name and optional type. Return 0 on success. < 0 on error. */
+int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type);
+/* Map file into memory leaking the mapping. Only should be used when
+ * leaking mappings are a no-op. Returns NULL on error, else returns
+ * the mapping and sets the size of the file. */
+void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size);
+
+/*************************************************
+ * Perform CBFS operations on the provided file. *
+ *************************************************/
+
+/* Map file into memory. Return NULL on error. */
+void *cbfs_file_mmap(const struct cbfsf *fh, size_t offset, size_t size);
+/* Unmap previously mapped file. Returns 0 on success. < 0 on error. */
+int cbfs_file_munmap(const struct cbfsf *fh, void *mapping);
+/* Read size bytes into b at offset in file. Returns the number of bytes
+ * read on success. Returns < 0 on error. */
+ssize_t cbfs_file_readat(const struct cbfsf *fh, void *b, size_t offset,
+				size_t size);
+/* Load stage into memory filling in prog. Return 0 on success. < 0 on error. */
+int cbfs_file_stage_load(const struct cbfsf *fh, struct prog *prog);
+
+/*******************************************************
+ * Perform CBFS operations on the provided descriptor. *
+ *******************************************************/
+
+/* Locate file by name and optional type. Returns 0 on succcess else < 0 on
+ * error.*/
+int cbfs_locate(struct cbfsf *fh, const struct cbfsd *cbfs, const char *name,
+		uint32_t *type);
+
+/*****************************************************************
+ * Support structures and functions. Direct field access should  *
+ * only be done by implementers of cbfs regions -- Not the above *
+ * API.                                                          *
+ *****************************************************************/
+
+struct cbfsd {
+	const struct region_device *rdev;
+	size_t align;
+};
+
+struct cbfsf {
+	struct region_device rdev;
+};
+
+static inline size_t cbfs_file_size(const struct cbfsf *fh)
+{
+	return region_sz(&fh->rdev.region);
+}
+
+/* The cbfs_props struct describes the properties associated with a CBFS. */
+struct cbfs_props {
+	/* Each file is aligned. */
+	size_t align;
+	/* CBFS starts at the following offset within the boot region. */
+	size_t offset;
+	/* CBFS size. */
+	size_t size;
+};
+
+/* Return < 0 on error otherwise props are filled out accordingly. */
+int cbfs_boot_region_properties(struct cbfs_props *props);
 
 #endif
diff --git a/src/include/cbfs_core.h b/src/include/cbfs_core.h
deleted file mode 100644
index c71cc26..0000000
--- a/src/include/cbfs_core.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008 Jordan Crouse <jordan at cosmicpenguin.net>
- * Copyright (C) 2012 Google, Inc.
- * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
- *
- * This file is dual-licensed. You can choose between:
- *   - The GNU GPL, version 2, as published by the Free Software Foundation
- *   - The revised BSD license (without advertising clause)
- *
- * ---------------------------------------------------------------------------
- * 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
- * ---------------------------------------------------------------------------
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ---------------------------------------------------------------------------
- */
-
-#ifndef _CBFS_CORE_H_
-#define _CBFS_CORE_H_
-
-#include <endian.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <cbfs_serialized.h>
-
-#define CBFS_HEADER_INVALID_ADDRESS	((void*)(0xffffffff))
-
-#define CBFS_NAME(_c) (((char *) (_c)) + sizeof(struct cbfs_file))
-#define CBFS_SUBHEADER(_p) ( (void *) ((((uint8_t *) (_p)) + ntohl((_p)->offset))) )
-
-/*
- * ROMCC does not understand uint64_t, so we hide future definitions as they are
- * unlikely to be ever needed from ROMCC
- */
-#ifndef __ROMCC__
-
-#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;
-
-	/* 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.
-	 * 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);
-};
-
-/*
- * Locate file by name and fill in cbfs_file in host byte order. Returns
- * < 0 on error, else the offset of the file data.
- */
-ssize_t cbfs_locate_file(struct cbfs_media *media, struct cbfs_file *file,
-				const char *name);
-
-/* Read count bytes at offset into dest. Return number of bytes read. */
-size_t cbfs_read(struct cbfs_media *media, void *dest, size_t offset,
-			size_t count);
-
-/* 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, size_t *sz);
-
-/* returns decompressed size on success, 0 on failure */
-int cbfs_decompress(int algo, void *src, void *dst, int len);
-
-/* 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 /* __ROMCC__ */
-
-#endif
diff --git a/src/include/cbfs_declarations.h b/src/include/cbfs_declarations.h
deleted file mode 100644
index 03264a2..0000000
--- a/src/include/cbfs_declarations.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008 Jordan Crouse <jordan at cosmicpenguin.net>
- * Copyright (C) 2013-2015 Google, Inc.
- *
- * This file is dual-licensed. You can choose between:
- *   - The GNU GPL, version 2, as published by the Free Software Foundation
- *   - The revised BSD license (without advertising clause)
- *
- * ---------------------------------------------------------------------------
- * 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
- * ---------------------------------------------------------------------------
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ---------------------------------------------------------------------------
- */
-
-#ifndef _CBFS_DECLARATIONS_H_
-#define _CBFS_DECLARATIONS_H_
-
-#include <cbfs_core.h>
-
-int init_backing_media(struct cbfs_media **media, struct cbfs_media *backing);
-void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
-			  uint16_t device, void * dest);
-void *cbfs_load_stage(struct cbfs_media *media, const char *name);
-void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset);
-/* Load a stage from a prog structure. Returns < 0 on error. 0 on success. */
-struct prog;
-int cbfs_load_prog_stage(struct cbfs_media *media, struct prog *prog);
-
-/* 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);
-
-/* Defined in individual arch / board implementation. */
-int init_default_cbfs_media(struct cbfs_media *media);
-
-#if (IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES))
-void cbfs_set_header_offset(size_t offset);
-#else
-static inline void cbfs_set_header_offset(size_t offset) {}
-#endif
-#endif
diff --git a/src/include/rmodule.h b/src/include/rmodule.h
index 242ed91..5dc795c 100644
--- a/src/include/rmodule.h
+++ b/src/include/rmodule.h
@@ -54,7 +54,7 @@ int rmodule_calc_region(unsigned int region_alignment, size_t rmodule_size,
 /* Support for loading rmodule stages. This API is only available when
  * using dynamic cbmem because it uses the dynamic cbmem API to obtain
  * the backing store region for the stage. */
-struct cbfs_stage;
+struct cbfsf;
 struct prog;
 
 struct rmod_stage_load {
@@ -63,7 +63,7 @@ struct rmod_stage_load {
 };
 
 /* Both of the following functions return 0 on success, -1 on error. */
-int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage);
+int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfsf *fh);
 int rmodule_stage_load_from_cbfs(struct rmod_stage_load *rsl);
 
 struct rmodule {
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index 0367d0f..f33f878 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -19,7 +19,8 @@
 subdirs-y += loaders
 
 bootblock-y += prog_ops.c
-bootblock-y += cbfs_gpl.c cbfs_core.c
+bootblock-y += cbfs.c
+bootblock-y += cbfs_boot_props.c
 bootblock-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 bootblock-$(CONFIG_GENERIC_GPIO_LIB) += gpio.c
 
@@ -33,7 +34,8 @@ bootblock-y += region.c
 
 verstage-y += prog_ops.c
 verstage-y += delay.c
-verstage-y += cbfs_gpl.c
+verstage-y += cbfs.c
+verstage-y += cbfs_boot_props.c
 verstage-y += memcmp.c
 verstage-y += region.c
 verstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c
@@ -51,7 +53,8 @@ $(foreach arch,$(ARCH_SUPPORTED),\
 	    $(eval rmodules_$(arch)-y += rmodule.ld))
 
 romstage-$(CONFIG_I2C_TPM) += delay.c
-romstage-y += cbfs_gpl.c cbfs_core.c
+romstage-y += cbfs.c
+romstage-y += cbfs_boot_props.c
 romstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 romstage-$(CONFIG_COMPRESS_RAMSTAGE) += lzma.c lzmadecode.c
 romstage-$(CONFIG_PRIMITIVE_MEMTEST) += primitive_memtest.c
@@ -84,7 +87,8 @@ smm-$(CONFIG_SMM_TSEG) += malloc.c
 ramstage-y += delay.c
 ramstage-y += fallback_boot.c
 ramstage-y += compute_ip_checksum.c
-ramstage-y += cbfs_gpl.c cbfs_core.c
+ramstage-y += cbfs.c
+ramstage-y += cbfs_boot_props.c
 ramstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 ramstage-y += lzma.c lzmadecode.c
 ramstage-y += stack.c
@@ -131,7 +135,9 @@ ramstage-y += mem_pool.c
 romstage-y += region.c
 ramstage-y += region.c
 
-smm-y += cbfs_gpl.c cbfs_core.c memcmp.c
+smm-y += cbfs.c memcmp.c
+smm-y += region.c
+smm-y += mem_pool.c
 smm-$(CONFIG_COMPILER_GCC) += gcc.c
 
 bootblock-y += version.c
diff --git a/src/lib/cbfs.c b/src/lib/cbfs.c
new file mode 100644
index 0000000..b4bcee4
--- /dev/null
+++ b/src/lib/cbfs.c
@@ -0,0 +1,272 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 secunet Security Networks AG
+ * Copyright 2015 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.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <boot_device.h>
+#include <cbfs.h>
+#include <endian.h>
+#include <lib.h>
+
+#define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
+#define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
+#if IS_ENABLED(CONFIG_DEBUG_CBFS)
+#define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x)
+#else
+#define DEBUG(x...)
+#endif
+
+void __attribute__((weak)) boot_device_init(void)
+{
+	/* Default empty implementation to reduce scattered empty functions. */
+}
+
+int cbfs_boot_locate(struct cbfsf *fh, const char *name, uint32_t *type)
+{
+	struct cbfsd cbfs;
+	struct region_device rdev;
+	const struct region_device *boot_dev;
+	struct cbfs_props props;
+
+	boot_device_init();
+
+	if (cbfs_boot_region_properties(&props))
+		return -1;
+
+	/* All boot CBFS operations are performed using the RO devie. */
+	boot_dev = boot_device_ro();
+
+	if (boot_dev == NULL)
+		return -1;
+
+	if (rdev_chain(&rdev, boot_dev, props.offset, props.size))
+		return -1;
+
+	cbfs.rdev = &rdev;
+	cbfs.align = props.align;
+
+	return cbfs_locate(fh, &cbfs, name, type);
+}
+
+void *cbfs_boot_map_with_leak(const char *name, uint32_t type, size_t *size)
+{
+	struct cbfsf fh;
+	size_t fsize;
+
+	if (cbfs_boot_locate(&fh, name, &type))
+		return NULL;
+
+	fsize = cbfs_file_size(&fh);
+
+	if (size != NULL)
+		*size = fsize;
+
+	return cbfs_file_mmap(&fh, 0, fsize);
+}
+
+void *cbfs_file_mmap(const struct cbfsf *fh, size_t offset, size_t size)
+{
+	return rdev_mmap(&fh->rdev, offset, size);
+}
+
+int cbfs_file_munmap(const struct cbfsf *fh, void *mapping)
+{
+	return rdev_munmap(&fh->rdev, mapping);
+}
+
+ssize_t cbfs_file_readat(const struct cbfsf *fh, void *b, size_t offset,
+				size_t size)
+{
+	return rdev_readat(&fh->rdev, b, offset, size);
+}
+
+int cbfs_locate(struct cbfsf *fh, const struct cbfsd *cbfs, const char *name,
+		uint32_t *type)
+{
+	size_t offset;
+	const struct region_device *rd;
+	size_t align;
+
+	offset = 0;
+	rd = cbfs->rdev;
+	align = cbfs->align;
+
+	LOG("Locating '%s'\n", name);
+
+	/* Try to scan the entire cbfs region looking for file name. */
+	while (1) {
+		struct cbfs_file file;
+		const size_t fsz = sizeof(file);
+		char *fname;
+		int name_match;
+		size_t datasz;
+
+		DEBUG("Checking offset %zx\n", offset);
+
+		/* Can't read file. Nothing else to do but bail out. */
+		if (rdev_readat(rd, &file, offset, fsz) != fsz)
+			break;
+
+		if (memcmp(file.magic, CBFS_FILE_MAGIC, sizeof(file.magic))) {
+			offset++;
+			offset = ALIGN_UP(offset, align);
+			continue;
+		}
+
+		file.len = ntohl(file.len);
+		file.type = ntohl(file.type);
+		file.offset = ntohl(file.offset);
+
+		/* See if names match. */
+		fname = rdev_mmap(rd, offset + fsz, file.offset - fsz);
+
+		if (fname == NULL)
+			break;
+
+		name_match = !strcmp(fname, name);
+		rdev_munmap(rd, fname);
+
+		if (!name_match) {
+			DEBUG(" Unmatched '%s' at %zx\n", fname, offset);
+			offset += file.offset + file.len;
+			offset = ALIGN_UP(offset, align);
+			continue;
+		}
+
+		if (type != NULL && *type != file.type) {
+			DEBUG(" Unmatched type %x at %zx\n", file.type, offset);
+			offset += file.offset + file.len;
+			offset = ALIGN_UP(offset, align);
+			continue;
+		}
+
+		LOG("Found @ offset %zx size %x\n", offset, file.len);
+		/* File and type match. Create a chained region_device to
+		 * represent the cbfs file. */
+		offset += file.offset;
+		datasz = file.len;
+		if (rdev_chain(&fh->rdev, rd, offset, datasz))
+			break;
+
+		/* Success. */
+		return 0;
+	}
+
+	LOG("'%s' not found.\n", name);
+	return -1;
+}
+
+#if !ENV_SMM
+static size_t inflate(void *src, void *dst)
+{
+#if defined(__BOOTBLOCK__)
+		return 0;
+#endif
+#if (defined(__PRE_RAM__) && !IS_ENABLED(CONFIG_COMPRESS_RAMSTAGE))
+		return 0;
+#endif
+	return ulzma(src, dst);
+}
+
+static inline int tohex4(unsigned int c)
+{
+	return (c <= 9) ? (c + '0') : (c - 10 + 'a');
+}
+
+static void tohex16(unsigned int val, char* dest)
+{
+	dest[0] = tohex4(val>>12);
+	dest[1] = tohex4((val>>8) & 0xf);
+	dest[2] = tohex4((val>>4) & 0xf);
+	dest[3] = tohex4(val & 0xf);
+}
+
+void *cbfs_boot_map_optionrom(uint16_t vendor, uint16_t device)
+{
+	char name[17] = "pciXXXX,XXXX.rom";
+
+	tohex16(vendor, name+3);
+	tohex16(device, name+8);
+
+	return cbfs_boot_map_with_leak(name, CBFS_TYPE_OPTIONROM, NULL);
+}
+
+int cbfs_boot_load_stage(struct prog *stage)
+{
+	struct cbfsf fh;
+	uint32_t type = CBFS_TYPE_STAGE;
+
+	if (cbfs_boot_locate(&fh, stage->name, &type))
+		return -1;
+
+	return cbfs_file_stage_load(&fh, stage);
+}
+
+int cbfs_file_stage_load(const struct cbfsf *fh, struct prog *pstage)
+{
+	struct cbfs_stage stage;
+	uint8_t *load;
+	void *entry;
+	size_t fsize;
+	size_t foffset;
+
+	if (cbfs_file_readat(fh, &stage, 0, sizeof(stage)) != sizeof(stage))
+		return 0;
+
+	fsize = cbfs_file_size(fh);
+	fsize -= sizeof(stage);
+	foffset = 0;
+	foffset += sizeof(stage);
+
+	assert(fsize == stage.len);
+
+	/* Note: cbfs_stage fields are currently in the endianness of the
+	 * running processor. */
+	load = (void *)(uintptr_t)stage.load;
+	entry = (void *)(uintptr_t)stage.entry;
+
+	if (stage.compression == CBFS_COMPRESS_NONE) {
+		if (cbfs_file_readat(fh, load, foffset, fsize) != fsize)
+			return -1;
+	} else if (stage.compression == CBFS_COMPRESS_LZMA) {
+		void *map = cbfs_file_mmap(fh, foffset, fsize);
+
+		if (map == NULL)
+			return -1;
+
+		fsize = inflate(map, load);
+
+		cbfs_file_munmap(fh, map);
+
+		if (!fsize)
+			return -1;
+	} else
+		return -1;
+
+	/* Clear area not covered by file. */
+	memset(&load[fsize], 0, stage.memlen - fsize);
+
+	prog_set_area(pstage, load, stage.memlen);
+	prog_set_entry(pstage, entry, NULL);
+
+	return 0;
+}
+#endif /* !ENV_SMM */
diff --git a/src/lib/cbfs_boot_props.c b/src/lib/cbfs_boot_props.c
new file mode 100644
index 0000000..93b419a
--- /dev/null
+++ b/src/lib/cbfs_boot_props.c
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 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.
+ */
+
+#include <boot_device.h>
+#include <cbfs.h>
+#include <console/console.h>
+#include <endian.h>
+#include <region.h>
+
+/* This function is marked as weak to allow a particular platform to
+ * override the logic. This implementation should work for most devices. */
+int __attribute__((weak)) cbfs_boot_region_properties(struct cbfs_props *props)
+{
+	struct cbfs_header header;
+	const struct region_device *bdev;
+
+	bdev = boot_device_ro();
+
+	if (bdev == NULL)
+		return -1;
+
+	rdev_readat(bdev, &header, CONFIG_CBFS_HEADER_ROM_OFFSET,
+			sizeof(header));
+
+	header.magic = ntohl(header.magic);
+	header.romsize = ntohl(header.romsize);
+	header.align = ntohl(header.align);
+	header.offset = ntohl(header.offset);
+
+	if (header.magic != CBFS_HEADER_MAGIC)
+		return -1;
+
+	props->align = header.align;
+	props->offset = header.offset;
+	props->size = header.romsize;
+	props->size -= props->offset;
+
+	printk(BIOS_SPEW, "CBFS @ %zx size %zx\n", props->offset, props->size);
+
+	return 0;
+}
diff --git a/src/lib/cbfs_core.c b/src/lib/cbfs_core.c
deleted file mode 100644
index 9f45b3c..0000000
--- a/src/lib/cbfs_core.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2011 secunet Security Networks AG
- * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- *    derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* 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
- *
- * ERROR(x...)
- *      print an error message x (in printf format)
- *
- * LOG(x...)
- *      print a message x (in printf format)
- *
- * DEBUG(x...)
- *      print a debug message x (in printf format)
- *
- */
-
-#include <cbfs.h>
-#include <string.h>
-#include <symbols.h>
-
-#if IS_ENABLED(CONFIG_MULTIPLE_CBFS_INSTANCES)
-void cbfs_set_header_offset(size_t offset)
-{
-	_cbfs_header_offset[0] = offset;
-	LOG("header set to: %#zx\n", offset);
-}
-
-static size_t get_header_offset(void)
-{
-	return _cbfs_header_offset[0];
-}
-#else
-static size_t get_header_offset(void)
-{
-	return 0;
-}
-#endif
-
-#include "cbfs_core.h"
-
-/* 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)
-{
-	size_t offset;
-	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 initialize default media.\n");
-			return CBFS_HEADER_INVALID_ADDRESS;
-		}
-	}
-	media->open(media);
-
-	/* TODO: allow negative offsets from the end of the CBFS image at media
-	 * layer (like libpayload) so we can combine these two cases. */
-	if (IS_ENABLED(CONFIG_ARCH_X86)) {
-		offset = *(int32_t *)(uintptr_t)0xfffffffc;
-		header = media->map(media, offset, sizeof(*header));
-	} else {
-
-		offset = get_header_offset();
-
-		if (!offset) {
-			int32_t rel_offset;
-			size_t cbfs_top = CONFIG_CBFS_SIZE;
-			DEBUG("CBFS top at offset: 0x%zx\n", cbfs_top);
-			if (!media->read(media, &rel_offset, cbfs_top -
-					 sizeof(int32_t),
-					 sizeof(int32_t))) {
-				ERROR("Could not read master header offset!\n");
-				media->close(media);
-				return CBFS_HEADER_INVALID_ADDRESS;
-			}
-			offset = cbfs_top + rel_offset;
-		}
-		header = media->map(media, offset, sizeof(*header));
-	}
-	DEBUG("CBFS header offset: 0x%zx/0x%x\n", offset, CONFIG_ROM_SIZE);
-	media->close(media);
-
-	if (header == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
-		ERROR("Failed to load CBFS header from 0x%zx\n", offset);
-		return CBFS_HEADER_INVALID_ADDRESS;
-	}
-
-	if (CBFS_HEADER_MAGIC != ntohl(header->magic)) {
-		ERROR("Could not find valid CBFS master header at %#zx: "
-		      "magic %#.8x vs %#.8x.\n", offset, CBFS_HEADER_MAGIC,
-		      ntohl(header->magic));
-		if (header->magic == 0xffffffff) {
-			ERROR("Maybe ROM is not mapped properly?\n");
-		}
-		return CBFS_HEADER_INVALID_ADDRESS;
-	}
-	return header;
-}
-
-
-int init_backing_media(struct cbfs_media **media, struct cbfs_media *backing)
-{
-	if (*media == CBFS_DEFAULT_MEDIA) {
-		*media = backing;
-		if (init_default_cbfs_media(*media) != 0) {
-			ERROR("Failed to initialize default media.\n");
-			return -1;
-		}
-	}
-	return 0;
-}
-
-/* public API starts here*/
-ssize_t cbfs_locate_file(struct cbfs_media *media, struct cbfs_file *file,
-				const char *name)
-{
-	const char *file_name;
-	uint32_t offset, align, romsize, name_len;
-	const struct cbfs_header *header;
-	struct cbfs_media default_media;
-
-	if (init_backing_media(&media, &default_media))
-		return -1;
-
-	if (CBFS_HEADER_INVALID_ADDRESS == (header = cbfs_get_header(media)))
-		return -1;
-
-	// Logical offset (for source media) of first file.
-	offset = ntohl(header->offset);
-	align = ntohl(header->align);
-	romsize = ntohl(header->romsize);
-
-	// TODO Add a "size" in CBFS header for a platform independent way to
-	// determine the end of CBFS data.
-#if defined(CONFIG_ARCH_X86) && CONFIG_ARCH_X86
-	// resolve actual length of ROM used for CBFS components
-	// the bootblock size was not taken into account
-	romsize -= ntohl(header->bootblocksize);
-
-	// fine tune the length to handle alignment positioning.
-	// using (bootblock size) % align, to derive the
-	// number of bytes the bootblock is off from the alignment size.
-	if ((ntohl(header->bootblocksize) % align))
-		romsize -= (align - (ntohl(header->bootblocksize) % align));
-	else
-		romsize -= 1;
-#endif
-
-	DEBUG("CBFS location: 0x%x~0x%x, align: %d\n", offset, romsize, align);
-	DEBUG("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);
-			LOG("WARNING: No file header found at 0x%x - "
-			      "try next aligned address: 0x%x.\n", offset,
-			      offset + new_align);
-			offset += new_align;
-			continue;
-		}
-
-		file->len = ntohl(file->len);
-		file->type= ntohl(file->type);
-		file->offset = ntohl(file->offset);
-
-		name_len = 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) {
-			DEBUG("Found file (offset=0x%x, len=%d).\n",
-			    offset + file->offset, file->len);
-			media->unmap(media, file_name);
-			return offset + file->offset;
-		} else {
-			DEBUG(" (unmatched file @0x%x: %s)\n", offset,
-			      file_name);
-			media->unmap(media, file_name);
-		}
-
-		// Move to next file.
-		offset += file->len + file->offset;
-		if (offset % align)
-			offset += align - (offset % align);
-	}
-	media->close(media);
-	LOG("WARNING: '%s' not found.\n", name);
-	return -1;
-}
-
-size_t cbfs_read(struct cbfs_media *media, void *dest, size_t offset,
-			size_t count)
-{
-	struct cbfs_media default_media;
-	size_t nread;
-
-	if (init_backing_media(&media, &default_media))
-		return 0;
-
-	media->open(media);
-	nread = media->read(media, dest, offset, count);
-	media->close(media);
-
-	return nread;
-}
-
-struct cbfs_file *cbfs_get_file(struct cbfs_media *media, const char *name)
-{
-	struct cbfs_media default_media;
-	struct cbfs_file file, *file_ptr;
-	ssize_t offset;
-
-	if (init_backing_media(&media, &default_media))
-		return NULL;
-
-	offset = cbfs_locate_file(media, &file, name);
-	if (offset < 0)
-		return NULL;
-
-	/* Map both the metadata and the file contents. */
-	media->open(media);
-	offset -= file.offset;
-	file_ptr = media->map(media, offset, file.offset + file.len);
-	media->close(media);
-
-	if (file_ptr == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
-		ERROR("ERROR: Mapping %s failed.\n", name);
-		return NULL;
-	}
-
-	return file_ptr;
-}
-
-void *cbfs_get_file_content(struct cbfs_media *media, const char *name,
-			    int type, size_t *sz)
-{
-	struct cbfs_file *file = cbfs_get_file(media, name);
-
-	if (sz)
-		*sz = 0;
-
-	if (file == NULL) {
-		ERROR("Could not find file '%s'.\n", name);
-		return NULL;
-	}
-
-	if (ntohl(file->type) != type) {
-		ERROR("File '%s' is of type %x, but we requested %x.\n", name,
-		      ntohl(file->type), type);
-		return NULL;
-	}
-
-	if (sz)
-		*sz = ntohl(file->len);
-
-	return (void *)CBFS_SUBHEADER(file);
-}
-
-int cbfs_decompress(int algo, void *src, void *dst, int len)
-{
-	switch (algo) {
-		case CBFS_COMPRESS_NONE:
-			/* Reads need to be aligned at 4 bytes to avoid
-			   poor flash performance.  */
-			while (len && ((uintptr_t)src & 3)) {
-				*(u8*)dst++ = *(u8*)src++;
-				len--;
-			}
-			memmove(dst, src, len);
-			return len;
-#ifdef CBFS_CORE_WITH_LZMA
-		case CBFS_COMPRESS_LZMA:
-			return ulzma(src, dst);
-#endif
-		default:
-			ERROR("tried to decompress %d bytes with algorithm #%x,"
-			      "but that algorithm id is unsupported.\n", len,
-			      algo);
-			return 0;
-	}
-}
diff --git a/src/lib/cbfs_core.h b/src/lib/cbfs_core.h
deleted file mode 100644
index c301c33..0000000
--- a/src/lib/cbfs_core.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef __LIB_CBFS_CORE
-#define __LIB_CBFS_CORE
-
-#include <cbfs.h>
-#include <string.h>
-
-#ifdef LIBPAYLOAD
-# include <libpayload-config.h>
-# ifdef CONFIG_LZMA
-#  include <lzma.h>
-#  define CBFS_CORE_WITH_LZMA
-# endif
-# define CBFS_MINI_BUILD
-#elif defined(__SMM__)
-# define CBFS_MINI_BUILD
-#elif defined(__BOOTBLOCK__)
-  /* No LZMA in boot block. */
-#elif defined(__PRE_RAM__) && !CONFIG_COMPRESS_RAMSTAGE
-  /* No LZMA in romstage if ramstage is not compressed. */
-#else
-# define CBFS_CORE_WITH_LZMA
-# include <lib.h>
-#endif
-
-#include <cbfs.h>
-#include <string.h>
-#include <cbmem.h>
-
-#ifdef LIBPAYLOAD
-# include <stdio.h>
-# define DEBUG(x...)
-# define LOG(x...) printf(x)
-# define ERROR(x...) printf(x)
-#else
-# include <console/console.h>
-# define ERROR(x...) printk(BIOS_ERR, "CBFS: " x)
-# define LOG(x...) printk(BIOS_INFO, "CBFS: " x)
-# if CONFIG_DEBUG_CBFS
-#  define DEBUG(x...) printk(BIOS_SPEW, "CBFS: " x)
-# else
-#  define DEBUG(x...)
-# endif
-#endif
-
-#endif /* __LIB_CBFS_CORE */
diff --git a/src/lib/cbfs_gpl.c b/src/lib/cbfs_gpl.c
deleted file mode 100644
index 84638da..0000000
--- a/src/lib/cbfs_gpl.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2008, Jordan Crouse <jordan at cosmicpenguin.net>
- * Copyright (C) 2013 The Chromium OS Authors. All rights reserved.
- *
- * 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 <program_loading.h>
-#include "cbfs_core.h"
-
-#ifndef __SMM__
-static inline int tohex4(unsigned int c)
-{
-	return (c <= 9) ? (c + '0') : (c - 10 + 'a');
-}
-
-static void tohex16(unsigned int val, char* dest)
-{
-	dest[0] = tohex4(val>>12);
-	dest[1] = tohex4((val>>8) & 0xf);
-	dest[2] = tohex4((val>>4) & 0xf);
-	dest[3] = tohex4(val & 0xf);
-}
-
-void *cbfs_load_optionrom(struct cbfs_media *media, uint16_t vendor,
-			  uint16_t device, void *dest)
-{
-	char name[17] = "pciXXXX,XXXX.rom";
-	struct cbfs_optionrom *orom;
-	uint8_t *src;
-
-	tohex16(vendor, name+3);
-	tohex16(device, name+8);
-
-	orom = (struct cbfs_optionrom *)
-	  cbfs_get_file_content(media, name, CBFS_TYPE_OPTIONROM, NULL);
-
-	if (orom == NULL)
-		return NULL;
-
-	/* They might have specified a dest address. If so, we can decompress.
-	 * If not, there's not much hope of decompressing or relocating the rom.
-	 * in the common case, the expansion rom is uncompressed, we
-	 * pass 0 in for the dest, and all we have to do is find the rom and
-	 * return a pointer to it.
-	 */
-
-	/* BUG: the cbfstool is (not yet) including a cbfs_optionrom header */
-	src = (uint8_t *)orom; // + sizeof(struct cbfs_optionrom);
-
-	if (! dest)
-		return src;
-
-	if (!cbfs_decompress(ntohl(orom->compression),
-			     src,
-			     dest,
-			     ntohl(orom->len)))
-		return NULL;
-
-	return dest;
-}
-
-static int cbfs_load_prog_stage_by_offset(struct cbfs_media *media,
-					struct prog *prog, ssize_t offset)
-{
-	struct cbfs_stage stage;
-	struct cbfs_media backing_store;
-
-	if (init_backing_media(&media, &backing_store))
-		return -1;
-
-	if (cbfs_read(media, &stage, offset, sizeof(stage)) != sizeof(stage)) {
-		ERROR("ERROR: failed to read stage header\n");
-		return -1;
-	}
-
-	LOG("loading stage @ 0x%llx (%d bytes), entry @ 0x%llx\n",
-	    stage.load, stage.memlen, stage.entry);
-
-	/* Stages rely the below clearing so that the bss is initialized. */
-	memset((void *)(uintptr_t)stage.load, 0, stage.memlen);
-
-	if (stage.compression == CBFS_COMPRESS_NONE) {
-		if (cbfs_read(media, (void *)(uintptr_t)stage.load,
-			      offset + sizeof(stage), stage.len) != stage.len) {
-			ERROR("ERROR: Reading stage failed.\n");
-			return -1;
-		}
-	} else {
-		void *data = media->map(media, offset + sizeof(stage),
-					stage.len);
-		if (data == CBFS_MEDIA_INVALID_MAP_ADDRESS) {
-			ERROR("ERROR: Mapping stage failed.\n");
-			return -1;
-		}
-		if (!cbfs_decompress(stage.compression, data,
-				    (void *)(uintptr_t)stage.load, stage.len))
-			return -1;
-		media->unmap(media, data);
-	}
-
-	arch_segment_loaded(stage.load, stage.memlen, SEG_FINAL);
-	DEBUG("stage loaded\n");
-
-	prog_set_area(prog, (void *)(uintptr_t)stage.load, stage.memlen);
-	prog_set_entry(prog, (void *)(uintptr_t)stage.entry, NULL);
-
-	return 0;
-}
-
-int cbfs_load_prog_stage(struct cbfs_media *media, struct prog *prog)
-{
-	struct cbfs_file file;
-	ssize_t offset;
-	struct cbfs_media backing_store;
-
-	if (init_backing_media(&media, &backing_store))
-		return -1;
-
-	offset = cbfs_locate_file(media, &file, prog->name);
-	if (offset < 0 || file.type != CBFS_TYPE_STAGE)
-		return -1;
-
-	if (cbfs_load_prog_stage_by_offset(media, prog, offset) < 0)
-		return -1;
-
-	return 0;
-}
-
-void *cbfs_load_stage_by_offset(struct cbfs_media *media, ssize_t offset)
-{
-	struct prog prog = {
-		.name = NULL,
-	};
-
-	if (cbfs_load_prog_stage_by_offset(media, &prog, offset) < 0)
-		return (void *)-1;
-
-	return prog_entry(&prog);
-}
-
-void *cbfs_load_stage(struct cbfs_media *media, const char *name)
-{
-	struct prog prog = {
-		.name = name,
-	};
-
-	if (cbfs_load_prog_stage(media, &prog) < 0)
-		return (void *)-1;
-
-	return prog_entry(&prog);
-}
-
-/* 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=%zd, count=%zd): "
-	      "allocated=%zd, size=%zd, last_allocate=%zd\n",
-	    offset, count, buffer->allocated, buffer->size,
-	    buffer->last_allocate);
-	if (buffer->allocated + count > buffer->size) {
-		ERROR("simple_buffer: no room to map %zd bytes from %#zx\n",
-		      count, offset);
-		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=%zd, size=%zd, last_allocate=%zd\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;
-}
-
-#endif
diff --git a/src/lib/cbfs_spi.c b/src/lib/cbfs_spi.c
index 81e6ec3..1199be5 100644
--- a/src/lib/cbfs_spi.c
+++ b/src/lib/cbfs_spi.c
@@ -23,78 +23,48 @@
  * SPI.
  */
 
-#include <cbfs.h>
+#include <boot_device.h>
+#include <region.h>
 #include <spi_flash.h>
 #include <symbols.h>
 
-/* SPI flash as CBFS media. */
-struct cbfs_spi_context {
-	struct spi_flash *spi_flash_info;
-	struct cbfs_simple_buffer buffer;
-};
-
-static struct cbfs_spi_context spi_context;
-
-static int cbfs_media_open(struct cbfs_media *media)
-{
-	return 0;
-}
+static struct spi_flash *spi_flash_info;
 
-static int cbfs_media_close(struct cbfs_media *media)
+static ssize_t spi_readat(const struct region_device *rd, void *b,
+				size_t offset, size_t size)
 {
-	return 0;
+	if (spi_flash_info->read(spi_flash_info, offset, size, b))
+		return -1;
+	return size;
 }
 
-static size_t cbfs_media_read(struct cbfs_media *media,
-			      void *dest, size_t offset,
-			      size_t count)
-{
-	struct cbfs_spi_context *context = media->context;
+static const struct region_device_ops spi_ops = {
+	.mmap = mmap_helper_rdev_mmap,
+	.munmap = mmap_helper_rdev_munmap,
+	.readat = spi_readat,
+};
 
-	return context->spi_flash_info->read
-		(context->spi_flash_info, offset, count, dest) ? 0 : count;
-}
+static struct mmap_helper_region_device mdev =
+	MMAP_HELPER_REGION_INIT(&spi_ops, 0, CONFIG_ROM_SIZE);
 
-static void *cbfs_media_map(struct cbfs_media *media,
-			    size_t offset, size_t count)
+void boot_device_init(void)
 {
-	struct cbfs_spi_context *context = media->context;
+	int bus = CONFIG_BOOT_MEDIA_SPI_BUS;
+	int cs = 0;
 
-	return cbfs_simple_buffer_map(&context->buffer, media, offset, count);
-}
+	if (spi_flash_info != NULL)
+		return;
 
-static void *cbfs_media_unmap(struct cbfs_media *media,
-			       const void *address)
-{
-	struct cbfs_spi_context *context = media->context;
+	spi_flash_info = spi_flash_probe(bus, cs);
 
-	return cbfs_simple_buffer_unmap(&context->buffer, address);
+	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
 }
 
-static int init_cbfs_media_context(void)
-{
-	if (!spi_context.spi_flash_info) {
-
-		spi_context.spi_flash_info = spi_flash_probe
-			(CONFIG_BOOT_MEDIA_SPI_BUS, 0);
-
-		if (!spi_context.spi_flash_info)
-			return -1;
-
-		spi_context.buffer.buffer = (void *)_cbfs_cache;
-		spi_context.buffer.size = _cbfs_cache_size;
-	}
-	return 0;
-
-}
-int init_default_cbfs_media(struct cbfs_media *media)
+/* Return the CBFS boot device. */
+const struct region_device *boot_device_ro(void)
 {
-	media->context = &spi_context;
-	media->open = cbfs_media_open;
-	media->close = cbfs_media_close;
-	media->read = cbfs_media_read;
-	media->map = cbfs_media_map;
-	media->unmap = cbfs_media_unmap;
+	if (spi_flash_info == NULL)
+		return NULL;
 
-	return init_cbfs_media_context();
+	return &mdev.rdev;
 }
diff --git a/src/lib/coreboot_table.c b/src/lib/coreboot_table.c
index b62f452..e3fccf8 100644
--- a/src/lib/coreboot_table.c
+++ b/src/lib/coreboot_table.c
@@ -397,8 +397,8 @@ unsigned long write_coreboot_table(
 
 #if CONFIG_USE_OPTION_TABLE
 	{
-		struct cmos_option_table *option_table = cbfs_get_file_content(
-				CBFS_DEFAULT_MEDIA, "cmos_layout.bin",
+		struct cmos_option_table *option_table =
+			cbfs_boot_map_with_leak("cmos_layout.bin",
 				CBFS_COMPONENT_CMOS_LAYOUT, NULL);
 		if (option_table) {
 			struct lb_record *rec_dest = lb_new_record(head);
diff --git a/src/lib/loaders/cbfs_payload_loader.c b/src/lib/loaders/cbfs_payload_loader.c
index 3928613..fffb558 100644
--- a/src/lib/loaders/cbfs_payload_loader.c
+++ b/src/lib/loaders/cbfs_payload_loader.c
@@ -24,10 +24,9 @@ static int cbfs_locate_payload(struct prog *payload)
 {
 	void *buffer;
 	size_t size;
-	const int type = CBFS_TYPE_PAYLOAD;
+	const uint32_t type = CBFS_TYPE_PAYLOAD;
 
-	buffer = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, payload->name,
-					type, &size);
+	buffer = cbfs_boot_map_with_leak(payload->name, type, &size);
 
 	if (buffer == NULL)
 		return -1;
diff --git a/src/lib/loaders/cbfs_ramstage_loader.c b/src/lib/loaders/cbfs_ramstage_loader.c
index c460653..bbbf695 100644
--- a/src/lib/loaders/cbfs_ramstage_loader.c
+++ b/src/lib/loaders/cbfs_ramstage_loader.c
@@ -44,8 +44,7 @@ static int cbfs_load_ramstage(struct prog *ramstage)
 
 static int cbfs_load_ramstage(struct prog *ramstage)
 {
-	return cbfs_load_prog_stage(CBFS_DEFAULT_MEDIA, ramstage);
-
+	return cbfs_boot_load_stage(ramstage);
 }
 
 #endif /* CONFIG_RELOCATABLE_RAMSTAGE */
diff --git a/src/lib/loaders/load_and_run_romstage.c b/src/lib/loaders/load_and_run_romstage.c
index 9bd9603..40b65bb 100644
--- a/src/lib/loaders/load_and_run_romstage.c
+++ b/src/lib/loaders/load_and_run_romstage.c
@@ -34,7 +34,7 @@ void run_romstage(void)
 	};
 
 	timestamp_add_now(TS_START_COPYROM);
-	if (cbfs_load_prog_stage(CBFS_DEFAULT_MEDIA, &romstage) < 0) {
+	if (cbfs_boot_load_stage(&romstage) < 0) {
 		if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE))
 			die("Couldn't load romstage.\n");
 		halt();
diff --git a/src/lib/rmodule.c b/src/lib/rmodule.c
index 799d8f0..d886800 100644
--- a/src/lib/rmodule.c
+++ b/src/lib/rmodule.c
@@ -22,6 +22,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <lib.h>
 #include <console/console.h>
 #include <program_loading.h>
 #include <rmodule.h>
@@ -252,34 +253,57 @@ int rmodule_calc_region(unsigned int region_alignment, size_t rmodule_size,
 	return region_alignment - sizeof(struct rmodule_header);
 }
 
-int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage)
+int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfsf *fh)
 {
 	struct rmodule rmod_stage;
 	size_t region_size;
 	char *stage_region;
 	int rmodule_offset;
 	int load_offset;
+	struct cbfs_stage stage;
+	void *rmod_loc;
 
-	if (stage == NULL || rsl->prog == NULL || rsl->prog->name == NULL)
+	if (fh == NULL || rsl->prog == NULL || rsl->prog->name == NULL)
+		return -1;
+
+	if (cbfs_file_readat(fh, &stage, 0, sizeof(stage)) != sizeof(stage))
 		return -1;
 
 	rmodule_offset =
 		rmodule_calc_region(DYN_CBMEM_ALIGN_SIZE,
-		                    stage->memlen, &region_size, &load_offset);
+		                    stage.memlen, &region_size, &load_offset);
 
 	stage_region = cbmem_add(rsl->cbmem_id, region_size);
 
 	if (stage_region == NULL)
 		return -1;
 
+	rmod_loc = &stage_region[rmodule_offset];
+
 	printk(BIOS_INFO, "Decompressing stage %s @ 0x%p (%d bytes)\n",
-	       rsl->prog->name, &stage_region[rmodule_offset], stage->memlen);
+	       rsl->prog->name, rmod_loc, stage.memlen);
+
+	if (stage.compression == CBFS_COMPRESS_NONE) {
+		if (cbfs_file_readat(fh, rmod_loc, sizeof(stage), stage.len) !=
+		    stage.len)
+			return -1;
+	} else if (stage.compression == CBFS_COMPRESS_LZMA) {
+		size_t fsize;
+		void *map = cbfs_file_mmap(fh, sizeof(stage), stage.len);
 
-	if (!cbfs_decompress(stage->compression, &stage[1],
-	                    &stage_region[rmodule_offset], stage->len))
+		if (map == NULL)
+			return -1;
+
+		fsize = ulzma(map, rmod_loc);
+
+		cbfs_file_munmap(fh, map);
+
+		if (!fsize)
+			return -1;
+	} else
 		return -1;
 
-	if (rmodule_parse(&stage_region[rmodule_offset], &rmod_stage))
+	if (rmodule_parse(rmod_loc, &rmod_stage))
 		return -1;
 
 	if (rmodule_load(&stage_region[load_offset], &rmod_stage))
@@ -294,13 +318,11 @@ int rmodule_stage_load(struct rmod_stage_load *rsl, struct cbfs_stage *stage)
 
 int rmodule_stage_load_from_cbfs(struct rmod_stage_load *rsl)
 {
-	struct cbfs_stage *stage;
-
-	stage = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-	                              rsl->prog->name, CBFS_TYPE_STAGE, NULL);
+	struct cbfsf fh;
+	uint32_t type = CBFS_TYPE_STAGE;
 
-	if (stage == NULL)
+	if (cbfs_boot_locate(&fh, rsl->prog->name, &type))
 		return -1;
 
-	return rmodule_stage_load(rsl, stage);
+	return rmodule_stage_load(rsl, &fh);
 }
diff --git a/src/mainboard/emulation/qemu-armv7/media.c b/src/mainboard/emulation/qemu-armv7/media.c
index c3760ab..cb0b275 100644
--- a/src/mainboard/emulation/qemu-armv7/media.c
+++ b/src/mainboard/emulation/qemu-armv7/media.c
@@ -12,55 +12,13 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include <cbfs.h>
-#include <string.h>
-#include <symbols.h>
-#include <console/console.h>
+#include <boot_device.h>
 
-/* Simple memory-mapped ROM emulation. */
+/* Maps directly to qemu memory mapped space of 0x10000 up to rom size. */
+static const struct mem_region_device boot_dev =
+	MEM_REGION_DEV_INIT((void *)0x10000, CONFIG_ROM_SIZE);
 
-static int emu_rom_open(struct cbfs_media *media)
+const struct region_device *boot_device_ro(void)
 {
-	return 0;
-}
-
-static void *emu_rom_map(struct cbfs_media *media, size_t offset, size_t count)
-{
-        return (void*)offset;
-}
-
-static void *emu_rom_unmap(struct cbfs_media *media, const void *address)
-{
-	return NULL;
-}
-
-static size_t emu_rom_read(struct cbfs_media *media, void *dest, size_t offset,
-			   size_t count)
-{
-	void *ptr = emu_rom_map(media, offset, count);
-	memcpy(dest, ptr, count);
-	emu_rom_unmap(media, ptr);
-	return count;
-}
-
-static int emu_rom_close(struct cbfs_media *media)
-{
-	return 0;
-}
-
-int init_emu_rom_cbfs_media(struct cbfs_media *media);
-
-int init_emu_rom_cbfs_media(struct cbfs_media *media)
-{
-	media->open = emu_rom_open;
-	media->close = emu_rom_close;
-	media->map = emu_rom_map;
-	media->unmap = emu_rom_unmap;
-	media->read = emu_rom_read;
-	return 0;
-}
-
-int init_default_cbfs_media(struct cbfs_media *media)
-{
-	return init_emu_rom_cbfs_media(media);
+	return &boot_dev.rdev;
 }
diff --git a/src/mainboard/google/bolt/romstage.c b/src/mainboard/google/bolt/romstage.c
index bead56f..e80aedf 100644
--- a/src/mainboard/google/bolt/romstage.c
+++ b/src/mainboard/google/bolt/romstage.c
@@ -78,8 +78,8 @@ static void copy_spd(struct pei_data *peid)
 	int spd_index = 0; /* No GPIO selection, force index 0 for now */
 
 	printk(BIOS_DEBUG, "SPD index %d\n", spd_index);
-	spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin",
-					 CBFS_TYPE_SPD, &spd_file_len);
+	spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD,
+						&spd_file_len);
 	if (!spd_file)
 		die("SPD data not found.");
 
diff --git a/src/mainboard/google/butterfly/mainboard.c b/src/mainboard/google/butterfly/mainboard.c
index 655fc2f..5420f72 100644
--- a/src/mainboard/google/butterfly/mainboard.c
+++ b/src/mainboard/google/butterfly/mainboard.c
@@ -205,8 +205,8 @@ static void mainboard_init(device_t dev)
 	search_length = find_fmap_entry("RO_VPD", (void **)vpd_region_ptr);
 	search_address = (unsigned long)(*vpd_region_ptr);
 #else
-	void *vpd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "vpd.bin",
-					       CBFS_TYPE_RAW, &search_length);
+	void *vpd_file = cbfs_boot_map_with_leak("vpd.bin", CBFS_TYPE_RAW,
+							&search_length);
 	if (vpd_file) {
 		search_address = (unsigned long)vpd_file;
 	} else {
diff --git a/src/mainboard/google/falco/romstage.c b/src/mainboard/google/falco/romstage.c
index 4e79159..d28a914 100644
--- a/src/mainboard/google/falco/romstage.c
+++ b/src/mainboard/google/falco/romstage.c
@@ -79,8 +79,8 @@ static void copy_spd(struct pei_data *peid)
 	size_t spd_file_len;
 
 	printk(BIOS_DEBUG, "SPD index %d\n", spd_index);
-	spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin",
-					 CBFS_TYPE_SPD, &spd_file_len);
+	spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD,
+						&spd_file_len);
 	if (!spd_file)
 		die("SPD data not found.");
 
diff --git a/src/mainboard/google/link/romstage.c b/src/mainboard/google/link/romstage.c
index 2e7ee52..5872928 100644
--- a/src/mainboard/google/link/romstage.c
+++ b/src/mainboard/google/link/romstage.c
@@ -95,8 +95,8 @@ static void copy_spd(struct pei_data *peid)
 	int spd_index = get_gpios(gpio_vector);
 
 	printk(BIOS_DEBUG, "spd index %d\n", spd_index);
-	spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin",
-					 CBFS_TYPE_SPD, &spd_file_len);
+	spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD,
+						&spd_file_len);
 	if (!spd_file)
 		die("SPD data not found.");
 
diff --git a/src/mainboard/google/panther/lan.c b/src/mainboard/google/panther/lan.c
index 9d9e9be..22da881 100644
--- a/src/mainboard/google/panther/lan.c
+++ b/src/mainboard/google/panther/lan.c
@@ -120,8 +120,8 @@ static void program_mac_address(u16 io_base)
 #if CONFIG_CHROMEOS
 	search_length = find_fmap_entry("RO_VPD", &search_address);
 #else
-	search_address = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "vpd.bin",
-					       CBFS_TYPE_RAW, &search_length);
+	search_address = cbfs_boot_map_with_leak("vpd.bin", CBFS_TYPE_RAW,
+							&search_length);
 #endif
 
 	if (search_length <= 0)
diff --git a/src/mainboard/google/peach_pit/romstage.c b/src/mainboard/google/peach_pit/romstage.c
index 443eafd..b2456fc 100644
--- a/src/mainboard/google/peach_pit/romstage.c
+++ b/src/mainboard/google/peach_pit/romstage.c
@@ -21,12 +21,14 @@
 #include <arch/exception.h>
 #include <arch/stages.h>
 #include <armv7.h>
+#include <boot_device.h>
 #include <cbfs.h>
 #include <cbmem.h>
 #include <console/console.h>
 #include <device/i2c.h>
 #include <drivers/maxim/max77802/max77802.h>
 #include <program_loading.h>
+#include <region.h>
 #include <soc/clk.h>
 #include <soc/cpu.h>
 #include <soc/dmc.h>
@@ -176,29 +178,28 @@ static unsigned long primitive_mem_test(void)
 /* here is a simple SPI debug test, known to fid trouble */
 static void simple_spi_test(void)
 {
-	struct cbfs_media default_media, *media;
+	const struct region_device *boot_dev;
 	int i, amt = 4 * MiB, errors = 0;
 	//u32 *data = (void *)0x40000000;
 	u32 data[1024];
 	u32 in;
 
+	boot_device_init();
+	boot_dev = boot_device_ro();
 	amt = sizeof(data);
-	media = &default_media;
-	if (init_default_cbfs_media(media) != 0) {
+	if (boot_dev == NULL) {
 		printk(BIOS_SPEW, "Failed to initialize default media.\n");
 		return;
 	}
 
-
-	media->open(media);
-	if (media->read(media, data, (size_t) 0, amt) < amt){
+	if (rdev_readat(boot_dev, data, 0, amt) < amt) {
 		printk(BIOS_SPEW, "simple_spi_test fails\n");
 		return;
 	}
 
 
 	for(i = 0; i < amt; i += 4){
-		if (media->read(media, &in, (size_t) i, 4) < 1){
+		if (rdev_readat(boot_dev, &in, i, 4) < 4) {
 			printk(BIOS_SPEW, "simple_spi_test fails at %d\n", i);
 			return;
 		}
@@ -207,7 +208,7 @@ static void simple_spi_test(void)
 			printk(BIOS_SPEW, "BAD at %d(%p):\nRAM %08lx\nSPI %08lx\n",
 			       i, &data[i/4], (unsigned long)data[i/4], (unsigned long)in);
 			/* reread it to see which is wrong. */
-			if (media->read(media, &in, (size_t) i, 4) < 1){
+			if (rdev_readat(boot_dev, &in, i, 4) < 4) {
 				printk(BIOS_SPEW, "simple_spi_test fails at %d\n", i);
 				return;
 			}
diff --git a/src/mainboard/google/peppy/romstage.c b/src/mainboard/google/peppy/romstage.c
index 27962e1..6f00216 100644
--- a/src/mainboard/google/peppy/romstage.c
+++ b/src/mainboard/google/peppy/romstage.c
@@ -82,8 +82,8 @@ static void copy_spd(struct pei_data *peid)
 	size_t spd_file_len;
 
 	printk(BIOS_DEBUG, "SPD index %d\n", spd_index);
-	spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin",
-					 CBFS_TYPE_SPD, &spd_file_len);
+	spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD,
+						&spd_file_len);
 	if (!spd_file)
 		die("SPD data not found.");
 
diff --git a/src/mainboard/google/rambi/romstage.c b/src/mainboard/google/rambi/romstage.c
index 0f431d9..b25e1dc 100644
--- a/src/mainboard/google/rambi/romstage.c
+++ b/src/mainboard/google/rambi/romstage.c
@@ -71,9 +71,10 @@ static void *get_spd_pointer(char *spd_file_content, int total_spds, int *dual)
 
 void mainboard_romstage_entry(struct romstage_params *rp)
 {
-	struct cbfs_file *spd_file;
 	void *spd_content;
 	int dual_channel = 0;
+	void *spd_file;
+	size_t spd_fsize;
 
 	struct mrc_params mp = {
 		.mainboard = {
@@ -83,12 +84,12 @@ void mainboard_romstage_entry(struct romstage_params *rp)
 		},
 	};
 
-	spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin");
+	spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD,
+						&spd_fsize);
 	if (!spd_file)
 		die("SPD data not found.");
 
-	spd_content = get_spd_pointer(CBFS_SUBHEADER(spd_file),
-	                              ntohl(spd_file->len) / SPD_SIZE,
+	spd_content = get_spd_pointer(spd_file, spd_fsize / SPD_SIZE,
 	                              &dual_channel);
 	mp.mainboard.dram_data[0] = spd_content;
 	if (dual_channel)
diff --git a/src/mainboard/google/samus/spd/spd.c b/src/mainboard/google/samus/spd/spd.c
index 4f4f9ef..de41c71 100644
--- a/src/mainboard/google/samus/spd/spd.c
+++ b/src/mainboard/google/samus/spd/spd.c
@@ -90,8 +90,8 @@ void mainboard_fill_spd_data(struct pei_data *pei_data)
 	};
 	int spd_gpio[4];
 	int spd_index;
-	int spd_file_len;
-	struct cbfs_file *spd_file;
+	size_t spd_file_len;
+	char *spd_file;
 
 	spd_gpio[0] = get_gpio(spd_bits[0]);
 	spd_gpio[1] = get_gpio(spd_bits[1]);
@@ -106,10 +106,9 @@ void mainboard_fill_spd_data(struct pei_data *pei_data)
 	       spd_bits[3], spd_gpio[3], spd_bits[2], spd_gpio[2],
 	       spd_bits[1], spd_gpio[1], spd_bits[0], spd_gpio[0]);
 
-	spd_file = cbfs_get_file(CBFS_DEFAULT_MEDIA, "spd.bin");
+	spd_file = cbfs_boot_map_with_leak("spd.bin", 0xab, &spd_file_len);
 	if (!spd_file)
 		die("SPD data not found.");
-	spd_file_len = ntohl(spd_file->len);
 
 	if (spd_file_len < ((spd_index + 1) * SPD_LEN)) {
 		printk(BIOS_ERR, "SPD index override to 0 - old hardware?\n");
@@ -121,10 +120,8 @@ void mainboard_fill_spd_data(struct pei_data *pei_data)
 
 	/* Assume same memory in both channels */
 	spd_index *= SPD_LEN;
-	memcpy(pei_data->spd_data[0][0],
-	       ((char*)CBFS_SUBHEADER(spd_file)) + spd_index, SPD_LEN);
-	memcpy(pei_data->spd_data[1][0],
-	       ((char*)CBFS_SUBHEADER(spd_file)) + spd_index, SPD_LEN);
+	memcpy(pei_data->spd_data[0][0], spd_file + spd_index, SPD_LEN);
+	memcpy(pei_data->spd_data[1][0], spd_file + spd_index, SPD_LEN);
 
 	/* Make sure a valid SPD was found */
 	if (pei_data->spd_data[0][0][0] == 0)
diff --git a/src/mainboard/google/slippy/romstage.c b/src/mainboard/google/slippy/romstage.c
index c242ecd..c89687f 100644
--- a/src/mainboard/google/slippy/romstage.c
+++ b/src/mainboard/google/slippy/romstage.c
@@ -80,8 +80,8 @@ static void copy_spd(struct pei_data *peid)
 	size_t spd_file_len;
 
 	printk(BIOS_DEBUG, "SPD index %d\n", spd_index);
-	spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin",
-					 CBFS_TYPE_SPD, &spd_file_len);
+	spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD,
+						&spd_file_len);
 	if (!spd_file)
 		die("SPD data not found.");
 
diff --git a/src/mainboard/samsung/lumpy/romstage.c b/src/mainboard/samsung/lumpy/romstage.c
index e63a8f9..7e32282 100644
--- a/src/mainboard/samsung/lumpy/romstage.c
+++ b/src/mainboard/samsung/lumpy/romstage.c
@@ -237,8 +237,8 @@ void main(unsigned long bist)
 		break;
 	}
 
-	spd_data = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin",
-					 CBFS_TYPE_SPD, &spd_file_len);
+	spd_data = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD,
+						&spd_file_len);
 	if (!spd_data)
 		die("SPD data not found.");
 	if (spd_file_len < (spd_index + 1) * 256)
diff --git a/src/mainboard/siemens/mc_tcu3/modhwinfo.c b/src/mainboard/siemens/mc_tcu3/modhwinfo.c
index 95bb76c..b077868 100644
--- a/src/mainboard/siemens/mc_tcu3/modhwinfo.c
+++ b/src/mainboard/siemens/mc_tcu3/modhwinfo.c
@@ -31,8 +31,7 @@ u8* get_first_linked_block(char *filename, u8 **file_offset)
 {
 	u8* block_ptr = NULL;
 
-	block_ptr = (cbfs_get_file_content(CBFS_DEFAULT_MEDIA, filename,
-			0x50, NULL));
+	block_ptr = cbfs_boot_map_with_leak(filename, 0x50, NULL);
 	if (!block_ptr)
 		return NULL;
 	if (!strncmp((char*)block_ptr, "H1W2M3I4", LEN_MAGIC_NUM)) {
@@ -57,8 +56,7 @@ struct hwinfo* get_hwinfo(char *filename)
 {
 	struct hwinfo* main_hwinfo;
 
-	main_hwinfo = (struct hwinfo*)(cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-							filename, 0x50, NULL));
+	main_hwinfo = cbfs_boot_map_with_leak(filename, 0x50, NULL);
 	if ((main_hwinfo) &&
 		(!strncmp(main_hwinfo->magicNumber, "H1W2M3I4", LEN_MAGIC_NUM)) &&
 		(main_hwinfo->length == LEN_MAIN_HWINFO))
diff --git a/src/northbridge/amd/agesa/common/common.c b/src/northbridge/amd/agesa/common/common.c
index 29b4c2e..e4f8e9d 100644
--- a/src/northbridge/amd/agesa/common/common.c
+++ b/src/northbridge/amd/agesa/common/common.c
@@ -38,7 +38,8 @@ AGESA_STATUS common_ReadCbfsSpd (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 
 	char *spd_file;
 
-	spd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "spd.bin", CBFS_TYPE_SPD_BIN, &spd_file_length);
+	spd_file = cbfs_boot_map_with_leak("spd.bin", CBFS_TYPE_SPD_BIN,
+						&spd_file_length);
 	if (!spd_file)
 		die("file [spd.bin] not found in CBFS");
 
diff --git a/src/northbridge/amd/agesa/def_callouts.c b/src/northbridge/amd/agesa/def_callouts.c
index 26b1c0d..3f83e9e 100644
--- a/src/northbridge/amd/agesa/def_callouts.c
+++ b/src/northbridge/amd/agesa/def_callouts.c
@@ -117,8 +117,8 @@ AGESA_STATUS agesa_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt)
 {
 	GFX_VBIOS_IMAGE_INFO  *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
-	pVbiosImageInfo->ImagePtr = cbfs_get_file_content(
-			CBFS_DEFAULT_MEDIA, "pci"CONFIG_VGA_BIOS_ID".rom",
+	pVbiosImageInfo->ImagePtr = cbfs_boot_map_with_leak(
+			"pci"CONFIG_VGA_BIOS_ID".rom",
 			CBFS_TYPE_OPTIONROM, NULL);
 	/* printk(BIOS_DEBUG, "IMGptr=%x\n", pVbiosImageInfo->ImagePtr); */
 	return pVbiosImageInfo->ImagePtr == NULL ? AGESA_WARNING : AGESA_SUCCESS;
diff --git a/src/northbridge/amd/pi/def_callouts.c b/src/northbridge/amd/pi/def_callouts.c
index 2caf183..56a24ac 100644
--- a/src/northbridge/amd/pi/def_callouts.c
+++ b/src/northbridge/amd/pi/def_callouts.c
@@ -107,8 +107,8 @@ AGESA_STATUS agesa_RunFuncOnAp (UINT32 Func, UINT32 Data, VOID *ConfigPtr)
 AGESA_STATUS agesa_GfxGetVbiosImage(UINT32 Func, UINT32 FchData, VOID *ConfigPrt)
 {
 	GFX_VBIOS_IMAGE_INFO  *pVbiosImageInfo = (GFX_VBIOS_IMAGE_INFO *)ConfigPrt;
-	pVbiosImageInfo->ImagePtr = cbfs_get_file_content(
-			CBFS_DEFAULT_MEDIA, "pci"CONFIG_VGA_BIOS_ID".rom",
+	pVbiosImageInfo->ImagePtr = cbfs_boot_map_with_leak(
+			"pci"CONFIG_VGA_BIOS_ID".rom",
 			CBFS_TYPE_OPTIONROM, NULL);
 	printk(BIOS_DEBUG, "agesa_GfxGetVbiosImage: IMGptr=%p\n", pVbiosImageInfo->ImagePtr);
 	return (pVbiosImageInfo->ImagePtr ? AGESA_SUCCESS : AGESA_WARNING);
diff --git a/src/northbridge/intel/haswell/mrccache.c b/src/northbridge/intel/haswell/mrccache.c
index 8fbac17..d6522a0 100644
--- a/src/northbridge/intel/haswell/mrccache.c
+++ b/src/northbridge/intel/haswell/mrccache.c
@@ -70,10 +70,9 @@ static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr)
 	return find_fmap_entry("RW_MRC_CACHE", (void **)mrc_region_ptr);
 #else
 	size_t region_size;
-	*mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-						"mrc.cache",
-						CBFS_TYPE_MRC_CACHE,
-						&region_size);
+	*mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache",
+							CBFS_TYPE_MRC_CACHE,
+							&region_size);
 	return region_size;
 #endif
 }
diff --git a/src/northbridge/intel/haswell/raminit.c b/src/northbridge/intel/haswell/raminit.c
index 6bbb215..4740f73 100644
--- a/src/northbridge/intel/haswell/raminit.c
+++ b/src/northbridge/intel/haswell/raminit.c
@@ -162,8 +162,8 @@ void sdram_initialize(struct pei_data *pei_data)
 	pei_data->tx_byte = do_putchar;
 
 	/* Locate and call UEFI System Agent binary. */
-	entry = (unsigned long)cbfs_get_file_content(
-		CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, NULL);
+	entry = (unsigned long)cbfs_boot_map_with_leak("mrc.bin",
+							CBFS_TYPE_MRC, NULL);
 	if (entry) {
 		int rv;
 		asm volatile (
diff --git a/src/northbridge/intel/i82830/vga.c b/src/northbridge/intel/i82830/vga.c
index f846e37..cd07dcb 100644
--- a/src/northbridge/intel/i82830/vga.c
+++ b/src/northbridge/intel/i82830/vga.c
@@ -31,8 +31,7 @@ static void vga_init(device_t dev)
 {
 	printk(BIOS_INFO, "Starting Graphics Initialization\n");
 	size_t mbi_len;
-	void *mbi = cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "mbi.bin",
-					  CBFS_TYPE_MBI, &mbi_len);
+	void *mbi = cbfs_boot_map_with_leak("mbi.bin", CBFS_TYPE_MBI, &mbi_len);
 
 	if (mbi && mbi_len) {
 		/* The GDT or coreboot table is going to live here. But
diff --git a/src/northbridge/intel/sandybridge/mrccache.c b/src/northbridge/intel/sandybridge/mrccache.c
index 4a69233..6b02c21 100644
--- a/src/northbridge/intel/sandybridge/mrccache.c
+++ b/src/northbridge/intel/sandybridge/mrccache.c
@@ -70,10 +70,9 @@ static u32 get_mrc_cache_region(struct mrc_data_container **mrc_region_ptr)
 	return find_fmap_entry("RW_MRC_CACHE", (void **)mrc_region_ptr);
 #else
 	size_t region_size;
-	*mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-						"mrc.cache",
-						CBFS_TYPE_MRC_CACHE,
-						&region_size);
+	*mrc_region_ptr = cbfs_boot_map_with_leak("mrc.cache",
+							CBFS_TYPE_MRC_CACHE,
+							&region_size);
 	return region_size;
 #endif
 
diff --git a/src/northbridge/intel/sandybridge/raminit.c b/src/northbridge/intel/sandybridge/raminit.c
index d8c7eef..fde0cfa 100644
--- a/src/northbridge/intel/sandybridge/raminit.c
+++ b/src/northbridge/intel/sandybridge/raminit.c
@@ -246,8 +246,7 @@ void sdram_initialize(struct pei_data *pei_data)
 	pei_data->tx_byte = do_putchar;
 
 	/* Locate and call UEFI System Agent binary. */
-	entry = cbfs_get_file_content(
-		CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, NULL);
+	entry = cbfs_boot_map_with_leak("mrc.bin", CBFS_TYPE_MRC, NULL);
 	if (entry) {
 		int rv;
 		rv = entry (pei_data);
diff --git a/src/soc/intel/baytrail/romstage/raminit.c b/src/soc/intel/baytrail/romstage/raminit.c
index 61c122c..8611d70 100644
--- a/src/soc/intel/baytrail/romstage/raminit.c
+++ b/src/soc/intel/baytrail/romstage/raminit.c
@@ -148,8 +148,7 @@ void raminit(struct mrc_params *mp, int prev_sleep_state)
 	}
 
 	/* Determine if mrc.bin is in the cbfs. */
-	if (cbfs_get_file_content(CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC,
-			NULL) == NULL) {
+	if (cbfs_boot_map_with_leak("mrc.bin", CBFS_TYPE_MRC, NULL) == NULL) {
 		printk(BIOS_DEBUG, "Couldn't find mrc.bin\n");
 		return;
 	}
diff --git a/src/soc/intel/broadwell/romstage/raminit.c b/src/soc/intel/broadwell/romstage/raminit.c
index 52ea491..7b46a90 100644
--- a/src/soc/intel/broadwell/romstage/raminit.c
+++ b/src/soc/intel/broadwell/romstage/raminit.c
@@ -86,8 +86,7 @@ void raminit(struct pei_data *pei_data)
 	}
 
 	/* Determine if mrc.bin is in the cbfs. */
-	entry = (pei_wrapper_entry_t)cbfs_get_file_content(
-		CBFS_DEFAULT_MEDIA, "mrc.bin", CBFS_TYPE_MRC, NULL);
+	entry = cbfs_boot_map_with_leak("mrc.bin", CBFS_TYPE_MRC, NULL);
 	if (entry == NULL) {
 		printk(BIOS_DEBUG, "Couldn't find mrc.bin\n");
 		return;
diff --git a/src/soc/nvidia/tegra124/Makefile.inc b/src/soc/nvidia/tegra124/Makefile.inc
index 49669eb..1127682 100644
--- a/src/soc/nvidia/tegra124/Makefile.inc
+++ b/src/soc/nvidia/tegra124/Makefile.inc
@@ -1,6 +1,5 @@
 bootblock-y += bootblock.c
 bootblock-y += bootblock_asm.S
-bootblock-y += cbfs.c
 bootblock-y += clock.c
 bootblock-y += dma.c
 bootblock-y += i2c.c
@@ -20,7 +19,6 @@ bootblock-$(CONFIG_DRIVERS_UART) += uart.c
 endif
 
 verstage-y += verstage.c
-verstage-y += cbfs.c
 verstage-y += dma.c
 verstage-y += monotonic_timer.c
 verstage-y += spi.c
@@ -32,7 +30,6 @@ verstage-y += clock.c
 verstage-y += i2c.c
 verstage-y += cache.c
 
-romstage-y += cbfs.c
 romstage-y += cbmem.c
 romstage-y += clock.c
 romstage-y += dma.c
@@ -49,7 +46,6 @@ romstage-y += ../tegra/pinmux.c
 romstage-y += cache.c
 romstage-$(CONFIG_DRIVERS_UART) += uart.c
 
-ramstage-y += cbfs.c
 ramstage-y += cbmem.c
 ramstage-y += clock.c
 ramstage-y += display.c
diff --git a/src/soc/nvidia/tegra124/cbfs.c b/src/soc/nvidia/tegra124/cbfs.c
deleted file mode 100644
index 33a7258..0000000
--- a/src/soc/nvidia/tegra124/cbfs.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 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 <cbfs.h>  /* This driver serves as a CBFS media source. */
-#include <soc/spi.h>
-#include <symbols.h>
-
-int init_default_cbfs_media(struct cbfs_media *media)
-{
-	return initialize_tegra_spi_cbfs_media(media,
-		_cbfs_cache, _cbfs_cache_size);
-}
diff --git a/src/soc/nvidia/tegra124/include/soc/spi.h b/src/soc/nvidia/tegra124/include/soc/spi.h
index ab04632..cfa3cd2 100644
--- a/src/soc/nvidia/tegra124/include/soc/spi.h
+++ b/src/soc/nvidia/tegra124/include/soc/spi.h
@@ -61,11 +61,6 @@ struct tegra_spi_channel {
 	enum spi_xfer_mode xfer_mode;
 };
 
-struct cbfs_media;
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
-				     void *buffer_address,
-				     size_t buffer_size);
-
 struct tegra_spi_channel *tegra_spi_init(unsigned int bus);
 
 #endif	/* __NVIDIA_TEGRA124_SPI_H__ */
diff --git a/src/soc/nvidia/tegra124/spi.c b/src/soc/nvidia/tegra124/spi.c
index aefb4da..ba9cefa 100644
--- a/src/soc/nvidia/tegra124/spi.c
+++ b/src/soc/nvidia/tegra124/spi.c
@@ -21,10 +21,12 @@
 #include <arch/cache.h>
 #include <arch/io.h>
 #include <assert.h>
+#include <boot_device.h>
 #include <console/console.h>
 #include <cbfs.h>
 #include <delay.h>
 #include <inttypes.h>
+#include <region.h>
 #include <soc/addressmap.h>
 #include <soc/dma.h>
 #include <soc/spi.h>
@@ -33,6 +35,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <symbols.h>
 #include <timer.h>
 
 
@@ -799,22 +802,13 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
 	return ret;
 }
 
-/* SPI as CBFS media. */
-struct tegra_spi_media {
-	struct spi_slave *slave;
-	struct cbfs_simple_buffer buffer;
-};
-
-static int tegra_spi_cbfs_open(struct cbfs_media *media)
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
 {
-	DEBUG_SPI("tegra_spi_cbfs_open\n");
-	return 0;
-}
+	struct tegra_spi_channel *channel = to_tegra_spi(bus);
+	if (!channel)
+		return NULL;
 
-static int tegra_spi_cbfs_close(struct cbfs_media *media)
-{
-	DEBUG_SPI("tegra_spi_cbfs_close\n");
-	return 0;
+	return &channel->slave;
 }
 
 #define JEDEC_READ			0x03
@@ -822,16 +816,17 @@ static int tegra_spi_cbfs_close(struct cbfs_media *media)
 #define JEDEC_FAST_READ_DUAL		0x3b
 #define JEDEC_FAST_READ_DUAL_OUTSIZE	0x05
 
-static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
-				   size_t offset, size_t count)
+static struct spi_slave *boot_slave;
+
+static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
+				size_t offset, size_t count)
 {
-	struct tegra_spi_media *spi = (struct tegra_spi_media *)media->context;
 	u8 spi_read_cmd[JEDEC_FAST_READ_DUAL_OUTSIZE];
 	unsigned int read_cmd_bytes;
 	int ret = count;
 	struct tegra_spi_channel *channel;
 
-	channel = to_tegra_spi(spi->slave->bus);
+	channel = to_tegra_spi(boot_slave->bus);
 
 	if (channel->dual_mode) {
 		/*
@@ -852,9 +847,9 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
 	spi_read_cmd[2] = (offset >> 8) & 0xff;
 	spi_read_cmd[3] = offset & 0xff;
 
-	spi_claim_bus(spi->slave);
+	spi_claim_bus(boot_slave);
 
-	if (spi_xfer(spi->slave, spi_read_cmd,
+	if (spi_xfer(boot_slave, spi_read_cmd,
 			read_cmd_bytes, NULL, 0) < 0) {
 		ret = -1;
 		printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n",
@@ -865,7 +860,7 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
 	if (channel->dual_mode) {
 		setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT);
 	}
-	if (spi_xfer(spi->slave, NULL, 0, dest, count)) {
+	if (spi_xfer(boot_slave, NULL, 0, dest, count)) {
 		ret = -1;
 		printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n",
 				__func__, count);
@@ -875,64 +870,35 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
 
 tegra_spi_cbfs_read_exit:
 	/* de-assert /CS */
-	spi_release_bus(spi->slave);
-	return (ret < 0) ? 0 : ret;
+	spi_release_bus(boot_slave);
+	return ret;
 }
 
-static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset,
-				 size_t count)
-{
-	struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
-	void *map;
-	DEBUG_SPI("tegra_spi_cbfs_map\n");
-	map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
-	return map;
-}
+static const struct region_device_ops tegra_spi_ops = {
+	.mmap = mmap_helper_rdev_mmap,
+	.munmap = mmap_helper_rdev_munmap,
+	.readat = tegra_spi_readat,
+};
 
-static void *tegra_spi_cbfs_unmap(struct cbfs_media *media,
-				   const void *address)
+static struct mmap_helper_region_device mdev =
+	MMAP_HELPER_REGION_INIT(&tegra_spi_ops, 0, CONFIG_ROM_SIZE);
+
+const struct region_device *boot_device_ro(void)
 {
-	struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
-	DEBUG_SPI("tegra_spi_cbfs_unmap\n");
-	return cbfs_simple_buffer_unmap(&spi->buffer, address);
+	return &mdev.rdev;
 }
 
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
-				     void *buffer_address,
-				     size_t buffer_size)
+void boot_device_init(void)
 {
-	// TODO Replace static variable to support multiple streams.
-	static struct tegra_spi_media context;
-	static struct tegra_spi_channel *channel;
-
-	channel = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1];
-	channel->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
-
-	DEBUG_SPI("Initializing CBFS media on SPI\n");
-
-	context.slave = &channel->slave;
-	context.buffer.allocated = context.buffer.last_allocate = 0;
-	context.buffer.buffer = buffer_address;
-	context.buffer.size = buffer_size;
-	media->context = (void*)&context;
-	media->open = tegra_spi_cbfs_open;
-	media->close = tegra_spi_cbfs_close;
-	media->read = tegra_spi_cbfs_read;
-	media->map = tegra_spi_cbfs_map;
-	media->unmap = tegra_spi_cbfs_unmap;
+	struct tegra_spi_channel *boot_chan;
+
+	boot_chan = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1];
+	boot_chan->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
 
 #if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1
-	channel->dual_mode = 1;
+	boot_chan->dual_mode = 1;
 #endif
+	boot_slave = &boot_chan->slave;
 
-	return 0;
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
-{
-	struct tegra_spi_channel *channel = to_tegra_spi(bus);
-	if (!channel)
-		return NULL;
-
-	return &channel->slave;
+	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
 }
diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc
index fb81548..8ee1323 100644
--- a/src/soc/nvidia/tegra132/Makefile.inc
+++ b/src/soc/nvidia/tegra132/Makefile.inc
@@ -1,6 +1,5 @@
 bootblock-y += bootblock.c
 bootblock-y += bootblock_asm.S
-bootblock-y += cbfs.c
 bootblock-y += clock.c
 bootblock-y += spi.c
 bootblock-y += i2c.c
@@ -37,7 +36,6 @@ verstage-y += i2c.c
 romstage-y += 32bit_reset.S
 romstage-y += romstage_asm.S
 romstage-y += addressmap.c
-romstage-y += cbfs.c
 romstage-y += cbmem.c
 romstage-y += ccplex.c
 romstage-y += clock.c
@@ -61,7 +59,6 @@ romstage-$(CONFIG_DRIVERS_UART) += uart.c
 
 ramstage-y += 32bit_reset.S
 ramstage-y += addressmap.c
-ramstage-y += cbfs.c
 ramstage-y += cbmem.c
 ramstage-y += cpu.c
 ramstage-y += cpu_lib.S
diff --git a/src/soc/nvidia/tegra132/cbfs.c b/src/soc/nvidia/tegra132/cbfs.c
deleted file mode 100644
index 2efd48b..0000000
--- a/src/soc/nvidia/tegra132/cbfs.c
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2014 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 <cbfs.h>  /* This driver serves as a CBFS media source. */
-#include <soc/spi.h>
-#include <symbols.h>
-
-int init_default_cbfs_media(struct cbfs_media *media)
-{
-	return initialize_tegra_spi_cbfs_media(media,
-		_cbfs_cache, _cbfs_cache_size);
-}
diff --git a/src/soc/nvidia/tegra132/ccplex.c b/src/soc/nvidia/tegra132/ccplex.c
index 520c244..9cf34dd 100644
--- a/src/soc/nvidia/tegra132/ccplex.c
+++ b/src/soc/nvidia/tegra132/ccplex.c
@@ -75,10 +75,9 @@ static int ccplex_start(void)
 
 int ccplex_load_mts(void)
 {
-	struct cbfs_file file;
-	ssize_t offset;
-	size_t nread;
+	ssize_t nread;
 	struct stopwatch sw;
+	struct cbfsf fh;
 
 	/*
 	 * MTS location is hard coded to this magic address. The hardware will
@@ -86,21 +85,19 @@ int ccplex_load_mts(void)
 	 * place in the carveout region.
 	 */
 	void * const mts = (void *)(uintptr_t)MTS_LOAD_ADDRESS;
-	struct cbfs_media *media = CBFS_DEFAULT_MEDIA;
 
 	stopwatch_init(&sw);
-	offset = cbfs_locate_file(media, &file, MTS_FILE_NAME);
-	if (offset < 0) {
+	if (cbfs_boot_locate(&fh, MTS_FILE_NAME, NULL)) {
 		printk(BIOS_DEBUG, "MTS file not found: %s\n", MTS_FILE_NAME);
 		return -1;
 	}
 
 	/* Read MTS file into the carveout region. */
-	nread = cbfs_read(media, mts, offset, file.len);
+	nread = cbfs_file_readat(&fh, mts, 0, cbfs_file_size(&fh));
 
-	if (nread != file.len) {
+	if (nread != cbfs_file_size(&fh)) {
 		printk(BIOS_DEBUG, "MTS bytes read (%zu) != file length(%u)!\n",
-			nread, file.len);
+			nread, cbfs_file_size(&fh));
 		return -1;
 	}
 
diff --git a/src/soc/nvidia/tegra132/include/soc/spi.h b/src/soc/nvidia/tegra132/include/soc/spi.h
index 2fd9562..4c91c27 100644
--- a/src/soc/nvidia/tegra132/include/soc/spi.h
+++ b/src/soc/nvidia/tegra132/include/soc/spi.h
@@ -62,11 +62,6 @@ struct tegra_spi_channel {
 	enum spi_xfer_mode xfer_mode;
 };
 
-struct cbfs_media;
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
-				     void *buffer_address,
-				     size_t buffer_size);
-
 struct tegra_spi_channel *tegra_spi_init(unsigned int bus);
 
 #endif	/* __NVIDIA_TEGRA132_SPI_H__ */
diff --git a/src/soc/nvidia/tegra132/spi.c b/src/soc/nvidia/tegra132/spi.c
index 0bff31a..9fce8de 100644
--- a/src/soc/nvidia/tegra132/spi.c
+++ b/src/soc/nvidia/tegra132/spi.c
@@ -21,10 +21,12 @@
 #include <arch/cache.h>
 #include <arch/io.h>
 #include <assert.h>
+#include <boot_device.h>
 #include <cbfs.h>
 #include <console/console.h>
 #include <delay.h>
 #include <inttypes.h>
+#include <region.h>
 #include <spi-generic.h>
 #include <spi_flash.h>
 #include <soc/addressmap.h>
@@ -33,6 +35,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <symbols.h>
 #include <timer.h>
 
 
@@ -808,22 +811,13 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
 	return ret;
 }
 
-/* SPI as CBFS media. */
-struct tegra_spi_media {
-	struct spi_slave *slave;
-	struct cbfs_simple_buffer buffer;
-};
-
-static int tegra_spi_cbfs_open(struct cbfs_media *media)
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
 {
-	DEBUG_SPI("tegra_spi_cbfs_open\n");
-	return 0;
-}
+	struct tegra_spi_channel *channel = to_tegra_spi(bus);
+	if (!channel)
+		return NULL;
 
-static int tegra_spi_cbfs_close(struct cbfs_media *media)
-{
-	DEBUG_SPI("tegra_spi_cbfs_close\n");
-	return 0;
+	return &channel->slave;
 }
 
 #define JEDEC_READ			0x03
@@ -831,16 +825,17 @@ static int tegra_spi_cbfs_close(struct cbfs_media *media)
 #define JEDEC_FAST_READ_DUAL		0x3b
 #define JEDEC_FAST_READ_DUAL_OUTSIZE	0x05
 
-static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
-				   size_t offset, size_t count)
+static struct spi_slave *boot_slave;
+
+static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
+				size_t offset, size_t count)
 {
-	struct tegra_spi_media *spi = (struct tegra_spi_media *)media->context;
 	u8 spi_read_cmd[JEDEC_FAST_READ_DUAL_OUTSIZE];
 	unsigned int read_cmd_bytes;
 	int ret = count;
 	struct tegra_spi_channel *channel;
 
-	channel = to_tegra_spi(spi->slave->bus);
+	channel = to_tegra_spi(boot_slave->bus);
 
 	if (channel->dual_mode) {
 		/*
@@ -861,9 +856,9 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
 	spi_read_cmd[2] = (offset >> 8) & 0xff;
 	spi_read_cmd[3] = offset & 0xff;
 
-	spi_claim_bus(spi->slave);
+	spi_claim_bus(boot_slave);
 
-	if (spi_xfer(spi->slave, spi_read_cmd,
+	if (spi_xfer(boot_slave, spi_read_cmd,
 			read_cmd_bytes, NULL, 0) < 0) {
 		ret = -1;
 		printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n",
@@ -874,7 +869,7 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
 	if (channel->dual_mode) {
 		setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT);
 	}
-	if (spi_xfer(spi->slave, NULL, 0, dest, count)) {
+	if (spi_xfer(boot_slave, NULL, 0, dest, count)) {
 		ret = -1;
 		printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n",
 				__func__, count);
@@ -884,64 +879,35 @@ static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
 
 tegra_spi_cbfs_read_exit:
 	/* de-assert /CS */
-	spi_release_bus(spi->slave);
-	return (ret < 0) ? 0 : ret;
+	spi_release_bus(boot_slave);
+	return ret;
 }
 
-static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset,
-				 size_t count)
-{
-	struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
-	void *map;
-	DEBUG_SPI("tegra_spi_cbfs_map\n");
-	map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
-	return map;
-}
+static const struct region_device_ops tegra_spi_ops = {
+	.mmap = mmap_helper_rdev_mmap,
+	.munmap = mmap_helper_rdev_munmap,
+	.readat = tegra_spi_readat,
+};
 
-static void *tegra_spi_cbfs_unmap(struct cbfs_media *media,
-				   const void *address)
+static struct mmap_helper_region_device mdev =
+	MMAP_HELPER_REGION_INIT(&tegra_spi_ops, 0, CONFIG_ROM_SIZE);
+
+const struct region_device *boot_device_ro(void)
 {
-	struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
-	DEBUG_SPI("tegra_spi_cbfs_unmap\n");
-	return cbfs_simple_buffer_unmap(&spi->buffer, address);
+	return &mdev.rdev;
 }
 
-int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
-				     void *buffer_address,
-				     size_t buffer_size)
+void boot_device_init(void)
 {
-	// TODO Replace static variable to support multiple streams.
-	static struct tegra_spi_media context;
-	static struct tegra_spi_channel *channel;
-
-	channel = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1];
-	channel->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
-
-	DEBUG_SPI("Initializing CBFS media on SPI\n");
-
-	context.slave = &channel->slave;
-	context.buffer.allocated = context.buffer.last_allocate = 0;
-	context.buffer.buffer = buffer_address;
-	context.buffer.size = buffer_size;
-	media->context = (void*)&context;
-	media->open = tegra_spi_cbfs_open;
-	media->close = tegra_spi_cbfs_close;
-	media->read = tegra_spi_cbfs_read;
-	media->map = tegra_spi_cbfs_map;
-	media->unmap = tegra_spi_cbfs_unmap;
+	struct tegra_spi_channel *boot_chan;
+
+	boot_chan = &tegra_spi_channels[CONFIG_BOOT_MEDIA_SPI_BUS - 1];
+	boot_chan->slave.cs = CONFIG_BOOT_MEDIA_SPI_CHIP_SELECT;
 
 #if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1
-	channel->dual_mode = 1;
+	boot_chan->dual_mode = 1;
 #endif
+	boot_slave = &boot_chan->slave;
 
-	return 0;
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
-{
-	struct tegra_spi_channel *channel = to_tegra_spi(bus);
-	if (!channel)
-		return NULL;
-
-	return &channel->slave;
+	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
 }
diff --git a/src/soc/rockchip/rk3288/include/soc/spi.h b/src/soc/rockchip/rk3288/include/soc/spi.h
index bba38ef..a1be581 100644
--- a/src/soc/rockchip/rk3288/include/soc/spi.h
+++ b/src/soc/rockchip/rk3288/include/soc/spi.h
@@ -21,7 +21,6 @@
 #define __SOC_ROCKCHIP_RK3288_SPI_H__
 
 /* This driver serves as a CBFS media source. */
-#include <cbfs.h>
 #include <spi-generic.h>
 #include <stdint.h>
 
@@ -195,10 +194,6 @@ check_member(rockchip_spi, rxdr, 0x800);
 #define SPI_CLEAR_INT_RXOI	(1 << 2)
 #define SPI_CLEAR_INT_TXOI	(1 << 3)
 
-/* Serve as CBFS media source */
-int initialize_rockchip_spi_cbfs_media(struct cbfs_media *media,
-				     void *buffer_address,
-				     size_t buffer_size);
 void rockchip_spi_init(unsigned int bus, unsigned int speed_hz);
 
 #endif
diff --git a/src/soc/rockchip/rk3288/spi.c b/src/soc/rockchip/rk3288/spi.c
index fe4e377..49d0a18 100644
--- a/src/soc/rockchip/rk3288/spi.c
+++ b/src/soc/rockchip/rk3288/spi.c
@@ -19,15 +19,18 @@
 
 #include <arch/io.h>
 #include <assert.h>
+#include <boot_device.h>
 #include <console/console.h>
 #include <delay.h>
 #include <endian.h>
 #include <soc/addressmap.h>
 #include <soc/spi.h>
 #include <soc/clock.h>
+#include <region.h>
 #include <spi-generic.h>
 #include <spi_flash.h>
 #include <stdlib.h>
+#include <symbols.h>
 #include <timer.h>
 
 struct rockchip_spi_slave {
@@ -293,7 +296,57 @@ int spi_xfer(struct spi_slave *slave, const void *dout,
 	return ret < 0 ? ret : 0;
 }
 
-struct rockchip_spi_media {
-	struct spi_slave *slave;
-	struct cbfs_simple_buffer buffer;
+static struct spi_slave *boot_slave;
+
+static ssize_t rockchip_spi_readat(const struct region_device *rdev,
+					void *dest, size_t offset, size_t count)
+{
+	unsigned int cmd;
+	int ret;
+
+	spi_claim_bus(boot_slave);
+	cmd = swab32(offset) | SF_READ_DATA_CMD;
+	if (spi_xfer(boot_slave, &cmd, sizeof(cmd), NULL, 0)) {
+		printk(BIOS_DEBUG, "%s: could not send command\n", __func__);
+		ret = 0;
+		goto rockchip_spi_cbfs_read_done;
+	}
+
+	if (spi_xfer(boot_slave, NULL, 0, dest, count)) {
+		printk(BIOS_DEBUG, "%s: could not receive data\n", __func__);
+		ret = 0;
+		goto rockchip_spi_cbfs_read_done;
+	}
+
+rockchip_spi_cbfs_read_done:
+	spi_release_bus(boot_slave);
+	return ret < 0 ? 0 : count;
+}
+
+static void *rockchip_spi_mmap(const struct region_device *rdev, size_t offset,
+				size_t count)
+{
+	count = ALIGN_UP(count, 4);
+
+	return mmap_helper_rdev_mmap(rdev, offset, count);
+}
+
+static const struct region_device_ops rockchip_spi_ops = {
+	.mmap = rockchip_spi_mmap,
+	.munmap = mmap_helper_rdev_munmap,
+	.readat = rockchip_spi_readat,
 };
+
+static struct mmap_helper_region_device mdev =
+	MMAP_HELPER_REGION_INIT(&rockchip_spi_ops, 0, CONFIG_ROM_SIZE);
+
+const struct region_device *boot_device_ro(void)
+{
+	return &mdev.rdev;
+}
+
+void boot_device_init(void)
+{
+	boot_slave = &rockchip_spi_slaves[2].slave;
+	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
+}
diff --git a/src/soc/samsung/exynos5250/alternate_cbfs.c b/src/soc/samsung/exynos5250/alternate_cbfs.c
index 9f873bf..d884d1e 100644
--- a/src/soc/samsung/exynos5250/alternate_cbfs.c
+++ b/src/soc/samsung/exynos5250/alternate_cbfs.c
@@ -19,8 +19,10 @@
 
 
 #include <assert.h>
+#include <boot_device.h>
 #include <cbfs.h>  /* This driver serves as a CBFS media source. */
 #include <console/console.h>
+#include <region.h>
 #include <soc/alternate_cbfs.h>
 #include <soc/power.h>
 #include <soc/spi.h>
@@ -45,7 +47,7 @@
  * rest of the firmware's lifetime and all subsequent stages (which will not
  * have __PRE_RAM__ defined) can just directly reference it there.
  */
-static int usb_cbfs_open(struct cbfs_media *media)
+static int usb_cbfs_open(void)
 {
 #ifdef __PRE_RAM__
 	static int first_run = 1;
@@ -80,7 +82,7 @@ static int usb_cbfs_open(struct cbfs_media *media)
  * this seems like a safer approach. It also makes it easy to pass our image
  * down to payloads.
  */
-static int sdmmc_cbfs_open(struct cbfs_media *media)
+static int sdmmc_cbfs_open(void)
 {
 #ifdef __PRE_RAM__
 	/*
@@ -111,66 +113,43 @@ static int sdmmc_cbfs_open(struct cbfs_media *media)
 	return 0;
 }
 
-static int alternate_cbfs_close(struct cbfs_media *media) { return 0; }
+static struct mem_region_device alternate_rdev = MEM_REGION_DEV_INIT(NULL, 0);
 
-static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest,
-				  size_t offset, size_t count)
+const struct region_device *boot_device_ro(void)
 {
-	ASSERT(offset + count < _cbfs_cache_size);
-	memcpy(dest, _cbfs_cache + offset, count);
-	return count;
-}
-
-static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset,
-				   size_t count)
-{
-	ASSERT(offset + count < _cbfs_cache_size);
-	return _cbfs_cache + offset;
-}
-
-static void *alternate_cbfs_unmap(struct cbfs_media *media,
-				  const void *buffer) { return 0; }
-
-static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media)
-{
-	printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
-
-	media->open = sdmmc_cbfs_open;
-	media->close = alternate_cbfs_close;
-	media->read = alternate_cbfs_read;
-	media->map = alternate_cbfs_map;
-	media->unmap = alternate_cbfs_unmap;
+	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
+		return &alternate_rdev.rdev;
 
-	return 0;
+	switch (exynos_power->om_stat & OM_STAT_MASK) {
+	case OM_STAT_SDMMC:
+		return &alternate_rdev.rdev;
+	case OM_STAT_SPI:
+		return exynos_spi_boot_device();
+	default:
+		printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
+			exynos_power->om_stat);
+		return NULL;
+	}
 }
 
-static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media)
+void boot_device_init(void)
 {
-	printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
-
-	media->open = usb_cbfs_open;
-	media->close = alternate_cbfs_close;
-	media->read = alternate_cbfs_read;
-	media->map = alternate_cbfs_map;
-	media->unmap = alternate_cbfs_unmap;
+	mem_region_device_init(&alternate_rdev, _cbfs_cache, _cbfs_cache_size);
 
-	return 0;
-}
-
-int init_default_cbfs_media(struct cbfs_media *media)
-{
-	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
-		return initialize_exynos_usb_cbfs_media(media);
+	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) {
+		usb_cbfs_open();
+		return;
+	}
 
 	switch (exynos_power->om_stat & OM_STAT_MASK) {
 	case OM_STAT_SDMMC:
-		return initialize_exynos_sdmmc_cbfs_media(media);
+		sdmmc_cbfs_open();
+		break;
 	case OM_STAT_SPI:
-		return initialize_exynos_spi_cbfs_media(media,
-			_cbfs_cache, _cbfs_cache_size);
+		exynos_init_spi_boot_device();
+		break;
 	default:
 		printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
 			exynos_power->om_stat);
-		return 1;
 	}
 }
diff --git a/src/soc/samsung/exynos5250/include/soc/spi.h b/src/soc/samsung/exynos5250/include/soc/spi.h
index 4301d42..e4d62d2 100644
--- a/src/soc/samsung/exynos5250/include/soc/spi.h
+++ b/src/soc/samsung/exynos5250/include/soc/spi.h
@@ -92,8 +92,6 @@ 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 source */
-int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
-				     void *buffer_address,
-				     size_t buffer_size);
+void exynos_init_spi_boot_device(void);
+const struct region_device *exynos_spi_boot_device(void);
 #endif
diff --git a/src/soc/samsung/exynos5250/spi.c b/src/soc/samsung/exynos5250/spi.c
index 33a8c74..458a242 100644
--- a/src/soc/samsung/exynos5250/spi.c
+++ b/src/soc/samsung/exynos5250/spi.c
@@ -25,6 +25,7 @@
 #include <soc/gpio.h>
 #include <soc/spi.h>
 #include <stdlib.h>
+#include <symbols.h>
 
 #if defined(CONFIG_DEBUG_SPI) && CONFIG_DEBUG_SPI
 # define DEBUG_SPI(x,...)	printk(BIOS_DEBUG, "EXYNOS_SPI: " x)
@@ -144,70 +145,47 @@ int exynos_spi_close(struct exynos_spi *regs)
 	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;
-	DEBUG_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;
-	DEBUG_SPI("exynos_spi_cbfs_close\n");
-	return exynos_spi_close(spi->regs);
-}
+static struct exynos_spi *boot_slave_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;
+static ssize_t exynos_spi_readat(const struct region_device *rdev, void *dest,
+					size_t offset, size_t count)
+{
 	int bytes;
 	DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count);
-	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);
+	exynos_spi_open(boot_slave_regs);
+	bytes = exynos_spi_read(boot_slave_regs, dest, count, offset);
+	exynos_spi_close(boot_slave_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;
+static void *exynos_spi_map(const struct region_device *rdev,
+					size_t offset, size_t count)
+{
 	DEBUG_SPI("exynos_spi_cbfs_map\n");
-	// See exynos_spi_rx_tx for I/O alignment limitation.
+	// exynos: spi_rx_tx may work in 4 byte-width-transmission mode and
+	// requires buffer memory address to be aligned.
 	if (count % 4)
 		count += 4 - (count % 4);
-	return cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
+	return mmap_helper_rdev_mmap(rdev, 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;
-	DEBUG_SPI("exynos_spi_cbfs_unmap\n");
-	return cbfs_simple_buffer_unmap(&spi->buffer, address);
-}
+static const struct region_device_ops exynos_spi_ops = {
+	.mmap = exynos_spi_map,
+	.munmap = mmap_helper_rdev_munmap,
+	.readat = exynos_spi_readat,
+};
 
-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;
-	DEBUG_SPI("initialize_exynos_spi_cbfs_media\n");
-
-	context.regs = (void*)EXYNOS5_SPI1_BASE;
-	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;
+static struct mmap_helper_region_device mdev =
+	MMAP_HELPER_REGION_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE);
 
-	return 0;
+void exynos_init_spi_boot_device(void)
+{
+	boot_slave_regs = (void *)EXYNOS5_SPI1_BASE;
+
+	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
+}
+
+const struct region_device *exynos_spi_boot_device(void)
+{
+	return &mdev.rdev;
 }
diff --git a/src/soc/samsung/exynos5420/alternate_cbfs.c b/src/soc/samsung/exynos5420/alternate_cbfs.c
index 45489f1..4cfbfbf 100644
--- a/src/soc/samsung/exynos5420/alternate_cbfs.c
+++ b/src/soc/samsung/exynos5420/alternate_cbfs.c
@@ -20,8 +20,10 @@
 
 #include <arch/cache.h>
 #include <assert.h>
+#include <boot_device.h>
 #include <cbfs.h>  /* This driver serves as a CBFS media source. */
 #include <console/console.h>
+#include <region.h>
 #include <soc/alternate_cbfs.h>
 #include <soc/power.h>
 #include <soc/spi.h>
@@ -46,7 +48,7 @@
  * rest of the firmware's lifetime and all subsequent stages (which will not
  * have __PRE_RAM__ defined) can just directly reference it there.
  */
-static int usb_cbfs_open(struct cbfs_media *media)
+static int usb_cbfs_open(void)
 {
 #ifdef __PRE_RAM__
 	static int first_run = 1;
@@ -84,7 +86,7 @@ static int usb_cbfs_open(struct cbfs_media *media)
  * this seems like a safer approach. It also makes it easy to pass our image
  * down to payloads.
  */
-static int sdmmc_cbfs_open(struct cbfs_media *media)
+static int sdmmc_cbfs_open(void)
 {
 #ifdef __PRE_RAM__
 	/*
@@ -118,66 +120,43 @@ static int sdmmc_cbfs_open(struct cbfs_media *media)
 	return 0;
 }
 
-static int alternate_cbfs_close(struct cbfs_media *media) { return 0; }
+static struct mem_region_device alternate_rdev = MEM_REGION_DEV_INIT(NULL, 0);
 
-static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest,
-				  size_t offset, size_t count)
+const struct region_device *boot_device_ro(void)
 {
-	ASSERT(offset + count < _cbfs_cache_size);
-	memcpy(dest, _cbfs_cache + offset, count);
-	return count;
-}
-
-static void *alternate_cbfs_map(struct cbfs_media *media, size_t offset,
-				   size_t count)
-{
-	ASSERT(offset + count < _cbfs_cache_size);
-	return _cbfs_cache + offset;
-}
-
-static void *alternate_cbfs_unmap(struct cbfs_media *media,
-				  const void *buffer) { return 0; }
-
-static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media)
-{
-	printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
-
-	media->open = sdmmc_cbfs_open;
-	media->close = alternate_cbfs_close;
-	media->read = alternate_cbfs_read;
-	media->map = alternate_cbfs_map;
-	media->unmap = alternate_cbfs_unmap;
+	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
+		return &alternate_rdev.rdev;
 
-	return 0;
+	switch (exynos_power->om_stat & OM_STAT_MASK) {
+	case OM_STAT_SDMMC:
+		return &alternate_rdev.rdev;
+	case OM_STAT_SPI:
+		return exynos_spi_boot_device();
+	default:
+		printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
+			exynos_power->om_stat);
+		return NULL;
+	}
 }
 
-static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media)
+void boot_device_init(void)
 {
-	printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
-
-	media->open = usb_cbfs_open;
-	media->close = alternate_cbfs_close;
-	media->read = alternate_cbfs_read;
-	media->map = alternate_cbfs_map;
-	media->unmap = alternate_cbfs_unmap;
+	mem_region_device_init(&alternate_rdev, _cbfs_cache, _cbfs_cache_size);
 
-	return 0;
-}
-
-int init_default_cbfs_media(struct cbfs_media *media)
-{
-	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
-		return initialize_exynos_usb_cbfs_media(media);
+	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) {
+		usb_cbfs_open();
+		return;
+	}
 
 	switch (exynos_power->om_stat & OM_STAT_MASK) {
 	case OM_STAT_SDMMC:
-		return initialize_exynos_sdmmc_cbfs_media(media);
+		sdmmc_cbfs_open();
+		break;
 	case OM_STAT_SPI:
-		return initialize_exynos_spi_cbfs_media(media,
-			_cbfs_cache, _cbfs_cache_size);
+		exynos_init_spi_boot_device();
+		break;
 	default:
 		printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
 			exynos_power->om_stat);
-		return 1;
 	}
 }
diff --git a/src/soc/samsung/exynos5420/include/soc/spi.h b/src/soc/samsung/exynos5420/include/soc/spi.h
index 78cca6f..3b03561 100644
--- a/src/soc/samsung/exynos5420/include/soc/spi.h
+++ b/src/soc/samsung/exynos5420/include/soc/spi.h
@@ -91,8 +91,6 @@ check_member(exynos_spi, fb_clk, 0x2c);
 #define SPI_RX_BYTE_SWAP	(1 << 6)
 #define SPI_RX_HWORD_SWAP	(1 << 7)
 
-/* Serve as CBFS media source */
-int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
-				     void *buffer_address,
-				     size_t buffer_size);
+void exynos_init_spi_boot_device(void);
+const struct region_device *exynos_spi_boot_device(void);
 #endif
diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c
index 6ceb92e..21122e2 100644
--- a/src/soc/samsung/exynos5420/spi.c
+++ b/src/soc/samsung/exynos5420/spi.c
@@ -26,6 +26,7 @@
 #include <spi_flash.h>
 #include <stdlib.h>
 #include <string.h>
+#include <symbols.h>
 
 #define EXYNOS_SPI_MAX_TRANSFER_BYTES (65535)
 
@@ -242,76 +243,43 @@ static int exynos_spi_read(struct spi_slave *slave, void *dest, uint32_t len,
 	return len;
 }
 
-// SPI as CBFS media.
-struct exynos_spi_media {
-	struct spi_slave *slave;
-	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;
-	DEBUG_SPI("exynos_spi_cbfs_open\n");
-	return spi_claim_bus(spi->slave);
-}
-
-static int exynos_spi_cbfs_close(struct cbfs_media *media)
-{
-	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
-	DEBUG_SPI("exynos_spi_cbfs_close\n");
-	spi_release_bus(spi->slave);
-	return 0;
-}
+static struct exynos_spi_slave *boot_slave;
 
-static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest,
-				   size_t offset, size_t count)
+static ssize_t exynos_spi_readat(const struct region_device *rdev, void *dest,
+					size_t offset, size_t count)
 {
-	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
-	int bytes;
 	DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count);
-	bytes = exynos_spi_read(spi->slave, dest, count, offset);
-	return bytes;
+	return exynos_spi_read(&boot_slave->slave, dest, count, offset);
 }
 
-static void *exynos_spi_cbfs_map(struct cbfs_media *media, size_t offset,
-				 size_t count)
+static void *exynos_spi_map(const struct region_device *rdev,
+					size_t offset, size_t count)
 {
-	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
 	DEBUG_SPI("exynos_spi_cbfs_map\n");
 	// exynos: spi_rx_tx may work in 4 byte-width-transmission mode and
 	// requires buffer memory address to be aligned.
 	if (count % 4)
 		count += 4 - (count % 4);
-	return cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
+	return mmap_helper_rdev_mmap(rdev, offset, count);
 }
 
-static void *exynos_spi_cbfs_unmap(struct cbfs_media *media,
-				   const void *address)
+static const struct region_device_ops exynos_spi_ops = {
+	.mmap = exynos_spi_map,
+	.munmap = mmap_helper_rdev_munmap,
+	.readat = exynos_spi_readat,
+};
+
+static struct mmap_helper_region_device mdev =
+	MMAP_HELPER_REGION_INIT(&exynos_spi_ops, 0, CONFIG_ROM_SIZE);
+
+void exynos_init_spi_boot_device(void)
 {
-	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
-	DEBUG_SPI("exynos_spi_cbfs_unmap\n");
-	return cbfs_simple_buffer_unmap(&spi->buffer, address);
+	boot_slave = &exynos_spi_slaves[1];
+
+	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
 }
 
-int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
-				     void *buffer_address,
-				     size_t buffer_size)
+const struct region_device *exynos_spi_boot_device(void)
 {
-	// TODO Replace static variable to support multiple streams.
-	static struct exynos_spi_media context;
-	static struct exynos_spi_slave *eslave = &exynos_spi_slaves[1];
-	DEBUG_SPI("initialize_exynos_spi_cbfs_media\n");
-
-	context.slave = &eslave->slave;
-	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;
+	return &mdev.rdev;
 }



More information about the coreboot-gerrit mailing list