| /* |
| * |
| * Copyright (c) 2023 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * @file |
| * Utilities for accessing persisted device configuration on |
| * platforms based on the NXP SDK. |
| */ |
| |
| #include "NXPConfig.h" |
| |
| #include "FreeRTOS.h" |
| #include "FunctionLib.h" |
| #include "board.h" |
| #include <lib/core/CHIPEncoding.h> |
| #include <platform/CHIPDeviceError.h> |
| #include <platform/internal/testing/ConfigUnitTest.h> |
| |
| #include "fwk_file_cache.h" |
| #include "fwk_fs_abstraction.h" |
| #include "fwk_key_storage.h" |
| #include "fwk_lfs_mflash.h" |
| |
| #if defined(DEBUG_NVM) && (DEBUG_NVM == 2) |
| #include "fsl_debug_console.h" |
| #define DBG_PRINTF PRINTF |
| #define INFO_PRINTF PRINTF |
| |
| #elif defined(DEBUG_NVM) && (DEBUG_NVM == 1) |
| #include "fsl_debug_console.h" |
| #define DBG_PRINTF PRINTF |
| #define INFO_PRINTF(...) |
| |
| #else |
| #define DBG_PRINTF(...) |
| #define INFO_PRINTF(...) |
| #endif |
| |
| /* Temporary namespace for integer and string keys */ |
| #define NS_INT "_fki" |
| #define NS_STR "_fks" |
| |
| /* Set to 1 if you want to see the statistics about the keys and their length */ |
| #define ENABLE_KEYS_STATS 0 |
| |
| /* Size of the ram memory section for the KS configuration */ |
| /* following the study of the size of the Matter key storage files, |
| we defined that a buffer size equal to 2265 is necessary. We decided to add a mark-up, bringing the buffer size to 5k to be safe */ |
| #ifndef KS_MATTER_SCRATCH_AREA_SIZE_MAX |
| #define KS_MATTER_SCRATCH_AREA_SIZE_MAX 5 * 1024 |
| #endif |
| |
| static uint8_t mem_section[KS_MATTER_SCRATCH_AREA_SIZE_MAX]; |
| static ks_config_t ks_config = { |
| .size = KS_MATTER_SCRATCH_AREA_SIZE_MAX, .KS_name = "KSconf", .mem_p = mem_section, |
| //.mem_p = NULL, |
| }; |
| static void * ks_handle_p = NULL; |
| |
| static bool isInitialized = false; |
| |
| #if (ENABLE_KEYS_STATS == 1) |
| typedef struct |
| { |
| uint16_t writtenKeys_str; |
| uint16_t deletedKeys_str; |
| uint16_t writtenKeys_int; |
| uint16_t deletedKeys_int; |
| } ks_keys_stats_t; |
| static ks_keys_stats_t keys_stats = { 0, 0, 0, 0 }; |
| #endif |
| |
| namespace chip { |
| namespace DeviceLayer { |
| namespace Internal { |
| |
| CHIP_ERROR NXPConfig::Init() |
| { |
| if (!isInitialized) |
| { |
| ks_handle_p = KS_Init(&ks_config); |
| isInitialized = true; |
| } |
| |
| DBG_PRINTF("Init"); |
| return CHIP_NO_ERROR; |
| } |
| |
| CHIP_ERROR NXPConfig::ReadConfigValue(Key key, bool & val) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| int req_len; |
| int outLen; |
| bool tempVal; |
| |
| req_len = sizeof(bool); |
| outLen = 0; |
| tempVal = false; |
| |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_GetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, (void *) &tempVal, req_len, &outLen); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| val = tempVal; |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "ReadConfigValue bool = %u", val); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::ReadConfigValue(Key key, uint32_t & val) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| int req_len; |
| int outLen; |
| uint32_t tempVal; |
| |
| req_len = sizeof(uint32_t); |
| outLen = 0; |
| tempVal = 0; |
| |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_GetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, (void *) &tempVal, req_len, &outLen); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| val = tempVal; |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "ReadConfigValue uint32_t = %lu", val); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::ReadConfigValue(Key key, uint64_t & val) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| int req_len; |
| int outLen; |
| uint64_t tempVal; |
| |
| req_len = sizeof(uint64_t); |
| outLen = 0; |
| tempVal = 0; |
| |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_GetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, (void *) &tempVal, req_len, &outLen); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| val = tempVal; |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "ReadConfigValue uint64_t = " ChipLogFormatX64, ChipLogValueX64(val)); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| uint32_t sizeToRead; |
| |
| sizeToRead = bufSize; |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_GetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, (void *) buf, (int) bufSize, (int *) &sizeToRead); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| outLen = sizeToRead; |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "ReadConfigValueStr bufSize = %u, lenRead = %u", bufSize, outLen); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen) |
| { |
| return ReadConfigValueStr(key, (char *) buf, bufSize, outLen); |
| } |
| |
| CHIP_ERROR NXPConfig::ReadConfigValueBin(const char * keyString, uint8_t * buf, size_t bufSize, size_t & outLen) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| uint32_t sizeToRead; |
| |
| sizeToRead = bufSize; |
| VerifyOrExit(keyString != NULL, err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_GetKeyString(ks_handle_p, (char *) keyString, strlen(keyString) + 1, (char *) NS_STR, (void *) buf, (int) bufSize, |
| (int *) &sizeToRead); // +1 to add end \0 char |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| outLen = sizeToRead; |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "ReadConfigValueStr lenRead = %u", outLen); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::ReadConfigValueCounter(uint8_t counterIdx, uint32_t & val) |
| { |
| Key key = kMinConfigKey_ChipCounter + counterIdx; |
| return ReadConfigValue(key, val); |
| } |
| |
| CHIP_ERROR NXPConfig::WriteConfigValue(Key key, bool val) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| int valSize; |
| |
| valSize = sizeof(bool); |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_SetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, (void *) &val, valSize); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| |
| DBG_PRINTF("WriteConfigValue: MT write \r\n"); |
| |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "WriteConfigValue done"); |
| #endif |
| |
| #if (ENABLE_KEYS_STATS == 1) |
| keys_stats.writtenKeys_int++; |
| ChipLogProgress(DeviceLayer, "Data len: %u. Integer keys written until now: %u.", valSize, keys_stats.writtenKeys_int); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::WriteConfigValue(Key key, uint32_t val) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| int valSize; |
| |
| valSize = sizeof(uint32_t); |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_SetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, (void *) &val, valSize); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| |
| DBG_PRINTF("WriteConfigValue: MT write \r\n"); |
| |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "WriteConfigValue done"); |
| #endif |
| |
| #if (ENABLE_KEYS_STATS == 1) |
| keys_stats.writtenKeys_int++; |
| ChipLogProgress(DeviceLayer, "Data len: %u. Integer keys written until now: %u.", valSize, keys_stats.writtenKeys_int); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::WriteConfigValue(Key key, uint64_t val) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| int valSize; |
| |
| valSize = sizeof(uint64_t); |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_SetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, (void *) &val, valSize); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| |
| DBG_PRINTF("WriteConfigValue64: MT write \r\n"); |
| |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "WriteConfigValue done"); |
| #endif |
| |
| #if (ENABLE_KEYS_STATS == 1) |
| keys_stats.writtenKeys_int++; |
| ChipLogProgress(DeviceLayer, "Data len: %u. Integer keys written until now: %u.", valSize, keys_stats.writtenKeys_int); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::WriteConfigValueStr(Key key, const char * str) |
| { |
| return WriteConfigValueStr(key, str, (str != NULL) ? strlen(str) : 0); |
| } |
| |
| CHIP_ERROR NXPConfig::WriteConfigValueStr(Key key, const char * str, size_t strLen) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_SetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, (void *) str, strLen); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| |
| DBG_PRINTF("WriteConfigValueStr: MT write \r\n"); |
| |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "WriteConfigValue done"); |
| #endif |
| |
| #if (ENABLE_KEYS_STATS == 1) |
| keys_stats.writtenKeys_int++; |
| ChipLogProgress(DeviceLayer, "Data len: %u. Integer keys written until now: %u.", strLen, keys_stats.writtenKeys_int); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen) |
| { |
| return WriteConfigValueStr(key, (char *) data, dataLen); |
| } |
| |
| CHIP_ERROR NXPConfig::WriteConfigValueBin(const char * keyString, const uint8_t * data, size_t dataLen) |
| { |
| CHIP_ERROR err; |
| ks_error_t status; |
| int keyLen; |
| |
| keyLen = (int) strlen(keyString) + 1; // +1 to add end \0 char |
| VerifyOrExit(keyString != NULL, err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_SetKeyString(ks_handle_p, (char *) keyString, keyLen, (char *) NS_STR, (void *) data, (int) dataLen); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| |
| DBG_PRINTF("WriteConfigValueBin: MT write \r\n"); |
| |
| #if (DEBUG_NVM > 0) |
| ChipLogProgress(DeviceLayer, "WriteConfigValue done"); |
| #endif |
| |
| #if (ENABLE_KEYS_STATS == 1) |
| keys_stats.writtenKeys_str++; |
| ChipLogProgress(DeviceLayer, "Data len: %u. Key len: %u. String keys written until now: %u.", dataLen, keyLen, |
| keys_stats.writtenKeys_str); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::WriteConfigValueCounter(uint8_t counterIdx, uint32_t val) |
| { |
| Key key = kMinConfigKey_ChipCounter + counterIdx; |
| return WriteConfigValue(key, val); |
| } |
| |
| CHIP_ERROR NXPConfig::ClearConfigValue(Key key) |
| { |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| ks_error_t status; |
| |
| VerifyOrExit(ValidConfigKey(key), err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_DeleteKeyInt(ks_handle_p, (int) key, (char *) NS_INT); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| |
| DBG_PRINTF("ClearConfigValue: MT write \r\n"); |
| |
| #if (ENABLE_KEYS_STATS == 1) |
| keys_stats.deletedKeys_int++; |
| ChipLogProgress(DeviceLayer, "Integer keys deleted until now: %u.", keys_stats.deletedKeys_int); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| CHIP_ERROR NXPConfig::ClearConfigValue(const char * keyString) |
| { |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| ks_error_t status; |
| int keyLen; |
| |
| keyLen = strlen(keyString) + 1; // +1 to add end \0 char |
| VerifyOrExit(keyString != NULL, err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND); // Verify key id. |
| status = KS_DeleteKeyString(ks_handle_p, (char *) keyString, keyLen, (char *) NS_STR); |
| SuccessOrExit(err = MapKeyStorageStatus(status)); |
| |
| DBG_PRINTF("WriteConfigValueBin: MT write \r\n"); |
| |
| #if (ENABLE_KEYS_STATS == 1) |
| keys_stats.deletedKeys_str++; |
| ChipLogProgress(DeviceLayer, "String keys deleted until now: %u.", keys_stats.deletedKeys_str); |
| #endif |
| |
| exit: |
| return err; |
| } |
| |
| bool NXPConfig::ConfigValueExists(Key key) |
| { |
| ks_error_t status; |
| bool found; |
| void * readValue_p; |
| int outLen; |
| int bufSize; |
| |
| found = false; |
| readValue_p = NULL; |
| outLen = 0; |
| bufSize = 0; |
| |
| if (ValidConfigKey(key)) |
| { |
| /* Get the first occurence */ |
| status = KS_GetKeyInt(ks_handle_p, (int) key, (char *) NS_INT, readValue_p, bufSize, &outLen); |
| found = (status != KS_ERROR_KEY_NOT_FOUND); |
| } |
| return found; |
| } |
| |
| CHIP_ERROR NXPConfig::FactoryResetConfig(void) |
| { |
| /* |
| * When a factory reset is required, shut down the KeyStorage (which |
| * also flushes the FileCache) and then execute a simple format of the |
| * the file system partition. |
| */ |
| KS_DeInit(ks_handle_p); |
| FSA_Format(); |
| |
| DBG_PRINTF("FactoryResetConfig done\r\n"); |
| |
| return CHIP_NO_ERROR; |
| } |
| |
| bool NXPConfig::ValidConfigKey(Key key) |
| { |
| // Returns true if the key is in the valid CHIP Config PDM key range. |
| |
| if ((key >= kMinConfigKey_ChipFactory) && (key <= kMaxConfigKey_KVS)) |
| { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| CHIP_ERROR NXPConfig::MapKeyStorageStatus(ks_error_t ksStatus) |
| { |
| CHIP_ERROR err; |
| |
| switch (ksStatus) |
| { |
| case KS_ERROR_NONE: |
| err = CHIP_NO_ERROR; |
| break; |
| case KS_ERROR_BUF_TOO_SMALL: |
| err = CHIP_ERROR_BUFFER_TOO_SMALL; |
| break; |
| default: /* KS_ERROR_KEY_NOT_FOUND */ |
| err = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND; |
| break; |
| } |
| |
| return err; |
| } |
| |
| void NXPConfig::RunConfigUnitTest(void) {} |
| |
| void NXPConfig::RunSystemIdleTask(void) |
| { |
| if (isInitialized) |
| { |
| FC_Process(); |
| INFO_PRINTF("str mt write \r\n"); |
| } |
| } |
| |
| } // namespace Internal |
| } // namespace DeviceLayer |
| } // namespace chip |