[coreboot-gerrit] Patch set updated for coreboot: 1f189cd New mechanism to define SRAM/memory map with automatic bounds checking

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Sat Apr 4 23:13:57 CEST 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9283

-gerrit

commit 1f189cd51cf22833d3d2cb632f9adeeaa72a0687
Author: Julius Werner <jwerner at chromium.org>
Date:   Wed Aug 20 15:29:56 2014 -0700

    New mechanism to define SRAM/memory map with automatic bounds checking
    
    This patch creates a new mechanism to define the static memory layout
    (primarily in SRAM) for a given board, superseding the brittle mass of
    Kconfigs that we were using before. The core part is a memlayout.ld file
    in the mainboard directory (although boards are expected to just include
    the SoC default in most cases), which is the primary linker script for
    all stages (though not rmodules for now). It uses preprocessor macros
    from <memlayout.h> to form a different valid linker script for all
    stages while looking like a declarative, boilerplate-free map of memory
    addresses to the programmer. Linker asserts will automatically guarantee
    that the defined regions cannot overlap. Stages are defined with a
    maximum size that will be enforced by the linker. The file serves to
    both define and document the memory layout, so that the documentation
    cannot go missing or out of date.
    
    The mechanism is implemented for all boards in the ARM, ARM64 and MIPS
    architectures, and should be extended onto all systems using SRAM in the
    future. The CAR/XIP environment on x86 has very different requirements
    and the layout is generally not as static, so it will stay like it is
    and be unaffected by this patch (save for aligning some symbol names for
    consistency and sharing the new common ramstage linker script include).
    
    BUG=None
    TEST=Booted normally and in recovery mode, checked suspend/resume and
    the CBMEM console on Falco, Blaze (both normal and vboot2), Pinky and
    Pit. Compiled Ryu, Storm and Urara, manually compared the disassemblies
    with ToT and looked for red flags.
    
    Change-Id: Ifd2276417f2036cbe9c056f17e42f051bcd20e81
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: f1e2028e7ebceeb2d71ff366150a37564595e614
    Original-Change-Id: I005506add4e8fcdb74db6d5e6cb2d4cb1bd3cda5
    Original-Signed-off-by: Julius Werner <jwerner at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/213370
---
 Makefile.inc                                    |   5 +
 src/arch/arm/Makefile.inc                       |  23 ++--
 src/arch/arm/armv4/bootblock.S                  |  20 +---
 src/arch/arm/armv7/bootblock.S                  |  20 +---
 src/arch/arm/armv7/mmu.c                        |   5 +-
 src/arch/arm/bootblock.ld                       |  60 -----------
 src/arch/arm/include/arch/header.ld             |  33 ++++++
 src/arch/arm/include/arch/memlayout.h           |  38 +++++++
 src/arch/arm/include/arch/stages.h              |   2 +-
 src/arch/arm/ramstage.ld                        | 134 ------------------------
 src/arch/arm/romstage.ld                        |  79 --------------
 src/arch/arm/stages.c                           |   8 +-
 src/arch/arm/verstage.ld                        |  66 ------------
 src/arch/arm64/Makefile.inc                     |   6 +-
 src/arch/arm64/bootblock.ld                     |  64 -----------
 src/arch/arm64/include/arch/header.ld           |  32 ++++++
 src/arch/arm64/include/arch/memlayout.h         |  35 +++++++
 src/arch/arm64/ramstage.ld                      | 119 ---------------------
 src/arch/arm64/romstage.ld                      |  87 ---------------
 src/arch/mips/Makefile.inc                      |  19 ++--
 src/arch/mips/bootblock.S                       |   6 +-
 src/arch/mips/bootblock.ld                      |  57 ----------
 src/arch/mips/include/arch/header.ld            |  32 ++++++
 src/arch/mips/include/arch/memlayout.h          |  31 ++++++
 src/arch/mips/ramstage.ld                       | 121 ---------------------
 src/arch/mips/romstage.ld                       |  72 -------------
 src/arch/mips/stages.c                          |   2 +-
 src/arch/x86/Makefile.inc                       |   2 +-
 src/arch/x86/boot/boot.c                        |   6 +-
 src/arch/x86/init/romstage.ld                   |   8 +-
 src/arch/x86/lib/c_start.S                      |   2 +-
 src/arch/x86/ramstage.ld                        | 117 ++-------------------
 src/console/Kconfig                             |  10 --
 src/cpu/x86/lapic/lapic_cpu_init.c              |   1 +
 src/cpu/x86/mp_init.c                           |   1 +
 src/cpu/x86/smm/smm.ld                          |   4 +-
 src/cpu/x86/smm/smm_tseg.ld                     |   2 +
 src/include/lib.h                               |   5 -
 src/include/memlayout.h                         | 105 +++++++++++++++++++
 src/include/symbols.h                           |  76 ++++++++++++++
 src/lib/Makefile.inc                            |   8 ++
 src/lib/bootblock.ld                            |  48 +++++++++
 src/lib/cbfs_spi.c                              |   5 +-
 src/lib/cbmem_console.c                         |   9 +-
 src/lib/loaders/load_and_run_payload.c          |   1 +
 src/lib/ramstage.ld                             | 114 ++++++++++++++++++++
 src/lib/rmodule.ld                              |  10 +-
 src/lib/romstage.ld                             |  58 ++++++++++
 src/lib/selfboot.c                              |   9 +-
 src/mainboard/emulation/qemu-armv7/Kconfig      |  35 -------
 src/mainboard/emulation/qemu-armv7/Makefile.inc |   4 +
 src/mainboard/emulation/qemu-armv7/media.c      |   3 +-
 src/mainboard/emulation/qemu-armv7/memlayout.ld |  47 +++++++++
 src/mainboard/google/daisy/Makefile.inc         |   4 +
 src/mainboard/google/daisy/mainboard.c          |  14 ++-
 src/mainboard/google/daisy/memlayout.ld         |   1 +
 src/mainboard/google/nyan/Kconfig               |   8 --
 src/mainboard/google/nyan/Makefile.inc          |   4 +
 src/mainboard/google/nyan/mainboard.c           |   5 +-
 src/mainboard/google/nyan/memlayout.ld          |   1 +
 src/mainboard/google/nyan/romstage.c            |  24 +++--
 src/mainboard/google/nyan_big/Kconfig           |   8 --
 src/mainboard/google/nyan_big/Makefile.inc      |   4 +
 src/mainboard/google/nyan_big/mainboard.c       |   5 +-
 src/mainboard/google/nyan_big/memlayout.ld      |   1 +
 src/mainboard/google/nyan_big/romstage.c        |  24 +++--
 src/mainboard/google/nyan_blaze/Kconfig         |   8 --
 src/mainboard/google/nyan_blaze/Makefile.inc    |   5 +
 src/mainboard/google/nyan_blaze/mainboard.c     |   5 +-
 src/mainboard/google/nyan_blaze/memlayout.ld    |   1 +
 src/mainboard/google/nyan_blaze/romstage.c      |  24 +++--
 src/mainboard/google/peach_pit/Makefile.inc     |   4 +
 src/mainboard/google/peach_pit/mainboard.c      |  14 ++-
 src/mainboard/google/peach_pit/memlayout.ld     |   1 +
 src/mainboard/google/rush/Makefile.inc          |   4 +
 src/mainboard/google/rush/memlayout.ld          |   1 +
 src/mainboard/google/rush_ryu/Makefile.inc      |   4 +
 src/mainboard/google/rush_ryu/memlayout.ld      |   1 +
 src/mainboard/google/storm/Kconfig              |   8 --
 src/mainboard/google/storm/Makefile.inc         |   4 +
 src/mainboard/google/storm/mainboard.c          |  11 +-
 src/mainboard/google/storm/memlayout.ld         |   1 +
 src/mainboard/google/urara/Kconfig              |   4 -
 src/mainboard/google/urara/Makefile.inc         |   3 +
 src/mainboard/google/urara/memlayout.ld         |   1 +
 src/mainboard/google/veyron_pinky/Kconfig       |   8 --
 src/mainboard/google/veyron_pinky/Makefile.inc  |   5 +
 src/mainboard/google/veyron_pinky/mainboard.c   |   5 +-
 src/mainboard/google/veyron_pinky/memlayout.ld  |   1 +
 src/mainboard/google/veyron_pinky/romstage.c    |  19 ++--
 src/soc/imgtec/pistachio/Kconfig                |  31 ------
 src/soc/imgtec/pistachio/Makefile.inc           |   2 +-
 src/soc/imgtec/pistachio/memlayout.ld           |  38 +++++++
 src/soc/nvidia/tegra124/Kconfig                 |  87 ---------------
 src/soc/nvidia/tegra124/Makefile.inc            |   2 +-
 src/soc/nvidia/tegra124/bootblock_asm.S         |  20 +---
 src/soc/nvidia/tegra124/cbfs.c                  |   4 +-
 src/soc/nvidia/tegra124/clock.c                 |   3 +-
 src/soc/nvidia/tegra124/memlayout.ld            |  48 +++++++++
 src/soc/nvidia/tegra124/sdram.c                 |   3 +-
 src/soc/nvidia/tegra124/soc.c                   |   7 +-
 src/soc/nvidia/tegra124/verstage.c              |   7 +-
 src/soc/nvidia/tegra132/Kconfig                 |  44 --------
 src/soc/nvidia/tegra132/Makefile.inc            |   2 +-
 src/soc/nvidia/tegra132/addressmap.c            |   3 +-
 src/soc/nvidia/tegra132/bootblock_asm.S         |  14 +--
 src/soc/nvidia/tegra132/cbfs.c                  |   4 +-
 src/soc/nvidia/tegra132/memlayout.ld            |  44 ++++++++
 src/soc/nvidia/tegra132/romstage_asm.S          |  14 +--
 src/soc/nvidia/tegra132/stack.S                 |  18 ++--
 src/soc/qualcomm/ipq806x/Kconfig                |  40 -------
 src/soc/qualcomm/ipq806x/Makefile.inc           |   2 +-
 src/soc/qualcomm/ipq806x/cbmem.c                |   4 +-
 src/soc/qualcomm/ipq806x/memlayout.ld           |  40 +++++++
 src/soc/qualcomm/ipq806x/soc.c                  |   7 +-
 src/soc/rockchip/rk3288/Kconfig                 |  73 -------------
 src/soc/rockchip/rk3288/media.c                 |  15 +--
 src/soc/rockchip/rk3288/memlayout.ld            |  48 +++++++++
 src/soc/samsung/exynos5250/Kconfig              |  55 ----------
 src/soc/samsung/exynos5250/alternate_cbfs.c     |  28 ++---
 src/soc/samsung/exynos5250/alternate_cbfs.h     |  12 ---
 src/soc/samsung/exynos5250/cpu.h                |   3 +-
 src/soc/samsung/exynos5250/memlayout.ld         |  46 ++++++++
 src/soc/samsung/exynos5420/Kconfig              |  74 -------------
 src/soc/samsung/exynos5420/alternate_cbfs.c     |  28 ++---
 src/soc/samsung/exynos5420/alternate_cbfs.h     |  12 ---
 src/soc/samsung/exynos5420/cpu.h                |   3 +-
 src/soc/samsung/exynos5420/memlayout.ld         |  49 +++++++++
 src/vendorcode/google/chromeos/Makefile.inc     |   2 +
 src/vendorcode/google/chromeos/chromeos.c       |   3 +-
 src/vendorcode/google/chromeos/memlayout.h      |  47 +++++++++
 src/vendorcode/google/chromeos/symbols.h        |  32 ++++++
 src/vendorcode/google/chromeos/verstage.ld      |  58 ++++++++++
 src/vendorcode/google/chromeos/verstub.c        |   7 +-
 134 files changed, 1412 insertions(+), 1782 deletions(-)

diff --git a/Makefile.inc b/Makefile.inc
index 57e22b9..d67bb5e 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -456,6 +456,11 @@ tools: $(objutil)/kconfig/conf $(objutil)/cbfstool/cbfstool $(objutil)/cbfstool/
 # Common recipes for all stages
 ###########################################################################
 
+# loadaddr can determine the load address of a stage, which may be needed for
+# platform-specific image headers (only works *after* the stage has been built)
+loadaddr = $(shell $(OBJDUMP_$(1)) -p $(objcbfs)/$(1).debug | \
+	     sed -ne '/LOAD/s/^.*vaddr 0x\([0-9a-fA-F]\{8\}\).*$$/0x\1/p')
+
 # find-substr is required for stages like romstage_null and romstage_xip to
 # eliminate the _* part of the string
 find-substr = $(word 1,$(subst _, ,$(1)))
diff --git a/src/arch/arm/Makefile.inc b/src/arch/arm/Makefile.inc
index cd6c4a4..73b4b34 100644
--- a/src/arch/arm/Makefile.inc
+++ b/src/arch/arm/Makefile.inc
@@ -63,11 +63,9 @@ bootblock-y += memmove.S
 bootblock-y += div0.c
 bootblock-y += clock.c
 
-bootblock-y += bootblock.ld
-
-$(objcbfs)/bootblock.debug: $(obj)/arch/arm/bootblock.bootblock.ld $$(bootblock-objs) $$(VERSTAGE_LIB)
+$(objcbfs)/bootblock.debug: $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.bootblock.ld $(obj)/ldoptions $$(bootblock-objs) $$(VERSTAGE_LIB)
 	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(LD_bootblock) --gc-sections -static -o $@ -L$(obj) -T $(obj)/arch/arm/bootblock.bootblock.ld --start-group $(bootblock-objs) --end-group
+	$(LD_bootblock) --gc-sections -static -o $@ -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.bootblock.ld --start-group $(bootblock-objs) --end-group
 
 endif # CONFIG_ARCH_BOOTBLOCK_ARM
 
@@ -75,9 +73,9 @@ endif # CONFIG_ARCH_BOOTBLOCK_ARM
 # verification stage
 ###############################################################################
 
-$(objcbfs)/verstage.debug: $$(verstage-objs) $(obj)/arch/arm/verstage.verstage.ld $$(VB2_LIB)
+$(objcbfs)/verstage.debug: $$(verstage-objs) $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.verstage.ld $$(VB2_LIB)
 	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(LD_verstage) --gc-sections -static -o $@ -L$(obj) -T $(obj)/arch/arm/verstage.verstage.ld --start-group $(verstage-objs) --end-group
+	$(LD_verstage) --gc-sections -static -o $@ -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.verstage.ld --start-group $(verstage-objs) --end-group
 
 verstage-y += div0.c
 verstage-y += eabi_compat.c
@@ -111,9 +109,9 @@ romstage-y += romstage.ld
 
 VBOOT_STUB_DEPS += $(obj)/arch/arm/eabi_compat.rmodules_arm.o
 
-$(objcbfs)/romstage.debug: $$(romstage-objs) $(obj)/arch/arm/romstage.romstage.ld
+$(objcbfs)/romstage.debug: $$(romstage-objs) $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.romstage.ld
 	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(LD_romstage) -nostdlib --gc-sections -static -o $@ -L$(obj) -T $(obj)/arch/arm/romstage.romstage.ld --start-group $(romstage-objs) --end-group
+	$(LD_romstage) -nostdlib --gc-sections -static -o $@ -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.romstage.ld --start-group $(romstage-objs) --end-group
 
 endif # CONFIG_ARCH_ROMSTAGE_ARM
 
@@ -133,20 +131,19 @@ ramstage-y += memset.S
 ramstage-y += memcpy.S
 ramstage-y += memmove.S
 ramstage-y += clock.c
+
 rmodules_arm-y += memset.S
 rmodules_arm-y += memcpy.S
 rmodules_arm-y += memmove.S
 rmodules_arm-y += eabi_compat.c
 ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c)
 
-ramstage-y += ramstage.ld
-
-$(objcbfs)/ramstage.debug: $$(ramstage-objs) $(obj)/arch/arm/ramstage.ramstage.ld
+$(objcbfs)/ramstage.debug: $$(ramstage-objs) $(obj)/arch/arm/ramstage.ld $(obj)/ldoptions
 	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(LD_ramstage) -nostdlib --gc-sections -o $@ -L$(obj) -T $(obj)/arch/arm/ramstage.ramstage.ld --start-group $(ramstage-objs) --end-group
+	$(LD_ramstage) -nostdlib --gc-sections -o $@ -L$(obj) -T $(obj)/arch/arm/ramstage.ld --start-group $(ramstage-objs) --end-group
 
 $(objgenerated)/ramstage.o: $(stages_o) $$(ramstage-objs)
 	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(LD_ramstage) -nostdlib --gc-sections -r -o $@ --start-group $(ramstage-objs) --end-group
+	$(LD_ramstage) -nostdlib --gc-sections -r -o $@ -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.ramstage.ld --start-group $(ramstage-objs) --end-group
 
 endif # CONFIG_ARCH_RAMSTAGE_ARM
diff --git a/src/arch/arm/armv4/bootblock.S b/src/arch/arm/armv4/bootblock.S
index e4d4302..1a30dda 100644
--- a/src/arch/arm/armv4/bootblock.S
+++ b/src/arch/arm/armv4/bootblock.S
@@ -44,10 +44,8 @@ ENTRY(_start)
 	 * Initialize the stack to a known value. This is used to check for
 	 * stack overflow later in the boot process.
 	 */
-	ldr	r0, .Stack
-	ldr	r1, .Stack_size
-	sub	r0, r0, r1
-	ldr	r1, .Stack
+	ldr	r0, =_stack
+	ldr	r1, =_estack
 	ldr	r2, =0xdeadbeef
 init_stack_loop:
 	str	r2, [r0]
@@ -57,7 +55,7 @@ init_stack_loop:
 
 /* Set stackpointer in internal RAM to call bootblock main() */
 call_bootblock:
-	ldr	sp, .Stack /* Set up stack pointer */
+	ldr	sp, =_estack /* Set up stack pointer */
 	ldr	r0,=0x00000000
 	 /*
 	  * The current design of cpu_info places the
@@ -75,15 +73,3 @@ call_bootblock:
 	 */
 	bl	main
 ENDPROC(_start)
-
-/* we do it this way because it's a 32-bit constant and
- * in some cases too far away to be loaded as just an offset
- * from IP
- */
-.align 2
-.Stack:
-	.word CONFIG_STACK_TOP
-.align 2
-/* create this size the same way we do in coreboot_ram.ld: top-bottom */
-.Stack_size:
-	.word CONFIG_STACK_TOP - CONFIG_STACK_BOTTOM
diff --git a/src/arch/arm/armv7/bootblock.S b/src/arch/arm/armv7/bootblock.S
index a15d167..b468e15 100644
--- a/src/arch/arm/armv7/bootblock.S
+++ b/src/arch/arm/armv7/bootblock.S
@@ -62,10 +62,8 @@ ENTRY(_thumb_start)
 	 * Initialize the stack to a known value. This is used to check for
 	 * stack overflow later in the boot process.
 	 */
-	ldr	r0, .Stack
-	ldr	r1, .Stack_size
-	sub	r0, r0, r1
-	ldr	r1, .Stack
+	ldr	r0, =_stack
+	ldr	r1, =_estack
 	ldr	r2, =0xdeadbeef
 init_stack_loop:
 	str	r2, [r0]
@@ -75,7 +73,7 @@ init_stack_loop:
 
 /* Set stackpointer in internal RAM to call bootblock main() */
 call_bootblock:
-	ldr	sp, .Stack /* Set up stack pointer */
+	ldr	sp, =_estack /* Set up stack pointer */
 	ldr	r0,=0x00000000
 	 /*
 	  * The current design of cpu_info places the struct at the top of the
@@ -89,15 +87,3 @@ wait_for_interrupt:
 	wfi
 	mov	pc, lr			@ back to my caller
 ENDPROC(_thumb_start)
-
-/* we do it this way because it's a 32-bit constant and
- * in some cases too far away to be loaded as just an offset
- * from IP
- */
-.align 2
-.Stack:
-	.word CONFIG_STACK_TOP
-.align 2
-/* create this size the same way we do in coreboot_ram.ld: top-bottom */
-.Stack_size:
-	.word CONFIG_STACK_TOP - CONFIG_STACK_BOTTOM
diff --git a/src/arch/arm/armv7/mmu.c b/src/arch/arm/armv7/mmu.c
index bd12946..e9c6815 100644
--- a/src/arch/arm/armv7/mmu.c
+++ b/src/arch/arm/armv7/mmu.c
@@ -31,6 +31,7 @@
 #include <config.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <symbols.h>
 
 #include <cbmem.h>
 #include <console/console.h>
@@ -90,7 +91,7 @@ typedef uint32_t pmd_t;
 static const unsigned int denom = 1;
 #endif	/* CONFIG_ARM_LPAE */
 
-static pmd_t *const ttb_buff = (pmd_t *)CONFIG_TTB_BUFFER;
+static pmd_t *const ttb_buff = (pmd_t *)_ttb;
 
 /*
  * mask/shift/size for pages and blocks
@@ -186,7 +187,7 @@ void mmu_config_range(unsigned long start_mb, unsigned long size_mb,
 void mmu_init(void)
 {
         if (CONFIG_ARM_LPAE) {
-                pgd_t *const pgd_buff = (pgd_t*)(CONFIG_TTB_BUFFER + 16*KiB);
+                pgd_t *const pgd_buff = (pgd_t*)(_ttb + 16*KiB);
                 pmd_t *pmd = ttb_buff;
                 int i;
 
diff --git a/src/arch/arm/bootblock.ld b/src/arch/arm/bootblock.ld
deleted file mode 100644
index 091e3eb..0000000
--- a/src/arch/arm/bootblock.ld
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2006 Advanced Micro Devices, Inc.
- * Copyright (C) 2008-2010 coresystems GmbH
- *
- * 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
- */
-
-/* We use ELF as output format. So that we can debug the code in some form. */
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-ENTRY(_start)
-SECTIONS
-{
-	. = CONFIG_BOOTBLOCK_BASE;
-
-	.bootblock . : {
-		*(.text._start);
-		KEEP(*(.id));
-		*(.text);
-		*(.text.*);
-		*(.rodata);
-		*(.rodata.*);
-		*(.data);
-		*(.data.*);
-		*(.bss);
-		*(.bss.*);
-		*(.sbss);
-		*(.sbss.*);
-		_end = .;
-	} : to_load = 0xff
-
-	preram_cbmem_console = CONFIG_CONSOLE_PRERAM_BUFFER_BASE;
-
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.comment.*)
-		*(.note.*)
-		*(.ARM.*)
-	}
-}
diff --git a/src/arch/arm/include/arch/header.ld b/src/arch/arm/include/arch/header.ld
new file mode 100644
index 0000000..2138c77
--- /dev/null
+++ b/src/arch/arm/include/arch/header.ld
@@ -0,0 +1,33 @@
+/*
+ * 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
+ */
+
+/* We use ELF as output format. So that we can debug the code in some form. */
+OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
+OUTPUT_ARCH(arm)
+
+PHDRS
+{
+	to_load PT_LOAD;
+}
+
+#ifdef __BOOTBLOCK__
+ENTRY(_start)
+#else
+ENTRY(stage_entry)
+#endif
diff --git a/src/arch/arm/include/arch/memlayout.h b/src/arch/arm/include/arch/memlayout.h
new file mode 100644
index 0000000..9f5b383
--- /dev/null
+++ b/src/arch/arm/include/arch/memlayout.h
@@ -0,0 +1,38 @@
+/*
+ * 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
+ */
+
+/* This file contains macro definitions for memlayout.ld linker scripts. */
+
+#ifndef __ARCH_MEMLAYOUT_H
+#define __ARCH_MEMLAYOUT_H
+
+#define TTB(addr, size) \
+	REGION(ttb, addr, size, 16K) \
+	_ = ASSERT(size >= 16K + IS_ENABLED(CONFIG_ARM_LPAE) * 32, \
+		"TTB must be 16K (+ 32 for LPAE)!");
+
+/* ARM stacks need 8-byte alignment and stay in one place through ramstage. */
+#define STACK(addr, size) REGION(stack, addr, size, 8)
+
+#define DMA_COHERENT(addr, size) \
+	REGION(dma_coherent, addr, size, (1 + IS_ENABLED(CONFIG_ARM_LPAE)) * 1M) \
+	_ = ASSERT(size % ((1 + IS_ENABLED(CONFIG_ARM_LPAE)) * 1M) == 0, \
+		"DMA coherency buffer must fit exactly in full superpages!");
+
+#endif /* __ARCH_MEMLAYOUT_H */
diff --git a/src/arch/arm/include/arch/stages.h b/src/arch/arm/include/arch/stages.h
index 39fed99..1a0dcc1 100644
--- a/src/arch/arm/include/arch/stages.h
+++ b/src/arch/arm/include/arch/stages.h
@@ -22,7 +22,7 @@
 
 extern void main(void);
 
