summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Short <keithshort@chromium.org>2020-07-19 16:23:23 -0600
committerCommit Bot <commit-bot@chromium.org>2020-08-13 14:26:53 +0000
commite0bf946ced052fe5e857b42da666ba252b03da95 (patch)
treed5218c56b92ecf3e27e62af0a19c8e9d34443134
parent8ce0c16cc2d153b0002fbea64d08c09d98c3835f (diff)
downloadchrome-ec-e0bf946ced052fe5e857b42da666ba252b03da95.tar.gz
npcx: add support for rom resident sections
EC images are copied in full from flash to RAM. When the code RAM size is smaller than 1/2 the flash size, the EC image size is limited to the code RAM size, leaving unused flash space. Create a new linker section .init_rom used to store data objects that are single use in the previously unused flash area. Data objects can be used at runtime by copying into RAM using the flash_read() function. This change is tied to the NPCX flash layout, with asserts to ensure builds fail if the CONFIG_CHIP_INIT_ROM_REGION is not supported by the chip. CLs that enable CONFIG_CHIP_INIT_ROM_REGION should not be merged until the predecessor CL:2325764 is available in CPFE images. BUG=b:160330682 BRANCH=none TEST=make buildall TEST=With debug code, use the _init_rom macro and validate the data can be read using flash_read(). TEST=Using hex editor, verify .init_rom section located at 192K boundary and unused bytes are filled with 0xFF. TEST=compare_build.sh passes when run against waddledoo (npcx, cortex-m) Signed-off-by: Keith Short <keithshort@chromium.org> Change-Id: Ia0785798fd1938ad6a1c254a070b219027ee82a3 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2311268 Reviewed-by: caveh jalali <caveh@chromium.org> Commit-Queue: caveh jalali <caveh@chromium.org>
-rw-r--r--chip/npcx/build.mk13
-rw-r--r--chip/npcx/config_flash_layout.h12
-rw-r--r--core/cortex-m/ec.lds.S117
-rw-r--r--core/cortex-m0/ec.lds.S13
-rw-r--r--core/minute-ia/ec.lds.S13
-rw-r--r--core/nds32/ec.lds.S13
-rw-r--r--core/riscv-rv32i/ec.lds.S13
-rw-r--r--include/common.h13
-rw-r--r--include/config.h58
9 files changed, 262 insertions, 3 deletions
diff --git a/chip/npcx/build.mk b/chip/npcx/build.mk
index 81294edfbb..f33089bc60 100644
--- a/chip/npcx/build.mk
+++ b/chip/npcx/build.mk
@@ -58,9 +58,18 @@ endif
# ECST tool is for filling the header used by booter of npcx EC
show_esct_cmd=$(if $(V),,echo ' ECST ' $(subst $(out)/,,$@) ; )
+# Get the firmware length from the mapfile. This can differ from the file
+# size when the CONFIG_CHIP_INIT_ROM_REGION is used. Note that the -fwlen
+# parameter for the ecst utility must be in hex.
+cmd_fwlen=$(shell awk '\
+ /__flash_used =/ {flash_used = strtonum($$1)} \
+ END {printf ("%x", flash_used)}' $(1))
+
# ECST options for header
-bld_ecst=${out}/util/ecst -chip $(CHIP_VARIANT) -usearmrst -mode bt -ph -i $(1) -o $(2) -nohcrc \
--nofcrc -flashsize 8 -spimaxclk 50 -spireadmode dual 1> /dev/null
+bld_ecst=${out}/util/ecst -chip $(CHIP_VARIANT) \
+ -usearmrst -mode bt -ph -i $(1) -o $(2) -nohcrc -nofcrc -flashsize 8 \
+ -fwlen $(call cmd_fwlen, $(patsubst %.flat,%.map,$(2))) \
+ -spimaxclk 50 -spireadmode dual 1> /dev/null
# Replace original one with the flat file including header
moveflat=mv -f $(1) $(2)
diff --git a/chip/npcx/config_flash_layout.h b/chip/npcx/config_flash_layout.h
index 3ed9af4bc3..7aebe172c7 100644
--- a/chip/npcx/config_flash_layout.h
+++ b/chip/npcx/config_flash_layout.h
@@ -59,12 +59,24 @@
#define CONFIG_RO_SIZE NPCX_PROGRAM_MEMORY_SIZE
/*
+ * ROM resident area in flash used to store data objects that are not copied
+ * into code RAM. Enable using the CONFIG_CHIP_INIT_ROM_REGION option.
+ */
+#define CONFIG_RO_ROM_RESIDENT_MEM_OFF CONFIG_RO_SIZE
+#define CONFIG_RO_ROM_RESIDENT_SIZE \
+ (CONFIG_EC_PROTECTED_STORAGE_SIZE - CONFIG_RO_SIZE)
+
+/*
* RW firmware in program memory - Identical to RO, only one image loaded at
* a time.
*/
#define CONFIG_RW_MEM_OFF CONFIG_RO_MEM_OFF
#define CONFIG_RW_SIZE CONFIG_RO_SIZE
+#define CONFIG_RW_ROM_RESIDENT_MEM_OFF CONFIG_RW_SIZE
+#define CONFIG_RW_ROM_RESIDENT_SIZE \
+ (CONFIG_EC_WRITABLE_STORAGE_SIZE - CONFIG_RW_SIZE)
+
#if (CONFIG_RO_SIZE != CONFIG_RW_SIZE)
#error "Unsupported.. FLASH_ERASE_SIZE assumes RO and RW size is same!"
#endif
diff --git a/core/cortex-m/ec.lds.S b/core/cortex-m/ec.lds.S
index c24ee8321b..ed57a29529 100644
--- a/core/cortex-m/ec.lds.S
+++ b/core/cortex-m/ec.lds.S
@@ -6,6 +6,11 @@
#include "config.h"
#include "rwsig.h"
+#define CONCAT_STAGE_1(w, x, y, z) w ## x ## y ## z
+#define CONCAT2(w, x) CONCAT_STAGE_1(w, x, , )
+#define CONCAT3(w, x, y) CONCAT_STAGE_1(w, x, y, )
+#define CONCAT4(w, x, y, z) CONCAT_STAGE_1(w, x, y, z)
+
#define STRINGIFY0(name) #name
#define STRINGIFY(name) STRINGIFY0(name)
@@ -20,6 +25,30 @@
#define FW_SIZE_(section) CONFIG_##section##_SIZE
#define FW_SIZE(section) FW_SIZE_(section)
+/*
+ * Define the VMA (virtual memory address) of the ROM_RESIDENT region within
+ * the EC image. This is full 32-bit address starting from
+ * CONFIG_PROGRAM_MEMORY_BASE.
+ */
+#define ROM_RES_OFF(section) FW_OFF(CONCAT2(section, _ROM_RESIDENT))
+#define ROM_RES_SIZE(section) FW_SIZE(CONCAT2(section, _ROM_RESIDENT))
+
+/*
+ * Define the VMA (virtual memory address) of the ROM_RESIDENT region. Instead
+ * of a full 32-bit address, set the VMA to be an offset within the flash memory
+ * section. Objects linked into this section can pass the address of the
+ * object unmodified to the public APIs of the flash and init_rom modules.
+ */
+#ifdef SECTION_IS_RO
+#define ROM_RES_FLASH_OFF(section) \
+ FW_MEM_OFF(CONCAT2(section, _ROM_RESIDENT)) + \
+ CONFIG_EC_PROTECTED_STORAGE_OFF
+#else
+#define ROM_RES_FLASH_OFF(section) \
+ FW_MEM_OFF(CONCAT2(section, _ROM_RESIDENT)) + \
+ CONFIG_EC_WRITABLE_STORAGE_OFF
+#endif
+
/* Indicates where .data LMA should reside. */
#undef DATA_LMA_MEM_REGION
@@ -45,6 +74,15 @@ MEMORY
#else
FLASH (rx) : ORIGIN = FW_OFF(SECTION), LENGTH = FW_SIZE(SECTION)
#endif
+#ifdef CONFIG_CHIP_INIT_ROM_REGION
+ ROM_RESIDENT (r) : \
+ ORIGIN = ROM_RES_OFF(SECTION), \
+ LENGTH = ROM_RES_SIZE(SECTION)
+
+ ROM_RESIDENT_VMA (r) : \
+ ORIGIN = ROM_RES_FLASH_OFF(SECTION), \
+ LENGTH = ROM_RES_SIZE(SECTION)
+#endif /* CONFIG_CHIP_INIT_ROM_REGION */
#ifdef CONFIG_SHAREDLIB
SHARED_LIB (rx) : ORIGIN = FW_OFF(SHAREDLIB), \
LENGTH = FW_SIZE(SHAREDLIB)
@@ -274,6 +312,18 @@ SECTIONS
. = ALIGN(4);
*(.rodata*)
+#ifndef CONFIG_CHIP_INIT_ROM_REGION
+ /*
+ * When a separate ROM resident section isn't enabled, ensure
+ * the corresponding data objects are linked into the .rodata
+ * section.
+ */
+ . = ALIGN(4);
+ __init_rom_start = .;
+ *(.init.rom)
+ __init_rom_end = .;
+#endif /* CONFIG_CHIP_INIT_ROM_REGION */
+
#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH)
. = ALIGN(64);
KEEP(*(.google))
@@ -418,7 +468,6 @@ SECTIONS
* in hash calcuations.
*/
__flash_used = LOADADDR(.data) + SIZEOF(.data) - ORIGIN(FLASH);
- __image_size = __flash_used;
#ifdef CONFIG_FLASH
/*
@@ -446,6 +495,72 @@ SECTIONS
) >= __flash_used,
"No room left in the flash")
+#ifdef CONFIG_CHIP_INIT_ROM_REGION
+ /*
+ * Image layout when ROM_RESIDENT region is used (lower addresses
+ * at the top). This layout is setup by the LMA assignment.
+ *
+ * EC image layout (LMA) VMA
+ * .header (if RO image) none
+ * .text code RAM
+ * .rodata code RAM + .text size
+ * .data data RAM
+ * .fill none
+ * .init_rom flash offset
+ *
+ * The loader code copies the .text, .rodata, and .data sections into
+ * the code RAM of the EC. The .header and .init_rom sections are not
+ * copied by the loader.
+ */
+
+ /*
+ * The layout assumes the ROM_RESIDENT region follows the FLASH
+ * region.
+ */
+ ASSERT((ORIGIN(FLASH) + LENGTH(FLASH)) == ORIGIN(ROM_RESIDENT),
+ ".init_rom section must follow the flash section")
+
+ .init_rom : {
+ . = ALIGN(4);
+ __init_rom_start = .;
+ *(.init.rom)
+ __init_rom_end = .;
+ } > ROM_RESIDENT_VMA AT > ROM_RESIDENT
+
+ /*
+ * The ROM_RESIDENT section is assumed to be in the same physical
+ * flash as the FLASH section. Fill the space between.
+ */
+ .fill : {
+ . = LOADADDR(.data) + SIZEOF(.data);
+ . = ALIGN(4);
+ __fill_start = .;
+ FILL(0xFF);
+ . = ORIGIN(FLASH) + LENGTH(FLASH) - 1;
+ /* Need at least one byte so section is not omitted */
+ BYTE(0xFF);
+ __fill_end = .;
+ } > FLASH
+
+ /*
+ * The end of the .fill region should also be the start of the
+ * .init_rom region
+ */
+ ASSERT(__fill_end == LOADADDR(.init_rom),
+ ".fill region end not aligned to start of .init_rom")
+
+ /*
+ * __image_size is used for hash calculation. When
+ * CONFIG_CHIP_INIT_ROM_REGION is enabled, this includes the entire
+ * FLASH region and the bytes used in the .init_rom section.
+ */
+ __image_size = LENGTH(FLASH) + SIZEOF(.init_rom);
+#else
+ /*
+ * Typical build: __image_size is the same as __flash_used.
+ */
+ __image_size = __flash_used;
+#endif /* CONFIG_CHIP_INIT_ROM_REGION */
#ifdef CONFIG_CHIP_MEMORY_REGIONS
#define REGION(name, attr, start, size) \
diff --git a/core/cortex-m0/ec.lds.S b/core/cortex-m0/ec.lds.S
index 77f3f9c8a7..6839b37778 100644
--- a/core/cortex-m0/ec.lds.S
+++ b/core/cortex-m0/ec.lds.S
@@ -203,6 +203,19 @@ SECTIONS
. = ALIGN(4);
*(.rodata*)
+#ifdef CONFIG_CHIP_INIT_ROM_REGION
+ ASSERT(0, "CONFIG_CHIP_INIT_ROM_REGION not supported by linker script")
+#endif /* CONFIG_CHIP_INIT_ROM_REGION */
+ /*
+ * This linker file does not yet support a separate ROM resident
+ * section. Ensure the corresponding data objects are linked
+ * into the .rodata section.
+ */
+ . = ALIGN(4);
+ __init_rom_start = .;
+ *(.init.rom)
+ __init_rom_end = .;
+
#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH)
. = ALIGN(64);
KEEP(*(.google))
diff --git a/core/minute-ia/ec.lds.S b/core/minute-ia/ec.lds.S
index 5b814abe42..2463c6d397 100644
--- a/core/minute-ia/ec.lds.S
+++ b/core/minute-ia/ec.lds.S
@@ -158,6 +158,19 @@ SECTIONS
. = ALIGN(4);
KEEP(*(.rodata.*))
+
+#ifdef CONFIG_CHIP_INIT_ROM_REGION
+ ASSERT(0, "CONFIG_CHIP_INIT_ROM_REGION not supported by linker script")
+#endif /* CONFIG_CHIP_INIT_ROM_REGION */
+ /*
+ * This linker file does not yet support a separate ROM resident
+ * section. Ensure the corresponding data objects are linked
+ * into the .rodata section.
+ */
+ . = ALIGN(4);
+ __init_rom_start = .;
+ *(.init.rom)
+ __init_rom_end = .;
}
/*
diff --git a/core/nds32/ec.lds.S b/core/nds32/ec.lds.S
index 24ee1ef0ae..ae26e58f7b 100644
--- a/core/nds32/ec.lds.S
+++ b/core/nds32/ec.lds.S
@@ -188,6 +188,19 @@ SECTIONS
. = ALIGN(4);
*(.rodata*)
+#ifdef CONFIG_CHIP_INIT_ROM_REGION
+ ASSERT(0, "CONFIG_CHIP_INIT_ROM_REGION not supported by linker script")
+#endif /* CONFIG_CHIP_INIT_ROM_REGION */
+ /*
+ * This linker file does not yet support a separate ROM resident
+ * section. Ensure the corresponding data objects are linked
+ * into the .rodata section.
+ */
+ . = ALIGN(4);
+ __init_rom_start = .;
+ *(.init.rom)
+ __init_rom_end = .;
+
#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH)
. = ALIGN(64);
KEEP(*(.google))
diff --git a/core/riscv-rv32i/ec.lds.S b/core/riscv-rv32i/ec.lds.S
index 31a7972fa2..15a26e5eff 100644
--- a/core/riscv-rv32i/ec.lds.S
+++ b/core/riscv-rv32i/ec.lds.S
@@ -227,6 +227,19 @@ SECTIONS
. = ALIGN(4);
*(.rodata*)
+#ifdef CONFIG_CHIP_INIT_ROM_REGION
+ ASSERT(0, "CONFIG_CHIP_INIT_ROM_REGION not supported by linker script")
+#endif /* CONFIG_CHIP_INIT_ROM_REGION */
+ /*
+ * This linker file does not yet support a separate ROM resident
+ * section. Ensure the corresponding data objects are linked
+ * into the .rodata section.
+ */
+ . = ALIGN(4);
+ __init_rom_start = .;
+ *(.init.rom)
+ __init_rom_end = .;
+
. = ALIGN(4);
*(.srodata*)
#if defined(SECTION_IS_RO) && defined(CONFIG_FLASH)
diff --git a/include/common.h b/include/common.h
index c9a61545e6..92731182dc 100644
--- a/include/common.h
+++ b/include/common.h
@@ -111,6 +111,19 @@
#define __bss_slow __attribute__((section(".bss.slow")))
#endif
+/*
+ * Place a read-only object into a ROM resident section. If supported by the
+ * EC chip, the object is part of the flash image but not copied into RAM
+ * automatically. Users may only access the data using the include/init_rom.h
+ * module.
+ *
+ * Requires CONFIG_CHIP_INIT_ROM_REGION is defined, otherwise the object is
+ * linked into the .rodata section.
+ */
+#ifndef __init_rom
+#define __init_rom __attribute__((section(".init.rom")))
+#endif
+
/* gcc does not support __has_feature */
#ifndef __has_feature
#define __has_feature(x) 0
diff --git a/include/config.h b/include/config.h
index aa8ead6ba1..f80eac0513 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1091,6 +1091,18 @@
*/
#undef CONFIG_CHIP_UNCACHED_REGION
+/*
+ * When defined, adds a new linker section to store objects that remain resident
+ * in ROM/flash. This is useful on ECs that execute all code from RAM and
+ * in which the RAM size is smaller than the flash size.
+ *
+ * Code can force objects into the .init_rom resident section using the
+ * __init_rom macro. Objects should accessed using the include/init_rom.h
+ * module.
+ */
+#undef CONFIG_CHIP_INIT_ROM_REGION
+
+
/*****************************************************************************/
/* Chipset config */
@@ -1817,6 +1829,24 @@
#undef CONFIG_RW_SIZE
/*
+ * Offset relative to CONFIG_EC_PROTECTED_STORAGE_OFF
+ * These define a region of flash used to store ROM resident data objects
+ * for RO images. This is only possible when the program memory is smaller
+ * than CONFIG_EC_PROTECTED_STORAGE_SIZE.
+ */
+#undef CONFIG_RO_ROM_RESIDENT_MEM_OFF
+#undef CONFIG_RO_ROM_RESIDENT_SIZE
+
+/*
+ * Offset relative to CONFIG_EC_WRITABLE_STORAGE_OFF
+ * These define a region of flash used to store ROM resident data objects
+ * for RW images. This is only possible when the program memory is smaller
+ * than CONFIG_EC_WRITABLE_STORAGE_SIZE.
+ */
+#undef CONFIG_RW_ROM_RESIDENT_MEM_OFF
+#undef CONFIG_RW_ROM_RESIDENT_SIZE
+
+/*
* NPCX-specific bootheader geometry.
* TODO(crosbug.com/p/23796): Factor these CONFIGs out.
*/
@@ -5347,6 +5377,34 @@
#define CONFIG_USB_PD_TBT_GEN3_CAPABLE
#endif /* CONFIG_USB_PD_TBT_COMPAT_MODE */
+/*
+ * CONFIG_CHIP_INIT_ROM_REGION requires that the chip has defined a
+ * ROM resident region to store the .init_rom section.
+ *
+ * These sections must also not be zero bytes, which will happen if
+ * the program size is the same as the flash size.
+ */
+#ifdef CONFIG_CHIP_INIT_ROM_REGION
+
+#ifndef CONFIG_RO_ROM_RESIDENT_SIZE
+#error CONFIG_CHIP_INIT_ROM_REGION requires CONFIG_RO_ROM_RESIDENT_SIZE
+#endif
+
+#ifndef CONFIG_RW_ROM_RESIDENT_SIZE
+#error CONFIG_CHIP_INIT_ROM_REGION requires CONFIG_RW_ROM_RESIDENT_SIZE
+#endif
+
+
+#if (CONFIG_RO_ROM_RESIDENT_SIZE == 0)
+#error CONFIG_RO_ROM_RESIDENT_SIZE is 0 with CONFIG_CHIP_INIT_ROM_REGION defined
+#endif
+
+#if (CONFIG_RW_ROM_RESIDENT_SIZE == 0)
+#error CONFIG_RW_ROM_RESIDENT_SIZE is 0 with CONFIG_CHIP_INIT_ROM_REGION defined
+#endif
+
+#endif /* CONFIG_CHIP_INIT_ROM_REGION */
+
/*****************************************************************************/
/*