MultiBoot USB

This is a collection of GRUB scripts that allows to create a bootable pendrive (USB dongle, flash stick) supporting a number of different OS images. Simply copy ISO files under `/iso-imgs`. Both UEFI and Legacy BIOS boot modes can be enabled simultaneously.

Adding support for an ISO

This how-to will explain how we can configure GRUB so it can directly boot an ISO file for a specific distribution or software utility. There are several ways to achieve this, listed below in order of preference.

Getting the ISO

First of all, we’ll need to download the ISO file and mount it so we can access its contents to find out what the best method is:

Methods

As a previous step, we should check the home page for the project that created the ISO. They might provide further information on how to boot directly from the ISO file. Also, we should try contacting the project's developers via their support channels to ask for help.

Using loopback.cfg

Some ISO files include a file named loopback.cfg specifically designed to be read by GRUB. This file should be located in /boot/grub/.

As an example, we can load the /boot/grub/loopback.cfg file for Ubuntu 16.04 like so:

submenu "Ubuntu 16.04 ->" {
  iso_path="/boot/isos/ubuntu-16.04.1-desktop-i386.iso"
  export iso_path
  search --set=root --file "$iso_path"
  loopback loop "$iso_path"
  root=(loop)
  configfile /boot/grub/loopback.cfg
  loopback --delete loop
}

Converting ISOLINUX entries

Commonly, when creating a bootable ISO, you’d use ISOLINUX, which is part of the SYSLINUX Project, as boot loader.

The process involves creating a file named isolinux.cfg that contains the menu entries for the boot loader.

This file is usually located in /isolinux/ or /boot/syslinux/ but the location can vary, therefore it’s recommended to search the directory where our ISO is mounted (e.g. /mnt/loop) with the following command:

find /mnt/loop -type f -name 'isolinux.cfg'

However, isolinux.cfg usually loads other files via an INCLUDE clause. If so, we’ll need to follow these files in order to find the one containing the actual menu entries. Then, we can manually convert the entries from ISOLINUX’s format to GRUB’s format.

As an example, these are the menu entries for Debian 8 Live (file /isolinux/live.cfg):

label live-586
        menu label ^Live (586)
        menu default
        linux /live/vmlinuz1
        initrd /live/initrd1.img
        append boot=live components quiet splash

label live-586-failsafe
        menu label ^Live (586 failsafe)
        linux /live/vmlinuz1
        initrd /live/initrd1.img
        append boot=live components memtest noapic noapm nodma nomce nolapic nomodeset nosmp nosplash vga=normal

label live-686-pae
        menu label ^Live (686-pae)
        linux /live/vmlinuz2
        initrd /live/initrd2.img
        append boot=live components quiet splash

label live-686-pae-failsafe
        menu label ^Live (686-pae failsafe)
        linux /live/vmlinuz2
        initrd /live/initrd2.img
        append boot=live components memtest noapic noapm nodma nomce nolapic nomodeset nosmp nosplash vga=normal

Which could be converted as:

submenu "Debian 8 Live ->" {
  iso_path="/boot/isos/debian-live-8.7.1-i386-standard.iso"
  loopback loop "$iso_path"
  root=(loop)
  menuentry "Live (586)" {
    linux /live/vmlinuz1 findiso=$iso_path boot=live components quiet splash
    initrd /live/initrd1.img
  }
  menuentry "Live (586 failsafe)" {
    linux /live/vmlinuz1 findiso=$iso_path boot=live components memtest noapic noapm nodma nomce nolapic nomodeset nosmp nosplash vga=normal
    initrd /live/initrd1.img
  }
  menuentry "Live (686-pae)" {
    linux /live/vmlinuz2 findiso=$iso_path boot=live components quiet splash
    initrd /live/initrd2.img
  }
  menuentry "Live (686-pae failsafe)" {
    linux /live/vmlinuz2 findiso=$iso_path boot=live components memtest noapic noapm nodma nomce nolapic nomodeset nosmp nosplash vga=normal
    initrd /live/initrd2.img
  }
}

Notice, however, that we’ve had to add the parameter findiso=$iso_path so the kernel can mount and access the contents of the ISO during boot. Otherwise the boot process will fail.

Unfortunately, many distributions use different parameters. Some known examples:

Distributions Parameters
Arch-based img_dev=$imgdevpath img_loop=$iso_path
Debian-based findiso=$iso_path
Fedora-based iso-scan/filename=$iso_path
Gentoo-based isoboot=$iso_path
openSUSE-based isofrom_system=$iso_path
PCLinuxOS-based bootfromiso=$iso_path
Slackware-based livemedia=$imgdevpath:$iso_path
Ubuntu-based iso-scan/filename=$iso_path

Distributions based on these might work with its corresponding parameter, so it’s a matter of trial and error.

Using MEMDISK

If the ISO file is relatively small (less than 128MB) or nothing else works, we can try using MEMDISK. With this method, the ISO is loaded directly into memory (as long as the system has enough) which will allow for booting some unsupported ISOs.

To get MEMDISK’s binary, we can install SYSLINUX using our system’s package manager, and find it at /usr/lib/syslinux/memdisk or /usr/lib/syslinux/bios/memdisk, depending on our distribution.

Alternatively, we can download the official tarball from kernel.org, in which case, we will find the binary at /bios/memdisk/memdisk.

As an example, we can load into memory the ISO for DBAN 2.3.0 (only 17MB) using this:

menuentry "DBAN 2.3.0" {
  iso_path="/boot/isos/dban-2.3.0_i586.iso"
  linux16 $prefix/memdisk iso raw
  initrd16 $iso_path
}

If our ISO is bigger than 128MB and we have a 32-bit OS, then we have to increase the maximum memory usage, by adding the parameter vmalloc with (at least) the size of the ISO file. For instance, for Ultimate Boot CD v5.3.6:

menuentry "Ultimate Boot CD v5.3.6" {
  iso_path="/boot/isos/ubcd536.iso"
  linux16 $prefix/memdisk iso raw vmalloc=650M
  initrd16 $iso_path
}

If nothing works

Resources