-void stage_entry(void) __attribute__((section(".text.stage_entry.arm")));
+void stage_entry(void);
 void stage_exit(void *);
 
 #endif
diff --git a/src/arch/arm/ramstage.ld b/src/arch/arm/ramstage.ld
deleted file mode 100644
index 7daa8cb..0000000
--- a/src/arch/arm/ramstage.ld
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *	Memory map:
- *
- *	CONFIG_RAMSTAGE_BASE	: text segment
- *				: rodata segment
- *				: data segment
- *				: bss segment
- *				: stack
- *				: heap
- */
-/*
- * Bootstrap code for the STPC Consumer
- * Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
- */
-
-/*
- *	Written by Johan Rydberg, based on work by Daniel Kahlin.
- *      Rewritten by Eric Biederman
- *  2005.12 yhlu add ramstage cross the vga font buffer handling
- */
-
-ENTRY(stage_entry)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-SECTIONS
-{
-	. = CONFIG_RAMSTAGE_BASE;
-	/* First we place the code and read only data (typically const declared).
-	 * This could theoretically be placed in rom.
-	 */
-	.text : {
-		_text = .;
-		_start = .;
-		*(.text.stage_entry.arm);
-		*(.text);
-		*(.text.*);
-		. = ALIGN(16);
-		_etext = .;
-	} : to_load
-
-	.ctors : {
-		. = ALIGN(0x100);
-		__CTOR_LIST__ = .;
-		KEEP(*(.ctors));
-		LONG(0);
-		__CTOR_END__ = .;
-	}
-
-	.rodata : {
-		_rodata = .;
-		. = ALIGN(4);
-		pci_drivers = . ;
-		KEEP(*(.rodata.pci_driver));
-		epci_drivers = . ;
-		cpu_drivers = . ;
-		KEEP(*(.rodata.cpu_driver));
-		ecpu_drivers = . ;
-		_bs_init_begin = .;
-		KEEP(*(.bs_init));
-		LONG(0);
-		_bs_init_end = .;
-		*(.rodata)
-		*(.rodata.*)
-		/* kevinh/Ispiri - Added an align, because the objcopy tool
-		 * incorrectly converts sections that are not long word aligned.
-		 */
-		 . = ALIGN(4);
-
-		_erodata = .;
-	}
-	/* After the code we place initialized data (typically initialized
-	 * global variables). This gets copied into ram by startup code.
-	 * __data_start and __data_end shows where in ram this should be placed,
-	 * whereas __data_loadstart and __data_loadend shows where in rom to
-	 * copy from.
-	 */
-	.data : {
-		_data = .;
-		*(.data)
-		*(.data.*)
-		_edata = .;
-	}
-
-	/* bss does not contain data, it is just a space that should be zero
-	 * initialized on startup. (typically uninitialized global variables)
-	 * crt0.S fills between _bss and _ebss with zeroes.
-	 */
-	.bss . : {
-		_bss = .;
-		*(.bss)
-		*(.bss.*)
-		*(.sbss)
-		*(.sbss.*)
-		_ebss = .;
-	}
-	_end = .;
-
-	/* coreboot really "ends" here. Only heap and stack are placed after
-	 * this line.
-	 */
-
-        .heap . : {
-			_heap = .;
-                /* Reserve CONFIG_HEAP_SIZE bytes for the heap */
-                . = CONFIG_HEAP_SIZE ;
-                . = ALIGN(4);
-			_eheap = .;
-        }
-
-	/* The ram segment. This includes all memory used by the memory
-	 * resident copy of coreboot, except the tables that are produced on
-	 * the fly, but including stack and heap.
-	 */
-	_ram_seg = _text;
-	_eram_seg = _eheap;
-
-	/* The stack lives in SRAM in a different location, so keep
-	 * it out of ram_seg
-	 */
-	_stack = CONFIG_STACK_BOTTOM;
-	_estack = CONFIG_STACK_TOP;
-
-	/* Discard the sections we don't need/want */
-
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.note.*)
-	}
-}
diff --git a/src/arch/arm/romstage.ld b/src/arch/arm/romstage.ld
deleted file mode 100644
index d107687..0000000
--- a/src/arch/arm/romstage.ld
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *	Memory map:
- *
- *	CONFIG_ROMSTAGE_BASE	: text segment
- *				: rodata segment
- *				: data segment
- *				: bss segment
- *				: stack
- *				: heap
- */
-/*
- * Bootstrap code for the STPC Consumer
- * Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
- */
-
-/*
- *	Written by Johan Rydberg, based on work by Daniel Kahlin.
- *      Rewritten by Eric Biederman
- *  2005.12 yhlu add ramstage cross the vga font buffer handling
- */
-
-/* We use ELF as output format. So that we can debug the code in some form. */
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-
-ENTRY(stage_entry)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-SECTIONS
-{
-	. = CONFIG_ROMSTAGE_BASE;
-
-	.romtext . : {
-		_start = .;
-		*(.text.stage_entry.arm);
-		*(.text.startup);
-		*(.text);
-		*(.text.*);
-	} : to_load
-
-	.romdata . : {
-		*(.rodata);
-		*(.rodata.*);
-		*(.data);
-		*(.data.*);
-		. = ALIGN(8);
-	}
-
-	/* bss does not contain data, it is just a space that should be zero
-	 * initialized on startup. (typically uninitialized global variables)
-	 * crt0.S fills between _bss and _ebss with zeroes.
-	 */
-	.bss . : {
-		. = ALIGN(8);
-		_bss = .;
-		*(.bss)
-		*(.bss.*)
-		*(.sbss)
-		*(.sbss.*)
-		_ebss = .;
-	}
-
-	_end = .;
-
-	preram_cbmem_console = CONFIG_CONSOLE_PRERAM_BUFFER_BASE;
-
-	/* Discard the sections we don't need/want */
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.comment.*)
-		*(.note.*)
-		*(.eh_frame);
-	}
-}
diff --git a/src/arch/arm/stages.c b/src/arch/arm/stages.c
index 47f13fa..11acc9b 100644
--- a/src/arch/arm/stages.c
+++ b/src/arch/arm/stages.c
@@ -22,10 +22,10 @@
  * execution (bootblock entry and ramstage exit will depend on external
  * loading).
  *
- * Entry points must be placed at the location the previous stage jumps
- * to (the lowest address in the stage image). This is done by giving
- * stage_entry() its own section in .text and placing it first in the
- * linker script.
+ * Entry points should be set in the linker script and honored by CBFS,
+ * so text section layout shouldn't matter. Still, it doesn't hurt to put
+ * stage_entry first (which XXXstage.ld will do automatically through the
+ * .text.stage_entry section created by -ffunction-sections).
  */
 
 #include <arch/stages.h>
diff --git a/src/arch/arm/verstage.ld b/src/arch/arm/verstage.ld
deleted file mode 100644
index 88d4bc8..0000000
--- a/src/arch/arm/verstage.ld
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *	Memory map:
- *
- *	CONFIG_VERSTAGE_BASE	: text segment
- *				: rodata segment
- *				: data segment
- *				: bss segment
- */
-
-/* We use ELF as output format. So that we can debug the code in some form. */
-OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
-OUTPUT_ARCH(arm)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-ENTRY(stage_entry)
-
-SECTIONS
-{
-	. = CONFIG_VERSTAGE_BASE;
-
-	.romtext . : {
-		_start = .;
-		*(.text.stage_entry.arm);
-		*(.text.startup);
-		*(.text);
-		*(.text.*);
-	} : to_load
-
-	.romdata . : {
-		*(.rodata);
-		*(.rodata.*);
-		*(.data);
-		*(.data.*);
-		. = ALIGN(8);
-	}
-
-	/* bss does not contain data, it is just a space that should be zero
-	 * initialized on startup. (typically uninitialized global variables)
-	 */
-	.bss . : {
-		. = ALIGN(8);
-		_bss = .;
-		*(.bss)
-		*(.bss.*)
-		*(.sbss)
-		*(.sbss.*)
-		_ebss = .;
-	}
-
-	_end = .;
-
-	preram_cbmem_console = CONFIG_CONSOLE_PRERAM_BUFFER_BASE;
-
-	/* Discard the sections we don't need/want */
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.comment.*)
-		*(.note.*)
-		*(.eh_frame);
-	}
-}
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc
index 661e673..d3bc0ee 100644
--- a/src/arch/arm64/Makefile.inc
+++ b/src/arch/arm64/Makefile.inc
@@ -72,7 +72,7 @@ bootblock-y += ../../lib/memmove.c
 
 $(objcbfs)/bootblock.debug: $(src)/arch/arm64/bootblock.ld $$(bootblock-objs) $(obj)/config.h
 	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(LD_bootblock) --gc-sections -static -o $@ -L$(obj) --start-group $(bootblock-objs) --end-group -T $(src)/arch/arm64/bootblock.ld
+	$(LD_bootblock) --gc-sections -static -o $@ -L$(obj) --start-group $(bootblock-objs) --end-group -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.bootblock.ld
 
 endif # CONFIG_ARCH_BOOTBLOCK_ARM64
 
@@ -104,7 +104,7 @@ VBOOT_STUB_DEPS += $(obj)/arch/arm/eabi_compat.rmodules_arm64.o
 
 $(objcbfs)/romstage.debug: $$(romstage-objs) $(src)/arch/arm64/romstage.ld
 	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(LD_romstage) -nostdlib --gc-sections -static -o $@ -L$(obj) --start-group $(romstage-objs) --end-group -T $(src)/arch/arm64/romstage.ld
+	$(LD_romstage) -nostdlib --gc-sections -static -o $@ -L$(obj) --start-group $(romstage-objs) --end-group -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.romstage.ld
 
 endif # CONFIG_ARCH_ROMSTAGE_ARM64
 
@@ -151,6 +151,6 @@ $(objcbfs)/ramstage.debug: $$(ramstage-objs) $(src)/arch/arm64/ramstage.ld
 
 $(objgenerated)/ramstage.o: $(stages_o) $$(ramstage-objs)
 	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(LD_ramstage) -nostdlib --gc-sections -r -o $@ --start-group $(ramstage-objs) --end-group
+	$(LD_ramstage) -nostdlib --gc-sections -r -o $@ --start-group $(ramstage-objs) --end-group -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.ramstage.ld
 
 endif # CONFIG_ARCH_RAMSTAGE_ARM64
diff --git a/src/arch/arm64/bootblock.ld b/src/arch/arm64/bootblock.ld
deleted file mode 100644
index 98c6454..0000000
--- a/src/arch/arm64/bootblock.ld
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2006 Advanced Micro Devices, Inc.
- * Copyright (C) 2008-2010 coresystems GmbH
- *
- * 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
- */
-
-/* We use ELF as output format. So that we can debug the code in some form. */
-OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
-OUTPUT_ARCH(aarch64)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-ENTRY(stage_entry)
-TARGET(binary)
-SECTIONS
-{
-	. = CONFIG_BOOTBLOCK_BASE;
-
-	.bootblock . : {
-		*(.text.stage_entry);
-		KEEP(*(.id));
-		*(.text);
-		*(.text.*);
-		*(.rodata);
-		*(.rodata.*);
-		*(.data);
-		*(.data.*);
-		*(.bss);
-		*(.bss.*);
-		*(.sbss);
-		*(.sbss.*);
-	} : to_load = 0xff
-
-	/* arm64 chipsets need to define CONFIG_BOOTBLOCK_STACK_(TOP|BOTTOM) */
-	_stack = CONFIG_BOOTBLOCK_STACK_BOTTOM;
-	_estack = CONFIG_BOOTBLOCK_STACK_TOP;
-
-	preram_cbmem_console = CONFIG_CONSOLE_PRERAM_BUFFER_BASE;
-
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.comment.*)
-		*(.note.*)
-		*(.ARM.*)
-	}
-}
diff --git a/src/arch/arm64/include/arch/header.ld b/src/arch/arm64/include/arch/header.ld
new file mode 100644
index 0000000..bb32a93
--- /dev/null
+++ b/src/arch/arm64/include/arch/header.ld
@@ -0,0 +1,32 @@
+/*
+ * 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
+ */
+
+/* We use ELF as output format. So that we can debug the code in some form. */
+OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
+OUTPUT_ARCH(aarch64)
+
+PHDRS
+{
+	to_load PT_LOAD;
+}
+
+#ifdef __BOOTBLOCK__
+TARGET(binary)
+#endif
+ENTRY(stage_entry)
diff --git a/src/arch/arm64/include/arch/memlayout.h b/src/arch/arm64/include/arch/memlayout.h
new file mode 100644
index 0000000..328156b
--- /dev/null
+++ b/src/arch/arm64/include/arch/memlayout.h
@@ -0,0 +1,35 @@
+/*
+ * 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
+ */
+
+/* This file contains macro definitions for memlayout.ld linker scripts. */
+
+#ifndef __ARCH_MEMLAYOUT_H
+#define __ARCH_MEMLAYOUT_H
+
+/* TODO: add SRAM TTB region and figure out the correct size/alignment for it */
+
+/* ARM64 stacks need 16-byte alignment. The ramstage will set up its own stacks
+ * in BSS, so this is only used for the SRAM stages. */
+#ifdef __PRE_RAM__
+#define STACK(addr, size) REGION(stack, addr, size, 16)
+#else
+#define STACK(addr, size) REGION(preram_stack, addr, size, 16)
+#endif
+
+#endif /* __ARCH_MEMLAYOUT_H */
diff --git a/src/arch/arm64/ramstage.ld b/src/arch/arm64/ramstage.ld
deleted file mode 100644
index 7022e4f..0000000
--- a/src/arch/arm64/ramstage.ld
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- *	Memory map:
- *
- *	CONFIG_RAMBASE		: text segment
- *				: rodata segment
- *				: data segment
- *				: bss segment
- *				: stack
- *				: heap
- */
-/*
- * Copyright 2013 Google Inc.
- * Bootstrap code for the STPC Consumer
- * Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
- */
-
-/*
- *	Written by Johan Rydberg, based on work by Daniel Kahlin.
- *      Rewritten by Eric Biederman
- *  2005.12 yhlu add ramstage cross the vga font buffer handling
- */
-
-ENTRY(stage_entry)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-SECTIONS
-{
-	. = CONFIG_RAMSTAGE_BASE;
-
-	.text : {
-		_text = .;
-		_start = .;
-		*(.text.stage_entry);
-		*(.text);
-		*(.text.*);
-		. = ALIGN(16);
-		_etext = .;
-	} : to_load
-
-	.ctors : {
-		. = ALIGN(0x100);
-		__CTOR_LIST__ = .;
-		KEEP(*(.ctors));
-		LONG(0);
-		LONG(0);
-		__CTOR_END__ = .;
-	}
-
-	.rodata : {
-		. = ALIGN(64);
-		_rodata = .;
-		console_drivers = .;
-		KEEP(*(.rodata.console_drivers));
-		econsole_drivers = . ;
-		. = ALIGN(64);
-		pci_drivers = . ;
-		KEEP(*(.rodata.pci_driver));
-		epci_drivers = . ;
-		cpu_drivers = . ;
-		KEEP(*(.rodata.cpu_driver));
-		ecpu_drivers = . ;
-		_bs_init_begin = .;
-		KEEP(*(.bs_init));
-		LONG(0);
-		LONG(0);
-		_bs_init_end = .;
-		. = ALIGN(64);
-		*(.rodata)
-		*(.rodata.*)
-		_erodata = .;
-	}
-
-	.data : {
-		 . = ALIGN(64);
-		_data = .;
-		*(.data)
-		*(.data.*)
-		 . = ALIGN(64);
-		_edata = .;
-	}
-
-	.bss : {
-		 . = ALIGN(64);
-		_bss = .;
-		*(.bss)
-		*(.bss.*)
-		*(.sbss.*)
-		*(COMMON)
-		. = ALIGN(64);
-		_ebss = .;
-	}
-
-	.heap : {
-		_heap = .;
-		/* Reserve CONFIG_HEAP_SIZE bytes for the heap */
-		. = . + CONFIG_HEAP_SIZE ;
-		. = ALIGN(64);
-		_eheap = .;
-	}
-
-	/* The ram segment. This includes all memory used by the memory
-	 * resident copy of coreboot, except the tables that are produced on
-	 * the fly, but including stack and heap.
-	 */
-	_ram_seg = _text;
-	_eram_seg = _eheap;
-
-	/* Discard the sections we don't need/want */
-
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.note.*)
-	}
-}
diff --git a/src/arch/arm64/romstage.ld b/src/arch/arm64/romstage.ld
deleted file mode 100644
index fef2ac5..0000000
--- a/src/arch/arm64/romstage.ld
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- *	Memory map:
- *
- *	CONFIG_ROMSTAGE_BASE	: text segment
- *				: rodata segment
- *				: data segment
- *				: bss segment
- *				: stack
- *				: heap
- */
-/*
- * Bootstrap code for the STPC Consumer
- * Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
- */
-
-/*
- *	Written by Johan Rydberg, based on work by Daniel Kahlin.
- *      Rewritten by Eric Biederman
- *  2005.12 yhlu add ramstage cross the vga font buffer handling
- */
-
-/* We use ELF as output format. So that we can debug the code in some form. */
-OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
-OUTPUT_ARCH(aarch64)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-ENTRY(stage_entry)
-
-SECTIONS
-{
-	. = CONFIG_ROMSTAGE_BASE;
-
-	.romtext . : {
-		_start = .;
-		*(.text.stage_entry);
-		*(.text.startup);
-		*(.text);
-		*(.text.*);
-	} : to_load
-
-	.romdata . : {
-		*(.rodata);
-		*(.rodata.*);
-		*(.machine_param);
-		*(.data);
-		*(.data.*);
-		. = ALIGN(8);
-		_erom = .;
-	}
-
-	__image_copy_end = .;
-
-	/* bss does not contain data, it is just a space that should be zero
-	 * initialized on startup. (typically uninitialized global variables)
-	 * crt0.S fills between _bss and _ebss with zeroes.
-	 */
-	.bss . : {
-		. = ALIGN(8);
-		_bss = .;
-		*(.bss)
-		*(.bss.*)
-		*(.sbss)
-		*(.sbss.*)
-		_ebss = .;
-	}
-
-	_end = .;
-
-	/* arm64 chipsets need to define CONFIG_ROMSTAGE_STACK_(TOP|BOTTOM) */
-	_stack = CONFIG_ROMSTAGE_STACK_BOTTOM;
-	_estack = CONFIG_ROMSTAGE_STACK_TOP;
-
-	preram_cbmem_console = CONFIG_CONSOLE_PRERAM_BUFFER_BASE;
-
-	/* Discard the sections we don't need/want */
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.comment.*)
-		*(.note.*)
-		*(.eh_frame);
-	}
-}
diff --git a/src/arch/mips/Makefile.inc b/src/arch/mips/Makefile.inc
index 969a03d..ca8519b 100644
--- a/src/arch/mips/Makefile.inc
+++ b/src/arch/mips/Makefile.inc
@@ -43,17 +43,15 @@ bootblock-y += ../../lib/memcpy.c
 bootblock-y += ../../lib/memmove.c
 bootblock-y += ../../lib/memset.c
 
-bootblock-y += bootblock.ld
-
 # Much of the assembly code is generated by the compiler, and may contain
 # terms which the preprocessor will happily go on to replace. For example
 # "mips" would be replaced with "1". Clear all the built in definitions to
 # prevent that.
 bootblock-S-ccopts += -undef
 
-$(objcbfs)/bootblock.debug:  $(obj)/arch/mips/bootblock.bootblock.ld $$(bootblock-objs) $(obj)/config.h
+$(objcbfs)/bootblock.debug: $$(bootblock-objs) $(obj)/config.h $(obj)/ldoptions $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.bootblock.ld
 	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(LD_bootblock) --gc-sections -static -o $@ -L$(obj) -T $(obj)/arch/mips/bootblock.bootblock.ld --start-group $(bootblock-objs) --end-group
+	$(LD_bootblock) --gc-sections -static -o $@ -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.bootblock.ld --start-group $(bootblock-objs) --end-group
 
 endif # CONFIG_ARCH_BOOTBLOCK_MIPS
 
@@ -71,11 +69,9 @@ romstage-y += ../../lib/memcpy.c
 romstage-y += ../../lib/memmove.c
 romstage-y += ../../lib/memset.c
 
-romstage-y += romstage.ld
-
-$(objcbfs)/romstage.debug: $$(romstage-objs) $(obj)/arch/mips/romstage.romstage.ld
+$(objcbfs)/romstage.debug: $$(romstage-objs) $(obj)/ldoptions $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.romstage.ld
 	@printf "    LINK       $(subst $(obj)/,,$(@))\n"
-	$(LD_romstage) --gc-sections -static -o $@ -L$(obj) -T $(obj)/arch/mips/romstage.romstage.ld --start-group $(romstage-objs) --end-group
+	$(LD_romstage) --gc-sections -static -o $@ -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.romstage.ld --start-group $(romstage-objs) --end-group
 
 endif # CONFIG_ARCH_ROMSTAGE_MIPS
 
@@ -93,12 +89,11 @@ ramstage-y += timer.c
 ramstage-y += ../../lib/memcpy.c
 ramstage-y += ../../lib/memmove.c
 ramstage-y += ../../lib/memset.c
-ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c)
 
-ramstage-y += ramstage.ld
+ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c)
 
-$(objcbfs)/ramstage.debug: $$(ramstage-objs) $(obj)/arch/mips/ramstage.ramstage.ld
+$(objcbfs)/ramstage.debug: $$(ramstage-objs) $(obj)/ldoptions $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.ramstage.ld
 	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(LD_ramstage) --gc-sections -static -o $@ -L$(obj) -T $(obj)/arch/mips/ramstage.ramstage.ld --start-group $(ramstage-objs) --end-group
+	$(LD_ramstage) --gc-sections -static -o $@ -L$(obj) -T $(obj)/mainboard/$(MAINBOARDDIR)/memlayout.ramstage.ld --start-group $(ramstage-objs) --end-group
 
 endif # CONFIG_ARCH_RAMSTAGE_MIPS
