Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| docs:techref:flash.layout [2023/03/09 14:32] – [Explanations] Fix typoes brlin | docs:techref:flash.layout [2023/10/18 09:06] (current) – [NOR flash vs NAND flash] lanchon | ||
|---|---|---|---|
| Line 21: | Line 21: | ||
| Additionally we at OpenWrt distinguish between the two basic types of flash memory: [[wp> | Additionally we at OpenWrt distinguish between the two basic types of flash memory: [[wp> | ||
| - | "Raw NOR flash" in typical routers is generally small (4 MiB – 16 MiB) and __error-free__, i.e. there cannot be bad erase blocks. Because raw NOR flash is error-free, the installed file system(s) do not need to take bad erase blocks into account, and neither SquashFS nor JFFS2 do! The combination of OverlayFS with SquashFS and JFFS2 has been the default OpenWrt setup since the beginning, and it works flawlessly on "raw NOR flash" | + | "Raw NOR flash" in typical routers is generally small (4 MiB – 16 MiB) and __error-free__: all data blocks |
| - | "Raw NAND flash" in typical routers is generally larger (32 MiB – 256 MiB) and __not error-free__, i.e. it may contain | + | "Raw NAND flash" in typical routers is generally |
| - | - the manufacturer of the " | + | Bad blocks in NAND flash and handled in various ways: |
| - | * namely the one(s) which the bootloader is to be written to | + | |
| - | * but also the ones which the Linux kernel | + | |
| - | - the [[docs:guide-user: | + | |
| - | - OpenWrt would replace JFFS2 with [[docs: | + | |
| - | | {{: | + | * The NAND flash manufacturer guarantees that certain very small areas of the flash are defect-free. The use of such areas is up to the system designer. Some SoCs may store the first stage bootloader there (but since newer SoCs tend to support chain-of-trust booting, they typically store the first stage bootloader on-chip). |
| + | * Some partitions are used as large files that can only be read or written completely and in one go. This is the case of raw bootloaders and kernels in MTD partitions. For these partitions, bad blocks are simply skipped during both reads and writes. Because new defects almost exclusively develop during erase and writes, once written these partitions are mostly trusted to be readable forever. (But newer devices tend to duplicate these partitions to minimize failures.) | ||
| + | * Some partitions are used as large files that can only be written completely and in one go, but can be read in a random access fashion. This is the case of raw read-only file systems (such as squashfs) in MTD partitions. For these partitions, bad blocks are simply skipped during writes, and a kernel driver is used to read them. The driver reads the complete partition during setup skipping bad blocks, and builds a logical-block-to-flash-block table in RAM to be able to later access the partition random-access. | ||
| + | * Some large partitions are used as containers for other compartmentalized data. Note that the amount of bad blocks in a certain partition is a-priory unknown, and thus a raw partition size cannot be taken as the its usable size. For smaller partitions this effect is amplified: although there is a manufacturer-defined limit on the number of bad blocks in a flash, nothing precludes all bad blocks from residing in the same partition. Thus, for guaranteed operation, a system designer should allow //in each and every partition// the maximum number of bad blocks specified for the complete flash. (In practice though, this is almost never done.) Also note that the previous kinds of defect handling do not spread wear produced by erase/write cycles across the whole flash, and thus in general reduce the lifespan of the device. These problems are both solved by UBI. Ideally a single very large UBI partition is created that entirely manages flash defects and wear-leveling for contained volumes, and inside it different UBI volumes are created: | ||
| + | * Some UBI volumes are used as large files that can only be read or written completely and in one go. This is the case of kernels in UBI partitions. | ||
| + | * Some UBI volumes are used as large files that can only be written completely and in one go, but can be read in a random access fashion. This is the case of read-only file systems (such as squashfs) in UBI partitions. For these volumes, an ubiblock kernel device is used to read them: the device emulates a read-only block device and maintains a logical-block-to-flash-block table in RAM to be able to access the volume random-access. | ||
| + | * Some UBI volumes are used as read-write filesystems. Only the UBIFS filesystem is used for this. (It would be possible to emulate read-write block devices on top of UBI and use regular filesystems on top of that, but such setups would underperfom compared to UBIFS, and it seems that the necessary UBI block emulation driver has not yet been implemented, | ||
| + | |||
| + | Note that because of these factors, the OpenWrt [[docs: | ||
| Line 40: | Line 44: | ||
| To be noted that it is **NOT RIGHT** to estimate the life of a NAND flash in embedded devices using the same method for SSD! | To be noted that it is **NOT RIGHT** to estimate the life of a NAND flash in embedded devices using the same method for SSD! | ||
| - | ===== Partitioning of the Flash ===== | + | ===== Partitioning of NOR flash-based devices |
| - | Almost all embedded | + | |
| + | On these systems, the storage is presented by the kernel as an MTD device, and it is divided into MTD partitions. The device | ||
| The generic flash layout is: | The generic flash layout is: | ||
| ^ Layer0 | raw flash |||||| | ^ Layer0 | raw flash |||||| | ||
| - | ^ Layer1 | bootloader \\ partition(s) | + | ^ Layer1 | bootloader \\ partition(s) |
| - | ^ Layer2 |::: | + | ^ Layer2 |::: |
| - | ^ Layer3 |:::|:::|:::| **'' | + | ^ Layer3 |::: |
| + | ^ Layer4 |::: | ||
| - | Many newer devices share this scheme, but the flash layout can differ between the devices! Mostly minor details slightly differ concerning U-Boot and SoC specific firmware images. Please see the wiki pages for each SoC and devices for information about a particular layout. In case the flash layout differs for your device please update the wiki pages.\\ | + | Many NOR devices share this scheme, but the flash layout can differ between the devices. Please see the wiki pages for each SoC and devices for information about a particular layout. In case the flash layout differs for your device please update the wiki pages. |
| - | Here are some examples how it looks on actual devices: | + | |
| - | ==== Example flash partitioning ==== | + | |
| + | ==== Sysupgrade and '' | ||
| + | |||
| + | To better use the minimal storage on devices available when OpenWrt was originally being developed, the **'' | ||
| + | |||
| + | To handle this situation, sysupgrade works in an atypical fashion. During an upgrade OpenWrt reads selected content from **'' | ||
| + | |||
| + | Because of this, a failed sysupgrade might not only brick the device, it might also cause the contents of **'' | ||
| + | |||
| + | Note: Arbitrary files you may choose to store in **'' | ||
| + | |||
| + | ==== Example | ||
| [[docs: | [[docs: | ||
| Line 112: | Line 128: | ||
| - | ===== Partitioning of UBIFS-Images | + | ===== Partitioning of NAND flash-based devices |
| - | UBIFS-Images are suitable for devices with //"raw NAND flash memory"// | + | |
| - | TODO | + | On these systems, the storage is presented by the kernel as an MTD device, and it is divided into MTD partitions. The device is not partitioned in the traditional way, where you store information about partitions in a [[wp> |
| + | |||
| + | Some NAND devices contain bootloaders that do not understand UBI partitions and thus cannot boot kernels contained in UBI volumes. The generic flash layout for these devices is: | ||
| + | ^ Layer0 | raw flash ||||||| | ||
| + | ^ Layer1 | bootloader \\ partition(s) | ||
| + | ^ Layer2 |::: | ||
| + | ^ Layer3 |::: | ||
| + | |||
| + | The generic flash layout for NAND devices that can boot kernels contained in UBI volumes is: | ||
| + | ^ Layer0 | raw flash |||||| | ||
| + | ^ Layer1 | bootloader \\ partition(s) | ||
| + | ^ Layer2 |::: | ||
| + | ^ Layer3 |::: | ||
| + | |||
| + | Many NAND devices share this scheme, but the flash layout can differ between the devices. Please see the wiki pages for each SoC and devices for information about a particular layout. In case the flash layout differs for your device please update the wiki pages. | ||
| + | |||
| + | |||
| + | ==== Reserving UBI partition space for user-defined UBI volumes ==== | ||
| + | |||
| + | For [[: | ||
| + | |||
| + | On NAND devices using UBI, sysupgrade partially reads the **'' | ||
| + | |||
| + | While this setup worked well for old space-limited NOR devices, it may not be optimal for today' | ||
| + | |||
| + | Fortunately the default behavior of sysupgrade on NAND devices using UBI can be modified: instead of recreating the **'' | ||
| + | |||
| + | The relevant bootloader variable can be read with this command: | ||
| + | |||
| + | < | ||
| + | fw_printenv -n rootfs_data_max | ||
| + | </ | ||
| + | |||
| + | Set with: | ||
| + | |||
| + | < | ||
| + | fw_setenv rootfs_data_max < | ||
| + | </ | ||
| + | |||
| + | And cleared with: | ||
| + | |||
| + | < | ||
| + | fw_setenv rootfs_data_max | ||
| + | </ | ||
| + | |||
| + | Note that sysupgrade will fail if there is not enough space in the UBI partition to create **'' | ||
| + | |||
| + | ==== Example: Creating a UBI volume for persistent storage across sysupgrades ==== | ||
| + | |||
| + | In an Askey RT4230W REV6 router with 512 MiB flash, the **'' | ||
| + | |||
| + | < | ||
| + | root@router: | ||
| + | Volume ID: 2 (on ubi0) | ||
| + | Type: dynamic | ||
| + | Alignment: | ||
| + | Size: 3086 LEBs (391847936 bytes, 373.6 MiB) | ||
| + | State: | ||
| + | Name: rootfs_data | ||
| + | Character device major/ | ||
| + | </ | ||
| + | |||
| + | Given that this volume is routinely wiped by sysupgrade, storing any remotely valuable files here would be ill-advised. For this router you might choose to limit **'' | ||
| + | |||
| + | First you need to limit **'' | ||
| + | |||
| + | < | ||
| + | root@router: | ||
| + | </ | ||
| + | |||
| + | Next do a sysupgarde (even if no upgrade is needed) to resize **'' | ||
| + | |||
| + | < | ||
| + | root@router: | ||
| + | Volume ID: 2 (on ubi0) | ||
| + | Type: dynamic | ||
| + | Alignment: | ||
| + | Size: 1058 LEBs (134340608 bytes, 128.1 MiB) | ||
| + | State: | ||
| + | Name: rootfs_data | ||
| + | Character device major/ | ||
| + | </ | ||
| + | |||
| + | You just freed 240+ MiB in the UBI partition. Next, you could manually create, format, and mount a new UBIFS volume. But OpenWrt has a tool to automate this, so let's use it. | ||
| + | |||
| + | Connect the router to the internet if necessary, and use Luci to install package '' | ||
| + | |||
| + | Now check the installation (sizes are in bytes): | ||
| + | |||
| + | < | ||
| + | root@router: | ||
| + | root@router: | ||
| + | 422576128 | ||
| + | root@router: | ||
| + | 253317120 | ||
| + | </ | ||
| + | |||
| + | Create and enable the '' | ||
| + | |||
| + | < | ||
| + | root@router: | ||
| + | Volume ID 4, size 1586 LEBs (201383936 bytes, 192.0 MiB), LEB size 126976 bytes (124.0 KiB), dynamic, name " | ||
| + | root@router: | ||
| + | root@router: | ||
| + | extra rw 201383936 | ||
| + | root@router: | ||
| + | /dev/ubi0_4 on / | ||
| + | </ | ||
| + | |||
| + | You do not like the default mount path ('' | ||
| + | |||
| + | < | ||
| + | root@router: | ||
| + | </ | ||
| + | |||
| + | Finally reboot and check that your new volume is mounted where you want it: | ||
| + | |||
| + | < | ||
| + | root@router: | ||
| + | /dev/ubi0_4 on /extra type ubifs (rw, | ||
| + | </ | ||
| ===== MTD (Memory Technology Device) and MTDSPLIT ===== | ===== MTD (Memory Technology Device) and MTDSPLIT ===== | ||