You can customize the partition table of a Digi embedded module using a series of U-Boot commands.

On a NAND flash, the partition table is simply a string that gets passed to the kernel during the boot process. The NAND flash itself is not written with any partition table data.

The syntax for describing a NAND partition table is defined at cmd/mtdparts.c file in the U-Boot source code:

 * mtdparts=mtdparts=<mtd-def>[;<mtd-def>...]
 *
 * <mtd-def>  := <mtd-id>:<part-def>[,<part-def>...]
 * <mtd-id>   := unique device tag used by linux kernel to find mtd device (mtd->name)
 * <part-def> := <size>[@<offset>][<name>][<ro-flag>]
 * <size>     := standard linux memsize OR '-' to denote all remaining space
 * <offset>   := partition start offset within the device
 * <name>     := '(' NAME ')'
 * <ro-flag>  := when set to 'ro' makes partition read-only (not used, passed to kernel)
 * <enc-flag> := when set to 'enc' makes partition encrypted (not used, passed to kernel)

In U-Boot, the NAND partition table is stored in variable mtdparts.

File systems have some overhead, so the total partition size won’t be available for use when the file system is mounted. This overhead is significant in UBIFS and NAND flashes since in addition to the metadata of the file system itself, a certain amount of blocks must be reserved to account for potential bad blocks.

Multi-MTD system partitioning

Multi-MTD system partitioning uses one UBI volume per MTD partition. This is the default for the ConnectCore 6UL.

Change the partition table (run-time)

  • Edit the partition table with env edit command. (You can also use the mtdparts command.)

    => env edit mtdparts
  • Modify the command to fit your desired partition table, but note the following:

    • Do not change the names of the system partitions. These partitions are meant to have their original names for system updates to work. For Digi Embedded Yocto these are: safe, linux, recovery, rootfs, update.

    • You can resize system partitions, but make sure your system will fit in them.

    • The update partition must be approximately the size of the rootfs partition to fit system updates.

    • You can add partitions as necessary.

  • Save the environment with saveenv.

  • After modifying the partition table, previously written information about UBI volumes may exist in the NAND that won’t match the new layout. For this reason, Digi recommends you erase all partitions that are new, have moved, or have been resized, using this command:

    => nand erase.part <partition>

Change the default partition table (build-time)

You may want to change the default partition table so that all devices ship with the same partition layout. To do that:

  • Open your platform’s common header file in U-Boot source code at include/configs/ccimx6ul_common.h.

  • Locate the partition table definition for your module’s NAND capacity (constants MTDPARTS_256MB, MTDPARTS_512MB or MTDPARTS_1024MB):

    #define MTDPARTS_256MB		"mtdparts=" CONFIG_NAND_NAME ":" \
    				__stringify(UBOOT_PART_SIZE_SMALL) "m(" CONFIG_UBOOT_PARTITION ")," \
    				__stringify(ENV_PART_SIZE_SMALL) "m(environment)," \
    				"1m(safe)," \
    				"12m(" CONFIG_LINUX_PARTITION ")," \
    				"14m(" CONFIG_RECOVERY_PARTITION ")," \
    				"122m(" ROOTFS_PARTITION ")," \
    				"-(update)"
    #define MTDPARTS_512MB		"mtdparts=" CONFIG_NAND_NAME ":" \
    				__stringify(UBOOT_PART_SIZE_BIG) "m(" CONFIG_UBOOT_PARTITION ")," \
    				__stringify(ENV_PART_SIZE_BIG) "m(environment)," \
    				"1m(safe)," \
    				"24m(" CONFIG_LINUX_PARTITION ")," \
    				"32m(" CONFIG_RECOVERY_PARTITION ")," \
    				"256m(" ROOTFS_PARTITION ")," \
    				"-(update)"
    #define MTDPARTS_1024MB		"mtdparts=" CONFIG_NAND_NAME ":" \
    				__stringify(UBOOT_PART_SIZE_BIG) "m(" CONFIG_UBOOT_PARTITION ")," \
    				__stringify(ENV_PART_SIZE_BIG) "m(environment)," \
    				"1m(safe)," \
    				"24m(" CONFIG_LINUX_PARTITION ")," \
    				"32m(" CONFIG_RECOVERY_PARTITION ")," \
    				"512m(" ROOTFS_PARTITION ")," \
    				"-(update)"
  • Edit the appropriate constant that corresponds to your NAND capacity using the syntax described in Change the partition table (run-time). If using DualBoot, the constants are called MTDPARTS_DUALBOOT_256MB, MTDPARTS_DUALBOOT_512MB or MTDPARTS_DUALBOOT_1024MB.

  • Save your changes and recompile U-Boot.

  • Update the bootloader of your device and reboot it.

  • Reset the whole environment to default values:

    => env default -a
  • Run the following script to generate the partition table:

    => run partition_nand_linux
  • Save the environment with saveenv.

  • After modifying the partition table, previously written information about UBI volumes may exist in the NAND that won’t match the new layout. For this reason, Digi recommends you erase all partitions that are new, have moved, or have been resized, using this command:

    => nand erase.part <partition>

