28 June 2010

multi-boot in embedded device

My device have U-Boot boot loader and 64MB cavium-nand flash (for "kernel" and "filesystem"). How can i support dual-boot in it???

I have decided to format the NAND flash like this:
/dev/mtd0 : 0x00000000-0x00300000 :  3 MB : "kernel1"
/dev/mtd1 : 0x00300000-0x01300000 : 16 MB : "cramfs1"

/dev/mtdblock2 : 0x01300000-0x01700000 : 4 MB : "jffs2"
/dev/mtdblock3 : 0x01700000-0x01800000 : 1 MB : "nvram"

/dev/mtd4 : 0x01800000-0x01b00000 : 3 MB : "kernel2"
/dev/mtd5 : 0x01b00000-0x02b00000 : 16 MB : "cramfs2"
And made device soft link like:
/dev/mtd-kernel     -> mtd0
/dev/mtd-rfs -> mtd1

/dev/mtd-kernel-alt -> mtd4
/dev/mtd-rfs-alt -> mtd5
How does U-Boot does the boot process:
1. Read kernel from NAND to RAM
2. un-compress the kernel to RAM
3. execute kernel

Ex:-
bootcmd=nand read <TO> <FROM> <SIZE>; \
gunzip <FROM> <SIZE> <TO> <MAX SIZE>; \
bootoctlinux <NEW FROM> root=/dev/mtdblock1 ${mtdparts}

bootcmd=nand read 0x500000 0x00000 0x300000; \
gunzip 0x500000 0x300000 0x2800000 0xf00000; \
bootoctlinux 0x2800000 root=/dev/mtdblock1 ${mtdparts}

Solution:
1. get the current kernel information from U-Boot parameter
2. burnel kernel image in alternate locations (mtd0, mtd5)
3. update U-Boot parameter

Ideal U-Boot parameters:
bootcmd=run boot1
altbootcmd=run boot2

boot1=namedfree __tmp_reserved_bootloader; \
nand read 500000 00000 300000; \
run boot11
boot2=namedfree __tmp_reserved_bootloader; \
nand read 500000 1800000 300000; \
run boot21

mtdparts=mtdparts=cavium-nand:3072k(kernel1),16384k(cramfs1), \
4096k(jffs2),1024k(nvram), \
3072k(kernel2),16384k(cramfs2),3072k()

boot11=gunzip 0x500000 300000 0x2800000 0xf00000; \
bootoctlinux 2800000 root=/dev/mtdblock1 ${mtdparts}
boot21=gunzip 0x500000 300000 0x2800000 0xf00000; \
bootoctlinux 2800000 root=/dev/mtdblock5 ${mtdparts}
firmware upgrade script:
#!/bin/sh

bootcmd=`bootenv -d bootcmd`
altcmd=`bootenv -d altbootcmd`

if [ "$bootcmd" == "run boot1" ];
then
kernelimage="/dev/mtd-kernel-alt"
rfsimage="/dev/mtd-rfs-alt"
else
kernelimage="/dev/mtd-kernel"
rfsimage="/dev/mtd-rfs"
fi

# Kernel in mtd-kernel
echo "Erasing the kernel image in $kernelimage"
echo -n "Flashing in the new kernel image. Please wait..."

# Root File System in mtd-rfs
echo "Erasing the root f/s image in $rfsimage"
echo -n "Flashing in the new root f/s image. Please wait..."

if [ "$bootcmd" == "run boot1" ];
then
echo "Setting new bootcmd as run boot2 and backup as run boot1"
bootenv -s bootver "$upgradeVersion"
bootenv -s bootcmd "run boot2"
bootenv -s altbootver "$existingVersion"
bootenv -s altbootcmd "run boot1"
else
echo "Setting new bootcmd as run boot1 and backup as run boot2"
bootenv -s bootver "$upgradeVersion"
bootenv -s bootcmd "run boot1"
bootenv -s altbootver "$existingVersion"
bootenv -s altbootcmd "run boot2"
fi

/bin/sync
/bin/sleep 2

# Reboot
exec /sbin/init -r


Reference:

1 comment:

  1. Based on your kernel command line, I think the code in your kernel is not found in mainline. Do you have sources? I'm looking for cavium-nand MTD partitioning support.

    Mine (2.6.21.5) boots with this:
    argv[3]: mtdparts=cavium-nand:2240k(kernel1),12800k(cramfs1),1664k(jffs2),1024k(nvram),2240k(kernel2),12800k(cramfs2)

    I've poked around a lot, and I believe jffs2 and other parts were backported, or non mainline patches but later became mainline patches. The missing piece in the puzzle appears to be mtdparts=cavium-nand

    $ egrep -C 2 -ia 'cavium.nand' vmlinux.64 | tr "\0" " " | sort | uniq
    <7>Bad block table at page %d, version 0x%02X
    cavium_nand NAND found in bootbus %d bit base=%x
    cavium-nand Unable to allocate NAND MTD dev structure.
    command line static <5>Using %s partition definition

    i'm unable to find the cavium-nand signatures in the latest 2.6 kernel.

    ReplyDelete