diff --git a/src/arch/mips/bootblock.S b/src/arch/mips/bootblock.S
index f369e00..8899fe0 100644
--- a/src/arch/mips/bootblock.S
+++ b/src/arch/mips/bootblock.S
@@ -19,17 +19,17 @@
 
 .set	noreorder	/* Prevent assembler from "optimizing" this code. */
 
-.section ".start", "ax", %progbits
+.section ".text._start", "ax", %progbits
 .globl _start
 _start:
 	/* Set the stack pointer */
-	li	$sp, CONFIG_BOOTBLOCK_STACK_TOP
+	la	$sp, _estack
 
 	/*
 	 * Initialise the stack to a known value, used later to check for
 	 * overflow.
 	 */
-	li	$t0, CONFIG_BOOTBLOCK_STACK_BOTTOM
+	la	$t0, _stack
 	addi	$t1, $sp, -4
 	li	$t2, 0xdeadbeef
 1:	sw	$t2, 0($t0)
diff --git a/src/arch/mips/bootblock.ld b/src/arch/mips/bootblock.ld
deleted file mode 100644
index 3721f85..0000000
--- a/src/arch/mips/bootblock.ld
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2006 Advanced Micro Devices, Inc.
- * Copyright (C) 2008-2010 coresystems GmbH
- * Copyright (C) 2014 Imagination Technologies
- *
- * 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
- */
-
-OUTPUT_ARCH(mips)
-
-ENTRY(_start)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-preram_cbmem_console = CONFIG_CBMEM_CONSOLE_PRERAM_BASE;
-
-SECTIONS
-{
-	. = CONFIG_BOOTBLOCK_BASE;
-
-	/* This section might be better named .setup */
-	.rom : {
-		_rom = .;
-		*(.start);
-		*(.id);
-		*(.text);
-		*(.text.*);
-		*(.rom.text);
-		*(.rom.data);
-		*(.rom.data.*);
-		*(.rodata.*);
-		_erom = .;
-	} : to_load = 0xff
-
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.comment.*)
-		*(.note.*)
-	}
-}
diff --git a/src/arch/mips/include/arch/header.ld b/src/arch/mips/include/arch/header.ld
new file mode 100644
index 0000000..0c7d7a1
--- /dev/null
+++ b/src/arch/mips/include/arch/header.ld
@@ -0,0 +1,32 @@
+/*
+ * 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
+ */
+
+/* We use ELF as output format. So that we can debug the code in some form. */
+OUTPUT_ARCH(mips)
+
+PHDRS
+{
+	to_load PT_LOAD;
+}
+
+#ifdef __BOOTBLOCK__
+ENTRY(_start)
+#else
+ENTRY(stage_entry)
+#endif
diff --git a/src/arch/mips/include/arch/memlayout.h b/src/arch/mips/include/arch/memlayout.h
new file mode 100644
index 0000000..4cbbe1d
--- /dev/null
+++ b/src/arch/mips/include/arch/memlayout.h
@@ -0,0 +1,31 @@
+/*
+ * 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
+ */
+
+/* This file contains macro definitions for memlayout.ld linker scripts. */
+
+#ifndef __ARCH_MEMLAYOUT_H
+#define __ARCH_MEMLAYOUT_H
+
+/* MIPS stacks need 8-byte alignment and stay in one place through ramstage. */
+/* TODO: Double-check that that's the correct alignment for our ABI. */
+#define STACK(addr, size) REGION(stack, addr, size, 8)
+
+/* TODO: Need to add DMA_COHERENT region like on ARM? */
+
+#endif /* __ARCH_MEMLAYOUT_H */
diff --git a/src/arch/mips/ramstage.ld b/src/arch/mips/ramstage.ld
deleted file mode 100644
index 4052444..0000000
--- a/src/arch/mips/ramstage.ld
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2014 Imagination Technologies
- *
- * Based on src/arch/arm/ramstage.ld:
- *   Written by Johan Rydberg, based on work by Daniel Kahlin.
- *   Rewritten by Eric Biederman
- *
- * 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
- */
-
-OUTPUT_ARCH(mips)
-
-ENTRY(stage_entry)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-SECTIONS
-{
-	. = CONFIG_SYS_SDRAM_BASE;
-
-	.text : {
-		_text = .;
-		_start = .;
-		*(.text.stage_entry.mips);
-		*(.text);
-		*(.text.*);
-		. = ALIGN(16);
-		_etext = .;
-	} : to_load
-
-	.ctors : {
-		. = ALIGN(0x100);
-		__CTOR_LIST__ = .;
-		*(.ctors);
-		LONG(0);
-		__CTOR_END__ = .;
-	}
-
-	.rodata : {
-		_rodata = .;
-		. = ALIGN(4);
-		console_drivers = .;
-		KEEP(*(.rodata.console_drivers));
-		econsole_drivers = . ;
-		. = ALIGN(4);
-		pci_drivers = . ;
-		KEEP(*(.rodata.pci_driver));
-		epci_drivers = . ;
-		cpu_drivers = . ;
-		KEEP(*(.rodata.cpu_driver));
-		ecpu_drivers = . ;
-		_bs_init_begin = .;
-		KEEP(*(.bs_init));
-		_bs_init_end = .;
-		*(.rodata)
-		*(.rodata.*)
-		 . = ALIGN(4);
-		_erodata = .;
-	}
-
-	.data : {
-		_data = .;
-		*(.data)
-		_edata = .;
-	}
-
-	/* bss will be cleared by cbfs_load_stage */
-	_bss = .;
-	.bss . : {
-		*(.bss)
-		*(.sbss)
-		*(COMMON)
-	}
-	_ebss = .;
-	_end = .;
-
-	/*
-	 * coreboot from the perspective of the loader really "ends"
-	 * here. Only symbols are placed after this.
-	 */
-
-        _heap = .;
-        _eheap = . + CONFIG_HEAP_SIZE;
-
-	_stack = CONFIG_STACK_BOTTOM;
-	_estack = CONFIG_STACK_TOP;
-
-	/*
-	 * The ram segment. This includes all memory used by the memory
-	 * resident copy of coreboot, except the tables that are produced on
-	 * the fly, but including stack and heap.
-	 */
-	_ram_seg = _text;
-	_eram_seg = _eheap;
-
-	/* Discard the sections we don't need/want */
-
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.note.*)
-	}
-}
diff --git a/src/arch/mips/romstage.ld b/src/arch/mips/romstage.ld
deleted file mode 100644
index 8964285..0000000
--- a/src/arch/mips/romstage.ld
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright (C) 2014 Imagination Technologies
- *
- * 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
- */
-
-OUTPUT_ARCH(mips)
-
-ENTRY(stage_entry)
-
-PHDRS
-{
-	to_load PT_LOAD;
-}
-
-preram_cbmem_console = CONFIG_CBMEM_CONSOLE_PRERAM_BASE;
-
-SECTIONS
-{
-	. = CONFIG_ROMSTAGE_BASE;
-
-	.romtext . : {
-		_rom = .;
-		_start = .;
-		*(.text.stage_entry.mips);
-		*(.text.startup);
-		*(.text);
-	} : to_load
-
-	.romdata . : {
-		*(.rodata);
-		*(.data);
-		. = ALIGN(16);
-		_erom = .;
-	}
-
-	/* bss will be cleared by cbfs_load_stage */
-	.bss . : {
-		. = ALIGN(8);
-		_bss = .;
-		*(.bss)
-		*(.sbss)
-		*(COMMON)
-	}
-
-	_ebss = .;
-	_end = .;
-
-	/* Discard the sections we don't need/want */
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.comment.*)
-		*(.note.*)
-		*(.eh_frame);
-	}
-}
diff --git a/src/arch/mips/stages.c b/src/arch/mips/stages.c
index ae10594..79b2ea4 100644
--- a/src/arch/mips/stages.c
+++ b/src/arch/mips/stages.c
@@ -20,7 +20,7 @@
 #include <arch/stages.h>
 #include <arch/cache.h>
 
- __attribute__((section(".text.stage_entry.mips"))) void stage_entry(void)
+void stage_entry(void)
 {
 	main();
 }
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index 3388025..fbee821 100644
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -303,7 +303,7 @@ ramstage-srcs += $(src)/arch/x86/ramstage.ld
 
 $(objcbfs)/ramstage.debug: $(objgenerated)/ramstage.o $(obj)/arch/x86/ramstage.ramstage.ld
 	@printf "    CC         $(subst $(obj)/,,$(@))\n"
-	$(LD_ramstage) --gc-sections -o $@ -L$(obj) $< -T $(obj)/arch/x86/ramstage.ramstage.ld
+	$(LD_ramstage) $(CPPFLAGS) --gc-sections -o $@ -L$(obj) $< -T $(src)/arch/x86/ramstage.ld
 
 endif
 
diff --git a/src/arch/x86/boot/boot.c b/src/arch/x86/boot/boot.c
index 08fabcf..0ff8a6c 100644
--- a/src/arch/x86/boot/boot.c
+++ b/src/arch/x86/boot/boot.c
@@ -3,6 +3,7 @@
 #include <program_loading.h>
 #include <ip_checksum.h>
 #include <string.h>
+#include <symbols.h>
 
 /* When the ramstage is relocatable the elf loading ensures an elf image cannot
  * be loaded over the ramstage code. */
@@ -25,11 +26,10 @@ static void jmp_payload_no_bounce_buffer(void *entry)
 
 static void jmp_payload(void *entry, unsigned long buffer, unsigned long size)
 {
-	extern unsigned char _ram_seg, _eram_seg;
 	unsigned long lb_start, lb_size;
 
-	lb_start = (unsigned long)&_ram_seg;
-	lb_size = (unsigned long)(&_eram_seg - &_ram_seg);
+	lb_start = (unsigned long)&_program;
+	lb_size = _program_size;
 
 	printk(BIOS_SPEW, "entry    = 0x%08lx\n", (unsigned long)entry);
 	printk(BIOS_SPEW, "lb_start = 0x%08lx\n", lb_start);
diff --git a/src/arch/x86/init/romstage.ld b/src/arch/x86/init/romstage.ld
index 40ed354..133fb7e 100644
--- a/src/arch/x86/init/romstage.ld
+++ b/src/arch/x86/init/romstage.ld
@@ -60,12 +60,12 @@ SECTIONS
 		*(.car.global_data);
 		_car_data_end = .;
 		/* The preram cbmem console area comes last to take advantage
-		 * of a zero-sized array to hold the memconsole contents that
-		 * grows to a bound of CONFIG_CONSOLE_PRERAM_BUFFER_SIZE.
+		 * of a zero-sized array to hold the memconsole contents.
 		 * However, collisions within the cache-as-ram region cannot be
 		 * statically checked because the cache-as-ram region usage is
 		 * cpu/chipset dependent. */
-		preram_cbmem_console = .;
+		_preram_cbmem_console = .;
+		_epreram_cbmem_console = . + 0xc00;
 	}
 
 	/* Global variables are not allowed in romstage
@@ -83,5 +83,5 @@ SECTIONS
 		*(.sbss.*)
 	}
 
-	_bogus = ASSERT((SIZEOF(.car.data) + CONFIG_CONSOLE_PRERAM_BUFFER_SIZE <= CONFIG_DCACHE_RAM_SIZE), "Cache as RAM area is too full");
+	_bogus = ASSERT((SIZEOF(.car.data) + 0xc00 <= CONFIG_DCACHE_RAM_SIZE), "Cache as RAM area is too full");
 }
diff --git a/src/arch/x86/lib/c_start.S b/src/arch/x86/lib/c_start.S
index 675a09c..dbed123 100644
--- a/src/arch/x86/lib/c_start.S
+++ b/src/arch/x86/lib/c_start.S
@@ -16,7 +16,7 @@ thread_stacks:
 .space CONFIG_STACK_SIZE*CONFIG_NUM_THREADS
 #endif
 
-	.section ".textfirst", "ax", @progbits
+	.section ".text._start", "ax", @progbits
 	.code32
 	.globl _start
 	.globl __rmodule_entry
diff --git a/src/arch/x86/ramstage.ld b/src/arch/x86/ramstage.ld
index f765cbe..5fcbbb6 100644
--- a/src/arch/x86/ramstage.ld
+++ b/src/arch/x86/ramstage.ld
@@ -8,121 +8,18 @@
  *				: stack
  *				: heap
  */
-/*
- * Bootstrap code for the STPC Consumer
- * Copyright (c) 1999 by Net Insight AB. All Rights Reserved.
- */
-
-/*
- *	Written by Johan Rydberg, based on work by Daniel Kahlin.
- *      Rewritten by Eric Biederman
- *  2005.12 yhlu add ramstage cross the vga font buffer handling
- */
-
 ENTRY(_start)
 
+PHDRS
+{
+	to_load PT_LOAD;
+}
+
 SECTIONS
 {
 	. = CONFIG_RAMBASE;
-	/* First we place the code and read only data (typically const declared).
-	 * This could theoretically be placed in rom.
-	 */
-	.text : {
-		_text = .;
-		*(.textfirst);
-		*(.text);
-		*(.text.*);
-		. = ALIGN(16);
-		_etext = .;
-	}
-
-	.ctors : {
-		. = ALIGN(0x100);
-		__CTOR_LIST__ = .;
-		KEEP(*(.ctors));
-		LONG(0);
-		__CTOR_END__ = .;
-	}
-
-	.rodata : {
-		_rodata = .;
-		. = ALIGN(4);
-
-		/* If any changes are made to the driver start/symbols or the
-		 * section names the equivalent changes need to made to
-		 * rmodule.ld. */
-		pci_drivers = . ;
-		KEEP(*(.rodata.pci_driver));
-		epci_drivers = . ;
-		cpu_drivers = . ;
-		KEEP(*(.rodata.cpu_driver));
-		ecpu_drivers = . ;
-		_bs_init_begin = .;
-		KEEP(*(.bs_init));
-		LONG(0);
-		_bs_init_end = .;
-
-		*(.rodata)
-		*(.rodata.*)
-		/* kevinh/Ispiri - Added an align, because the objcopy tool
-		 * incorrectly converts sections that are not long word aligned.
-		 */
-		 . = ALIGN(4);
-
-		_erodata = .;
-	}
-	/* After the code we place initialized data (typically initialized
-	 * global variables). This gets copied into ram by startup code.
-	 * __data_start and __data_end shows where in ram this should be placed,
-	 * whereas __data_loadstart and __data_loadend shows where in rom to
-	 * copy from.
-	 */
-	.data : {
-		_data = .;
-		*(.data)
-		*(.data.*)
-		_edata = .;
-	}
-
-	/* bss does not contain data, it is just a space that should be zero
-	 * initialized on startup. (typically uninitialized global variables)
-	 * crt0.S fills between _bss and _ebss with zeroes.
-	 */
-	_bss = .;
-	.bss . : {
-		*(.bss)
-		*(.bss.*)
-		*(.sbss)
-		*(.sbss.*)
-		*(COMMON)
-	}
-	_ebss = .;
-
-        _heap = .;
-        .heap . : {
-                /* Reserve CONFIG_HEAP_SIZE bytes for the heap */
-                . = CONFIG_HEAP_SIZE ;
-                . = ALIGN(4);
-        }
-        _eheap = .;
-
-	/* The ram segment. This includes all memory used by the memory
-	 * resident copy of coreboot, except the tables that are produced on
-	 * the fly, but including stack and heap.
-	 */
-	_ram_seg = _text;
-	_eram_seg = _eheap;
-
-	/* CONFIG_RAMTOP is the upper address of cached memory (among other
-	 * things). We must not exceed beyond that address, there be dragons.
-	 */
-	_bogus = ASSERT( ( _eram_seg < (CONFIG_RAMTOP)) , "Please increase CONFIG_RAMTOP");
 
-	/* Discard the sections we don't need/want */
+	INCLUDE "lib/ramstage.ramstage.ld"
 
-	/DISCARD/ : {
-		*(.comment)
-		*(.note)
-		*(.note.*)
-	}
+	_ = ASSERT( ( _eprogram < (CONFIG_RAMTOP)) , "Please increase CONFIG_RAMTOP");
 }
diff --git a/src/console/Kconfig b/src/console/Kconfig
index 0a0e069..09cfb39 100644
--- a/src/console/Kconfig
+++ b/src/console/Kconfig
@@ -189,16 +189,6 @@ config CONSOLE_PRERAM_BUFFER_BASE
 	default 0xabadbeef if !CACHE_AS_RAM || LATE_CBMEM_INIT
 	default 0x0
 
-config CONSOLE_PRERAM_BUFFER_SIZE
-	hex
-	default 0x0 if CONSOLE_PRERAM_BUFFER_BASE = 0xabadbeef
-	default 0xc00
-	help
-	  Console is used before RAM is initialized. This is the room reserved
-	  in the DCACHE based RAM, SRAM, etc. to keep console output before it
-	  can be saved in a CBMEM buffer. 3K bytes should be enough even for
-	  the BIOS_SPEW level.
-
 endif
 
 config CONSOLE_QEMU_DEBUGCON
diff --git a/src/cpu/x86/lapic/lapic_cpu_init.c b/src/cpu/x86/lapic/lapic_cpu_init.c
index 472d6ed..d4a9884 100644
--- a/src/cpu/x86/lapic/lapic_cpu_init.c
+++ b/src/cpu/x86/lapic/lapic_cpu_init.c
@@ -27,6 +27,7 @@
 #include <halt.h>
 #include <lib.h>
 #include <string.h>
+#include <symbols.h>
 #include <console/console.h>
 #include <device/device.h>
 #include <device/path.h>
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c
index 3e293f6..a5bbb98 100644
--- a/src/cpu/x86/mp_init.c
+++ b/src/cpu/x86/mp_init.c
@@ -39,6 +39,7 @@
 #include <lib.h>
 #include <smp/atomic.h>
 #include <smp/spinlock.h>
+#include <symbols.h>
 #include <thread.h>
 
 #define MAX_APIC_IDS 256
