i.MX28: Enable initramfs step by step

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX28: Enable initramfs step by step

26,560 Views
PeterChan
NXP Employee
NXP Employee

1. Prepare initramfs image

 

First of all, please follow the i.MX28 linux BSP user guide to build the LTIB once to make sure the u-boot, kernel, boot streams and rootfs are built successfully.

Then run the following command in LTIB for configuration setup.

 

./ltib -m config

 

Pick "initramfs" in the Target Image Generation.

 

--- Target Image Generation
   Options --->
        --- Choose your root filesystem image type
        Target image: (initramfs) --->

 

Exit and save this configuration. Run the following command to build the LTIB again.

 

./ltib -f

 

After a successful build, the initramfs image "initramfs.cpio.gz" will be created under the "ltib" directory.

 

 

2. Integrate initramfs into SB file

 

In the building steps, when the following command is run

 

./ltib -p boot_stream.spec -f

 

power_prep, boot_prep, linux_prep will be built and then these boot streams will be combined with zImage and u-boot to form the SD files. These SD files can be found at directory rootfs/boot. In imx28_(ivt_)linux.sb, the boot sequence is power_prep, boot_prep, linux_prep and then zImage. In imx28_(ivt_)uboot.sb, the boot sequence is power_prep, boot_prep and then u-boot.

The boot and load sequence is actually controlled by the BD files linux(_ivt).bd and uboot(_ivt).bd. To integrate the initramfs into SB, simply apply the mx28_initramfs_imx-bootlets-src-10.12.01.patch to modify linux(_ivt).bd and run the build boot streams command again.

 

./ltib -p boot_stream.spec -f

 

After the build, the initramfs image will be integrated into the SB. You can check this from the imx28_(ivt_)linux.sb file size.

 

In linux_prep, function setup_initrd_tag() setup a ATAG_INITRD2 memory tag to inform the kernel where the compressed initramfs iamge is located and its size. It is the the developer's responsibility to ensure that the size of the initrd.size is large enough to hold the initramfs.cpio.gz. If initrd.size is smaller than the initramfs.cpio.gz file size, please increase the initrd.size value. Otherwise, the kernel will find this is a corrupted image and skip mounting the initramfs.

In this example, the patch reserves 32MB for initramfs.cpio.gz. Reserving 32MB may be too luxury but don't worry, this piece of memory will free after decompression complete and the initramfs has mounted.

 

Program the imx28_(ivt_)linux.sb to your booting media and power up the board. You should see the kernel will mount the initramfs as roofs after boot up.

 

 

3. Load initramfs from bootloader (Optional)

 

In the previous section, the boot stream linux_prep helps to load the kernel and initramfs image and run the kernel automatically. Optionally, you can also make use of the bootloader to load the kernel and initramfs.

 

To use the u-boot as bootloader, please apply the mx28_initramfs_u-boot-2009.08.patch and build the imx28_(ivt_)uboot.sb by the following commands

 

./ltib -p u-boot -f
./ltib -p boot_stream.spec -f

 

After a successful build, the initramfs image "initramfs.cpio.gz" is created. Use the following command to insert the u-boot header to this image for u-boot to load.


mkimage -A arm -O linux -T ramdisk -C none -a 0x40800000 -n "Root Filesystem" -d ./initramfs.cpio.gz ./initramfs.cpio.gz.uboot

 

The mkimage utility can be found under the u-boot directory "u-boot-2009.08/tools/".

Here the address 0x40800000 is the address where initramfs will be located. For i.MX28, the kernel will be always loaded at 0x40008000. Unless the kernel size is getting very large, usually there is no need to move the initramfs address.

 

Let us take the SD card boot as an example to continue. Use fdisk command and create the follow partitions on an SD card.


Command (m for help): p

Disk /dev/sdc: 255 MB, 255066112 bytes
64 heads, 32 sectors/track, 243 cylinders
Units = cylinders of 2048 * 512 = 1048576 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xb3f32f78

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1              16          64       50176   53  OnTrack DM6 Aux3
/dev/sdc2              65         127       64512    b  W95 FAT32
/dev/sdc3             128         243      118784   83  Linux

Command (m for help):


Here the beginning 16MB of the SD card is reserved for storing the master boot record, u-boot environment, uImage and initramfs.cpio.gz.uboot.
The first partition is used to store the imx28_(ivt_)uboot.sb. Partition 2 & 3 are optional for custom use.

Let's define the uImage to be stored at 128KB physical offset in the SD and the initramfs.cpio.gz.uboot is stored at 4MB offset to the SD.
Run the following to program the firmware images into the SD card.


