Reloaded

Introduction
A Berlin-based developer named "fonz" created a kernel module for the DNS-323 called 'reloaded.ko', with the function to reboot the system with a different kernel, rootfs and/or initramfs. This module has been ported to the NSA-220, and is for download here

Booting your own kernel
Let's say you want IPv6. Using the GPL sources provided by ZyXEL it is easy to build the needed kernelmodules, but they don't load due to unresolved functions. Using reloaded.ko I could compile a kernel with IPv6 enabled, and use usb_key_func.sh to load it: if cat /proc/cmdline | grep reloaded ; then # The kernel is already reloaded # Insert traditional usb_key_func.sh code here exit 1 fi touch /tmp/initramfs CMDLINE=` cat /proc/cmdline ` sync /sbin/insmod /mnt/parnerkey/reloaded.ko kernel=/mnt/parnerkey/zImage initrd=/tmp/initramfs cmdline="$CMDLINE reloaded" echo Oops! Reloading failed. Check dmesg exit 0 This will reboot the box with the new kernel. (BTW, this doesn't need to be a Linux kernel. In theory you could provide a NetBSD kernel either, given you can build one with the needed drivers)
 * 1) !/bin/sh
 * 1) create an empty initramfs
 * 1) If we advance till here, something went wrong.

Booting your own rootfs
Let's say you want to use a modificated firmware. Then you *could* copy the firmware rootfs to usbstick, and load it using usb_key_func.sh (the usb device needs to be formatted ext2/3 for this): if cat /proc/cmdline | grep reloaded ; then # The kernel is already reloaded # Insert traditional usb_key_func.sh code here exit 1 fi usbdev=` cat /proc/mounts | grep /mnt | grep -v ram | awk '{print $1}' ` mountpoint=` cat /proc/mounts | grep $usbdev | awk '{print $2}' ` if [ ! -f $mountpoint/zImage ] ; then dd if=/dev/mtd0 of=$mountpoint/zImage fi if [ ! -f $mountpoint/etc/Zy_Private ] ; then dd if=/dev/mtd1 of=$mountpoint/firmware mkdir /tmp/firmware mount $mountpoint/firmware /tmp/firmware cp -pr /tmp/firmware/* $mountpoint umount /tmp/firmware fi touch /tmp/initramfs for cmd in ` cat /proc/cmdline `; do 	case $cmd in 		root=*) 			CMDLINE="$CMDLINE root=$usbdev" 			;; 		rootfstype=*) # Not needed, and maybe even contra-productive ;; 		*) 			CMDLINE="$CMDLINE $cmd" 			;; 	esac done CMDLINE="$CMDLINE rootdelay=10" /sbin/insmod $mountpoint/reloaded.ko kernel=$mountpoint/zImage initrd=/tmp/initramfs cmdline="$CMDLINE reloaded" echo Oops! Reloading failed. Check dmesg exit 0 This didn't work too well for me. Starting Samba costs ages, and after that it doesn't work either. But, hey, it's only an example.
 * 1) !/bin/sh
 * 1) find the current device:
 * 1) find current mountpoint
 * 1) check if we already have a kernel:
 * 1) check if we already have a copy of the firmware:
 * 1) Create an empty initramfs
 * 1) generate a commandline
 * 1) add a delay, needed for USB device
 * 1) If we advance till here, something went wrong.

Using your own initramfs
Let's say you want to load your rootfs from your internal RAID1 array. Then you can't just use root=/dev/md0 in your commandline, because you'll have to assemble the array first. That can be done in initramfs. Create a root-tree, somewhere, containing a subdirectory bin, sbin, etc, proc, tmp, var, dev, lib, mnt and firmware. Fill them with the absolute minimum amount of needed files. (You can find a statically linked version of busybox here). Create the busybox symlinks, (at least mount, umount, cd, cp, exec and switch_root) and make sure that they link to /bin/busybox or busybox, and not /your/own/path/to/bin/busybox. Further you'll need at least the device nodes /dev/sda2, /dev/sdb2, /dev/md0, /dev/ttyS0 and the firmware /sbin/mdadm Then in the root of your root-tree create an executable script init. For instance echo starting init... mount -t proc /proc /proc mount -t sysfs sysfs /sys mount /dev/mtd1 /firmware mount --bind /firmware/lib /lib /sbin/mdadm --assemble /dev/md0 /dev/sda2 /dev/sdb2 mount /dev/md0 /mnt umount /lib umount /firmware mount --move /proc     /mnt/proc mount --move /sys      /mnt/sys mount -t usbfs usbfs   /mnt/proc/bus/usb cd /mnt exec switch_root -c /dev/ttyS0. /sbin/init
 * 1) !/bin/sh
 * 1) make /lib available for mdadm
 * 1) assemble and mount raidarray
 * 1) don't need /lib anymore
 * 1) move mounts to new root

Then use cpio and gzip to create the initramfs. I wrote a script for that: if [ "$#" != "2" ] ; then echo usage $0  exit 0 fi cd $1 find. | cpio -H newc -o > /tmp/initramfs.cpio cd .. cat /tmp/initramfs.cpio | gzip > $2 rm /tmp/initramfs.cpio
 * 1) !/bin/sh

Now you can provide this initramfs instead of the empty ony in above scripts.

Putting it all together
Debian without need to flash