diff --git a/src/cpu/x86/smm/smm.ld b/src/cpu/x86/smm/smm.ld
index c198161..6d33fbe 100644
--- a/src/cpu/x86/smm/smm.ld
+++ b/src/cpu/x86/smm/smm.ld
@@ -11,6 +11,7 @@ SECTIONS
 	 */
 	. = 0xa0000;
 	.handler (.): {
+		_program = .;
 		/* Assembler stub */
 		*(.handler)
 
@@ -35,9 +36,10 @@ SECTIONS
 		*(.sbss)
 		*(.sbss.*)
 
-		/* What is this? */
+		/* What is this? (Something we don't need with -fno-common.) */
 		*(COMMON)
 		 . = ALIGN(4);
+		_eprogram = .;
 	}
 
 	/* We are using the ASEG interleaved to stuff the SMM handlers
diff --git a/src/cpu/x86/smm/smm_tseg.ld b/src/cpu/x86/smm/smm_tseg.ld
index b57461c..4dedd2c 100644
--- a/src/cpu/x86/smm/smm_tseg.ld
+++ b/src/cpu/x86/smm/smm_tseg.ld
@@ -31,6 +31,7 @@ SECTIONS
 	/* 16KB for the heap at 64KB */
 	. = 0x10000;
 	.heap : {
+		_program = .;
 		_heap = .;
 		. = 0x4000;
 		_eheap = .;
@@ -65,6 +66,7 @@ SECTIONS
 		 . = ALIGN(4);
 
 		_smm_c_handler_end = .;
+		_eprogram = .;
 	}
 
 	/DISCARD/ : {
diff --git a/src/include/lib.h b/src/include/lib.h
index 0cb2c0c..aa8fe4d 100644
--- a/src/include/lib.h
+++ b/src/include/lib.h
@@ -45,11 +45,6 @@ int primitive_memtest(uintptr_t base, uintptr_t size);
 /* Defined in src/lib/stack.c */
 int checkstack(void *top_of_stack, int core);
 
-#ifndef __PRE_RAM__ // fails in bootblock compiled with romcc
-/* currently defined by a ldscript */
-extern unsigned char _estack[];
-#endif
-
 /* Defined in src/lib/hexdump.c */
 void hexdump(const void *memory, size_t length);
 void hexdump32(char LEVEL, const void *d, size_t len);
diff --git a/src/include/memlayout.h b/src/include/memlayout.h
new file mode 100644
index 0000000..a80e03e
--- /dev/null
+++ b/src/include/memlayout.h
@@ -0,0 +1,105 @@
+/*
+ * 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
+ */
+
+/* This file contains macro definitions for memlayout.ld linker scripts. */
+
+#ifndef __MEMLAYOUT_H
+#define __MEMLAYOUT_H
+
+#include <arch/memlayout.h>
+
+#define STR(x) #x
+
+#define SET_COUNTER(name, addr) \
+	_ = ASSERT(. <= addr, STR(name overlaps the previous region!)); \
+	. = addr;
+
+#define SYMBOL(name, addr) \
+	SET_COUNTER(name, addr) \
+	_##name = .;
+
+#define REGION(name, addr, size, expected_align) \
+	SYMBOL(name, addr) \
+	_ = ASSERT(. == ALIGN(expected_align), \
+		STR(name must be aligned to expected_align!)); \
+	SYMBOL(e##name, addr + size)
+
+/* Declare according to SRAM/DRAM ranges in SoC hardware-defined address map. */
+#define SRAM_START(addr) SYMBOL(sram, addr)
+
+#define SRAM_END(addr) SYMBOL(esram, addr)
+
+#define DRAM_START(addr) SYMBOL(dram, addr)
+
+#define PRERAM_CBMEM_CONSOLE(addr, size) \
+	REGION(preram_cbmem_console, addr, size, 4)
+
+/* Use either CBFS_CACHE (unified) or both (PRERAM|POSTRAM)_CBFS_CACHE */
+#define CBFS_CACHE(addr, size) REGION(cbfs_cache, addr, size, 4)
+
+/* TODO: This only works if you never access CBFS in romstage before RAM is up!
+ * If you need to change that assumption, you have some work ahead of you... */
+#if defined(__PRE_RAM__) && !defined(__ROMSTAGE__)
+	#define PRERAM_CBFS_CACHE(addr, size) CBFS_CACHE(addr, size)
+	#define POSTRAM_CBFS_CACHE(addr, size) \
+		REGION(unused_cbfs_cache, addr, size, 4)
+#else
+	#define PRERAM_CBFS_CACHE(addr, size) \
+		REGION(unused_cbfs_cache, addr, size, 4)
+	#define POSTRAM_CBFS_CACHE(addr, size) CBFS_CACHE(addr, size)
+#endif
+
+/* Careful: 'INCLUDE <filename>' must always be at the end of the output line */
+#ifdef __BOOTBLOCK__
+	#define BOOTBLOCK(addr, sz) \
+		SET_COUNTER(bootblock, addr) \
+		_ = ASSERT(_ebootblock - _bootblock <= sz, \
+			STR(Bootblock exceeded its allotted size! (sz))); \
+		INCLUDE "lib/bootblock.bootblock.ld"
+#else
+	#define BOOTBLOCK(addr, sz) \
+		SET_COUNTER(bootblock, addr) \
+		. += sz;
+#endif
+
+#ifdef __ROMSTAGE__
+	#define ROMSTAGE(addr, sz) \
+		SET_COUNTER(romstage, addr) \
+		_ = ASSERT(_eromstage - _romstage <= sz, \
+			STR(Romstage exceeded its allotted size! (sz))); \
+		INCLUDE "lib/romstage.romstage.ld"
+#else
+	#define ROMSTAGE(addr, sz) \
+		SET_COUNTER(romstage, addr) \
+		. += sz;
+#endif
+
+#ifdef __RAMSTAGE__
+	#define RAMSTAGE(addr, sz) \
+		SET_COUNTER(ramstage, addr) \
+		_ = ASSERT(_eramstage - _ramstage <= sz, \
+			STR(Ramstage exceeded its allotted size! (sz))); \
+		INCLUDE "lib/ramstage.ramstage.ld"
+#else
+	#define RAMSTAGE(addr, sz) \
+		SET_COUNTER(ramstage, addr) \
+		. += sz;
+#endif
+
+#endif /* __MEMLAYOUT_H */
diff --git a/src/include/symbols.h b/src/include/symbols.h
new file mode 100644
index 0000000..c343fd9
--- /dev/null
+++ b/src/include/symbols.h
@@ -0,0 +1,76 @@
+/*
+ * 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
+ */
+
+#ifndef __SYMBOLS_H
+#define __SYMBOLS_H
+
+#include <types.h>
+
+extern u8 _sram[];
+extern u8 _esram[];
+#define _sram_size (_esram - _sram)
+
+extern u8 _dram[];
+
+extern u8 _preram_cbmem_console[];
+extern u8 _epreram_cbmem_console[];
+#define _preram_cbmem_console_size \
+		(_epreram_cbmem_console - _preram_cbmem_console)
+
+extern u8 _stack[];
+extern u8 _estack[];
+#define _stack_size (_estack - _stack)
+
+extern u8 _cbfs_cache[];
+extern u8 _ecbfs_cache[];
+#define _cbfs_cache_size (_ecbfs_cache - _cbfs_cache)
+
+extern u8 _payload[];
+extern u8 _epayload[];
+#define _payload_size (_epayload - _payload)
+
+/* Careful: _e<stage> and _<stage>_size only defined for the current stage! */
+extern u8 _bootblock[];
+extern u8 _ebootblock[];
+#define _bootblock_size (_ebootblock - _bootblock)
+
+extern u8 _romstage[];
+extern u8 _eromstage[];
+#define _romstage_size (_eromstage - _romstage)
+
+extern u8 _ramstage[];
+extern u8 _eramstage[];
+#define _ramstage_size (_eramstage - _ramstage)
+
+/* "program" always refers to the current execution unit, except for x86 ROM. */
+extern u8 _program[];
+extern u8 _eprogram[];
+#define _program_size (_eprogram - _program)
+
+/* Arch-specific, move to <arch/symbols.h> if they become too many. */
+
+extern u8 _ttb[];
+extern u8 _ettb[];
+#define _ttb_size (_ettb - _ttb)
+
+extern u8 _dma_coherent[];
+extern u8 _edma_coherent[];
+#define _dma_coherent_size (_edma_coherent - _dma_coherent)
+
+#endif /* __SYMBOLS_H */
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index 7d02934..2b0cf20 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -122,6 +122,14 @@ ramstage-y += halt.c
 smm-y += halt.c
 secmon-y += halt.c
 
+ifneq ($(CONFIG_ARCH_X86),y)
+# X86 bootblock and romstage use custom ldscripts that are all glued together,
+# so we need to exclude it here or it would pick these up as well
+bootblock-y += bootblock.ld
+romstage-y += romstage.ld
+endif
+ramstage-y += ramstage.ld
+
 ifeq ($(CONFIG_RELOCATABLE_MODULES),y)
 ramstage-y += rmodule.c
 romstage-$(CONFIG_RELOCATABLE_RAMSTAGE) += rmodule.c
diff --git a/src/lib/bootblock.ld b/src/lib/bootblock.ld
new file mode 100644
index 0000000..a1c2e71
--- /dev/null
+++ b/src/lib/bootblock.ld
@@ -0,0 +1,48 @@
+/*
+ * 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
+ */
+
+/* This file is included inside a SECTIONS block */
+
+.bootblock . : {
+	_program = .;
+	_bootblock = .;
+	*(.text._start);
+	*(.text.stage_entry);
+	KEEP(*(.id));
+	*(.text);
+	*(.text.*);
+	*(.rodata);
+	*(.rodata.*);
+	*(.data);
+	*(.data.*);
+	*(.bss);
+	*(.bss.*);
+	*(.sbss);
+	*(.sbss.*);
+	_ebootblock = .;
+	_eprogram = .;
+} : to_load = 0xff
+
+/DISCARD/ : {
+	*(.comment)
+	*(.note)
+	*(.comment.*)
+	*(.note.*)
+	*(.ARM.*)
+}
diff --git a/src/lib/cbfs_spi.c b/src/lib/cbfs_spi.c
index 2b3728e..81e6ec3 100644
--- a/src/lib/cbfs_spi.c
+++ b/src/lib/cbfs_spi.c
@@ -25,6 +25,7 @@
 
 #include <cbfs.h>
 #include <spi_flash.h>
+#include <symbols.h>
 
 /* SPI flash as CBFS media. */
 struct cbfs_spi_context {
@@ -80,8 +81,8 @@ static int init_cbfs_media_context(void)
 		if (!spi_context.spi_flash_info)
 			return -1;
 
-		spi_context.buffer.buffer = (void *)CONFIG_CBFS_CACHE_ADDRESS;
-		spi_context.buffer.size = CONFIG_CBFS_CACHE_SIZE;
+		spi_context.buffer.buffer = (void *)_cbfs_cache;
+		spi_context.buffer.size = _cbfs_cache_size;
 	}
 	return 0;
 
diff --git a/src/lib/cbmem_console.c b/src/lib/cbmem_console.c
index 0c2722c..770c1d2 100644
--- a/src/lib/cbmem_console.c
+++ b/src/lib/cbmem_console.c
@@ -21,6 +21,7 @@
 #include <console/cbmem_console.h>
 #include <cbmem.h>
 #include <arch/early_variables.h>
+#include <symbols.h>
 #include <string.h>
 
 /*
@@ -44,11 +45,9 @@ static void copy_console_buffer(struct cbmem_console *old_cons_p,
 /*
  * While running from ROM, before DRAM is initialized, some area in cache as
  * ram space is used for the console buffer storage. The size and location of
- * the area are defined in the config.
+ * the area are defined by the linker script with _(e)preram_cbmem_console.
  */
 
-extern struct cbmem_console preram_cbmem_console;
-
 #else
 
 /*
@@ -112,8 +111,8 @@ void cbmemc_init(void)
 		if (IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE))
 			flags = 0;
 
-	init_console_ptr(&preram_cbmem_console,
-			 CONFIG_CONSOLE_PRERAM_BUFFER_SIZE, flags);
+	init_console_ptr(_preram_cbmem_console,
+			_preram_cbmem_console_size, flags);
 #else
 	/*
 	 * Initializing before CBMEM is available, use static buffer to store
diff --git a/src/lib/loaders/load_and_run_payload.c b/src/lib/loaders/load_and_run_payload.c
index 6c42a58..0e08d88 100644
--- a/src/lib/loaders/load_and_run_payload.c
+++ b/src/lib/loaders/load_and_run_payload.c
@@ -24,6 +24,7 @@
 #include <fallback.h>
 #include <lib.h>
 #include <program_loading.h>
+#include <symbols.h>
 #include <timestamp.h>
 
 extern const struct prog_loader_ops vboot_payload_loader;
diff --git a/src/lib/ramstage.ld b/src/lib/ramstage.ld
new file mode 100644
index 0000000..9ad0e88
--- /dev/null
+++ b/src/lib/ramstage.ld
@@ -0,0 +1,114 @@
+/*
+ * 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
+ */
+
+/* This file is included inside a SECTIONS block */
+
+/* First we place the code and read only data (typically const declared).
+ * This could theoretically be placed in rom.
+ */
+.text : {
+	_program = .;
+	_ramstage = .;
+	_text = .;
+	*(.text._start);
+	*(.text.stage_entry);
+	*(.text);
+	*(.text.*);
+	. = ALIGN(16);
+	_etext = .;
+} : to_load
+
+#ifdef CONFIG_COVERAGE
+.ctors : {
+	. = ALIGN(0x100);
+	__CTOR_LIST__ = .;
+	KEEP(*(.ctors));
+	LONG(0);
+	LONG(0);
+	__CTOR_END__ = .;
+}
+#endif
+
+/* TODO: align data sections to cache lines? (is that really useful?) */
+.rodata : {
+	_rodata = .;
+	. = ALIGN(8);
+
+	/* If any changes are made to the driver start/symbols or the
+	 * section names the equivalent changes need to made to
+	 * rmodule.ld. */
+	console_drivers = .;
+	KEEP(*(.rodata.console_drivers));
+	econsole_drivers = . ;
+	. = ALIGN(8);
+	pci_drivers = . ;
+	KEEP(*(.rodata.pci_driver));
+	epci_drivers = . ;
+	cpu_drivers = . ;
+	KEEP(*(.rodata.cpu_driver));
+	ecpu_drivers = . ;
+	_bs_init_begin = .;
+	KEEP(*(.bs_init));
+	_bs_init_end = .;
+
+	*(.rodata)
+	*(.rodata.*)
+	/* kevinh/Ispiri - Added an align, because the objcopy tool
+	 * incorrectly converts sections that are not long word aligned.
+	 */
+	 . = ALIGN(8);
+
+	_erodata = .;
+}
+
+.data : {
+	/* Move to different cache line to avoid false sharing with .rodata. */
+	. = ALIGN(64);	/* May not be actual line size, not that important. */
+	_data = .;
+	*(.data)
+	*(.data.*)
+	_edata = .;
+}
+
+.bss . : {
+	_bss = .;
+	*(.bss)
+	*(.bss.*)
+	*(.sbss)
+	*(.sbss.*)
+	_ebss = .;
+}
+
+.heap . : {
+	_heap = .;
+	/* Reserve CONFIG_HEAP_SIZE bytes for the heap */
+	. += CONFIG_HEAP_SIZE ;
+	. = ALIGN(4);
+	_eheap = .;
+	_eramstage = .;
+	_eprogram = .;
+}
+
+/* Discard the sections we don't need/want */
+
+/DISCARD/ : {
+	*(.comment)
+	*(.note)
+	*(.note.*)
+}
diff --git a/src/lib/rmodule.ld b/src/lib/rmodule.ld
index 065b5b6..70a2d3d 100644
--- a/src/lib/rmodule.ld
+++ b/src/lib/rmodule.ld
@@ -22,18 +22,21 @@ SECTIONS
 
 	.payload :  {
 		/* C code of the module. */
-		_ram_seg = .;
-		*(.textfirst);
+		_program = .;
+		*(.text._start);
+		*(.text.stage_entry);
 		*(.text);
 		*(.text.*);
 		/* C read-only data. */
 		. = ALIGN(16);
 
+#ifdef CONFIG_COVERAGE
 		__CTOR_LIST__ = .;
 		*(.ctors);
 		LONG(0);
 		LONG(0);
 		__CTOR_END__ = .;
+#endif
 
 		/* The driver sections are to allow linking coreboot's
 		 * ramstage with the rmodule linker. Any changes made in
@@ -68,6 +71,7 @@ SECTIONS
 		. = ALIGN(8);
 
 		/* Data section. */
+		. = ALIGN(64);	/* Mirror cache line alignment from ramstage. */
 		_sdata = .;
 		*(.data);
 		*(.data.*);
@@ -95,7 +99,7 @@ SECTIONS
 		_heap = .;
 		. = . + __heap_size;
 		_eheap = .;
-		_eram_seg = .;
+		_eprogram = .;
 	}
 
 	/DISCARD/ : {
diff --git a/src/lib/romstage.ld b/src/lib/romstage.ld
new file mode 100644
index 0000000..c3a2643
--- /dev/null
+++ b/src/lib/romstage.ld
@@ -0,0 +1,58 @@
+/*
+ * 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
+ */
+
+/* This file is included inside a SECTIONS block */
+
+.text . : {
+	_program = .;
+	_romstage = .;
+	*(.text._start);
+	*(.text.stage_entry);
+	*(.text);
+	*(.text.*);
+} : to_load
+
+.data . : {
+	*(.rodata);
+	*(.rodata.*);
+	*(.data);
+	*(.data.*);
+	. = ALIGN(8);
+}
+
+.bss . : {
+	. = ALIGN(8);
+	_bss = .;
+	*(.bss)
+	*(.bss.*)
+	*(.sbss)
+	*(.sbss.*)
+	_ebss = .;
+	_eromstage = .;
+	_eprogram = .;
+}
+
+/* Discard the sections we don't need/want */
+/DISCARD/ : {
+	*(.comment)
+	*(.note)
+	*(.comment.*)
+	*(.note.*)
+	*(.eh_frame);
+}
diff --git a/src/lib/selfboot.c b/src/lib/selfboot.c
index bd4c169..d73b3f5 100644
--- a/src/lib/selfboot.c
+++ b/src/lib/selfboot.c
@@ -24,17 +24,14 @@
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
+#include <symbols.h>
 #include <cbfs.h>
 #include <lib.h>
 #include <bootmem.h>
 #include <program_loading.h>
 
-/* from ramstage.ld: */
-extern unsigned char _ram_seg;
-extern unsigned char _eram_seg;
-
-static const unsigned long lb_start = (unsigned long)&_ram_seg;
-static const unsigned long lb_end = (unsigned long)&_eram_seg;
+static const unsigned long lb_start = (unsigned long)&_program;
+static const unsigned long lb_end = (unsigned long)&_eprogram;
 
 struct segment {
 	struct segment *next;
diff --git a/src/mainboard/emulation/qemu-armv7/Kconfig b/src/mainboard/emulation/qemu-armv7/Kconfig
index b275e88..c0e7095 100644
--- a/src/mainboard/emulation/qemu-armv7/Kconfig
+++ b/src/mainboard/emulation/qemu-armv7/Kconfig
@@ -49,45 +49,10 @@ config MAINBOARD_VENDOR
 	string
 	default "ARM Ltd."
 
-config SYS_SDRAM_BASE
-	hex "SDRAM base address"
-	default 0x01000000
-
 config DRAM_SIZE_MB
 	int
 	default 1024
 
-# Memory map for qemu vexpress-a9:
-#
-# 0x0000_0000: jump instruction (by qemu)
-# 0x0001_0000: bootblock (entry of kernel / firmware)
-# 0x0002_0000: romstage, assume up to 128KB in size.
-# 0x0007_ff00: stack pointer
-# 0x0010_0000: CBFS header
-# 0x0011_0000: CBFS data
-# 0x0100_0000: reserved for ramstage
-# 0x1000_0000: I/O map address
-#
-config STACK_TOP
-	hex
-	default 0x00100000
-
-config STACK_BOTTOM
-	hex
-	default 0x0007FF00
-
-config BOOTBLOCK_BASE
-	hex
-	default 0x00010000
-
-config ROMSTAGE_BASE
-	hex
-	default 0x00020000
-
-config RAMSTAGE_BASE
-	hex
-	default SYS_SDRAM_BASE
-
 config BOOTBLOCK_ROM_OFFSET
 	hex
 	default 0x0
diff --git a/src/mainboard/emulation/qemu-armv7/Makefile.inc b/src/mainboard/emulation/qemu-armv7/Makefile.inc
index 4119f93..d5742e1 100644
--- a/src/mainboard/emulation/qemu-armv7/Makefile.inc
+++ b/src/mainboard/emulation/qemu-armv7/Makefile.inc
@@ -28,3 +28,7 @@ ramstage-y += timer.c
 bootblock-y += mmio.c
 romstage-y += mmio.c
 ramstage-y += mmio.c
+
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/emulation/qemu-armv7/media.c b/src/mainboard/emulation/qemu-armv7/media.c
index 1168881..8e6cd46 100644
--- a/src/mainboard/emulation/qemu-armv7/media.c
+++ b/src/mainboard/emulation/qemu-armv7/media.c
@@ -14,6 +14,7 @@
  */
 #include <cbfs.h>
 #include <string.h>
+#include <symbols.h>
 #include <console/console.h>
 
 /* Simple memory-mapped ROM emulation. */
@@ -25,7 +26,7 @@ static int emu_rom_open(struct cbfs_media *media)
 
 static void *emu_rom_map(struct cbfs_media *media, size_t offset, size_t count)
 {
-        return (void*)(offset + CONFIG_BOOTBLOCK_BASE);
+        return (void*)(offset + _bootblock);
 }
 
 static void *emu_rom_unmap(struct cbfs_media *media, const void *address)
diff --git a/src/mainboard/emulation/qemu-armv7/memlayout.ld b/src/mainboard/emulation/qemu-armv7/memlayout.ld
new file mode 100644
index 0000000..8990afa
--- /dev/null
+++ b/src/mainboard/emulation/qemu-armv7/memlayout.ld
@@ -0,0 +1,47 @@
+/*
+ * 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 <memlayout.h>
+
+#include <arch/header.ld>
+
+/*
+ * Memory map for qemu vexpress-a9:
+ *
+ * 0x0000_0000: jump instruction (by qemu)
+ * 0x0001_0000: bootblock (entry of kernel / firmware)
+ * 0x0002_0000: romstage, assume up to 128KB in size.
+ * 0x0007_ff00: stack pointer
+ * 0x0010_0000: CBFS header
+ * 0x0011_0000: CBFS data
+ * 0x0100_0000: reserved for ramstage
+ * 0x1000_0000: I/O map address
+ */
+
+SECTIONS
+{
+	/* TODO: does this thing emulate SRAM? */
+
+	BOOTBLOCK(0x10000, 64K)
+	ROMSTAGE(0x20000, 128K)
+	STACK(0x000FC000, 16K)
+
+	DRAM_START(0x01000000)
+	RAMSTAGE(0x01000000)
+}
diff --git a/src/mainboard/google/daisy/Makefile.inc b/src/mainboard/google/daisy/Makefile.inc
index df9b797..1f041ab 100644
--- a/src/mainboard/google/daisy/Makefile.inc
+++ b/src/mainboard/google/daisy/Makefile.inc
@@ -26,3 +26,7 @@ romstage-y += chromeos.c
 
 ramstage-y += mainboard.c
 ramstage-y += chromeos.c
+
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/daisy/mainboard.c b/src/mainboard/google/daisy/mainboard.c
index 5840e51..138e498 100644
--- a/src/mainboard/google/daisy/mainboard.c
+++ b/src/mainboard/google/daisy/mainboard.c
@@ -36,20 +36,17 @@
 #include <soc/samsung/exynos5250/dp.h>
 #include <soc/samsung/exynos5250/periph.h>
 #include <soc/samsung/exynos5250/usb.h>
+#include <symbols.h>
 
 #include "exynos5250.h"
 
 #define MMC0_GPIO_PIN	(58)
 
 /* convenient shorthand (in MB) */
-#define DRAM_START	(CONFIG_SYS_SDRAM_BASE >> 20)
+#define DRAM_START	((uintptr_t)_dram/MiB)
 #define DRAM_SIZE	CONFIG_DRAM_SIZE_MB
 #define DRAM_END	(DRAM_START + DRAM_SIZE)	/* plus one... */
 
-/* Arbitrary range of DMA memory for depthcharge's drivers */
-#define DMA_START	(0x77300000)
-#define DMA_SIZE	(0x00100000)
-
 static struct edid edid = {
 	.ha = 1366,
 	.va = 768,
@@ -333,7 +330,8 @@ static void mainboard_enable(device_t dev)
 	mmu_init();
 	mmu_config_range(0, DRAM_START, DCACHE_OFF);
 	mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK);
-	mmu_config_range(DMA_START >> 20, DMA_SIZE >> 20, DCACHE_OFF);
+	mmu_config_range((uintptr_t)_dma_coherent/MiB,
+			 _dma_coherent_size/MiB, DCACHE_OFF);
 	mmu_config_range(DRAM_END, 4096 - DRAM_END, DCACHE_OFF);
 	dcache_mmu_enable();
 
@@ -359,6 +357,6 @@ void lb_board(struct lb_header *header)
 	dma = (struct lb_range *)lb_new_record(header);
 	dma->tag = LB_TAB_DMA;
 	dma->size = sizeof(*dma);
-	dma->range_start = (intptr_t)DMA_START;
-	dma->range_size = DMA_SIZE;
+	dma->range_start = (uintptr_t)_dma_coherent;
+	dma->range_size = _dma_coherent_size;
 }
diff --git a/src/mainboard/google/daisy/memlayout.ld b/src/mainboard/google/daisy/memlayout.ld
new file mode 100644
index 0000000..72c018e
--- /dev/null
+++ b/src/mainboard/google/daisy/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/samsung/exynos5250/memlayout.ld>
diff --git a/src/mainboard/google/nyan/Kconfig b/src/mainboard/google/nyan/Kconfig
index 864e577..082985d 100644
--- a/src/mainboard/google/nyan/Kconfig
+++ b/src/mainboard/google/nyan/Kconfig
@@ -42,14 +42,6 @@ config MAINBOARD_PART_NUMBER
 	string
 	default "Nyan"
 
-config DRAM_DMA_START
-	hex
-	default 0x90000000
-
-config DRAM_DMA_SIZE
-	hex
-	default 0x00200000
-
 choice
 	prompt "BCT boot media"
 	default NYAN_BCT_CFG_SPI
diff --git a/src/mainboard/google/nyan/Makefile.inc b/src/mainboard/google/nyan/Makefile.inc
index 7ac11e8..6506aba 100644
--- a/src/mainboard/google/nyan/Makefile.inc
+++ b/src/mainboard/google/nyan/Makefile.inc
@@ -42,3 +42,7 @@ ramstage-y += reset.c
 ramstage-y += boardid.c
 ramstage-y += mainboard.c
 ramstage-$(CONFIG_CHROMEOS) += chromeos.c
+
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/nyan/mainboard.c b/src/mainboard/google/nyan/mainboard.c
index b534ea9..e52db83 100644
--- a/src/mainboard/google/nyan/mainboard.c
+++ b/src/mainboard/google/nyan/mainboard.c
@@ -30,6 +30,7 @@
 #include <soc/nvidia/tegra124/pmc.h>
 #include <soc/nvidia/tegra124/spi.h>
 #include <soc/nvidia/tegra/usb.h>
+#include <symbols.h>
 #include <vendorcode/google/chromeos/chromeos.h>
 
 static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
@@ -268,6 +269,6 @@ void lb_board(struct lb_header *header)
 	dma = (struct lb_range *)lb_new_record(header);
 	dma->tag = LB_TAB_DMA;
 	dma->size = sizeof(*dma);
-	dma->range_start = CONFIG_DRAM_DMA_START;
-	dma->range_size = CONFIG_DRAM_DMA_SIZE;
+	dma->range_start = (uintptr_t)_dma_coherent;
+	dma->range_size = _dma_coherent_size;
 }
diff --git a/src/mainboard/google/nyan/memlayout.ld b/src/mainboard/google/nyan/memlayout.ld
new file mode 100644
index 0000000..33ce644
--- /dev/null
+++ b/src/mainboard/google/nyan/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/nvidia/tegra124/memlayout.ld>
diff --git a/src/mainboard/google/nyan/romstage.c b/src/mainboard/google/nyan/romstage.c
index 1ff500b..f2077bb 100644
--- a/src/mainboard/google/nyan/romstage.c
+++ b/src/mainboard/google/nyan/romstage.c
@@ -39,6 +39,7 @@
 #include <soc/addressmap.h>
 #include <soc/clock.h>
 #include <soc/display.h>
+#include <symbols.h>
 #include <timestamp.h>
 
 static void __attribute__((noinline)) romstage(void)
@@ -52,24 +53,25 @@ static void __attribute__((noinline)) romstage(void)
 	sdram_init(get_sdram_config());
 
 	/* used for MMU and CBMEM setup, in MB */
-	u32 dram_start = (CONFIG_SYS_SDRAM_BASE >> 20);
-	u32 dram_end = sdram_max_addressable_mb();	/* plus one... */
-	u32 dram_size = dram_end - dram_start;
+	u32 dram_start_mb = (uintptr_t)_dram/MiB;
+	u32 dram_end_mb = sdram_max_addressable_mb();
+	u32 dram_size_mb = dram_end_mb - dram_start_mb;
 
 	configure_l2_cache();
 	mmu_init();
 	/* Device memory below DRAM is uncached. */
-	mmu_config_range(0, dram_start, DCACHE_OFF);
-	/* SRAM is cached. Round the size up to 2MB, the LPAE page size. */
-	mmu_config_range(0x40000000 >> 20, 2, DCACHE_WRITEBACK);
+	mmu_config_range(0, dram_start_mb, DCACHE_OFF);
+	/* SRAM is cached. MMU code will round size up to page size. */
+	mmu_config_range((uintptr_t)_sram/MiB, div_round_up(_sram_size, MiB),
+			 DCACHE_WRITEBACK);
 	/* DRAM is cached. */
-	mmu_config_range(dram_start, dram_size, DCACHE_WRITEBACK);
+	mmu_config_range(dram_start_mb, dram_size_mb, DCACHE_WRITEBACK);
 	/* A window for DMA is uncached. */
-	mmu_config_range(CONFIG_DRAM_DMA_START >> 20,
-			 CONFIG_DRAM_DMA_SIZE >> 20, DCACHE_OFF);
+	mmu_config_range((uintptr_t)_dma_coherent/MiB,
+			 _dma_coherent_size/MiB, DCACHE_OFF);
 	/* The space above DRAM is uncached. */
-	if (dram_end < 4096)
-		mmu_config_range(dram_end, 4096 - dram_end, DCACHE_OFF);
+	if (dram_end_mb < 4096)
+		mmu_config_range(dram_end_mb, 4096 - dram_end_mb, DCACHE_OFF);
 	mmu_disable_range(0, 1);
 	dcache_mmu_enable();
 
diff --git a/src/mainboard/google/nyan_big/Kconfig b/src/mainboard/google/nyan_big/Kconfig
index 2968b01..7334472 100644
--- a/src/mainboard/google/nyan_big/Kconfig
+++ b/src/mainboard/google/nyan_big/Kconfig
@@ -44,14 +44,6 @@ config MAINBOARD_PART_NUMBER
 	string
 	default "Nyan Big"
 
-config DRAM_DMA_START
-	hex
-	default 0x90000000
-
-config DRAM_DMA_SIZE
-	hex
-	default 0x00200000
-
 choice
 	prompt "BCT boot media"
 	default NYAN_BIG_BCT_CFG_SPI
diff --git a/src/mainboard/google/nyan_big/Makefile.inc b/src/mainboard/google/nyan_big/Makefile.inc
index 8ca495c..fddb44e 100644
--- a/src/mainboard/google/nyan_big/Makefile.inc
+++ b/src/mainboard/google/nyan_big/Makefile.inc
@@ -41,3 +41,7 @@ ramstage-y += reset.c
 ramstage-y += boardid.c
 ramstage-y += mainboard.c
 ramstage-$(CONFIG_CHROMEOS) += chromeos.c
+
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/nyan_big/mainboard.c b/src/mainboard/google/nyan_big/mainboard.c
index 86d9fe3..05f6fae 100644
--- a/src/mainboard/google/nyan_big/mainboard.c
+++ b/src/mainboard/google/nyan_big/mainboard.c
@@ -30,6 +30,7 @@
 #include <soc/nvidia/tegra124/pmc.h>
 #include <soc/nvidia/tegra124/spi.h>
 #include <soc/nvidia/tegra/usb.h>
+#include <symbols.h>
 #include <vendorcode/google/chromeos/chromeos.h>
 
 static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
@@ -266,6 +267,6 @@ void lb_board(struct lb_header *header)
 	dma = (struct lb_range *)lb_new_record(header);
 	dma->tag = LB_TAB_DMA;
 	dma->size = sizeof(*dma);
-	dma->range_start = CONFIG_DRAM_DMA_START;
-	dma->range_size = CONFIG_DRAM_DMA_SIZE;
+	dma->range_start = (uintptr_t)_dma_coherent;
+	dma->range_size = _dma_coherent_size;
 }
diff --git a/src/mainboard/google/nyan_big/memlayout.ld b/src/mainboard/google/nyan_big/memlayout.ld
new file mode 100644
index 0000000..33ce644
--- /dev/null
+++ b/src/mainboard/google/nyan_big/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/nvidia/tegra124/memlayout.ld>
diff --git a/src/mainboard/google/nyan_big/romstage.c b/src/mainboard/google/nyan_big/romstage.c
index 1ff500b..f2077bb 100644
--- a/src/mainboard/google/nyan_big/romstage.c
+++ b/src/mainboard/google/nyan_big/romstage.c
@@ -39,6 +39,7 @@
 #include <soc/addressmap.h>
 #include <soc/clock.h>
 #include <soc/display.h>
+#include <symbols.h>
 #include <timestamp.h>
 
 static void __attribute__((noinline)) romstage(void)
@@ -52,24 +53,25 @@ static void __attribute__((noinline)) romstage(void)
 	sdram_init(get_sdram_config());
 
 	/* used for MMU and CBMEM setup, in MB */
-	u32 dram_start = (CONFIG_SYS_SDRAM_BASE >> 20);
-	u32 dram_end = sdram_max_addressable_mb();	/* plus one... */
-	u32 dram_size = dram_end - dram_start;
+	u32 dram_start_mb = (uintptr_t)_dram/MiB;
+	u32 dram_end_mb = sdram_max_addressable_mb();
+	u32 dram_size_mb = dram_end_mb - dram_start_mb;
 
 	configure_l2_cache();
 	mmu_init();
 	/* Device memory below DRAM is uncached. */
-	mmu_config_range(0, dram_start, DCACHE_OFF);
-	/* SRAM is cached. Round the size up to 2MB, the LPAE page size. */
-	mmu_config_range(0x40000000 >> 20, 2, DCACHE_WRITEBACK);
+	mmu_config_range(0, dram_start_mb, DCACHE_OFF);
+	/* SRAM is cached. MMU code will round size up to page size. */
+	mmu_config_range((uintptr_t)_sram/MiB, div_round_up(_sram_size, MiB),
+			 DCACHE_WRITEBACK);
 	/* DRAM is cached. */
-	mmu_config_range(dram_start, dram_size, DCACHE_WRITEBACK);
+	mmu_config_range(dram_start_mb, dram_size_mb, DCACHE_WRITEBACK);
 	/* A window for DMA is uncached. */
-	mmu_config_range(CONFIG_DRAM_DMA_START >> 20,
-			 CONFIG_DRAM_DMA_SIZE >> 20, DCACHE_OFF);
+	mmu_config_range((uintptr_t)_dma_coherent/MiB,
+			 _dma_coherent_size/MiB, DCACHE_OFF);
 	/* The space above DRAM is uncached. */
-	if (dram_end < 4096)
-		mmu_config_range(dram_end, 4096 - dram_end, DCACHE_OFF);
+	if (dram_end_mb < 4096)
+		mmu_config_range(dram_end_mb, 4096 - dram_end_mb, DCACHE_OFF);
 	mmu_disable_range(0, 1);
 	dcache_mmu_enable();
 
diff --git a/src/mainboard/google/nyan_blaze/Kconfig b/src/mainboard/google/nyan_blaze/Kconfig
index 5938e7e..3495919 100644
--- a/src/mainboard/google/nyan_blaze/Kconfig
+++ b/src/mainboard/google/nyan_blaze/Kconfig
@@ -45,14 +45,6 @@ config MAINBOARD_PART_NUMBER
 	string
 	default "Nyan Blaze"
 
-config DRAM_DMA_START
-	hex
-	default 0x90000000
-
-config DRAM_DMA_SIZE
-	hex
-	default 0x00200000
-
 choice
 	prompt "BCT boot media"
 	default NYAN_BLAZE_BCT_CFG_SPI
diff --git a/src/mainboard/google/nyan_blaze/Makefile.inc b/src/mainboard/google/nyan_blaze/Makefile.inc
index dc998d1..3430409 100644
--- a/src/mainboard/google/nyan_blaze/Makefile.inc
+++ b/src/mainboard/google/nyan_blaze/Makefile.inc
@@ -45,3 +45,8 @@ ramstage-y += reset.c
 ramstage-y += boardid.c
 ramstage-y += mainboard.c
 ramstage-$(CONFIG_CHROMEOS) += chromeos.c
+
+bootblock-y += memlayout.ld
+verstage-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/nyan_blaze/mainboard.c b/src/mainboard/google/nyan_blaze/mainboard.c
index ccbaf63..5f1cb49 100644
--- a/src/mainboard/google/nyan_blaze/mainboard.c
+++ b/src/mainboard/google/nyan_blaze/mainboard.c
@@ -30,6 +30,7 @@
 #include <soc/nvidia/tegra124/pmc.h>
 #include <soc/nvidia/tegra124/spi.h>
 #include <soc/nvidia/tegra/usb.h>
+#include <symbols.h>
 #include <vendorcode/google/chromeos/chromeos.h>
 
 static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE;
@@ -266,6 +267,6 @@ void lb_board(struct lb_header *header)
 	dma = (struct lb_range *)lb_new_record(header);
 	dma->tag = LB_TAB_DMA;
 	dma->size = sizeof(*dma);
-	dma->range_start = CONFIG_DRAM_DMA_START;
-	dma->range_size = CONFIG_DRAM_DMA_SIZE;
+	dma->range_start = (uintptr_t)_dma_coherent;
+	dma->range_size = _dma_coherent_size;
 }
