Skip to content

Commit

Permalink
[Zephyr] Allow to erase entire NVS on factory reset (#23434)
Browse files Browse the repository at this point in the history
* [Zephyr] Allow to erase entire NVS on factory reset

Currently, the default factory reset implementation simply
removes Matter (and OpenThread) settings instead of
formatting the non-volatile storage partition. The latter
approach may be advisable in the cases where no settings
need to survive a factory reset, as it is expected to work
properly regardless of the state of the storage partition.
Additionally, it will regain the original storage
performance if it has been loaded with a lot of stale data.

Signed-off-by: Damian Krolik <[email protected]>

* Update doc

Signed-off-by: Damian Krolik <[email protected]>
  • Loading branch information
Damian-Nordic authored and pull[bot] committed Aug 16, 2024
1 parent f16cac2 commit 2749649
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 3 deletions.
4 changes: 4 additions & 0 deletions config/nrfconnect/chip-module/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -284,5 +284,9 @@ config CHIP_CERTIFiCATION_DECLARATION_OTA_IMAGE_ID

endif

# See config/zephyr/Kconfig for full definition
config CHIP_FACTORY_RESET_ERASE_NVS
bool
default y if CHIP_FACTORY_DATA || CHIP_FACTORY_DATA_CUSTOM_BACKEND

endif
11 changes: 11 additions & 0 deletions config/zephyr/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,17 @@ config CHIP_CRYPTO_PSA
Use the backend for the Matter crypto layer that is based on PSA crypto
API instead of the default, based on legacy mbedTLS APIs.

config CHIP_FACTORY_RESET_ERASE_NVS
bool "Erase NVS flash pages on factory reset"
depends on SETTINGS_NVS
help
When factory reset is requested, erase flash pages occupied by non-volatile storage
instead of removing Matter-related settings only. This provides a more robust
factory reset mechanism and allows to regain the original storage performance if any
firmware issue has brought it to an unexpected state. For this reason, it is
advisable to set this option if all configuration, including device-specific
entries, is supposed to be cleared on a factory reset.

config CHIP_MALLOC_SYS_HEAP
bool "Memory allocator based on Zephyr sys_heap"
imply SYS_HEAP_RUNTIME_STATS
Expand Down
9 changes: 9 additions & 0 deletions docs/guides/nrfconnect_examples_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ instead of using a QR code, which is the default configuration.
To enable NFC for commissioning and share the onboarding payload in an NFC tag,
set the `CONFIG_CHIP_NFC_COMMISSIONING` option.

**Factory reset behavior**

By default, the factory reset procedure implemented in the Matter stack removes
Matter-related settings only. If your application does not depend on any
device-lifelong data stored in the non-volatile storage, set the
`CONFIG_CHIP_FACTORY_RESET_ERASE_NVS` option to fully erase the NVS partition at
the factory reset. This approach is more robust and regains the original NVS
performance in case it has been polluted with unwanted entries.

**Logging**

You can enable logging for both the stack and Zephyr’s
Expand Down
27 changes: 24 additions & 3 deletions src/platform/Zephyr/ConfigurationManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>

#ifdef CONFIG_CHIP_FACTORY_RESET_ERASE_NVS
#include <zephyr/fs/nvs.h>
#include <zephyr/settings/settings.h>
#endif

namespace chip {
namespace DeviceLayer {

Expand Down Expand Up @@ -168,14 +173,30 @@ void ConfigurationManagerImpl::RunConfigUnitTest(void)
void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg)
{
ChipLogProgress(DeviceLayer, "Performing factory reset");

#ifdef CONFIG_CHIP_FACTORY_RESET_ERASE_NVS
void * storage = nullptr;
int status = settings_storage_get(&storage);

if (status == 0)
{
status = nvs_clear(static_cast<nvs_fs *>(storage));
}

if (status)
{
ChipLogError(DeviceLayer, "Factory reset 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());
}

#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
ThreadStackMgr().ErasePersistentInfo();
#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
ConnectivityMgr().ErasePersistentInfo();
#endif

PlatformMgr().Shutdown();
}
Expand Down

0 comments on commit 2749649

Please sign in to comment.