Best way to implement Reset Factory functionality?

Hi everyone,

We need to implement some kind of Reset Factory functionality on our Raspberry CM4 and we were wondering what would be the best way to implement such functionality.

We did see in the docs that:

a common implementation of “reset to factory defaults” is to purposely corrupt the application partition and reboot." https://hexdocs.pm/nerves_runtime/readme.html#filesystem-initialization

But it’s not clear how we can purposely corrupt the application partition since most of it is read-only.
Could we for instance change some key-values in Nerves.Runtime.KV to “indicate” the application partition would need to be rebuilt upon reboot?

Or maybe we could call fwup to reinstall its firmware version without having the img file?

What would be the best practice to implement a Reset Factory functionality?

Thanks in advance for any insights.
Best regards
Quentin

Hi Quentin,

As with everything, there are many ways of implementing factory reset.

First, I might have misunderstood part of your post, so let me write some background to make sure we’re on the same page. There are two main filesystems with Nerves devices. The first is the rootfs that contains Erlang and all of your compiled code. This is read-only. Upgrades alternate between A and B versions of it. The second is the application partition. This is always writable. It’s available under the path /data or /root. Nerves.Runtime.KV stores key-value pairs outside of either filesystem. This can be particularly convenient to bootloaders (but not on the RPi) and fwup. The Raspberry Pi’s also have a boot filesystem.

I recommend ONLY using Nerves.Runtime.KV for configuration that is set at manufacturing time. I generally avoid updating it. Here are reasons: 1. it’s small, 2. everything is stored as a string, 3. it’s hard to recover if it gets corrupted. Point 3 is fixable by enabling a redundant storage location, but that’s not enabled on the official RPi4 builds.

I recommend storing all user settings and data on /data or /root.

Back to implementing factory reset, my favorite way to implement it is to corrupt the application partition and reboot. The default behavior is to reformat the application partition on boot if it’s corrupt. The reason that I like it is that a fresh format gives me the comfort that there’s not some silent filesystem corruption that’s lurking. (I honestly don’t know how big of an issue this is with ext4 and f2fs, but I have deep scars from FAT32 filesystem corruption and assume the worst on devices that I can’t easily fix.) A second option is to rm -fr /data/*. Both of these methods only work if your “Factory Default” is a clean application data partition.

One note about corrupting the application partition so that it triggers a reformat, I’m thinking that Nerves should provide a function for doing this to make it easier. I added an issue to track it.

As a final note, some people have calibration or settings that they want to exist after a factory reset, and this data has been too large for Nerves.Runtime.KV. The solution has been to make a custom Nerves system that has a second application data partition.

If you don’t plan to run factory resets that often or if it’s only slightly harder to replace a MicroSD card, for example, then perhaps the rm -fr /data/* option and a reboot will suffice. You might also have an easy way to reinitialize a SQLite database or similar that’s equivalent.

Hope this helps.

Hi Frank,

Many thanks for your detailed response and insights.
I did a quick test and indeed using dd + reboot did the trick to corrupt & rebuild the app partition.

I also think it would be great to have a dedicated function for this.
I’ll follow-up on the issue you opened to see if i can provide some help on this front. I’d gladly help if i can.

Thanks again for everything.
Quentin