Chapter 54A: MTD / UBI for raw NAND¶
What: the MTD (Memory Technology Devices) subsystem and the UBI (Unsorted Block Images) layer that sits on top of it. MTD partitions and exposes raw NAND/NOR flash to the kernel. UBI handles wear-levelling, bad-block management, and exposes UBI volumes that look like static block devices. UBI: Unsorted Block Images, a flash-management layer over raw NAND that handles wear leveling and bad blocks. MTD: Memory Technology Device, Linux’s raw flash subsystem for eraseblock-based storage.
Why: Raw NAND is common in industrial embedded, cheaper per GB than eMMC, longer-lived if managed correctly. But NAND is not a block device. It has erase blocks (about 128 KB) and pages (about 2 KB). Bad blocks appear over the device’s lifetime. Erase cycles are limited. MTD/UBI is the kernel’s solution.
Focus: the three layers, MTD (NAND geometry), UBI (wear leveling + bad-block remapping), UBIFS (filesystem). Keep them separate in your head, each solves a different problem.
Tooling. This chapter uses
mtd-utils(flash_erase,nandwrite,flashcp,mtdinfo,ubinfo,ubinize,ubiformat).
Ubuntu-base (target):
apt install mtd-utilsBuildroot:
BR2_PACKAGE_MTD=yBuildroot: a configuration-driven build system that produces a complete root filesystem and related images.Full per-tool reference: Userspace tooling appendix. MCU bridge: Think of the rootfs as the firmware image’s file-backed runtime environment. On an MCU you link everything into flash. On Linux, programs and config live in this mounted tree. rootfs: root filesystem, the directory tree mounted at / that contains /bin, /etc, /dev, and libraries.
54A.1 Three layers¶
user-space (cp, vi, ...)
│
▼
┌─────────────────────────────┐
│ UBIFS or other UBI-aware │ ← filesystem layer
│ filesystem │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ UBI │ ← wear levelling, bad-block
│ /dev/ubi0_0, ubi0_1, ... │ remapping
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ MTD │ ← raw NAND access
│ /dev/mtd0, mtd1, ... │
└─────────────────────────────┘
│
▼
┌─────────────────────────────┐
│ NAND chip + GPMI controller │
└─────────────────────────────┘
You can use MTD without UBI for read-only partitions (kernel image). For writable storage, always use UBI.
54A.2 NAND on i.MX6ULL¶
i.MX6ULL has the GPMI (General Purpose Media Interface) NAND controller with BCH error correction. Connects to standard 8-bit NAND chips.
DT:
&gpmi {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpmi_nand>;
nand-on-flash-bbt;
fsl,no-blockmark-swap;
status = "okay";
partition@0 {
label = "u-boot";
reg = <0x0 0x400000>; /* 4 MB */
};
partition@1 {
label = "kernel";
reg = <0x400000 0x800000>; /* 8 MB */
};
partition@2 {
label = "rootfs";
reg = <0xc00000 0x0>; /* rest of NAND */
};
};
Each partition becomes /dev/mtdN (and a character-device /dev/mtdNchar).
54A.3 MTD operations¶
[root@pa-mini:~]# cat /proc/mtd
dev: size erasesize name
mtd0: 00400000 00020000 "u-boot"
mtd1: 00800000 00020000 "kernel"
mtd2: 0f400000 00020000 "rootfs"
[root@pa-mini:~]# flash_erase /dev/mtd1 0 0 # erase entire kernel partition
[root@pa-mini:~]# nandwrite -p /dev/mtd1 zImage # write kernel image
[root@pa-mini:~]# nanddump /dev/mtd1 > backup.bin # dump
mtd-utils (flash_erase, flashcp, nandwrite, nanddump, flash_eraseall) is the standard toolset.
54A.4 UBI on top¶
For the rootfs partition, layer UBI:
[root@pa-mini:~]# ubiformat /dev/mtd2 -O 2048 -s 2048 # format mtd2 for UBI
[root@pa-mini:~]# ubiattach -m 2 -d 0 # attach as ubi0
[root@pa-mini:~]# ubimkvol /dev/ubi0 -N root -m # max-size volume named "root"
[root@pa-mini:~]# ubimkvol /dev/ubi0 -N data -s 100MiB # 100 MB volume "data"
[root@pa-mini:~]# cat /proc/partitions
major minor #blocks name
31 0 4096 mtdblock0
31 1 8192 mtdblock1
31 2 249856 mtdblock2
...
UBI volumes appear as /dev/ubi0_0 (root) and /dev/ubi0_1 (data). To user-space they look like character devices. With a UBI-aware filesystem (UBIFS) on top, they look like filesystems.
[root@pa-mini:~]# mkfs.ubifs -m 2048 -e 126976 -c 1000 -o root.ubifs /path/to/staging
[root@pa-mini:~]# ubiupdatevol /dev/ubi0_0 root.ubifs
[root@pa-mini:~]# mount -t ubifs ubi0:root /mnt
The -m (min I/O size, equals NAND page size), -e (logical eraseblock size), and -c (max LEB count) come from ubinfo /dev/ubi0.
54A.5 Boot config¶
Kernel cmdline:
ubi.mtd=2 root=ubi0:root rootfstype=ubifs
This says: attach mtd2 as UBI, then mount the UBI volume named “root” as the rootfs.
U-Boot:
MCU bridge: Think of U-Boot like a much larger boot stub plus debug monitor: it initializes hardware, loads the next image, and gives you commands before Linux starts. U-Boot: the bootloader that initializes enough hardware to load and start the Linux kernel.
setenv bootargs 'console=ttymxc0,115200 ubi.mtd=2 root=ubi0:root rootfstype=ubifs rw'
nand read 80800000 kernel
bootz 80800000 - 81000000
54A.6 Wear levelling¶
NAND erase blocks survive ~10,000–100,000 erase cycles (chip-dependent). UBI tracks per-block erase counts and migrates rarely-erased blocks toward “hot” data, averaging wear across the whole device.
[root@pa-mini:~]# ubinfo -a /dev/ubi0
ubi0
Volumes count: 2
Logical eraseblock size: 126976 bytes, 124.0 KiB
Total amount of logical eraseblocks: 1888 (239708672 bytes, 228.6 MiB)
Amount of available logical eraseblocks: 0 (0 bytes)
Maximum count of volumes 128
Count of bad physical eraseblocks: 3
Count of reserved physical eraseblocks: 40
Current maximum erase counter value: 145
Minimum input/output unit size: 2048 bytes
Character device major/minor: 246:0
Present volumes: 0, 1
Bad blocks (3 here) are remapped to reserved blocks (40 set aside). Max erase counter is 145, far below the 10k+ chip limit, so the device is healthy.
54A.7 UBIFS, the filesystem¶
UBIFS is a journalling filesystem designed for UBI. Features:
Atomic operations (power-loss safe).
Compression (LZO or zstd), typically 1.5–2× compression of typical embedded filesystems.
Read/write performance ~2–3× ext4-on-eMMC for typical workloads (NAND fundamentals. Ext4 not designed for NAND).
When not to use:
Random small writes, UBIFS is bad at this.
Large databases, consider a separate ext4-on-eMMC slot if you have both.
54A.8 Lab¶
Storage safety: Before any command that names /dev/sdX, run lsblk -o NAME,SIZE,MODEL,TRAN,TYPE,MOUNTPOINTS. Verify the removable card by size and model, unmount its partitions, and stop if the path is not the target card. Writing the wrong /dev node can destroy the host disk.
Identify NAND partitions. Boot a kernel with GPMI enabled and partitions in DT.
cat /proc/mtd.Format and use UBI.
ubiformat,ubiattach,ubimkvol. Confirmubi0and volumes appear.Make a UBIFS rootfs. From your existing Buildroot output,
mkfs.ubifs. Flash to NAND.Boot from NAND. Configure U-Boot to load kernel + dtb from NAND, set
bootargsfor ubi root.Wear test. Write a script that writes a 1 MB file in a loop, deleting and recreating. Run for an hour. Check max erase counter via
ubinfo. Verify wear levelling spreads writes.Recover from bad block. Use
nandtestto mark a block bad. Reformat UBI. Observe it being remapped.
54A.9 Pitfalls¶
Wrong page/OOB size.
ubiformatdefaults may not match your chip. Specify-O 2048 -e 131072explicitly to matchcat /proc/mtdoutput.Mounting UBIFS over ext4. “Why does my UBIFS feel slow?”, UBIFS atop a block layer that’s atop NAND is double-translation. Use UBIFS directly on a UBI volume.
No bbt (Bad Block Table) reservation. Pre-existing factory bad blocks become “good” in UBI’s view, then fail unpredictably. Always
nand-on-flash-bbtorfsl,use-bbtin DT.Erasing the wrong partition.
flash_erase /dev/mtd0erases U-Boot. Always confirm partition number. Back up before erase.Power-loss during write. UBIFS handles this well. Ext4-on-mtdblock does not. Use UBIFS for writable partitions.
ubi.mtd=mismatch with DT partition number. If you add/remove partitions in DT, the numbering shifts. Kernel cmdline gets stale. Lock both at the same time.
54A.10 Going deeper¶
Documentation/filesystems/ubifs.rst: UBIFS documentation.Documentation/ABI/stable/sysfs-bus-ubi: UBI sysfs ABI.
ABI: Application Binary Interface: the calling convention, register use, binary format, and library contract that let separately built code run together. sysfs: a kernel-generated filesystem under /sys that exposes devices, drivers, and attributes.
drivers/mtd/nand/raw/gpmi-nand/: i.MX GPMI NAND driver.drivers/mtd/ubi/: UBI implementation.mtd-utilssource: user-space tools.http://linux-mtd.infradead.org/: the canonical MTD/UBI website.
Next chapter: Chapter 54B: V4L2 + GStreamer for the CSI camera. Capture video frames from the i.MX6ULL CSI parallel camera interface and pipe them through GStreamer for processing or display.