BLFS‎ > ‎

4. USB boot

created : 2010-02-09   updated : 2010-02-09
 
Booting BLFS with an USB stick or SD card is not as simple as I thought.
After a lot of google search, I realized that I need to do the following :
 
1. Compile all the USB option as built in kernel modules
2. Modify /etc/fstab to make the mount point based on UUID
3. Compile busybox
4. Create initramfs
5. Modify /boot/grub/menu.lst to make the root based on UUID
6. Copy the data in the virtual disk blfs.vdi to a USB stick.
7. Boot from the USB directly, without using VirtualBox again.
 
Now I am going to describe them in details :
 
1. Compile all the USB option as built in kernel modules
 
If you didn't compile the USB support as built in modules, then you may need to recompile your kernel.  Instruction can be found here.
 
If you have used my .config file, which have all needed modules built in, you don't have to do this step.
 
2. Modify /etc/fstab
The /etc/fstab defines the root mount point for the BLFS system.  The following is a sample of /etc/fstab files
---------------------------------------------------
/dev/sda1 / ext3 defaults 1 1
#/dev/sda5 swap swap pri=1 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devpts /dev/pts devpts gid=4,mode=620 0 0
tmpfs /dev/shm tmpfs defaults 0 0
----------------------------------------------------
 
The root mount point was defined to be /dev/sda1 in the above file, which means the first partition of harddisk 1.
This is not a good method for defining USB disk.  Because USB device are portable in nature.  And device name may change from computer to computer.  It is better to use the UUID to define the root mount point.
 
To find the UUID of your USB drive,  type :
 blkid
 
 
The result is something like :
/dev/sda1: UUID="6650a279-0415-4104-b687-486fb2df82d0" TYPE="ext3"
So it is time to modify the /etc/fstab file as follow :
Comment the line /dev/sda1 :
sed -i 's|/dev/sda1|#&|g' /etc/fstab
 
Add the UUID as root mount point :
sed -i '/\/dev\/sda1/a \
UUID="6650a279-0415-4104-b687-486fb2df82d0"  / ext3 defaults 1 1' /etc/fstab
 
 
Or, you may just invoke "vi /etc/fstab",  finally, the file /etc/fstab should become something like :
 
#/dev/sda1 / ext3 defaults 1 1
UUID="6650a279-0415-4104-b687-486fb2df82d0"  / ext3 defaults 1 1
#/dev/sda5 swap swap pri=1 0 0
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
devpts /dev/pts devpts gid=4,mode=620 0 0
tmpfs /dev/shm tmpfs defaults 0 0
Reboot,  to see whether it works !  If it fail to boot, use the chroot environment to correct any mistakes.
 
3. Compile BusyBox
 
BusyBox is a shell utilities that doesn't depend on any library (if you build it statically).
It is useful as the startup shell for the initramfs described next section.
 
Download busybox :
 
cd /blfs
wget http://www.busybox.net/downloads/busybox-1.15.3.tar.bz2
 
 
Unpack source :
 
tar xvf busybox-1.15.3.tar.bz2
cd busybox-1.15.3
 
Configuration :
Clean all config :
make allnoconfig
 
Busybox provides a menu based config interface
make menuconfig
 
Setting as follows :
 
Busybox Settings --->
  Build Options --->
  [*] Build BusyBox as a static binary
Archival Utilities --->
[*] cpio
[*]   support for archive creation
[*]     support for passthrough mode
[*] gzip
Coreutils --->
[*] cat
[*] cp
[*] cut
[*] echo
[*]   Enable echo option (-n and -e)
[*] install
[*] ls
    (all 'ls' suboptions will be automatically selected)
[*] mkdir
[*] mknod
[*] mv
[*] rm
[*] rmdir
[*] sleep
Console Utilities --->
[*] clear
Editors --->
[*] vi
    (all vi suboptions will be automatically selected)
Finding Utilities --->
[*] find
    (necessary suboptions will be automatically selected)
 
