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@chromium.org>
Original-Commit-Id: f1e2028e7ebceeb2d71ff366150a37564595e614
Original-Change-Id: I005506add4e8fcdb74db6d5e6cb2d4cb1bd3cda5
Original-Signed-off-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/213370
Reviewed-on: http://review.coreboot.org/9283
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Tauner <stefan.tauner@gmx.at>
Reviewed-by: Aaron Durbin <adurbin@google.com>
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 @@
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 @@
/*
* 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 @@
* 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 @@
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 @@
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 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 @@
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 @@
#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 @@
/* 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)
+}