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:

  1. Invoke parted for the USB device, e.g. parted /dev/sdu

  2. Display the current partition layout with print, which produces an output similar to:
    Disk /dev/sdu: 4151MB

    Sector size (logical/physical): 512B/512B

    Partition Table: msdos

    mber  Start   End     Size    Type     File system  Flags

     1      16,4kB  4150MB  4150MB  primary  fat32        boot

  3. Remove the original partition with rm 1

  4. 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)

  5. Create the VFAT(32) filesystem with mkfs 1 fat32 (for a device smaller than 2GB replace fat32 with fat16)

  6. Mark the partition as bootable with toggle 1 boot

  7. 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

  8. 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:

  1. 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.

  2. Install the syslinux Debian package (or download and build it from source)

  3. [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 .

  4. [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:

  5. [when using syslinux]:
    mkdir /tmp/fs-root

    cp /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:

  1. Invoke syslinux /dev/sdu1
  2. 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:

  1. 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)
  2. Create a directoriy for grub with mkdir -p /mnt/boot/grub
  3. Copy the grub files with cp /lib/grub/i386-pc/* /mnt/boot/grub
  4. Set a correct device map with echo ‘(hd0)  /dev/sdu’ > /mnt/boot/grub/device.map
  5. 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.

René Mayrhofer
René Mayrhofer
Professor of Networks and Security & Director of Engineering at Android Platform Security; pacifist, privacy fan, recovering hypocrite; generally here to question and learn