[coreboot-gerrit] New patch to review for coreboot: 925ab0c Revert fmap and boot_device commits

Vladimir Serbinenko (phcoder@gmail.com) gerrit at coreboot.org
Thu May 28 14:48:50 CEST 2015


Vladimir Serbinenko (phcoder at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/10350

-gerrit

commit 925ab0c60b0c7ae78f0ac384f475a60b3928e304
Author: Vladimir Serbinenko <phcoder at gmail.com>
Date:   Thu May 28 14:24:09 2015 +0200

    Revert fmap and boot_device commits
    
    Those commits miss tseg_relocate somewhere and so SMI hangs on shutdown.
    Revert the commit until we figure out where is the mistake or switch
    sandy/ivy/nehalem to SMM modules (preffered)
    
    This reverts commit 0424c95a6dafdb65070538d6c5aa394b75eb9850.
    This reverts commit c6588c5af94e568bddd8111c3fca736f464042cf.
    
    Change-Id: I1e330c2730092e9b81d98ee861605bc32a6a7ab3
    Signed-off-by: Vladimir Serbinenko <phcoder at gmail.com>
---
 src/Kconfig                                        |   9 --
 src/arch/riscv/rom_media.c                         |  66 ++++++------
 src/arch/x86/lib/Makefile.inc                      |   3 -
 src/arch/x86/lib/mmap_boot.c                       |  31 ------
 src/arch/x86/lib/rom_media.c                       |  57 +++++-----
 src/cpu/allwinner/a10/bootblock_media.c            |   8 +-
 src/cpu/ti/am335x/bootblock_media.c                |  47 ++------
 src/cpu/ti/am335x/nand.c                           |  10 +-
 src/drivers/elog/elog.c                            |  49 ++++++---
 src/include/boot_device.h                          |  41 -------
 src/include/fmap.h                                 |  35 ------
 src/include/fmap_serialized.h                      |  73 -------------
 src/lib/Makefile.inc                               |  11 --
 src/lib/boot_device.c                              |  38 -------
 src/lib/cbfs_spi.c                                 |  97 +++++------------
 src/lib/fmap.c                                     | 119 ---------------------
 src/mainboard/emulation/qemu-armv7/media.c         |  45 ++------
 src/mainboard/google/butterfly/mainboard.c         |  41 +++----
 src/mainboard/google/panther/lan.c                 |  25 ++---
 src/northbridge/intel/haswell/mrccache.c           |  28 +++--
 src/northbridge/intel/sandybridge/mrccache.c       |  29 +++--
 src/soc/intel/common/mrc_cache.c                   |  27 ++---
 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                      | 116 +++++++-------------
 src/soc/nvidia/tegra132/Makefile.inc               |   4 +
 src/soc/nvidia/tegra132/cbfs.c                     |  28 +++++
 src/soc/nvidia/tegra132/include/soc/spi.h          |   5 +
 src/soc/nvidia/tegra132/spi.c                      | 116 +++++++-------------
 src/soc/samsung/exynos5250/alternate_cbfs.c        | 118 +++++++-------------
 src/soc/samsung/exynos5250/include/soc/spi.h       |   9 +-
 src/soc/samsung/exynos5250/spi.c                   |  85 +++++++++------
 src/soc/samsung/exynos5420/alternate_cbfs.c        | 118 +++++++-------------
 src/soc/samsung/exynos5420/include/soc/spi.h       |   9 +-
 src/soc/samsung/exynos5420/spi.c                   |  78 ++++++++++----
 src/vendorcode/google/chromeos/Kconfig             |   9 ++
 src/vendorcode/google/chromeos/Makefile.inc        |   4 +
 src/vendorcode/google/chromeos/cros_vpd.c          |  30 +++---
 src/vendorcode/google/chromeos/fmap.h              |  79 ++++++++++++++
 .../google/chromeos/vboot2/vboot_handoff.c         |   2 +-
 41 files changed, 665 insertions(+), 1072 deletions(-)

diff --git a/src/Kconfig b/src/Kconfig
index 26e1194..5cfb06f 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -244,15 +244,6 @@ config CACHE_RELOCATED_RAMSTAGE_OUTSIDE_CBMEM
 	 The relocated ramstage is saved in an area specified by the
 	 by the board and/or chipset.
 
-config FLASHMAP_OFFSET
-	hex "Flash Map Offset"
-	default 0x00670000 if NORTHBRIDGE_INTEL_SANDYBRIDGE
-	default 0x00610000 if NORTHBRIDGE_INTEL_IVYBRIDGE
-	default CBFS_SIZE if !ARCH_X86
-	default 0
-	help
-	  Offset of flash map in firmware image
-
 choice
 	prompt "Bootblock behaviour"
 	default BOOTBLOCK_SIMPLE
diff --git a/src/arch/riscv/rom_media.c b/src/arch/riscv/rom_media.c
index f18030c..8d3376c 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 2015 Google Inc.
+ * 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
@@ -17,59 +17,40 @@
  * 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 <string.h>
 
-/* This assumes that the CBFS resides at 0x0, which is true for the default
- * configuration. */
-static const struct mem_region_device gboot_dev =
-	MEM_REGION_DEV_INIT(NULL, CONFIG_ROM_SIZE);
+#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
 
-const struct region_device *boot_device_ro(void)
-{
-	return &gboot_dev.rdev;
-}
+// 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) {
-	const struct region_device *boot_dev;
 	void *ptr;
-
 	printk(BIOS_INFO, "%s: media %p, offset %lx, size %ld.\n", __func__, media, offset, count);
-	boot_dev = media->context;
-
-	ptr = rdev_mmap(boot_dev, offset, count);
-
-	if (ptr == NULL)
-		return (void *)-1;
 
+	ptr = (void*)offset;
 	return ptr;
 }
 
 static void *rom_media_unmap(struct cbfs_media *media, const void *address) {
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	rdev_munmap(boot_dev, (void *)address);
-
 	return NULL;
 }
 
 static size_t rom_media_read(struct cbfs_media *media, void *dest, size_t offset,
 			   size_t count) {
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	if (rdev_readat(boot_dev, dest, offset, count) < 0)
-		return 0;
-
+	void *ptr = rom_media_map(media, offset, count);
+	memcpy(dest, ptr, count);
+	rom_media_unmap(media, ptr);
 	return count;
 }
 