diff --git a/src/mainboard/google/nyan_blaze/memlayout.ld b/src/mainboard/google/nyan_blaze/memlayout.ld
new file mode 100644
index 0000000..33ce644
--- /dev/null
+++ b/src/mainboard/google/nyan_blaze/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/nvidia/tegra124/memlayout.ld>
diff --git a/src/mainboard/google/nyan_blaze/romstage.c b/src/mainboard/google/nyan_blaze/romstage.c
index fca705d..fb1b9e2 100644
--- a/src/mainboard/google/nyan_blaze/romstage.c
+++ b/src/mainboard/google/nyan_blaze/romstage.c
@@ -39,6 +39,7 @@
 #include <soc/addressmap.h>
 #include <soc/clock.h>
 #include <soc/display.h>
+#include <symbols.h>
 #include <timestamp.h>
 
 static void __attribute__((noinline)) romstage(void)
@@ -52,29 +53,30 @@ static void __attribute__((noinline)) romstage(void)
 	sdram_init(get_sdram_config());
 
 	/* used for MMU and CBMEM setup, in MB */
-	u32 dram_start = (CONFIG_SYS_SDRAM_BASE >> 20);
-	u32 dram_end = sdram_max_addressable_mb();	/* plus one... */
-	u32 dram_size = dram_end - dram_start;
+	u32 dram_start_mb = (uintptr_t)_dram/MiB;
+	u32 dram_end_mb = sdram_max_addressable_mb();
+	u32 dram_size_mb = dram_end_mb - dram_start_mb;
 
 #if !CONFIG_VBOOT2_VERIFY_FIRMWARE
 	configure_l2_cache();
 	mmu_init();
 	/* Device memory below DRAM is uncached. */
-	mmu_config_range(0, dram_start, DCACHE_OFF);
-	/* SRAM is cached. Round the size up to 2MB, the LPAE page size. */
-	mmu_config_range(0x40000000 >> 20, 2, DCACHE_WRITEBACK);
+	mmu_config_range(0, dram_start_mb, DCACHE_OFF);
+	/* SRAM is cached. MMU code will round size up to page size. */
+	mmu_config_range((uintptr_t)_sram/MiB, div_round_up(_sram_size, MiB),
+			 DCACHE_WRITEBACK);
 	/* The space above DRAM is uncached. */
-	if (dram_end < 4096)
-		mmu_config_range(dram_end, 4096 - dram_end, DCACHE_OFF);
+	if (dram_end_mb < 4096)
+		mmu_config_range(dram_end_mb, 4096 - dram_end_mb, DCACHE_OFF);
 	mmu_disable_range(0, 1);
 	dcache_mmu_enable();
 #endif
 
 	/* DRAM is cached. */
-	mmu_config_range(dram_start, dram_size, DCACHE_WRITEBACK);
+	mmu_config_range(dram_start_mb, dram_size_mb, DCACHE_WRITEBACK);
 	/* A window for DMA is uncached. */
-	mmu_config_range(CONFIG_DRAM_DMA_START >> 20,
-			 CONFIG_DRAM_DMA_SIZE >> 20, DCACHE_OFF);
+	mmu_config_range((uintptr_t)_dma_coherent/MiB,
+			 _dma_coherent_size/MiB, DCACHE_OFF);
 
 	/*
 	 * A watchdog reset only resets part of the system so it ends up in
diff --git a/src/mainboard/google/peach_pit/Makefile.inc b/src/mainboard/google/peach_pit/Makefile.inc
index df9b797..1f041ab 100644
--- a/src/mainboard/google/peach_pit/Makefile.inc
+++ b/src/mainboard/google/peach_pit/Makefile.inc
@@ -26,3 +26,7 @@ romstage-y += chromeos.c
 
 ramstage-y += mainboard.c
 ramstage-y += chromeos.c
+
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/peach_pit/mainboard.c b/src/mainboard/google/peach_pit/mainboard.c
index 1a15bd2..b6f49e2 100644
--- a/src/mainboard/google/peach_pit/mainboard.c
+++ b/src/mainboard/google/peach_pit/mainboard.c
@@ -40,15 +40,12 @@
 #include <drivers/parade/ps8625/ps8625.h>
 #include <ec/google/chromeec/ec.h>
 #include <stdlib.h>
+#include <symbols.h>
 
 /* convenient shorthand (in MB) */
-#define DRAM_START	(CONFIG_SYS_SDRAM_BASE >> 20)
+#define DRAM_START	((uintptr_t)_dram/MiB)
 #define DRAM_SIZE	CONFIG_DRAM_SIZE_MB
 
-/* Arbitrary range of DMA memory for depthcharge's drivers */
-#define DMA_START	(0x77300000)
-#define DMA_SIZE	(0x00100000)
-
 static struct edid edid = {
 	.ha = 1366,
 	.va = 768,
@@ -469,7 +466,8 @@ static void mainboard_enable(device_t dev)
 
 	/* set up caching for the DRAM */
 	mmu_config_range(DRAM_START, DRAM_SIZE, DCACHE_WRITEBACK);
-	mmu_config_range(DMA_START >> 20, DMA_SIZE >> 20, DCACHE_OFF);
+	mmu_config_range((uintptr_t)_dma_coherent/MiB,
+			 _dma_coherent_size/MiB, DCACHE_OFF);
 
 	const unsigned epll_hz = 192000000;
 	const unsigned sample_rate = 48000;
@@ -493,6 +491,6 @@ void lb_board(struct lb_header *header)
 	dma = (struct lb_range *)lb_new_record(header);
 	dma->tag = LB_TAB_DMA;
 	dma->size = sizeof(*dma);
-	dma->range_start = (intptr_t)DMA_START;
-	dma->range_size = DMA_SIZE;
+	dma->range_start = (uintptr_t)_dma_coherent;
+	dma->range_size = _dma_coherent_size;
 }
diff --git a/src/mainboard/google/peach_pit/memlayout.ld b/src/mainboard/google/peach_pit/memlayout.ld
new file mode 100644
index 0000000..565ba89
--- /dev/null
+++ b/src/mainboard/google/peach_pit/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/samsung/exynos5420/memlayout.ld>
diff --git a/src/mainboard/google/rush/Makefile.inc b/src/mainboard/google/rush/Makefile.inc
index 2a1ce99..e41745f 100644
--- a/src/mainboard/google/rush/Makefile.inc
+++ b/src/mainboard/google/rush/Makefile.inc
@@ -40,3 +40,7 @@ ramstage-y += boardid.c
 ramstage-y += mainboard.c
 ramstage-y += reset.c
 ramstage-$(CONFIG_CHROMEOS) += chromeos.c
+
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/rush/memlayout.ld b/src/mainboard/google/rush/memlayout.ld
new file mode 100644
index 0000000..b9def51
--- /dev/null
+++ b/src/mainboard/google/rush/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/nvidia/tegra132/memlayout.ld>
diff --git a/src/mainboard/google/rush_ryu/Makefile.inc b/src/mainboard/google/rush_ryu/Makefile.inc
index 2fe12a4..67a3fac 100644
--- a/src/mainboard/google/rush_ryu/Makefile.inc
+++ b/src/mainboard/google/rush_ryu/Makefile.inc
@@ -41,3 +41,7 @@ ramstage-y += boardid.c
 ramstage-y += mainboard.c
 ramstage-y += reset.c
 ramstage-y += chromeos.c
+
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/rush_ryu/memlayout.ld b/src/mainboard/google/rush_ryu/memlayout.ld
new file mode 100644
index 0000000..b9def51
--- /dev/null
+++ b/src/mainboard/google/rush_ryu/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/nvidia/tegra132/memlayout.ld>
diff --git a/src/mainboard/google/storm/Kconfig b/src/mainboard/google/storm/Kconfig
index b0c064c..3e1e016 100644
--- a/src/mainboard/google/storm/Kconfig
+++ b/src/mainboard/google/storm/Kconfig
@@ -48,12 +48,4 @@ config DRAM_SIZE_MB
 	default 512 if BOARD_VARIANT_AP148
 	default 1024
 
-config DRAM_DMA_START
-	hex
-	default 0x5a000000
-
-config DRAM_DMA_SIZE
-	hex
-	default 0x00200000
-
 endif # BOARD_GOOGLE_STORM
diff --git a/src/mainboard/google/storm/Makefile.inc b/src/mainboard/google/storm/Makefile.inc
index 907638a..6ee0841 100644
--- a/src/mainboard/google/storm/Makefile.inc
+++ b/src/mainboard/google/storm/Makefile.inc
@@ -25,3 +25,7 @@ romstage-y += cdp.c
 ramstage-y += boardid.c
 ramstage-y += cdp.c
 ramstage-y += mainboard.c
+
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/storm/mainboard.c b/src/mainboard/google/storm/mainboard.c
index 3da6f90..478e2a8 100644
--- a/src/mainboard/google/storm/mainboard.c
+++ b/src/mainboard/google/storm/mainboard.c
@@ -25,19 +25,20 @@
 #include <device/device.h>
 #include <gpiolib.h>
 #include <string.h>
+#include <symbols.h>
 
 #include <soc/qualcomm/ipq806x/include/clock.h>
 #include <soc/qualcomm/ipq806x/include/gpio.h>
 #include <soc/qualcomm/ipq806x/include/usb.h>
 
 /* convenient shorthand (in MB) */
-#define DRAM_START           (CONFIG_SYS_SDRAM_BASE / MiB)
+#define DRAM_START           ((uintptr_t)_dram / MiB)
 #define DRAM_SIZE            (CONFIG_DRAM_SIZE_MB)
 #define DRAM_END             (DRAM_START + DRAM_SIZE)
 
 /* DMA memory for drivers */
-#define DMA_START            (CONFIG_DRAM_DMA_START / MiB)
-#define DMA_SIZE             (CONFIG_DRAM_DMA_SIZE / MiB)
+#define DMA_START            ((uintptr_t)_dma_coherent / MiB)
+#define DMA_SIZE             (_dma_coherent_size / MiB)
 
 #define USB_ENABLE_GPIO		51
 
@@ -134,8 +135,8 @@ void lb_board(struct lb_header *header)
 	dma = (struct lb_range *)lb_new_record(header);
 	dma->tag = LB_TAB_DMA;
 	dma->size = sizeof(*dma);
-	dma->range_start = CONFIG_DRAM_DMA_START;
-	dma->range_size = CONFIG_DRAM_DMA_SIZE;
+	dma->range_start = (uintptr_t)_dma_coherent;
+	dma->range_size = _dma_coherent_size;
 }
 
 static int read_gpio(gpio_t gpio_num)
diff --git a/src/mainboard/google/storm/memlayout.ld b/src/mainboard/google/storm/memlayout.ld
new file mode 100644
index 0000000..1735835
--- /dev/null
+++ b/src/mainboard/google/storm/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/qualcomm/ipq806x/memlayout.ld>
diff --git a/src/mainboard/google/urara/Kconfig b/src/mainboard/google/urara/Kconfig
index bde26d6..a9363f9 100644
--- a/src/mainboard/google/urara/Kconfig
+++ b/src/mainboard/google/urara/Kconfig
@@ -38,10 +38,6 @@ config MAINBOARD_PART_NUMBER
 	string
 	default "ImgTec Pistachio Virtual Platform"
 
-config SYS_SDRAM_BASE
-	hex "SDRAM base address"
-	default 0x80000000
-
 config DRAM_SIZE_MB
 	int
 	default 256
diff --git a/src/mainboard/google/urara/Makefile.inc b/src/mainboard/google/urara/Makefile.inc
index 4ce6398..5a9dc02 100644
--- a/src/mainboard/google/urara/Makefile.inc
+++ b/src/mainboard/google/urara/Makefile.inc
@@ -21,3 +21,6 @@
 
 ramstage-y += mainboard.c
 
+bootblock-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/urara/memlayout.ld b/src/mainboard/google/urara/memlayout.ld
new file mode 100644
index 0000000..ab0b4dd
--- /dev/null
+++ b/src/mainboard/google/urara/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/imgtec/pistachio/memlayout.ld>
diff --git a/src/mainboard/google/veyron_pinky/Kconfig b/src/mainboard/google/veyron_pinky/Kconfig
index 97a0097..7c4f084 100644
--- a/src/mainboard/google/veyron_pinky/Kconfig
+++ b/src/mainboard/google/veyron_pinky/Kconfig
@@ -61,14 +61,6 @@ config BOOT_MEDIA_SPI_BUS
         int
         default 2
 
-config DRAM_DMA_START
-	hex
-	default 0x10000000
-
-config DRAM_DMA_SIZE
-	hex
-	default 0x00200000
-
 config DRAM_SIZE_MB
 	int
 	default 2048
diff --git a/src/mainboard/google/veyron_pinky/Makefile.inc b/src/mainboard/google/veyron_pinky/Makefile.inc
index c33cfa3..0cc89d0 100644
--- a/src/mainboard/google/veyron_pinky/Makefile.inc
+++ b/src/mainboard/google/veyron_pinky/Makefile.inc
@@ -35,3 +35,8 @@ ramstage-y += boardid.c
 ramstage-y += chromeos.c
 ramstage-y += mainboard.c
 ramstage-y += reset.c
+
+bootblock-y += memlayout.ld
+verstage-y += memlayout.ld
+romstage-y += memlayout.ld
+ramstage-y += memlayout.ld
diff --git a/src/mainboard/google/veyron_pinky/mainboard.c b/src/mainboard/google/veyron_pinky/mainboard.c
index 232010d..19d6675 100644
--- a/src/mainboard/google/veyron_pinky/mainboard.c
+++ b/src/mainboard/google/veyron_pinky/mainboard.c
@@ -22,6 +22,7 @@
 #include <arch/cache.h>
 #include <delay.h>
 #include <edid.h>
