[ELDK] U-Boot configuration kernel + rootfs squashfs image in NAND Flash, copy rootfs to ram, mount rootfs from ram

Christoph Petzold cpetzoldatwork at gmx.de
Tue Jan 15 09:45:05 CET 2013


Hi,

i have an embedded system based on arm (tx28) with 128MB ram and
128MB NAND-flash with a working cross compilation toolchain.

Now id like to get the following boot configuration to work:

- kernel from NAND and root file system with squashfs from ram

(I am going to shorten 'root file system' to rootfs in normal text
from now on)

Assume the kernel image to reside in a partition of the NAND-flash.
Lets call this partition "linux". And assume the rootfs
image to reside on another partition of the NAND-flash. Lets call
this partition "rootfs".

Now id like to have U-Boot read the squashfs rootfs image
from partition "rootfs" into ram and then let the kernel boot and
mount the squashfs rootfs from ram.

Why do i need squashfs?
I need a fast and small rootfs. It must boot quickly. I do not
want write support.

What i have tried already?
Abstract:
A) create squashfs root file (rootfs.sq) system on host pc
B) erase rootfs partition on target
C) load rootfs squashfs image from host pc to target ram
D) write this rootfs image from ram to NAND partition "rootfs"
E) adjust kernel parameters
F) Bootscript:
     - read rootfs image into ram
     - boot kernel with rootfs in ram

Here are the details:

A) create squashfs root file (rootfs.sq) system on host pc:

host-pc$ mksquashfs filesystem/ rootfs_squashfs

where "filesystem" is a directory that contains a complete
rootfs and rootfs_squashfs is the name of the
image to be built.

Here are some infos about the target U-Boot environment:

MX28 U-Boot > mtdparts

device nand0 <gpmi-nand>, # parts = 4
  #: name                size            offset          mask_flags
  0: env                 0x00020000      0x00020000      0
  1: u-boot              0x00100000      0x00040000      0
  2: linux               0x00400000      0x00140000      0
  3: rootfs              0x07ac0000      0x00540000      0

active partition: nand0,0 - (env) 0x00020000 @ 0x00020000

The "linux" partition contains the kernel. The squashfs image
will be deployed in the "rootfs" partition. As you can see in the
output of the mtdparts command of u-boot the blocksize is
20000(hex) which is 131072 (dezimal) which is the default
value for the block size used by the mksquashfs tool.

B) erase rootfs partition on target
Here i invoke the u-boot command for flashing the "rootfs" partition
on the target:

MX28 U-Boot > nand erase.part rootfs
NAND erase.part: device 0 offset 0x540000, size 0x7ac0000
Skipping bad block at  0x00e20000
Skipping bad block at  0x01ec0000
Skipping bad block at  0x028c0000
Skipping bad block at  0x04b40000
Skipping bad block at  0x06de0000
Skipping bad block at  0x07f80000
Skipping bad block at  0x07fa0000
Skipping bad block at  0x07fc0000
Skipping bad block at  0x07fe0000

OK

C) load rootfs squashfs image from host pc to target ram

I use the tftp command of u-boot with two arguments to load the
rootfs image from the host pc into the ram of the target.
The first argument is the u-boot variable loadaddr, which is the
address of the place where the image is to be loaded to. The
second argument is the name of the rootfs image file
in the host pc tftp folder.

MX28 U-Boot > print loadaddr
loadaddr=0x40100000
MX28 U-Boot > print rootfs_squashfs
rootfs_squashfs=rootfs_squashfs
MX28 U-Boot > tftp ${loadaddr} ${rootfs_squashfs}
Using FEC0 device
TFTP from server 192.168.1.212; our IP address is 192.168.1.214
Filename 'rootfs_squashfs'.
Load address: 0x40100000
Loading: ##########
                 [snip]
          ########################
done
Bytes transferred = 33755136 (2031000 hex)

Now i have the rot file system image lying in ram at address
0x40100000.

U-Boot automatically sets the variables fileaddr and filesize
to the file address and file size of the last file that was loaded
in ram.

MX28 U-Boot > print fileaddr
fileaddr=40100000
MX28 U-Boot > print file
   fileaddr filesize
MX28 U-Boot > print filesize
filesize=2031000

D) write this rootfs image from ram to NAND partition "rootfs"
Maybe i do something wrong here. I use the u-boot nand write.trimffs
command to write the rootfs image file to the "rootfs"
partition of the NAND-flash.