@@ -78,8 +59,25 @@ static int rom_media_close(struct cbfs_media *media) {
 }
 
 static int init_rom_media_cbfs(struct cbfs_media *media) {
-	boot_device_init();
-	media->context = (void *)boot_device_ro();
+	/* 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;
diff --git a/src/arch/x86/lib/Makefile.inc b/src/arch/x86/lib/Makefile.inc
index e308be9..c7e8b62 100644
--- a/src/arch/x86/lib/Makefile.inc
+++ b/src/arch/x86/lib/Makefile.inc
@@ -6,7 +6,6 @@ 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
 
@@ -23,7 +22,6 @@ 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
@@ -34,7 +32,6 @@ 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
deleted file mode 100644
index eb7b23e..0000000
--- a/src/arch/x86/lib/mmap_boot.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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>
-
-/* 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;
-}
diff --git a/src/arch/x86/lib/rom_media.c b/src/arch/x86/lib/rom_media.c
index d4663c7..659e5e4 100644
--- a/src/arch/x86/lib/rom_media.c
+++ b/src/arch/x86/lib/rom_media.c
@@ -17,8 +17,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc.
  */
-
-#include <boot_device.h>
 #include <cbfs.h>
 #include <string.h>
 
@@ -38,19 +36,14 @@ static int x86_rom_open(struct cbfs_media *media) {
 
 static void *x86_rom_map(struct cbfs_media *media, size_t offset, size_t count) {
 	void *ptr;
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
+	// Some address (ex, pointer to master header) may be given in memory
+	// mapped location. To workaround that, we handle >0xf0000000 as real
+	// memory pointer.
 
-	/* Extremely large offsets are considered relative to end of region. */
 	if ((uint32_t)offset > (uint32_t)0xf0000000)
-		offset += region_device_sz(boot_dev);
-
-	ptr = rdev_mmap(boot_dev, offset, count);
-
-	if (ptr == NULL)
-		return (void *)-1;
-
+		ptr = (void*)offset;
+	else
+		ptr = (void*)(0 - (uint32_t)media->context + offset);
 	return ptr;
 }
 
@@ -60,13 +53,7 @@ static void *x86_rom_unmap(struct cbfs_media *media, const void *address) {
 
 static size_t x86_rom_read(struct cbfs_media *media, void *dest, size_t offset,
 			   size_t count) {
-	void *ptr;
-
-	ptr = x86_rom_map(media, offset, count);
-
-	if (ptr == (void *)-1)
-		return 0;
-
+	void *ptr = x86_rom_map(media, offset, count);
 	memcpy(dest, ptr, count);
 	x86_rom_unmap(media, ptr);
 	return count;
@@ -76,14 +63,30 @@ static int x86_rom_close(struct cbfs_media *media) {
 	return 0;
 }
 
-static int init_x86rom_cbfs_media(struct cbfs_media *media) {
-	boot_device_init();
-
-	media->context = (void *)boot_device_ro();
-
-	if (media->context == NULL)
+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;
diff --git a/src/cpu/allwinner/a10/bootblock_media.c b/src/cpu/allwinner/a10/bootblock_media.c
index a585bca..a5863b6 100644
--- a/src/cpu/allwinner/a10/bootblock_media.c
+++ b/src/cpu/allwinner/a10/bootblock_media.c
@@ -4,17 +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 <boot_device.h>
 #include <cbfs.h>
 #include <console/console.h>
 
-const struct region_device *boot_device_ro(void)
-{
-	return NULL;
-}
-
 int init_default_cbfs_media(struct cbfs_media *media)
 {
 	printk(BIOS_ERR, "Oh my! I don't know how to access CBFS yet.");
-	return -1;
+	return 0;
 }
diff --git a/src/cpu/ti/am335x/bootblock_media.c b/src/cpu/ti/am335x/bootblock_media.c
index 79724ee..9824fc3 100644
--- a/src/cpu/ti/am335x/bootblock_media.c
+++ b/src/cpu/ti/am335x/bootblock_media.c
@@ -17,21 +17,11 @@
  * Foundation, Inc.
  */
 
-#include <boot_device.h>
 #include <cbfs.h>
 #include <console/console.h>
 #include <string.h>
 #include <symbols.h>
 
-/* FIXME: No idea how big the internal SRAM actually is. */
-static const struct mem_region_device gboot_dev =
-	MEM_REGION_DEV_INIT(_dram, CONFIG_ROM_SIZE);
-
-const struct region_device *boot_device_ro(void)
-{
-	return &gboot_dev.rdev;
-}
-
 static int dummy_open(struct cbfs_media *media)
 {
 	return 0;
@@ -45,48 +35,33 @@ static int dummy_close(struct cbfs_media *media)
 static void * on_chip_memory_map(struct cbfs_media *media, size_t offset,
 				 size_t count)
 {
-	const struct region_device *boot_dev;
-	void *ptr;
-
-	boot_dev = media->context;
-
-	ptr = rdev_mmap(boot_dev, offset, count);
-
-	if (ptr == NULL)
-		return (void *)-1;
-
-	return ptr;
+	return _dram + offset;
 }
 
 static void * dummy_unmap(struct cbfs_media *media, const void *address)
 {
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	rdev_munmap(boot_dev, (void *)address);
-
 	return NULL;
 }
 
 static size_t on_chip_memory_read(struct cbfs_media *media, void *dest,
 				  size_t offset, size_t count)
 {
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	if (rdev_readat(boot_dev, dest, offset, count) < 0)
-		return 0;
-
+	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)
 {
-	boot_device_init();
+	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->context = (void *)boot_device_ro();
 	media->open = dummy_open;
 	media->close = dummy_close;
 	media->map = on_chip_memory_map;
diff --git a/src/cpu/ti/am335x/nand.c b/src/cpu/ti/am335x/nand.c
index dd05fb6..a8c945b 100644
--- a/src/cpu/ti/am335x/nand.c
+++ b/src/cpu/ti/am335x/nand.c
@@ -17,16 +17,10 @@
  * Foundation, Inc.
  */
 
-#include <boot_device.h>
 #include <cbfs.h>
 
-const struct region_device *boot_device_ro(void)
-{
-	return NULL;
-}
-
 int init_default_cbfs_media(struct cbfs_media *media)
 {
-	/* FIXME: add support for reading coreboot from NAND */
-	return -1;
+        /* FIXME: add support for reading coreboot from NAND */
+	return 0;
 }
diff --git a/src/drivers/elog/elog.c b/src/drivers/elog/elog.c
index 8dce86b..da1f6fa 100644
--- a/src/drivers/elog/elog.c
+++ b/src/drivers/elog/elog.c
@@ -26,7 +26,6 @@
 #include <pc80/mc146818rtc.h>
 #endif
 #include <bcd.h>
-#include <fmap.h>
 #include <rtc.h>
 #include <smbios.h>
 #include <spi-generic.h>
@@ -36,6 +35,7 @@
 #include <elog.h>
 #include "elog_internal.h"
 
+#include <vendorcode/google/chromeos/fmap.h>
 
 #if !IS_ENABLED(CONFIG_CHROMEOS) && CONFIG_ELOG_FLASH_BASE == 0
 #error "CONFIG_ELOG_FLASH_BASE is invalid"
@@ -86,6 +86,26 @@ static inline u32 get_rom_size(void)
 }
 
 /*
+ * Convert a memory mapped flash address into a flash offset
+ */
+static inline u32 elog_flash_address_to_offset(u8 *address)
+{
+#if CONFIG_ARCH_X86
+	/* For x86, assume address is memory-mapped near 4GB */
+	u32 rom_size;
+
+	if (!elog_spi)
+		return 0;
+
+	rom_size = get_rom_size();
+
+	return (u32)address - ((u32)~0UL - rom_size + 1);
+#else
+	return (u32)(uintptr_t)address;
+#endif
+}
+
+/*
  * Pointer to an event log header in the event data area
  */
 static inline struct event_header*
@@ -497,22 +517,21 @@ static void elog_find_flash(void)
 {
 	elog_debug("elog_find_flash()\n");
 
-	if (IS_ENABLED(CONFIG_CHROMEOS)) {
-		/* Find the ELOG base and size in FMAP */
-		struct region r;
-
-		if (fmap_locate_area("RW_ELOG", &r) < 0) {
-			printk(BIOS_WARNING,
-				"ELOG: Unable to find RW_ELOG in FMAP\n");
-			flash_base = total_size = 0;
-		} else {
-			flash_base = region_offset(&r);
-			total_size = MIN(region_sz(&r), CONFIG_ELOG_AREA_SIZE);
-		}
+#if CONFIG_CHROMEOS
+	/* Find the ELOG base and size in FMAP */
+	u8 *flash_base_ptr;
+	int fmap_size = find_fmap_entry("RW_ELOG", (void **)&flash_base_ptr);
+	if (fmap_size < 0) {
+		printk(BIOS_WARNING, "ELOG: Unable to find RW_ELOG in FMAP\n");
+		flash_base = total_size = 0;
 	} else {
-		flash_base = CONFIG_ELOG_FLASH_BASE;
-		total_size = CONFIG_ELOG_AREA_SIZE;
+		flash_base = elog_flash_address_to_offset(flash_base_ptr);
+		total_size = MIN(fmap_size, CONFIG_ELOG_AREA_SIZE);
 	}
+#else
+	flash_base = CONFIG_ELOG_FLASH_BASE;
+	total_size = CONFIG_ELOG_AREA_SIZE;
+#endif
 	log_size = total_size - sizeof(struct elog_header);
 	full_threshold = log_size - ELOG_MIN_AVAILABLE_ENTRIES * MAX_EVENT_SIZE;
 	shrink_size = MIN(total_size * ELOG_SHRINK_PERCENTAGE / 100,
diff --git a/src/include/boot_device.h b/src/include/boot_device.h
deleted file mode 100644
index 0848ea5..0000000
--- a/src/include/boot_device.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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);
-
-/*
- * Create a sub-region of the read-only boot device.
- * Returns 0 on success, < 0 on error.
- */
-int boot_device_ro_subregion(const struct region *sub,
-				struct region_device *subrd);
-
-/*
- * Initialize the boot device. This may be called multiple times within
- * a stage so boot device implementations should account for this behavior.
- **/
-void boot_device_init(void);
-
-#endif /* _BOOT_DEVICE_H_ */
diff --git a/src/include/fmap.h b/src/include/fmap.h
deleted file mode 100644
index e575bbf..0000000
--- a/src/include/fmap.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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 _FMAP_H_
-#define _FMAP_H_
-
-#include <region.h>
-
-/* Locate the named area in the fmap and fill in a region device representing
- * that area. The region is a sub-region of the readonly boot media. Return
- * 0 on success, < 0 on error. */
-int fmap_locate_area_as_rdev(const char *name, struct region_device *area);
-
-/* Locate the named area in the fmap and fill in a region with the
- * offset and size of that area within the boot media. Return 0 on success,
- * < 0 on error. */
-int fmap_locate_area(const char *name, struct region *r);
-
-#endif
diff --git a/src/include/fmap_serialized.h b/src/include/fmap_serialized.h
deleted file mode 100644
index 3585f0b..0000000
--- a/src/include/fmap_serialized.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2010, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *    * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *    * 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.
- *    * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
- * OWNER 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.
- *
- * Alternatively, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") version 2 as published by the Free
- * Software Foundation.
- */
-
-#ifndef FLASHMAP_SERIALIZED_H__
-#define FLASHMAP_SERIALIZED_H__
-
-#include <stdint.h>
-
-#define FMAP_SIGNATURE		"__FMAP__"
-#define FMAP_VER_MAJOR		1	/* this header's FMAP minor version */
-#define FMAP_VER_MINOR		1	/* this header's FMAP minor version */
-#define FMAP_STRLEN		32	/* maximum length for strings, */
-					/* including null-terminator */
-
-enum fmap_flags {
-	FMAP_AREA_STATIC	= 1 << 0,
-	FMAP_AREA_COMPRESSED	= 1 << 1,
-	FMAP_AREA_RO		= 1 << 2,
-};
-
-/* Mapping of volatile and static regions in firmware binary */
-struct fmap_area {
-	uint32_t offset;                /* offset relative to base */
-	uint32_t size;                  /* size in bytes */
-	uint8_t  name[FMAP_STRLEN];     /* descriptive name */
-	uint16_t flags;                 /* flags for this area */
-}  __attribute__((packed));
-
-struct fmap {
-	uint8_t  signature[8];		/* "__FMAP__" (0x5F5F464D41505F5F) */
-	uint8_t  ver_major;		/* major version */
-	uint8_t  ver_minor;		/* minor version */
-	uint64_t base;			/* address of the firmware binary */
-	uint32_t size;			/* size of firmware binary in bytes */
-	uint8_t  name[FMAP_STRLEN];	/* name of this firmware binary */
-	uint16_t nareas;		/* number of areas described by
-					   fmap_areas[] below */
-	struct fmap_area areas[];
-} __attribute__((packed));
-
-#endif	/* FLASHMAP_SERIALIZED_H__ */
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index 5ec9de7..11562bd 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -31,19 +31,15 @@ bootblock-y += memchr.c
 bootblock-y += memcmp.c
 bootblock-y += mem_pool.c
 bootblock-y += region.c
-bootblock-y += boot_device.c
-bootblock-y += fmap.c
 
 verstage-y += prog_ops.c
 verstage-y += delay.c
 verstage-y += cbfs.c
 verstage-y += cbfs_core.c
 verstage-y += halt.c
-verstage-y += fmap.c
 verstage-y += memcmp.c
 verstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
 verstage-y += region.c
-verstage-y += boot_device.c
 verstage-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c
 verstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
 
@@ -64,7 +60,6 @@ $(foreach arch,$(ARCH_SUPPORTED),\
 	    $(eval rmodules_$(arch)-y += memcmp.c) \
 	    $(eval rmodules_$(arch)-y += rmodule.ld))
 
-romstage-y += fmap.c
 romstage-$(CONFIG_I2C_TPM) += delay.c
 romstage-y += cbfs.c cbfs_core.c
 romstage-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
@@ -92,7 +87,6 @@ ramstage-y += hardwaremain.c
 ramstage-y += selfboot.c
 ramstage-y += coreboot_table.c
 ramstage-y += bootmem.c
-ramstage-y += fmap.c
 ramstage-y += memchr.c
 ramstage-y += memcmp.c
 ramstage-y += malloc.c
@@ -147,12 +141,7 @@ ramstage-y += mem_pool.c
 
 romstage-y += region.c
 ramstage-y += region.c
-romstage-y += boot_device.c
-ramstage-y += boot_device.c
 
-smm-y += region.c
-smm-y += boot_device.c
-smm-y += fmap.c
 smm-y += cbfs.c cbfs_core.c memcmp.c
 smm-$(CONFIG_COMPILER_GCC) += gcc.c
 
diff --git a/src/lib/boot_device.c b/src/lib/boot_device.c
deleted file mode 100644
index e0353fc..0000000
--- a/src/lib/boot_device.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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>
-
-void __attribute__((weak)) boot_device_init(void)
-{
-	/* Provide weak do-nothing init. */
-}
-
-int boot_device_ro_subregion(const struct region *sub,
-				struct region_device *subrd)
-{
-	const struct region_device *boot_dev;
-
-	boot_dev = boot_device_ro();
-
-	if (boot_dev == NULL)
-		return -1;
-
-	return rdev_chain(subrd, boot_dev, region_offset(sub), region_sz(sub));
-}
diff --git a/src/lib/cbfs_spi.c b/src/lib/cbfs_spi.c
index 6758220..6c8d78d 100644
--- a/src/lib/cbfs_spi.c
+++ b/src/lib/cbfs_spi.c
@@ -23,52 +23,17 @@
  * SPI.
  */
 
-#include <boot_device.h>
 #include <cbfs.h>
-#include <region.h>
 #include <spi_flash.h>
 #include <symbols.h>
 
-static struct spi_flash *spi_flash_info;
-
-static ssize_t spi_readat(const struct region_device *rd, void *b,
-				size_t offset, size_t size)
-{
-	if (spi_flash_info->read(spi_flash_info, offset, size, b))
-		return -1;
-	return size;
-}
-
-static const struct region_device_ops spi_ops = {
-	.mmap = mmap_helper_rdev_mmap,
-	.munmap = mmap_helper_rdev_munmap,
-	.readat = spi_readat,
+/* SPI flash as CBFS media. */
+struct cbfs_spi_context {
+	struct spi_flash *spi_flash_info;
+	struct cbfs_simple_buffer buffer;
 };
 
-static struct mmap_helper_region_device mdev =
-	MMAP_HELPER_REGION_INIT(&spi_ops, 0, CONFIG_ROM_SIZE);
-
-void boot_device_init(void)
-{
-	int bus = CONFIG_BOOT_MEDIA_SPI_BUS;
-	int cs = 0;
-
-	if (spi_flash_info != NULL)
-		return;
-
-	spi_flash_info = spi_flash_probe(bus, cs);
-
-	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
-}
-
-/* Return the CBFS boot device. */
-const struct region_device *boot_device_ro(void)
-{
-	if (spi_flash_info == NULL)
-		return NULL;
-
-	return &mdev.rdev;
-}
+static struct cbfs_spi_context spi_context;
 
 static int cbfs_media_open(struct cbfs_media *media)
 {
@@ -84,58 +49,52 @@ static size_t cbfs_media_read(struct cbfs_media *media,
 			      void *dest, size_t offset,
 			      size_t count)
 {
-	const struct region_device *boot_dev;
+	struct cbfs_spi_context *context = media->context;
 
-	boot_dev = media->context;
-
-	if (rdev_readat(boot_dev, dest, offset, count) < 0)
-		return 0;
-
-	return count;
+	return context->spi_flash_info->read
+		(context->spi_flash_info, offset, count, dest) ? 0 : count;
 }
 
 static void *cbfs_media_map(struct cbfs_media *media,
 			    size_t offset, size_t count)
 {
-	const struct region_device *boot_dev;
-	void *ptr;
-
-	boot_dev = media->context;
-
-	ptr = rdev_mmap(boot_dev, offset, count);
+	struct cbfs_spi_context *context = media->context;
 
-	if (ptr == NULL)
-		return (void *)-1;
-
-	return ptr;
+	return cbfs_simple_buffer_map(&context->buffer, media, offset, count);
 }
 
 static void *cbfs_media_unmap(struct cbfs_media *media,
 			       const void *address)
 {
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	rdev_munmap(boot_dev, (void *)address);
+	struct cbfs_spi_context *context = media->context;
 
-	return NULL;
+	return cbfs_simple_buffer_unmap(&context->buffer, address);
 }
 
-int init_default_cbfs_media(struct cbfs_media *media)
+static int init_cbfs_media_context(void)
 {
-	boot_device_init();
+	if (!spi_context.spi_flash_info) {
+
+		spi_context.spi_flash_info = spi_flash_probe
+			(CONFIG_BOOT_MEDIA_SPI_BUS, 0);
 
-	media->context = (void *)boot_device_ro();
+		if (!spi_context.spi_flash_info)
+			return -1;
 
-	if (media->context == NULL)
-		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)
+{
+	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;
 
-	return 0;
+	return init_cbfs_media_context();
 }
diff --git a/src/lib/fmap.c b/src/lib/fmap.c
deleted file mode 100644
index 0f48cdc..0000000
--- a/src/lib/fmap.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2012-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 <console/console.h>
-#include <fmap.h>
-#include <fmap_serialized.h>
-#include <stddef.h>
-#include <string.h>
-
-/*
- * See http://code.google.com/p/flashmap/ for more information on FMAP.
- */
-
-static int find_fmap_directory(struct region_device *fmrd)
-{
-	const struct region_device *boot;
-	struct fmap *fmap;
-	size_t fmap_size;
-	size_t offset = CONFIG_FLASHMAP_OFFSET;
-
-	boot_device_init();
-	boot = boot_device_ro();
-
-	if (boot == NULL)
-		return -1;
-
-	fmap_size = sizeof(struct fmap);
-
-	fmap = rdev_mmap(boot, offset, fmap_size);
-
-	if (fmap == NULL)
-		return -1;
-
-	if (memcmp(fmap->signature, FMAP_SIGNATURE, sizeof(fmap->signature))) {
-		printk(BIOS_DEBUG, "No FMAP found at %zx offset.\n", offset);
-		rdev_munmap(boot, fmap);
-		return -1;
-	}
-
-	printk(BIOS_DEBUG, "FMAP: Found \"%s\" version %d.%d at %zx.\n",
-	       fmap->name, fmap->ver_major, fmap->ver_minor, offset);
-	printk(BIOS_DEBUG, "FMAP: base = %llx size = %x #areas = %d\n",
-	       (long long)fmap->base, fmap->size, fmap->nareas);
-
-	fmap_size += fmap->nareas * sizeof(struct fmap_area);
-
-	rdev_munmap(boot, fmap);
-
-	return rdev_chain(fmrd, boot, offset, fmap_size);
-}
-
-int fmap_locate_area_as_rdev(const char *name, struct region_device *area)
-{
-	struct region ar;
-
-	if (fmap_locate_area(name, &ar))
-		return -1;
-
-	return boot_device_ro_subregion(&ar, area);
-}
-
-int fmap_locate_area(const char *name, struct region *ar)
-{
-	struct region_device fmrd;
-	size_t offset;
-
-	if (find_fmap_directory(&fmrd))
-		return -1;
-
-	/* Start reading the areas just after fmap header. */
-	offset = sizeof(struct fmap);
-
-	while (1) {
-		struct fmap_area *area;
-
-		area = rdev_mmap(&fmrd, offset, sizeof(*area));
-
-		if (area == NULL)
-			return -1;
-
-		if (strcmp((const char *)area->name, name)) {
-			rdev_munmap(&fmrd, area);
-			offset += sizeof(struct fmap_area);
-			continue;
-		}
-
-		printk(BIOS_DEBUG, "FMAP: area %s found\n", name);
-		printk(BIOS_DEBUG, "FMAP:   offset: %x\n", area->offset);
-		printk(BIOS_DEBUG, "FMAP:   size:   %d bytes\n", area->size);
-
-		ar->offset = area->offset;
-		ar->size = area->size;
-
-		rdev_munmap(&fmrd, area);
-
-		return 0;
-	}
-
-	printk(BIOS_DEBUG, "FMAP: area %s not found\n", name);
-
-	return -1;
-}
diff --git a/src/mainboard/emulation/qemu-armv7/media.c b/src/mainboard/emulation/qemu-armv7/media.c
index e0f2251..8c71263 100644
--- a/src/mainboard/emulation/qemu-armv7/media.c
+++ b/src/mainboard/emulation/qemu-armv7/media.c
@@ -12,20 +12,12 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include <boot_device.h>
 #include <cbfs.h>
 #include <string.h>
 #include <symbols.h>
 #include <console/console.h>
 
-/* Maps directly to qemu memory mapped space of 0x10000 up to rom size. */
-static const struct mem_region_device gboot_dev =
-	MEM_REGION_DEV_INIT((void *)0x10000, CONFIG_ROM_SIZE);
-
-const struct region_device *boot_device_ro(void)
-{
-	return &gboot_dev.rdev;
-}
+/* Simple memory-mapped ROM emulation. */
 
 static int emu_rom_open(struct cbfs_media *media)
 {
@@ -34,40 +26,26 @@ static int emu_rom_open(struct cbfs_media *media)
 
 static void *emu_rom_map(struct cbfs_media *media, size_t offset, size_t count)
 {
-	const struct region_device *boot_dev;
-	void *ptr;
-
-	boot_dev = media->context;
-
-	ptr = rdev_mmap(boot_dev, offset, count);
-
-	if (ptr == NULL)
-		return (void *)-1;
-
-	return ptr;
+	if (offset + count > CONFIG_ROM_SIZE)
+		return  (void *)-1;
+        return (void*)(offset + 0x10000);
 }
 
 static void *emu_rom_unmap(struct cbfs_media *media, const void *address)
 {
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	rdev_munmap(boot_dev, (void *)address);
-
 	return NULL;
 }
 
 static size_t emu_rom_read(struct cbfs_media *media, void *dest, size_t offset,
 			   size_t count)
 {
-	const struct region_device *boot_dev;
+	void *ptr = emu_rom_map(media, offset, count);
 
-	boot_dev = media->context;
-
-	if (rdev_readat(boot_dev, dest, offset, count) < 0)
+	if (ptr == (void *)-1)
 		return 0;
 
+	memcpy(dest, ptr, count);
+	emu_rom_unmap(media, ptr);
 	return count;
 }
 
@@ -76,11 +54,10 @@ static int emu_rom_close(struct cbfs_media *media)
 	return 0;
 }
 
-static int init_emu_rom_cbfs_media(struct cbfs_media *media)
-{
-	boot_device_init();
+int init_emu_rom_cbfs_media(struct cbfs_media *media);
 
-	media->context = (void *)boot_device_ro();
+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;
diff --git a/src/mainboard/google/butterfly/mainboard.c b/src/mainboard/google/butterfly/mainboard.c
index e09336d..bd2fbd5 100644
--- a/src/mainboard/google/butterfly/mainboard.c
+++ b/src/mainboard/google/butterfly/mainboard.c
@@ -20,13 +20,11 @@
 
 #include <types.h>
 #include <string.h>
-#include <cbfs.h>
 #include <device/device.h>
 #include <device/pci_def.h>
 #include <device/pci_ops.h>
 #include <console/console.h>
 #include <drivers/intel/gma/int15.h>
-#include <fmap.h>
 #include <pc80/mc146818rtc.h>
 #include <arch/acpi.h>
 #include <arch/io.h>
@@ -38,6 +36,11 @@
 #include <smbios.h>
 #include <device/pci.h>
 #include <ec/quanta/ene_kb3940q/ec.h>
+#if CONFIG_CHROMEOS
+#include <vendorcode/google/chromeos/fmap.h>
+#else
+#include <cbfs.h>
+#endif
 
 static unsigned int search(char *p, char *a, unsigned int lengthp,
 			   unsigned int lengtha)
@@ -197,30 +200,20 @@ static void mainboard_init(device_t dev)
 	size_t search_length = -1;
 	u16 io_base = 0;
 	struct device *ethernet_dev = NULL;
-	void *vpd_file;
-
-	if (IS_ENABLED(CONFIG_CHROMEOS)) {
-		struct region_device rdev;
-
-		if (fmap_locate_area_as_rdev("RO_VPD", &rdev) == 0) {
-			vpd_file = rdev_mmap_full(&rdev);
-
-			if (vpd_file != NULL) {
-				search_length = region_device_sz(&rdev);
-				search_address = (uintptr_t)vpd_file;
-			}
-		}
+#if CONFIG_CHROMEOS
+	char **vpd_region_ptr = NULL;
+	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);
+	if (vpd_file) {
+		search_address = (unsigned long)vpd_file;
 	} else {
-		vpd_file = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-						"vpd.bin", CBFS_TYPE_RAW,
-						&search_length);
-		if (vpd_file) {
-			search_address = (unsigned long)vpd_file;
-		} else {
-			search_length = -1;
-			search_address = 0;
-		}
+		search_length = -1;
+		search_address = 0;
 	}
+#endif
 
 	/* Initialize the Embedded Controller */
 	butterfly_ec_init();
diff --git a/src/mainboard/google/panther/lan.c b/src/mainboard/google/panther/lan.c
index 8a648cb..9fd325f 100644
--- a/src/mainboard/google/panther/lan.c
+++ b/src/mainboard/google/panther/lan.c
@@ -24,8 +24,8 @@
 #include <console/console.h>
 #include <device/device.h>
 #include <device/pci.h>
-#include <fmap.h>
 #include <southbridge/intel/bd82x6x/pch.h>
+#include <vendorcode/google/chromeos/fmap.h>
 #include "onboard.h"
 
 static unsigned int search(char *p, u8 *a, unsigned int lengthp,
@@ -117,24 +117,15 @@ static void program_mac_address(u16 io_base)
 	u32 high_dword = 0xD0BA00A0;	/* high dword of mac address */
 	u32 low_dword = 0x0000AD0B;	/* low word of mac address as a dword */
 
-	if (IS_ENABLED(CONFIG_CHROMEOS)) {
-		struct region_device rdev;
-
-		if (fmap_locate_area_as_rdev("RO_VPD", &rdev) == 0) {
-			search_address = rdev_mmap_full(&rdev);
-
-			if (search_address != NULL)
-				search_length = region_device_sz(&rdev);
-		}
-	} else {
-		search_address = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-							"vpd.bin",
-							CBFS_TYPE_RAW,
-							&search_length);
-	}
+#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);
+#endif
 
 	if (search_length <= 0)
-		printk(BIOS_ERR, "LAN: VPD not found.\n");
+		printk(BIOS_ERR, "LAN: find_fmap_entry returned -1.\n");
 	else
 		get_mac_address(&high_dword, &low_dword, search_address,
 				search_length);
diff --git a/src/northbridge/intel/haswell/mrccache.c b/src/northbridge/intel/haswell/mrccache.c
index d72c2c3..3bb7fa5 100644
--- a/src/northbridge/intel/haswell/mrccache.c
+++ b/src/northbridge/intel/haswell/mrccache.c
@@ -22,7 +22,6 @@
 #include <bootstate.h>
 #include <console/console.h>
 #include <cbfs.h>
-#include <fmap.h>
 #include <ip_checksum.h>
 #include <device/device.h>
 #include <cbmem.h>
@@ -30,6 +29,9 @@
 #include "haswell.h"
 #include <spi-generic.h>
 #include <spi_flash.h>
+#if CONFIG_CHROMEOS
+#include <vendorcode/google/chromeos/fmap.h>
+#endif
 
 /* convert a pointer to flash area into the offset inside the flash */
 static inline u32 to_flash_offset(struct spi_flash *flash, void *p) {
@@ -64,22 +66,16 @@ 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 = 0;
-
-	if (IS_ENABLED(CONFIG_CHROMEOS)) {
-		struct region_device rdev;
-
-		if (fmap_locate_area_as_rdev("RW_MRC_CACHE", &rdev) == 0) {
-			region_size = region_device_sz(&rdev);
-			*mrc_region_ptr = rdev_mmap_full(&rdev);
-		}
-	} else {
-		*mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-							"mrc.cache",
-							CBFS_TYPE_MRC_CACHE,
-							&region_size);
-	}
+#if CONFIG_CHROMEOS
+	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);
 	return region_size;
+#endif
 }
 
 /*
diff --git a/src/northbridge/intel/sandybridge/mrccache.c b/src/northbridge/intel/sandybridge/mrccache.c
index e17c54b..e5f74e8 100644
--- a/src/northbridge/intel/sandybridge/mrccache.c
+++ b/src/northbridge/intel/sandybridge/mrccache.c
@@ -22,7 +22,6 @@
 #include <bootstate.h>
 #include <console/console.h>
 #include <cbfs.h>
-#include <fmap.h>
 #include <ip_checksum.h>
 #include <device/device.h>
 #include <cbmem.h>
@@ -30,6 +29,9 @@
 #include "sandybridge.h"
 #include <spi-generic.h>
 #include <spi_flash.h>
+#if CONFIG_CHROMEOS
+#include <vendorcode/google/chromeos/fmap.h>
+#endif
 
 /* convert a pointer to flash area into the offset inside the flash */
 static inline u32 to_flash_offset(struct spi_flash *flash, void *p) {
@@ -64,22 +66,17 @@ 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 = 0;
-
-	if (IS_ENABLED(CONFIG_CHROMEOS)) {
-		struct region_device rdev;
-
-		if (fmap_locate_area_as_rdev("RW_MRC_CACHE", &rdev) == 0) {
-			region_size = region_device_sz(&rdev);
-			*mrc_region_ptr = rdev_mmap_full(&rdev);
-		}
-	} else {
-		*mrc_region_ptr = cbfs_get_file_content(CBFS_DEFAULT_MEDIA,
-							"mrc.cache",
-							CBFS_TYPE_MRC_CACHE,
-							&region_size);
-	}
+#if CONFIG_CHROMEOS
+	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);
 	return region_size;
+#endif
+
 }
 
 /*
diff --git a/src/soc/intel/common/mrc_cache.c b/src/soc/intel/common/mrc_cache.c
index 6783f18..9366aa5 100644
--- a/src/soc/intel/common/mrc_cache.c
+++ b/src/soc/intel/common/mrc_cache.c
@@ -20,8 +20,10 @@
 #include <string.h>
 #include <console/console.h>
 #include <cbmem.h>
-#include <fmap.h>
 #include <ip_checksum.h>
+#if CONFIG_CHROMEOS
+#include <vendorcode/google/chromeos/fmap.h>
+#endif
 #include "mrc_cache.h"
 
 #define MRC_DATA_ALIGN           0x1000
@@ -37,23 +39,16 @@ struct mrc_data_region {
 /* common code */
 static int mrc_cache_get_region(struct mrc_data_region *region)
 {
-	if (IS_ENABLED(CONFIG_CHROMEOS)) {
-		struct region_device rdev;
-
-		if (fmap_locate_area_as_rdev("RW_MRC_CACHE", &rdev))
-			return -1;
-
-		region->size = region_device_sz(&rdev);
-		region->base = rdev_mmap_full(&rdev);
-
-		if (region->base == NULL)
-			return -1;
-
+#if CONFIG_CHROMEOS
+	int ret;
+	ret = find_fmap_entry("RW_MRC_CACHE", &region->base);
+	if (ret >= 0) {
+		region->size = ret;
 		return 0;
-	} else {
-		region->base = (void *)CONFIG_MRC_SETTINGS_CACHE_BASE;
-		region->size = CONFIG_MRC_SETTINGS_CACHE_SIZE;
 	}
+#endif
+	region->base = (void *)CONFIG_MRC_SETTINGS_CACHE_BASE;
+	region->size = CONFIG_MRC_SETTINGS_CACHE_SIZE;
 	return 0;
 }
 
diff --git a/src/soc/nvidia/tegra124/Makefile.inc b/src/soc/nvidia/tegra124/Makefile.inc
index 46ce59d..78054f4 100644
--- a/src/soc/nvidia/tegra124/Makefile.inc
+++ b/src/soc/nvidia/tegra124/Makefile.inc
@@ -2,6 +2,7 @@ ifeq ($(CONFIG_SOC_NVIDIA_TEGRA124),y)
 
 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
@@ -21,6 +22,7 @@ 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,6 +34,7 @@ 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
@@ -48,6 +51,7 @@ 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
new file mode 100644
index 0000000..d82ca9a
--- /dev/null
+++ b/src/soc/nvidia/tegra124/cbfs.c
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+
+#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 cfa3cd2..ab04632 100644
--- a/src/soc/nvidia/tegra124/include/soc/spi.h
+++ b/src/soc/nvidia/tegra124/include/soc/spi.h
@@ -61,6 +61,11 @@ 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 0cf5495..683edd1 100644
--- a/src/soc/nvidia/tegra124/spi.c
+++ b/src/soc/nvidia/tegra124/spi.c
@@ -21,7 +21,6 @@
 #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>
@@ -34,7 +33,6 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
-#include <symbols.h>
 #include <timer.h>
 
 
@@ -802,6 +800,12 @@ 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)
 {
 	DEBUG_SPI("tegra_spi_cbfs_open\n");
@@ -819,17 +823,16 @@ static int tegra_spi_cbfs_close(struct cbfs_media *media)
 #define JEDEC_FAST_READ_DUAL		0x3b
 #define JEDEC_FAST_READ_DUAL_OUTSIZE	0x05
 
-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)
+static size_t tegra_spi_cbfs_read(struct cbfs_media *media, 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(boot_slave->bus);
+	channel = to_tegra_spi(spi->slave->bus);
 
 	if (channel->dual_mode) {
 		/*
@@ -850,9 +853,9 @@ static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
 	spi_read_cmd[2] = (offset >> 8) & 0xff;
 	spi_read_cmd[3] = offset & 0xff;
 
-	spi_claim_bus(boot_slave);
+	spi_claim_bus(spi->slave);
 
-	if (spi_xfer(boot_slave, spi_read_cmd,
+	if (spi_xfer(spi->slave, spi_read_cmd,
 			read_cmd_bytes, NULL, 0) < 0) {
 		ret = -1;
 		printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n",
@@ -863,7 +866,7 @@ static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
 	if (channel->dual_mode) {
 		setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT);
 	}
-	if (spi_xfer(boot_slave, NULL, 0, dest, count)) {
+	if (spi_xfer(spi->slave, NULL, 0, dest, count)) {
 		ret = -1;
 		printk(BIOS_ERR, "%s: Failed to transfer %u bytes\n",
 				__func__, count);
@@ -873,70 +876,56 @@ static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
 
 tegra_spi_cbfs_read_exit:
 	/* de-assert /CS */
-	spi_release_bus(boot_slave);
-	return ret;
-}
-
-static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
-				size_t offset, size_t count)
-{
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	printk(BIOS_ERR, "%s: reading %zx bytes from %zx\n",
-			__func__, count, offset);
-	if (rdev_readat(boot_dev, dest, offset, count) < 0)
-		return 0;
-
-	return count;
+	spi_release_bus(spi->slave);
+	return (ret < 0) ? 0 : ret;
 }
 
 static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset,
 				 size_t count)
 {
-	const struct region_device *boot_dev;
+	struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
 	void *map;
-
 	DEBUG_SPI("tegra_spi_cbfs_map\n");
-
-	boot_dev = media->context;
-
-	map = rdev_mmap(boot_dev, offset, count);
-
-	if (map == NULL)
-		map = (void *)-1;
-
+	map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
 	return map;
 }
 
 static void *tegra_spi_cbfs_unmap(struct cbfs_media *media,
 				   const void *address)
 {
-	const struct region_device *boot_dev;
-
+	struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
 	DEBUG_SPI("tegra_spi_cbfs_unmap\n");
-
-	boot_dev = media->context;
-
-	rdev_munmap(boot_dev, (void *)address);
-
-	return NULL;
+	return cbfs_simple_buffer_unmap(&spi->buffer, address);
 }
 
-int init_default_cbfs_media(struct cbfs_media *media)
+int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
+				     void *buffer_address,
+				     size_t buffer_size)
 {
-	DEBUG_SPI("Initializing CBFS media on SPI\n");
+	// 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;
 
-	boot_device_init();
+	DEBUG_SPI("Initializing CBFS media on SPI\n");
 
-	media->context = (void *)boot_device_ro();
+	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;
 
+#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1
+	channel->dual_mode = 1;
+#endif
+
 	return 0;
 }
 
@@ -948,32 +937,3 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
 
 	return &channel->slave;
 }
-
-static const struct region_device_ops tegra_spi_ops = {
-	.mmap = mmap_helper_rdev_mmap,
-	.munmap = mmap_helper_rdev_munmap,
-	.readat = tegra_spi_readat,
-};
-
-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)
-{
-	return &mdev.rdev;
-}
-
-void boot_device_init(void)
-{
-	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
-	boot_chan->dual_mode = 1;
-#endif
-	boot_slave = &boot_chan->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 c192055..365dab3 100644
--- a/src/soc/nvidia/tegra132/Makefile.inc
+++ b/src/soc/nvidia/tegra132/Makefile.inc
@@ -2,6 +2,7 @@ ifeq ($(CONFIG_SOC_NVIDIA_TEGRA132),y)
 
 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
@@ -22,6 +23,7 @@ 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
@@ -37,6 +39,7 @@ 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
@@ -60,6 +63,7 @@ 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
new file mode 100644
index 0000000..7aeb59b
--- /dev/null
+++ b/src/soc/nvidia/tegra132/cbfs.c
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#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/include/soc/spi.h b/src/soc/nvidia/tegra132/include/soc/spi.h
index 4c91c27..2fd9562 100644
--- a/src/soc/nvidia/tegra132/include/soc/spi.h
+++ b/src/soc/nvidia/tegra132/include/soc/spi.h
@@ -62,6 +62,11 @@ 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 1650057..7ca66e1 100644
--- a/src/soc/nvidia/tegra132/spi.c
+++ b/src/soc/nvidia/tegra132/spi.c
@@ -21,7 +21,6 @@
 #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>
@@ -34,7 +33,6 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
-#include <symbols.h>
 #include <timer.h>
 
 
@@ -817,6 +815,12 @@ 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)
 {
 	DEBUG_SPI("tegra_spi_cbfs_open\n");
@@ -834,17 +838,16 @@ static int tegra_spi_cbfs_close(struct cbfs_media *media)
 #define JEDEC_FAST_READ_DUAL		0x3b
 #define JEDEC_FAST_READ_DUAL_OUTSIZE	0x05
 
-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)
+static size_t tegra_spi_cbfs_read(struct cbfs_media *media, 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(boot_slave->bus);
+	channel = to_tegra_spi(spi->slave->bus);
 
 	if (channel->dual_mode) {
 		/*
@@ -865,9 +868,9 @@ static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
 	spi_read_cmd[2] = (offset >> 8) & 0xff;
 	spi_read_cmd[3] = offset & 0xff;
 
-	spi_claim_bus(boot_slave);
+	spi_claim_bus(spi->slave);
 
-	if (spi_xfer(boot_slave, spi_read_cmd,
+	if (spi_xfer(spi->slave, spi_read_cmd,
 			read_cmd_bytes, NULL, 0) < 0) {
 		ret = -1;
 		printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n",
@@ -878,7 +881,7 @@ static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
 	if (channel->dual_mode) {
 		setbits_le32(&channel->regs->command1, SPI_CMD1_BOTH_EN_BIT);
 	}
-	if (spi_xfer(boot_slave, NULL, 0, dest, count)) {
+	if (spi_xfer(spi->slave, NULL, 0, dest, count)) {
 		ret = -1;
 		printk(BIOS_ERR, "%s: Failed to transfer %zu bytes\n",
 				__func__, count);
@@ -888,70 +891,56 @@ static ssize_t tegra_spi_readat(const struct region_device *rdev, void *dest,
 
 tegra_spi_cbfs_read_exit:
 	/* de-assert /CS */
-	spi_release_bus(boot_slave);
-	return ret;
-}
-
-static size_t tegra_spi_cbfs_read(struct cbfs_media *media, void *dest,
-				size_t offset, size_t count)
-{
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	DEBUG_SPI("%s: reading %zx bytes from %zx\n", __func__, count, offset);
-
-	if (rdev_readat(boot_dev, dest, offset, count) < 0)
-		return 0;
-
-	return count;
+	spi_release_bus(spi->slave);
+	return (ret < 0) ? 0 : ret;
 }
 
 static void *tegra_spi_cbfs_map(struct cbfs_media *media, size_t offset,
 				 size_t count)
 {
-	const struct region_device *boot_dev;
+	struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
 	void *map;
-
 	DEBUG_SPI("tegra_spi_cbfs_map\n");
-
-	boot_dev = media->context;
-
-	map = rdev_mmap(boot_dev, offset, count);
-
-	if (map == NULL)
-		map = (void *)-1;
-
+	map = cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
 	return map;
 }
 
 static void *tegra_spi_cbfs_unmap(struct cbfs_media *media,
 				   const void *address)
 {
-	const struct region_device *boot_dev;
-
+	struct tegra_spi_media *spi = (struct tegra_spi_media*)media->context;
 	DEBUG_SPI("tegra_spi_cbfs_unmap\n");
-
-	boot_dev = media->context;
-
-	rdev_munmap(boot_dev, (void *)address);
-
-	return NULL;
+	return cbfs_simple_buffer_unmap(&spi->buffer, address);
 }
 
-int init_default_cbfs_media(struct cbfs_media *media)
+int initialize_tegra_spi_cbfs_media(struct cbfs_media *media,
+				     void *buffer_address,
+				     size_t buffer_size)
 {
-	DEBUG_SPI("Initializing CBFS media on SPI\n");
+	// 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;
 
-	boot_device_init();
+	DEBUG_SPI("Initializing CBFS media on SPI\n");
 
-	media->context = (void *)boot_device_ro();
+	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;
 
+#if CONFIG_SPI_FLASH_FAST_READ_DUAL_OUTPUT_3B == 1
+	channel->dual_mode = 1;
+#endif
+
 	return 0;
 }
 
@@ -963,32 +952,3 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
 
 	return &channel->slave;
 }
-
-static const struct region_device_ops tegra_spi_ops = {
-	.mmap = mmap_helper_rdev_mmap,
-	.munmap = mmap_helper_rdev_munmap,
-	.readat = tegra_spi_readat,
-};
-
-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)
-{
-	return &mdev.rdev;
-}
-
-void boot_device_init(void)
-{
-	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
-	boot_chan->dual_mode = 1;
-#endif
-	boot_slave = &boot_chan->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 546018a..2e2aeec 100644
--- a/src/soc/samsung/exynos5250/alternate_cbfs.c
+++ b/src/soc/samsung/exynos5250/alternate_cbfs.c
@@ -19,7 +19,6 @@
 
 
 #include <assert.h>
-#include <boot_device.h>
 #include <cbfs.h>  /* This driver serves as a CBFS media source. */
 #include <console/console.h>
 #include <soc/alternate_cbfs.h>
@@ -46,7 +45,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(void)
+static int usb_cbfs_open(struct cbfs_media *media)
 {
 #ifdef __PRE_RAM__
 	static int first_run = 1;
@@ -81,7 +80,7 @@ static int usb_cbfs_open(void)
  * this seems like a safer approach. It also makes it easy to pass our image
  * down to payloads.
  */
-static int sdmmc_cbfs_open(void)
+static int sdmmc_cbfs_open(struct cbfs_media *media)
 {
 #ifdef __PRE_RAM__
 	/*
@@ -112,109 +111,66 @@ static int sdmmc_cbfs_open(void)
 	return 0;
 }
 
-static int exynos_cbfs_open(struct cbfs_media *media) {
-	return 0;
-}
-
-static int exynos_cbfs_close(struct cbfs_media *media) {
-	return 0;
-}
-
-static size_t exynos_cbfs_read(struct cbfs_media *media, void *dest,
-				   size_t offset, size_t count) {
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	if (rdev_readat(boot_dev, dest, offset, count) < 0)
-		return 0;
+static int alternate_cbfs_close(struct cbfs_media *media) { return 0; }
 
+static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest,
+				  size_t offset, size_t count)
+{
+	ASSERT(offset + count < _cbfs_cache_size);
+	memcpy(dest, _cbfs_cache + offset, count);
 	return count;
 }
 
-static void *exynos_cbfs_map(struct cbfs_media *media, size_t offset,
-				 size_t count) {
-	const struct region_device *boot_dev;
-	void *ptr;
-
-	boot_dev = media->context;
-
-	ptr = rdev_mmap(boot_dev, offset, count);
-
-	if (ptr == NULL)
-		return (void *)-1;
-
-	return ptr;
+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 *exynos_cbfs_unmap(struct cbfs_media *media,
-				   const void *address) {
-	const struct region_device *boot_dev;
+static void *alternate_cbfs_unmap(struct cbfs_media *media,
+				  const void *buffer) { return 0; }
 
-	boot_dev = media->context;
+static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media)
+{
+	printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
 
-	rdev_munmap(boot_dev, (void *)address);
+	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;
 
-	return NULL;
+	return 0;
 }
 
-int init_default_cbfs_media(struct cbfs_media *media)
+static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media)
 {
-	boot_device_init();
+	printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
 
-	media->context = (void *)boot_device_ro();
-
-	if (media->context == NULL)
-		return -1;
-
-	media->open = exynos_cbfs_open;
-	media->close = exynos_cbfs_close;
-	media->read = exynos_cbfs_read;
-	media->map = exynos_cbfs_map;
-	media->unmap = exynos_cbfs_unmap;
+	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;
 
 	return 0;
 }
 
-static struct mem_region_device alternate_rdev = MEM_REGION_DEV_INIT(NULL, 0);
-
-const struct region_device *boot_device_ro(void)
+int init_default_cbfs_media(struct cbfs_media *media)
 {
 	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
-		return &alternate_rdev.rdev;
-
-	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;
-	}
-}
-
-void boot_device_init(void)
-{
-	mem_region_device_init(&alternate_rdev, _cbfs_cache, _cbfs_cache_size);
-
-	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) {
-		printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
-		usb_cbfs_open();
-		return;
-	}
+		return initialize_exynos_usb_cbfs_media(media);
 
 	switch (exynos_power->om_stat & OM_STAT_MASK) {
 	case OM_STAT_SDMMC:
-		printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
-		sdmmc_cbfs_open();
-		break;
+		return initialize_exynos_sdmmc_cbfs_media(media);
 	case OM_STAT_SPI:
-		exynos_init_spi_boot_device();
-		break;
+		return initialize_exynos_spi_cbfs_media(media,
+			_cbfs_cache, _cbfs_cache_size);
 	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 298db1a..92236ae 100644
--- a/src/soc/samsung/exynos5250/include/soc/spi.h
+++ b/src/soc/samsung/exynos5250/include/soc/spi.h
@@ -20,7 +20,8 @@
 #ifndef CPU_SAMSUNG_EXYNOS5250_SPI_H
 #define CPU_SAMSUNG_EXYNOS5250_SPI_H
 
-#include <boot_device.h>
+/* This driver serves as a CBFS media source. */
+#include <cbfs.h>
 
 /* SPI peripheral register map; padded to 64KB */
 struct exynos_spi {
@@ -91,6 +92,8 @@ 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);
 
-void exynos_init_spi_boot_device(void);
-const struct region_device *exynos_spi_boot_device(void);
+/* Serve as CBFS media source */
+int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
+				     void *buffer_address,
+				     size_t buffer_size);
 #endif
diff --git a/src/soc/samsung/exynos5250/spi.c b/src/soc/samsung/exynos5250/spi.c
index adf31e4..4f32487 100644
--- a/src/soc/samsung/exynos5250/spi.c
+++ b/src/soc/samsung/exynos5250/spi.c
@@ -20,13 +20,11 @@
 
 #include <arch/io.h>
 #include <assert.h>
-#include <boot_device.h>
 #include <console/console.h>
 #include <soc/clk.h>
 #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)
@@ -146,47 +144,70 @@ int exynos_spi_close(struct exynos_spi *regs)
 	return 0;
 }
 
-static struct exynos_spi *boot_slave_regs;
+// SPI as CBFS media.
+struct exynos_spi_media {
+	struct exynos_spi *regs;
+	struct cbfs_simple_buffer buffer;
+};
 
-static ssize_t exynos_spi_readat(const struct region_device *rdev, void *dest,
-					size_t offset, size_t count)
-{
+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 size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest,
+				   size_t offset, size_t count) {
+	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
 	int bytes;
 	DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count);
-	exynos_spi_open(boot_slave_regs);
-	bytes = exynos_spi_read(boot_slave_regs, dest, count, offset);
-	exynos_spi_close(boot_slave_regs);
+	bytes = exynos_spi_read(spi->regs, dest, count, offset);
+	// Flush and re-open the device.
+	exynos_spi_close(spi->regs);
+	exynos_spi_open(spi->regs);
 	return bytes;
 }
 
-static void *exynos_spi_map(const struct region_device *rdev,
-					size_t offset, size_t count)
-{
+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;
 	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.
+	// See exynos_spi_rx_tx for I/O alignment limitation.
 	if (count % 4)
 		count += 4 - (count % 4);
-	return mmap_helper_rdev_mmap(rdev, offset, count);
+	return cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
 }
 
-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)
-{
-	boot_slave_regs = (void *)EXYNOS5_SPI1_BASE;
-
-	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
+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);
 }
 
-const struct region_device *exynos_spi_boot_device(void)
-{
-	return &mdev.rdev;
+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;
+
+	return 0;
 }
diff --git a/src/soc/samsung/exynos5420/alternate_cbfs.c b/src/soc/samsung/exynos5420/alternate_cbfs.c
index 9bba748..b30ed6b 100644
--- a/src/soc/samsung/exynos5420/alternate_cbfs.c
+++ b/src/soc/samsung/exynos5420/alternate_cbfs.c
@@ -20,7 +20,6 @@
 
 #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 <soc/alternate_cbfs.h>
@@ -47,7 +46,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(void)
+static int usb_cbfs_open(struct cbfs_media *media)
 {
 #ifdef __PRE_RAM__
 	static int first_run = 1;
@@ -85,7 +84,7 @@ static int usb_cbfs_open(void)
  * this seems like a safer approach. It also makes it easy to pass our image
  * down to payloads.
  */
-static int sdmmc_cbfs_open(void)
+static int sdmmc_cbfs_open(struct cbfs_media *media)
 {
 #ifdef __PRE_RAM__
 	/*
@@ -119,109 +118,66 @@ static int sdmmc_cbfs_open(void)
 	return 0;
 }
 
-static int exynos_cbfs_open(struct cbfs_media *media) {
-	return 0;
-}
-
-static int exynos_cbfs_close(struct cbfs_media *media) {
-	return 0;
-}
-
-static size_t exynos_cbfs_read(struct cbfs_media *media, void *dest,
-				   size_t offset, size_t count) {
-	const struct region_device *boot_dev;
-
-	boot_dev = media->context;
-
-	if (rdev_readat(boot_dev, dest, offset, count) < 0)
-		return 0;
+static int alternate_cbfs_close(struct cbfs_media *media) { return 0; }
 
+static size_t alternate_cbfs_read(struct cbfs_media *media, void *dest,
+				  size_t offset, size_t count)
+{
+	ASSERT(offset + count < _cbfs_cache_size);
+	memcpy(dest, _cbfs_cache + offset, count);
 	return count;
 }
 
-static void *exynos_cbfs_map(struct cbfs_media *media, size_t offset,
-				 size_t count) {
-	const struct region_device *boot_dev;
-	void *ptr;
-
-	boot_dev = media->context;
-
-	ptr = rdev_mmap(boot_dev, offset, count);
-
-	if (ptr == NULL)
-		return (void *)-1;
-
-	return ptr;
+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 *exynos_cbfs_unmap(struct cbfs_media *media,
-				   const void *address) {
-	const struct region_device *boot_dev;
+static void *alternate_cbfs_unmap(struct cbfs_media *media,
+				  const void *buffer) { return 0; }
 
-	boot_dev = media->context;
+static int initialize_exynos_sdmmc_cbfs_media(struct cbfs_media *media)
+{
+	printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
 
-	rdev_munmap(boot_dev, (void *)address);
+	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;
 
-	return NULL;
+	return 0;
 }
 
-int init_default_cbfs_media(struct cbfs_media *media)
+static int initialize_exynos_usb_cbfs_media(struct cbfs_media *media)
 {
-	boot_device_init();
+	printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
 
-	media->context = (void *)boot_device_ro();
-
-	if (media->context == NULL)
-		return -1;
-
-	media->open = exynos_cbfs_open;
-	media->close = exynos_cbfs_close;
-	media->read = exynos_cbfs_read;
-	media->map = exynos_cbfs_map;
-	media->unmap = exynos_cbfs_unmap;
+	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;
 
 	return 0;
 }
 
-static struct mem_region_device alternate_rdev = MEM_REGION_DEV_INIT(NULL, 0);
-
-const struct region_device *boot_device_ro(void)
+int init_default_cbfs_media(struct cbfs_media *media)
 {
 	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB)
-		return &alternate_rdev.rdev;
-
-	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;
-	}
-}
-
-void boot_device_init(void)
-{
-	mem_region_device_init(&alternate_rdev, _cbfs_cache, _cbfs_cache_size);
-
-	if (*iram_secondary_base == SECONDARY_BASE_BOOT_USB) {
-		printk(BIOS_DEBUG, "Using Exynos alternate boot mode USB A-A\n");
-		usb_cbfs_open();
-		return;
-	}
+		return initialize_exynos_usb_cbfs_media(media);
 
 	switch (exynos_power->om_stat & OM_STAT_MASK) {
 	case OM_STAT_SDMMC:
-		printk(BIOS_DEBUG, "Using Exynos alternate boot mode SDMMC\n");
-		sdmmc_cbfs_open();
-		break;
+		return initialize_exynos_sdmmc_cbfs_media(media);
 	case OM_STAT_SPI:
-		exynos_init_spi_boot_device();
-		break;
+		return initialize_exynos_spi_cbfs_media(media,
+			_cbfs_cache, _cbfs_cache_size);
 	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 77d5ffc..cf77800 100644
--- a/src/soc/samsung/exynos5420/include/soc/spi.h
+++ b/src/soc/samsung/exynos5420/include/soc/spi.h
@@ -20,7 +20,8 @@
 #ifndef CPU_SAMSUNG_EXYNOS5420_SPI_H
 #define CPU_SAMSUNG_EXYNOS5420_SPI_H
 
-#include <boot_device.h>
+/* This driver serves as a CBFS media source. */
+#include <cbfs.h>
 
 /* SPI peripheral register map; padded to 64KB */
 struct exynos_spi {
@@ -90,6 +91,8 @@ check_member(exynos_spi, fb_clk, 0x2c);
 #define SPI_RX_BYTE_SWAP	(1 << 6)
 #define SPI_RX_HWORD_SWAP	(1 << 7)
 
-void exynos_init_spi_boot_device(void);
-const struct region_device *exynos_spi_boot_device(void);
+/* Serve as CBFS media source */
+int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
+				     void *buffer_address,
+				     size_t buffer_size);
 #endif
diff --git a/src/soc/samsung/exynos5420/spi.c b/src/soc/samsung/exynos5420/spi.c
index 2edc337..5f29803 100644
--- a/src/soc/samsung/exynos5420/spi.c
+++ b/src/soc/samsung/exynos5420/spi.c
@@ -26,7 +26,6 @@
 #include <spi_flash.h>
 #include <stdlib.h>
 #include <string.h>
-#include <symbols.h>
 
 #define EXYNOS_SPI_MAX_TRANSFER_BYTES (65535)
 
@@ -243,43 +242,76 @@ static int exynos_spi_read(struct spi_slave *slave, void *dest, uint32_t len,
 	return len;
 }
 
-static struct exynos_spi_slave *boot_slave;
+// 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 ssize_t exynos_spi_readat(const struct region_device *rdev, void *dest,
-					size_t offset, size_t count)
+static size_t exynos_spi_cbfs_read(struct cbfs_media *media, void *dest,
+				   size_t offset, size_t count)
 {
+	struct exynos_spi_media *spi = (struct exynos_spi_media*)media->context;
+	int bytes;
 	DEBUG_SPI("exynos_spi_cbfs_read(%u)\n", count);
-	return exynos_spi_read(&boot_slave->slave, dest, count, offset);
+	bytes = exynos_spi_read(spi->slave, dest, count, offset);
+	return bytes;
 }
 
-static void *exynos_spi_map(const struct region_device *rdev,
-					size_t offset, size_t count)
+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;
 	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 mmap_helper_rdev_mmap(rdev, offset, count);
+	return cbfs_simple_buffer_map(&spi->buffer, media, offset, count);
 }
 
-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)
+static void *exynos_spi_cbfs_unmap(struct cbfs_media *media,
+				   const void *address)
 {
-	boot_slave = &exynos_spi_slaves[1];
-
-	mmap_helper_device_init(&mdev, _cbfs_cache, _cbfs_cache_size);
+	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);
 }
 