+#include <symbols.h>
 #include <vbe.h>
 #include <boot/coreboot_tables.h>
 #include <device/i2c.h>
@@ -153,6 +154,6 @@ void lb_board(struct lb_header *header)
 	dma = (struct lb_range *)lb_new_record(header);
 	dma->tag = LB_TAB_DMA;
 	dma->size = sizeof(*dma);
-	dma->range_start = CONFIG_DRAM_DMA_START;
-	dma->range_size = CONFIG_DRAM_DMA_SIZE;
+	dma->range_start = (uintptr_t)_dma_coherent;
+	dma->range_size = _dma_coherent_size;
 }
diff --git a/src/mainboard/google/veyron_pinky/memlayout.ld b/src/mainboard/google/veyron_pinky/memlayout.ld
new file mode 100644
index 0000000..a8b7465
--- /dev/null
+++ b/src/mainboard/google/veyron_pinky/memlayout.ld
@@ -0,0 +1 @@
+#include <soc/rockchip/rk3288/memlayout.ld>
diff --git a/src/mainboard/google/veyron_pinky/romstage.c b/src/mainboard/google/veyron_pinky/romstage.c
index f972ee2..1d7812b 100644
--- a/src/mainboard/google/veyron_pinky/romstage.c
+++ b/src/mainboard/google/veyron_pinky/romstage.c
@@ -35,6 +35,7 @@
 #include <soc/rockchip/rk3288/clock.h>
 #include <soc/rockchip/rk3288/pwm.h>
 #include <soc/rockchip/rk3288/grf.h>
+#include <symbols.h>
 #include "timer.h"
 
 static void regulate_vdd_log(unsigned int mv)
@@ -64,9 +65,9 @@ void main(void)
 	start_romstage_time = timestamp_get();
 #endif
 	/* used for MMU and CBMEM setup, in MB */
-	u32 dram_start = (CONFIG_SYS_SDRAM_BASE >> 20);
-	u32 dram_size = CONFIG_DRAM_SIZE_MB;
-	u32 dram_end = dram_start + dram_size;
+	u32 dram_start_mb = (uintptr_t)_dram/MiB;
+	u32 dram_size_mb = CONFIG_DRAM_SIZE_MB;
+	u32 dram_end_mb = dram_start_mb + dram_size_mb;
 
 	console_init();
 
@@ -81,15 +82,15 @@ void main(void)
 #endif
 	mmu_init();
 	/* Device memory below DRAM is uncached. */
-	mmu_config_range(0, dram_start, DCACHE_OFF);
+	mmu_config_range(0, dram_start_mb, DCACHE_OFF);
 	/* DRAM is cached. */
-	mmu_config_range(dram_start, dram_size, DCACHE_WRITEBACK);
+	mmu_config_range(dram_start_mb, dram_size_mb, DCACHE_WRITEBACK);
 	/* A window for DMA is uncached. */
-	mmu_config_range(CONFIG_DRAM_DMA_START >> 20,
-			 CONFIG_DRAM_DMA_SIZE >> 20, DCACHE_OFF);
+	mmu_config_range((uintptr_t)_dma_coherent/MiB,
+			 _dma_coherent_size/MiB, DCACHE_OFF);
 	/* The space above DRAM is uncached. */
-	if (dram_end < 4096)
-		mmu_config_range(dram_end, 4096 - dram_end, DCACHE_OFF);
+	if (dram_end_mb < 4096)
+		mmu_config_range(dram_end_mb, 4096 - dram_end_mb, DCACHE_OFF);
 	dcache_mmu_enable();
 
 	cbmem_initialize_empty();
diff --git a/src/soc/imgtec/pistachio/Kconfig b/src/soc/imgtec/pistachio/Kconfig
index 2e8b700..70e5741 100644
--- a/src/soc/imgtec/pistachio/Kconfig
+++ b/src/soc/imgtec/pistachio/Kconfig
@@ -35,10 +35,6 @@ config BOOTBLOCK_CPU_INIT
 	string
 	default "soc/imgtec/pistachio/bootblock.c"
 
-config BOOTBLOCK_BASE
-	hex
-	default 0x9b000000
-
 config CBFS_ROM_OFFSET
 	hex
 	default 0x4100
@@ -48,31 +44,4 @@ config CBFS_HEADER_ROM_OFFSET
 	hex
 	default 0x4000
 
-config ROMSTAGE_BASE
-	hex
-	default 0x9b004000
-	help
-	  The address where romstage is supposed to be loaded, right above the
-	  bootblock.
-
-config CBMEM_CONSOLE_PRERAM_BASE
-        hex "memory address of the CBMEM console buffer"
-        default 0x9b00f800
-	help
-	  Allocate 4KB to the pre-ram console buffer, we should be able to use
-	  GRAM eventually and have a much larger buffer.
-
-config BOOTBLOCK_STACK_BOTTOM
-	hex
-	default 0x9b00e000
-	help
-	  This allocates 6KB of stack space. One needs to verify that this is
-	  sufficient.
-
-config BOOTBLOCK_STACK_TOP
-	hex
-	default CBMEM_CONSOLE_PRERAM_BASE
-	help
-	  Bootblock stack starts immediately under the CBMEM console buffer,
-	  stack location might be changed by romstage.
 endif