## Clean up u-boot env
dd if=/dev/zero of=/dev/sdx bs=512 seek=2 count=254; sync
## Write u-boot
./sdimage -f rootfs/boot/imx28_ivt_uboot.sb -d /dev/sdx; sync
dd if=rootfs/boot/uImage of=/dev/sdx bs=512 seek=256; sync
dd if=initramfs.cpio.gz.uboot of=/dev/sdx bs=512 seek=8192; sync


Power up your board with the SD and you will see the autoboot countdown at the serial debug console. Hit any key to stop it. Review the boot environment by the "printenv" command.

 

MX28 U-Boot > printenv
bootargs=console=ttyAM0,115200n8
bootcmd=run bootcmd_SD; bootm ${loadaddr} ${rd_loadaddr}
bootdelay=3
baudrate=115200
ipaddr=192.168.1.103
serverip=192.168.1.101
netmask=255.255.255.0
bootfile="uImage"
loadaddr=0x42000000
nfsroot=/home/notroot/nfs/rootfs
bootargs_nfs=setenv bootargs ${bootargs} root=/dev/nfs ip=dhcp nfsroot=${serverip}:${nfsroot},v3,tcp fec_mac=${ethaddr}
bootcmd_net=run bootargs_nfs; dhcp; bootm
bootargs_mmc=setenv bootargs ${bootargs} root=/dev/mmcblk0p3 rw rootwait ip=dhcp fec_mac=${ethaddr}
bootcmd_mmc=run bootargs_mmc; mmc read 0 ${loadaddr} 100 3000; bootm
loadaddr=0x42000000
rd_loadaddr=0x42300000
bootargs_SD=setenv bootargs ${bootargs} rw gpmi
bootcmd_SD=run bootargs_SD; mmc read 0 ${loadaddr} 0x100 0x1800; mmc read 0 ${rd_loadaddr} 0x2000 0x4000
stdin=serial
stdout=serial
stderr=serial
ethact=FEC0
ver=U-Boot 2009.08-dirty (Mar 13 2013 - 18:43:19)

Environment size: 886/130044 bytes
MX28 U-Boot >


"bootargs_SD" simply setup the kernel command line.

"bootcmd_SD" run the "bootargs_SD" and read uImage from SD physical offset 128KB to address "loadaddr" and then read initramfs.cpio.gz.uboot from the SD physical offset 4MB to "rd_loadaddr".

"loadaddr" is 0x42000000 and "rd_loadaddr" is 0x42300000. These memory areas are generally not used by i.MX28 u-boot and are used here to hold the uImage and initramfs.cpio.gz.uboot. "loadaddr" and "rd_loadaddr" must be far apart enough so that the loaded images will not overlap.

The "bootcmd" run "bootcmd_SD", and use "bootm" commnad to boot the kernel. The first argument is the address where the kernel uImage is stored. The second argument is the initramfs u-image. This second argument can be omitted if initramfs is not used and in this case, kernel will expect a correct "root=" option in the kernel command line.

 

You can manually edit the boot environment or hardcode it in the include/configs/mx28_evk.h.

 

Reset your board and let it autoboot. You should see the initramfs will be mounted as rootfs as in section 2.

Original Attachment has been moved to: mx28_initramfs_imx-bootlets-src-10.12.01.patch.zip

Original Attachment has been moved to: mx28_initramfs_u-boot-2009.08.patch.zip

Labels (2)
10 Replies

4,664 Views
chris321
Contributor IV

Hello and thank you for this tutorial.

In the bootlet patch you have used absolute paths. This issn't right or?

[...]

-    zImage = "./zImage";

+    zImage="/home/pchan/SDK_source/mx28_1012_nand/ltib/rootfs/boot/zImage";

+    initramfs="/home/pchan/SDK_source/mx28_1012_nand/ltib/initramfs.cpio.gz";

[...]

best regards

Edit:


Hello again Peter


I have tried your step by step tutorial and I got a bootstream with integrated initramfs, thank you.

But I dont get it to boot from it. Please can you tell me your boot param cmdline ?

Mine are:

console=ttyAMA0,115200 root=/dev/ram0 rootfstype=ramfs initrd=0x40800000 ip=none gpmi init=sbin/init

But I got errors like this

[...]

[8.076007] VFS: Mounted root (ramfs filesystem) readonly on device 0:11.
[8.083648] devtmpfs: error mounting -2
[8.088680] Freeing init memory: 168K
[8.092951] Failed to execute sbin/init.  Attempting defaults...
[8.100317] Kernel panic - not syncing: No init found.  Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
[8.112861] [<c0014eac>] (unwind_backtrace+0x0/0xf4) from [<c047ccc0>] (panic+0x98/0x204)
[8.121094] [<c047ccc0>] (panic+0x98/0x204) from [<c047bfa0>] (kernel_init+0xc0/0xe4)
[8.128975] [<c047bfa0>] (kernel_init+0xc0/0xe4) from [<c000f2c8>] (ret_from_fork+0x14/0x2c)