-const struct region_device *exynos_spi_boot_device(void)
+int initialize_exynos_spi_cbfs_media(struct cbfs_media *media,
+				     void *buffer_address,
+				     size_t buffer_size)
 {
-	return &mdev.rdev;
+	// 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;
 }
diff --git a/src/vendorcode/google/chromeos/Kconfig b/src/vendorcode/google/chromeos/Kconfig
index 0b0b862..0fc0d54 100644
--- a/src/vendorcode/google/chromeos/Kconfig
+++ b/src/vendorcode/google/chromeos/Kconfig
@@ -94,6 +94,15 @@ config CHROMEOS_RAMOOPS_RAM_SIZE
 	default 0x00100000
 	depends on CHROMEOS_RAMOOPS
 
+config FLASHMAP_OFFSET
+	hex "Flash Map Offset"
+	default 0x00670000 if NORTHBRIDGE_INTEL_SANDYBRIDGE
+	default 0x00610000 if NORTHBRIDGE_INTEL_IVYBRIDGE
+	default CBFS_SIZE if !ARCH_X86
+	default 0
+	help
+	  Offset of flash map in firmware image
+
 config EC_SOFTWARE_SYNC
 	bool "Enable EC software sync"
 	default n
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index df24435..6e416ee 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -34,7 +34,11 @@ ramstage-$(CONFIG_CHROMEOS_VBNV_FLASH) += vbnv_flash.c
 
 ramstage-$(CONFIG_ELOG) += elog.c
 ramstage-$(CONFIG_HAVE_ACPI_TABLES) += gnvs.c
