Howto make a USB stick bootable
USB sticks are really useful. Not only for transferring files between computers, but also also rescue media, or more generally, to boot from. However, making a USB stick bootable can turn out to be tricky. This small howto describes the tricks that I discovered over the last years. The following commands assume the necessary package to be installed under Linux. It has been tested with Debian GNU/Linux sid (unstable as of 2006-06-26) with packages mbr (1.1.8-1), syslinux (3.11-3), and grub (0.97-11).
Which filesystem?
There are a lot of different file systems around, but for USB sticks, I generally use VFAT(32). This allows the stick to be read and written by all major operating systems.
Making the USB stick itself bootable
Some manufacturers explicitly declare their USB sticks as “bootable” and
point that out in their marketing brochures. Others don’t, so does that
mean that only some USB sticks are bootable?
No! All USB sticks are (or at least, can be made) bootable. It seems to
be a well established myth that it is important to buy a “bootable” USB
stick, and it is cited often on various web pages. But there is no
reason why any USB stick should not be able to boot any operating
system. After all, it’s just a mass storage medium accessed via a
well-defined USB protocol. Just because a standard hard disk is not
declared as bootable does not mean that anybody would not expect it to
fail being bootable. The only catch with USB sticks is that some
manufacturers pre-format them in a way that makes it easy to boot from
them, while others don’t. But I have not yet found a single USB stick
that I could not get to boot.
It is generally advisable to use parted to partition the USB stick. fdisk will work just as fine for creating the partitions, but mkdosfs is known to create FAT file systems without a valid boot sector. Therefore, parted is the best tool to create FAT file systems under Linux. The recipe that worked best for me is to:
-
Invoke parted for the USB device, e.g. parted /dev/sdu
-
Display the current partition layout with print, which produces an output similar to:
Disk /dev/sdu: 4151MBSector size (logical/physical): 512B/512B
Partition Table: msdos
mber Start End Size Type File system Flags
1 16,4kB 4150MB 4150MB primary fat32 boot
-
Remove the original partition with rm 1
-
Create a new partition with mkpart primary fat32 0 4151MB (for a device smaller than 2GB replace fat32 with fat16, the last value is the size as shown by print)
-
Create the VFAT(32) filesystem with mkfs 1 fat32 (for a device smaller than 2GB replace fat32 with fat16)
-
Mark the partition as bootable with toggle 1 boot
-
The partition table as shown with print should now look like:
Disk /dev/sdu: 4151MB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 0,51kB 4151MB 4151MB primary fat32 boot, lba
-
Exit parted with quit
For my large USB stick (4GB), once this resulted in a correct VFAT32 filesystem, but for some reason the Linux kernel was unable to auto-detect it. That is, mounting with an explicit mount -t vfat /dev/sdu1 /mnt worked, but using e.g. KDE for auto-mounting resulted in an error message. In such a case, it helps to format the device with mkdosfs /dev/sdu1 and then reformat with parted (only the mkfs command is necessary). It seems that mkdosfs and parted both have their advantages when it comes to VFAT(32).
Alternative way of making the USB stick bootable
If for some reason the above procedure coupled with syslinux or grub does not let the USB stick boot on some system or if you want to put FreeDOS on it (e.g. for performing BIOS updates), then the makebootfat tool can be used to create a partition table, write the MBR, and the file system all in one step:
-
Download makebootfat (version 1.4 at the time of this writing) and compile it using the usual ./configure; make - unfortunately, nobody has created a Debian package yet.
-
Install the syslinux Debian package (or download and build it from source)
-
[when using FreeDOS]: Download the FreeDOS source distribution fdbasews.iso and mount the ISO image to extract the required files for booting:
sudo mount -o loop /<path to fsbasews.iso>/fdbasews.iso /mnt/mkdir /tmp/fs-root
cp /mnt/freedos/setup/odin/command.com /tmp/fs-root
cp /mnt/freedos/setup/odin/kernel.sys /tmp/fs-root
cd /tmp
unzip /mnt/freedos/packages/src_base/kernels.zip
cp ./source/ukernel/boot/fat12.bin .
cp ./source/ukernel/boot/fat16.bin .
cp ./source/ukernel/boot/fat32lba.bin .
cp /usr/lib/syslinux/mbr.bin .
-
[when using FreeDOS]: Write everything to the stick
sudo /<path to makebootfat>/makebootfat -o /dev/sdu1 -E 255 -1 fat12.bin -2 fat16.bin -3 fat32lba.bin -m mbr.bin /tmp/fs-root
Note that this will use the MBR that comes with syslinux and the FAT boot sectors that come with FreeDOS, so command.com and kernel.sys will be loaded during bootup. For using syslinux instead, use: -
[when using syslinux]:
mkdir /tmp/fs-rootcp /usr/lib/syslinux/ldlinux.sys /tmp/fs-root
sudo /<path to makebootfat>/makebootfat -o /dev/sdu1 -E 255 -b /usr/lib/syslinux/ldlinux.bss -m /usr/lib/syslinux/mbr.bin
makebootfat can help in some instance by making the USB stick not only appear as a USB hard disk (sometimes labeled “USB-HDD” or “USB-ZIP” in BIOS boot options) but also as a (rather large) USB floppy drive (sometimes labeled “USB-FDD” in BIOS boot options). This trick can make it work on some broken BIOSes.
I don’t know if this approach would also work with grub, and somehow doubt it. For installing grub, its own code needs to be used.
Using syslinux as a boot loader
The traditional boot loader for Linux (and other operating systems) on VFAT is syslinux. It is used by many embedded Linux distributions including Gibraltar firewall (this will change to grub in the near future). Installing it is very simple and only necessitates two steps after the previous generation of the filesystem:
- Invoke syslinux /dev/sdu1
- Create correct master boot record with install-mbr /dev/sdu
This creates the boot sector and the ldlinux.sys file in the main directory and a master boot record that will boot from the first partition (because that’s the one that has been marked as active with parted).
Note: syslinux might be problematic with bigger partitions and will not
currently work with FAT32. According to the manual page, “SYSLINUX is
unsafe to use on any filesystem that extends past cylinder 1024. This is
a fundamental limitation of the standard BIOS API. SYSLINUX will not
work (and will refuse to install) on filesystems with a cluster size of
more than 16K (typically means a filesystem of more than 1 GB.)”
This limitation does not exist with grub, so if you have large USB
sticks, grub is the recommended option.
Using grub as a boot loader
Although syslinux is small, simple to install, and comes with a very simple command line menu to select from different boot options, I definitely prefer grub. It is larger, but a lot more flexible and offers a complete boot menu and interactive command interface. With recent versions of grub (tested with 0.97), booting from USB is also possible without real issues. To install grub as a boot loader on the USB stick:
- Mount the VFAT(32) file system with mount /dev/sdu1 /mnt (or via KDE, in which case it will probably be mounted under /media/usb, then replace the /mnt occurances below accordingly)
- Create a directoriy for grub with mkdir -p /mnt/boot/grub
- Copy the grub files with cp /lib/grub/i386-pc/* /mnt/boot/grub
- Set a correct device map with echo ‘(hd0) /dev/sdu’ > /mnt/boot/grub/device.map
- Install grub into the master boot record with grub-install –root-directory=/mnt /dev/sdu
After that, grub should already be bootable from the USB stick, and booting a PC with the stick attached should show the grub boot menu.