Maybe the "initrd=0x40800000" is wrong. I got the address from the patched linux_prep/core/setup.c : params->u.initrd.start = 0x40800000;

The initramfs.cpio.gz is 6.6 MB (14,1 MB gunzipped) large. According to the patched setup.c the initramfs have 33 MB place. Here you can see my partitions, I think there is enough space for it.

   Gerät  boot. Anfang    Ende Blöcke   Id  System
/dev/sdb1           1      16   59487+   b  W95 FAT32
/dev/sdb2          16      31   56730   53  OnTrack DM6 Aux3
/dev/sdb3          31    1022 3747962+  83  Linux

Best Regards

Nachricht geändert durch Chris 321

0 Kudos

4,664 Views
PeterChan
NXP Employee
NXP Employee

Good catch! I shouldn't use absolute path in the patch.

I didn't modify boot parameter cmdline and just leave it as default.

You should not set "root=/dev/ram0 rootfstype=ramfs initrd=0x40800000". I think they are only required for initrd. For initramfs, the initramfs address is specified when running the mkimage.

Please read this link

Introducing initramfs, a new model for initial RAM disks - Linux For Devices Articles - Linux for De...

for the difference between initramfs and initrd.


Please also omit "init=sbin/init" in cmdline if you don't need to remount the rootfs to other media.

0 Kudos

4,665 Views
chris321
Contributor IV

with the standart cmdline  (except the console :smileywink: )

noinitrd console=ttyAMA0,115200 root=/dev/mmcblk0p3 rw rootwait ip=none gpmi

and no rfs on mmcblk0p3, ofcourse the kernel can't find the root @ /dev/mmcblk0p3

[    8.078378] List of all partitions:

[    8.082170] b300         3866624 mmcblk0  driver: mmcblk

[    8.087564]   b301           59487 mmcblk0p1 f129ae9b-01

[    8.093085]   b302           56730 mmcblk0p2 f129ae9b-02

[    8.098445]   b303         3747962 mmcblk0p3 f129ae9b-03

[    8.103945] No filesystem could mount root, tried:  ext3 ext2 ext4

[    8.110501] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,3)

[    8.119033] [<c0014eac>] (unwind_backtrace+0x0/0xf4) from [<c047ccc0>] (panic+0x98/0x204)

[    8.127267] [<c047ccc0>] (panic+0x98/0x204) from [<c0631d18>] (mount_block_root+0x218/0x25c)

[    8.135752] [<c0631d18>] (mount_block_root+0x218/0x25c) from [<c0631e30>] (mount_root+0xd4/0xf8)

[    8.144576] [<c0631e30>] (mount_root+0xd4/0xf8) from [<c0631f7c>] (prepare_namespace+0x128/0x18c)

[    8.153490] [<c0631f7c>] (prepare_namespace+0x128/0x18c) from [<c063131c>] (kernel_init_freeable+0x16c/0x1b0)

[    8.163444] [<c063131c>] (kernel_init_freeable+0x16c/0x1b0) from [<c047bee8>] (kernel_init+0x8/0xe4)

[    8.172630] [<c047bee8>] (kernel_init+0x8/0xe4) from [<c000f2c8>] (ret_from_fork+0x14/0x2c)

with the same cmdline and a rootfs on /dev/mmcblk0p3 the kernel loads the rootfs from there

and with the cmdline without root=XXX

noinitrd console=ttyAMA0,115200 rw rootwait ip=none gpmi

the kernel stops at

[    8.060459] Waiting for root device ...

so I had removed the "rootwait" param

so this is the cmdline

noinitrd console=ttyAMA0,115200 rw ip=none gpmi

and now he can't actually find some root

[    8.899387] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6

[    8.906915] Please append a correct "root=" boot option; here are the available partitions:

[    8.915490] b300         3866624 mmcblk0  driver: mmcblk

[    8.921007]   b301           59487 mmcblk0p1 16d99b46-01

[    8.926374]   b302           56730 mmcblk0p2 16d99b46-02

[    8.931887]   b303         3747962 mmcblk0p3 16d99b46-03

[    8.937534] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

[    8.945894] [<c0014eac>] (unwind_backtrace+0x0/0xf4) from [<c047ccc0>] (panic+0x98/0x204)

[    8.954127] [<c047ccc0>] (panic+0x98/0x204) from [<c0631ca4>] (mount_block_root+0x1a4/0x25c)

[    8.962608] [<c0631ca4>] (mount_block_root+0x1a4/0x25c) from [<c0631e30>] (mount_root+0xd4/0xf8)

[    8.971434] [<c0631e30>] (mount_root+0xd4/0xf8) from [<c0631f7c>] (prepare_namespace+0x128/0x18c)

[    8.980350] [<c0631f7c>] (prepare_namespace+0x128/0x18c) from [<c063131c>] (kernel_init_freeable+0x16c/0x1b0)