+verstage-y += fmap.c
+romstage-y += fmap.c
+ramstage-y += fmap.c
 ramstage-$(CONFIG_CHROMEOS_RAMOOPS) += ramoops.c
+smm-y += fmap.c
 romstage-y += vpd_decode.c cros_vpd.c
 ramstage-y += vpd_decode.c cros_vpd.c vpd_mac.c vpd_serialno.c vpd_calibration.c
 ifeq ($(CONFIG_ARCH_X86)$(CONFIG_ARCH_MIPS),)
diff --git a/src/vendorcode/google/chromeos/cros_vpd.c b/src/vendorcode/google/chromeos/cros_vpd.c
index fed1d82..c0e4830 100644
--- a/src/vendorcode/google/chromeos/cros_vpd.c
+++ b/src/vendorcode/google/chromeos/cros_vpd.c
@@ -6,11 +6,12 @@
 
 #include <console/console.h>
 
-#include <fmap.h>
+#include <cbfs.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include "cros_vpd.h"
+#include "fmap.h"
 #include "lib_vpd.h"
 #include "vpd_tables.h"
 
@@ -34,7 +35,9 @@ static int cros_vpd_load(uint8_t **vpd_address, int32_t *vpd_size)
 	MAYBE_STATIC int result = -1;
 	struct google_vpd_info info;
 	int32_t base;
