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
Reference : http://jootamam.net/howto-initramfs-image.htm
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 |
BLFS >