From 0c98307bbb37ea149a8e2a304276ac99a0f1ee6e Mon Sep 17 00:00:00 2001 From: Krzysztof Taborowski Date: Fri, 2 Aug 2024 15:22:58 +0200 Subject: [PATCH] pal: mfg support only tlv [KRKNWK-18440] * remove support for non-tlv mfg versions * refactor Signed-off-by: Krzysztof Taborowski --- Kconfig.dependencies | 4 +- subsys/sal/sid_pal/src/sid_mfg_storage.c | 483 ++++++++--------------- tests/functional/mfg_storage/Kconfig | 2 +- tests/unit_tests/pal_mfg_storage/Kconfig | 2 +- 4 files changed, 164 insertions(+), 327 deletions(-) diff --git a/Kconfig.dependencies b/Kconfig.dependencies index 16fdfe35e0..7a873ce79a 100644 --- a/Kconfig.dependencies +++ b/Kconfig.dependencies @@ -125,12 +125,12 @@ config SIDEWALK_MFG_STORAGE help Sidewalk manufacturing storage module -config SIDEWALK_MFG_STORAGE_WRITE +config SIDEWALK_MFG_STORAGE_DIAGNOSTIC bool default SIDEWALK_ON_DEV_CERT depends on SIDEWALK_MFG_STORAGE help - Enable write functionality to mfg storage + Enable mfg storage diagnostic functionalities config SIDEWALK_STORAGE bool diff --git a/subsys/sal/sid_pal/src/sid_mfg_storage.c b/subsys/sal/sid_pal/src/sid_mfg_storage.c index 1afb83d462..03caf18468 100644 --- a/subsys/sal/sid_pal/src/sid_mfg_storage.c +++ b/subsys/sal/sid_pal/src/sid_mfg_storage.c @@ -11,6 +11,7 @@ #include #include #ifdef CONFIG_SIDEWALK_CRYPTO_PSA_KEY_STORAGE +// TODO: move secure features to another file? #include #endif /* CONFIG_SIDEWALK_CRYPTO_PSA_KEY_STORAGE */ @@ -29,11 +30,7 @@ LOG_MODULE_REGISTER(sid_mfg, CONFIG_SIDEWALK_LOG_LEVEL); -// Manufacturing version define -#define MFG_VERSION_1_VAL 0x01000000 -#define MFG_VERSION_2_VAL 0x2 - -#define FLASH_MEM_CHUNK (128) +#define FLASH_MEM_CHUNK (128) // TODO: get from low layer? #ifndef DEV_ID_REG #if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(NRF52832_XXAA) @@ -51,17 +48,9 @@ LOG_MODULE_REGISTER(sid_mfg, CONFIG_SIDEWALK_LOG_LEVEL); #endif #endif /* DEV_ID_REG */ -// DEV_ID masks -#define ENCODED_DEV_ID_SIZE_5_BYTES_MASK 0xA0 -#define DEV_ID_MSB_MASK 0x1F - -#define MFG_WORD_SIZE_VER_1 (8) - -static const uint32_t MFG_WORD_SIZE = 4; // in bytes - -#define MFG_STORE_TLV_HEADER_SIZE 4 -#define MFG_STORE_TLV_TAG_EMPTY 0xFFFF -#define EXPAND_TO_MULTIPLE_WORD(_VALUE_) (((_VALUE_ + 3) / 4) * 4) +#define MFG_STORE_TLV_HEADER_SIZE (4) +#define MFG_STORE_TLV_EMPTY_TAG_VALUE (0xFFFF) +#define ALIGN_VALUE_TO_WORD_SIZE(_VALUE_) (((_VALUE_ + WORD_SIZE - 1) / WORD_SIZE) * WORD_SIZE) #ifdef CONFIG_SIDEWALK_CRYPTO_PSA_KEY_STORAGE #define SID_PAL_MFG_STORE_DEVICE_PRIV_ED25519_RAW (100) @@ -81,12 +70,6 @@ struct sid_pal_mfg_store_value_to_address_offset { uint32_t offset; }; -static void ntoh_buff(uint8_t *buffer, size_t buff_len); -static uint32_t default_app_value_to_offset(int value); -static off_t checked_addr_return(off_t offset, uintptr_t start_address, uintptr_t end_address); -static off_t value_to_offset(sid_pal_mfg_store_value_t value, uintptr_t start_address, - uintptr_t end_address); - // clang-format off struct sid_pal_mfg_store_value_to_address_offset sid_pal_mfg_store_app_value_to_offset_table[] = { {SID_PAL_MFG_STORE_VERSION, SID_PAL_MFG_STORE_VERSION_SIZE, SID_PAL_MFG_STORE_OFFSET_VERSION}, @@ -130,119 +113,63 @@ struct sid_pal_mfg_store_value_to_address_offset sid_pal_mfg_store_app_value_to_ }; // clang-format on +static uint32_t app_value_to_offset(int value); static sid_pal_mfg_store_region_t nrf_mfg_store_region = { - .app_value_to_offset = default_app_value_to_offset, + .app_value_to_offset = app_value_to_offset, }; +// TODO: abstract zephyr flash device? static const struct device *flash_dev; +/** + * @brief Search for tag value in mfg tlv. + * + * @param tag [in] tlv tag (type) to look for + * @param tlv_info [out] tag, length and value of found tag. + * @return true if tag was found. + * @return false if no tag found. + */ static bool sid_pal_mfg_store_search_for_tag(uint16_t tag, struct sid_pal_mfg_store_tlv_info *tlv_info) { off_t address = (off_t)(nrf_mfg_store_region.addr_start + - SID_PAL_MFG_STORE_OFFSET_VERSION * MFG_WORD_SIZE + - SID_PAL_MFG_STORE_VERSION_SIZE); + SID_PAL_MFG_STORE_OFFSET_VERSION * WORD_SIZE + + SID_PAL_MFG_STORE_VERSION_SIZE); // TODO: shouldn't is also support to read version? uint16_t current_tag, length; - uint8_t type_length_raw[MFG_STORE_TLV_HEADER_SIZE] = { 0 }; + uint8_t header_raw[MFG_STORE_TLV_HEADER_SIZE] = { 0 }; while (1) { - int rc = flash_read(flash_dev, address, type_length_raw, MFG_STORE_TLV_HEADER_SIZE); + /* Read next header (tag & length) */ + int rc = flash_read(flash_dev, address, header_raw, MFG_STORE_TLV_HEADER_SIZE); if (0 != rc) { LOG_ERR("Flash read fail %d", rc); return false; } - current_tag = (type_length_raw[0] << 8) + type_length_raw[1]; - length = (type_length_raw[2] << 8) + type_length_raw[3]; + current_tag = (header_raw[0] << 8) + header_raw[1]; + length = (header_raw[2] << 8) + header_raw[3]; if (current_tag == tag) { + /* Tag found */ tlv_info->tag = tag; tlv_info->length = length; tlv_info->offset = address; return true; - } else { - if (current_tag == MFG_STORE_TLV_TAG_EMPTY) { - break; - } - /* - * Go to the next TLV. - * Since data is written to flash with data aligned to 4, we must take this - * into account if the data length is not a multiple of 4. - */ - address += (MFG_STORE_TLV_HEADER_SIZE + EXPAND_TO_MULTIPLE_WORD(length)); - // Check that we have not reached the end of the storage - if ((uintptr_t)(address + MFG_STORE_TLV_HEADER_SIZE + MFG_WORD_SIZE) > - nrf_mfg_store_region.addr_end) { - break; - } } - } - return false; -} -/** - * @brief The function converts network byte order to host byte order on the whole buffer. - * - * @param buffer - input/output buffer. - * @param buff_len - number of bytes in buffer. - */ -static void ntoh_buff(uint8_t *buffer, size_t buff_len) -{ - uint32_t val_l = 0; - size_t i = 0; - size_t mod_len = buff_len % sizeof(uint32_t); - - if (sizeof(uint32_t) <= buff_len) { - for (i = 0; i < (buff_len - mod_len); i += sizeof(uint32_t)) { - memcpy(&val_l, &buffer[i], sizeof(val_l)); - val_l = sys_be32_to_cpu(val_l); - memcpy(&buffer[i], &val_l, sizeof(val_l)); + if (current_tag == MFG_STORE_TLV_EMPTY_TAG_VALUE) { + break; } - } - if (2 == mod_len) { - uint16_t val_s = 0; - memcpy(&val_s, &buffer[i], sizeof(val_s)); - val_s = sys_be16_to_cpu(val_s); - memcpy(&buffer[i], &val_s, sizeof(val_s)); - } else if (3 == mod_len) { - val_l = 0; - memcpy(&val_l, &buffer[i], 3 * sizeof(uint8_t)); - val_l = sys_be24_to_cpu(val_l); - memcpy(&buffer[i], &val_l, 3 * sizeof(uint8_t)); - } -} + /* Go to the next TLV */ + address += (MFG_STORE_TLV_HEADER_SIZE + ALIGN_VALUE_TO_WORD_SIZE(length)); -/** - * @brief The 'dummy' function used when application doesn't provide it's own - * implementation for this function. - * - * @param value - unused argument. - * @return SID_PAL_MFG_STORE_INVALID_OFFSET - */ -static uint32_t default_app_value_to_offset(int value) -{ - ARG_UNUSED(value); - LOG_WRN("No support for app_value_to_offset."); - return SID_PAL_MFG_STORE_INVALID_OFFSET; -} - -/** - * @brief The function checks if offset is in address range of the manufacturing store partition. - * - * @param offset - memory offset. - * @param start_address - mfg partition start address. - * @param end_address - mfg partition end address. - * @return Offset in physical flash memory or SID_PAL_MFG_STORE_INVALID_OFFSET when offest is out - * of manufacturing storage address range. - */ -static off_t checked_addr_return(off_t offset, uintptr_t start_address, uintptr_t end_address) -{ - if (start_address + offset >= end_address) { - LOG_ERR("Offset past manufacturing store end: %d.", (int)offset); - return SID_PAL_MFG_STORE_INVALID_OFFSET; + if ((uintptr_t)(address + MFG_STORE_TLV_HEADER_SIZE + WORD_SIZE) > + nrf_mfg_store_region.addr_end) { + break; + } } - return (off_t)(start_address + offset); + return false; } /** @@ -253,8 +180,8 @@ static off_t checked_addr_return(off_t offset, uintptr_t start_address, uintptr_ * @param end_address - mfg partition end address. * @return Offset in physical flash memory when success otherwise SID_PAL_MFG_STORE_INVALID_OFFSET. */ -static off_t value_to_offset(sid_pal_mfg_store_value_t value, uintptr_t start_address, - uintptr_t end_address) +static off_t sid_pal_mfg_store_value_to_offset(sid_pal_mfg_store_value_t value, + uintptr_t start_address, uintptr_t end_address) { const size_t table_count = ARRAY_SIZE(sid_pal_mfg_store_app_value_to_offset_table); @@ -271,7 +198,12 @@ static off_t value_to_offset(sid_pal_mfg_store_value_t value, uintptr_t start_ad // This is not a core value. Search for this value among those provided by the application. off_t custom_offset = nrf_mfg_store_region.app_value_to_offset(value); if (SID_PAL_MFG_STORE_INVALID_OFFSET != custom_offset) { - return checked_addr_return(custom_offset, start_address, end_address); + if (start_address + custom_offset >= end_address) { + LOG_ERR("Offset past manufacturing store end: %d.", + (int)custom_offset); + return SID_PAL_MFG_STORE_INVALID_OFFSET; + } + return (off_t)(start_address + custom_offset); } } @@ -279,12 +211,26 @@ static off_t value_to_offset(sid_pal_mfg_store_value_t value, uintptr_t start_ad return SID_PAL_MFG_STORE_INVALID_OFFSET; } +/** + * @brief The 'dummy' function used when application doesn't provide it's own + * implementation for this function. + * + * @param value - unused argument. + * @return SID_PAL_MFG_STORE_INVALID_OFFSET + */ +static uint32_t app_value_to_offset(int value) +{ + ARG_UNUSED(value); + LOG_WRN("No support for app_value_to_offset."); + return SID_PAL_MFG_STORE_INVALID_OFFSET; +} + void sid_pal_mfg_store_init(sid_pal_mfg_store_region_t mfg_store_region) { nrf_mfg_store_region = mfg_store_region; if (!nrf_mfg_store_region.app_value_to_offset) { - nrf_mfg_store_region.app_value_to_offset = default_app_value_to_offset; + nrf_mfg_store_region.app_value_to_offset = app_value_to_offset; } flash_dev = DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_flash_controller)); @@ -300,19 +246,20 @@ void sid_pal_mfg_store_init(sid_pal_mfg_store_region_t mfg_store_region) sid_pal_mfg_store_read(SID_PAL_MFG_STORE_DEVICE_PRIV_ED25519_RAW, raw_key, sizeof(raw_key)); if (0 != memcmp(raw_key, zeros, sizeof(raw_key))) { rc = sid_crypto_keys_new_import(SID_CRYPTO_MFG_ED25519_PRIV_KEY_ID, raw_key, - sizeof(raw_key)); + sizeof(raw_key)); LOG_INF("MFG_ED25519 import %s", (0 == rc) ? "success" : "failure"); LOG_HEXDUMP_INF(raw_key, sizeof(raw_key), "value:"); memset(raw_key, 0, sizeof(raw_key)); - rc = sid_pal_mfg_store_write(SID_PAL_MFG_STORE_DEVICE_PRIV_ED25519_RAW, raw_key, - sizeof(raw_key)); + rc = sid_pal_mfg_store_write( + SID_PAL_MFG_STORE_DEVICE_PRIV_ED25519_RAW, raw_key, + sizeof(raw_key)); // TODO: mfg storage doesn't support overwrite! LOG_INF("MFG_ED25519 overwrite status %d", rc); } sid_pal_mfg_store_read(SID_PAL_MFG_STORE_DEVICE_PRIV_P256R1_RAW, raw_key, sizeof(raw_key)); if (0 != memcmp(raw_key, zeros, sizeof(raw_key))) { rc = sid_crypto_keys_new_import(SID_CRYPTO_MFG_SECP_256R1_PRIV_KEY_ID, raw_key, - sizeof(raw_key)); + sizeof(raw_key)); LOG_INF("MFG_SECP_256R1 import %s", (0 == rc) ? "success" : "failure"); LOG_HEXDUMP_INF(raw_key, sizeof(raw_key), "value:"); memset(raw_key, 0, sizeof(raw_key)); @@ -322,6 +269,8 @@ void sid_pal_mfg_store_init(sid_pal_mfg_store_region_t mfg_store_region) } #endif /* CONFIG_SIDEWALK_CRYPTO_PSA_KEY_STORAGE */ + + // TODO: use fprotect to protect mfg partition form overwrite } void sid_pal_mfg_store_deinit(void) @@ -331,104 +280,69 @@ void sid_pal_mfg_store_deinit(void) int32_t sid_pal_mfg_store_write(uint16_t value, const uint8_t *buffer, uint16_t length) { -#if CONFIG_SIDEWALK_MFG_STORAGE_WRITE - uint32_t ret_code = 0; - uint8_t __aligned(4) wr_array[SID_PAL_MFG_STORE_MAX_FLASH_WRITE_LEN]; - - if (length == 0 || value == MFG_STORE_TLV_TAG_EMPTY || buffer == NULL) { + if (value == MFG_STORE_TLV_EMPTY_TAG_VALUE || !buffer || !length) { return (int32_t)SID_ERROR_INVALID_ARGS; } - uint32_t version = sid_pal_mfg_store_get_version(); - if (value == SID_PAL_MFG_STORE_VERSION) { - version = SID_PAL_MFG_STORE_VERSION; + struct sid_pal_mfg_store_tlv_info tlv_info = {}; + uintptr_t address; + bool found; + uint8_t __aligned(4) wr_array + [SID_PAL_MFG_STORE_MAX_FLASH_WRITE_LEN]; // TODO: Is SID_PAL_MFG_STORE_MAX_FLASH_WRITE_LEN accurate for nRF53 and nRF54? Shouldn't it be taken form zephyr, not sid ifc? + uint16_t full_length = ALIGN_VALUE_TO_WORD_SIZE(length); + int err = 0; + + /* mfg storage doesn't allow overwrites */ + if (sid_pal_mfg_store_search_for_tag(value, &tlv_info)) { + LOG_ERR("tag value already exists: %d", value); + return -1; } - if (version == SID_PAL_MFG_STORE_TLV_VERSION) { - struct sid_pal_mfg_store_tlv_info tlv_info = {}; - - if (sid_pal_mfg_store_search_for_tag(value, &tlv_info)) { - // The tag value already exists. We can't write duplicate - return -1; - } - - // Search for the end of data - if (!sid_pal_mfg_store_search_for_tag(MFG_STORE_TLV_TAG_EMPTY, &tlv_info)) { - LOG_ERR("MFG storage is full"); - return -1; - } - - uint16_t wr_length; - // The length sholud be a multiple of the program unit - uint16_t full_length = EXPAND_TO_MULTIPLE_WORD(length); - uintptr_t address = tlv_info.offset; - - // Check the remaining storage size - if (address + MFG_STORE_TLV_HEADER_SIZE + full_length > - nrf_mfg_store_region.addr_end) { - LOG_ERR("Not enough space to store: %d", value); - return -1; - } - - wr_array[0] = value >> 8; - wr_array[1] = value; - wr_array[2] = full_length >> 8; - wr_array[3] = full_length; - - ret_code = (int32_t)flash_write(flash_dev, address, wr_array, - MFG_STORE_TLV_HEADER_SIZE); - if (ret_code != 0) { - return ret_code; - } - address += MFG_STORE_TLV_HEADER_SIZE; - - while (full_length) { - wr_length = full_length > sizeof(wr_array) ? sizeof(wr_array) : full_length; - memset(wr_array, 0xFF, sizeof(wr_array)); - memcpy(wr_array, buffer, wr_length > length ? length : wr_length); - - ret_code = (int32_t)flash_write(flash_dev, address, wr_array, wr_length); - if (ret_code != 0) { - return ret_code; - } - address += wr_length; - buffer += wr_length; - full_length -= wr_length; - }; + /* search for empty space */ + found = sid_pal_mfg_store_search_for_tag(MFG_STORE_TLV_EMPTY_TAG_VALUE, &tlv_info); + if (!found) { + LOG_ERR("MFG storage is full"); + return -1; + } - return 0; + address = (uintptr_t)tlv_info.offset; + if (address + MFG_STORE_TLV_HEADER_SIZE + full_length > nrf_mfg_store_region.addr_end) { + LOG_ERR("Not enough space to store: %d", value); + return -1; + } - } else { - if (length > sizeof(wr_array)) { - return (int32_t)SID_ERROR_OUT_OF_RESOURCES; - } + /* write tag value and length */ + wr_array[0] = value >> 8; + wr_array[1] = value; + wr_array[2] = full_length >> 8; + wr_array[3] = full_length; - if (length % sizeof(uint32_t)) { - LOG_WRN("Length is not word-aligned."); - return (int32_t)SID_ERROR_INCOMPATIBLE_PARAMS; - } + err = flash_write(flash_dev, address, wr_array, MFG_STORE_TLV_HEADER_SIZE); + if (err != 0) { + return err; + } + address += MFG_STORE_TLV_HEADER_SIZE; - const off_t value_offset = value_to_offset(value, nrf_mfg_store_region.addr_start, - nrf_mfg_store_region.addr_end); + /* write data */ + while (full_length) { + uint16_t wr_length = + full_length > sizeof(wr_array) ? sizeof(wr_array) : full_length; - if (SID_PAL_MFG_STORE_INVALID_OFFSET == value_offset) { - return (int32_t)SID_ERROR_NOT_FOUND; - } + memset(wr_array, 0xFF, sizeof(wr_array)); + memcpy(wr_array, buffer, wr_length > length ? length : wr_length); - if (NULL == buffer) { - return (int32_t)SID_ERROR_NULL_POINTER; + err = flash_write(flash_dev, address, wr_array, wr_length); + if (err != 0) { + return err; } - memcpy(wr_array, buffer, length); - if (flash_dev) { - return (int32_t)flash_write(flash_dev, value_offset, wr_array, length); - } + address += wr_length; + buffer += wr_length; + full_length -= + wr_length; // TODO: consider refactor with for loop. full_length is unsigned... + }; - return (int32_t)SID_ERROR_UNINITIALIZED; - } -#else - return (int32_t)SID_ERROR_NOSUPPORT; -#endif + return 0; } void sid_pal_mfg_store_read(uint16_t value, uint8_t *buffer, uint16_t length) @@ -436,12 +350,14 @@ void sid_pal_mfg_store_read(uint16_t value, uint8_t *buffer, uint16_t length) #ifdef CONFIG_SIDEWALK_CRYPTO_PSA_KEY_STORAGE switch (value) { case SID_PAL_MFG_STORE_DEVICE_PRIV_ED25519: - if (sid_crypto_keys_buffer_set(SID_CRYPTO_MFG_ED25519_PRIV_KEY_ID, buffer, length)) { + if (sid_crypto_keys_buffer_set(SID_CRYPTO_MFG_ED25519_PRIV_KEY_ID, buffer, + length)) { LOG_ERR("DEVICE_PRIV_ED25519 read fail"); } return; case SID_PAL_MFG_STORE_DEVICE_PRIV_P256R1: - if (sid_crypto_keys_buffer_set(SID_CRYPTO_MFG_SECP_256R1_PRIV_KEY_ID, buffer, length)) { + if (sid_crypto_keys_buffer_set(SID_CRYPTO_MFG_SECP_256R1_PRIV_KEY_ID, buffer, + length)) { LOG_ERR("DEVICE_PRIV_P256R1 read fail"); } return; @@ -454,96 +370,40 @@ void sid_pal_mfg_store_read(uint16_t value, uint8_t *buffer, uint16_t length) } #endif /* CONFIG_SIDEWALK_CRYPTO_PSA_KEY_STORAGE */ - uint32_t version = sid_pal_mfg_store_get_version(); - if (version == SID_PAL_MFG_STORE_TLV_VERSION) { - // The SID_PAL_MFG_STORE_VERSION we should read as fixed offset - if (value == SID_PAL_MFG_STORE_VERSION) { - memcpy(buffer, &version, sizeof(version)); - return; - } - - struct sid_pal_mfg_store_tlv_info tlv_info; - if (sid_pal_mfg_store_search_for_tag(value, &tlv_info)) { - if (length > tlv_info.length) { - LOG_ERR("invalid length of the value"); - return; - } - int rc = flash_read(flash_dev, tlv_info.offset + MFG_STORE_TLV_HEADER_SIZE, - buffer, length); - if (0 != rc) { - LOG_ERR("Flash read fail %d", rc); - return; - } - } else { - /* - * For backwards compatibility with MFG version with fixed offsets, - * we must fill the buffer with empty data. - */ - memset(buffer, 0xFF, length); - } - } else { - const off_t value_offset = value_to_offset((sid_pal_mfg_store_value_t)value, - nrf_mfg_store_region.addr_start, - nrf_mfg_store_region.addr_end); - - if (!buffer) { - LOG_ERR("Null pointer provided."); - return; - } - - if (SID_PAL_MFG_STORE_INVALID_OFFSET != value_offset) { - if (flash_dev) { - int rc = flash_read(flash_dev, value_offset, buffer, length); - if (0 != rc) { - LOG_ERR("Flash read fail %d", rc); - } - } else { - LOG_ERR("MFG store is not initialized."); - } - } + struct sid_pal_mfg_store_tlv_info tlv_info; + bool found = sid_pal_mfg_store_search_for_tag(value, &tlv_info); + if (!found) { + LOG_ERR("tag value not found %d", value); + return; } -} - -static bool is_valid_value_offset(uint32_t offset) -{ - return offset != SID_PAL_MFG_STORE_INVALID_OFFSET; -} - -static uint16_t value_to_size(sid_pal_mfg_store_value_t value) -{ - const size_t table_count = sizeof(sid_pal_mfg_store_app_value_to_offset_table) / - sizeof(sid_pal_mfg_store_app_value_to_offset_table[0]); - for (uint32_t i = 0; i < table_count; i++) { - if (value == sid_pal_mfg_store_app_value_to_offset_table[i].value) { - return is_valid_value_offset( - sid_pal_mfg_store_app_value_to_offset_table[i].offset) ? - sid_pal_mfg_store_app_value_to_offset_table[i].size : - 0; - } + if (length > tlv_info.length) { + LOG_ERR("invalid length %d of tag value %d", length, value); + return; } - // NOTE: Getting size for App values >= SID_PAL_MFG_STORE_CORE_VALUE_MAX is not supported - return 0; + int err = + flash_read(flash_dev, tlv_info.offset + MFG_STORE_TLV_HEADER_SIZE, buffer, length); + if (err) { + LOG_ERR("Flash read fail %d", err); + memset(buffer, 0xFF, length); + } } uint16_t sid_pal_mfg_store_get_length_for_value(uint16_t value) { uint16_t length = 0; - if (sid_pal_mfg_store_get_version() == SID_PAL_MFG_STORE_TLV_VERSION) { - struct sid_pal_mfg_store_tlv_info tlv_info; - if (sid_pal_mfg_store_search_for_tag(value, &tlv_info)) { - length = tlv_info.length; - } - } else { - length = value_to_size((sid_pal_mfg_store_value_t)value); + struct sid_pal_mfg_store_tlv_info tlv_info; + if (sid_pal_mfg_store_search_for_tag(value, &tlv_info)) { + length = tlv_info.length; } + return length; } int32_t sid_pal_mfg_store_erase(void) { -#if CONFIG_SIDEWALK_MFG_STORAGE_WRITE +#if CONFIG_SIDEWALK_MFG_STORAGE_DIAGNOSTIC const size_t mfg_size = nrf_mfg_store_region.addr_end - nrf_mfg_store_region.addr_start; if (flash_dev) { return (int32_t)flash_erase(flash_dev, nrf_mfg_store_region.addr_start, mfg_size); @@ -557,39 +417,39 @@ int32_t sid_pal_mfg_store_erase(void) bool sid_pal_mfg_store_is_empty(void) { -#if CONFIG_SIDEWALK_MFG_STORAGE_WRITE +#if CONFIG_SIDEWALK_MFG_STORAGE_DIAGNOSTIC + if (!flash_dev) { + LOG_ERR("MFG store is not initialized."); + return false; + } + uint8_t empty_flash_mem[FLASH_MEM_CHUNK]; uint8_t tmp_buff[FLASH_MEM_CHUNK]; size_t length = sizeof(tmp_buff); + int rc; memset(empty_flash_mem, 0xFF, sizeof(empty_flash_mem)); + for (off_t offset = nrf_mfg_store_region.addr_start; offset < nrf_mfg_store_region.addr_end; + offset += length) { + if ((offset + length) > nrf_mfg_store_region.addr_end) { + length = nrf_mfg_store_region.addr_end - offset; + } - if (flash_dev) { - int rc; - for (off_t offset = nrf_mfg_store_region.addr_start; - offset < nrf_mfg_store_region.addr_end; offset += length) { - if ((offset + length) > nrf_mfg_store_region.addr_end) { - length = nrf_mfg_store_region.addr_end - offset; - } - - rc = flash_read(flash_dev, offset, tmp_buff, length); - if (0 != rc) { - LOG_ERR("Read flash memory error: %d.", rc); - return false; - } + rc = flash_read(flash_dev, offset, tmp_buff, length); + if (0 != rc) { + LOG_ERR("Read flash memory error: %d.", rc); + return false; + } - if (0 != memcmp(empty_flash_mem, tmp_buff, length)) { - return false; - } + if (0 != memcmp(empty_flash_mem, tmp_buff, length)) { + return false; } - return true; - } else { - LOG_ERR("MFG store is not initialized."); } + return true; #else LOG_WRN("The sid_pal_mfg_store_is_empty function is not enabled."); -#endif return false; +#endif } bool sid_pal_mfg_store_is_tlv_support(void) @@ -600,11 +460,11 @@ bool sid_pal_mfg_store_is_tlv_support(void) uint32_t sid_pal_mfg_store_get_version(void) { uint32_t version = 0; -#define MFG_VERSION_OFFSET_BYTES 4 if (flash_dev) { int rc = flash_read(flash_dev, - nrf_mfg_store_region.addr_start + MFG_VERSION_OFFSET_BYTES, + nrf_mfg_store_region.addr_start + + (SID_PAL_MFG_STORE_OFFSET_VERSION * WORD_SIZE), (uint8_t *)&version, SID_PAL_MFG_STORE_VERSION_SIZE); if (0 != rc) { LOG_ERR("Flash read fail %d", rc); @@ -616,6 +476,8 @@ uint32_t sid_pal_mfg_store_get_version(void) return sys_be32_to_cpu(version); } +/* Functions specific to Sidewalk with special handling */ + bool sid_pal_mfg_store_dev_id_get(uint8_t dev_id[SID_PAL_MFG_STORE_DEVID_SIZE]) { bool dev_id_found = false; @@ -632,26 +494,6 @@ bool sid_pal_mfg_store_dev_id_get(uint8_t dev_id[SID_PAL_MFG_STORE_DEVID_SIZE]) dev_id[0] = 0xBF; mcu_devid = sys_cpu_to_be32(mcu_devid); memcpy(&dev_id[1], &mcu_devid, sizeof(mcu_devid)); - } else { - const uint32_t version = sid_pal_mfg_store_get_version(); - if (MFG_VERSION_1_VAL == version || 0x1 == version) { - /** - * Correct dev_id for mfg version 1 - * For devices with mfg version 1, the device Id is stored as two words - * in network endian format. - * To read the device Id two words at SID_PAL_MFG_STORE_DEVID has to be - * read and each word needs to be changed to host endian format. - */ - uint8_t dev_id_buffer[MFG_WORD_SIZE_VER_1] = { 0 }; - sid_pal_mfg_store_read(SID_PAL_MFG_STORE_DEVID, dev_id_buffer, - sizeof(dev_id_buffer)); - ntoh_buff(dev_id_buffer, sizeof(dev_id_buffer)); - // Encode the size in the first 3 bits in MSB of the devId - dev_id_buffer[0] = (dev_id_buffer[0] & DEV_ID_MSB_MASK) | - ENCODED_DEV_ID_SIZE_5_BYTES_MASK; - memcpy(dev_id, dev_id_buffer, SID_PAL_MFG_STORE_DEVID_SIZE); - } - dev_id_found = true; } } return dev_id_found; @@ -674,11 +516,6 @@ bool sid_pal_mfg_store_serial_num_get(uint8_t serial_num[SID_PAL_MFG_STORE_SERIA return false; } - const uint32_t version = sid_pal_mfg_store_get_version(); - - if (MFG_VERSION_1_VAL == version || 0x1 == version) { - ntoh_buff(serial_num, SID_PAL_MFG_STORE_SERIAL_NUM_SIZE); - } return true; } diff --git a/tests/functional/mfg_storage/Kconfig b/tests/functional/mfg_storage/Kconfig index 195a7409f3..38fc7cd78e 100644 --- a/tests/functional/mfg_storage/Kconfig +++ b/tests/functional/mfg_storage/Kconfig @@ -16,7 +16,7 @@ config SIDEWALK_LOG_LEVEL config SHELL default y -config SIDEWALK_MFG_STORAGE_WRITE +config SIDEWALK_MFG_STORAGE_DIAGNOSTIC default y source "Kconfig.zephyr" diff --git a/tests/unit_tests/pal_mfg_storage/Kconfig b/tests/unit_tests/pal_mfg_storage/Kconfig index ceac53f3be..88180e72fb 100644 --- a/tests/unit_tests/pal_mfg_storage/Kconfig +++ b/tests/unit_tests/pal_mfg_storage/Kconfig @@ -11,7 +11,7 @@ config SIDEWALK_MFG_STORAGE default y imply FLASH -config SIDEWALK_MFG_STORAGE_WRITE +config SIDEWALK_MFG_STORAGE_DIAGNOSTIC default y source "Kconfig.zephyr"