I recently needed to boot from a USB key to install Xubuntu, in my case Xubuntu 11.04 using alternate CD. I used Unetbootin before for this job, however one thing I did not like is that it expands the ISO onto the USB. While this can be beneficial in some cases – e.g. when you actually want to change the files already present on the ISO, I wanted to just drop ISO onto the USB key and boot from it verbatim. Here’s what worked for me using Grub2.
VM for testing
I’m going to use Qemu VM for testing this. The VM will have a small HDD, a DVD reader and a USB key. To simulate the HDD and USB key, let’s create two images:
$ qemu-img create -f qcow2 sda.img 5G $ qemu-img create -f qcow2 sdb.img 1G
sda is the HDD, sdb is the USB stick. I will put the following distributions there and add them to the Grub2 boot menu:
30M slitaz-3.0.iso 11M tinycore_3.8.4.iso 640M xubuntu-11.04-alternate-amd64.iso
In order to actually do this, I downloaded the desktop variant of Xubuntu 11.04. I’ll use it to boot the VM initially and prepare the USB stick from within VM.
Here are the links you can use to download these:
- SliTaz 3.0 – http://mirror.slitaz.org/iso/3.0/slitaz-3.0.iso
- Tiny Core 3.8.4 – http://distro.ibiblio.org/tinycorelinux/3.x/release/tinycore_3.8.4.iso
- Xubuntu 11.04 alternate – http://mirror.anl.gov/pub/ubuntu-iso/CDs-Xubuntu/11.04/release/xubuntu-11.04-alternate-amd64.iso
- Xubuntu 11.04 desktop – http://mirror.anl.gov/pub/ubuntu-iso/CDs-Xubuntu/11.04/release/xubuntu-11.04-desktop-amd64.iso
Obviously, you can use other versions, especially if newer ones come in in the meantime, or try other distributions. Note also that Xubuntu links from the above are amd64 versions, so if you want 32-bit check this page.
Starting the VM
First, let’s boot Xubuntu 11.04 desktop:
$ qemu-system-x86_64 -m 512 -hda sda.img -hdb sdb.img -cdrom xubuntu-11.04-desktop-amd64.iso -boot d
Choose the first option “Try Xubuntu without installing” and boot the Xubuntu. When it boots, open the terminal by right clicking on the desktop and choosing Applications/Accessories/Terminal Emulator
. Let’s confirm we have both disks as expected:
ubuntu@ubuntu:~$ sudo fdisk -cul Disk /dev/sda: 5368 MB, 5368709120 bytes 255 heads, 63 sectors/track, 652 cylinders, total 10485760 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0xa9af789e Disk /dev/sda doesn't contain a valid partition table Disk /dev/sdb: 1073 MB, 1073741824 bytes 139 heads, 8 sectors/track, 1885 cylinders, total 2097152 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x5e2afaf3 Disk /dev/sdb doesn't contain a valid partition table
Let’s make a LVM partition on sda:
ubuntu@ubuntu:~$ sudo fdisk -cu /dev/sda Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel Building a new DOS disklabel with disk identifier 0xa9af789e. Changes will remain in memory only, until you decide to write them. After that, of course, the previous content won't be recoverable. Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite) Command (m for help): n Command action e extended p primary partition (1-4) p Partition number (1-4): 1 First sector (2048-10485759, default 2048): Using default value 2048 Last sector, +sectors or +size{K,M,G} (2048-10485750, default 10485759): Using default value 10485759 Command (m for help): t Selected partition 1 Hex code (type L to list codes): 8e Changed system type of partition 1 to 8e (Linux LVM) Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. Syncing disks.
and a Linux partition on sdb:
ubuntu@ubuntu:~$ sudo fdisk -cu /dev/sdb Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel Building a new DOS disklabel with disk identifier 0x5e2afaf3. Changes will remain in memory only, until you decide to write them. After that, of course, the previous content won't be recoverable. Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite) Command (m for help): n Command action e extended p primary partition (1-4) p Partition number (1-4): 1 First sector (2048-2097151, default 2048): Using default value 2048 Last sector, +sectors or +size{K,M,G} (2048-2097151, default 2097151): Using default value 2097151 Command (m for help): a Partition number (1-4): 1 Command (m for help): w The partition table has been altered! Calling ioctl() to re-read partition table. Syncing disks.
Let’s now format /dev/sdb1 as ext4:
ubuntu@ubuntu:~$ sudo mkfs.ext4 /dev/sdb1 mke2fs 1.41.14 (22-Dec-2010) Filesystem label= OS type: Linux Block size=4096 (log=2) Fragment size=4096 (log=2) Stride=0 blocks, Stripe width=0 blocks 65536 inodes, 261888 blocks 13094 blocks (5.00%) reserved for the super user First data block=0 Maximum filesystem blocks=268435456 8 block groups 32768 blocks per group, 32768 fragments per group 8192 inodes per group Superblock backups stored on blocks: 32768, 98304, 163840, 229376 Writing inode tables: done Creating journal (4096 blocks): done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 32 mounts or 180 days, whichever comes first. Use tune2fs -c or -i to override.
Note other partition types should work – e.g. vfat might be a better choice if you have Windows machines around that might access this USB.
We have all set up now to install and configure Grub2.
Copying the ISO files from host to guest USB stick
Qemu has a built-in router that exposes host within the guest on IP 10.0.2.2. This can be used to communicate with the host and can be handy when copying files between hosts. My host is Ubuntu 11.10-beta1, but should not matter going forward. I will be using SMB with Samba to copy this. First, make sure you have a share on the host and that all ISO files are there. To create a share on the host from command line, you can do this:
$ net usershare add isos /path/to/isos "" "" guest_ok=y
The above adds a share called isos to the path where you saved isos (/path/to/isos) and allows guest access.
From within guest, we’ll mount this, but in Xubuntu 11.04 desktop live CD we need to install smbfs first. Here are all the steps:
ubuntu@ubuntu:~$ sudo apt-get install smbfs ... <installation information> ... ubuntu@ubuntu:~$ mkdir isos ubuntu@ubuntu:~$ sudo smbmount //10.0.2.2/isos isos Password: ubuntu@ubuntu:~$ cd isos ubuntu@ubuntu:~/isos$ ls -1hs total 1.5G 30M slitaz-3.0.iso 11M tinycore_3.8.4.iso 640M xubuntu-11.04-alternate-amd64.iso 688M xubuntu-11.04-desktop-amd64.iso
Let’s copy all but the desktop ISO to our USB stick:
ubuntu@ubuntu:~$ mkdir sdb1 ubuntu@ubuntu:~$ sudo mount /dev/sdb1 sdb1 ubuntu@ubuntu:~$ mkdir sdb1/isos ubuntu@ubuntu:~/isos$ sudo cp lubu-528.iso slitaz-3.0.iso tinycore_3.8.4.iso xubuntu-11.04-alternate-amd64.iso ~/sdb1/isos ubuntu@ubuntu:~/isos$ cd .. ubuntu@ubuntu:~$
This will take a few minutes to complete.
Installing Grub2
We can install Grub2 using this:
ubuntu@ubuntu:~$ sudo grub-install --root-directory=sdb1 /dev/sdb Installation finished. No error reported.
The only thing left is to make a configuration with the above-mentioned distributions:
ubuntu@ubuntu:~$ cd ~/sdb1/boot/grub ubuntu@ubuntu:~/sdb1/boot/grub$ sudo sh -c "cat > grub.cfg" menuentry "SliTaz 3.0" { set iso=/isos/slitaz-3.0.iso loopback loop $iso linux (loop)/boot/bzImage isofrom=$iso boot=live -- initrd (loop)/boot/rootfs.gz autologin } menuentry "Tinycore 3.8.4" { loopback loop /isos/tinycore_3.8.4.iso linux (loop)/boot/bzImage -- initrd (loop)/boot/tinycore.gz } menuentry "Xubuntu 11.04 alternate" { set iso=/isos/xubuntu-11.04-alternate-amd64.iso loopback loop $iso linux (loop)/install/vmlinuz findiso=$iso file=/cdrom/preseed/xubuntu.seed quiet -- initrd (loop)/install/initrd.gz } ^D ubuntu@ubuntu:~/sdb1/boot/grub$ cd ubuntu@ubuntu:~$ sudo umount sdb1 ubuntu@ubuntu:~$ sudo umount isos
^D means press Ctrl+D to send EOF to cat. After this, we are all set to try to boot from our newly created USB stick. Close the current Qemu instance and launch another one like this:
$ qemu-system-x86_64 -m 512 -hda sdb.img -hdb sda.img -boot c
Note that the order is reversed, as we can only boot from the first HDD. You should be presented with the menu we just created and be able to boot the 3 distributions.
Installing Xubuntu 11.04 alternate on the above system
You may be wondering why I have a 5GB /dev/sda (well, /dev/sdb now after exchanging sda and sdb to be able to boot from USB) at all. I used this to test Xubuntu install before I installed on a physical machine. Anyway, this worked pretty much excellent provided one additional step on VM. Not sure if this is related to using ext4 on the USB, but if I’m not mistaken doing this on a physical machine worked fine without any intervention. Anyway, the issue was that Xubuntu alternate installer could not detect the CD-ROM, even though findiso
parameter has been supplied. This was easy to fix – go to the second console (Alt-F2) and do this:
$ mv /dev/sr0 /dev/sr0a $ mount /dev/sda1 /mnt $ ln -s /mnt/isos/xubuntu-11.04-alternate-amd64.iso /dev/sr0
This will basically put the Xubuntu alternate CD in place of what really should be CD-ROM (/dev/sr0 in this case). Now just repeat the CD-ROM detection step and you’ll be all set. Installing Xubuntu went like a charm from withing Qemu and also on another physical machine.