Running a rootfs from usb (Home Media)
In some circumstances it could be nice to run a rootfs from usbstick, for instance when you want to try to install and configure some packages, but you don't want to mess up the main fs. There are several ways to do that.
The commandline for the kernel is
elevator=cfq panic=20 root=/dev/sda1 console=ttyS0,115200 init=/linuxrc mem=64M poweoutage=yes
So it will run /linuxrc from sda1. /linuxrc is a script, so we can change it to our needs. Using pivot_root we can switch to another root, if available. In our case we want to mount an usb device, so we'll have to load the necessary modules, wait for the stick to settle, mount it, switch root, and pass the execution to this rootfs. A sample script:
#!/bin/sh # This file is created by /csb/product/hmed/scratch/mods/init/linuxrc.sh !! DO NOT edit !! # Unset variable exported by sh. unset PWD # Try the same paths as the kernel would. PATH=/sbin:/etc:/bin:/usr/bin:/usr/sbin # Load the necessary modules and do the mounts to be able to mount an usb stick mount -t proc proc /proc modprobe usb_storage modprobe usbcore modprobe ehci_hcd mount -t usbfs usb /proc/bus/usb # Wait for the stick to 'come up' sleep 10 # Mount usb stick: mknod /dev/sdb1 b 8 17 mkdir -p /mnt/sdb1 if mount -t ext3 /dev/sdb1 /mnt/sdb1 ; then if [ -x /mnt/sdb1/sbin/init ] ; then mount --move /proc /mnt/sdb1/proc # Pivot cd /mnt/sdb1 mkdir -p oldroot pivot_root . oldroot # Pass execution to new rootfs exec /sbin/init fi # else: no /sbin/init on the stick fi # else no stick to be mounted # Pass execution to the original rootfs exec /sbin/init
Creating a suitable rootfs
For us it's important to bring up the network, being the only interface to the box (Unless you've got serial access). So we need to load the driver module gmac.ko. This module needs a userspace helper to pass the NIC's firmware (/lib/firmware/gmac_copro_firmware). Further this module expects the macaddress as a parameter during load. Fortunately Debian can do this out-of-the-box. In /etc/modules you can specify modules to load, and add load parameters. Further the package 'udev' will handle the request for firmware. By default udev will be started before the modules in /etc/modules will be loaded.
There is a kernel module thermAndFan.ko which handles this. Add it to /etc/modules to start it automatically.
Unfortunately the udev from squeeze doesn't work on kernels older than 2.6.27. So when running squeeze you'll have to provide your own helper program for the NIC firmware, or use a newer kernel than the stock one (188.8.131.52)
Creating a filesystem:
su # install cdebootstrap apt-get update apt-get install cdebootstrap # prepare stick mke2fs -j /dev/sdb1 mount /dev/sdb1 /media # get a clean lenny cdebootstrap lenny /media http://ftp.us.debian.org/debian # chroot the new rootfs mount proc /media/proc -t proc mount --bind /var /media/var chroot /media /bin/sh # set a root password passwd # install udev and dropbear # (you could also use openssh or telnetd instead of dropbear, # but dropbear is 700k, and the other are several MB's) apt-get update apt-get install dropbear udev # leave chroot exit umount /media/proc umount /media/var # copy some config files cp /etc/inittab /media/etc/ cp /etc/network/interfaces /media/etc/network/ cat /etc/modules >>/media/etc/modules cp /etc/resolv.conf /media/etc/ # copy modules and firmware cp -r /lib/modules/* /media/lib/modules/ mkdir /media/lib/firmware cp -r /lib/firmware/* /media/lib/firmware/
This rootfs should be able to get booted by /linuxrc above
Usage of reloaded.ko. This is a kernelmodule which gives you the possibility to load runtime another kernel, pass an initrd and a commandline, and boot it. In our case we could use the stock kernel, create an initrd which loads the necessary modules for usb devices, and let it mount the stick and switch_root to it. The other way is to use a kernel with usb possibilities build in, and just provide a cmdline which tells this kernel to boot from the stick. I compiled a kernel with usb support build in, and with a bunch of modules which Iomega forgot to supply (usbv6, nfs, usb sound, ...). You can download it here. When you extract reload-kernel.tgz to the builded rootfs, it will install both the kernel modules and reloaded.ko, and a reload script. You can reload the kernel by
su cd /mountpoint/of/usbdevice/boot ./reload.sh
The box will reboot instantaneously, so make sure it was not doing something important.