Recently I found
this thread, which led me to
uppman's wiki.
His method allows booting from a USB device to a file system on the same USB
device. However, the "root=LABEL=*" is hard coded into the initrd, which may
make sense for booting from a USB device, but I wanted to boot from either an
IDE or SATA HD, without having to modify /etc/fstab, so I modified uppman's init
script.
Now, I use the following to modify my basic initrd (all of this based
on uppman's wiki):
1) Start by making a clean initrd. I use:
Code:
mkinitrd -c -k 2.6.24.5-smp -m ext3:reiserfs -f ext3 -r /dev/hda3
The options are:
-c - Clear the /boot/initrd-tree subdirectory & create a new one
-k - The default kernel to be used if no kernel is specified in menu.lst/lilo.conf
-m - Colon delimited list of modules to be loaded
-f - File system used in root file system (the -r option must be used also)
-r - Device for root file system (must be used with -r)
Note: The script dynamically determines root filesystem type when "root=/dev/*", "root/LABEL/*" or "root/UUID/*" is used in the menu.lst/lilo.conf. Be sure that you add the modules for the required filesyetems, either here or in Step 5. (It's easier here.)
2) Patch the original "/boot/initrd-tree/init" file:
Copy this code to a file named "init.patch".
Code:
74a75,82
> # Added, 20081119, by Bill Kirkpatrick <bkirkp@gmail.com>, to allow dynamic
> # determination of root filesystem type.
> ROOTFS=""
> BLKID=`blkid $ROOTDEV`
> ROOTFS=`echo $BLKID_ROOT | awk 'BEGIN{FS="="}{l=length($5);print substr($5, 2, l-2)}'`
> if [ "$ROOTFS" = "" ]; then ROOTFS=`echo $BLKID_ROOT | awk 'BEGIN{FS="="}{l=length($4);print substr($4, 2, l-2)}'`; fi
> echo "ROOTFS:" $ROOTFS " ROOTDEV:" $ROOTDEV
> # End dynamic determination
75a84,133
> # Added for dynamic booting when the disk LABEL is known but not the device.
> # Author: Magnus Uppman, magnus_uppman@hotmail.com
> # Modified, 20081119, by Bill Kirkpatrick <bkirkp@gmail.com>, to allow use
> # of "root=LABEL=*" & "root=UUID=*" in menu.lst or lilo.conf & dynamic
> # determination of root filesystem type.
> root=LABEL=*)
> ROOTDEV=""
> ROOTFS=""
> ROOTLABEL=`echo $ARG | cut -f3 -d=`
> while [ "$ROOTDEV" = "" ]; do
> echo "Trying to find:" $ROOTLABEL
> #Display some info
> PARTITIONS=`cat /proc/partitions`
> BLKID=`blkid -c /dev/null`
> echo $BLKID
> echo
> echo $PARTITIONS
> echo
> BLKID_ROOT=`blkid -t LABEL=$ROOTLABEL -c /dev/null`
> echo "Found:" $BLKID_ROOT
> ROOTDEV=`echo $BLKID_ROOT | awk 'BEGIN{FS=":"}{print $1}'`
> ROOTFS=`echo $BLKID_ROOT | awk 'BEGIN{FS="="}{l=length($5);print substr($5, 2, l-2)}'`
> if [ "$ROOTFS" = "" ]; then ROOTFS=`echo $BLKID_ROOT | awk 'BEGIN{FS="="}{l=length($4);print substr($4, 2, l-2)}'`; fi
> if [ "$ROOTDEV" = "" ]; then sleep 2; fi
> done
> echo "ROOTFS:" $ROOTFS " ROOTDEV:" $ROOTDEV
> ;;
> root=UUID=*)
> ROOTDEV=""
> ROOTFS=""
> ROOTUUID=`echo $ARG | cut -f3 -d=`
> while [ "$ROOTDEV" = "" ]; do
> echo "Trying to find:" $ROOTUUID
> #Display some info
> PARTITIONS=`cat /proc/partitions`
> BLKID=`blkid -c /dev/null`
> echo $BLKID
> echo
> echo $PARTITIONS
> echo
> BLKID_ROOT=`blkid -t UUID=$ROOTUUID -c /dev/null`
> echo "Found:" $BLKID_ROOT
> ROOTDEV=`echo $BLKID_ROOT | awk 'BEGIN{FS=":"}{print $1}'`
> ROOTFS=`echo $BLKID_ROOT | awk 'BEGIN{FS="="}{l=length($5);print substr($5, 2, l-2)}'`
> if [ "$ROOTFS" = "" ]; then ROOTFS=`echo $BLKID_ROOT | awk 'BEGIN{FS="="}{l=length($4);print substr($4, 2, l-2)}'`; fi
> if [ "$ROOTDEV" = "" ]; then sleep 2; fi
> done
> echo "ROOTFS:" $ROOTFS " ROOTDEV:" $ROOTDEV
> ;;
> # End dynamic booting
Issue this command:
Code:
patch /boot/initrd-tree/init "/path/to/init.patch"
There may be a better way of doing this, I know little about diff/patch.
3) Copy blkid to initrd-tree/sbin:
Code:
cp /sbin/blkid /boot/initrd-tree/sbin
Note: uppman used a separate directory & also copied in /usr/bin/awk, but the busybox implementation of awk works for me & other programs(for RAID & LVM, for example) are placed in /boot/initrd-tree/sbin by the /sbin/mkinitrd script, so I used that location instead of the separate directory.
4) Copy libraries (ld-linux.so.2 libblkid.so.1 libc.so.6 libdl.so.2 libm.so.6 libuuid.so.1) to lib:
Code:
cp /lib/{ld-linux.so.2,libblkid.so.1,libc.so.6,libdl.so.2,libm.so.6,libuuid.so.1} /boot/initrd-tree/lib
5) If you need any other modules in the initrd, copy them into '/boot/initrd-tree/lib/modules/'uname -r/'.
This step is optional. I do not perform it. If you do, you should also delete (or remove the executable bit from) the file /boot/initrd-tree/load_kernel_modules, so that all modules will be loaded, instead of just the ones that were loaded when the initrd was created.
6) Create a new initrd which contains the modifications:
Code:
cd /boot
mkinitrd [ -o initrd-mod.gz ]
The -o option may be used to rename the output initrd, so as to not clobber the original default "initrd.gz". I used this until it worked, now I don't.
7) Label the partitions. You may have to unmount some filesystems to label them. e2label works on a mounted ext3 fs, however.
8) Modify lilo.conf or menu.lst to use the correct "/dev/*", "root=LABEL=*" or "root=UUID=*" & new initrd name. Note that if you use a "/dev/*", "root=LABEL=*" or "root=UUID=*" that does not exist, you will get an error & have to reboot. With "root=LABEL=*" & "root=UUID=*", the process will sleep 2 seconds between each of five retries. If the label/uuid existed, my system has never needed but one attempt at finding it.
9) You're done. Test it out.