-	struct region_device vpd;
+
+	const struct fmap_area *area;
+	struct cbfs_media media;
 
 	if (cached) {
 		*vpd_address = cached_address;
@@ -43,31 +46,32 @@ static int cros_vpd_load(uint8_t **vpd_address, int32_t *vpd_size)
 	}
 
 	cached = 1;
-	if (fmap_locate_area_as_rdev("RO_VPD", &vpd)) {
+	area = find_fmap_area(fmap_find(), "RO_VPD");
+	if (!area) {
 		printk(BIOS_ERR, "%s: No RO_VPD FMAP section.\n", __func__);
 		return result;
 	}
-
-	base = 0;
-	cached_size = region_device_sz(&vpd);
-
-	if ((cached_size < GOOGLE_VPD_2_0_OFFSET + sizeof(info)) ||
-	    rdev_chain(&vpd, &vpd, GOOGLE_VPD_2_0_OFFSET,
-			cached_size - GOOGLE_VPD_2_0_OFFSET)) {
+	if (area->size <= GOOGLE_VPD_2_0_OFFSET + sizeof(info)) {
 		printk(BIOS_ERR, "%s: Too small (%d) for Google VPD 2.0.\n",
-		       __func__, cached_size);
+		       __func__, area->size);
 		return result;
 	}
 
+	base = area->offset + GOOGLE_VPD_2_0_OFFSET;
+	cached_size = area->size - GOOGLE_VPD_2_0_OFFSET;
+	init_default_cbfs_media(&media);
+	media.open(&media);
+
 	/* Try if we can find a google_vpd_info, otherwise read whole VPD. */
-	if (rdev_readat(&vpd, &info, base, sizeof(info)) == sizeof(info) &&
+	if (media.read(&media, &info, base, sizeof(info)) == sizeof(info) &&
 	    memcmp(info.header.magic, VPD_INFO_MAGIC, sizeof(info.header.magic))
 	    == 0 && cached_size >= info.size + sizeof(info)) {
 		base += sizeof(info);
 		cached_size = info.size;
 	}
 
-	cached_address = rdev_mmap(&vpd, base, cached_size);
+	cached_address = media.map(&media, base, cached_size);
+	media.close(&media);
 	if (cached_address) {
 		*vpd_address = cached_address;
 		*vpd_size = cached_size;
diff --git a/src/vendorcode/google/chromeos/fmap.h b/src/vendorcode/google/chromeos/fmap.h
new file mode 100644
index 0000000..05d3fb6
--- /dev/null
+++ b/src/vendorcode/google/chromeos/fmap.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2010, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *    * 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.
+ *    * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT
+ * OWNER 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.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#ifndef FLASHMAP_LIB_FMAP_H__
+#define FLASHMAP_LIB_FMAP_H__
+
+#include <stdint.h>
+
+#define FMAP_REVERSED_SIGNATURE	"__PAMF__" /* avoid magic number in .rodata */
+#define FMAP_VER_MAJOR		1	/* this header's FMAP minor version */
+#define FMAP_VER_MINOR		1	/* this header's FMAP minor version */
+#define FMAP_STRLEN		32	/* maximum length for strings, */
+					/* including null-terminator */
+
+enum fmap_flags {
+	FMAP_AREA_STATIC	= 1 << 0,
+	FMAP_AREA_COMPRESSED	= 1 << 1,
+	FMAP_AREA_RO		= 1 << 2,
+};
+
+/* Mapping of volatile and static regions in firmware binary */
+struct fmap_area {
+	uint32_t offset;                /* offset relative to base */
+	uint32_t size;                  /* size in bytes */
+	uint8_t  name[FMAP_STRLEN];     /* descriptive name */
+	uint16_t flags;                 /* flags for this area */
+}  __attribute__((packed));
+
+struct fmap {
+	uint8_t  signature[8];		/* "__FMAP__" (0x5F5F464D41505F5F) */
+	uint8_t  ver_major;		/* major version */
+	uint8_t  ver_minor;		/* minor version */
+	uint64_t base;			/* address of the firmware binary */
+	uint32_t size;			/* size of firmware binary in bytes */
+	uint8_t  name[FMAP_STRLEN];	/* name of this firmware binary */
+	uint16_t nareas;		/* number of areas described by
+					   fmap_areas[] below */
+	struct fmap_area areas[];
+} __attribute__((packed));
+
+
+/* coreboot specific function prototypes */
+const struct fmap *fmap_find(void);
+const struct fmap_area *find_fmap_area(const struct fmap *fmap,
+							const char name[]);
+int find_fmap_entry(const char name[], void **pointer);
+#endif	/* FLASHMAP_LIB_FMAP_H__*/
diff --git a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c
index 955d72f..6b3d7dc 100644
--- a/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c
+++ b/src/vendorcode/google/chromeos/vboot2/vboot_handoff.c
@@ -26,13 +26,13 @@
 #include <cbmem.h>
 #include <console/console.h>
 #include <console/vtxprintf.h>
-#include <fmap.h>
 #include <stdlib.h>
 #include <timestamp.h>
 #define NEED_VB20_INTERNALS  /* TODO: remove me! */
 #include <vb2_api.h>
 #include <vboot_struct.h>
 #include "../chromeos.h"
+#include "../fmap.h"
 #include "../vboot_handoff.h"
 #include "misc.h"
 



More information about the coreboot-gerrit mailing list