Linux Module Utilites --->
[*] insmod
[*] lsmod
[*] modprobe
[*] depmod
    (no need to change the automatically selected options in this page)

Linux System Utilities --->
[*] blkid
[*] fdisk
    (necessary suboptions will be automatically selected)
[*] findfs
[*] mdev
[*] Ext filesystem
[*] mount
    (Make sure to enable all suboptions manually)
[*] priot_root
[*] switch_root
[*] umount

Shells --->
Choose your default shell (ash) <--- must change it from (none) to (ash)
[*] ash
    (some suboptions will be automatically selected, no need to make any change)
 
Backup config :
cp .config ../busybox-1.15.3.config
 
Build busybox :
time make
 
real    1m47.899s
user    0m16.185s
sys     1m29.606s
 
Since busybox is only useful for generating initramfs for booting purpose, it doesn't need any installation.
Right now, just copy it to the /boot folder
 
cp busybox /boot/busybox-1.15.3
 
4. Create initramfs
 
Create folder structure :
mkdir -p /boot/initramfs/{bin,sbin,etc,proc,sys,newroot}
cd /boot
touch initramfs/etc/mdev.conf
 
Install busybox to the right position :
cp busybox-1.15.3 initramfs/bin/busybox
chmod +x initramfs/bin/busybox
 
Create links for all compiled functions :
ln -s busybox initramfs/bin/blkid
ln -s busybox initramfs/bin/cat
ln -s busybox initramfs/bin/clear
ln -s busybox initramfs/bin/cp
ln -s busybox initramfs/bin/cpio
ln -s busybox initramfs/bin/cut
ln -s busybox initramfs/bin/depmod
ln -s busybox initramfs/bin/echo
ln -s busybox initramfs/bin/fdisk
ln -s busybox initramfs/bin/find
ln -s busybox initramfs/bin/findfs
ln -s busybox initramfs/bin/gzip
ln -s busybox initramfs/bin/insmod
ln -s busybox initramfs/bin/install
ln -s busybox initramfs/bin/ls
ln -s busybox initramfs/bin/lsmod
ln -s busybox initramfs/bin/mdev
ln -s busybox initramfs/bin/mkdir
ln -s busybox initramfs/bin/mknod
ln -s busybox initramfs/bin/modprobe
ln -s busybox initramfs/bin/mount
ln -s busybox initramfs/bin/mv
ln -s busybox initramfs/bin/pivot_root
ln -s busybox initramfs/bin/rm
ln -s busybox initramfs/bin/rmdir
ln -s busybox initramfs/bin/sh
ln -s busybox initramfs/bin/sleep
ln -s busybox initramfs/bin/switch_root
ln -s busybox initramfs/bin/umount
ln -s busybox initramfs/bin/vi
 
 
Create init script :
 
cat > initramfs/init << "EOF"
#!/bin/sh
 
#Mount things needed by this script
mount -t proc proc /proc
mount -t sysfs sysfs /sys
 
#Disable kernel messages from popping onto the screen
echo 0 > /proc/sys/kernel/printk
 
#Clear the screen
clear
 
#Create all the symlinks to /bin/busybox
#busybox --install -s
 
#Create device nodes
mknod /dev/null c 1 3
mknod /dev/tty c 5 0
 
echo "Detecting root device..."
sleep 9
 
mdev -s
 
#Function for parsing command line options with "=" in them
# get_opt("init=/sbin/init") will return "/sbin/init"
get_opt() {
echo "$@" | cut -d "=" -f 2
}
 
#Defaults
init="/sbin/init"
root="/dev/hda1"
 
#Process command line options
for i in $(cat /proc/cmdline); do
case $i in
root\=*)
root=$(get_opt $i)
type=$(echo $i | cut -d= -f2)
if [ $type=="LABEL" ] || [ $type=="UUID" ]; then
uuid=$(echo $i | cut -d= -f3)
root=$(findfs "$type"="$uuid")
echo $root
sleep 5
fi
;;
init\=*)
init=$(get_opt $i)
;;
esac
done
 
