From 5f0dff61be0f2ff5e42d29f2d65a6c6adc2a424c Mon Sep 17 00:00:00 2001 From: Dominik Ermel Date: Tue, 29 Jun 2021 09:51:18 +0000 Subject: [PATCH] storage/flash_map: Separate layout and integrity functions The commit separates conditionally compiled API calls to separate C files and moves conditional compilation to CMakeLists.txt. Inline helpers have been moved to flash_map_priv.h. Signed-off-by: Dominik Ermel --- subsys/storage/flash_map/CMakeLists.txt | 3 +- subsys/storage/flash_map/flash_map.c | 197 +----------------- .../storage/flash_map/flash_map_integrity.c | 77 +++++++ subsys/storage/flash_map/flash_map_layout.c | 124 +++++++++++ subsys/storage/flash_map/flash_map_priv.h | 39 ++++ 5 files changed, 244 insertions(+), 196 deletions(-) create mode 100644 subsys/storage/flash_map/flash_map_integrity.c create mode 100644 subsys/storage/flash_map/flash_map_layout.c create mode 100644 subsys/storage/flash_map/flash_map_priv.h diff --git a/subsys/storage/flash_map/CMakeLists.txt b/subsys/storage/flash_map/CMakeLists.txt index 715410c07e4..3b5085e61f1 100644 --- a/subsys/storage/flash_map/CMakeLists.txt +++ b/subsys/storage/flash_map/CMakeLists.txt @@ -3,4 +3,5 @@ zephyr_sources(flash_map.c) zephyr_sources_ifndef(CONFIG_FLASH_MAP_CUSTOM flash_map_default.c) zephyr_sources_ifdef(CONFIG_FLASH_MAP_SHELL flash_map_shell.c) - +zephyr_sources_ifdef(CONFIG_FLASH_PAGE_LAYOUT flash_map_layout.c) +zephyr_sources_ifdef(CONFIG_FLASH_AREA_CHECK_INTEGRITY flash_map_integrity.c) diff --git a/subsys/storage/flash_map/flash_map.c b/subsys/storage/flash_map/flash_map.c index 79577a5bc19..d17d994b63d 100644 --- a/subsys/storage/flash_map/flash_map.c +++ b/subsys/storage/flash_map/flash_map.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017-2021 Nordic Semiconductor ASA * Copyright (c) 2015 Runtime Inc * Copyright (c) 2017 Linaro Ltd * Copyright (c) 2020 Gerson Fernando Budke @@ -12,42 +12,11 @@ #include #include #include +#include "flash_map_priv.h" #include #include #include -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY) -#include -#include -#include -#endif - -#if defined(CONFIG_FLASH_PAGE_LAYOUT) -struct layout_data { - uint32_t area_idx; - uint32_t area_off; - uint32_t area_len; - void *ret; /* struct flash_area* or struct flash_sector* */ - uint32_t ret_idx; - uint32_t ret_len; - int status; -}; -#endif /* CONFIG_FLASH_PAGE_LAYOUT */ - -extern const struct flash_area *flash_map; -extern const int flash_map_entries; - -static struct flash_area const *get_flash_area_from_id(int idx) -{ - for (int i = 0; i < flash_map_entries; i++) { - if (flash_map[i].fa_id == idx) { - return &flash_map[i]; - } - } - - return NULL; -} - void flash_area_foreach(flash_area_cb_t user_cb, void *user_data) { for (int i = 0; i < flash_map_entries; i++) { @@ -77,111 +46,6 @@ void flash_area_close(const struct flash_area *fa) /* nothing to do for now */ } -static inline bool is_in_flash_area_bounds(const struct flash_area *fa, - off_t off, size_t len) -{ - return (off >= 0) && ((off + len) <= fa->fa_size); -} - -#if defined(CONFIG_FLASH_PAGE_LAYOUT) -/* - * Check if a flash_page_foreach() callback should exit early, due to - * one of the following conditions: - * - * - The flash page described by "info" is before the area of interest - * described in "data" - * - The flash page is after the end of the area - * - There are too many flash pages on the device to fit in the array - * held in data->ret. In this case, data->status is set to -ENOMEM. - * - * The value to return to flash_page_foreach() is stored in - * "bail_value" if the callback should exit early. - */ -static bool should_bail(const struct flash_pages_info *info, - struct layout_data *data, - bool *bail_value) -{ - if (info->start_offset < data->area_off) { - *bail_value = true; - return true; - } else if (info->start_offset >= data->area_off + data->area_len) { - *bail_value = false; - return true; - } else if (data->ret_idx >= data->ret_len) { - data->status = -ENOMEM; - *bail_value = false; - return true; - } - - return false; -} - -/* - * Generic page layout discovery routine. This is kept separate to - * support both the deprecated flash_area_to_sectors() and the current - * flash_area_get_sectors(). A lot of this can be inlined once - * flash_area_to_sectors() is removed. - */ -static int flash_area_layout(int idx, uint32_t *cnt, void *ret, -flash_page_cb cb, struct layout_data *cb_data) -{ - const struct device *flash_dev; - const struct flash_area *fa; - int rc = flash_area_open(idx, &fa); - - if (rc < 0 || fa == NULL) { - return -EINVAL; - } - - cb_data->area_idx = idx; - cb_data->area_off = fa->fa_off; - cb_data->area_len = fa->fa_size; - - cb_data->ret = ret; - cb_data->ret_idx = 0U; - cb_data->ret_len = *cnt; - cb_data->status = 0; - - flash_dev = device_get_binding(fa->fa_dev_name); - flash_area_close(fa); - if (flash_dev == NULL) { - return -ENODEV; - } - - flash_page_foreach(flash_dev, cb, cb_data); - - if (cb_data->status == 0) { - *cnt = cb_data->ret_idx; - } - - return cb_data->status; -} - -static bool get_sectors_cb(const struct flash_pages_info *info, void *datav) -{ - struct layout_data *data = datav; - struct flash_sector *ret = data->ret; - bool bail; - - if (should_bail(info, data, &bail)) { - return bail; - } - - ret[data->ret_idx].fs_off = info->start_offset - data->area_off; - ret[data->ret_idx].fs_size = info->size; - data->ret_idx++; - - return true; -} - -int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret) -{ - struct layout_data data; - - return flash_area_layout(idx, cnt, ret, get_sectors_cb, &data); -} -#endif /* CONFIG_FLASH_PAGE_LAYOUT */ - int flash_area_read(const struct flash_area *fa, off_t off, void *dst, size_t len) { @@ -260,60 +124,3 @@ uint8_t flash_area_erased_val(const struct flash_area *fa) return param->erase_value; } - -#if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY) -int flash_area_check_int_sha256(const struct flash_area *fa, - const struct flash_area_check *fac) -{ - unsigned char hash[TC_SHA256_DIGEST_SIZE]; - struct tc_sha256_state_struct sha; - const struct device *dev; - int to_read; - int pos; - int rc; - - if (fa == NULL || fac == NULL || fac->match == NULL || - fac->rbuf == NULL || fac->clen == 0 || fac->rblen == 0) { - return -EINVAL; - } - - if (!is_in_flash_area_bounds(fa, fac->off, fac->clen)) { - return -EINVAL; - } - - if (tc_sha256_init(&sha) != TC_CRYPTO_SUCCESS) { - return -ESRCH; - } - - dev = device_get_binding(fa->fa_dev_name); - to_read = fac->rblen; - - for (pos = 0; pos < fac->clen; pos += to_read) { - if (pos + to_read > fac->clen) { - to_read = fac->clen - pos; - } - - rc = flash_read(dev, (fa->fa_off + fac->off + pos), - fac->rbuf, to_read); - if (rc != 0) { - return rc; - } - - if (tc_sha256_update(&sha, - fac->rbuf, - to_read) != TC_CRYPTO_SUCCESS) { - return -ESRCH; - } - } - - if (tc_sha256_final(hash, &sha) != TC_CRYPTO_SUCCESS) { - return -ESRCH; - } - - if (memcmp(hash, fac->match, TC_SHA256_DIGEST_SIZE)) { - return -EILSEQ; - } - - return 0; -} -#endif /* CONFIG_FLASH_AREA_CHECK_INTEGRITY */ diff --git a/subsys/storage/flash_map/flash_map_integrity.c b/subsys/storage/flash_map/flash_map_integrity.c new file mode 100644 index 00000000000..a76841e3d6d --- /dev/null +++ b/subsys/storage/flash_map/flash_map_integrity.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017-2021 Nordic Semiconductor ASA + * Copyright (c) 2015 Runtime Inc + * Copyright (c) 2017 Linaro Ltd + * Copyright (c) 2020 Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "flash_map_priv.h" +#include +#include +#include + +#include +#include +#include + +int flash_area_check_int_sha256(const struct flash_area *fa, + const struct flash_area_check *fac) +{ + unsigned char hash[TC_SHA256_DIGEST_SIZE]; + struct tc_sha256_state_struct sha; + const struct device *dev; + int to_read; + int pos; + int rc; + + if (fa == NULL || fac == NULL || fac->match == NULL || + fac->rbuf == NULL || fac->clen == 0 || fac->rblen == 0) { + return -EINVAL; + } + + if (!is_in_flash_area_bounds(fa, fac->off, fac->clen)) { + return -EINVAL; + } + + if (tc_sha256_init(&sha) != TC_CRYPTO_SUCCESS) { + return -ESRCH; + } + + dev = device_get_binding(fa->fa_dev_name); + to_read = fac->rblen; + + for (pos = 0; pos < fac->clen; pos += to_read) { + if (pos + to_read > fac->clen) { + to_read = fac->clen - pos; + } + + rc = flash_read(dev, (fa->fa_off + fac->off + pos), + fac->rbuf, to_read); + if (rc != 0) { + return rc; + } + + if (tc_sha256_update(&sha, + fac->rbuf, + to_read) != TC_CRYPTO_SUCCESS) { + return -ESRCH; + } + } + + if (tc_sha256_final(hash, &sha) != TC_CRYPTO_SUCCESS) { + return -ESRCH; + } + + if (memcmp(hash, fac->match, TC_SHA256_DIGEST_SIZE)) { + return -EILSEQ; + } + + return 0; +} diff --git a/subsys/storage/flash_map/flash_map_layout.c b/subsys/storage/flash_map/flash_map_layout.c new file mode 100644 index 00000000000..a622427a2e4 --- /dev/null +++ b/subsys/storage/flash_map/flash_map_layout.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017-2021 Nordic Semiconductor ASA + * Copyright (c) 2015 Runtime Inc + * Copyright (c) 2017 Linaro Ltd + * Copyright (c) 2020 Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct layout_data { + uint32_t area_idx; + uint32_t area_off; + uint32_t area_len; + void *ret; /* struct flash_area* or struct flash_sector* */ + uint32_t ret_idx; + uint32_t ret_len; + int status; +}; + +/* + * Check if a flash_page_foreach() callback should exit early, due to + * one of the following conditions: + * + * - The flash page described by "info" is before the area of interest + * described in "data" + * - The flash page is after the end of the area + * - There are too many flash pages on the device to fit in the array + * held in data->ret. In this case, data->status is set to -ENOMEM. + * + * The value to return to flash_page_foreach() is stored in + * "bail_value" if the callback should exit early. + */ +static bool should_bail(const struct flash_pages_info *info, + struct layout_data *data, + bool *bail_value) +{ + if (info->start_offset < data->area_off) { + *bail_value = true; + return true; + } else if (info->start_offset >= data->area_off + data->area_len) { + *bail_value = false; + return true; + } else if (data->ret_idx >= data->ret_len) { + data->status = -ENOMEM; + *bail_value = false; + return true; + } + + return false; +} + +/* + * Generic page layout discovery routine. This is kept separate to + * support both the deprecated flash_area_to_sectors() and the current + * flash_area_get_sectors(). A lot of this can be inlined once + * flash_area_to_sectors() is removed. + */ +static int flash_area_layout(int idx, uint32_t *cnt, void *ret, +flash_page_cb cb, struct layout_data *cb_data) +{ + const struct device *flash_dev; + const struct flash_area *fa; + int rc = flash_area_open(idx, &fa); + + if (rc < 0 || fa == NULL) { + return -EINVAL; + } + + cb_data->area_idx = idx; + cb_data->area_off = fa->fa_off; + cb_data->area_len = fa->fa_size; + + cb_data->ret = ret; + cb_data->ret_idx = 0U; + cb_data->ret_len = *cnt; + cb_data->status = 0; + + flash_dev = device_get_binding(fa->fa_dev_name); + flash_area_close(fa); + if (flash_dev == NULL) { + return -ENODEV; + } + + flash_page_foreach(flash_dev, cb, cb_data); + + if (cb_data->status == 0) { + *cnt = cb_data->ret_idx; + } + + return cb_data->status; +} + +static bool get_sectors_cb(const struct flash_pages_info *info, void *datav) +{ + struct layout_data *data = datav; + struct flash_sector *ret = data->ret; + bool bail; + + if (should_bail(info, data, &bail)) { + return bail; + } + + ret[data->ret_idx].fs_off = info->start_offset - data->area_off; + ret[data->ret_idx].fs_size = info->size; + data->ret_idx++; + + return true; +} + +int flash_area_get_sectors(int idx, uint32_t *cnt, struct flash_sector *ret) +{ + struct layout_data data; + + return flash_area_layout(idx, cnt, ret, get_sectors_cb, &data); +} diff --git a/subsys/storage/flash_map/flash_map_priv.h b/subsys/storage/flash_map/flash_map_priv.h new file mode 100644 index 00000000000..48de310f0a2 --- /dev/null +++ b/subsys/storage/flash_map/flash_map_priv.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2017-2021 Nordic Semiconductor ASA + * Copyright (c) 2015 Runtime Inc + * Copyright (c) 2017 Linaro Ltd + * Copyright (c) 2020 Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SUBSYS_STORAGE_FLASH_MAP_PRIV_H_ +#define ZEPHYR_SUBSYS_STORAGE_FLASH_MAP_PRIV_H_ + +#include +#include +#include +#include + +extern const struct flash_area *flash_map; +extern const int flash_map_entries; + +static inline struct flash_area const *get_flash_area_from_id(int idx) +{ + for (int i = 0; i < flash_map_entries; i++) { + if (flash_map[i].fa_id == idx) { + return &flash_map[i]; + } + } + + return NULL; +} + + +static inline bool is_in_flash_area_bounds(const struct flash_area *fa, + off_t off, size_t len) +{ + return (off >= 0) && ((off + len) <= fa->fa_size); +} + +#endif /* ZEPHYR_SUBSYS_STORAGE_FLASH_MAP_PRIV_H_ */