[    8.990305] [<c063131c>] (kernel_init_freeable+0x16c/0x1b0) from [<c047bee8>] (kernel_init+0x8/0xe4)

[    8.999488] [<c047bee8>] (kernel_init+0x8/0xe4) from [<c000f2c8>] (ret_from_fork+0x14/0x2c)

thats why I had tried the other way in my first post with

console=ttyAMA0,115200 root=/dev/ram0 rootfstype=ramfs initrd=0x40800000 ip=none gpmi init=sbin/init


Maybe the Kernel needs some extra configuration for initramfs support?

0 Kudos

4,664 Views
PeterChan
NXP Employee
NXP Employee

Hello Chris,

I have attached my .config and the boot log here. In the boot log, you can see that the kernel command line is just the default one. The image is prepared by just applying the mx28_initramfs_imx-bootlets-src-10.12.01.patch and follow the step 1 & 2 in this post.

0 Kudos

4,664 Views
chris321
Contributor IV

Thank you Peter,

you have an additional "-e" in the cmdline, it will be added with your patch but I lost it :smileywink:

You also have the kernel option BLK_DEV_INITRD enabled that I didn't had.

I also found some other options wich are not enabled, like

BLK_DEV_RAM

Now I got this error in the bootlog

INITRD: 0x40800000+0x02000000 overlaps in-use memory region - disabling initrd

0 Kudos

4,664 Views
PeterChan
NXP Employee
NXP Employee

The "overlaps in use-memory region" error may probably due to kernel size too large. By default, address space starting from 0x40008000 is reserved for kernel and address space starting from 0x40800000 is reserved for initramfs. If the kernel spans into 0x40800000, the error will occur. You can find out the kernel size from System.map. If this is really the case, you can modify the setup_initrd_tag() function in linux_prep and the linux(_ivt).bd to move this address.

You are also recommended to use a clean BSP to try this patch first.

0 Kudos

4,664 Views
chris321
Contributor IV

with a new clean BSP with kernel 2.6.35 it works, thank you Peter.

But there are two questions left :smileyhappy:

How can I get the kernel size out of the system.map? The last adress in it points to a address c04d97a8 (3 GB?)

I found something like c0008790 start_kernel but no end/stop.

And the other question, what is the difference for using an initramfs by force of of the bootlet patch

and the kernel option CONFIG_INITRAMFS_SOURCE where I can enter the path to the initramfs.cpio.gz ?

0 Kudos

4,664 Views
宗標廖
Contributor V

Hello chris321

I am now using freescale L3.0.35 BSP,and when I use initramfs,I have the same issues that you have met.

1)when I set  'root=/dev/ram0 rootfstype=ramfs initrd=0x40800000 ip=none gpmi init=sbin/init',

    it comes ' Failed to execute sbin/init.  Attempting defaults...'

2)when I omit these params,it comes ' VFS: Cannot open root device "(null)" or unknown-block(0,0)'

Can you give some advice.

Thank you very much!

0 Kudos

4,664 Views
rootb3r
Contributor II

I'm facing the same problem.

VFS: Mounted root (ramfs filesystem) on device 0:11.

Freeing init memory: 124K

Failed to execute /init. Attempting defaults...

Kernel panic - not syncing: No init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.

Backtrace:

[<8002b990>] (dump_backtrace+0x0/0x110) from [<802d69a8>] (dump_stack+0x18/0x1c)
r7:00000013 r6:80046b14 r5:800221c8 r4:803dbd58

[<802d6990>] (dump_stack+0x0/0x1c) from [<802d6a24>] (panic+0x78/0xfc)

[<802d69ac>] (panic+0x0/0xfc) from [<800275ec>] (init_post+0xb4/0xdc)
r3:00000000 r2:83c72d00 r1:83c72e00 r0:80359312

[<80027538>] (init_post+0x0/0xdc) from [<800084fc>] (kernel_init+0x12c/0x170)
r5:800221c8 r4:803daf40

[<800083d0>] (kernel_init+0x0/0x170) from [<80046b14>] (do_exit+0x0/0x6a4)
r5:800083d0 r4:00000000

Has anyone found a solution for this?

Regards.

0 Kudos

4,664 Views
PeterChan
NXP Employee
NXP Employee

The kernel size can be calculated by subtracting lowest address from the highest address in System.map. In your case, it is 0xC04d97a8 - 0xc0004000 which should be 5,068,712 bytes.

They are the same. Here the rootfs under LTIB will be mounted as rootfs by initramfs. You can also specify the initramfs path by the kernel option CONFIG_INITRAMFS_SOURCE. In LTIB, this kernel option CONFIG_INITRAMFS_SOURCE can be edited at

General setup  --->

    [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

         ()    Initramfs source file(s)