HOWTO: Booting LiveCD ISOs from USB flash drive with Grub2
Updates
2009-10-27 08:50 UTC:
Fixed Ubuntu menu entries
2009-10-26 00:15 UTC:
Because the Lua scripting support was dropped from Grub2 after an update I've split the tutorial in two parts. One shows the old way of auto detecting live systems with the help of Lua and the other new way is to manually edit the grub.cfg.
2009-10-22 21:10 UTC:
bootiso.lua: Added support for Tinycore LiveCDs
2009-10-21 18:40 UTC:
bootiso.lua: Slax LiveCDs are now supported and general code cleanup
Introduction
In this tutorial you will prepare a USB flash drive to make it bootable. After you booted it it shows you a menu where you can choose which live system you want to boot.
So you might be interested in this tutorial if:
- You want to have multiple live systems on one USB flash drive
- In the future you want to create a new bootable live system just by copying the ISO file onto the drive and edit the grub.cfg
- You don't want to or can't use Distro specific LiveUSB creator tools
- You prefer a cleaner solution than the most LiveUSB creator tools which create several folders and files at the device root
- You are feeling bored and want to see cool features of Grub2
If you have a Grub2 version with Lua support you even don't need to manually edit the grub.cfg when you add new or remove live systems.
System Requirements
- One USB flash drive
- A running Ubuntu 9.10 (Karmic Koala), either installed or from a Live System
Installation
Warning: If you have important data on your USB flash drive you might want to backup them, although no step of the tutorial should delete files.
Please note: This tutorial will use placeholders like “/dev/sdx” for the device name and “/media/USBFolderName” for the mounted directory name which must be replaced with the proper names of your plugged in USB flash drive. If you don't know them you can look under the File System tab from the System Monitor or execute the “mount” command in a terminal.
The first step is to install Grub2 on the USB flash drive. Be careful that you don't put a number behind the device name because we want to install Grub2 into the MBR of the device and not into a partition. Replace the placeholders and execute the following command in a terminal.
Code:
sudo grub-install --root-directory=/media/USBFolderName /dev/sdx
After that you should see a new folder “boot” on your USB flash drive which contains another folder named “grub”. In the "boot" folder you create a new folder “isos”. In this folder you can put supported LiveCD ISOs to boot from.
The next part "Configuration" depends on your Grub2 version and if it does or doesn't support Lua scripting. Please go directly to the right part and ignore the other. The Ubuntu Grub2 versions will most likely have no Lua support but if you manually compile Grub2 with the Grub-extras you have. To check this you can look in the "boot/grub" folder if the "lua.mod" file exist or boot Grub, press "c" and check if the "parser.lua" command exist.
Configuration (no Lua support)
Create a "grub.cfg" file in the "boot/grub" folder of your USB drive and add the matching menu entries. Perhaps you must also modify the path to your ISO file.
grml:
Code:
menuentry "grml" {
set isofile="/boot/isos/grml.iso"
loopback loop $isofile
linux (loop)/boot/grml/linux26 findiso=$isofile apm=power-off quiet boot=live nomce
initrd (loop)/boot/grml/initrd.gz
}
Parted Magic:
Code:
menuentry "Parted Magic" {
set isofile="/boot/isos/pmagic.iso"
loopback loop $isofile
linux (loop)/pmagic/bzImage iso_filename=$isofile edd=off noapic load_ramdisk=1 prompt_ramdisk=0 rwnomce sleep=10 loglevel=0
initrd (loop)/pmagic/initramfs
}
Slax:
Code:
menuentry "Slax" {
set isofile="/boot/isos/slax.iso"
loopback loop $isofile
linux (loop)/boot/vmlinuz from=$isofile ramdisk_size=6666 root=/dev/ram0 rw
initrd (loop)/boot/initrd.gz
}
Tinycore:
Code:
menuentry "Tinycore" {
set isofile="/boot/isos/tinycore.iso"
loopback loop $isofile
linux (loop)/boot/bzImage
initrd (loop)/boot/tinycore.gz
}
Ubuntu (since 9.10 Karmic Koala):
Code:
menuentry "Ubuntu" {
set isofile="/boot/isos/ubuntu.iso"
loopback loop $isofile
linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile quiet splash noprompt --
initrd (loop)/casper/initrd.lz
}
Ubuntu (before 9.10 Karmic Koala):
Code:
menuentry "Ubuntu" {
set isofile="/boot/isos/ubuntu.iso"
loopback loop $isofile
linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile quiet splash noprompt --
initrd (loop)/casper/initrd.gz
}
Configuration (with Lua support)
Create the following three files in the "boot/grub" folder of your USB drive.
grub.cfg
Code:
# Uncomment for a different ISO files search path
#set isofolder="/boot/isos"
#export isofolder
# Uncomment for a different live system language
#set isolangcode="us"
#export isolangcode
source /boot/grub/listisos.lua
listisos.lua
Code:
#!lua
isofolder = grub.getenv ("isofolder")
if (isofolder == nil) then
isofolder = "/boot/isos"
end
function enum_file (name)
local title = string.match (name, "(.*)%.[iI][sS][oO]")
if (title) then
local source = "set isofile=" .. isofolder .. "/" .. name ..
"\nsource /boot/grub/bootiso.lua"
grub.add_menu (source, title)
end
end
grub.enum_file (enum_file, isofolder)
bootiso.lua
Code:
#!lua
-- Detects the live system type and boots it
function boot_iso (isofile, langcode)
-- grml
if (dir_exist ("(loop)/boot/grml")) then
boot_linux (
"(loop)/boot/grml/linux26",
"(loop)/boot/grml/initrd.gz",
"findiso=" .. isofile .. " apm=power-off quiet boot=live nomce"
)
-- Parted Magic
elseif (dir_exist ("(loop)/pmagic")) then
boot_linux (
"(loop)/pmagic/bzImage",
"(loop)/pmagic/initramfs",
"iso_filename=" .. isofile ..
" edd=off noapic load_ramdisk=1 prompt_ramdisk=0 rw" ..
" sleep=10 loglevel=0 keymap=" .. langcode
)
-- Sidux
elseif (dir_exist ("(loop)/sidux")) then
boot_linux (
find_file ("(loop)/boot", "vmlinuz%-.*%-sidux%-.*"),
find_file ("(loop)/boot", "initrd%.img%-.*%-sidux%-.*"),
"fromiso=" .. isofile .. " boot=fll quiet"
)
-- Slax
elseif (dir_exist ("(loop)/slax")) then
boot_linux (
"(loop)/boot/vmlinuz",
"(loop)/boot/initrd.gz",
"from=" .. isofile .. " ramdisk_size=6666 root=/dev/ram0 rw"
)
-- Tinycore
elseif (grub.file_exist ("(loop)/boot/tinycore.gz")) then
boot_linux (
"(loop)/boot/bzImage",
"(loop)/boot/tinycore.gz"
)
-- Ubuntu and Casper based Distros
elseif (dir_exist ("(loop)/casper")) then
boot_linux (
"(loop)/casper/vmlinuz",
find_file ("(loop)/casper", "initrd%..z"),
"boot=casper iso-scan/filename=" .. isofile ..
" quiet splash noprompt" ..
" keyb=" .. langcode ..
" debian-installer/language=" .. langcode ..
" console-setup/layoutcode?=" .. langcode ..
" --"
)
else
print_error ("Unsupported ISO type")
end
end
-- Help function to show an error
function print_error (msg)
print ("Error: " .. msg)
grub.run ("read")
end
-- Help function to search for a file
function find_file (folder, match)
local filename
local function enum_file (name)
if (filename == nil) then
filename = string.match (name, match)
end
end
grub.enum_file (enum_file, folder)
if (filename) then
return folder .. "/" .. filename
else
return nil
end
end
-- Help function to check if a directory exist
function dir_exist (dir)
return (grub.run("test -d '" .. dir .. "'") == 0)
end
-- Boots a Linux live system
function boot_linux (linux, initrd, params)
if (linux and grub.file_exist (linux)) then
if (initrd and grub.file_exist (initrd)) then
if (params) then
grub.run ("linux " .. linux .. " " .. params)
else
grub.run ("linux " .. linux)
end
grub.run ("initrd " .. initrd)
else
print_error ("Booting Linux failed: cannot find initrd file '" .. initrd .. "'")
end
else
print_error ("Booting Linux failed: cannot find linux file '" .. initrd .. "'")
end
end
-- Mounts the iso file
function mount_iso (isofile)
local result = false
if (isofile == nil) then
print_error ("variable 'isofile' is undefined")
elseif (not grub.file_exist (isofile)) then
print_error ("Cannot find isofile '" .. isofile .. "'")
else
local err_no, err_msg = grub.run ("loopback loop " .. isofile)
if (err_no ~= 0) then
print_error ("Cannot load ISO: " .. err_msg)
else
result = true
end
end
return result
end
-- Getting the environment parameters
isofile = grub.getenv ("isofile")
langcode = grub.getenv ("isolangcode")
if (langcode == nil) then
langcode = "us"
end
-- Mounting and booting the live system
if (mount_iso (isofile)) then
boot_iso (isofile, langcode)
end
Supported LiveCDs
Sadly it is not possible to boot every LiveCD ISO out there. The most important thing is that the live system is able to boot from an ISO file. These live systems parse a special boot parameter (like fromiso or findiso) to find the ISO file. Furthermore if you are using the Lua variant only registered live systems in the bootiso.lua file can be booted. Currently the following live systems are supported:
Booting
Now after you have successfully completed every step and put at least one supported ISO file in the “isos” folder you should be able to boot from the USB flash drive and see a menu with your ISOs.
License information
This tutorial and its scripts are public domain.
PS: I know that there is a Tutorials & Tips section in this forum but thought it would be better to post it under Karmic Testing until Karmic is final.
Bookmarks