grub: how to boot into ISO partition

I have copied an ISO file into a partition (i.e. dd if=isofile of=/dev/sdb1). How can I boot into that partition via GRUB?

When I try just with chainloader (hd1,0)+1, it says unknown executable format.


Solution 1:

See my answer on your boot-from-ISO-files question. Using that as a starting point, I ran some tests with an old hard-drive. I've previously configured Grub2 to boot a multi-ISO flash drive, so what I did was:

  1. Create a couple of partitions on an old hard drive. This was done using a USB-to-IDE adapter, so the drive appears as /dev/sdb.

    • Partition 1: FAT32, ~2GB in size
    • Partition 2: unformatted


  2. Mounted the first partition to /mnt and installed a copy of Grub from my system onto the drive:

    sudo grub-install --no-floppy --root-directory=/mnt /dev/sdb
    


  3. "Burned" an ISO to the second partition:

    sudo dd if=avg.iso /dev/sdb2
    


  4. This is an AVG virus-scanner ISO; on my multi-ISO flash drive, I use this to boot the ISO directly:

    menuentry "AVG Rescue CD" {
       loopback loop /iso/avg.iso
       linux (loop)/isolinux/vmlinuz max_loop=255 vga=791 init=linuxrc iso-scan/filename=/iso/avg.iso
       initrd (loop)/isolinux/initrd.lzm
    }
    

    In order to make this work from a hard drive partition, we need to nix the loopback command and set the root device and such. My attempts to have Grub2 discover the root device automagically all failed, so I pointed it at the partition directly. This works, but watch out for Grub's device enumeration; the drive you're trying to boot from may not be (hd0). Here's a working entry for the ISO partition:

    menuentry "AVG Rescue CD" {
       linux (hd0,2)/isolinux/vmlinuz max_loop=255 vga=791 init=linuxrc
       initrd (hd0,2)/isolinux/initrd.lzm
    }
    

    This results in a bootable ISO-on-partition.

This works because Grub2 can read ISO9660 filesystems, because this particular ISO is loading an OS that can cope with an ISO on a partition, and because practically everything the kernel loads is in the initrd.


If you're using Grub4DOS or Grub 1, you may be able to pull a similar trick with the chainloader. Presuming that this works to boot the Win7 ISO directly (source):

title Windows 7
  map (hd0,0)/win7.iso (hd32)
  map --hook
  chainloader (hd32)

You may have luck with this modification (assuming you "burned" the ISO to the second primary partition, (hd0,1); otherwise substitute the proper partition):

title Windows 7
  map (hd0,1) (hd32)
  map --hook
  chainloader (hd32)

You may also get away with this:

title Windows 7
  chainloader (hd0,1)

However, the ISO isn't really configured to boot from a drive, so you may run into other problems.

Solution 2:

Here's how I was able to do it using Grub4DOS (last official build):

Grub4DOS can boot iso images, so it should be able to do it for partitions.
We'd want to map the iso partition to a new drive and boot from it with:

title Boot ISO Partition
    map (hd0,7) (0xff)
    map --hook
    chainloader (0xff)

But this doesn't work, the whole disk is getting mapped.

Fortunately map can take a "file or blocklist" as first argument.

  1. Find out how many blocks your partition takes:

    $ sudo fdisk -l /dev/sda
    ...
       Device Boot      Start         End      Blocks   Id  System
    /dev/sda8            5948        6087     1124518+   b  W95 FAT32
    

    I created a 1.1Gb partition, so I need to use 1124518 * 2 = 2249036 here.
    (technically it's 2249037 but doesn't matter)

  2. Now pass the blocklist to grub:

    title Boot ISO Partition
        map --heads=0 --sectors-per-track=0 (hd0,7)0+2249036 (0xff)
        map --hook
        chainloader (0xff)
    

    And it works !

Notes:

  • If you get the size wrong grub will catch it (map command will fail beyond the partition boundary).
    If it's too small it likely won't boot.
  • Can use (hd32) instead of (0xff) also.
  • Haven't tried the 4.5b version, issue might be fixed there.

To chainload Grub4DOS from Grub2:

menuentry "Boot ISO Partition" {
        root (hd0,1)
        set opts='map --heads=0 --sectors-per-track=0 (hd0,7)0+2249036 (0xff);
                  map --hook;
                  chainloader (0xff) '
        linux16 /boot/grub4dos/grub.exe --config-file=$opts
}

Add this to /boot/grub/grub.cfg (or perhaps better /etc/grub.d/40_custom).
(assuming grub.exe in /boot/grub4dos on first partition)


Conclusion: It's pretty cool actually.

  • Chainloads into isolinux / whatever bootloader the image is using,
    so boot experience is exactly the same as cd or usb stick.
  • All you have to do to try a new iso is dd'ing it to the partition and reboot.
  • Faster than usb (esp. with ssd !) and more efficient than loop mounting the iso (ubuntu based isos).
  • Image doesn't have to be read from disk as with memdisk.

This should work with any hybrid iso. Works great with ubuntu live images and other linux isos as they manage to find their files in the iso9660 partition. Anything real-mode (DOS) should be fine too. Windows isos won't be able to cope.

Gujin can do it also btw.