Friday, 17 February 2017

Make a generic grub2 boot menu (using loopback.cfg)

If you have ever tried to boot directly to a linux ISO file, then you will know that it is necessary to tell the linux boot kernel/scripts where to find the ISO file so that it can load it as a 'cdrom' (loop) device and access the files inside the ISO. If this is not done, you will typically see a 'squashfs file not found' error message!

Typically we can fix this by specifying a kernel parameter or 'cheat code'.

A typical grub2 command line which loads the Ubuntu boot kernel and specifies the location of the ISO file would be:

linux (loop)/casper/vmlinuz.efi boot=casper iso-scan/filename=/_ISO/ubuntu64.iso quiet splash

This allows us to boot from a grub2 USB drive (say), mount the ISO as a loop device and load the kernel and initial ramdrive files from inside the ISO file and then pass on the location of the ISO file so that when the linux kernel boots, it can re-load the ISO file as a loop device again (because the first loop device is lost when the linux kernel loads).

So to boot to linux in this way, we need to know what all these parameters need to be.

The problem is that they vary from version to version and distro to distro and we always have to do some 'research' and experimentation to try to find out what parameters we need. There also may be several menu entries (for live cd, install, safe mode, memtest, etc.) and we would need to make grub2 menus for each of them.

Enter the loopback.cfg file!

However, some distros, such as Ubuntu, contain a useful loopback.cfg file (located at \boot\grub\loopback.cfg).

Here is a typical Ubuntu loopback.cfg file which is inside the ISO file:

IMPORTANT: The iso filename must not contain spaces! Kernel parameters passed using the xxx=yyy format do not cater for filenames with spaces and 'escaping' the filename in quotes of any kind does not work!

menuentry "Try Ubuntu without installing" {
set gfxpayload=keep
linux /casper/vmlinuz.efi  file=/cdrom/preseed/ubuntu.seed boot=casper iso-scan/filename=${iso_path} quiet splash ---
initrd /casper/initrd.lz
}
menuentry "Install Ubuntu" {
linux /casper/vmlinuz.efi  file=/cdrom/preseed/ubuntu.seed boot=casper only-ubiquity iso-scan/filename=${iso_path} quiet splash ---
initrd /casper/initrd.lz
}
menuentry "Check disc for defects" {
linux /casper/vmlinuz.efi  boot=casper integrity-check iso-scan/filename=${iso_path} quiet splash ---
initrd /casper/initrd.lz
}
menuentry "Test memory" {
linux16 /install/mt86plus
}

The loopback.cfg file should already contain the correct kernel parameters for that particular distro which is inside that particular ISO file.

You can also see that it expects the $iso_path variable to specify the full path of the ISO file (without device name) and so it expects it to have already been defined.

An example .cfg file which will scan for various ISOs in the /iso and /boot/iso folders and create a menu can be found here.

So, if we could simply 'call' this loopback.cfg file, not only would not need to guess at the correct ISO cheat code and all the other parameters, but we also get a 'full' menu (in this case four menu entries), instead of having to code all the menu options ourselves.

Easily USB-boot from an Ubuntu ISO using the loopback.cfg file.
Here is simple grub2 menu which uses the loopback.cfg file that is inside a Ubuntu64.iso:

menuentry "Ubuntu" {
        set iso_path=/_ISO/Ubuntu64.iso
export iso_path
        search --set=root --file $iso_path
        loopback loop $iso_path
        set root=(loop)
        configfile /boot/grub/loopback.cfg
        loopback --delete loop
}


There is also a .cfg file here which will scan the /iso folder for any ISO files and automatically generate a grub2 menu for each of them. It should work for most ISOs which contain a loopback.cfg file.


grub2 E2B

If you are using the E2B grub2 menu system, you can use this menu (e.g. \_ISO\MAINMENU\grub2\Ubuntu_lb.grub2):

if [ -e "$isofpath/ubuntu.iso" ]; then
menuentry "Ubuntu via loopback.cfg" --unrestricted --class ubuntu {
set isoname=ubuntu.iso ; CHECK_MNU_FOLDER
set root=$root2
loopback loop $isofile
set iso_path=$isofile
export iso_path
set root=(loop)
if [ -e "/boot/grub/loopback.cfg" ]; then 
echo loopback.cfg exists 
configfile /boot/grub/loopback.cfg
  loopback --delete loop
 else 
echo ERROR: /boot/grub/loopback.cfg does not exist!
search --file /g2ldr --set=root
  loopback --delete loop
 fi
}
fi

These menus should work for both MBR and UEFI-booting (they do for Ubuntu).

So, if your linux ISO uses grub2 and contains a \boot\grub\loopback.cfg file, you can just use this menu for each one!

Unfortunately, very few distros contain a \boot\grub\loopback.cfg file. If you are involved in linux development, why not ask the developers to add a loopback.cfg file (preferably one which also supports persistence too!).

Note: ISO filenames may be case sensitive, so check the case of the iso filename carefully! Spaces in the iso filename or path are not allowed (it won't boot!).