The EC codebase currently supports the following chips:
lm4, stm32: Internal memory-mapped flash storage
cr50: Internal memory-mapped flash storage, with image signature preceding RO image
npcx: External memory-mapped flash storage dedicated for EC, code copied to SRAM before execution
mec1322: External unmapped flash storage dedicated for EC, code is copied to SRAM before execution
For memory-mapped flash storage, contents are read from a chip-defined region in memory. Contents are written though SPI commands. For unmapped flash storage, contents are read and written through SPI commands.
There is currently no support in the codebase for shared external storage, but we’d like to support it in the near future.
With three different storage categories supported, there is a lack of uniformity within our code base. Certain geometry CONFIGs (ex. CONFIG_FLASH_BASE, which originated when we had only internal memory-mapped flash) no longer have meanings consistent with names. In other cases (ex. CONFIG_CDRAM_BASE) the meaning of CONFIGs are too narrow and can be more broadly defined among all three categories. In addition, a few CONFIGs (ex. CONFIG_RO_MEM_OFF) no longer have any consistent meaning at all. This discontinuity makes it extremely difficult to change higher-level code without breaking one or more chip categories, or writing separate code to accommodate corner-cases for each category.
The goal of the changes described here is to make our CONFIGs uniform and understandable among all chip categories.
With the changes proposed here, we aim to support ECs with the following configurations:
The following CONFIGs are defined entirely based upon chip architecture with no flexibility to change them based upon image / loader arrangement.
CONFIG_INTERNAL_STORAGE - Indicates that chip uses internal storage
CONFIG_EXTERNAL_STORAGE - Indicates that chip uses external storage
CONFIG_MAPPED_STORAGE - Indicates that storage is mapped into the EC's address space
CONFIG_CDRAM_ARCH and CONFIG_FLASH_MAPPED previously encompassed these defines.
CONFIG_PROGRAM_MEMORY_BASE - Base address of program memory
CONFIG_MAPPED_STORAGE_BASE - Base address of memory-mapped flash storage (if present)
CONFIG_FLASH_BASE and CONFIG_CDRAM_BASE previously encompassed these defines.
lm4 will define CONFIG_INTERNAL_STORAGE and CONFIG_MAPPED_STORAGE, and set CONFIG_PROGRAM_MEMORY_BASE = CONFIG_MAPPED_STORAGE_BASE = 0.
cr50 will define CONFIG_INTERNAL_STORAGE and CONFIG_MAPPED_STORAGE, and set CONFIG_PROGRAM_MEMORY_BASE = CONFIG_MAPPED_STORAGE_BASE = 0x40000.
npcx will define CONFIG_EXTERNAL_STORAGE and CONFIG_MAPPED_STORAGE, and set CONFIG_PROGRAM_MEMORY_BASE = 0x10088000, CONFIG_MAPPED_STORAGE_BASE = 0x64000000.
mec1322 will define CONFIG_EXTERNAL_STORAGE, and set CONFIG_PROGRAM_MEMORY_BASE = 0x100000. CONFIG_MAPPED_STORAGE_BASE will not be defined, since storage is not memory mapped.
Layout / Geometry Configs
The following configs represent the Chrome EC implementation for a given chip and will normally be defined at the chip-level. There is flexibility to change these configs based upon needs. For example, the RO image on storage could reside at the beginning or the end of storage, based upon protection capabilities. Image sizes could grow or shrink if program memory space is dedicated to a loader.
Since external storage may be shared between the EC and the AP, only a certain region of storage may “belong” to the EC.
Color coding key:
Relative to address zero / beginning of external storage.
Relative to CONFIG_PROGRAM_MEMORY_BASE.
Relative to CONFIG_PROTECTED_STORAGE_OFF.
Relative to CONFIG_WRITABLE_STORAGE_OFF.
CONFIG_EC_PROTECTED_STORAGE_OFF - Offset of protected region of storage belonging to the EC.
CONFIG_EC_PROTECTED_STORAGE_SIZE - Size of protected region of storage belonging to the EC.
CONFIG_EC_WRITABLE_STORAGE_OFF - Offset of the writable region of storage (the region that will be field auto-updated, when write protection is enabled) belonging to the EC.
CONFIG_EC_WRITABLE_STORAGE_SIZE - Size of the writable region of storage belonging to the EC.
CONFIG_FLASH_BASE_SPI was previously used to indicate the offset to storage region belonging to EC. We now need multiple defines, because we can no longer assume that there is one contiguous region of storage that belongs to the EC.
CONFIG_RO_MEM_OFF - RO image offset in program memory, when loaded.
CONFIG_RO_STORAGE_OFF - RO image offset on storage, relative to the start of the EC protected storage region.
CONFIG_RO_SIZE - Size of RO image (in both program memory and storage).
CONFIG_RW_MEM_OFF - RW image offset in program memory, when loaded.
CONFIG_RW_B_MEM_OFF - RW B image (optional second identical RW image) offset in program memory, when loaded. Only valid when CONFIG_RW_B is defined.
CONFIG_RW_STORAGE_OFF - RW image offset on storage, relative to the start of the EC writable storage region.
CONFIG_RW_SIZE - Size of RW image (in both program memory and storage).
CONFIG_WP_STORAGE_OFF - Start of write protect region (the region that will be write protected, when write protection is enabled) on EC storage. This may exceed CONFIG_EC_PROTECTED_STORAGE_OFF if more than just the region belonging to the EC must be protected.
CONFIG_WP_STORAGE_SIZE - Size of write protect region on EC storage. This may be greater than CONFIG_EC_PROTECTED_STORAGE_SIZE for the same reason.
CONFIG_FW_R*_OFF, CONFIG_FW_R*_SPI_OFF and CONFIG_FW_R*_SIZE previously encompassed these defines.
Hypothetical shared SPI platform (see Appendix):
Different chips may have different NIDs, such as boot headers and bootloaders. Since these NIDs may have chip-specific requirements, we will not attempt to standardize their layouts. It is suggested to keep uniform naming for NID geometry configs, such as:
These chip-specific NID-related CONFIGs may be used in chip folders as required. They should NEVER be used outside of chip folders (except to describe them in config.h) since their precise meanings are not standardized.
Our linker scripts were originally written to support internal memory-mapped storage with only RO and RW images (no NIDs). The scripts will be extended to support the new configs defined above. For example, the linker will produce a unified image with the RW image at the appropriate offset, as defined by CONFIG_RW_STORAGE_OFF / CONFIG_RW_STORAGE_SIZE.
If NIDs are required, they will need to be copied to the appropriate location by a chip-specific packing script. Such a script has already been implemented for mec1322 in chip/mec1322/util/pack_ec.py. We may consider implementing a generic version of pack_ec.py in the future, with only custom parameters for each chip.
NIDs should not be copied by modifying the global, non-chip linker scripts. For example, the NPCX-custom changes related to NPCX_RO_HEADER in core/cortex-m/ec.lds.S are not acceptable and will need to be removed.
FMAP is a data structure (authoritative copy today lives inside the RO image, but copies exist in both images) that describes the layout of EC storage.
Its header defines the following values of significance:
In addition, boundaries for seven regions are defined.
Currently, CONFIG_PROGRAM_MEMORY_BASE is written to fmap_base, and CONFIG_EC_STORAGE_SIZE is written to fmap_size. This design makes no sense for an FMAP intended to be read outside of the EC, since CONFIG_PROGRAM_MEMORY_BASE is only meaningful to the EC. Instead, the following changes are proposed:
fmap_base: Offset to storage region described by FMAP
fmap_size: Size of storage region described by FMAP
When protected and writable storage regions are contiguous, the FMAP in RO and RW (if present) images will be identical and describe both regions, with the RO copy being authoritative. This is entirely consistent with the way FMAP works today (all current platforms have contiguous readable + writable storage regions).
When protected and writable storage regions are non-contiguous (in certain future shared SPI designs), the FMAP in RO and RW images will be different and will each describe the EC protected and writable storage regions, respectfully.
For shared SPI, there will also be master FMAP (today known as the FW SPI FMAP), outside the EC storage regions, that describes all regions of SPI storage, including FW romstage images, ramstage images, vendor blobs, and EC storage regions.
The workings of the master FMAP are outside the scope of the document, but it’s anticipated that EC FW updates could work as follows:
The master FMAP has separate entries for the EC RO update region, the EC RW update region, and the SPI write protect region. Therefore, the EC regions can be flashed without parsing the EC FMAP. If desired, the EC FMAP can be parsed to ensure consistency before flashing.
The seven regions are unchanged and will keep their overall meaning (though some corrections still must be made in code). Note that all region start addresses are relative to fmap_base.
EC_RO - Region that will be updated on an RO update (equivalent to the CONFIG_EC_PROTECTED_STORAGE region). This region includes the RO image and any other meaningful NIDs in the RO region. Note that RO FW update is a feature not supported on production devices, yet it is important for pre-MP updates and factory flow.
FR_MAIN - Region consisting only of RO image (CONFIG_RO_STORAGE region)
RO_FRID - Region consisting of version struct inside RO image (generally start of FR_MAIN + constant offset)
FMAP - Region consisting of the FMAP inside RO image, or the FMAP inside the RW image, if the RO image doesn’t exist.
WP_RO - EC region that will be write protected at the factory before shipping PVT / production devices. Equivalent to EC_RO. Note that if the protect region exceeds the fmap_base / fmap_size region (when the CONFIG_WP_STORAGE exceeds the CONFIG_EC_PROTECTED_STORAGE region, such as with shared SPI) then WP_RO doesn’t describe the entire SPI region that must be protected. The master FMAP must describe that region separately.
EC_RW - Region that will be updated on an RW update (CONFIG_EC_WRITABLE_STORAGE region).
RW_FWID - Region consisting of version struct inside RW image.
FR_MAIN (EC RO image) <= EC_RO (RO update region / CONFIG_EC_PROTECTED_STORAGE region) = WP_RO (EC write protect region)
EC RW IMAGE (not defined by FMAP) <= EC_RW (RW update region / CONFIG_WRITABLE_STORAGE region)
EC_RO + EC_RW == fmap_base + fmap_size, for contiguous EC_RO + EC_RW