summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott <scollyer@chromium.org>2016-08-30 17:21:49 -0700
committerchrome-bot <chrome-bot@chromium.org>2016-09-02 21:16:35 -0700
commit1d46c3770842d6c1f06ea3798aa36c5eeb2b392f (patch)
treebf513b92a52722ae85a3723268b663d7aeb25511
parentb2a751cfd8b5f543e7b40f32c81a7a6f876c42c7 (diff)
downloadchrome-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.c16
-rw-r--r--board/cr50/board.h11
-rw-r--r--common/nvmem.c50
-rw-r--r--include/config.h6
-rw-r--r--include/nvmem.h10
-rw-r--r--test/nvmem.c21
-rw-r--r--test/test_config.h9
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