I'm not sure if anyone on the list has tried this as of yet, but I've
been looking for a way to replace the kernel in flash at runtime.
Presently, all of the Technologic documentation says that you need to
replace kernel images from the RedBoot command line. This grows to be a
bit cumbersome when boards are in production or operation because it
requires an immediate physical presence of a technician in the field,
just to type a few simple keystrokes. In many cases though, the boards
will be at quite a distance from eachother, so direct interaction
becomes impractical.
My strategy was this:
1) if the kernel is loaded into SDRAM, that means it is not XIP (execute
in place). -- confirmed -- NAND flash is too slow for general
execution... also, cat /proc/iomem shows it resides in RAM at
runtime. Therefore the kernel section in flash must be writeable!
2) find out the proper flash 'partition' to write to
3) determine the exact offset to start writing from above partition
4) use the proper utility to write new kernel image to flash
5) reboot && verify that the kernel image was properly updated.
I haven't fully tested what I came up with yet because I wanted to ask
if anyone else has attempted this, and if so, what parameters are
important?
Lennert and / or Jessie, I am guessing that you probably know the answer
to this, but I wanted to post for everyone else's benefit too.
Please keep in mind that I do not want anyone to try this on a mass
scale until it's been confirmed to work, especially because the MTD
people have dropped support for the 2.4 kernel.
One would _think_ that it would be possible to overwrite the kernel
image (vmlinux) which exists in flash memory using the 'dd' command. For
example,
dd if=zImage of=/dev/mtd/X obs=8 seek=<some_offset>
However, this will ONLY work if the write areas being addressed have
zero bad blocks. Otherwise, since the NAND devices are sequential, there
will be one block of data missing. Also, it assumes that the NAND device
does not require a prior erase cycle.
NAND devices, which are increasingly cheaper to manufacture than NOR
devices, are not gauranteed to have zero bad blocks upon shipment.
Needless to say, assuming there are zero bad blocks is not the best idea.
The 'dd' utility does not currently take those considerations into
account when writing to flash devices. Thus, the good folks at
http://www.linux-mtd.infradead.org wrote up block dumping / writing
utilities specifically to cover this gap (nanddump / nandwrite).
The nanddump / nandwrite, as well as a slew of other MTD utilities can
be obtained from http://www.linux-mtd.infradead.org/source.html . You
will need to use "git" unless you find a snapshot somewhere.
OK, SO - to re-image the kernel section in flash memory, it's a good
idea to make sure that the zImage binary does not exceed the 'partition'
size that RedBoot has allocated for it.
###################################################
#!/bin/sh
#
# upgrade_kernel_in_flash.sh
#
# Assume $1 is 'zImage'
# my actual kernel size was 0xCB7FF ... RedBoot says
# that the partition size is 0xCC000 so i assume that
# is the upper bound. 0xCC000 (hex) = 835,584 (dec)
allowed_size=835584
# Arbitrary, but mainly to prevent stupid mistakes
min_size=100000
img_size=`wc -c $1`
# Probably better to write a usage() function
if [ ! $# -eq 1 ] || [ "$1" == "--help" ]; then
echo "Usage: $0 <filename>"
exit 1
else
if [ ! -f $1 ]; then
echo "$1 is not a regular file"
exit 2
else
if [ $img_size -ge $allowed_size ] ||
[ $img_size -lt $min_size ]; then
echo "$1 is > $allowed_size or < $min_size"
exit 3
else
# go ahead and do a 'nandwrite' operation
# (will fill in later)
# exit $?
fi
fi
fi
###################################################
Next, to locate the kernel in flash memory, I did the following:
RedBoot> fis list
Name FLASH addr Mem addr Length Entry point
(reserved) 0x60000000 0x60000000 0x01D04000 0x00000000
RedBoot 0x61D04000 0x61D04000 0x00040000 0x00000000
vmlinux 0x61D44000 0x00218000 0x000CC000 0x00218000
RedBoot config 0x61FF8000 0x61FF8000 0x00001000 0x00000000
FIS directory 0x61FFC000 0x61FFC000 0x00004000 0x00000000
You should notice that the start address of the kernel image is
0x61D44000. This translates to a 0x40000 offset from the 'RedBoot'
partition. Now on the board, if you check out
$ cat /proc/mtd
dev: size erasesize name
mtd0: 00004000 00004000 "TS-BOOTROM"
mtd1: 01d00000 00004000 "Linux"
mtd2: 002fc000 00004000 "RedBoot"
You'll notice that the RedBoot partition corresponds to /dev/mtd/2 (char
device) which is subsequently related to /dev/mtdblock/2 (block device).
I also went a bit further than this for paranoia's sake, and performed a
hexedit on the most recent kernel image that I had flashed my board
with. The first several bytes of the kernel image were:
$ hexedit zImage
00000000 00 00 A0 E1 00 00 A0 E1 00 00 A0 E1 00 00 A0 E1
00000010 00 00 A0 E1 00 00 A0 E1 00 00 A0 E1 00 00 A0 E1
00000020 02 00 00 EA 18 28 6F 01 ...
Next, I NFS mounted my laptop's /usr/debian_root directory from the
board and dumped the entire /dev/mtd/2 partition out to a file on my
laptop's hard disk. Below, the -o option says to omit OOB (out of bound)
data and the -f just specifies an output filename.
$ mount -t nfs 192.168.2.201:/usr/debian_root /mnt/nfs
$ nanddump -o -f /mnt/nfs/dev_mtd_2.bin /dev/mtd/2
After that, to make sure I had a matching memory location, I did a
hexedit on the image i just wrote to my laptop.
$ hexedit /usr/debian_root/dev_mtd_2.bin
00000000 43 52 55 53 FD 03 00 EA 18 F0 9F E5 18 F0 9F E5 CRUS...
00000010 18 F0 9F E5 18 F0 9F E5 00 00 00 00 18 F0 9F E5
00000020 18 F0 9F E5 FC 0F 00 00 30 91 00 00 54 91 00 00
00000030 80 91 00 00 9C 91 00 00 00 00 00 00 B4 92 00 00
00000040 7C 92 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ...
Obviously, I had some searching to do... so I used hexedit's built in
hexa-search to look for a signature from my kernel image :) This just
requires a '/' keystroke.
Hexa string to search: () 020000EA1828
and voila! I found the start point of my kernel (by hitting up a couple
of times)!
...
00040000 00 00 A0 E1 00 00 A0 E1 00 00 A0 E1 00 00 A0 E1
00040010 00 00 A0 E1 00 00 A0 E1 00 00 A0 E1 00 00 A0 E1
00040020 02 00 00 EA 18 28 6F 01 ...
Sure enough, it was at the same 0x40000 byte offset from the 'RedBoot'
partition, just like RedBoot said (duh!).
So, I updated the shell script from before. The -a option specifies
automatic placement of OOB data. The -s option specifies an effective
'seek' position to start at.
###################################################
...
# go ahead and do a 'nandwrite' operation
# kernel image should start at 0x40000
# 0x40000 (hex) = 262144 (dec)
nandwrite -a -s 262144 /dev/mtd/2
exit $?
...
###################################################
I'm pretty ready to go here, but I wanted to see what everyone thought.
Do I need any other options? The options available are below.
$ nandwrite --help
Usage: nandwrite [OPTION] MTD_DEVICE INPUTFILE
Writes to the specified MTD device.
-a, --autoplace Use auto oob layout
-j, --jffs2 force jffs2 oob layout (legacy support)
-y, --yaffs force yaffs oob layout (legacy support)
-f, --forcelegacy force legacy support on autoplacement enabled
mtd device
-n, --noecc write without ecc
-o, --oob image contains oob data
-s addr, --start=addr set start address (default is 0)
-p, --pad pad to page size
-b, --blockalign=1|2|4 set multiple of eraseblocks to align to
-q, --quiet don't display progress messages
--help display this help and exit
--version output version information and exit
Any and all suggestions would be very well appreciated from myself but
hopefully others who find this useful.
~/Chris
------------------------ Yahoo! Groups Sponsor --------------------~-->
You can search right from your browser? It's easy and it's free. See how.
http://us.click.yahoo.com/_7bhrC/NGxNAA/yQLSAA/CFFolB/TM
--------------------------------------------------------------------~->
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/ts-7000/
<*> To unsubscribe from this group, send an email to:
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
|