After my latest post I had a u-boot and a kernel flashed to NAND. I was however mistaken about the load address. Fortunately someone with more knowledge had prepared U-boot with default parameters.
=> printenv loadaddr
loadaddr=0x42000000
I have no clue why it is at 0x42000000 and not at 0x40008000 that I got from uboot-mkimage but the U-boot preloaded value was correct in my case. Anyone with input on this would be appreciated.
Once the kernel has the correct load address it will get much further during startup, all the way to mounting the root file system. For the file system it seemed that ubifs was the modern way to go so thats what I did.
Flashing a ubifs file system on a nand can be done in two ways. You can, for one, flash it with a generic NAND flasher. This requires a ubi image which is created by running ubinize on an existing ubifs image.
The other alternative is to flash a ubifs image through U-Boot, which is what I decided to do. The ubifs image is created by running mkubifs but this is handled automatically by bitbake if you have set ubifs as a target in conf/machine/imx28evk.conf.
IMAGE_FSTYPES ?= "tar.bz2 ext3 uboot.mxsboot-sdcard sdcard ubifs"
However building the ubifs image requires certain parameters set in the same file (conf/machine/imx28evk.conf)
MKUBIFS_ARGS = "--min-io-size 2048 --leb-size 126976 --max-leb-cnt 864"
These values can be found by running ubiattach -m 1 /dev/ubi_ctrl (requires packages mtd-utils and mtd-utils-ubifs) in Linux on your target system. The easiest way to do this is to boot on an SD card, see Task #4 - Deploy and test
However depending on your bootargs you might not have access to /dev/mtdX. If the mtd device is missing, reboot and enter U-Boot and add gpmi (Can not see the NAND device /dev/mtd0 or /dev/mtd1 for micron MT29F1G08ABADA) to the mmcargs.
setenv mmcargs setenv bootargs gpmi ${mtdparts} console=${console_mainline},${baudrate} root=${mmcroot}
run mmcboot
Your /dev/mtdX should be available now. The NAND partitions does not work like normal file system partitions, instead they are entirely logical and setup with an address and a size. In U-Boot the NAND partitions can be setup neatly with the command mtdparts and for many imx boards that can translate just nicely to a booted Linux, but not the imx28. The other boards have an external file where the NAND partitions can be configured but the imx28 has the partition hardcoded in the driver. It can be found (grep for mtd_partition) and modified but then it must be maintained as a kernel patch every time there is an upgrade. Instead I opted for going with the default partition the imx28 nand driver offers: /dev/mtd0 20MiB, /dev/mtd1 has the rest. Verify the numbers using mtdinfo command. My strategy is to put bootloader, environment and kernel in /dev/mtd0 and in /dev/mtd1 I put filesystems by using multiple ubifs volumes in the same partition.
So analyzing the output from ubiattach -m 1 /dev/ubi_ctrl
UBI: attaching mtd1 to ubi0
UBI: physical eraseblock size: 131072 bytes (128 KiB)
UBI: logical eraseblock size: 126976 bytes
UBI: smallest flash I/O unit: 2048
UBI: VID header offset: 2048 (aligned 2048)
UBI: data offset: 4096
UBI: attached mtd1 to ubi0
UBI: MTD device name: "gpmi-nfc-general-use"
UBI: MTD device size: 108 MiB
UBI: number of good PEBs: 864
UBI: number of bad PEBs: 0
UBI: max. allowed volumes: 128
UBI: wear-leveling threshold: 4096
UBI: number of internal volumes: 1
UBI: number of user volumes: 0
UBI: available PEBs: 852
UBI: total number of reserved PEBs: 12
UBI: number of PEBs reserved for bad PEB handling: 8
UBI: max/mean erase counter: 1/1
UBI: image sequence number: 0
UBI: background thread "ubi_bgt0d" started, PID 397
UBI device number 0, total 864 LEBs (109707264 bytes, 104.6 MiB), available 852 LEBs (108183552 bytes, 103.2 MiB), LEB size 126976 by)
Use the values to set the MKUBIFS_ARGS to get a ubifs image that will work for your NAND flash.
Now since we are reconsidering the partitioning lets recap where to put stuff and start from the point where we only have u-boot on the nand.
First lets build the partition table using mtdparts default and then we delete the incorrectly placed file system.
mtdparts default
mtdparts del filesystem
Then we place the file system after the first 20MiB. I use a 128MiB NAND here.
mtdparts add nand0 0x06C00000@0x1400000 filesystem
The partition table should look like this now
=> mtdparts
device nand0 <gpmi-nand>, # parts = 7
#: name size offset mask_flags
0: bootloader 0x00300000 0x00000000 1
1: environment 0x00080000 0x00300000 0
2: redundant-environment0x00080000 0x00380000 0
3: kernel 0x00400000 0x00400000 0
4: fdt 0x00080000 0x00800000 0
5: ramdisk 0x00800000 0x00880000 0
6: filesystem 0x06c00000 0x01400000 0
Lets save the partition table to the environment.
saveenv
Now let us first flash the kernel where it is supposed to be. As usual we download it from a USB thumb since I haven't gotten to setup TFTP yet.
usb start
fatls usb 0:1
nand erase.part kernel
fatload usb 0:1 ${loadaddr} uimage-imx28evk.bin
nand write ${loadaddr} kernel
Now the kernel is in place, lets setup the kernel boot arguments. U-boot comes with a default environment nandargs which is almost entirely correct for us.
nandargs=setenv bootargs console=${console_mainline},${baudrate} rootfstype=ubifs ubi.mtd=6 root=ubi0_0 ${mtdparts}
The part that is incorrect for us is ubi.mtd=6 as we are planning to have the filesystem on mtd1. So we take the setenv part and runs it manually. It is also important to add the gpmi argument so the nand driver will load.
setenv bootargs gpmi console=${console_mainline},${baudrate} rootfstype=ubifs ubi.mtd=1 root=ubi0_0 ${mtdparts}
setenv bootcmd 'nboot kernel; bootm'
saveenv
We can now try to boot and should get as far as trying to mount the root file system.
So now it is time to put in our ubifs image into nand. First we load the ubifs image into memory.
usb start
fatls usb 0:1
fatload usb 0:1 ${loadaddr} core-image-minimal-imx28evk.ubifs
Then we erase the filesystem partition.
nand erase.part filesystem
We set the ubi subsystem to work with the filesystem partition
ubi part filesystem
We create a volume. Since we don't set type or size it becomes dynamic and covers the entire size.
ubi create rootfs
Write the loaded image to the newly created volume. If we had created multiple volumes we chose which volume to receive the image. Useful for having multiple filesystems/partitions.
ubi write ${loadaddr} rootfs ${filesize}
Finally we mount the file system locally to verify that it looks ok.
ubifsmount ubi0:rootfs
ubifsls
Now we can reboot and this time Linux should start properly. It did for me and I hope it will work for you too!