Prepare a bootable NAND/eMMC
The purpose of this tutorial is to show how to flash a complete linux (u-boot + kernel + rootfs) into the internal storage of the system.
This steps has to be followed inside a board running a Linux from a external interface.
Note: you will need to boot from an SD or NFS in order to use an existing Linux to flash the new one. |
Prepare the files
First, it will be needed to prepare the following elements:
- u-boot or X-loader MLO and .img (in the case of i.mx chips both are together in a .imx file)
- zImage with the corresponfing kernel
- Correct .dtb used by this kernel
- rootfs with the corresponding modules installed all compressed in a .tar.bz2 file.
Flash into NAND (Tesdted with am335x based procesor)
This steps has been followed using a Linux Kernel 4.9 and a IGEP SMARC MODULE AM335x |
First, we will start with the case of using a NAND flash as internal storage.
Note: it will be used some special tools collected in the Mtdutils package. More info here: Mtdutils |
It is recommendable to test the NAND flash and its partitions:
nandtest -m /dev/mtd0
nandtest -m /dev/mtd1
nandtest -m /dev/mtd2
nandtest -m /dev/mtd3
Then we erase the partitions:
flash_eraseall /dev/mtd0
flash_eraseall /dev/mtd1
flash_eraseall /dev/mtd2
flash_eraseall /dev/mtd3
Now we can flash the MLO in the first partition /dev/mtd0. It important to know that in this case (because it is a NAND flash and we have to record the MLO) we have to flash it four times in the first 4 blocks of this partition. In order to know the exact addresses we can check the documentation of the chip developer (in this case: AM335x U-Boot User's Guide (Texas Documentation) NAND Layout) and will get the offset addresses [0x0 0x20000 0x40000 0x60000] . For each one of this addresses we have to write:
nandwrite -p -s [address] /dev/mtd0 [your_MLO]
For example:
nandwrite -p -s 0x0 /dev/mtd0 /home/root/flash_files/MLO
nandwrite -p -s 0x20000 /dev/mtd0 /home/root/flash_files/MLO
nandwrite -p -s 0x40000 /dev/mtd0 /home/root/flash_files/MLO
nandwrite -p -s 0x60000 /dev/mtd0 /home/root/flash_files/MLO
Then we will flash into the second partition /dev/mtd1 the u-boot.img:
nandwrite -p /dev/mtd1 [your_u-boot.img]
For example:
nandwrite -p /dev/mtd1 /home/root/flash_files/u-boot.img
In order to flash the rootfs we use the UBIFS (filesystem for unmanaged flash memory devices) in the last partition /dev/mtd3. We are using a UBIFS in order to do it:]]
Note: In this case we skip the third partiton /dev/mtd2 that is prepared to include if it is needed a environment uEnv.txt |
ubiformat /dev/mtd3
ubiattach -p /dev/mtd3
ubimkvol /dev/ubi0 -N filesystem -m
Then, we can flash the rootfs:
mkdir /tmp/flashroot
mount -t ubifs ubi0:rootfs /tmp/flashroot/
cd /tmp/flashroot/
tar -xf -C .
cd /
umount /tmp/flashroot
ubidetach -p /dev/mtd3
For example:
mkdir /tmp/flashroot
mount -t ubifs ubi0:rootfs /tmp/flashroot/
cd /tmp/flashroot/
tar -xf /home/root/flash_files/my_rootfs.tar -C .
cd /
umount /tmp/flashroot
ubidetach -p /dev/mtd3
Flash into eMMC (Tested with iMX6-DualLite)
This steps has been followed using a Linux Kernel 4.9 and a IGEP SMARC MODULE iMX6 |
Flashing into a eMMC is quite similar to flash a SD card. This tutorial is going to be focus in the i.MX chip boards. This chips specifies that the u-boot.imx file (MLO+img) has to be at the beginning without format. Knowing this we have to create the partitions in a different way, leaving 8MB before the beginning of the first partition.
We begin by unmounting and clearing the partition on the eMMC (mmcblk2 in this case)
umount /run/media/mmcblk2*
parted -s /dev/mmcblk2 mklabel msdos
Now we use sfdisk to create the partitions. We are creating two partitions:
Partition 1: boot
- FAT32 partition.
- Begin at the 16065 sector (leaving 8MB free before).
- Has to have the boot flag.
- It has to be Cylinder alignment. (Use Cylinder alignment to maintain compatibility with operating systems released before the year 2000, such as DOS). This setting aligns partitions to start and end on disk cylinder boundaries).
- Size of 64MB (approx).
Partition 2: rootfs
- Starts after partition 1.
- Default settings
- Size of the rest of the space
We transform this specifications into a sfdisk command:
sfdisk -D -H 255 -S 63 /dev/mmcblk2 << THEEND
1,8,0x0C,*
9,,,-
THEEND
We can check the partitions are correctly set using:
fdisk -l /dev/mmcblk2
The result should be similar to the following:
Then we finish the partitions:
mkfs.vfat -F 32 /dev/mmcblk2p1 -n boot
RFS_UUID=`cat /proc/sys/kernel/random/uuid`
mkfs.ext3 -U "$RFS_UUID" "/dev/mmcblk2p2" -L rootfs
Now we can create temporaly folders to work with and mount the partitions there.
mkdir -p /tmp/mmcblk2p1
mkdir -p /tmp/mmcblk2p2
mount -t vfat /dev/mmcblk2p1 /tmp/mmcblk2p1
mount -t ext3 /dev/mmcblk2p2 /tmp/mmcblk2p2
Note: If your system has automatically mounted the partitions you have to umount them again by using: umount /run/media/mmcblk2* |
Now we can flash the rest of the elements (by default the zImage and the dtb are place inside the rootfs boot folder).
First we extract the rootfs we want to flash in the temporary folder of the second partition ()
tar -xf -C /tmp/mmcblk2p2/
For example:
tar -xf
/opt/firmware/isee-fsl-image-dev-imx6dl-igep0046d10-20170712121141.rootfs.
tar.bz2 -C /tmp/mmcblk2p2/
At this point you can flash the u-boot.imx image using dd command and dissebling the read only protection:
RO_PROTECTION=`cat /sys/block/mmcblk2/force_ro`
echo 0 > /sys/block/mmcblk2/force_ro
dd if= of=/dev/mmcblk2 bs=512 seek=2 2> /dev/null
echo $RO_PROTECTION > /sys/block/mmcblk2/force_ro
sync
For example:
RO_PROTECTION=`cat /sys/block/mmcblk2/force_ro`
echo 0 > /sys/block/mmcblk2/force_ro
dd if=/tmp/mmcblk2p2/boot/u-boot.imx of=/dev/mmcblk2 bs=512 seek=2 2>
/dev/null
echo $RO_PROTECTION > /sys/block/mmcblk2/force_ro
sync
Finally we copy the zImage and the dtb into the first partition (boot partition)
cp /tmp/mmcblk2p1
cp -f /tmp/mmcblk2p1
For example:
cp /tmp/mmcblk2p2/boot/zImage /tmp/mmcblk2p1
cp -f /tmp/mmcblk2p2/boot/imx6*.dtb /tmp/mmcblk2p1