diff options
author | Keith Short <keithshort@chromium.org> | 2020-07-19 16:23:23 -0600 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-08-13 14:26:53 +0000 |
commit | e0bf946ced052fe5e857b42da666ba252b03da95 (patch) | |
tree | d5218c56b92ecf3e27e62af0a19c8e9d34443134 | |
parent | 8ce0c16cc2d153b0002fbea64d08c09d98c3835f (diff) | |
download | chrome-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.mk | 13 | ||||
-rw-r--r-- | chip/npcx/config_flash_layout.h | 12 | ||||
-rw-r--r-- | core/cortex-m/ec.lds.S | 117 | ||||
-rw-r--r-- | core/cortex-m0/ec.lds.S | 13 | ||||
-rw-r--r-- | core/minute-ia/ec.lds.S | 13 | ||||
-rw-r--r-- | core/nds32/ec.lds.S | 13 | ||||
-rw-r--r-- | core/riscv-rv32i/ec.lds.S | 13 | ||||
-rw-r--r-- | include/common.h | 13 | ||||
-rw-r--r-- | include/config.h | 58 |
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 */ + /*****************************************************************************/ /* |