Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
docs:techref:flash.layout [2023/10/18 00:37] – [Partitioning of NAND flash-based devices] add kernel volume name lanchondocs:techref:flash.layout [2023/10/18 09:06] (current) – [NOR flash vs NAND flash] lanchon
Line 30: Line 30:
   * 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 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 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 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 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 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.
Line 52: Line 52:
 ^ Layer1 |  bootloader \\ partition(s)  |  optional \\ SoC \\ specific \\ partition(s)  |  firmware partition  |||  optional \\ SoC \\ specific \\ partition(s)  | ^ Layer1 |  bootloader \\ partition(s)  |  optional \\ SoC \\ specific \\ partition(s)  |  firmware partition  |||  optional \\ SoC \\ specific \\ partition(s)  |
 ^ Layer2 |:::|::: OpenWrt firmware image  ||  //(space available for storage)//  |:::| ^ Layer2 |:::|::: OpenWrt firmware image  ||  //(space available for storage)//  |:::|
-^ Layer3 |:::|::: Linux kernel  |  **''rootfs''** \\ mounted: "''/rom''", [[docs:techref:filesystems#SquashFS|SquashFS]] \\ size depends on selected packages  |  **''rootfs_data''** \\ mounted: "''/overlay''", [[docs:techref:filesystems#JFFS2|JFFS2]] \\ all remaining free space  |:::|+^ Layer3 |:::|::: Linux kernel \\ (raw image)   **''rootfs''** \\ mounted: "''/rom''", [[docs:techref:filesystems#SquashFS|SquashFS]] \\ size depends on selected packages  |  **''rootfs_data''** \\ mounted: "''/overlay''", [[docs:techref:filesystems#JFFS2|JFFS2]] \\ all remaining free space  |:::|
 ^ Layer4 |:::|:::|::: mounted: "''/''", [[docs:techref:filesystems#overlayfs|OverlayFS]] \\ stacking ''/overlay'' on top of ''/rom''  ||:::| ^ Layer4 |:::|:::|::: mounted: "''/''", [[docs:techref:filesystems#overlayfs|OverlayFS]] \\ stacking ''/overlay'' on top of ''/rom''  ||:::|
  
Line 134: Line 134:
 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: 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  ||||||| ^ Layer0 |  raw flash  |||||||
-^ Layer1 |  bootloader \\ partition(s)  |  optional \\ SoC \\ specific \\ partition(s)  |  Linux kernel  |  optional \\ SoC \\ specific \\ partition(s)  |  UBI partition  ||  optional \\ SoC \\ specific \\ partition(s)  |+^ Layer1 |  bootloader \\ partition(s)  |  optional \\ SoC \\ specific \\ partition(s)  |  Linux kernel \\ (raw image)   optional \\ SoC \\ specific \\ partition(s)  |  UBI partition  ||  optional \\ SoC \\ specific \\ partition(s)  |
 ^ Layer2 |:::|:::|:::|::: **''rootfs''** \\ mounted: "''/rom''", [[docs:techref:filesystems#SquashFS|SquashFS]] \\ size depends on selected packages  |  **''rootfs_data''** \\ mounted: "''/overlay''", [[docs:techref:filesystems#UBIFS|UBIFS]] \\ all remaining free space  |:::| ^ Layer2 |:::|:::|:::|::: **''rootfs''** \\ mounted: "''/rom''", [[docs:techref:filesystems#SquashFS|SquashFS]] \\ size depends on selected packages  |  **''rootfs_data''** \\ mounted: "''/overlay''", [[docs:techref:filesystems#UBIFS|UBIFS]] \\ all remaining free space  |:::|
 ^ Layer3 |:::|:::|:::|::: mounted: "''/''", [[docs:techref:filesystems#overlayfs|OverlayFS]] \\ stacking ''/overlay'' on top of ''/rom''  ||:::| ^ Layer3 |:::|:::|:::|::: mounted: "''/''", [[docs:techref:filesystems#overlayfs|OverlayFS]] \\ stacking ''/overlay'' on top of ''/rom''  ||:::|
Line 141: Line 141:
 ^ Layer0 |  raw flash  |||||| ^ Layer0 |  raw flash  ||||||
 ^ Layer1 |  bootloader \\ partition(s)  |  optional \\ SoC \\ specific \\ partition(s)  |  UBI partition  |||  optional \\ SoC \\ specific \\ partition(s)  | ^ Layer1 |  bootloader \\ partition(s)  |  optional \\ SoC \\ specific \\ partition(s)  |  UBI partition  |||  optional \\ SoC \\ specific \\ partition(s)  |
-^ Layer2 |:::|::: **''kernel''** \\ Linux kernel  |  **''rootfs''** \\ mounted: "''/rom''", [[docs:techref:filesystems#SquashFS|SquashFS]] \\ size depends on selected packages  |  **''rootfs_data''** \\ mounted: "''/overlay''", [[docs:techref:filesystems#UBIFS|UBIFS]] \\ all remaining free space  |:::|+^ Layer2 |:::|::: **''kernel''** \\ Linux kernel \\ (raw image)   **''rootfs''** \\ mounted: "''/rom''", [[docs:techref:filesystems#SquashFS|SquashFS]] \\ size depends on selected packages  |  **''rootfs_data''** \\ mounted: "''/overlay''", [[docs:techref:filesystems#UBIFS|UBIFS]] \\ all remaining free space  |:::|
 ^ Layer3 |:::|:::|::: mounted: "''/''", [[docs:techref:filesystems#overlayfs|OverlayFS]] \\ stacking ''/overlay'' on top of ''/rom''  ||:::| ^ Layer3 |:::|:::|::: mounted: "''/''", [[docs:techref:filesystems#overlayfs|OverlayFS]] \\ stacking ''/overlay'' on top of ''/rom''  ||:::|
  
Line 147: Line 147:
  
  
-==== Reserving UBI space of user-defined UBI volumes ====+==== Reserving UBI partition space for user-defined UBI volumes ====
  
 For [[:docs:techref:flash.layout#sysupgrade_and_rootfs_data|historical reasons]] concerning NOR flash-based devices, sysupgrade works in an atypical fashion. During upgrades OpenWrt reads selected content from **''rootfs_data''** that it wants surviving the upgrade into RAM, creates an all-new **''rootfs_data''**, and writes back the selected content to it from RAM. For [[:docs:techref:flash.layout#sysupgrade_and_rootfs_data|historical reasons]] concerning NOR flash-based devices, sysupgrade works in an atypical fashion. During upgrades OpenWrt reads selected content from **''rootfs_data''** that it wants surviving the upgrade into RAM, creates an all-new **''rootfs_data''**, and writes back the selected content to it from RAM.
Line 159: Line 159:
 The relevant bootloader variable can be read with this command: The relevant bootloader variable can be read with this command:
  
-**''fw_printenv -n rootfs_data_max''**+<code> 
 +fw_printenv -n rootfs_data_max 
 +</code>
  
 Set with: Set with:
  
-**''fw_setenv rootfs_data_max <VALUE>''**+<code> 
 +fw_setenv rootfs_data_max <VALUE> 
 +</code>
  
 And cleared with: And cleared with:
  
-**''fw_setenv rootfs_data_max''**+<code> 
 +fw_setenv rootfs_data_max 
 +</code>
  
 Note that sysupgrade will fail if there is not enough space in the UBI partition to create **''rootfs_data''** of the specified size, and the contents of **''rootfs_data''** will then be lost. (The **''rootfs_data_max''** variable should have better been named **''rootfs_data_size''**.) The user must make sure that enough free space exists in UBI to accommodate growth of future OpenWrt images and/or custom OpenWrt images with more packages. Note that sysupgrade will fail if there is not enough space in the UBI partition to create **''rootfs_data''** of the specified size, and the contents of **''rootfs_data''** will then be lost. (The **''rootfs_data_max''** variable should have better been named **''rootfs_data_size''**.) The user must make sure that enough free space exists in UBI to accommodate growth of future OpenWrt images and/or custom OpenWrt images with more packages.
  
-For example, on an Askey RT4230W REV6 router with 512 MiB flash, the **''rootfs_data''** volume is normally sized at 373 MiB (the remaining flash space being used for bootloaders, SoC-specific partitions, kernel, rootfs, and recovery). Given that this volume is routinely wiped by sysupgrade, storing any remotely valuable files there would be ill-advised. On that router one might choose to limit **''rootfs_data''** to generous 128 MiB, and create an 192 MiB **''extra''** UBIFS volume for persistent storage that survives sysupgrade, while still be allowing 50+ MiB for future growth of OpenWrt images.+==== Example: Creating UBI volume for persistent storage across sysupgrades ====
  
 +In an Askey RT4230W REV6 router with 512 MiB flash, the **''rootfs_data''** volume is normally sized at around 370 MiB (the remaining flash space being used for bootloaders, SoC-specific partitions, kernel, rootfs, and recovery). You can check this using:
 +
 +<code>
 +root@router:~# ubinfo -d 0 -N rootfs_data
 +Volume ID:   2 (on ubi0)
 +Type:        dynamic
 +Alignment:   1
 +Size:        3086 LEBs (391847936 bytes, 373.6 MiB)
 +State:       OK
 +Name:        rootfs_data
 +Character device major/minor: 246:3
 +</code>
 +
 +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 **''rootfs_data''** to a generous 128 MiB, and create a new 192 MiB UBIFS volume for persistent storage, while still reserving 50+ MiB as free space to accommodate future growth of OpenWrt images. Let's do just that and name the new volume **''extra''**.
 +
 +First you need to limit **''rootfs_data''** to 128 MiB for all following sysupgrades:
 +
 +<code>
 +root@router:~# fw_setenv rootfs_data_max 0x8000000
 +</code>
 +
 +Next do a sysupgarde (even if no upgrade is needed) to resize **''rootfs_data''**. After that, verify its new size:
 +
 +<code>
 +root@router:~# ubinfo -d 0 -N rootfs_data
 +Volume ID:   2 (on ubi0)
 +Type:        dynamic
 +Alignment:   1
 +Size:        1058 LEBs (134340608 bytes, 128.1 MiB)
 +State:       OK
 +Name:        rootfs_data
 +Character device major/minor: 246:3
 +</code>
 +
 +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 ''**uvol**'' (**System > Software**). You might also want to install your favorite text editor now (''**nano-full**'' is a good option).
 +
 +Now check the installation (sizes are in bytes):
 +
 +<code>
 +root@router:~# uvol list
 +root@router:~# uvol total
 +422576128
 +root@router:~# uvol free
 +253317120
 +</code>
 +
 +Create and enable the ''**extra**'' volume using ''**uvol**'':
 +
 +<code>
 +root@router:~# uvol create extra $(( 192*1024*1024 )) rw
 +Volume ID 4, size 1586 LEBs (201383936 bytes, 192.0 MiB), LEB size 126976 bytes (124.0 KiB), dynamic, name "uvol-wp-extra", alignment 1
 +root@router:~# uvol up extra
 +root@router:~# uvol list
 +extra rw 201383936
 +root@router:~# mount | grep extra
 +/dev/ubi0_4 on /tmp/run/uvol/extra type ubifs (rw,relatime,assert=read-only,ubi=0,vol=4)
 +</code>
 +
 +You do not like the default mount path (''**/tmp/run/uvol/extra**''), so you change it to ''**/extra**'' using you text editor:
 +
 +<code>
 +root@router:~# nano /etc/config/fstab 
 +</code>
 +
 +Finally reboot and check that your new volume is mounted where you want it:
 +
 +<code>
 +root@router:~# mount | grep extra
 +/dev/ubi0_4 on /extra type ubifs (rw,relatime,assert=read-only,ubi=0,vol=4)
 +</code>
  
 ===== MTD (Memory Technology Device) and MTDSPLIT ===== ===== MTD (Memory Technology Device) and MTDSPLIT =====
  • Last modified: 2023/10/18 00:37
  • by lanchon