From 2466248ac55a2a92e86eb5ba683d2243b12698b6 Mon Sep 17 00:00:00 2001 From: Alex Tsitsiura Date: Mon, 29 May 2023 19:19:24 +0300 Subject: [PATCH] [Telink] Fix TC-OPCREDS-3.6 and prevent writing to NVS during factory reset (#26784) * [Telink] Added storage reset in case of fabric count == 0 Signed-off-by: Misha Tkachenko * [Telink] Disable openthread before reset to prevent writing to NVS Signed-off-by: Misha Tkachenko * [Telink] remove commented code * Restyled by clang-format * [Telink]: Added a clear explanation for preventing NVS writing on shutdown Signed-off-by: Misha Tkachenko * [Telink]: Updated OpenThread finalization function Signed-off-by: Misha Tkachenko * Restyled by whitespace --------- Signed-off-by: Misha Tkachenko Co-authored-by: Misha Tkachenko Co-authored-by: Restyled.io Co-authored-by: Misha Tkachenko <36621698+mishadesh@users.noreply.github.com> --- .../telink/common/src/AppTaskCommon.cpp | 56 ++++++++++++++++++- .../telink/ThreadStackManagerImpl.cpp | 5 ++ src/platform/telink/ThreadStackManagerImpl.h | 1 + 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/examples/platform/telink/common/src/AppTaskCommon.cpp b/examples/platform/telink/common/src/AppTaskCommon.cpp index 4297d3ae3d4bad..ec45f9241d46e0 100644 --- a/examples/platform/telink/common/src/AppTaskCommon.cpp +++ b/examples/platform/telink/common/src/AppTaskCommon.cpp @@ -38,6 +38,11 @@ #include #endif +#ifdef CONFIG_CHIP_FACTORY_RESET_ERASE_NVS +#include +#include +#endif + using namespace chip::app; LOG_MODULE_DECLARE(app, CONFIG_CHIP_APP_LOG_LEVEL); @@ -118,7 +123,47 @@ class AppFabricTableDelegate : public FabricTable::Delegate { if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) { - chip::Server::GetInstance().ScheduleFactoryReset(); + ChipLogProgress(DeviceLayer, "Performing erasing of settings partition"); + +#ifdef CONFIG_CHIP_FACTORY_RESET_ERASE_NVS + void * storage = nullptr; + int status = settings_storage_get(&storage); + + if (status == 0) + { + status = nvs_clear(static_cast(storage)); + } + + if (!status) + { + status = nvs_mount(static_cast(storage)); + } + + if (status) + { + ChipLogError(DeviceLayer, "Storage clearance failed: %d", status); + } +#else + const CHIP_ERROR err = PersistedStorage::KeyValueStoreMgrImpl().DoFactoryReset(); + + if (err != CHIP_NO_ERROR) + { + ChipLogError(DeviceLayer, "Factory reset failed: %" CHIP_ERROR_FORMAT, err.Format()); + } + + ConnectivityMgr().ErasePersistentInfo(); +#endif + } + } +}; + +class PlatformMgrDelegate : public DeviceLayer::PlatformManagerDelegate +{ + void OnShutDown() override + { + if (ThreadStackManagerImpl().IsThreadEnabled()) + { + ThreadStackManagerImpl().Finalize(); } } }; @@ -240,6 +285,15 @@ CHIP_ERROR AppTaskCommon::InitCommonParts(void) chip::app::InteractionModelEngine::GetInstance()->RegisterReadHandlerAppCallback(&GetICDUtil()); #endif + // We need to disable OpenThread to prevent writing to the NVS storage when factory reset occurs + // The OpenThread thread is running during factory reset. The nvs_clear function is called during + // factory reset, which makes the NVS storage innaccessible, but the OpenThread knows nothing + // about this and tries to store the parameters to NVS. Because of this the OpenThread need to be + // shut down before NVS. This delegate fixes the issue "Failed to store setting , ret -13", + // which means that the NVS is already disabled. + // For this the OnShutdown function is used + PlatformMgr().SetDelegate(new PlatformMgrDelegate); + // Add CHIP event handler and start CHIP thread. // Note that all the initialization code should happen prior to this point to avoid data races // between the main and the CHIP threads. diff --git a/src/platform/telink/ThreadStackManagerImpl.cpp b/src/platform/telink/ThreadStackManagerImpl.cpp index d6657c4ef010e9..e66735b1de68f2 100644 --- a/src/platform/telink/ThreadStackManagerImpl.cpp +++ b/src/platform/telink/ThreadStackManagerImpl.cpp @@ -136,5 +136,10 @@ CHIP_ERROR ThreadStackManagerImpl::_StartThreadScan(NetworkCommissioning::Thread return CHIP_NO_ERROR; } +void ThreadStackManagerImpl::Finalize(void) +{ + otInstanceFinalize(openthread_get_default_instance()); +} + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/telink/ThreadStackManagerImpl.h b/src/platform/telink/ThreadStackManagerImpl.h index 870ea17c90eaed..508382332072c6 100644 --- a/src/platform/telink/ThreadStackManagerImpl.h +++ b/src/platform/telink/ThreadStackManagerImpl.h @@ -64,6 +64,7 @@ class ThreadStackManagerImpl final : public ThreadStackManager, CHIP_ERROR _InitThreadStack(); void SetRadioBlocked(bool state) { mRadioBlocked = state; } bool IsReadyToAttach(void) const { return mReadyToAttach; } + void Finalize(void); protected: // ===== Methods that implement the ThreadStackManager abstract interface.