MX28 U-Boot > nand write.trimffs ${fileaddr} rootfs ${filesize}

NAND write: device 0 offset 0x540000, size 0x2031000
Skip bad block 0x00e20000
Skip bad block 0x01ec0000
  33755136 bytes written: OK


E) adjust kernel parameters
Now the kernel needs to know, where to find the rootfs in ram.
Maybe i do something wrong here, too. I save my bootargs for
ram boot in a variable "bootargs_ram_squashfs".

MX28 U-Boot > printenv bootargs_ram_squashfs
bootargs_ram_squashfs=run default_bootargs; setenv bootargs ${bootargs} 
root=/dev/ram r initrd=${rootfsaddr} rootfstype=squashfs

The "run default_bootargs" part is for loading some default board specific
values. The important part of the kernel parameters is
"root=/dev/ram r initrd=${rootfsaddr} rootfstype=squashfs".

Here i don't know why i have to specify /dev/ram. Sometimes i read 
/dev/ram0
in How-Tos and in kernel Documentation/initrd.txt. In my booted target 
system
i have the devices /dev/ram0 to /dev/ram3 but there is no /dev/ram 
device file.
The kernel documentation for the use of initramfs and initrd is quite
confusing for me and there are nearly no kernel docs for squashfs in
kernel 3.0. As far as i understand the initramfs method combines a kernel
and the rootfs in one image. But this method does not use
squashfs.

Here is a sketch of what i believe to be the memory layout i'd like to have.

Address number        description
-----------------------------------------------
0x40000000            start address
0x40008000            Loadaddress/Entrypoint rported by nboot command
0x40500000            ${rootfsaddr} address of rootfs image in ram

The u-boot command 'nboot linux' gives the following output:

MX28 U-Boot > nboot linux

Loading from nand0, offset 0x140000
    Image Name:   Linux-3.3.0-karo
    Image Type:   ARM Linux Kernel Image (uncompressed)
    Data Size:    2629304 Bytes = 2.5 MiB
    Load Address: 40008000
    Entry Point:  40008000

I believe that u-boot loads the kernel image from the 'linux'
partition of my NAND-flash into the ram at starting address
0x40008000. What is the difference between Load Address
and Entry Point by the way? In which case do they differ?
8000(hex) is 32Kbyte. Where is this parameter defined?
I did not find it in my u-boot sources. Its confusing to have
parameters and output that i don't understand. Anyway, I
believe that there will be enough space between kernel and
rootfs in ram if i put the rootfs image at the startaddress
${rootfsaddr} = 0x40500000. So the rootfs image is to
be loaded at the position after the first 5MB of ram.


F) Bootscript

First i load the rootfs image into ram with the help of u-boot
nand read:


MX28 U-Boot > nand read ${rootfsaddr} rootfs ${filesize}

NAND read: device 0 offset 0x540000, size 0x2031000
Skipping bad block 0x00e20000
Skipping bad block 0x01ec0000
  33755136 bytes read: OK

Here i invoked nand read with three arguments. The first is
${rootfsaddr} which is set to 0x40500000. The second argument
is the NAND-partition name of the partition containing the rootfs
image. The third argument is ${filesize} which is set to the actual
size of the rootfs image (0x2031000). I obtained the size number
from step C).

Now it is time to load and start the kernel. I use the u-boot nboot
command to load the kernel and then i use the u-boot bootm
command to start the kernel.

MX28 U-Boot > nboot linux

Loading from nand0, offset 0x140000
    Image Name:   Linux-3.3.0-karo
    Image Type:   ARM Linux Kernel Image (uncompressed)
    Data Size:    2629304 Bytes = 2.5 MiB
    Load Address: 40008000
    Entry Point:  40008000

MX28 U-Boot > bootm

... Kernel boots until root file system mount ...

List of all partitions:
1f00             128 mtdblock0  (driver?)
1f01            1024 mtdblock1  (driver?)
1f02           16384 mtdblock2  (driver?)
1f03          110336 mtdblock3  (driver?)
1f04            4096 mtdblock4  (driver?)
No filesystem could mount root, tried:  squashfs
Kernel panic - not syncing: VFS: Unable to mount root fs on 
unknown-block(1,0)
Rebooting in 1 seconds..


Any help or suggestions are highly appreciated.


I have succesfully tried to boot:

     - kernel via tftp and rootfs via nfs
     - kernel from NAND and rootfs (jffs2) from NAND


More information about the eldk mailing list