diff --git a/src/soc/imgtec/pistachio/Makefile.inc b/src/soc/imgtec/pistachio/Makefile.inc
index b91bb1b5..d052c8f 100644
--- a/src/soc/imgtec/pistachio/Makefile.inc
+++ b/src/soc/imgtec/pistachio/Makefile.inc
@@ -51,5 +51,5 @@ $(objcbfs)/bootblock.raw: $(objcbfs)/bootblock.elf
 # Create a complete bootblock which will start up the system
 $(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw $(BIMGTOOL)
 	@printf "    BIMGTOOL   $(subst $(obj)/,,$(@))\n"
-	$(BIMGTOOL) $< $@ $(CONFIG_BOOTBLOCK_BASE)
+	$(BIMGTOOL) $< $@ $(call loadaddr,bootblock)
 
diff --git a/src/soc/imgtec/pistachio/memlayout.ld b/src/soc/imgtec/pistachio/memlayout.ld
new file mode 100644
index 0000000..21c3d73
--- /dev/null
+++ b/src/soc/imgtec/pistachio/memlayout.ld
@@ -0,0 +1,38 @@
+/*
+ * 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 <memlayout.h>
+
+#include <arch/header.ld>
+
+/* TODO: This should be revised by someone who understands the SoC better. */
+
+SECTIONS
+{
+	CBFS_CACHE(0x0, 0) /* TODO: fix this, it was already broken before!!! */
+
+	DRAM_START(0x80000000)
+	RAMSTAGE(0x80000000, 128K)
+
+	/* TODO: Does this SoC use SRAM? Add SRAM_START() and SRAM_END(). */
+	BOOTBLOCK(0x9B000000, 16K)
+	ROMSTAGE(0x9B004000, 40K)
+	STACK(0x9B00E000, 6K)
+	PRERAM_CBMEM_CONSOLE(0x9B00F800, 3K)
+}
diff --git a/src/soc/nvidia/tegra124/Kconfig b/src/soc/nvidia/tegra124/Kconfig
index acc6e7e..1680f45 100644
--- a/src/soc/nvidia/tegra124/Kconfig
+++ b/src/soc/nvidia/tegra124/Kconfig
@@ -22,34 +22,6 @@ config BOOTBLOCK_CPU_INIT
 	  bootblock must load microcode or copy data from ROM before
 	  searching for the bootblock.
 
-# ROM image layout.
-#
-# 0x00000 Combined bootblock and BCT blob
-# 0x18000 Master CBFS header.
-# 0x18080 Free for CBFS data.
-#
-# iRAM (256k) layout.
-# (Note: The BootROM uses the address range [0x4000_0000:0x4000_E000) itself,
-#  so the bootblock loading address must be placed after that. After the
-#  handoff that area may be reclaimed for other uses, e.g. CBFS cache.)
-#
-# 0x4000_0000 TTB (16K+32B). 32B is for L1 table of LPAE.
-# 0x4000_4020 CBFS mapping cache (96K-32B)
-# 0x4001_C000 Stack (16KB... don't reduce without comparing LZMA scratchpad!).
-# 0x4002_0000 Bootblock (max 48KB).
-# 0x4002_C000 ROM stage (max 80KB).
-# 0x4003_FFFF End of iRAM.
-#
-# if VBOOT2_VERIFY_FIRMWARE,
-# 0x4000_0000 TTB (16K+32B). 32B is for L1 table of LPAE.
-# 0x4000_4020 CBMEM console area (8K-32B)
-# 0x4000_6000 CBFS mapping cache (72K)
-# 0x4001_8000 vboot work buffer (16K)
-# 0x4001_C000 Stack (16KB... don't reduce without comparing LZMA scratchpad!).
-# 0x4002_0000 bootblock and romstage (max 70KB).
-# 0x4003_1000 verstage (max 60KB).
-# 0x4003_FFFF End of iRAM.
-
 config BOOTBLOCK_ROM_OFFSET
 	hex
 	default 0x0
@@ -62,65 +34,6 @@ config CBFS_ROM_OFFSET
 	hex "offset of CBFS data in ROM"
 	default 0x18080
 
-config SYS_SDRAM_BASE
-	hex
-	default 0x80000000
-
-config BOOTBLOCK_BASE
-	hex
-	default 0x40020000
-
-# this has to be big enough to leave room big enough for the larger of the
-# bootblock and the romstage.
-config VERSTAGE_BASE
-	hex
-	default 0x40031000
-
-# with vboot2, romstage is loaded over to the bootblock space
-config ROMSTAGE_BASE
-	hex
-	default 0x40020000 if VBOOT2_VERIFY_FIRMWARE
-	default 0x4002c000
-
-config RAMSTAGE_BASE
-	hex
-	default 0x80200000
-
-config STACK_TOP
-	hex
-	default 0x40020000
-
-config STACK_BOTTOM
-	hex
-	default 0x4001c000
-
-# This is the ramstage thread stack, *not* the same as above! Currently unused.
-config STACK_SIZE
-	hex
-	default 0x800
-
-# TTB needs to be aligned to 16KB. Stick it in iRAM.
-config TTB_BUFFER
-	hex "memory address of the TTB buffer"
-	default 0x40000000
-
-config CBFS_CACHE_ADDRESS
-	hex "memory address to put CBFS cache data"
-	default 0x40004020
-
-config CBFS_CACHE_SIZE
-	hex "size of CBFS cache data"
-	default 0x00012000 if VBOOT2_VERIFY_FIRMWARE
-	default 0x00016000
-
-config VBOOT_WORK_BUFFER_ADDRESS
-	hex "memory address of vboot work buffer"
-	default 0x40018000
-
-config VBOOT_WORK_BUFFER_SIZE
-	hex "size of vboot work buffer"
-	default 0x00004000
-
 config TEGRA124_MODEL_TD570D
 	bool "TD570D"
 
diff --git a/src/soc/nvidia/tegra124/Makefile.inc b/src/soc/nvidia/tegra124/Makefile.inc
index d32580e..6de142d 100644
--- a/src/soc/nvidia/tegra124/Makefile.inc
+++ b/src/soc/nvidia/tegra124/Makefile.inc
@@ -103,6 +103,6 @@ $(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin $(BCT_BIN) $(CBOOTIMAGE)
 	echo "Version    = 1;" > $(BCT_WRAPPER)
 	echo "Redundancy = 1;" >> $(BCT_WRAPPER)
 	echo "Bctfile    = $(BCT_BIN);" >> $(BCT_WRAPPER)
-	echo "BootLoader = $<,$(CONFIG_BOOTBLOCK_BASE),$(CONFIG_BOOTBLOCK_BASE),Complete;" >> $(BCT_WRAPPER)
+	echo "BootLoader = $<,$(call loadaddr,bootblock),$(call loadaddr,bootblock),Complete;" >> $(BCT_WRAPPER)
 	@printf "    CBOOTIMAGE $(subst $(obj)/,,$(@))\n"
 	$(CBOOTIMAGE) $(BCT_WRAPPER) $@
diff --git a/src/soc/nvidia/tegra124/bootblock_asm.S b/src/soc/nvidia/tegra124/bootblock_asm.S
index e4d4302..1a30dda 100644
--- a/src/soc/nvidia/tegra124/bootblock_asm.S
+++ b/src/soc/nvidia/tegra124/bootblock_asm.S
@@ -44,10 +44,8 @@ ENTRY(_start)
 	 * Initialize the stack to a known value. This is used to check for
 	 * stack overflow later in the boot process.
 	 */
-	ldr	r0, .Stack
-	ldr	r1, .Stack_size
-	sub	r0, r0, r1
-	ldr	r1, .Stack
+	ldr	r0, =_stack
+	ldr	r1, =_estack
 	ldr	r2, =0xdeadbeef
 init_stack_loop:
 	str	r2, [r0]
@@ -57,7 +55,7 @@ init_stack_loop:
 
 /* Set stackpointer in internal RAM to call bootblock main() */
 call_bootblock:
-	ldr	sp, .Stack /* Set up stack pointer */
+	ldr	sp, =_estack /* Set up stack pointer */
 	ldr	r0,=0x00000000
 	 /*
 	  * The current design of cpu_info places the
@@ -75,15 +73,3 @@ call_bootblock:
 	 */
 	bl	main
 ENDPROC(_start)
-
-/* we do it this way because it's a 32-bit constant and
- * in some cases too far away to be loaded as just an offset
- * from IP
- */
-.align 2
-.Stack:
-	.word CONFIG_STACK_TOP
-.align 2
-/* create this size the same way we do in coreboot_ram.ld: top-bottom */
-.Stack_size:
-	.word CONFIG_STACK_TOP - CONFIG_STACK_BOTTOM
diff --git a/src/soc/nvidia/tegra124/cbfs.c b/src/soc/nvidia/tegra124/cbfs.c
index 4497d6a..d56050d 100644
--- a/src/soc/nvidia/tegra124/cbfs.c
+++ b/src/soc/nvidia/tegra124/cbfs.c
@@ -19,12 +19,12 @@
 
 
 #include <cbfs.h>  /* This driver serves as a CBFS media source. */
+#include <symbols.h>
 
 #include "spi.h"
 
 int init_default_cbfs_media(struct cbfs_media *media)
 {
 	return initialize_tegra_spi_cbfs_media(media,
-		(void*)CONFIG_CBFS_CACHE_ADDRESS,
-		CONFIG_CBFS_CACHE_SIZE);
+		_cbfs_cache, _cbfs_cache_size);
 }
diff --git a/src/soc/nvidia/tegra124/clock.c b/src/soc/nvidia/tegra124/clock.c
index fa33283..f5043af 100644
--- a/src/soc/nvidia/tegra124/clock.c
+++ b/src/soc/nvidia/tegra124/clock.c
@@ -20,6 +20,7 @@
 #include <soc/addressmap.h>
 #include <soc/clock.h>
 #include <stdlib.h>
+#include <symbols.h>
 #include <arch/clock.h>
 #include "clk_rst.h"
 #include "flow.h"
@@ -485,7 +486,7 @@ void clock_cpu0_config(void *entry)
 {
 	void * const evp_cpu_reset = (uint8_t *)TEGRA_EVP_BASE + 0x100;
 
-	write32(CONFIG_STACK_TOP, &maincpu_stack_pointer);
+	write32((uintptr_t)_estack, &maincpu_stack_pointer);
 	write32((uintptr_t)entry, &maincpu_entry_point);
 	write32((uintptr_t)&maincpu_setup, evp_cpu_reset);
 
diff --git a/src/soc/nvidia/tegra124/memlayout.ld b/src/soc/nvidia/tegra124/memlayout.ld
new file mode 100644
index 0000000..0d9e772
--- /dev/null
+++ b/src/soc/nvidia/tegra124/memlayout.ld
@@ -0,0 +1,48 @@
+/*
+ * 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 <memlayout.h>
+#include <vendorcode/google/chromeos/memlayout.h>
+
+#include <arch/header.ld>
+
+/*
+ * Note: The BootROM uses the address range [0x4000_0000:0x4000_E000) itself,
+ * so the bootblock loading address must be placed after that. After the
+ * handoff that area may be reclaimed for other uses, e.g. CBFS cache.
+ */
+
+SECTIONS
+{
+	SRAM_START(0x40000000)
+	TTB(0x40000000, 16K + 32)
+	PRERAM_CBMEM_CONSOLE(0x40004020, 8K - 32)
+	PRERAM_CBFS_CACHE(0x40006000, 16K)
+	VBOOT2_WORK(0x4000A000, 16K)
+	STACK(0x4000E000, 8K)
+	BOOTBLOCK(0x40010000, 24K)
+	VERSTAGE(0x40016000, 72K)
+	ROMSTAGE(0x40028000, 96K)
+	SRAM_END(0x40040000)
+
+	DRAM_START(0x80000000)
+	POSTRAM_CBFS_CACHE(0x80100000, 1M)
+	RAMSTAGE(0x80200000, 128K)
+	DMA_COHERENT(0x90000000, 2M)
+}
diff --git a/src/soc/nvidia/tegra124/sdram.c b/src/soc/nvidia/tegra124/sdram.c
index f0797db..82219b1 100644
--- a/src/soc/nvidia/tegra124/sdram.c
+++ b/src/soc/nvidia/tegra124/sdram.c
@@ -23,6 +23,7 @@
 #include <soc/addressmap.h>
 #include <soc/clock.h>
 #include <stdlib.h>
+#include <symbols.h>
 
 #include "emc.h"
 #include "mc.h"
@@ -643,5 +644,5 @@ int sdram_size_mb(void)
 
 uintptr_t sdram_max_addressable_mb(void)
 {
-	return MIN((CONFIG_SYS_SDRAM_BASE/MiB) + sdram_size_mb(), 4096);
+	return MIN(((uintptr_t)_dram/MiB) + sdram_size_mb(), 4096);
 }
diff --git a/src/soc/nvidia/tegra124/soc.c b/src/soc/nvidia/tegra124/soc.c
index 48e50bd..5da41a9 100644
--- a/src/soc/nvidia/tegra124/soc.c
+++ b/src/soc/nvidia/tegra124/soc.c
@@ -26,6 +26,7 @@
 #include <soc/nvidia/tegra124/sdram.h>
 #include "chip.h"
 #include <soc/display.h>
+#include <symbols.h>
 #include <vendorcode/google/chromeos/chromeos.h>
 
 /* this sucks, but for now, fb size/location are hardcoded.
@@ -37,12 +38,12 @@ static void soc_enable(device_t dev)
 	u32 lcdbase = fb_base_mb();
 	unsigned long fb_size = FB_SIZE_MB;
 
-	ram_resource(dev, 0, CONFIG_SYS_SDRAM_BASE/KiB,
+	ram_resource(dev, 0, (uintptr_t)_dram/KiB,
 		(sdram_max_addressable_mb() - fb_size)*KiB -
-		CONFIG_SYS_SDRAM_BASE/KiB);
+		(uintptr_t)_dram/KiB);
 	mmio_resource(dev, 1, lcdbase*KiB, fb_size*KiB);
 
-	u32 sdram_end_mb = sdram_size_mb() + CONFIG_SYS_SDRAM_BASE/MiB;
+	u32 sdram_end_mb = sdram_size_mb() + (uintptr_t)_dram/MiB;
 
 	if (sdram_end_mb > sdram_max_addressable_mb())
 		ram_resource(dev, 2, sdram_max_addressable_mb()*KiB,
diff --git a/src/soc/nvidia/tegra124/verstage.c b/src/soc/nvidia/tegra124/verstage.c
index 60361a2..2e5ddf2 100644
--- a/src/soc/nvidia/tegra124/verstage.c
+++ b/src/soc/nvidia/tegra124/verstage.c
@@ -22,6 +22,8 @@
 #include <console/console.h>
 #include <soc/nvidia/tegra124/cache.h>
 #include <soc/nvidia/tegra124/early_configs.h>
+#include <stdlib.h>
+#include <symbols.h>
 #include <vendorcode/google/chromeos/chromeos.h>
 
 static void enable_cache(void)
@@ -29,8 +31,9 @@ static void enable_cache(void)
 	mmu_init();
 	/* Whole space is uncached. */
 	mmu_config_range(0, 4096, DCACHE_OFF);
-	/* SRAM is cached. Round the size up to 2MB, the LPAE page size. */
-	mmu_config_range(0x40000000 >> 20, 1, DCACHE_WRITEBACK);
+	/* SRAM is cached. MMU code will round size up to page size. */
+	mmu_config_range((uintptr_t)_sram/MiB, div_round_up(_sram_size, MiB),
+			 DCACHE_WRITEBACK);
 	mmu_disable_range(0, 1);
 	dcache_mmu_enable();
 }
diff --git a/src/soc/nvidia/tegra132/Kconfig b/src/soc/nvidia/tegra132/Kconfig
index 24bf864..c87698a 100644
--- a/src/soc/nvidia/tegra132/Kconfig
+++ b/src/soc/nvidia/tegra132/Kconfig
@@ -43,50 +43,6 @@ config CBFS_ROM_OFFSET
 	hex "offset of CBFS data in ROM"
 	default 0x40080
 
-config BOOTBLOCK_BASE
-	hex
-	default 0x40020000
-
-config ROMSTAGE_BASE
-	hex
-	default 0x40025000
-
-config SYS_SDRAM_BASE
-	hex
-	default 0x80000000
-
-config RAMSTAGE_BASE
-	hex
-	default 0x80200000
-
-config BOOTBLOCK_STACK_TOP
-	hex
-	default 0x40020000
-
-config BOOTBLOCK_STACK_BOTTOM
-	hex
-	default 0x4001c000
-
-config ROMSTAGE_STACK_TOP
-	hex
-	default 0x40020000
-
-config ROMSTAGE_STACK_BOTTOM
-	hex
-	default 0x4001c000
-
-config CBFS_CACHE_ADDRESS
-	hex "memory address to put CBFS cache data"
-	default 0x40006000
-
-config CBFS_CACHE_SIZE
-	hex "size of CBFS cache data"
-	default 0x00016000
-
-config CONSOLE_PRERAM_BUFFER_BASE
-	hex "memory address of the CBMEM console buffer"
-	default 0x40004020
-
 config MTS_DIRECTORY
 	string "Directory where MTS microcode files are located"
 	default "3rdparty/cpu/nvidia/tegra132/current/prod"
diff --git a/src/soc/nvidia/tegra132/Makefile.inc b/src/soc/nvidia/tegra132/Makefile.inc
index 10d4d4e..81d08f5 100644
--- a/src/soc/nvidia/tegra132/Makefile.inc
+++ b/src/soc/nvidia/tegra132/Makefile.inc
@@ -114,7 +114,7 @@ $(objcbfs)/bootblock.bin: $(objcbfs)/bootblock.raw.bin $(BCT_BIN) $(CBOOTIMAGE)
 	echo "Bctcopy    = 1;" >> $(BCT_WRAPPER)
 	echo "Bctfile    = $(BCT_BIN);" >> $(BCT_WRAPPER)
 	echo "MtsPreboot = $(PREBOOT_MTS_FILE),0x4000f000,0x4000f000,Complete;" >> $(BCT_WRAPPER)
-	echo "BootLoader = $<,$(CONFIG_BOOTBLOCK_BASE),$(CONFIG_BOOTBLOCK_BASE),Complete;" >> $(BCT_WRAPPER)
+	echo "BootLoader = $<,$(call loadaddr,bootblock),$(call loadaddr,bootblock),Complete;" >> $(BCT_WRAPPER)
 	@printf "    CBOOTIMAGE $(subst $(obj)/,,$(@))\n"
 	$(CBOOTIMAGE) $(CBOOTIMAGE_OPTS) $(BCT_WRAPPER) $@
 
diff --git a/src/soc/nvidia/tegra132/addressmap.c b/src/soc/nvidia/tegra132/addressmap.c
index a18e1b8..bd644d4 100644
--- a/src/soc/nvidia/tegra132/addressmap.c
+++ b/src/soc/nvidia/tegra132/addressmap.c
@@ -23,6 +23,7 @@
 #include <console/console.h>
 #include <soc/addressmap.h>
 #include <soc/id.h>
+#include <symbols.h>
 #include "mc.h"
 #include "sdram.h"
 
@@ -105,7 +106,7 @@ static void memory_in_range(uintptr_t *base_mib, uintptr_t *end_mib,
 	uintptr_t end;
 	int i;
 
-	base = CONFIG_SYS_SDRAM_BASE / MiB;
+	base = (uintptr_t)_dram / MiB;
 	end = base + sdram_size_mb();
 
 	/* Requested limits out of range. */
diff --git a/src/soc/nvidia/tegra132/bootblock_asm.S b/src/soc/nvidia/tegra132/bootblock_asm.S
index 1b2fbb7..bf63c02 100644
--- a/src/soc/nvidia/tegra132/bootblock_asm.S
+++ b/src/soc/nvidia/tegra132/bootblock_asm.S
@@ -42,17 +42,5 @@ ENTRY(_start)
 	 */
 	msr	cpsr_cxf, #0xdf
 
-	stack_init stack=.Stack size=.Stack_size seed=1 func=main
+	stack_init stack_top=_estack stack_bottom=_stack seed=1 func=main
 ENDPROC(_start)
-
-/* we do it this way because it's a 32-bit constant and
- * in some cases too far away to be loaded as just an offset
- * from IP
- */
-.align 2
-.Stack:
-	.word CONFIG_BOOTBLOCK_STACK_TOP
-.align 2
-/* create this size the same way we do in ramstage.ld: top-bottom */
-.Stack_size:
-	.word CONFIG_BOOTBLOCK_STACK_TOP - CONFIG_BOOTBLOCK_STACK_BOTTOM
diff --git a/src/soc/nvidia/tegra132/cbfs.c b/src/soc/nvidia/tegra132/cbfs.c
index 7b75f7c..648d136 100644
--- a/src/soc/nvidia/tegra132/cbfs.c
+++ b/src/soc/nvidia/tegra132/cbfs.c
@@ -19,12 +19,12 @@
 
 
 #include <cbfs.h>  /* This driver serves as a CBFS media source. */
+#include <symbols.h>
 
 #include "spi.h"
 
 int init_default_cbfs_media(struct cbfs_media *media)
 {
 	return initialize_tegra_spi_cbfs_media(media,
-		(void*)CONFIG_CBFS_CACHE_ADDRESS,
-		CONFIG_CBFS_CACHE_SIZE);
+		_cbfs_cache, _cbfs_cache_size);
 }
diff --git a/src/soc/nvidia/tegra132/memlayout.ld b/src/soc/nvidia/tegra132/memlayout.ld
new file mode 100644
index 0000000..63cf4f0
--- /dev/null
+++ b/src/soc/nvidia/tegra132/memlayout.ld
@@ -0,0 +1,44 @@
+/*
+ * 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 <memlayout.h>
+
+#include <arch/header.ld>
+
+/*
+ * Note: The BootROM uses the address range [0x4000_0000:0x4000_E000) itself,
+ * so the bootblock loading address must be placed after that. After the
+ * handoff that area may be reclaimed for other uses, e.g. CBFS cache.
+ * TODO: Did this change on Tegra132? What's the new valid range?
+ */
+
+SECTIONS
+{
+	SRAM_START(0x40000000)
+	/* 16K hole */
+	PRERAM_CBMEM_CONSOLE(0x40004000, 8K)
+	CBFS_CACHE(0x40006000, 88K)
+	STACK(0x4001C000, 16K)
+	BOOTBLOCK(0x40020000, 20K)
+	ROMSTAGE(0x40025000, 108K)
+	SRAM_END(0x40040000)
+
+	DRAM_START(0x80000000)
+	RAMSTAGE(0x80200000, 192K)
+}
diff --git a/src/soc/nvidia/tegra132/romstage_asm.S b/src/soc/nvidia/tegra132/romstage_asm.S
index ac3c93e..d0b036c 100644
--- a/src/soc/nvidia/tegra132/romstage_asm.S
+++ b/src/soc/nvidia/tegra132/romstage_asm.S
@@ -23,17 +23,5 @@
         .section ".text", "ax", %progbits
 
 ENTRY(main)
-	stack_init stack=.Stack size=.Stack_size seed=0 func=romstage
+	stack_init stack_top=_estack stack_bottom=_stack seed=0 func=romstage
 ENDPROC(main)
-
-/* we do it this way because it's a 32-bit constant and
- * in some cases too far away to be loaded as just an offset
- * from IP
- */
-.align 2
-.Stack:
-	.word CONFIG_ROMSTAGE_STACK_TOP
-.align 2
-.Stack_size:
-	.word CONFIG_ROMSTAGE_STACK_TOP - CONFIG_ROMSTAGE_STACK_BOTTOM
-
diff --git a/src/soc/nvidia/tegra132/stack.S b/src/soc/nvidia/tegra132/stack.S
index 6d3cd4e..3b877e4 100644
--- a/src/soc/nvidia/tegra132/stack.S
+++ b/src/soc/nvidia/tegra132/stack.S
@@ -19,21 +19,19 @@
 
 /* Macro to initialize stack, perform seeding if required and finally call the
  * function provided
- * @stack : Stack address
- * @size  : Stack size
- * @seed  : Stack seeding required (1=yes/otherwise=no)
- * @func  : Function to call after initializing stack
+ * @stack_top    : First address above the stack
+ * @stack_bottom : Lowest address on the stack
+ * @seed         : Stack seeding required (1=yes/otherwise=no)
+ * @func         : Function to call after initializing stack
  */
-.macro stack_init stack, size, seed, func
+.macro stack_init stack_top, stack_bottom, seed, func
         /* Check if stack seeding is required */
 	mov	r0, #\seed
 	cmp     r0, #1
 	bne     call_func
 	/* Stack seeding */
-	ldr     r0, \stack
-	ldr	r1, \size
-	sub	r0, r0, r1
-	ldr	r1, \stack
+	ldr     r0, =\stack_bottom
+	ldr	r1, =\stack_top
 	ldr	r2, =0xdeadbeef
 init_stack_loop:
 	str	r2, [r0]
@@ -42,6 +40,6 @@ init_stack_loop:
 	bne	init_stack_loop
 
 call_func:
-	ldr	sp, \stack /* Set up stack pointer */
+	ldr	sp, =\stack_top /* Set up stack pointer */
 	bl	\func
 .endm
diff --git a/src/soc/qualcomm/ipq806x/Kconfig b/src/soc/qualcomm/ipq806x/Kconfig
index 013d86c..092951d 100644
--- a/src/soc/qualcomm/ipq806x/Kconfig
+++ b/src/soc/qualcomm/ipq806x/Kconfig
@@ -39,44 +39,4 @@ config SBL_BLOB
 	  ipq806x early initialization code, as supplied by the
 	  vendor.
 
-config BOOTBLOCK_BASE
-	hex "256K bytes left for TZBSP"
-	default 0x40600000
-
-config ROMSTAGE_BASE
-	hex
-	default 0x40620000
-
-config RAMSTAGE_BASE
-	hex
-	default 0x40640000
-
-config SYS_SDRAM_BASE
-	hex
-	default 0x40000000
-
-config CBMEM_CONSOLE_PRERAM_BASE
-	hex "memory address of the pre-RAM CBMEM console buffer"
-	default 0x40618000
-
-config STACK_TOP
-	hex
-	default 0x40600000
-
-config STACK_BOTTOM
-	hex
-	default 0x405fc000
-
-config CBFS_CACHE_ADDRESS
-	hex "memory address to put CBFS cache data"
-	default 0x405cc000
-
-config CBFS_CACHE_SIZE
-	hex "size of CBFS cache data"
-	default 0x00030000
-
-config TTB_BUFFER
-	hex "memory address for page tables"
-	default 0x2a05c000
-
 endif
diff --git a/src/soc/qualcomm/ipq806x/Makefile.inc b/src/soc/qualcomm/ipq806x/Makefile.inc
index a7dabc6..5dfca4d 100644
--- a/src/soc/qualcomm/ipq806x/Makefile.inc
+++ b/src/soc/qualcomm/ipq806x/Makefile.inc
@@ -51,7 +51,7 @@ $(objcbfs)/bootblock.raw: $(objcbfs)/bootblock.elf
 # Add MBN header to allow SBL3 to start coreboot bootblock
 $(objcbfs)/bootblock.mbn: $(objcbfs)/bootblock.raw
 	@printf "    ADD MBN    $(subst $(obj)/,,$(@))\n"
-	./util/ipqheader/ipqheader.py $(CONFIG_BOOTBLOCK_BASE) $< $@.tmp
+	./util/ipqheader/ipqheader.py $(call loadaddr,bootblock) $< $@.tmp
 	@mv $@.tmp $@
 
 # Create a complete bootblock which will start up the system
diff --git a/src/soc/qualcomm/ipq806x/cbmem.c b/src/soc/qualcomm/ipq806x/cbmem.c
index ecb02e4..fdf2605 100644
--- a/src/soc/qualcomm/ipq806x/cbmem.c
+++ b/src/soc/qualcomm/ipq806x/cbmem.c
@@ -19,9 +19,9 @@
 
 #include <cbmem.h>
 #include <stddef.h>
+#include <symbols.h>
 
 void *cbmem_top(void)
 {
-	return (void *)((uintptr_t)CONFIG_SYS_SDRAM_BASE +
-					(CONFIG_DRAM_SIZE_MB << 20));
+	return (void *)((uintptr_t)_dram + CONFIG_DRAM_SIZE_MB*MiB);
 }
diff --git a/src/soc/qualcomm/ipq806x/memlayout.ld b/src/soc/qualcomm/ipq806x/memlayout.ld
new file mode 100644
index 0000000..9158c17
--- /dev/null
+++ b/src/soc/qualcomm/ipq806x/memlayout.ld
@@ -0,0 +1,40 @@
+/*
+ * 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 <memlayout.h>
+
+#include <arch/header.ld>
+
+/* TODO: This should be revised by someone who understands the SoC better. */
+
+SECTIONS
+{
+	/* TODO: add SRAM_START(), SRAM_END() and REGION(reserved_sbl) */
+	TTB(0x2A05C000, 16K)
+
+	DRAM_START(0x40000000)
+	CBFS_CACHE(0x405CC000, 192K)
+	STACK(0x405FC000, 16K)
+	/* TODO: "256K bytes left for TZBSP"... what does that mean? */
+	BOOTBLOCK(0x40600000, 32K)
+	PRERAM_CBMEM_CONSOLE(0x40618000, 8K)
+	ROMSTAGE(0x40620000, 128K)
+	RAMSTAGE(0x40640000, 128K)
+	DMA_COHERENT(0x5A000000, 2M)
+}
diff --git a/src/soc/qualcomm/ipq806x/soc.c b/src/soc/qualcomm/ipq806x/soc.c
index 6421ccd..1d63cac 100644
--- a/src/soc/qualcomm/ipq806x/soc.c
+++ b/src/soc/qualcomm/ipq806x/soc.c
@@ -21,16 +21,15 @@
 
 #include <console/console.h>
 #include <device/device.h>
-
+#include <symbols.h>
 
 #define RESERVED_SIZE_KB	(0x01500000 / KiB)
 
 static void soc_read_resources(device_t dev)
 {
 	/* Reserve bottom 0x150_0000 bytes for NSS, SMEM, etc. */
-	reserved_ram_resource(dev, 0,
-			CONFIG_SYS_SDRAM_BASE/KiB, RESERVED_SIZE_KB);
-	ram_resource(dev, 0, CONFIG_SYS_SDRAM_BASE/KiB + RESERVED_SIZE_KB,
+	reserved_ram_resource(dev, 0, (uintptr_t)_dram / KiB, RESERVED_SIZE_KB);
+	ram_resource(dev, 0, (uintptr_t)_dram / KiB + RESERVED_SIZE_KB,
 		     (CONFIG_DRAM_SIZE_MB * KiB) - RESERVED_SIZE_KB);
 }
 
diff --git a/src/soc/rockchip/rk3288/Kconfig b/src/soc/rockchip/rk3288/Kconfig
index 05876f4..0865fe8 100644
--- a/src/soc/rockchip/rk3288/Kconfig
+++ b/src/soc/rockchip/rk3288/Kconfig
@@ -41,51 +41,6 @@ config BOOTBLOCK_CPU_INIT
 # 0x00000 Combined bootblock and ID Block
 # 0x08000 Master CBFS header.
 # 0x18000 Free for CBFS data.
-#
-# iRAM (96k) layout.
-# (Note: The BootROM will jump to 0xff704004 after loading bootblock,
-#  so the bootblock loading address must be at 0xff704004.)
-#
-# 0xFF70_0000 TTB (16KB).
-# 0xFF70_4004 Bootblock (max 16KB-4B).
-# 0xFF70_8000 verstage then romstage (max 40KB).
-# 0xFF71_2000 STACK (4KB).
-# 0xFF71_3000 CBFS mapping cache (4K)
-# 0xFF71_4000 vboot work buffer (16K)
-# 0xFF71_7FFF End of iRAM.
-
-config SYS_SRAM_BASE
-	hex "SRAM base address"
-	default 0xFF700000
-
-config SYS_SDRAM_BASE
-	hex "SDRAM base address"
-	default 0x00000000
-
-config STACK_TOP
-	hex "STACK TOP"
-	default 0xff713000
-
-config STACK_BOTTOM
-	hex "STACK BOTTOM"
-	default 0xff712000
-
-config BOOTBLOCK_BASE
-	hex
-	default 0xff704004
-
-# with vboot2, romstage is loaded over the verstage space
-config VERSTAGE_BASE
-	hex
-	default 0xff708000
-
-config ROMSTAGE_BASE
-	hex "ROM STAGE BASE"
-	default 0xff708000
-
-config RAMSTAGE_BASE
-	hex "RAMSTAGE BASE"
-	default 0x00200000
 
 config BOOTBLOCK_ROM_OFFSET
 	hex
@@ -99,32 +54,4 @@ config CBFS_ROM_OFFSET
 	hex
 	default 0x0018000
 
-config CBFS_SRAM_CACHE_ADDRESS
-	hex "sram memory address to put CBFS cache data"
-	default 0xff713000
-
-config CBFS_SRAM_CACHE_SIZE
-	hex "size of CBFS cache data"
-	default 0x00001000
-
-config VBOOT_WORK_BUFFER_ADDRESS
-	hex "memory address of vboot work buffer"
-	default 0xff714000
-
-config VBOOT_WORK_BUFFER_SIZE
-	hex "size of vboot work buffer"
-	default 0x00004000
-
-config CBFS_DRAM_CACHE_ADDRESS
-	hex "dram memory address to put CBFS cache data"
-	default 0x01000000
-
-config CBFS_DRAM_CACHE_SIZE
-	hex "size of CBFS cache data"
-	default 0x00100000
-
-config TTB_BUFFER
-	hex "memory address of the TTB buffer"
-	default 0xff700000
-
 endif
diff --git a/src/soc/rockchip/rk3288/media.c b/src/soc/rockchip/rk3288/media.c
index 2b023e1..f2471f9 100644
--- a/src/soc/rockchip/rk3288/media.c
+++ b/src/soc/rockchip/rk3288/media.c
@@ -18,19 +18,12 @@
  */
 
 #include <cbfs.h>
-#include <string.h>
-#include <console/console.h>
-#include "soc/rockchip/rk3288/spi.h"
+#include <symbols.h>
+
+#include "spi.h"
 
 int init_default_cbfs_media(struct cbfs_media *media)
 {
-#if defined(__PRE_RAM__) && !defined(__ROMSTAGE__)
-	return initialize_rockchip_spi_cbfs_media(media,
-		(void *)CONFIG_CBFS_SRAM_CACHE_ADDRESS,
-		CONFIG_CBFS_SRAM_CACHE_SIZE);
-#else
 	return initialize_rockchip_spi_cbfs_media(media,
-		(void *)CONFIG_CBFS_DRAM_CACHE_ADDRESS,
-		CONFIG_CBFS_DRAM_CACHE_SIZE);
-#endif
+		_cbfs_cache, _cbfs_cache_size);
 }
diff --git a/src/soc/rockchip/rk3288/memlayout.ld b/src/soc/rockchip/rk3288/memlayout.ld
new file mode 100644
index 0000000..6faec63
--- /dev/null
+++ b/src/soc/rockchip/rk3288/memlayout.ld
@@ -0,0 +1,48 @@
+/*
+ * 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 <memlayout.h>
+#include <vendorcode/google/chromeos/memlayout.h>
+
+#include <arch/header.ld>
+
+/* Note: The BootROM will jump to 0xFF704004 after loading bootblock,
+ * so the bootblock loading address must be at 0xFF704004.
+ */
+SECTIONS
+{
+	DRAM_START(0x00000000)
+	RAMSTAGE(0x00200000, 128K)
+	POSTRAM_CBFS_CACHE(0x01000000, 1M)
+	DMA_COHERENT(0x10000000, 2M)
+
+	SRAM_START(0xFF700000)
+	TTB(0xFF700000, 16K)
+	BOOTBLOCK(0xFF704004, 16K - 4)
+	VBOOT2_WORK(0xFF708000, 16K)
+	OVERLAP_VERSTAGE_ROMSTAGE(0xFF70C000, 40K)
+	PRERAM_CBFS_CACHE(0xFF716000, 4K)
+	STACK(0xFF717000, 4K)
+	SRAM_END(0xFF718000)
+
+	/* 4K of special SRAM in PMU power domain. Careful: only supports 32-bit
+	 * wide write accesses! Only use with MMU and writeback mapping. */
+	SYMBOL(pmu_sram, 0xFF720000)
+	SYMBOL(epmu_sram, 0xFF721000)
+}
diff --git a/src/soc/samsung/exynos5250/Kconfig b/src/soc/samsung/exynos5250/Kconfig
index 3c7d6c4..4126ec1 100644
--- a/src/soc/samsung/exynos5250/Kconfig
+++ b/src/soc/samsung/exynos5250/Kconfig
@@ -32,59 +32,4 @@ config CBFS_ROM_OFFSET
 	hex "offset of CBFS data in ROM"
 	default 0x0A080
 
-config SYS_SDRAM_BASE
-	hex
-	default 0x40000000
-
-# Example SRAM/iRAM map for Exynos5250 platform:
-#
-# 0x0202_0000: vendor-provided BL1
-# 0x0202_3400: bootblock, assume up to 32KB in size
-# 0x0203_0000: romstage, assume up to 128KB in size.
-# 0x0207_8000: stack pointer
-
-config BOOTBLOCK_BASE
-	hex
-	default 0x02023400
-
-config ROMSTAGE_BASE
-	hex
-	default 0x02030000
-
-config RAMSTAGE_BASE
-	hex
-	default SYS_SDRAM_BASE
-
-# Stack may reside in either IRAM or DRAM. We will define it to live
-# at the top of IRAM for now.
-#
-# Stack grows downward, push operation stores register contents in
-# consecutive memory locations ending just below SP
-config STACK_TOP
-	hex
-	default 0x02078000
-
-config STACK_BOTTOM
-	hex
-	default 0x02074000
-
-config STACK_SIZE
-	hex
-	default 0x4000
-
-# TODO We may probably move this to board-specific implementation files instead
-# of KConfig values.
-config CBFS_CACHE_ADDRESS
-	hex "memory address to put CBFS cache data"
-	default 0x0205c000
-
-config CBFS_CACHE_SIZE
-	hex "size of CBFS cache data"
-	default 0x00018000
-
-# TTB needs to be aligned to 16KB.
-config TTB_BUFFER
-	hex "memory address of the TTB buffer"
-	default 0x02058000
-
 endif
diff --git a/src/soc/samsung/exynos5250/alternate_cbfs.c b/src/soc/samsung/exynos5250/alternate_cbfs.c
index 10b33f0..e46221c 100644
--- a/src/soc/samsung/exynos5250/alternate_cbfs.c
+++ b/src/soc/samsung/exynos5250/alternate_cbfs.c
@@ -22,6 +22,7 @@
 #include <cbfs.h>  /* This driver serves as a CBFS media source. */
 #include <stdlib.h>
 #include <string.h>
+#include <symbols.h>
 #include <console/console.h>
 #include "alternate_cbfs.h"
 #include "power.h"
@@ -33,14 +34,14 @@
  * by the IROM / BL1, so this code has nothing to do with them.
  *
  * The third transfer is a valid CBFS image that contains only the romstage,
- * and must be small enough to fit into alternate_cbfs_size[__BOOT_BLOCK__] in
+ * and must be small enough to fit into the PRE_RAM CBFS cache in
  * IRAM. It is loaded when this function gets called in the boot block, and
  * the normal CBFS code extracts the romstage from it.
  *
  * The fourth transfer is also a CBFS image, but can be of arbitrary size and
  * should contain all available stages/payloads/etc. It is loaded when this
  * function is called a second time at the end of the romstage, and copied to
- * alternate_cbfs_buffer[!__BOOT_BLOCK__] in DRAM. It will reside there for the
+ * the romstage/ramstage CBFS cache in DRAM. It will reside there for the
  * rest of the firmware's lifetime and all subsequent stages (which will not
  * have __PRE_RAM__ defined) can just directly reference it there.
  */
@@ -60,12 +61,12 @@ static int usb_cbfs_open(struct cbfs_media *media)
 
 	/*
 	 * We need to trust the host/irom to copy the image to our
-	 * alternate_cbfs_buffer address... there is no way to control or even
+	 * _cbfs_cache address... there is no way to control or even
 	 * check the transfer size or target address from our side.
 	 */
 
 	printk(BIOS_DEBUG, "USB A-A transfer successful, CBFS image should now"
-		" be at %p\n", alternate_cbfs_buffer);
+		" be at %p\n", _cbfs_cache);
 	first_run = 0;
 #endif
 	return 0;
@@ -86,11 +87,11 @@ static int sdmmc_cbfs_open(struct cbfs_media *media)
 	 * In the bootblock, we just copy the small part that fits in the buffer
 	 * and hope that it's enough (since the romstage is currently always the
 	 * first component in the image, this should work out). In the romstage,
-	 * we copy until our buffer is full (currently 12M) to avoid the pain of
+	 * we copy until our cache is full (currently 12M) to avoid the pain of
 	 * figuring out the true image size from in here. Since this is mainly a
 	 * developer/debug boot mode, those shortcomings should be bearable.
 	 */
-	const u32 count = alternate_cbfs_size / 512;
+	const u32 count = _cbfs_cache_size / 512;
 	static int first_run = 1;
 	int (*irom_load_sdmmc)(u32 start, u32 count, void *dst) =
 		*irom_sdmmc_read_blocks_ptr;
