diff options
author | Scott <scollyer@chromium.org> | 2016-08-30 17:21:49 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-09-02 21:16:35 -0700 |
commit | 1d46c3770842d6c1f06ea3798aa36c5eeb2b392f (patch) | |
tree | bf513b92a52722ae85a3723268b663d7aeb25511 | |
parent | b2a751cfd8b5f543e7b40f32c81a7a6f876c42c7 (diff) | |
download | chrome-ec-1d46c3770842d6c1f06ea3798aa36c5eeb2b392f.tar.gz |
Cr50: NvMem: Allow for partitions to not be contiguous
TPM2.0 needs more NvMem space and currently the whole block is
contiguous in memory with 2 partitions. This CL removes the
requirement that the partitions are in contiguous which allows for 1
partition to placed at top of RW_A and the other at RW_B.
This CL does not change the size of each partition as that will be
done in a subsequent CL.
BRANCH=none
BUG=chrome-os-partner:56798
TEST=manual
Tested with the unit test 'make runtests TEST_LIST_HOST=nvmem' and
verified that all tests pass.
Tested on Kevin, erased the existing NvMem area and verified that TPM
was still manufactured and executed the command: trunks_client --own
Erased parition 0 and 1 in the new locations and repeated the tests.
Change-Id: I295441f94dccdf5a152c32603c2638ffac23f471
Signed-off-by: Scott <scollyer@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/378675
Commit-Ready: Bill Richardson <wfrichar@chromium.org>
Tested-by: Bill Richardson <wfrichar@chromium.org>
Tested-by: Scott Collyer <scollyer@chromium.org>
Tested-by: Andrey Pronin <apronin@chromium.org>
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r-- | board/cr50/board.c | 16 | ||||
-rw-r--r-- | board/cr50/board.h | 11 | ||||
-rw-r--r-- | common/nvmem.c | 50 | ||||
-rw-r--r-- | include/config.h | 6 | ||||
-rw-r--r-- | include/nvmem.h | 10 | ||||
-rw-r--r-- | test/nvmem.c | 21 | ||||
-rw-r--r-- | test/test_config.h | 9 |
7 files changed, 74 insertions, 49 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c index 13e86e842e..7f320fff8c 100644 --- a/board/cr50/board.c +++ b/board/cr50/board.c @@ -247,7 +247,7 @@ int flash_regions_to_enable(struct g_flash_region *regions, * separate regions. */ - if (max_regions < 2) + if (max_regions < 3) return 0; /* Enable access to the other RW image... */ @@ -263,13 +263,19 @@ int flash_regions_to_enable(struct g_flash_region *regions, regions[0].reg_size = CONFIG_RW_SIZE; regions[0].reg_perms = FLASH_REGION_EN_ALL; - /* Enable access to the NVRAM region */ + /* Enable access to the NVRAM partition A region */ regions[1].reg_base = CONFIG_MAPPED_STORAGE_BASE + - CONFIG_FLASH_NVMEM_OFFSET; - regions[1].reg_size = CONFIG_FLASH_NVMEM_SIZE; + CONFIG_FLASH_NVMEM_OFFSET_A; + regions[1].reg_size = NVMEM_PARTITION_SIZE; regions[1].reg_perms = FLASH_REGION_EN_ALL; - return 2; + /* Enable access to the NVRAM partition B region */ + regions[2].reg_base = CONFIG_MAPPED_STORAGE_BASE + + CONFIG_FLASH_NVMEM_OFFSET_B; + regions[2].reg_size = NVMEM_PARTITION_SIZE; + regions[2].reg_perms = FLASH_REGION_EN_ALL; + + return 3; } #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) diff --git a/board/cr50/board.h b/board/cr50/board.h index d8d89e31ec..bcb21849f8 100644 --- a/board/cr50/board.h +++ b/board/cr50/board.h @@ -21,13 +21,16 @@ /* TODO(crosbug.com/p/44745): For debugging only */ #define CONFIG_CMD_FLASH -/* We're using all of TOP_B for NVMEM. TOP_A is unused as yet. */ +/* We're using all of TOP_A for partition A, TOP_B for partition 1 */ #define CONFIG_FLASH_NVMEM /* Offset to start of NvMem area from base of flash */ -#define CONFIG_FLASH_NVMEM_OFFSET (CFG_TOP_B_OFF) +#define CONFIG_FLASH_NVMEM_OFFSET_A (CFG_TOP_A_OFF) +#define CONFIG_FLASH_NVMEM_OFFSET_B (CFG_TOP_B_OFF) /* Address of start of Nvmem area */ -#define CONFIG_FLASH_NVMEM_BASE (CONFIG_PROGRAM_MEMORY_BASE + \ - CONFIG_FLASH_NVMEM_OFFSET) +#define CONFIG_FLASH_NVMEM_BASE_A (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_FLASH_NVMEM_OFFSET_A) +#define CONFIG_FLASH_NVMEM_BASE_B (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_FLASH_NVMEM_OFFSET_B) /* Size in bytes of NvMem area */ #define CONFIG_FLASH_NVMEM_SIZE CFG_TOP_SIZE /* Size partition in NvMem */ diff --git a/common/nvmem.c b/common/nvmem.c index c293e26ce3..b3470b9889 100644 --- a/common/nvmem.c +++ b/common/nvmem.c @@ -19,6 +19,17 @@ #define NVMEM_ACQUIRE_CACHE_MAX_ATTEMPTS (250 / NVMEM_ACQUIRE_CACHE_SLEEP_MS) #define NVMEM_NOT_INITIALIZED (-1) +/* Table of start addresses for each partition */ +static const uintptr_t nvmem_base_addr[NVMEM_NUM_PARTITIONS] = { + CONFIG_FLASH_NVMEM_BASE_A, + CONFIG_FLASH_NVMEM_BASE_B + }; +/* Table of offset within flash space to start of each partition */ +static const uint32_t nvmem_flash_offset[NVMEM_NUM_PARTITIONS] = { + CONFIG_FLASH_NVMEM_OFFSET_A, + CONFIG_FLASH_NVMEM_OFFSET_B + }; + /* NvMem user buffer start offset table */ static uint32_t nvmem_user_start_offset[NVMEM_NUM_USERS]; @@ -45,8 +56,7 @@ static int nvmem_verify_partition_sha(int index) struct nvmem_partition *p_part; uint8_t *p_data; - p_part = (struct nvmem_partition *)CONFIG_FLASH_NVMEM_BASE; - p_part += index; + p_part = (struct nvmem_partition *)nvmem_base_addr[index]; p_data = (uint8_t *)p_part; p_data += sizeof(sha_comp); @@ -77,9 +87,7 @@ static int nvmem_acquire_cache(void) (char **)&shared_mem_ptr); if (ret == EC_SUCCESS) { /* Copy partiion contents from flash into cache */ - p_src = (uint8_t *)(CONFIG_FLASH_NVMEM_BASE + - nvmem_act_partition * - NVMEM_PARTITION_SIZE); + p_src = (uint8_t *)nvmem_base_addr[nvmem_act_partition]; memcpy(shared_mem_ptr, p_src, NVMEM_PARTITION_SIZE); /* Now that cache is up to date, assign pointer */ cache.base_ptr = shared_mem_ptr; @@ -145,17 +153,20 @@ static void nvmem_release_cache(void) static int nvmem_is_unitialized(void) { + int p; int n; int ret; uint32_t *p_nvmem; struct nvmem_partition *p_part; - /* Point to start of Nv Memory */ - p_nvmem = (uint32_t *)CONFIG_FLASH_NVMEM_BASE; - /* Verify that each byte is 0xff (4 bytes at a time) */ - for (n = 0; n < (CONFIG_FLASH_NVMEM_SIZE >> 2); n++) - if (p_nvmem[n] != 0xffffffff) - return EC_ERROR_CRC; + for (p = 0; p < NVMEM_NUM_PARTITIONS; p++) { + /* Point to start of Nv Memory */ + p_nvmem = (uint32_t *)nvmem_base_addr[p]; + /* Verify that each byte is 0xff (4 bytes at a time) */ + for (n = 0; n < (NVMEM_PARTITION_SIZE >> 2); n++) + if (p_nvmem[n] != 0xffffffff) + return EC_ERROR_CRC; + } /* * NvMem is fully unitialized. Need to initialize tag and write tag to @@ -179,8 +190,8 @@ static int nvmem_is_unitialized(void) * partition was just verified to be fully erased, can just do write * operation. */ - ret = flash_physical_write(CONFIG_FLASH_NVMEM_OFFSET, - sizeof(struct nvmem_tag), + ret = flash_physical_write(nvmem_flash_offset[0], + sizeof(struct nvmem_tag), cache.base_ptr); nvmem_release_cache(); if (ret) { @@ -196,9 +207,9 @@ static int nvmem_compare_version(void) uint16_t ver0, ver1; uint32_t delta; - p_part = (struct nvmem_partition *)CONFIG_FLASH_NVMEM_BASE; + p_part = (struct nvmem_partition *)nvmem_base_addr[0]; ver0 = p_part->tag.version; - p_part++; + p_part = (struct nvmem_partition *)nvmem_base_addr[1]; ver1 = p_part->tag.version; /* Compute version difference accounting for wrap condition */ @@ -382,8 +393,7 @@ int nvmem_is_different(uint32_t offset, uint32_t size, void *data, /* Point to either NvMem flash or ram if that's active */ if (cache.base_ptr == NULL) - src_addr = CONFIG_FLASH_NVMEM_BASE + nvmem_act_partition * - NVMEM_PARTITION_SIZE; + src_addr = nvmem_base_addr[nvmem_act_partition]; else src_addr = (uintptr_t)cache.base_ptr; @@ -410,8 +420,7 @@ int nvmem_read(uint32_t offset, uint32_t size, /* Point to either NvMem flash or ram if that's active */ if (cache.base_ptr == NULL) - src_addr = CONFIG_FLASH_NVMEM_BASE + nvmem_act_partition * - NVMEM_PARTITION_SIZE; + src_addr = nvmem_base_addr[nvmem_act_partition]; else src_addr = (uintptr_t)cache.base_ptr; @@ -542,8 +551,7 @@ int nvmem_commit(void) /* Toggle parition being used (always write to current spare) */ new_active_partition = nvmem_act_partition ^ 1; /* Point to first block within active partition */ - nvmem_offset = CONFIG_FLASH_NVMEM_OFFSET + new_active_partition * - NVMEM_PARTITION_SIZE; + nvmem_offset = nvmem_flash_offset[new_active_partition]; /* Write partition to NvMem */ /* Erase partition */ diff --git a/include/config.h b/include/config.h index 1cb5b83108..5ecfe2400b 100644 --- a/include/config.h +++ b/include/config.h @@ -915,9 +915,11 @@ /* Enable NV Memory module within flash */ #undef CONFIG_FLASH_NVMEM /* Offset to start of NvMem area from base of flash */ -#undef CONFIG_FLASH_NVMEM_OFFSET +#undef CONFIG_FLASH_NVMEM_OFFSET_A +#undef CONFIG_FLASH_NVMEM_OFFSET_B /* Address of start of Nvmem area */ -#undef CONFIG_FLASH_NVMEM_BASE +#undef CONFIG_FLASH_NVMEM_BASE_A +#undef CONFIG_FLASH_NVMEM_BASE_B /* Size in bytes of NvMem area */ #undef CONFIG_FLASH_NVMEM_SIZE diff --git a/include/nvmem.h b/include/nvmem.h index 82942dbe8e..781ea219f0 100644 --- a/include/nvmem.h +++ b/include/nvmem.h @@ -32,6 +32,10 @@ * aren't fully erased, then NvMem is marked corrupt and this failure condition * must be reported back to the caller. * + * Note that the NvMem partitions can be placed anywhere in flash space, but + * must be equal in total size. A table is used by the NvMem module to get the + * correct base address and offset for each partition. + * * A version number is used to distinguish between two valid partitions with * the newsest version number (in a circular sense) marking the correct * partition to use. The parition number 0/1 is tracked via a static @@ -43,8 +47,8 @@ * * The following CONFIG_FLASH_NVMEM_ defines are required for this module: * CONFIG_FLASH_NVMEM -> enable/disable the module - * CONFIG_FLASH_NVMEM_OFFSET -> offset to start of NvMem from base of flash - * CONFIG_FLASH_NVMEM_BASE -> address of start of NvMem area + * CONFIG_FLASH_NVMEM_OFFSET_(A|B) -> offset to start of each partition + * CONFIG_FLASH_NVMEM_BASE_(A|B) -> address of start of each partition * * The board.h file must define a macro or enum named NVMEM_NUM_USERS. * The board.c file must include 1 function and an array of user buffer lengths @@ -52,7 +56,7 @@ * nvmem_compute_sha() -> function used to compute 4 byte sha (or equivalent) * * Note that total length of user buffers must satisfy the following: - * sum(user sizes) <= (CONFIG_FLASH_NVMEM_SIZE / 2) - sizeof(struct nvmem_tag) + * sum(user sizes) <= (NVMEM_PARTITION_SIZE) - sizeof(struct nvmem_tag) */ /* NvMem user buffer length table */ diff --git a/test/nvmem.c b/test/nvmem.c index bbd580589d..9f007f0191 100644 --- a/test/nvmem.c +++ b/test/nvmem.c @@ -139,8 +139,10 @@ static int test_fully_erased_nvmem(void) */ /* Erase full NvMem area */ - flash_physical_erase(CONFIG_FLASH_NVMEM_OFFSET, - CONFIG_FLASH_NVMEM_SIZE); + flash_physical_erase(CONFIG_FLASH_NVMEM_OFFSET_A, + NVMEM_PARTITION_SIZE); + flash_physical_erase(CONFIG_FLASH_NVMEM_OFFSET_B, + NVMEM_PARTITION_SIZE); /* Call NvMem initialization function */ return nvmem_init(); } @@ -160,8 +162,6 @@ static int test_configured_nvmem(void) static int test_corrupt_nvmem(void) { - uint32_t offset; - int n; int ret; struct nvmem_tag *p_part; uint8_t *p_data; @@ -175,12 +175,12 @@ static int test_corrupt_nvmem(void) /* Overwrite each partition will all 0s */ memset(write_buffer, 0, NVMEM_PARTITION_SIZE); - for (n = 0; n < NVMEM_NUM_PARTITIONS; n++) { - offset = NVMEM_PARTITION_SIZE * n; - flash_physical_write(CONFIG_FLASH_NVMEM_OFFSET + offset, + flash_physical_write(CONFIG_FLASH_NVMEM_OFFSET_A, + NVMEM_PARTITION_SIZE, + (const char *)write_buffer); + flash_physical_write(CONFIG_FLASH_NVMEM_OFFSET_B, NVMEM_PARTITION_SIZE, (const char *)write_buffer); - } /* * The initialization function will look for a valid partition and if * none is found, then will call nvmem_setup() which will erase the @@ -197,7 +197,7 @@ static int test_corrupt_nvmem(void) * partition 0 has a version number of 1 and that all of the user buffer * data has been erased. */ - p_part = (struct nvmem_tag *)CONFIG_FLASH_NVMEM_BASE; + p_part = (struct nvmem_tag *)CONFIG_FLASH_NVMEM_BASE_A; TEST_ASSERT(p_part->version == 1); p_data = (uint8_t *)p_part + sizeof(struct nvmem_tag); /* Verify that partition 0 is fully erased */ @@ -205,8 +205,7 @@ static int test_corrupt_nvmem(void) sizeof(struct nvmem_tag)); /* Run the same test for partition 1 which should have version 0 */ - p_part = (struct nvmem_tag *)(CONFIG_FLASH_NVMEM_BASE + - NVMEM_PARTITION_SIZE); + p_part = (struct nvmem_tag *)CONFIG_FLASH_NVMEM_BASE_B; TEST_ASSERT(p_part->version == 0); p_data = (uint8_t *)p_part + sizeof(struct nvmem_tag); ccprintf("Partition Version = %d\n", p_part->version); diff --git a/test/test_config.h b/test/test_config.h index d04708f617..dacfe04868 100644 --- a/test/test_config.h +++ b/test/test_config.h @@ -152,9 +152,12 @@ int ncp15wb_calculate_temp(uint16_t adc); #ifdef TEST_NVMEM #define CONFIG_FLASH_NVMEM -#define CONFIG_FLASH_NVMEM_OFFSET 0x1000 -#define CONFIG_FLASH_NVMEM_BASE (CONFIG_PROGRAM_MEMORY_BASE + \ - CONFIG_FLASH_NVMEM_OFFSET) +#define CONFIG_FLASH_NVMEM_OFFSET_A 0x1000 +#define CONFIG_FLASH_NVMEM_OFFSET_B 0x4000 +#define CONFIG_FLASH_NVMEM_BASE_A (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_FLASH_NVMEM_OFFSET_A) +#define CONFIG_FLASH_NVMEM_BASE_B (CONFIG_PROGRAM_MEMORY_BASE + \ + CONFIG_FLASH_NVMEM_OFFSET_B) #define CONFIG_FLASH_NVMEM_SIZE 0x4000 #define CONFIG_SW_CRC |