How to create bootable USB flash drive

Today, I will show you how to create customized USB flash drive to boot selected ISO images using Syslinux bootloader for Linux ext4 filesystem. It is very handy and useful, so let's begin immediately.

Requirements

Install syslinux bootloader for ext4 filesystem to use modern Linux filesystem..

$ sudo apt-get install extlinux 
Notice that syslinux-common package will be installed as dependency - it is very important as it contains many required files.

Step 1

Create one big partition on USB drive and make it active.

I will use /dev/sdc as an USB drive in this example.
$ sudo sfdisk /dev/sdc << EOF
,+,L,*
EOF
sfdisk: Checking that no-one is using this disk right now ...
sfdisk: OK

Disk /dev/sdc: 14800 cylinders, 64 heads, 32 sectors/track
Old situation:
Units: cylinders of 1048576 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/sdc1          0       -       0          0    0  Empty
/dev/sdc2          0       -       0          0    0  Empty
/dev/sdc3          0       -       0          0    0  Empty
/dev/sdc4          0       -       0          0    0  Empty
New situation:
Units: cylinders of 1048576 bytes, blocks of 1024 bytes, counting from 0

   Device Boot Start     End   #cyls    #blocks   Id  System
/dev/sdc1   *      0+  14799   14800-  15155199+  83  Linux
/dev/sdc2          0       -       0          0    0  Empty
/dev/sdc3          0       -       0          0    0  Empty
/dev/sdc4          0       -       0          0    0  Empty
Successfully wrote the new partition table

Re-reading the partition table ...

sfdisk: If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)
to zero the first 512 bytes:  dd if=/dev/zero of=/dev/foo7 bs=512 count=1
(See fdisk(8).)

Read sfdisk partition table manipulator for Linux manual page for more detailed information.

$ man sfdisk

Step 2

Format it as ext4 without journal to get the benefits of modern filesystem.

$ sudo mkfs.ext4 -F -O ^has_journal /dev/sdc1 
mke2fs 1.42.12 (29-Aug-2014)
/dev/sdc1 contains a ext4 file system
	created on Sun Sep 27 21:40:45 2015
Creating filesystem with 3788799 4k blocks and 948416 inodes
Filesystem UUID: 655f27e9-dee2-4ac3-9014-76fa711432e1
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done   

Step 3

Install Master Boot Record (included in mentioned earlier syslinux-common package).

$ sudo dd bs=440 count=1 conv=notrunc if=/usr/lib/syslinux/mbr/mbr.bin of=/dev/sdc
1+0 records in
1+0 records out
440 bytes (440 B) copied, 0,00827953 s, 53,1 kB/s

Read MBR (Master Boot Record) - Syslinux Wiki document for detailed information.

Step 4

Create temporary directory to mount partition created in the first step.

$ sudo mkdir -p /media/usb

Mount created partition.

$ sudo mount /dev/sdc1 /media/usb/

Step 5

Create boot/extlinux boot directory.

$ sudo mkdir -p /media/usb/boot/extlinux

Install syslinux bootloader on ext4 filesystem.

$ sudo extlinux --install /media/usb/boot/extlinux/
/media/usb/boot/extlinux/ is device /dev/sdc1

Step 6

Copy memdisk module to the boot directory.

$ sudo cp /usr/lib/syslinux/memdisk /media/usb/boot/extlinux/

memdisk is a module which simulates a disk to allow booting legacy operating systems.

Step 7

Copy modules required to display menu, boot from hard drive and reboot system.

$ sudo cp /usr/lib/syslinux/modules/bios/{menu.c32,reboot.c32,chain.c32,libutil.c32,libcom32.c32} /media/usb/boot/extlinux/

Module dependencies are described at Syslinux modules working dependencies wiki page.

Step 8

Create basic boot menu and store it in /media/usb/boot/extlinux/extlinux.conf file.

DEFAULT menu.c32
PROMPT 0

MENU TITLE Bootable USB drive

MENU BEGIN Boot from hard drive
  MENU TITLE Boot from hard drive
  LABEL boot_hd0
    MENU LABEL Boot from ^first hard drive
    MENU INDENT 1
    COM32 chain.c32
    APPEND hd0
    TEXT HELP
    * Boot from first hard drive
    ENDTEXT
  LABEL boot_hd1
    MENU LABEL Boot from ^second hard drive
    MENU INDENT 1
    COM32 chain.c32
    APPEND hd1
    TEXT HELP
    * Boot from second hard drive
    ENDTEXT
MENU END

LABEL reboot
  MENU LABEL ^Reboot
  MENU INDENT 1
  COM32 reboot.c32
  TEXT HELP
  * Reboot system
  ENDTEXT

Step 9

Create images directory.

$ sudo mkdir -p /media/usb/images

Store ISO images inside this directory.

Step 10

Configure syslinux bootloader to boot ISO images.

I will show you three examples that will allow you to test and use most of the available ISO images. I know about one notable exception, but it will be described next time.

Super Grub2 Disk

This is the simplest task as it does not require anything more then memdisk module.

Step A

Download super_grub2_disk_hybrid_2.02s3.iso ISO image from supergrubdisk.org and store it inside /media/usb/images/ directory.

Step B

Create boot menu entry.

LABEL super_grub
  MENU LABEL Emergency Linux boot
  LINUX memdisk
  INITRD /images/super_grub2_disk_hybrid_2.02s3.iso
  APPEND iso
  TEXT HELP
  * Boot into Linux system with broken GRUB2 bootloader
  ENDTEXT

Clonezilla

This process is very similar to the previous one.

Step A

Download clonezilla-live-2.4.2-32-amd64.is ISO image from clonezilla.org and store it inside /media/usb/images/ directory.

Step B

Create boot menu entry.

LABEL clonezilla
  MENU LABEL Clonet i 
  LINUX memdisk
  INITRD /images/clonezilla-live-2.4.2-32-amd64.iso
  APPEND iso
  TEXT HELP
  * Clonezilla live version: 2.4.2-32-amd64. (C) 2003-2015, NCHC, Taiwan
  ENDTEXT

Ubuntu Desktop Live

memdisk does not work in more complicated setups, including often used casper hook for initramfs-tools to boot live systems. However, the solution is to extract kernel and initrd from ISO file, then use them to boot the image.

Step A

Download ubuntu-15.04-desktop-amd64.iso ISO image from ubuntu.com and store it inside /media/usb/images/ directory.

Step B

Extract kernel (vmlinuz.efi) and initrd image (initrd.lz) from casper directory inside ISO image and store them on USB flash drive (inside boot/ubuntu/ directory).

Step C

Create boot menu entry.

LABEL ubuntu_live
  MENU LABEL Live non-persistent desktop
  LINUX /boot/ubuntu/vmlinuz.efi
  APPEND boot=casper initrd=/boot/ubuntu/initrd.lz iso-scan/filename=/images/ubuntu-15.04-desktop-amd64.iso
  TEXT HELP
  * Ubuntu 15.04 desktop 64-bit
  ENDTEXT

Simple as that.

Additional notes

I could not boot Tails 1.6, but maybe it is related to this specific version.

Debian Jessie requires some additional work, so I decided to publish these instructions separately. You can expect them next week.

References

The Syslinux Project

ArchWiki - Syslinux

ariane Version 2

Milosz Galazka's Picture

About Milosz Galazka

Milosz is a Linux Foundation Certified Engineer working for a successful Polish company as a system administrator and a long time supporter of Free Software Foundation and Debian operating system. He is also open for new opportunities and challenges.

Gdansk, Poland https://sleeplessbeastie.eu