The recoverycmd and mtdparts U-Boot variables are used by the dboot and update commands as well as by the installation, recovery, and boot scripts generated by Digi Embedded Yocto.

  • The values of these variables must reflect any changes made to the partition table, and vice versa.

  • Make sure the variable syntax is correct; incorrect syntax may lead to unexpected results.

Single-MTD system partitioning

The single-MTD system partitioning strategy uses one MTD partition called system and multiple UBI volumes.

The system partition occupies most of the available space on the NAND so it’s unlikely that you want to change the MTD partition layout. Instead, you may want to change the number and size of the UBI volumes inside the system partition.

Change the system UBI volumes (run-time)

Although it is possible, it’s not recommended to change the layout of UBI volumes at run-time. This layout is defined on variable ubivolscript, which is a long script with conditionals, difficult to edit on a terminal using env edit command.

Change the system UBI volumes (build-time)

You may want to change the default UBI volumes so that all devices ship with the same layout. To do that:

  • Open your platform’s common header file in U-Boot source code at include/configs/$ccimx6ul_common.h.

  • Locate the UBI volumes layout definition for your module’s NAND capacity (constants UBIVOLS_256MB, UBIVOLS_512MB or UBIVOLS_1024MB):

    #define UBIVOLS_256MB		"ubi create " CONFIG_LINUX_PARTITION " c00000;" \
    				"ubi create " CONFIG_RECOVERY_PARTITION " e00000;" \
    				"ubi create " ROOTFS_PARTITION " 7e00000;" \
    				"ubi create update;"
    #define UBIVOLS_512MB		"ubi create " CONFIG_LINUX_PARTITION " 1800000;" \
    				"ubi create " CONFIG_RECOVERY_PARTITION " 2000000;" \
    				"ubi create " ROOTFS_PARTITION " 10000000;" \
    				"ubi create update;"
    #define UBIVOLS_1024MB		"ubi create " CONFIG_LINUX_PARTITION " 1800000;" \
    				"ubi create " CONFIG_RECOVERY_PARTITION " 2000000;" \
    				"ubi create " ROOTFS_PARTITION " 20000000;" \
    				"ubi create update;"
  • Edit the appropriate constant to create the volumes you want. For system updates to work, preserve the original names of the default UBI volumes (you can modify the sizes, though). If using DualBoot, the defines are called UBIVOLS_DUALBOOT_256MB, UBIVOLS_DUALBOOT_512MB or UBIVOLS_DUALBOOT_1024MB.

  • Save your changes and recompile U-Boot.

  • Update the bootloader of your device and reboot it.

  • Reset the whole environment to default values:

    => env default -a
  • Run the following script to generate the new partition table and UBI volumes:

    => run partition_nand_linux
  • Save the environment with saveenv.

Adjust Digi Embedded Yocto for partition table changes

After changing the NAND partition table in U-Boot, you must review the MKUBIFS_BOOT_ARGS and MKUBIFS_ARGS variables used in Digi Embedded Yocto. These variables establish the NAND partition parameters to use when building UBIFS images for your system:

  • MKUBIFS_BOOT_ARGS is used for partitions linux and recovery.

  • MKUBIFS_ARGS is used for partition rootfs.

The default parameters in Digi Embedded Yocto:

# mkfs.ubifs parameters for boot partition (the one holding kernel and device tree files)
MKUBIFS_BOOT_ARGS ?= "-m 2048 -e 126976 -c 127"

# mkfs.ubifs parameters for rootfs partition
MKUBIFS_ARGS ?= "-m 2048 -e 126976 -c 8191"

where:

  • -m 2048 (2 KiB) is the minimum I/O size of the underlying UBI and MTD devices (page size).

  • -e 126976 (124 KiB) is the Logical Erase Block (LEB) size. UBI requires two minimum I/O units out of each Physical Erase Block (PEB) for overhead: one for maintaining erase count information, and another for maintaining the Volume ID information. For a PEB size of 128 KiB and a page size of 2 KiB, the LEB would be 128 - (2 * 2) = 124 KiB.

  • -c 127 is the maximum LEB count, or maximum size, in LEBs, of the UBIFS file system. This can be calculated as the next power of two following the number of erase-blocks in the partition (partition_size / erase_block_size) minus 1. For example for a partition size of 14MiB and an erase block size of 128KiB → 14 * 1024 * 1024 / 128 * 1024 = 112. The next power of two following 112 is 128, so use a max-leb-count of 128 - 1 = 127.

The -m and -e parameters depend on the NAND geometry, so they do not need to be modified. The -c parameter may need to be adjusted depending on the size of your partitions, to better adjust the overhead of the UBIFS image to the real size of the partition.