Change the partition table
You can customize the partition table of a Digi embedded module using a series of U-Boot commands. The partition table is handled differently depending on the media used to store the system: MMC media or NAND flash.
MMC media (eMMC/microSD card)
GPT partition table
eMMC and microSD are partitioned using a GPT. The partition table (partition names, sizes, and UUIDs) is described in a U-Boot environment variable.
The syntax for describing a GPT as a string is defined at doc/README.gpt file in the U-Boot source code:
Format of partitions layout: "partitions=uuid_disk=...;name=u-boot,size=60MiB,uuid=...; name=kernel,size=60MiB,uuid=...;" or "partitions=uuid_disk=${uuid_gpt_disk};name=${uboot_name}, size=${uboot_size},uuid=${uboot_uuid};" The fields 'name' and 'size' are mandatory for every partition. The field 'start' is optional. The fields 'uuid' and 'uuid_disk' are optional if CONFIG_RANDOM_UUID is enabled. A random uuid will be used if omitted or they point to an empty/ non-existent environment variable. The environment variable will be set to the generated UUID.
Note A size of "-" (without the MiB suffix) indicates that the partition will use the remaining available space on the media, so the dash is usually used for the last partition in the table.
Once the partition table is defined as a string, you can write the partition table to the media using U-Boot's gpt command.
Digi provides the following predefined variables:
- Partition tables
- parts_linux: partition table suitable for storing the Digi Embedded Yocto Linux system
- parts_android: partition table suitable for storing the Digi Embedded Android system
- UUIDs
- uuid_disk: predefined UUID for the media
- part1_uuid..part9_uuid: predefined UUIDs for the partitions
- Scripts
- partition_mmc_linux: script for writing the partition table in variable $parts_linux to the MMC device index in variable $mmcdev
- partition_mmc_android: script for writing the partition table in variable $parts_android to the MMC device index in variable $mmcdev
Change the MMC partition table (run-time)
- Edit the partition table of your selected operating system with env edit command:
=> env edit parts_linux
- 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 Linux these are: safe, linux, recovery, rootfs, and update.
For Android these are: safe, boot, recovery, system, cache, and data. - You can resize system partitions, but make sure your system will fit in them.
- The update partition (cache in Android) must be approximately the size of the rootfs partition (system in Android) to fit system updates.
- You can add partitions as necessary, but you must assign a different name and UUID.
- (Optional) Set mmcdev to the desired media. By default this variable should point to the MMC media index you are booting from (eMMC or microSD). You don't need to set mmcdev unless you want to write the GPT to a specific MMC media other than the one you booted from.
- Save the environment with saveenv.
- Run the script that matches your operating system to write the new partition table to the MMC media:
=> run partition_mmc_linux
Change the default MMC 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:
- Locate the definition of the parts_linux (or parts_android) variable in your platform's header file in U-Boot source code at include/configs/.
- Edit the partition table in the header file using the syntax described in Change the MMC partition table (run-time).
- Save your changes and recompile U-Boot.
- Update the bootloader of your device.
- Reset the variable to default value that corresponds to your operating system:
=> env default parts_linux
You can also reset the whole environment to default values:
=> env default -a
- Save the environment with saveenv.
- Reset the device (or verify that mmcdev points to the MMC index of the media where the partition table will be written)
- Write the new partition table to the media that corresponds to your operating system:
=> run partition_mmc_linux
The mmcpart, mmcroot, and recoverycmd 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.
NAND flash
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 common/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.
Note 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.
Change the NAND 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 Linux these are: bootloader, environment, safe, linux, recovery, rootfs, and 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 NAND 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:
- Locate the definition of mtdparts variable in your platform's header file in U-Boot source code at include/configs/. Note that there may be variants to accommodate different NAND memory sizes.
- Edit the partition table in the header file using the syntax described in Change the NAND partition table (run-time).
- Save your changes and recompile U-Boot.
- Update the bootloader of your device.
- Reset the variable to default value with:
=> env default mtdparts
You can also reset the whole environment to default values:
=> env default -a
- 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.
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.