diff options
author | Bill Richardson <wfrichar@chromium.org> | 2016-11-28 11:38:20 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-12-21 19:42:37 -0800 |
commit | 971e758ddec1b04b4a5479d716ec5a53ea48950f (patch) | |
tree | 489332a65ce2c781efb1692c53e81cb6fe994a20 /include | |
parent | 0a97a6cf4bbc052e715080a9634078396645b733 (diff) | |
download | chrome-ec-971e758ddec1b04b4a5479d716ec5a53ea48950f.tar.gz |
Add nvmem-backed key=value variable storage
The CONFIG_FLASH_NVMEM option implements persistent, reliable storage
regions in flash. This adds CONFIG_FLASH_NVMEM_VARS, which uses one of
those storage regions for free-form variables.
Refer to the comments in include/nvmem_vars.h and common/nvmem_vars.c
for usage and implementation details.
BUG=chrome-os-partner:61107
BRANCH=none
TEST=make runtests
This CL includes a number of new tests, specifically for this feature.
No target boards use this feature yet so there's nothing to test on
actual hardware, but the test/nvmem_vars executable includes console
commands ("get", "set", "print") to try it out.
Change-Id: I8597415dc3b00a1462f5b164eeb5073129030525
Signed-off-by: Bill Richardson <wfrichar@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/414194
Reviewed-by: Randall Spangler <rspangler@chromium.org>
Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/config.h | 10 | ||||
-rw-r--r-- | include/nvmem_vars.h | 87 |
2 files changed, 97 insertions, 0 deletions
diff --git a/include/config.h b/include/config.h index 43b7c141bf..3ab6765b99 100644 --- a/include/config.h +++ b/include/config.h @@ -987,6 +987,16 @@ /* Size in bytes of NvMem area */ #undef CONFIG_FLASH_NVMEM_SIZE +/* Enable <key,value> variable support (requires CONFIG_FLASH_NVMEM) */ +#undef CONFIG_FLASH_NVMEM_VARS +/* + * We already have to define nvmem_user_sizes[] to specify the order and size + * of the user regions. CONFIG_FLASH_NVMEM_VARS looks for two symbols to + * specify the region number and size for the variable region. + */ +#undef CONFIG_FLASH_NVMEM_VARS_USER_NUM +#undef CONFIG_FLASH_NVMEM_VARS_USER_SIZE + /*****************************************************************************/ /* Include a flashmap in the compiled firmware image */ diff --git a/include/nvmem_vars.h b/include/nvmem_vars.h new file mode 100644 index 0000000000..867ea32018 --- /dev/null +++ b/include/nvmem_vars.h @@ -0,0 +1,87 @@ +/* Copyright 2016 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef __EC_INCLUDE_NVMEM_VARS_H +#define __EC_INCLUDE_NVMEM_VARS_H + +/* + * CONFIG_FLASH_NVMEM provides persistent, atomic-update storage in + * flash. The storage is logically divided into one or more "user regions", as + * configured in board.h and board.c + * + * CONFIG_FLASH_NVMEM_VARS stores a set of <KEY, VALUE> tuples in the nvmem + * user region designated by CONFIG_FLASH_NVMEM_VARS_USER_NUM (in board.h) + * + * Tuples are stored and managed using this struct: + */ + +struct tuple { + uint8_t key_len; /* 1 - 255 */ + uint8_t val_len; /* 1 - 255 */ + uint8_t flags; /* RESERVED, will be zeroed */ + uint8_t data_[0]; /* Opaque. Don't look here. */ +}; + +/* + * Both KEY and VALUE can be any binary blob between 1 and 255 bytes (flash + * memory is limited, so if you need longer values just use two keys and + * concatenate the blobs). Zero-length KEYs or VALUEs are not allowed. + * Assigning a zero-length VALUE to a KEY just deletes that tuple (if it + * existed). + * + * The expected usage is: + * + * 1. At boot, call initvars() to ensure that the variable storage region is + * valid. If it isn't, this will initialize it to an empty set. + * + * 2. Call getenv() or setenv() as needed. The first call to either will copy + * the storage regsion from flash into a RAM buffer. Any changes made with + * setenv() will affect only that RAM buffer. + * + * 3. Call writevars() to commit the RAM buffer to flash and free it. + * + * CAUTION: The underlying CONFIG_FLASH_NVMEM implementation allows access by + * multiple tasks, provided each task access only one user region. There is no + * support for simultaneous access to the *same* user region by multiple tasks. + * CONFIG_FLASH_NVMEM_VARS stores all variables in one user region, so if + * variable access by multiple tasks is required, the tasks should establish + * their own locks or mutexes to fit their usage. In general that would mean + * aquiring a lock before calling getvar() or setvar(), and releasing it after + * calling writevars(). + */ + +/* + * Initialize the persistent storage. This checks the user region to ensure + * that all tuples are valid and that there is one additional '\0' at the end. + * If any discrepancies are found, it erases all values. This should return + * EC_SUCCESS unless there is a problem writing to flash. + */ +int initvars(void); + +/* + * Look up a key, return a pointer to the tuple. If the key is not found, + * return NULL. WARNING: The returned pointer is only valid until the next call + * to setvar() or writevars(). Use it or lose it. + */ +const struct tuple *getvar(const uint8_t *key, uint8_t key_len); + +/* Use these to access the data components of a valid struct tuple pointer */ +const uint8_t *tuple_key(const struct tuple *); +const uint8_t *tuple_val(const struct tuple *); + +/* + * Save the tuple in the RAM buffer. If val is NULL or val_len is 0, the + * tuple is deleted (if it existed). Returns EC_SUCCESS or error code. + */ +int setvar(const uint8_t *key, uint8_t key_len, + const uint8_t *val, uint8_t val_len); + +/* + * Commit any changes made with setvar() to persistent memory, and invalidate + * the RAM buffer. Return EC_SUCCESS or error code on failure. + */ +int writevars(void); + +#endif /* __EC_INCLUDE_NVMEM_VARS_H */ |