diff options
author | Vadim Bendebury <vbendeb@google.com> | 2017-02-28 17:52:23 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-03-02 16:50:05 -0800 |
commit | b1afdd76bc3f7b35a2cdca817684ebe224a4c9a9 (patch) | |
tree | 454b243ceeb6c687de114463cbcc4bd4f622c81f /chip/g/flash.c | |
parent | 899fba96494e022f8e083611c328e7b57cf18079 (diff) | |
download | chrome-ec-b1afdd76bc3f7b35a2cdca817684ebe224a4c9a9.tar.gz |
g: enhance flash INFO api
Flash INFO access API presently is hardcoded to access the endorsement
space. To enable INFO map based rollback protection one needs to be
able to access different areas of the INFO.
The FLASH REGION3 register used by the API is in fact used for NVMEM
flash accesses too, so it is better to leave it alone and use REGION6
for the purpose of accessing of the INFO space.
The API now requires the user to specify flash offset and region size,
the size must be power of 2, the offset must be aligned at size, and
the region must not spill beyond the INFO space address range.
BRANCH=cr50
BUG=b:35774863
TEST=with the rest of the patches applied it is possible to erase the
base word in the info map segment;
reading of the endorsement space at startup still works fine.
Change-Id: I008165ee9e11a7b49985d2b30683509cf6699431
Signed-off-by: Vadim Bendebury <vbendeb@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/447965
Reviewed-by: Nagendra Modadugu <ngm@google.com>
Reviewed-by: Mary Ruthven <mruthven@chromium.org>
Diffstat (limited to 'chip/g/flash.c')
-rw-r--r-- | chip/g/flash.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/chip/g/flash.c b/chip/g/flash.c index 3b02a5d014..c0b1f72979 100644 --- a/chip/g/flash.c +++ b/chip/g/flash.c @@ -352,22 +352,62 @@ int flash_physical_info_read_word(int byte_offset, uint32_t *dst) return EC_SUCCESS; } -void flash_info_write_enable(void) +/* + * Verify that the range's size is power of 2, the range offset is aligned by + * size, and the range does not cross the INFO space boundary. + */ +static int valid_info_range(uint32_t offset, size_t size) +{ + if (!size || (size & (size - 1))) + return 0; + + if (offset & (size - 1)) + return 0; + + if ((offset + size) > FLASH_INFO_SIZE) + return 0; + + return 1; + +} + +static int flash_info_configure_access(uint32_t offset, + size_t size, int read_mode) +{ + int mask; + + if (!valid_info_range(offset, size)) + return EC_ERROR_INVAL; + + if (read_mode) + mask = GC_GLOBALSEC_FLASH_REGION6_CTRL_EN_MASK | + GC_GLOBALSEC_FLASH_REGION6_CTRL_RD_EN_MASK; + else + mask = GC_GLOBALSEC_FLASH_REGION6_CTRL_EN_MASK | + GC_GLOBALSEC_FLASH_REGION6_CTRL_WR_EN_MASK; + + GREG32(GLOBALSEC, FLASH_REGION6_BASE_ADDR) = + FLASH_INFO_MEMORY_BASE + offset; + + GREG32(GLOBALSEC, FLASH_REGION6_SIZE) = size - 1; + GREG32(GLOBALSEC, FLASH_REGION6_CTRL) = mask; + + return EC_SUCCESS; +} + +int flash_info_read_enable(uint32_t offset, size_t size) +{ + return flash_info_configure_access(offset, size, 1); +} + +int flash_info_write_enable(uint32_t offset, size_t size) { - /* Enable R/W access to INFO. */ - GREG32(GLOBALSEC, FLASH_REGION3_BASE_ADDR) = FLASH_INFO_MEMORY_BASE + - FLASH_INFO_MANUFACTURE_STATE_OFFSET; - GREG32(GLOBALSEC, FLASH_REGION3_SIZE) = - FLASH_INFO_MANUFACTURE_STATE_SIZE - 1; - GREG32(GLOBALSEC, FLASH_REGION3_CTRL) = - GC_GLOBALSEC_FLASH_REGION3_CTRL_EN_MASK | - GC_GLOBALSEC_FLASH_REGION3_CTRL_WR_EN_MASK | - GC_GLOBALSEC_FLASH_REGION3_CTRL_RD_EN_MASK; + return flash_info_configure_access(offset, size, 0); } void flash_info_write_disable(void) { - GREG32(GLOBALSEC, FLASH_REGION3_CTRL) = 0; + GWRITE_FIELD(GLOBALSEC, FLASH_REGION6_CTRL, WR_EN, 0); } int flash_info_physical_write(int byte_offset, int num_bytes, const char *data) |