OpenWrt firmware image for Mikrotik NAND-based devices

Since OpenWrt 21.02 the OpenWrt developers decided to not build firmware images for MikroTik NAND-based devices by default. Therefore you do not find the firmware for, e.g.  RB921GS-5HPacD-15S (mANTBox 15s), on https://downloads.openwrt.org/releases/21.02.0/targets/

The reason for that decision is MikroTiks usage of YAFFS. YAFFS is not supported by linux kernel. Read also the form thread for Mikrotik mANTBox 15s r3.

Disabling NAND-based build was implemented in commit 9d96b6fb720d9 There is mentioned: “we disable building these images to prevent unknowing users from risking their devices.”

Q: What does “risking their devices” mean? A: When OpenWrt firmware is flashed several partitions are created and written for flash. The problem is that kernel partition is written to flash without any method of bad-block management. Therefore, if the flash has any faulty sector at the position where kernel partition is written this will not reside in any error. On the next boot you will notice that booting will not be possible (or other side affects).

Q: What does “prevent unknowing users” mean? A: If you read the above you are a “knowing user” and you know the risk. But what can we do to prevent this problem? Continue to read…

Q: What is the probability of having this problem? A: The probability is very small. To destroy a cell in flash you have to write in it very often or it is already defect from the beginning.

Q: How can we recover when device does not boot after flashing OpenWrt? A: see debrick / flash original firmware

Q: How was this firmware build? A: Example for OpenWrt 21.02.3

# enter the release you want to build
RELEASE="21.02.3"

git clone https://github.com/openwrt/openwrt.git
cd openwrt
git checkout v$RELEASE
wget -O .config https://downloads.openwrt.org/releases/$RELEASE/targets/ath79/mikrotik/config.buildinfo
  
# there is a patch which deactivates builds for mikrotik devices with nand flash
git show 9d96b6fb720d9cecc7bd50b4f16dabe1b337f9f2 > mikrotik-nand-build.patch
# we will revert this patch
patch -p1 -R < mikrotik-nand-build.patch

make defconfig
make

Q: What could be a solution that OpenWrt developers will enable NAND-based images again? A: …..

Q: How can we be sure that we doe not have this problem (defect sector)? A: mANTBox had two different flashes: * NOR, connected via SPI * NAND

root@openwrt:~# for m in /dev/mtd?; do mtdinfo $m --map | grep -E '^[^ ]';
echo; done
mtd0
Name:                           routerboot
Type:                           nor
Eraseblock size:                4096 bytes, 4.0 KiB
Amount of eraseblocks:          12 (49152 bytes, 48.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:0
Bad blocks are allowed:         false
Device is writable:             false
Eraseblock map:

mtd1
Name:                           hard_config
Type:                           nor
Eraseblock size:                4096 bytes, 4.0 KiB
Amount of eraseblocks:          1 (4096 bytes, 4.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:2
Bad blocks are allowed:         false
Device is writable:             false
Eraseblock map:

mtd2
Name:                           bios
Type:                           nor
Eraseblock size:                4096 bytes, 4.0 KiB
Amount of eraseblocks:          1 (4096 bytes, 4.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:4
Bad blocks are allowed:         false
Device is writable:             false
Eraseblock map:

mtd3
Name:                           soft_config
Type:                           nor
Eraseblock size:                4096 bytes, 4.0 KiB
Amount of eraseblocks:          1 (4096 bytes, 4.0 KiB)
Minimum input/output unit size: 1 byte
Sub-page size:                  1 byte
Character device major/minor:   90:6
Bad blocks are allowed:         false
Device is writable:             true
Eraseblock map:

mtd4
Name:                           booter
Type:                           nand
Eraseblock size:                131072 bytes, 128.0 KiB
Amount of eraseblocks:          2 (262144 bytes, 256.0 KiB)
Minimum input/output unit size: 2048 bytes
Sub-page size:                  2048 bytes
OOB size:                       64 bytes
Character device major/minor:   90:8
Bad blocks are allowed:         true
Device is writable:             false
Eraseblock map:

mtd5
Name:                           kernel
Type:                           nand
Eraseblock size:                131072 bytes, 128.0 KiB
Amount of eraseblocks:          30 (3932160 bytes, 3.7 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size:                  2048 bytes
OOB size:                       64 bytes
Character device major/minor:   90:10
Bad blocks are allowed:         true
Device is writable:             true
Eraseblock map:

mtd6
Name:                           ubi
Type:                           nand
Eraseblock size:                131072 bytes, 128.0 KiB
Amount of eraseblocks:          992 (130023424 bytes, 124.0 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size:                  2048 bytes
OOB size:                       64 bytes
Character device major/minor:   90:12
Bad blocks are allowed:         true
Device is writable:             true
Eraseblock map:

root@openwrt:~# ll /sys/block/mtdblock* | cut -d/ -f2-
sys/block/mtdblock0 ->
../devices/platform/ath79-spi/spi_master/spi0/spi0.0/mtd/mtd0/mtdblock0/
sys/block/mtdblock1 ->
../devices/platform/ath79-spi/spi_master/spi0/spi0.0/mtd/mtd1/mtdblock1/
sys/block/mtdblock2 ->
../devices/platform/ath79-spi/spi_master/spi0/spi0.0/mtd/mtd2/mtdblock2/
sys/block/mtdblock3 ->
../devices/platform/ath79-spi/spi_master/spi0/spi0.0/mtd/mtd3/mtdblock3/
sys/block/mtdblock4 -> ../devices/virtual/mtd/mtd4/mtdblock4/
sys/block/mtdblock5 -> ../devices/virtual/mtd/mtd5/mtdblock5/
sys/block/mtdblock6 -> ../devices/virtual/mtd/mtd6/mtdblock6/

Kernel parition is in MTD5. We can check for defect sectors if we read the partition more than one time and compare the MD5 hash of the result. The result should be constant.

root@openwrt:~# for i in $(seq 1 10); do dd if=/dev/mtd5ro bs=2k 2>/dev/null |
md5sum; done | sort | uniq -c
     10 19278469ad40fbdc37bfb93508cf1e07  -