| 
  • If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

WGT634U_USB_root

This version was saved 18 years ago View current version     Page history
Saved by PBworks
on March 31, 2006 at 9:56:48 am
 

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:

 

svn co -r 3535 https://svn.openwrt.org/openwrt/trunk/

cd trunk/openwrt

make menuconfig

 

  • Select '*' (not 'M'!) for the following items:
    • Target System (Broadcom BCM47xx/53xx [2.6])
    • OpenWrt Package Selection --->
      • Utilities --->

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
          1. 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:

 

make

 

 

  • 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:

 

mkdir -p /usb

 

  • 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

 

  • Make sure you do:

 

chmod +x etc/init.d/rcK

 

  • 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

 

 

  • Build the new image:

 

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.