Ubootenv is preserved in backup / BPI-R3

Dear OpenWRT community,

i am fairly new to the topic, got a BPI-R3 a week ago and ran into some problems regarding the ubootenv config when restoring backup archives. Maybe it is more accurate to say i became victim of my own lack of knowledge.
Anyway, i wanted to share this here in case someone else is looking for advice in a similar situation and also i think i may have discovered a bug but that is certainly for someone with more knowledge of the system to say.

My journey started when trying to figure out if its best to use NOR, NAND or the eMMC to install OpenWRT on. I ended up choosing NAND to boot (and using eMMC for some stuff as well). To do that, i was following this wiki article of the BPI-R3. Booted from sdcard, installed on NAND using the command specified in the wiki (fw_setenv bootcmd "env default bootcmd ; saveenv ; run ubi_init ; bootmenu 0") and booted from NAND. So far, so good.

Next i wanted to install on NOR too using the command specified in the article:
fw_setenv bootcmd "env default bootcmd ; saveenv ; run nor_init ; bootmenu 0"
This time i received the following error:

Cannot open /dev/mmcblk0p2: No such file or directory

A fw_printenv returned:

Warning: Bad CRC, using default environment

Also, same result when trying to install to eMMC.

At this point, the following observation may be helpful:

From my current understanding installing on NOR when booted from NAND is not possible. I has to be done from SDcard or eMMC when the boot selector switches are in the according position. The reason why i believe this to be the case is because SPI only shows NAND. From that i conclude that only one is connected to the bus at a time depending on the position of the hardware switch. It is not explicitly stated in the BPI-R3 documentation though.

Back to the fw_printenv/_setenv error. I found that /etc/fw_env.config referenced /dev/mmcblk0p2 as containing the bootenv partition, which did not exist. The /dev/mmcblk0p2 is the bootenv partition on the sd card (and maybe similar on emmc). For NAND the config file has to look like:

/dev/ubi0_4 0 0x1f000 0x1f000 1
/dev/ubi0_5 0 0x1f000 0x1f000 1

Please be aware that according to my understanding, it is not sufficient to edit /etc/fw_env.config because it is generated using /etc/config/ubootenv. Again, this is based on the understanding i got through reading and trial and error during the last couple of days, someone correct me please if i am wrong.

So how did i manage to break it like that you may ask? Well, before deciding to use NAND storage, i was starting the device from an sd card and also ended up doing a bit of configuration while playing around and making up my mind of how i want to use it. So after installing on NAND, i recovered a backup which i made via luci while the device was booted from sd card. The backup archive contains /etc/config/ubootenv, so the recovery ended up overwriting the presumable okay file. This is where i think there could be a bug. Since ubootenv is dependent on the device and even on what storage one may use, placing ubootenv into the backup archive makes the backup device and configuration specific.

So now to the details on how i fixed my specific issue which may help others to fix theirs:

  1. Find out where you are booting from. On a fresh install most likely you can run mount and see where your /overlay is located. In my case its /dev/ubi0_6, meaning the 6th partition of ubi0. This assumes your overlay is located where you are booting from, i guess this is most common. It could be different though.
  2. Assuming the bootenv is where you are booting from, go through the neighboring partitions (in this case /dev/ubi0_X) and see what partition is named ubootenv or ubootenv2 (which is the backup of the first). In case of ubifs you can do that with ubinfo /dev/ubi0_X.
  3. Now you need to find out the size of the env storage, the offset and the blocksize. Investigate the uboot package in the Github Repository of OpenWRT to find that out. You are looking for a platform specific file, so navigate through the tree to find yours. For a BPI-R3, this one is the correct one.
  4. Now read the file to find what you are looking for. The parameters of ubootenv_add_uci_config show you the offset, size of the env storage, and the block size. In case of the above linked for the BPI-R3, you see that it considers three cases: eMMC, NOR and default. The latter is also the case if NAND is used. You can do trial and error by modifying /etc/fw_env.config and running fw_printenv to check. It won't break anything.
  5. With the results of Steps 2 and 4 you can update your fw_env.config and i guess more importantly your config/ubootenv.

Alternatively and maybe easier: Fresh install on the storage you want to use and look at /etc/config/ubootenv of the fresh installation.

Another thing i want to add: You may call me captain obvious now, but RTFM. Seriously. My mistake was rooted in me just starting to do something without the proper knowledge of the system. Only when encountering problems i started reading the documentation, learning about UCI, what mtd and ubi are and how they relate to each other. The OpenWRT user guide is a very good starting place. Once you have some basic knowledge you can also use ChatGPT to let you explain something. Beware that it is a notorious and very confident liar but with enough background knowledge and experience you find it easy to know how accurate the information it spits out actually is.
And, for more deep dive, just look at your system. For example, use cat to navigate through and look into files under /sys/* or /proc/*. (e.g. cat /sys/class/ubi/ubi0/mtd_num tells you what mtd the ubi0 is located at). I had actually a lot of fun doing that and the gained knowledge will help me in the future.

I hope some of this is useful to someone in the future. And to the people with more knowledge than me, please correct me if i wrote nonsense. There is already enough misinformation out there.