Tuesday 12 October 2010

Booting to ISO images from a USB key

I'm pretty sure this has been done before (I recall seeing a blog post about it... if you're the one who posted on Planet Ubuntu with a similar howto, let me know as I want to talk to you, at least to say thanks), but here it is anyway:

A couple of days ago I wrote this quick script to generate a roughly correct grub.cfg from the contents of a directory filled with .iso files. The goal: generate a USB bootable key that runs GRUB and allows you to choose which ISO to boot. It could be Ubuntu desktop, netbook, etc, doesn't matter, as long as you have enough room on the key.

This is done by leveraging the loopback grub command and the isoscan parameter. But first, setting it up...

You'll need (to):

  • one free USB key, formatted to vfat (mkfs.vfat -F 32 /dev/sdX1) the more space the better
  • create a directory called "iso" on it
  • install grub on it:
    grub-install --root-directory=/media/MOUNTPOINT /dev/sdX
    • this will create the boot/grub directories and install everything grub needs
  • copy iso files to the iso/ directory
  • run update-grub.py (available in bzr branch: lp:~mathieu-tl/+junk/bootable-iso-usb) from the key's mountpoint 
    • Careful: it's only quickly tested, and overwrites boot/grub/grub.cfg from the current working directory.
Sorry for the unimaginative naming of the script.

In short, this script attempts to guess what kind of distribution is in the ISO file. I've tested desktop and alternate with success, both seem to boot and properly get you to an install (or for desktop, "maybe-ubiquity", which means you'll get a prompt for whether you want to run the live session or just ubiquity to install). All this needed was to make use of the iso naming scheme and more importantly of the contents of the ISO files, as read by isoinfo (from the genisoimage package).

Even if it never ends up being of any use, it was at least a fun little thing to write.


Anonymous said...

"+junk" ! That's hilarious-ly humble :D

BTW many thanks for all the help and ideas you bring to the support team :D Always HAPPY to have you around!!!

Anonymous said...

For isos containing a /boot/grub/loopback.cfg, like the Ubuntu 10.10 isos, please use that rather than hard coding the kernel paths / parameters. More info here http://www.supergrubdisk.org/wiki/Loopback.cfg

Also grub 1.99 will hopefully ship, as part of the official documentation, an example grub.cfg that will actually detect iso files at boot. So you can just add iso files to the flash drive without needing to modify the grub.cfg at all. If you want to see the beginnings of this autoiso.cfg you can find it here: http://lists.gnu.org/archive/html/grub-devel/2010-09/msg00080.html

Anonymous said...

not sure if my previous comment got though. when pasting the grub command make sure you get a double hyphen instead of an emdash. otherwise you get an error like "More than one install_devices?".

also i think it should be
sudo grub-install --root-directory=/media/DISKNAME/ /dev/sdc

with sudo, the full mountpoint, and the disk rather than the partition.

also the shebang line in the script is wrong. it is missing the '!', and should probably be
#!/usr/bin/env python

otherwise it works for me. nice to have the i386 and amd64 on the same usb stick.

Matt Trudel said...

jordanu: cute, but I feel autoiso.cfg is doing quite a lot of checking and multiple passes over an ISO, which doesn't happen with my script. OTOH, if loopback.cfg means I can have "submenus" or in a way delegate to the iso giving out choices (a la "live or graphical installer?", read maybe-ubiquity), that's pretty interesting.

samtygier: thanks for the catches, I'll fix the script in bzr and my post :)

Anonymous said...

"cute, but I feel autoiso.cfg is doing quite a lot of checking and multiple passes over an ISO, which doesn't happen with my script."

It's true that your script lists the files in the iso once, then checks that cached list, whereas autoiso.cfg currently does one "pass" checking for each type of iso supported (exiting when it finds one, so only one pass if the iso has a loobpack.cfg). But I hope that grub's metadata caching means that in effect the same thing is happening in autoiso.cfg. I.e. The directory is read once into RAM then consulted multiple times when checking for files. I'll have to do some actual performance tests to see where it could be made faster.

Also of course your script is run once, then the static grub.cfg is used multiple times, whereas autoiso.cfg does the detection at every boot. For me the advantage of not requiring a system which can run update-grub.py to add new isos outweighs the disadvantage of the menu taking slightly longer to load each boot.

"OTOH, if loopback.cfg means I can have "submenus" or in a way delegate to the iso giving out choices (a la "live or graphical installer?", read maybe-ubiquity), that's pretty interesting."

That's exactly what it means :)

Unknown said...

Why do you use vfat for the filesystem instead of ext4 (with journaling turned off) or another, more efficient filesystem?

Matt Trudel said...

Well, vfat is conveniently just how filesystems are set up on brand new USB keys, so jordanu's comment about having a system to run the script on applies there -- what I mean by this is you *could* add the ISOs under windows, but then if you don't also have python you can't run the script to update the grub menu. Furthermore, it means you don't really need to format the key if it's a new one.

In reality, vfat or another filesystem won't really make much of a difference for this.

My feeling was that since you have to add the isos in the first place, running the script is just an extra step that can be done quickly.

With all this in mind, I'll prepare a few USB keys with this trick to help other installing at tonight's release party in Montreal. We'll see what kind of feedback will come out ;)

Unknown said...

I just tried this and got a message: "/dev/sdb does not have any corresponding BIOS drive." after the grub-install stage.

Any ideas what the problem may be? I now have a boot/grub folder with a single file, device.map, with a single line, "(fd0) /dev/fd0" - nothing else.

Unknown said...

OK, sorry, I should have looked further on the "BIOS" error, using "--recheck" seems to help that, however now I get a grub shell and no menu. I have two iso's in the folder, and a sensible looking grub.cfg