@@ -98,13 +99,13 @@ static int sdmmc_cbfs_open(struct cbfs_media *media)
 	if (!first_run)
 		return 0;
 
-	if (!irom_load_sdmmc(1, count, alternate_cbfs_buffer)) {
+	if (!irom_load_sdmmc(1, count, _cbfs_cache)) {
 		printk(BIOS_EMERG, "Unable to load CBFS image from SDMMC!\n");
 		return -1;
 	}
 
 	printk(BIOS_DEBUG, "SDMMC read successful, CBFS image should now be"
-		" at %p\n", alternate_cbfs_buffer);
+		" at %p\n", _cbfs_cache);
 	first_run = 0;
 #endif
 	return 0;
@@ -115,16 +116,16 @@ 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 < alternate_cbfs_size);
-	memcpy(dest, alternate_cbfs_buffer + offset, count);
+	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 < alternate_cbfs_size);
-	return alternate_cbfs_buffer + offset;
+	ASSERT(offset + count < _cbfs_cache_size);
+	return _cbfs_cache + offset;
 }
 
 static void *alternate_cbfs_unmap(struct cbfs_media *media,
@@ -166,8 +167,7 @@ int init_default_cbfs_media(struct cbfs_media *media)
 		return initialize_exynos_sdmmc_cbfs_media(media);
 	case OM_STAT_SPI:
 		return initialize_exynos_spi_cbfs_media(media,
-			(void*)CONFIG_CBFS_CACHE_ADDRESS,
-			CONFIG_CBFS_CACHE_SIZE);
+			_cbfs_cache, _cbfs_cache_size);
 	default:
 		printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
 			exynos_power->om_stat);
diff --git a/src/soc/samsung/exynos5250/alternate_cbfs.h b/src/soc/samsung/exynos5250/alternate_cbfs.h
index a064b62..fe1af46 100644
--- a/src/soc/samsung/exynos5250/alternate_cbfs.h
+++ b/src/soc/samsung/exynos5250/alternate_cbfs.h
@@ -36,16 +36,4 @@ static u32 * const iram_secondary_base = (u32 *)0x02020018;
 #define OM_STAT_SPI  0x14
 #define OM_STAT_MASK 0x7f
 
-#if defined(__PRE_RAM__) && !defined(__ROMSTAGE__)
-	/* A small space in IRAM to hold the romstage-only image */
-	static void * const alternate_cbfs_buffer =
-			(void *)CONFIG_CBFS_CACHE_ADDRESS;
-	static size_t const alternate_cbfs_size = CONFIG_CBFS_CACHE_SIZE;
-#else
-	/* Just put this anywhere in RAM that's far enough from anything else */
-	/* TODO: Find a better way to "reserve" this region? */
-	static void * const alternate_cbfs_buffer = (void *)0x77400000;
-	static size_t const alternate_cbfs_size = 0xc00000;
-#endif
-
 #endif
diff --git a/src/soc/samsung/exynos5250/cpu.h b/src/soc/samsung/exynos5250/cpu.h
index 10f9ef4..c9c5832 100644
--- a/src/soc/samsung/exynos5250/cpu.h
+++ b/src/soc/samsung/exynos5250/cpu.h
@@ -21,6 +21,7 @@
 #define CPU_SAMSUNG_EXYNOS5250_CPU_H
 
 #include <arch/io.h>
+#include <symbols.h>
 
 /* Base address registers */
 #define EXYNOS5_GPIO_PART6_BASE		0x03860000	/* Z<6:0> */
@@ -76,7 +77,7 @@ extern struct tmu_info exynos5250_tmu_info;
 
 /* TODO clean up defines. */
 #define FB_SIZE_KB  4096
-#define RAM_BASE_KB (CONFIG_SYS_SDRAM_BASE >> 10)
+#define RAM_BASE_KB ((uintptr_t)_dram/KiB)
 #define RAM_SIZE_KB (CONFIG_DRAM_SIZE_MB << 10UL)
 
 static inline u32 get_fb_base_kb(void)
diff --git a/src/soc/samsung/exynos5250/memlayout.ld b/src/soc/samsung/exynos5250/memlayout.ld
new file mode 100644
index 0000000..010bb7b
--- /dev/null
+++ b/src/soc/samsung/exynos5250/memlayout.ld
@@ -0,0 +1,46 @@
+/*
+ * 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 <memlayout.h>
+
+#include <arch/header.ld>
+
+/*
+ * Note: The BootROM loads the 8K BL1 at [0x2020000:0x2022000), so the bootblock
+ * must be placed after that. After the handoff, the space can be reclaimed.
+ */
+
+SECTIONS
+{
+	SRAM_START(0x2020000)
+	/* 13K hole, includes BL1 */
+	BOOTBLOCK(0x2023400, 32K)
+	/* 19K hole */
+	ROMSTAGE(0x2030000, 128K)
+	/* 32K hole */
+	TTB(0x2058000, 16K)
+	PRERAM_CBFS_CACHE(0x205C000, 96K)
+	STACK(0x2074000, 16K)
+	SRAM_END(0x2078000)
+
+	DRAM_START(0x40000000)
+	RAMSTAGE(0x40000000, 128K)
+	POSTRAM_CBFS_CACHE(0x41000000, 8M)
+	DMA_COHERENT(0x77300000, 1M)
+}
diff --git a/src/soc/samsung/exynos5420/Kconfig b/src/soc/samsung/exynos5420/Kconfig
index bd2bf13..ed9d2f8 100644
--- a/src/soc/samsung/exynos5420/Kconfig
+++ b/src/soc/samsung/exynos5420/Kconfig
@@ -33,78 +33,4 @@ config CBFS_ROM_OFFSET
 	hex "offset of CBFS data in ROM"
 	default 0x0A000
 
-config SYS_SDRAM_BASE
-	hex
-	default 0x20000000
-
-# Example SRAM/iRAM map for Exynos5420 platform:
-#
-# 0x0202_0000: vendor-provided BL1
-# 0x0202_4400: variable length bootblock checksum header.
-# 0x0202_4410: bootblock, assume up to 32KB in size
-# 0x0203_0000: romstage, assume up to 128KB in size.
-# 0x0205_8000: TTB buffer.
-# 0x0205_c000: cache for CBFS data.
-# 0x0206_f000: stack bottom
-# 0x0207_3000: stack pointer
-# 0x0207_3000: shared (with kernel) page for cpu & secondary core states.
-#              the shared data is currently only <0x50 bytes so we can share
-#              this page with stack.
-
-config BOOTBLOCK_BASE
-	hex
-	default 0x02024410
-
-config ROMSTAGE_BASE
-	hex
-	default 0x02030000
-
-config RAMSTAGE_BASE
-	hex
-	default SYS_SDRAM_BASE
-
-# Stack may reside in either IRAM or DRAM. We will define it to live
-# at the top of IRAM for now.
-#
-# Stack grows downward, push operation stores register contents in
-# consecutive memory locations ending just below SP.
-# The setup in the exynos 5420 is a new one for coreboot. We have got
-# the bootblock, romstage, and ramstage sharing the same stack space.
-# The SRAM is always there and having a known-good stack memory
-# makes for a more reliable setup.
-# Thus, in this case:
-# STACK_TOP: highest stack address in SRAM
-# STACK_BOTTOM: lowest stack address in SRAM
-# STACK_SIZE: as in standard coreboot usage, size of thread stacks in ramstage
-# ROMSTAGE_STACK_SIZE: size of the single stack in romstage
-
-config STACK_TOP
-	hex
-	default 0x02073000
-
-config STACK_BOTTOM
-	hex
-	default 0x0206f000
-
-# STACK_SIZE is for the ramstage core and thread stacks.
-# It must be a power of 2, to make the cpu_info computation work,
-# and cpu_info needs to work to make SMP startup and threads work.
-config STACK_SIZE
-	hex
-	default 0x0800
-
-# TODO We may probably move this to board-specific implementation files instead
-# of KConfig values.
-config CBFS_CACHE_ADDRESS
-	hex "memory address to put CBFS cache data"
-	default 0x0205c000
-
-config CBFS_CACHE_SIZE
-	hex "size of CBFS cache data"
-	default 0x00013000
-
-config TTB_BUFFER
-	hex "memory address of the TTB buffer"
-	default 0x02058000
-
 endif
diff --git a/src/soc/samsung/exynos5420/alternate_cbfs.c b/src/soc/samsung/exynos5420/alternate_cbfs.c
index d19098b..7fc0e6d 100644
--- a/src/soc/samsung/exynos5420/alternate_cbfs.c
+++ b/src/soc/samsung/exynos5420/alternate_cbfs.c
@@ -22,6 +22,7 @@
 #include <cbfs.h>  /* This driver serves as a CBFS media source. */
 #include <stdlib.h>
 #include <string.h>
+#include <symbols.h>
 #include <arch/cache.h>
 #include <console/console.h>
 #include "alternate_cbfs.h"
@@ -34,14 +35,14 @@
  * by the IROM / BL1, so this code has nothing to do with them.
  *
  * The third transfer is a valid CBFS image that contains only the romstage,
- * and must be small enough to fit into alternate_cbfs_size[__BOOT_BLOCK__] in
+ * and must be small enough to fit into the PRE_RAM CBFS cache in
  * IRAM. It is loaded when this function gets called in the boot block, and
  * the normal CBFS code extracts the romstage from it.
  *
  * The fourth transfer is also a CBFS image, but can be of arbitrary size and
  * should contain all available stages/payloads/etc. It is loaded when this
  * function is called a second time at the end of the romstage, and copied to
- * alternate_cbfs_buffer[!__BOOT_BLOCK__] in DRAM. It will reside there for the
+ * the romstage/ramstage CBFS cache in DRAM. It will reside there for the
  * rest of the firmware's lifetime and all subsequent stages (which will not
  * have __PRE_RAM__ defined) can just directly reference it there.
  */
@@ -64,12 +65,12 @@ static int usb_cbfs_open(struct cbfs_media *media)
 
 	/*
 	 * We need to trust the host/irom to copy the image to our
-	 * alternate_cbfs_buffer address... there is no way to control or even
+	 * _cbfs_cache address... there is no way to control or even
 	 * check the transfer size or target address from our side.
 	 */
 
 	printk(BIOS_DEBUG, "USB A-A transfer successful, CBFS image should now"
-		" be at %p\n", alternate_cbfs_buffer);
+		" be at %p\n", _cbfs_cache);
 	first_run = 0;
 #endif
 	return 0;
@@ -90,11 +91,11 @@ static int sdmmc_cbfs_open(struct cbfs_media *media)
 	 * In the bootblock, we just copy the small part that fits in the buffer
 	 * and hope that it's enough (since the romstage is currently always the
 	 * first component in the image, this should work out). In the romstage,
-	 * we copy until our buffer is full (currently 12M) to avoid the pain of
+	 * we copy until our cache is full (currently 12M) to avoid the pain of
 	 * figuring out the true image size from in here. Since this is mainly a
 	 * developer/debug boot mode, those shortcomings should be bearable.
 	 */
-	const u32 count = alternate_cbfs_size / 512;
+	const u32 count = _cbfs_cache_size / 512;
 	static int first_run = 1;
 	int (*irom_load_sdmmc)(u32 start, u32 count, void *dst) =
 		*irom_sdmmc_read_blocks_ptr;
@@ -103,7 +104,7 @@ static int sdmmc_cbfs_open(struct cbfs_media *media)
 		return 0;
 
 	dcache_mmu_disable();
-	if (!irom_load_sdmmc(1, count, alternate_cbfs_buffer)) {
+	if (!irom_load_sdmmc(1, count, _cbfs_cache)) {
 		dcache_mmu_enable();
 		printk(BIOS_EMERG, "Unable to load CBFS image from SDMMC!\n");
 		return -1;
@@ -111,7 +112,7 @@ static int sdmmc_cbfs_open(struct cbfs_media *media)
 	dcache_mmu_enable();
 
 	printk(BIOS_DEBUG, "SDMMC read successful, CBFS image should now be"
-		" at %p\n", alternate_cbfs_buffer);
+		" at %p\n", _cbfs_cache);
 	first_run = 0;
 #endif
 	return 0;
@@ -122,16 +123,16 @@ 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 < alternate_cbfs_size);
-	memcpy(dest, alternate_cbfs_buffer + offset, count);
+	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 < alternate_cbfs_size);
-	return alternate_cbfs_buffer + offset;
+	ASSERT(offset + count < _cbfs_cache_size);
+	return _cbfs_cache + offset;
 }
 
 static void *alternate_cbfs_unmap(struct cbfs_media *media,
@@ -173,8 +174,7 @@ int init_default_cbfs_media(struct cbfs_media *media)
 		return initialize_exynos_sdmmc_cbfs_media(media);
 	case OM_STAT_SPI:
 		return initialize_exynos_spi_cbfs_media(media,
-			(void*)CONFIG_CBFS_CACHE_ADDRESS,
-			CONFIG_CBFS_CACHE_SIZE);
+			_cbfs_cache, _cbfs_cache_size);
 	default:
 		printk(BIOS_EMERG, "Exynos OM_STAT value 0x%x not supported!\n",
 			exynos_power->om_stat);
diff --git a/src/soc/samsung/exynos5420/alternate_cbfs.h b/src/soc/samsung/exynos5420/alternate_cbfs.h
index 8122a25..4df61d5 100644
--- a/src/soc/samsung/exynos5420/alternate_cbfs.h
+++ b/src/soc/samsung/exynos5420/alternate_cbfs.h
@@ -36,16 +36,4 @@ static u32 * const iram_secondary_base = (u32 *)0x02020018;
 #define OM_STAT_SPI  0x14
 #define OM_STAT_MASK 0x7f
 
-#if defined(__PRE_RAM__) && !defined(__ROMSTAGE__)
-	/* A small space in IRAM to hold the romstage-only image */
-	static void * const alternate_cbfs_buffer =
-			(void *)CONFIG_CBFS_CACHE_ADDRESS;
-	static size_t const alternate_cbfs_size = CONFIG_CBFS_CACHE_SIZE;
-#else
-	/* Just put this anywhere in RAM that's far enough from anything else */
-	/* TODO: Find a better way to "reserve" this region? */
-	static void * const alternate_cbfs_buffer = (void *)0x77400000;
-	static size_t const alternate_cbfs_size = 0xc00000;
-#endif
-
 #endif /* CPU_SAMSUNG_EXYNOS5420_ALTERNATE_CBFS_H */
diff --git a/src/soc/samsung/exynos5420/cpu.h b/src/soc/samsung/exynos5420/cpu.h
index 5b5c731..bea7f1e 100644
--- a/src/soc/samsung/exynos5420/cpu.h
+++ b/src/soc/samsung/exynos5420/cpu.h
@@ -21,6 +21,7 @@
 #define CPU_SAMSUNG_EXYNOS5420_CPU_H
 
 #include <arch/io.h>
+#include <symbols.h>
 
 #define EXYNOS5_SRAM_BASE		0x02020000
 
@@ -84,7 +85,7 @@ extern struct tmu_info exynos5420_tmu_info;
 
 /* TODO clean up defines. */
 #define FB_SIZE_KB  4096
-#define RAM_BASE_KB (CONFIG_SYS_SDRAM_BASE >> 10)
+#define RAM_BASE_KB ((uintptr_t)_dram/KiB)
 #define RAM_SIZE_KB (CONFIG_DRAM_SIZE_MB << 10UL)
 
 static inline u32 get_fb_base_kb(void)
diff --git a/src/soc/samsung/exynos5420/memlayout.ld b/src/soc/samsung/exynos5420/memlayout.ld
new file mode 100644
index 0000000..3259ff9
--- /dev/null
+++ b/src/soc/samsung/exynos5420/memlayout.ld
@@ -0,0 +1,49 @@
+/*
+ * 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 <memlayout.h>
+
+#include <arch/header.ld>
+
+/*
+ * Note: The BootROM loads the 8K BL1 at [0x2020000:0x2022000), so the bootblock
+ * must be placed after that. After the handoff, the space can be reclaimed.
+ */
+
+SECTIONS
+{
+	SRAM_START(0x2020000)
+	/* 17K hole, includes BL1 */
+	/* Bootblock is preceeded by 16 byte variable length BL2 checksum. */
+	BOOTBLOCK(0x2024410, 32K - 16)
+	/* 15K hole */
+	ROMSTAGE(0x2030000, 128K)
+	/* 32K hole */
+	TTB(0x2058000, 16K)
+	PRERAM_CBFS_CACHE(0x205C000, 76K)
+	STACK(0x206F000, 16K)
+	/* 1K hole for weird kernel-shared CPU/SMP state structure that doesn't
+	 * seem to be implemented right now? */
+	SRAM_END(0x2074000)
+
+	DRAM_START(0x20000000)
+	RAMSTAGE(0x20000000, 128K)
+	POSTRAM_CBFS_CACHE(0x21000000, 8M)
+	DMA_COHERENT(0x77300000, 1M)
+}
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index c445135..f43a87e 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -110,6 +110,8 @@ verstage-$(CONFIG_CHROMEOS_VBNV_EC) += vbnv_ec.c
 verstage-$(CONFIG_CHROMEOS_VBNV_FLASH) += vbnv_flash.c
 romstage-y += vboot_handoff.c
 
+verstage-y += verstage.ld
+
 VB_FIRMWARE_ARCH := $(ARCHDIR-$(ARCH-VERSTAGE-y))
 VB2_LIB = $(obj)/external/vboot_reference/vboot_fw2.a
 VBOOT_CFLAGS += $(patsubst -I%,-I$(top)/%,$(filter-out -include $(src)/include/kconfig.h, $(CFLAGS_verstage) $(CPPFLAGS_verstage)))
diff --git a/src/vendorcode/google/chromeos/chromeos.c b/src/vendorcode/google/chromeos/chromeos.c
index edaa0d9..c4d651a 100644
--- a/src/vendorcode/google/chromeos/chromeos.c
+++ b/src/vendorcode/google/chromeos/chromeos.c
@@ -22,6 +22,7 @@
 #include "chromeos.h"
 #if CONFIG_VBOOT_VERIFY_FIRMWARE || CONFIG_VBOOT2_VERIFY_FIRMWARE
 #include "fmap.h"
+#include "symbols.h"
 #include "vboot_handoff.h"
 #include <reset.h>
 #endif
@@ -253,7 +254,7 @@ void *vboot_load_stage(int stage_index,
 
 struct vb2_working_data * const vboot_get_working_data(void)
 {
-	return (struct vb2_working_data *)CONFIG_VBOOT_WORK_BUFFER_ADDRESS;
+	return (struct vb2_working_data *)_vboot2_work;
 }
 
 void vboot_reboot(void)
diff --git a/src/vendorcode/google/chromeos/memlayout.h b/src/vendorcode/google/chromeos/memlayout.h
new file mode 100644
index 0000000..468f746
--- /dev/null
+++ b/src/vendorcode/google/chromeos/memlayout.h
@@ -0,0 +1,47 @@
+/*
+ * 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
+ */
+
+/* This file contains macro definitions for memlayout.ld linker scripts. */
+
+#ifndef __CHROMEOS_MEMLAYOUT_H
+#define __CHROMEOS_MEMLAYOUT_H
+
+#define VBOOT2_WORK(addr, size) \
+	REGION(vboot2_work, addr, size, 4) \
+	_ = ASSERT(size >= 16K, "vboot2 work buffer must be at least 16K!");
+
+#ifdef __VERSTAGE__
+	#define VERSTAGE(addr, sz) \
+		SET_COUNTER(VERSTAGE, addr) \
+		_ = ASSERT(_everstage - _verstage <= sz, \
+			STR(Verstage exceeded its allotted size! (sz))); \
+		INCLUDE "vendorcode/google/chromeos/verstage.verstage.ld"
+#else
+	#define VERSTAGE(addr, sz) \
+		SET_COUNTER(VERSTAGE, addr) \
+		. += sz;
+#endif
+
+#ifdef __VERSTAGE__
+	#define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) VERSTAGE(addr, size)
+#else
+	#define OVERLAP_VERSTAGE_ROMSTAGE(addr, size) ROMSTAGE(addr, size)
+#endif
+
+#endif /* __CHROMEOS_MEMLAYOUT_H */
diff --git a/src/vendorcode/google/chromeos/symbols.h b/src/vendorcode/google/chromeos/symbols.h
new file mode 100644
index 0000000..21169f0
--- /dev/null
+++ b/src/vendorcode/google/chromeos/symbols.h
@@ -0,0 +1,32 @@
+/*
+ * 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
+ */
+
+#ifndef __CHROMEOS_SYMBOLS_H
+#define __CHROMEOS_SYMBOLS_H
+
+extern u8 _vboot2_work[];
+extern u8 _evboot2_work[];
+#define _vboot2_work_size (_evboot2_work - _vboot2_work)
+
+/* Careful: _e<stage> and _<stage>_size only defined for the current stage! */
+extern u8 _verstage[];
+extern u8 _everstage[];
+#define _verstage_size (_everstage - _verstage)
+
+#endif /* __CHROMEOS_SYMBOLS_H */
diff --git a/src/vendorcode/google/chromeos/verstage.ld b/src/vendorcode/google/chromeos/verstage.ld
new file mode 100644
index 0000000..c7fd646
--- /dev/null
+++ b/src/vendorcode/google/chromeos/verstage.ld
@@ -0,0 +1,58 @@
+/*
+ * 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
+ */
+
+/* This file is included inside a SECTIONS block */
+
+.text . : {
+	_program = .;
+	_verstage = .;
+	*(.text._start);
+	*(.text.stage_entry);
+	*(.text);
+	*(.text.*);
+} : to_load
+
+.data . : {
+	*(.rodata);
+	*(.rodata.*);
+	*(.data);
+	*(.data.*);
+	. = ALIGN(8);
+}
+
+.bss . : {
+	. = ALIGN(8);
+	_bss = .;
+	*(.bss)
+	*(.bss.*)
+	*(.sbss)
+	*(.sbss.*)
+	_ebss = .;
+	_everstage = .;
+	_eprogram = .;
+}
+
+/* Discard the sections we don't need/want */
+/DISCARD/ : {
+	*(.comment)
+	*(.note)
+	*(.comment.*)
+	*(.note.*)
+	*(.eh_frame);
+}
diff --git a/src/vendorcode/google/chromeos/verstub.c b/src/vendorcode/google/chromeos/verstub.c
index e295b25..eb91c22 100644
--- a/src/vendorcode/google/chromeos/verstub.c
+++ b/src/vendorcode/google/chromeos/verstub.c
@@ -22,17 +22,18 @@
 #include <console/console.h>
 #include <string.h>
 #include "chromeos.h"
+#include "symbols.h"
 
 static struct vb2_working_data *init_vb2_working_data(void)
 {
 	struct vb2_working_data *wd;
 
 	wd = vboot_get_working_data();
-	memset(wd, 0, CONFIG_VBOOT_WORK_BUFFER_SIZE);
+	memset(wd, 0, _vboot2_work_size);
 	/* 8-byte alignment for ARMv7 */
 	wd->buffer = ALIGN_UP((uintptr_t)&wd[1], 8);
-	wd->buffer_size = CONFIG_VBOOT_WORK_BUFFER_SIZE + (uintptr_t)wd
-			- (uintptr_t)wd->buffer;
+	wd->buffer_size = _vboot2_work_size + (uintptr_t)wd
+			                    - (uintptr_t)wd->buffer;
 
 	return wd;
 }



More information about the coreboot-gerrit mailing list