#Mount the root device
mount "${root}" /newroot
 
#Check if $init exists and is executable
if [[ -x "/newroot/${init}" ]] ; then
#Unmount all other mounts so that the ram used by
#the initramfs can be cleared after switch_root
umount /sys /proc
 
#Switch to the new root and execute init
exec switch_root /newroot "${init}"
fi
 
#This will only be run if the exec above failed
echo "Failed to switch_root, dropping to a shell"
exec sh
 
EOF
 
Make the script executable : 
chmod +x initramfs/init
 
Build initramfs.igz :
 
cd /boot/initramfs
bin/find . | bin/cpio -H newc -o  > ../initramfs.cpio
cd ..
initramfs/bin/cat initramfs.cpio | initramfs/bin/gzip > initramfs.igz
rm initramfs.cpio
 
5. Modify /boot/grub/menu.lst to make the root based on UUID
 
title LFS 6.5 (initramfs)
# the parameter nomodeset is used to fixed the blank screen on boot problem
root (hd0,0)
kernel /boot/lfskernel-2.6.30.2 \
root=UUID=6650a279-0415-4104-b687-486fb2df82d0 nomodeset
initrd /boot/initramfs.igz
 
Recall that we are still using virtualbox vdi file,  the virtual machine have only one harddisk attached, therefore root(hd0,0) is correct.
 
Later, when we transform the vdi file to a physical USB device(the purpose of this section), root(hd0,0) would also be corrected since the USB bootable disk will be the first harddisk detected by grub.
 
Now reboot to see whether everything is fine.
 
6. Copy the data in the virtual disk blfs.vdi to a USB stick.
In the last part we have successfully remove the hardcoded /dev/sda1 in /etc/fstab and /boot/grub/menu.lst
So it is time to make BLFS portable.
 
First prepared a USB stick big enough to hold the disk image.  (8G in my case).
 
In the physical machine, find out the device name of the USB disk
 
fdisk -l
 
My USB stick is in /dev/sdc
(if you are not sure, unplug the USB stick,  then plug it in again, and compare result of "fdisk -l" with and without the USB stick.)
 
 
 
Now unmount the USB stick in the physical machine. (It was automatically mounted in my system)
umount /dev/sdc1
 
Now start the Virtual Machine, with USB support turned on.
 
In the virtual machine, find out the BLFS  device name and the USB device name:
fdisk -l
 
 
My BLFS is in /dev/sdb and USB device in /dev/sdc
Note : it is a coincidence that the USB device name is /dev/sdc in both my virtual and physical machine, it may not be your case. The nickname of dd is "data destroyer", make sure you understand what you are doing.
 
Now (in the virtual machine), copy the BLFS system to the USB device :
time dd if=/dev/sdb of=/dev/sdc bs=32768
 
It may be a long process, if you wish to show the progress of dd, use this form :
dd if=/dev/sdb of=/dev/sdc bs=32768 & pid=$!
while kill -USR1 $pid; do sleep 5; done
 

229376+0 records in
229376+0 records out
7516192768 bytes (7.5 GB) copied, 3602 s, 2.1 MB/s
 
real    60m2.386s
user    0m0.060s
sys     0m33.406s
 
7.  Boot the USB device :
 
If your bios supports boot from USB, it is time to make a test.
 
If your computer doesn't support USB booting,  see this page for solution.
 
 
Tips :
The command 'dd' is used for first time duplication. If you later make change to the virtual disk image and want to synchronize the change to the USB disk, use the command 'rsync'
 
mkdir /tmp/b
mkdir /tmp/c
mount /dev/sdb1 /tmp/b
mount /dev/sdc1 /tmp/c
rsync -av --progress /tmp/b/ /tmp/c/ 2>&1 | tee /tmp/log.txt
 
 
End
Comments