How to Use UBIFS

Warnings

Be sure to use the UBI tools (such as mkfs.ubifs) from the Factory toolchain. The desktop host (ubuntu/fedora) tools are not guaranteed to be compatible.

Please note that there are separate flash drivers for uBoot, Linux early userspace, and Linux userspace and there may be some differences in how they expect UBI or JFFS2 to operate.

Some of the UBI drivers do not support subpaging. If Linux tries to boot to a filesystem formatted with subpages, then errors such as 'VID header not found at expected offset' will be thrown when booting the kernel. To avoid this error, set the sub-page size equal to the page size when formatting and attaching a flash partition.
See [[http://www.linux-mtd.infradead.org/faq/ubi.html#L_vid_offset_mismatch]] for full explanation.

Definitions

UBIFS is a file system that acts like LVM with the MTD subsystem. UBIFS can only be used on an UBI volume, as it was designed to work with the UBI layer.
Details about UBIFS can be found at the "linux-mtd page": http://www.linux-mtd.infradead.org/doc/ubifs.html

UBI stands for "Unsorted Block Images." It is a volume management system for flash devices which manages multiple logical volumes on a single physical flash device and spreads the I/O load (i.e, wear-leveling) across the whole flash chip.

An UBI Device is a flash device with an UBI layer on top of it. This UBI device is typically created by either running the ubiformat command on a raw flash partition, or by writing an UBI image (created by the ubinize tool) to a raw flash partition.

An UBI Volume is an individual partition on an UBI device. An UBI Device can hold a number of volumes, which are each individual logical partitions. These volumes are not contiguous on a given device; they can be intermingled for good wear-leveling performance and to avoid bad-blocks on NAND flash. The UBI layer keeps track of the locations of each block of the volumes that it contains.

Sub-paging: Some types of NAND flash support the reading and writing of sub-pages so that the EC and VID headers can be stored in a single page. Without subpaging enabled, each header requires its own page. Not all flash hardware or drivers support sub-paging, so it is often disabled for better compatibility.

Prerequisites

  • 2.6.27 kernel (or newer) with the following configuration options enabled:
    • CONFIG_MTD_UBI=y
    • CONFIG_UBIFS_FS=y
  • mtd-utils 1.1.0 or newer (preferably as new as possible)

Creating UBI/UBIFS Images

An UBIFS filesystem can be deployed to a device in a number of ways: You can create an UBIFS image, and write it to a formatted UBI volume. You can wrap the UBIFS image in an UBI image that can be written directly to an unformatted flash device. You use the mkfs.ubifs and ubinize tools, respectively, to create these UBIFS and UBI images. Another option is to format, attach, and mount an empty UBI partion in userspace, then use tar to expand rootfs.tar.gz onto this UBI partition.

Creating a UBIFS Image

  1. First determine the geometry of the flash device that you are using. See HOWTO Find NAND Parameters for ways to determine the necessary information. You will need the following values:
    • Minimum I/O Size
    • Logical Erase Block Size (LEB)
  2. Create the ubifs file system image using the mkfs.ubifs tool
    mkfs.ubifs -r <root-fs> -m <min i/o size> -e <logical erase block size> -c <max erase blocks> -o <output file>
    • -r <root-fs>: Tells mkfs.ubifs to create an UBIFS image which would have identical contents as the root-fs directory.
    • -m <min i/o size>: Tells mkfs.ubifs that the minimum input/output unit size of the flash this UBIFS image is created for is min i/o size.
    • -e <logical erase block size>: Logical erase block size of the UBI volume this image is created for. This value is not the Physical Erase Block size found in the datasheet.
    • -c <max erase blocks>: Maximum file-system size in erase blocks. This means that it will be possible to use the resulting file-system on volumes up to this size (less or equivalent).
    • -o <output file>: Location of the resulting image file.

Example

bash> mkfs.ubifs -r /opt/timesys/at91sam9260_ek/rfs/ -m 2048 -e 129024 -c 2048 -o ubifs.img

Creating an UBI Configuration file

The ubinize tool takes a configuration file to determine the volume arrangement. The configuration file is in INI format.

  • Each volume gets its own section.
  • Each section can define the following variables for its associated volume:
    • mode - Mandatory. Must always equal ubi.
    • image - Location of the UBIFS image that will populate the volume.
    • vol_id - Numerical volume id. This is optional, and will be assigned numerically.
    • vol_size - Size of the logical volume.
    • vol_type - May be one of the following values: static, dynamic. Dynamic volumes may be resized later.
    • vol_name - Name of the volume. Corresponds to the -n parameter of the ubimkvol command.
    • vol_flags - Additional flags for the volume. autoresize is typically used with dynamic volumes for automatic volume resizing.

Example

The following example has two logical volumes on the UBI device:

[configuration-data-volume]
mode=ubi
image=config_data.img
vol_id=0
vol_size=512KiB
vol_type=static
vol_name=configuration

[rootfs-volume]
mode=ubi
image=rootfs.img
vol_id=1
vol_size=220MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize

Creating an UBI Image

  1. Determine the geometry of the flash device that you are using. See HOWTO Find NAND Parameters for ways to determine the necessary information. You will need the following values:
    • Physical Erase Block Size (PEB)
    • Sub-page size
  2. Create an UBIFS image, as described in the Creating an UBIFS Image section.
  3. Create ubi configuration file, <ubi config>.
  4. Use the ubinize tool to create an image that can be flashed to the device:
    ubinize -p <physical erase block size> -m <min i/o size> -s <sub-page size> -o <output file> <ubi config>
    • -p <physical erase block size>: tells ubinize that physical eraseblock size of the flash chip the UBI image is created for is 128KiB (128 * 1024 bytes).
    • -m <min i/o size>: Tells mkfs.ubifs that the minimum input/output unit size of the flash this UBIFS image is created for is min i/o size.
    • -s <sub-page size>: tells ubinize that the flash supports sub-pages and sub-page size is 512 bytes; ubinize will take this into account and put the VID header to the same NAND page as the EC header.
    • -o <output file>: Location of the resulting image file.
    • <ubi config>: Location of the ubi configuration file.

Example

ubinize -p "128 KiB" -m 2048 -s 512 -o ubi.img ubi.ini

Formatting an UBI Device

A flash device must be formatted with an UBI layer before it can be used by the UBI subsystem. This can be done by burning an UBI image to the flash partition, or by using the ubiformat tool.

Writing an UBI Image to Raw Flash

  1. Create an UBIFS image using the mkfs.ubifs tool, and wrap the UBIFS image in an UBI image using the ubinize tool.
  2. Or, use factory to generate an UBI formatted root filesystem.
  3. Most dev boards will have some pre-tested UBI parameters, which have been tested as working.
  4. Use ubiformat to burn the image to the desired MTD partition:
    ubiformat /dev/mtdX -f rootfs.ubi [-s <subpage_size>] [-O vid_header_offset]

    Creating an UBI device using ubiformat

  1. Determine which MTD partition to use as the root device (e.g. 0 for /dev/mtd0).
  2. Determine the sub-page size of the partition by using the ubiattach command:
    ubiattach /dev/ubi_ctrl -m <mtd partition>

    Example
    # ubiattach /dev/ubi_ctrl -m 0
    UBI: attaching mtd0 to ubi1                                                     
    UBI: physical eraseblock size:   131072 bytes (128 KiB)                         
    UBI: logical eraseblock size:    129024 bytes                                   
    UBI: smallest flash I/O unit:    2048                                           
    UBI: sub-page size:              512                                            
    UBI: VID header offset:          512 (aligned 512)                              
    UBI: data offset:                2048                                           
    UBI error: ubi_read_volume_table: the layout volume was not found               
    ubiattach: error!: cannot attach mtd0                                           
               error 22 (Invalid argument) 
    

    This command should fail, but it will tell you the subpage size.
  3. Format the partition using the ubiformat command:
    Examples
    # ubiformat /dev/mtd0 -s 512 

    # ubiformat /dev/mtd0 -O 2048

Attaching UBI Devices

In order to use an UBI device, it must be attached to the UBI subsystem. This can be accomplished in userspace, or through the kernel.

Attaching an UBI device in Userspace

  1. Determine which MTD partition to use as the root device (e.g. 1 for /dev/mtd1).
  2. On the target, use the ubiattach command to attach the UBI device to the UBI subsystem:
    # ubiattach /dev/ubi_ctrl -m <mtd partition> [-s <subpage_size>] [-O vid_header_offset]

    Example
    # ubiattach /dev/ubi_ctrl -m 1 -O 2048

Attaching an UBI device from the Kernel

  1. Determine which MTD partition 0to use as the root device (e.g. 1 for /dev/mtd1).
  2. If the UBI subsystem is compiled into the kernel, you must specify the UBI devices to attach on the kernel command line:
    ubi.mtd=<mtd partition>

    Example
    ubi.mtd=1
  3. If the UBI subsystem is compiled as a module, you can specify the devices as a command line option during the modprobe:
    modprobe ubi mtd=<mtd partition>

    Example
    # modprobe ubi mtd=1

NOTE: You may specify multiple parameters for multiple UBI volumes by using additional command line parameters:

ubi.mtd=1 ubi.mtd=2
# modprobe ubi mtd=1 mtd=2

Creating UBI Volumes

Adding an UBIFS Image to an existing UBI Device

  1. Attach the destination UBI device either in userspace or from the kernel.
  2. Create an UBIFS image using the mkfs.ubifs tool.
  3. On the target, use the ubimkvol utility to create an UBI volume on the desired UBI device:
    ubimkvol /dev/ubi<device number> -n <volume name>
    [ -s <volume size> | -m ]
  4. Use '-m' to use maximum available space:
    Examples
    ubimkvol /dev/ubi0 -n "rootfs"v -s 100MiB 

    ubimkvol /dev/ubi0 -n "rootfs" -m 
  1. On the target, use the ubiupdatevol utility to put the image on the desired UBI volume:
    ubiupdatevol /dev/<ubi descriptor> <ubifs image>

    Example
    ubiupdatevol /dev/ubi0_4 /rootfs.ubifs

Using UBIFS Partitions

Mounting UBIFS in Userspace

  1. Attach the UBI Device that contains the volume that you wish to mount using one of two methods described above.
  2. Determine the descriptor of the volume that you wish to mount, <volume descriptor>. A volume can be described in two ways:
    • ubi<device number>_<volume number> (e.g. ubi0_4)
    • ubi<device number>:<volume name> (e.g. ubi0:rootfs)
  3. Determine the mount point, (e.g. /mnt/ubifs), and create a dir for this:
    mkdir /mnt/ubifs
  4. Execute the mount command:
    mount -t ubifs <volume descriptor> <mount point>

    Example
    mount -t ubifs ubi0_4 /mnt/ubifs

Using UBIFS as the Root Partition

  1. Determine which MTD partition to use as the root device (e.g. 1 for /dev/mtd1).
  2. Determine the descriptor of the volume that you wish to mount, <volume descriptor>. A volume can be described in two ways:
    • ubi<device number>_<volume number> (e.g. ubi0_4)
    • ubi<device number>:<volume name> (e.g. ubi0:rootfs)
  3. Add the following parameters to the bootargs kernel command line:
    rootfstype=ubifs root=<volume descriptor> ubi.mtd=<mtd partition>

    Example
    setenv bootargs 'console=ttyLP1,115200 rootfstype=ubifs ubi.mtd=rootfs root=ubi0:rootfs rw rootwait'

Additional Resources

UBIFS Docs - From linux-mtd maintainers
mkfs.ubifs - mkfs.ubifs Guide
LWN Article on UBIFS - Article highlighting the features and rationale behind UBIFS
UBIFS Compression Experiments
UBIFS Support - Texas Instruments Embedded Processors Wiki
Quad SPI Vybrid Module Updates - Freescale Website

Files