WGT634U_USB_root
Clean USB pivot_root for WGT634U and OpenWrt (Kamikaze).
The general idea is to create a root filesystem on a usb storage device / partition, via standard OpenWrt install. Then to flash the wgt634u with a squashfs based image that has the requisite kernel modules to recognize USB storage devices and their partitions and to mount a FAT or ext2 filesystem (other are possible) as the root filesystem (via pivot_root) in /etc/preinit. The candidate usb file systems are tested for some basic directories and files before a pivot_root is done from the squashfs (which becomes /rom) to /usb (which becomes, duh, /). No jffs filesystem is ever mounted. Under this paradigm, the on-board flash is never written to during normal device operation. I take /tmp out of RAM (I opt for RAM, not for fast /tmp). /etc/inittab is altered to run /etc/init.d/rcK which unmounts filesystems and prevents unclean restarts.
In the case where a USB storage device with a compatibale filesystem is not present at initialization, /etc/preinit will keep scanning /dev/scsi (or some specified directory) for a suitable host, bus, target, lun, part combination. When a mountable filesystem is found, the filesystem type is detected (for fat and ext2) and a filesystem check is run, before the target is mounted read & write. The kernel will probably panic if the USB device with the root partition is removed while the system is running (I didn't try).
This has been tested on: OpenWrt (Kamikaze) release 3535
- Get fresh source & configure it for WGT634U w/ minimal modules for USB storage host and ext2 & FAT filesystems:
- Select '*' (not 'M'!) for the following items:
- Target System (Broadcom BCM47xx/53xx [2.6])
- OpenWrt Package Selection --->
lsusb # very useful
- FileSystems related --->
- dosfstools # for mkdosfs
- e2fsprogs # for e2fsck and mke2fs
- util-linux --->
- fdisk # very useful
- swap-utils # for swap, untested
- Kernel Configuration / Device Support --->
- Filesystems support --->
- kmod-fs-vfat # for vfat fs support
- kmod-fs-ext2 # for ext2 fs support
- others? untested but useful!
- Native Language support --->
- kmod-nls-base # for fat and vfat
- kmod-nls-cp437
- # select the correct one for you
- USB support --->
- kmod-usb-core # need usb host support
- kmod-usb-uhci
- kmod-usb-ohci
- kmod-usb2
- kmod-usb-storage # for mass storage devices
- Save your configuration. Build it with:
- Install the squashfs image in bin. For 3535 it is openwrt-wgt634u-2.6-squashfs.bin in the bin directory. I did it via CFE and a serial console. Like so (your hwaddr, ipaddr, etc. will differ as will the bytes read and written - (see the WGT634U hardware page at openwrt.org):
CFE> ifconfig eth0 -auto
et0: link down
Device eth0: hwaddr 00-00-C0-FF-EE-00, ipaddr 192.168.0.103, mask 255.255.255.0
gateway 192.168.0.1, nameserver 69.69.69.69, domain foo.bar.
*** command status = 0
CFE> flash -noheader 192.168.0.2:openwrt-wgt634u-2.6-squashfs.bin flash0.os
Reading 192.168.0.2:openwrt-wgt634u-2.6-squashfs.bin: Done. 1806336 bytes read
Programming...done. 1806336 bytes written
*** command status = 0
- Reboot the unit. It will boot kernel from flash and root from squashfs. Then it will run firstboot and create a complete jffs filesystem in flash for 'permanent storage'. Plug in a usb storage device (I used a couple of old (backed up) 16 and 32 MB flash sticks - all with a single filesystem on them). Wait while the usb drivers find, recognize and initialize the storage device. (What happens when it doesn't work? I don't know, haven't had that happen with tested devices.) On the serial console, I saw the following to signify a '32MB' flash stick device was working:
usb 2-1: new full speed USB device using ohci_hcd and address 3
usb 2-1: configuration #1 chosen from 1 choice
scsi1 : SCSI emulation for USB Mass Storage devices
Vendor: Generic Model: USB Flash Drive Rev: %z!Y
Type: Direct-Access ANSI SCSI revision: 02
SCSI device sda: 64128 512-byte hdwr sectors (33 MB)
sda: Write Protect is off
sda: assuming drive cache: write through
SCSI device sda: 64128 512-byte hdwr sectors (33 MB)
sda: Write Protect is off
sda: assuming drive cache: write through
/dev/scsi/host1/bus0/target0/lun0: p1
sd 1:0:0:0: Attached scsi removable disk sda
- Note the device it reports (in my case: /dev/scsi/host1/bus0/target0/lun0: p1 - which is /dev/scsi/host1/bus0/target0/lun0/part1). On 3554 it was /dev/scsi/host0 not /dev/scsi/host1. (Might have to do with module load order?) Do something clever in your serial console shell:
usb_root_device=/dev/scsi/host1/bus0/target0/lun0/part1
- Optional: Create a new filesystem (and possibly a partition table) on the device. I do this. Mostly as another check to make sure all the utilities to maintain a filesystem are installed. W/ fdisk, I initialize a new partition table and create a new partition. That partition's type should be 83 if you intend to use ext2 or one of the FAT types (types depending on device size?) for a FAT filesystem. Make filesystems (mke2fs $usb_root_device OR mkdosfs $usb_root_device).
- Mount the filesystem on the storage device. Make a /usb directory to mount your storage device:
- Mount it. To test that your mount auto type checking is working, DO NOT specify the filesystem type. If mount cannot autodetermine it now, it will not be able to at boot.
mount $usb_root_device /usb
- Now you need to copy the base filesystem from squashfs and jffs to your usb filesystem. This is tricky for a few reasons: most files in your jffs filesystem are sym links to your read only filesystem, firstboot creates some files that are only on jffs, and you have to do it by hand. I found it is easier to copy from /rom than from /. I did something like:
cd /usb
# directory stubs
mkdir proc
mkdir sys
mkdir dev
mkdir rom
# copy from from squashfs
mkdir bin
cp -a /rom/bin/* bin
mkdir etc
cp -a /rom/etc/* etc
mkdir usr
cp -a /rom/usr/* usr
mkdir lib
cp -a /rom/lib/* lib
mkdir sbin
cp -a /rom/sbin/* sbin
# copy from jffs
mkdir tmp
cp -a /tmp/* tmp
mkdir var
cp -a /var/* var
cp /etc/config etc
# do some final preparations on your new root filesystem
chmod oug+rwxt /tmp
# umount some filesystems that the kernel mounts or are required by preinit
# from /rom
cat << EOF >> etc/init.d/S99done
# umount old dev, proc and usbfs
umount /rom/proc/bus/usb
umount /rom/proc
umount /rom/dev
EOF
- To have init unmount filesystems cleanly and remount root filesystem readonly before halting, into etc/init.d/rcK put:
#!/bin/sh
# umount dev, proc, sys and usbfs
usb_root_device=`mount | awk '{ if ($3 == "/") print $1 }'`
echo "unmounting memory based filesystems"
umount /sys
umount /dev/pts
umount /proc/bus/usb
echo "remounting root in read only mode"
mount $usb_root_device / -o remount -o ro
echo "halting system"
/sbin/halt
- Also, alter inittab to call your kill script:
cat << EOF > inittab
::sysinit:/etc/init.d/rcS
::shutdown:/etc/init.d/rcK
tts/0::askfirst:/bin/ash --login
#tts/1::askfirst:/bin/ash --login
EOF
- Remove anything that could write to flash and clobber CFE (paranoia brick defense precautions):
\rm /usb/bin/firstboot /usb/sbin/mount_root /usb/etc/preinit /usb/sbin/mtd /usb/sbin/jffs2root
- Once you you are sure you have copied the relevant parts of the filesystem structure, unmount the usb storage device's partition(s). I recommend making a tar image of the usb device (on another machine). This way you can quickly just reformat the device and untar the archive for a fresh OpenWrt install.
- Now make a new flash image (openwrt-wgt634u-2.6-squashfs.bin) that has a different /etc/preinit (and some other minor paranoia brick defense changes). To do this, go into your build root directory, i.e.
trunk/openwrt/build_mipsel/root (where you previously built Kamikaze):
cd trunk/openwrt/build_mipsel/root
# paranoia brick defense precautions
\rm bin/firstboot sbin/mount_root etc/preinit sbin/mtd sbin/jffs2root
# make mount point for usb
mkdir usb
# copy your own preinit to etc/preinit
cat << EOF > etc/preinit
#!/bin/sh
# dacb's preinit to pivot_root to USB
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
# not sure if this is strictly necessary, but the usb modules like usbfs
# and it gives us someplace specific to look for usb storage devices
mount none /proc -t proc
# this allows your system to boot from ext2 or fat - I use ext2, but fat
# is nice if you want to drop the USB device into a windows box (I guess)
# if your root is ext2
insmod ext2
# if your root is fat/vfat
insmod nls_base
insmod fat
insmod vfat
# load modules for usb storage
insmod usbcore
insmod ohci-hcd
insmod uhci-hcd
insmod ehci-hcd
insmod scsi_mod
insmod sd_mod
insmod usb-storage
# find a suitable USB filesystem: assemble a list of devices available
# using lsusb might be better than searching for devices?
# first wait until the scsi device tree is created
usb_device_search_start=/dev/scsi
echo "waiting for usb storage devices (in device tree $usb_device_search_start)"
while ! -d $usb_device_search_start ; do
sleep 5
echo "still waiting for usb storage devices (in device tree $usb_device_search_start)"
done
echo "found base of usb storage device tree at $usb_device_search_start"
# now search the scsi device tree for filesystem device files
find_usb_storage_devices () {
usb_storage_devices=""
usb_scsi_hosts=`\ls $usb_device_search_start`
if ! -z $usb_scsi_hosts ; then
usb_storage_devices=`\ls $usb_device_search_start/*/*/*/*/part*`
echo "list of found usb storage device partition files: $usb_storage_devices"
else
echo "no scsi hosts found in $usb_device_search_start, retrying in 5 seconds"
sleep 5
fi
}
find_usb_storage_devices
while -z $usb_storage_devices ; do
echo "unable to find any suitable storage devices in $usb_device_search_start, retrying in 5 seconds"
sleep 5
find_usb_storage_devices
done
# go through list of usb storage devices and see if any are possible roots, use first one
find_usb_root_device () {
found_usb_root_device=0
for usb_root_device in $usb_storage_devices; do
echo "trying to mount $usb_root_device on /usb in readonly mode"
mount $usb_root_device /usb -o ro
\ls -l /usb
# is there an indiciation this partition has enough of a filesystem to be our new root?
if [ -d /usb/bin ] && [ -d /usb/etc ] && [ -d /usb/sbin ] && [ -x /usb/sbin/init ] && [ -d /usb/usr ] && [ -d /usb/var ] && [ -d /usb/tmp ]; then
echo "found suitable USB storage device w/ filesystem that looks like root: $usb_root_device"
found_usb_root_device=1
umount /usb
break
fi
# if the mount failed, so will this, oh well...
echo "trying to unmount /usb"
umount /usb
done
}
find_usb_root_device
if $found_usb_root_device = 0 ; then
# final catch
while 1 ; do
echo "unable to find suitable USB storage device w/ filesystem, waiting 10 seconds before retry"
sleep 10
find_usb_storage_devices
if ! -z $usb_storage_devices ; then
find_usb_root_device
if $found_usb_root_device = 1 ; then
break;
fi
fi
done
fi
# check and mount base filesystem
echo "determining filesystem type on $usb_root_device and checking filesystem"
# this would be easier with 'file' but we don't have it and neither does busybox
# this might be dangerous - determining filesystem type by trying to mount specific
# types (read only) - if it succeeds the filesystem type is known and a check is done
if mount -t ext2 $usb_root_device /usb -o ro ; then
umount /usb
# if your filesystem is ext2
echo "$usb_root_device is ext2"
e2fsck -y $usb_root_device
elif mount -t msdos $usb_root_device /usb -o ro ; then
umount /usb
# if your filesystem is fat check it
echo "$usb_root_device is fat"
dosfsck -y $usb_root_device
else
echo "giving up without checking filesystem"
fi
# mount our new root
mount $usb_root_device /usb -o rw
# pivot root - mount /usb as root and our old root as /rom under the usb partition
pivot_root /usb /usb/rom
# umount old dev, proc and usbfs
# doesn't work here (why?), add to end of /etc/init.d/S99done on usb root filesystem
#umount /rom/proc/bus/usb
#umount /rom/proc
#umount /rom/dev
# mount new dev, proc, sys and usbfs
mount none /proc -t proc
mount none /dev -t devfs
mkdir -p /dev/pts
mount none /dev/pts -t devpts
mount none /proc/bus/usb -t usbfs
mount none /sys -t sysfs
exec /sbin/init
EOF
chmod +x etc/preinit
cd trunk/openwrt
make target/install
- Check your image by looking at the tgz counterpart, quickly:
tar -tvzf build_mipsel/linux-2.6-brcm/root.tar.gz | more
- In particular, make sure ./etc/preinit is the correct size, also verify that (paranoia brick defense) ./bin/firstboot, ./sbin/mount_root, ./sbin/jffs2root and ./sbin/mtd are absent.
- Flash the image via CFE and tftp. Reboot. Enjoy - never have your system writing to flash again! See stuff below:
root@OpenWrt:/# df
Filesystem 1k-blocks Used Available Use% Mounted on
/dev/scsi/host0/bus0/target0/lun0/part1 31029 4665 24762 16% /
root@OpenWrt:/# mount
(null) on /rom type squashfs (ro)
/dev/scsi/host0/bus0/target0/lun0/part1 on / type ext2 (rw,nogrpid)
none on /proc type proc (rw)
none on /dev type devfs (rw)
none on /dev/pts type devpts (rw)
none on /proc/bus/usb type usbfs (rw)
none on /sys type sysfs (rw)
root@OpenWrt:/#
Comments (0)
You don't have permission to comment on this page.