public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/anaconda-overlay:master commit in: sys-boot/grub/files/ubuntu-upstream-1.98/, sys-boot/grub/files/, ...
@ 2011-07-07 22:43 Wiktor W Brodlo
  0 siblings, 0 replies; only message in thread
From: Wiktor W Brodlo @ 2011-07-07 22:43 UTC (permalink / raw
  To: gentoo-commits

commit:     f1a49dbf6383678d9672f3c122e1e5415e6c3be0
Author:     wiktor w brodlo <wiktor <AT> brodlo <DOT> net>
AuthorDate: Thu Jul  7 22:41:09 2011 +0000
Commit:     Wiktor W Brodlo <wiktor <AT> brodlo <DOT> net>
CommitDate: Thu Jul  7 22:41:09 2011 +0000
URL:        http://git.overlays.gentoo.org/gitweb/?p=proj/anaconda-overlay.git;a=commit;h=f1a49dbf

GRUB2 from Sabayon

---
 sys-boot/grub-handler/Manifest                     |    2 +
 sys-boot/grub-handler/files/grub-handler           |  318 ++
 sys-boot/grub-handler/grub-handler-0.2-r6.ebuild   |   20 +
 sys-boot/grub/Manifest                             |   53 +
 sys-boot/grub/files/00_fonts                       |   14 +
 sys-boot/grub/files/05_distro_theme                |   51 +
 sys-boot/grub/files/default-splash-5.4.png         |  Bin 0 -> 641815 bytes
 sys-boot/grub/files/default-splash-6.png           |  Bin 0 -> 1006813 bytes
 sys-boot/grub/files/default-splash.png             |  Bin 0 -> 379111 bytes
 sys-boot/grub/files/grub-0.97-gfxmenu-v8.patch     | 1003 ++++
 sys-boot/grub/files/grub-0.97-uuid.patch           | 5406 ++++++++++++++++++++
 sys-boot/grub/files/grub-0.97-uuid_doc.patch       |   38 +
 sys-boot/grub/files/grub-1.96-genkernel.patch      |   19 +
 sys-boot/grub/files/grub-1.97-genkernel.patch      |   28 +
 sys-boot/grub/files/grub-1.97-hostdisk.patch       |   60 +
 sys-boot/grub/files/grub-1.97-vga-deprecated.patch |   12 +
 .../grub-1.97-wallpaper-settings-support.patch     |   15 +
 .../grub-1.98-add-legacy-rootfs-detection.patch    |   83 +
 .../grub-1.98-follow-dev-mapper-symlinks.patch     |   25 +
 .../grub-1.98-genkernel-initramfs-single.patch     |   11 +
 sys-boot/grub/files/grub-1.98-genkernel.patch      |   28 +
 .../grub-1.98-wallpaper-settings-support.patch     |   15 +
 .../grub/files/grub-1.99-disable-floppies.patch    |   28 +
 sys-boot/grub/files/grub-1.99-genkernel.patch      |   11 +
 .../files/grub-1.99-vga-deprecated-not-yet.patch   |   14 +
 sys-boot/grub/files/grub-1.99-vga-deprecated.patch |   12 +
 .../grub-1.99-wallpaper-settings-support.patch     |   15 +
 .../files/grub-1.99-workaround-raid-bios-bug.patch |   17 +
 sys-boot/grub/files/grub.conf.gentoo               |   16 +
 sys-boot/grub/files/grub2-default                  |   62 +
 sys-boot/grub/files/grub2-default-1.99             |   63 +
 sys-boot/grub/files/splash.xpm.gz                  |  Bin 0 -> 6251 bytes
 .../01_uuids_and_lvm_dont_play_along_nicely.diff   |   14 +
 .../902_boot_blocklist_hack.diff                   |   20 +
 .../ubuntu-upstream-1.98/904_disable_floppies.diff |   28 +
 .../ubuntu-upstream-1.98/956_loopback_root.diff    |  139 +
 .../ubuntu-upstream-1.98/957_handle_loopback.diff  |   45 +
 .../958_linux_no_loopmount.diff                    |   20 +
 .../ubuntu-upstream-1.98/960_raid_virtio.diff      |  158 +
 .../ubuntu-upstream-1.98/961_dmraid_probe.diff     |  650 +++
 .../ubuntu-upstream-1.98/962_no_device_map.diff    |  112 +
 .../ubuntu-upstream-1.98/968_hostdisk_speedup.diff |  310 ++
 .../ubuntu-upstream-1.98/969_lvm_raid_probe.diff   |  227 +
 .../970_fix_locale_installation.diff               |   55 +
 .../files/ubuntu-upstream-1.98/971_langpacks.diff  |   30 +
 .../ubuntu-upstream-1.98/974_drive_probe.diff      |   23 +
 .../ubuntu-upstream-1.98/975_hostdisk_hd.diff      |  114 +
 .../01_uuids_and_lvm_dont_play_along_nicely.diff   |   14 +
 .../ubuntu-upstream/904_disable_floppies.diff      |   28 +
 sys-boot/grub/grub-0.97-r22.ebuild                 |  240 +
 sys-boot/grub/grub-1.98-r10.ebuild                 |  141 +
 sys-boot/grub/grub-1.98-r9.ebuild                  |  145 +
 sys-boot/grub/grub-1.99.ebuild                     |  279 +
 sys-libs/libuser/.libuser-0.57.1.ebuild.swp        |  Bin 0 -> 12288 bytes
 54 files changed, 10231 insertions(+), 0 deletions(-)

diff --git a/sys-boot/grub-handler/Manifest b/sys-boot/grub-handler/Manifest
new file mode 100644
index 0000000..cfd066c
--- /dev/null
+++ b/sys-boot/grub-handler/Manifest
@@ -0,0 +1,2 @@
+AUX grub-handler 10100 RMD160 e3c5885fd236e1c4f41d487897cb5e98cfab7525 SHA1 7d1f28701eb1cfc40c7efa582503a829cbb4391e SHA256 f7266ddcf8fb727645d64cc893a90f84ad75305bb71e87fe07b8897bdc2154aa
+EBUILD grub-handler-0.2-r6.ebuild 361 RMD160 2c2a3d4833cf817286803e175521278510017dc2 SHA1 f498f2c42f95c9cce3345759a28cb8d0de7699c5 SHA256 634762277e3423c14e442f9dae2f053dd76cd9fe9cbbf65ee903949671b1c7eb

diff --git a/sys-boot/grub-handler/files/grub-handler b/sys-boot/grub-handler/files/grub-handler
new file mode 100755
index 0000000..3820a4d
--- /dev/null
+++ b/sys-boot/grub-handler/files/grub-handler
@@ -0,0 +1,318 @@
+#!/usr/bin/python2
+# -*- coding: utf-8 -*-
+"""
+    Kernel grub.conf configuration script
+
+    Copyright (C) 2009 Fabio Erculiani
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+"""
+import os
+import sys
+import subprocess
+import shutil
+BOOT_MOUNT = False
+NO_SYS_ROOT_BOOT_DIR = "/boot"
+if os.path.ismount(NO_SYS_ROOT_BOOT_DIR):
+    BOOT_MOUNT = True
+SYS_ROOT = os.getenv("ROOT","")
+GRUB_CONF = SYS_ROOT+"/boot/grub/grub.conf"
+FSTAB_CONF = SYS_ROOT+"/etc/fstab"
+DISTRO_NAME = "Sabayon Linux"
+
+def getstatusoutput(cmd):
+    """Return (status, output) of executing cmd in a shell."""
+    pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
+    text = pipe.read()
+    sts = pipe.close()
+    if sts is None: sts = 0
+    if text[-1:] == '\n': text = text[:-1]
+    return sts, text
+
+def get_kernel_grub_line(kernel):
+    return "title=%s (%s)\n" % (DISTRO_NAME, os.path.basename(kernel),)
+
+def configure_boot_grub(kernel, initramfs):
+
+    grub_dir = os.path.dirname(GRUB_CONF)
+    if not os.path.isdir(grub_dir):
+        os.makedirs(grub_dir)
+
+    if os.access(GRUB_CONF, os.R_OK | os.F_OK):
+
+        # open in append
+        grub = open(GRUB_CONF,"aw")
+        shutil.copy2(GRUB_CONF, GRUB_CONF+".add")
+        # get boot dev
+        boot_dev = get_grub_boot_dev()
+        # test if entry has been already added
+        grubtest = open(GRUB_CONF,"r")
+        content = grubtest.readlines()
+        content = [unicode(x,'raw_unicode_escape') for x in content]
+        for line in content:
+
+            if line.find(get_kernel_grub_line(kernel)) != -1:
+                grubtest.close()
+                print "** Kernel already in configuration => ", line.strip()
+                return
+
+            # also check if we have the same kernel listed
+            if (line.find("kernel") != 1) and \
+                (line.find(os.path.basename(kernel)) != -1) and not \
+                line.strip().startswith("#") \
+                and (line.find("safe mode") == -1):
+
+                grubtest.close()
+                print "** Kernel already in configuration (2) => ", line.strip()
+                return
+    else:
+
+        # create
+        boot_dev = get_grub_boot_dev()
+        grub = open(GRUB_CONF,"w")
+        # write header - guess (hd0,0)... since it is weird
+        # having a running system without a bootloader, at least, grub.
+        grub.write("default=0\ntimeout=10\n")
+
+    cmdline = ''
+    if os.access("/proc/cmdline", os.R_OK):
+        cmdline_f = open("/proc/cmdline","r")
+        cmdline = " "+cmdline_f.readline().strip()
+        cmdline_f.close()
+
+    grub.write(get_kernel_grub_line(kernel))
+    grub.write("\troot "+boot_dev+"\n")
+    grub.write("\tkernel "+kernel+cmdline+"\n")
+    if initramfs:
+        grub.write("\tinitrd "+initramfs+"\n")
+    grub.write("\tsavedefault\n")
+    grub.write("\n")
+    grub.flush()
+    grub.close()
+
+def remove_boot_grub(kernel, initramfs):
+
+    grub_dir = os.path.dirname(GRUB_CONF)
+    if not os.path.isdir(grub_dir):
+        os.makedirs(grub_dir)
+
+    if os.path.isdir(grub_dir) and os.access(GRUB_CONF, os.R_OK | os.F_OK):
+
+        shutil.copy2(GRUB_CONF, GRUB_CONF+".remove")
+        grub_f = open(GRUB_CONF,"r")
+        grub_conf = grub_f.readlines()
+        grub_f.close()
+
+        content = [unicode(x,'raw_unicode_escape') for x in grub_conf]
+        if not isinstance(kernel, unicode):
+            kernel = unicode(kernel,'raw_unicode_escape')
+        if not isinstance(initramfs, unicode):
+            initramfs = unicode(initramfs,'raw_unicode_escape')
+
+        new_conf = []
+        skip = False
+        for line in content:
+
+            kernel_grub_line = get_kernel_grub_line(kernel)
+            if (line.find(kernel_grub_line) != -1):
+                skip = True
+                continue
+
+            if line.strip().startswith("title"):
+                skip = False
+
+            if not skip or line.strip().startswith("#"):
+                new_conf.append(line)
+
+        grub_tmp_f = open(GRUB_CONF+".tmp","w")
+        for line in new_conf:
+            try:
+                grub_tmp_f.write(line)
+            except UnicodeEncodeError:
+                grub_tmp_f.write(line.encode('utf-8'))
+        grub_tmp_f.flush()
+        grub_tmp_f.close()
+        os.rename(GRUB_CONF+".tmp", GRUB_CONF)
+
+def boot_device_translation(boot_dev):
+
+    # actually disabled due to buggy grub.conf entry
+    if os.access(GRUB_CONF, os.R_OK | os.F_OK) and 0:
+
+        f_grub = open(GRUB_CONF, "r")
+        stored_boot_dev = [x.strip() for x in f_grub.readlines() if \
+            x.strip().startswith("#boot=")]
+        f_grub.close()
+        if stored_boot_dev:
+            stored_boot_dev = stored_boot_dev[0]
+            boot_dev = "/dev/" + stored_boot_dev[len("#boot="):]
+
+    if boot_dev.startswith("/dev/md"):
+
+        boot_dev = os.path.realpath(boot_dev)
+        md_dev = os.path.basename(boot_dev)
+
+        if os.access("/proc/mdstat", os.R_OK | os.F_OK):
+
+            f_mdstat = open("/proc/mdstat","r")
+            stored_boot_dev = [x.split() for x in f_mdstat.readlines() if \
+                x.startswith(md_dev)]
+            f_mdstat.close()
+
+            if stored_boot_dev:
+                stored_boot_dev = stored_boot_dev[0]
+                for elem in stored_boot_dev:
+                    if elem.endswith("[0]"):
+                        boot_dev = "/dev/" + elem[:-len("[0]")]
+                        break
+
+    return boot_dev
+
+def resolve_device(device):
+    if device.startswith("/dev/"):
+        return device
+    if device.startswith("UUID=") or device.startswith("LABEL="):
+        print "resolving UUID/LABEL to device", device
+        rc, outstring = getstatusoutput("blkid -lt %s" % (device,))
+        if rc != 0:
+            print "cannot resolve UUID/LABEL for", device
+            return None # argh!
+        device = outstring.split(":")[0]
+        print "UUID/LABEL resolved to", device
+    return device
+
+def get_grub_boot_dev():
+
+    grub_avail = subprocess.call("which grub &> /dev/null", shell = True)
+    if grub_avail != 0:
+        print "** Cannot find grub. Cannot properly configure kernel"
+        return "(hd0,0)"
+
+    # load currently mounted partitions
+    if not os.access(FSTAB_CONF, os.R_OK | os.F_OK):
+        print "** Cannot find %s. Cannot properly configure kernel" % (
+            FSTAB_CONF,)
+        return "(hd0,0)"
+
+    f_fstab = open(FSTAB_CONF, "r")
+    mount_data = [x.split() for x in f_fstab.readlines()]
+    f_fstab.close()
+    # filter out bogus devices
+    mount_data = [x for x in mount_data if x]
+    mount_data = [x for x in mount_data if x[0].startswith("/") or \
+        x[0].startswith("UUID=") or x[0].startswith('LABEL=')]
+    
+    mount_hash = {}
+    for item in mount_data:
+        solved_dev = resolve_device(item[0])
+        if not solved_dev:
+            continue
+        mount_hash[item[1]] = solved_dev
+    boot_dev = mount_hash.get(NO_SYS_ROOT_BOOT_DIR, mount_hash.get("/"))
+    if boot_dev == None:
+        print "** Cannot determine boot device. Cannot properly configure" \
+            " kernel"
+        return "(hd0,0)"
+
+    # translate boot device, if needed
+    boot_dev = boot_device_translation(boot_dev)
+
+    # load grub map file
+    map_file = "grub.map"
+    subprocess.call('echo "quit" | grub --no-floppy --no-config-file ' \
+        '--no-curses --batch --device-map=grub.map &> /dev/null', shell = True)
+    if not os.access(map_file, os.R_OK | os.F_OK):
+        print "** Cannot find grub. Cannot properly configure kernel"
+        return "(hd0,0)"
+
+    f_map = open(map_file)
+    map_data = [x.split() for x in f_map.readlines()]
+    f_map.close()
+    os.remove(map_file)
+    map_data = dict(((y, x) for x, y in map_data))
+
+    map_data_devs = map_data.keys()
+    grub_dev = None
+    linux_dev = None
+    for dev in map_data_devs:
+        if boot_dev.startswith(dev):
+            grub_dev = map_data.get(dev)
+            linux_dev = dev
+            break
+
+    if grub_dev == None:
+        print "** Cannot match grub device. Cannot properly configure kernel"
+        return "(hd0,0)"
+
+    device_number = boot_dev.replace(linux_dev,'')
+    try:
+        device_number = int(device_number)
+    except ValueError:
+        print "** Cannot get device number for '%s' => '%s' | '%s'. Cannot properly configure kernel" % (
+	    device_number, boot_dev, linux_dev,)
+        return "(hd0,0)"
+
+    device_number -= 1
+    grub_boot_dev = grub_dev.replace(')',',%s)' % (device_number,))
+    return grub_boot_dev
+
+def print_help():
+    print "%s %s %s %s" % (sys.argv[0], "[add/remove]",
+        "<kernel>", "<initramfs or 'none'>",)
+
+def add_kernel(kernel, initramfs):
+
+    boot_len = len(NO_SYS_ROOT_BOOT_DIR)
+    if BOOT_MOUNT:
+        kernel = kernel[boot_len:]
+        if initramfs:
+            initramfs = initramfs[boot_len:]
+
+    # configure GRUB
+    print "** Configuring GRUB bootloader. Adding the new kernel ..."
+    configure_boot_grub(kernel, initramfs)
+
+def remove_kernel(kernel, initramfs):
+
+    boot_len = len(NO_SYS_ROOT_BOOT_DIR)
+    if BOOT_MOUNT:
+        kernel = kernel[boot_len:]
+        if initramfs:
+            initramfs = initramfs[boot_len:]
+
+    # configure GRUB
+    print "** Configuring GRUB bootloader. Removing the selected kernel ..."
+    remove_boot_grub(kernel, initramfs)
+
+
+
+if __name__ == "__main__":
+
+    args = sys.argv[1:]
+    if len(args) < 3:
+        print_help()
+        raise SystemExit(1)
+
+    cmd = args[0]
+    if cmd not in ("add", "remove",):
+        print_help()
+        raise SystemExit(1)
+
+    kernel = args[1]
+    initramfs = args[2]
+
+    if initramfs == "none":
+        initramfs = ''
+
+    if cmd == "add":
+        print "** Adding kernel '%s' and initramfs '%s'" % (kernel, initramfs,)
+        add_kernel(kernel, initramfs)
+    elif cmd == "remove":
+        print "** Removing kernel '%s' and initramfs '%s'" % (kernel,
+            initramfs,)
+        remove_kernel(kernel, initramfs)
+    raise SystemExit(0)

diff --git a/sys-boot/grub-handler/grub-handler-0.2-r6.ebuild b/sys-boot/grub-handler/grub-handler-0.2-r6.ebuild
new file mode 100644
index 0000000..ec1e3c8
--- /dev/null
+++ b/sys-boot/grub-handler/grub-handler-0.2-r6.ebuild
@@ -0,0 +1,20 @@
+# Copyright 2009 Sabayon Linux
+# Distributed under the terms of the GNU General Public License v2
+
+inherit eutils
+
+DESCRIPTION="Sabayon Linux GRUB utilities"
+HOMEPAGE="http://www.sabayonlinux.org/"
+SRC_URI=""
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="x86 amd64"
+IUSE=""
+
+RDEPEND=""
+DEPEND="${RDEPEND}"
+
+src_install () {
+	exeinto /usr/sbin
+	doexe "${FILESDIR}/${PN}"
+}

diff --git a/sys-boot/grub/Manifest b/sys-boot/grub/Manifest
new file mode 100644
index 0000000..f46c98d
--- /dev/null
+++ b/sys-boot/grub/Manifest
@@ -0,0 +1,53 @@
+AUX 00_fonts 462 RMD160 828b03d1201aa8b8abe339305ff4e2a8b99d1d33 SHA1 fcdaf4ac95ca318750c33153be993dac0e9c8c99 SHA256 fbe13c4e5373835fb529c6c9454ac07a3e523bd56529483d0ec86f9583ae8fed
+AUX 05_distro_theme 1180 RMD160 ee8d8707e07dbf9877be5bbc9322263822d4ddad SHA1 ad9fb101b7f959ca2392d404a86bec299f326c88 SHA256 cff76aaf874da7270265eca015ffada92f30609699f8cc956a4df0c480a9a5fc
+AUX default-splash-5.4.png 641815 RMD160 175bf793a542654e765fecca89f6c628e7a8a586 SHA1 a8ceabcef3854517d879522ab5155540ddeca3d9 SHA256 f9eedc888fd11d899000397f073d042ce5a4230923966f9d12828263f0a2d14a
+AUX default-splash-6.png 1006813 RMD160 9c00ed318f4b40486289b1bcf9d7d085d5d9c67c SHA1 aea9184f94b7c60deef172e730b5aada5fe209de SHA256 27da12fccce3fc4a40724471b9ebd4c2fed30c743fcd049a4c53963f87e17e24
+AUX default-splash.png 379111 RMD160 c399047d7d63e72495416f0f25cdc4c7bcc38946 SHA1 d0e6e920e4ce973c460d4bb994e4a87e2e32e8aa SHA256 09de78447d236669252b4669a341b5589043466bcb6bbf80e334462024c655c8
+AUX grub-0.97-gfxmenu-v8.patch 23313 RMD160 ee79292a61a4fcbfa2afe5bea56e56ee4efbfe01 SHA1 b4e567009e61e9bc6a2e60bae3333681c458debc SHA256 c2f7897027842631a95a654e7978d43e6d21d8c06426ff2d966678e3fca0ba4a
+AUX grub-0.97-uuid.patch 144339 RMD160 58816e0fc819a0c5afc2da0024611ec650119be2 SHA1 9b5a0fb112eaf143b8b81f487b3b515a13423372 SHA256 9766e446665a955e2dab10e5e42d83b3384b5e6e306c3eba70a08f35a3fbf129
+AUX grub-0.97-uuid_doc.patch 1364 RMD160 667f9e91ed037cac61a00e2ea4dda5d94ad4369c SHA1 1b12abc7270624c8192bdc692264584eea947e9a SHA256 371ca0229b5036071f418f4ca3d8b724b2ea8719954edadbf4ddfa4e937a089b
+AUX grub-1.96-genkernel.patch 634 RMD160 bc1fdaa51e3f0e3b777a303e0f1c76987c7e69e5 SHA1 e79384a3ac32bfd74c884ead8133b1691a743316 SHA256 8ee327465d9b6d704a78b0c7b31cfdee7c6e7e9f9897e8d0a86198430f0c6ea0
+AUX grub-1.97-genkernel.patch 998 RMD160 7b52c250c821f4c57c61a11d5f1f430795521b20 SHA1 30e4612a70a3bda444f29f3de35e838ed2c2c9e4 SHA256 a0cfc467d85e50108fbb9f2d76de24db0557e53aadb7afd8562404c138548625
+AUX grub-1.97-hostdisk.patch 1840 RMD160 bb6ea6dc165e12e3af61bcc159dafdbd9d439370 SHA1 478bf182c4d5371b8e08d50d47b318fc5e99d49a SHA256 dec80ac94b7e3d7ececca3e11b2afc9f65f8ce38ca27091d13b81484eae3ef57
+AUX grub-1.97-vga-deprecated.patch 477 RMD160 7cbdb7fad80b409f3939e728131e368b08cf0766 SHA1 a77497bd36c28221a7cc166dc1130b404fe05aa2 SHA256 2a95589c2967f3991289fe86bd3697fdd6f43282226a6ac5947b546c49ca2e00
+AUX grub-1.97-wallpaper-settings-support.patch 545 RMD160 701b01fbd760bc6413570d4399f5eb929005d81d SHA1 e599af9cfeefff585c9e2bce064ad988145dc2eb SHA256 8d9415fb6bbde2563f7713291396cef226f83a7c95d0ed86124e582463c04f3f
+AUX grub-1.98-add-legacy-rootfs-detection.patch 2250 RMD160 684cd457b26e25ace6a5e725a69d815ac356c098 SHA1 282c6df94df7e0daf5c7f29525fb2095d11a45ee SHA256 bc337f2cea948ab385a2085d08e6ed92434bfef4ad3b8100fa58efd910d2aefe
+AUX grub-1.98-follow-dev-mapper-symlinks.patch 793 RMD160 fe6ab74c302555e434c6e0c69022ba93c6b5ed4e SHA1 4f4e2f4b59d231566b63e611ae0d1cbb4b76d143 SHA256 82227c1fc973c2b075a222bc7b4d0a7bc4a59143a170e04090a27a7950080dd4
+AUX grub-1.98-genkernel-initramfs-single.patch 457 RMD160 62d63c5cbeffa7b1323964818253b4b14f6bdbee SHA1 d56ed964a8250928dd39a844f9950cc924988322 SHA256 6c95716ebd62fb1710ae86ee65bba159c90f2468b0af4e4bb63cb18dea2ac430
+AUX grub-1.98-genkernel.patch 1095 RMD160 597ea9c38f52f3f733fb68c2b8e7951e14cd6963 SHA1 afd82815bd292f517d9aa56128ee321fdc2071f9 SHA256 ef07667e5601a3dcf0e26e639b0a3acbf03484effe182aec16afdfebcdd110fc
+AUX grub-1.98-wallpaper-settings-support.patch 520 RMD160 49bc8578c63aa6294e9bbad53d98a7460135a539 SHA1 ba4ea49dc6b8e70ee6ef12ba5b4be91fed608765 SHA256 605a922190a848bf2c68c2e8ff9d425b792758739c25f739d0ab4ffe8dcddbf1
+AUX grub-1.99-disable-floppies.patch 763 RMD160 a169a6e23e20e42b681a21e0c448d94d18661334 SHA1 49db692f53ecf5e4a682ca4d73d0c41117151f11 SHA256 b1bebdc1fd62534b05907a9aaab2571be05047321320f9a8afece875225d6d5d
+AUX grub-1.99-genkernel.patch 433 RMD160 36be73354333ba3ea6ef7b25d4d55e889d21aba5 SHA1 a4e1a2a3635778387737316156c30370a2200d5c SHA256 368171fa84d446c93479973013105f2eab9eaf0e407b37693e491b4492618880
+AUX grub-1.99-vga-deprecated-not-yet.patch 575 RMD160 21f930d2ac90da42a52e95a8ed6fb07925b41554 SHA1 9efe1ecb47ee3882ba7bd635e4108da8df07f8d5 SHA256 d16821ea7c2bc49f16912880d0d5a32d3a517893d4ca339acdb845259902a820
+AUX grub-1.99-vga-deprecated.patch 408 RMD160 8b2c8560d8bf39bc06a110eaa81a388c3fd49b42 SHA1 7e7f196b86c6d8634e3889881687f5d303fa3d5e SHA256 55dd23c6a6a862a045b71e6dd564c76df08086af0d05a16311f46cc1a5f7941a
+AUX grub-1.99-wallpaper-settings-support.patch 521 RMD160 5a47c70dfc686a3741f99e4aad475f30c38a6876 SHA1 e70335fb11e92a182462f92866bf31324d070c34 SHA256 d21265645972e57278341cd27b1406f9f630f94cc1722374832cca95453ce807
+AUX grub-1.99-workaround-raid-bios-bug.patch 808 RMD160 749e9eacf6cb9c58274b77720650d77a86cd3604 SHA1 60fde97e779e940207376723535ad523b92a0531 SHA256 011c480d2001e37a8b7a347ddabe072c5c912932deda016badeeb1e57a6f63d6
+AUX grub.conf.gentoo 627 RMD160 d90fb4373bad476f98ec9c5065d6cdfd9e3b706f SHA1 004f2fc04605ec9190de0a87e7df8bbc33daff89 SHA256 914b15af252210a32776196437cd8013e10e57d5780e66877ef3fe9a2b4b9776
+AUX grub2-default 2084 RMD160 1a7ed37eeda753b279c6f6d864d9122d439631da SHA1 c2f697c4c525c50931b8f00864af0a9249c08777 SHA256 df286f514070ba4e4ee70a65f7f68a7103ffba4d230fb1dc99f9667515a9ca16
+AUX grub2-default-1.99 2113 RMD160 2ad38a800e66d7cb904b77e0167f4da51e390b0d SHA1 4b191d88d42e865d3efa882601da52ad6ace62be SHA256 b6e255a0e4127709e92d4049b23295feab6c026e7945b3b0ec4f675d9058a45e
+AUX splash.xpm.gz 6251 RMD160 d7b6f187c45597dab59415163fc9d0c154d40cbe SHA1 3b8615b6e105fcbcd6530b46947e06d480caa8f4 SHA256 46397f66ab9dbb2215d5191d94e6ca5aecb53f84ad70cc17aeb319353ba201b2
+AUX ubuntu-upstream-1.98/01_uuids_and_lvm_dont_play_along_nicely.diff 611 RMD160 0269ad21a4e5723383b2f04670088cc6b1a1e636 SHA1 344e63b80d9e3d057d41bc50e980a1b1c311a426 SHA256 282635fd75266dfe9222afc892f02a9f9fbc227f05556054531fb63704f9cd55
+AUX ubuntu-upstream-1.98/902_boot_blocklist_hack.diff 590 RMD160 12856f69930dc7783cf4184cc431e43d91f83b49 SHA1 941ed1934cf60c3564da010cd975248b92e321f4 SHA256 27466e25257cc267b0048086ae0ad76aa07bd703fa1827342c83b11bff843b84
+AUX ubuntu-upstream-1.98/904_disable_floppies.diff 743 RMD160 bc98e9c85245edac6c666f0eeca51da2b6b9cfb6 SHA1 bdba3cfe65b73c86ab3e74858a6baa3f8b20cf1e SHA256 930b1d38af76e477d4c0d9e357441882da3367fbe107561aa7fc25e8ccad2a80
+AUX ubuntu-upstream-1.98/956_loopback_root.diff 3893 RMD160 cd235a733fd209fc4a4ead82756b5dd3765fd97c SHA1 f47642fd61690ade9096ca170e8dfe6c81315df7 SHA256 aff4cb00a6915749a31441fd777b23328647fbad52095cf2eb9cf313af45f0e3
+AUX ubuntu-upstream-1.98/957_handle_loopback.diff 1601 RMD160 601da4911f5929ad44eea07cf78928b145f5d8d1 SHA1 01d03179ada50ee744f06d2f175d7966efc1c06d SHA256 64f735f93dd08f67042e8159af11653095a6707efa3cccc21ea8b0bd6078e7ec
+AUX ubuntu-upstream-1.98/958_linux_no_loopmount.diff 772 RMD160 05d5f158c5280a1ee9e7961d4f3069aacb7ca632 SHA1 7bb9547c634b5f9c44106cb43b9d843efc49e442 SHA256 aea5604df288a1809d406321200c5f4de13c04c5af91610b6b89a09add11ba37
+AUX ubuntu-upstream-1.98/960_raid_virtio.diff 4372 RMD160 76cc430483034d1821ec285f4799b4f841649401 SHA1 10904dce33757f4bcdbb0c7451106ef88bd453a4 SHA256 9ebb1ab4caaf72303ee6ab309bd0117674d20d15358f8f91800abd714555baf0
+AUX ubuntu-upstream-1.98/961_dmraid_probe.diff 17773 RMD160 ebdece5470a4f2248d5ccf086543d607092a205a SHA1 8e342077cc26c4185896729da5482070be0be973 SHA256 0c068a31fb30f139f9284d0b2df8334e07cf49a3912da9327278e3085f7fa2ff
+AUX ubuntu-upstream-1.98/962_no_device_map.diff 3556 RMD160 3c5ab122095e4ead78ba4504ff00b84277fa3f79 SHA1 9bf10e7e2f99ef6f41f901af10c3b6383bd8b371 SHA256 69d9dbb92fb7b05bb2441265d4fd9d592296dd85754212f7e9f3dfcf7e11d13f
+AUX ubuntu-upstream-1.98/968_hostdisk_speedup.diff 9928 RMD160 abfd47d57a3f7dbd4d9e4f1e6f679402c6891128 SHA1 e6a7d804139d5d1e8cd7f303a53bd37b6b83d02b SHA256 2ad5578356748f85c3bdaa24214613f2f061619ae4ea8e3db2fa1aeffe481f11
+AUX ubuntu-upstream-1.98/969_lvm_raid_probe.diff 7890 RMD160 3d109278f3fdc5e24cbc8d8a6a6a5403e128a91f SHA1 6c53f1d1720ce70d82da2f6b525340b0b764396d SHA256 207a4ebafdead64387bca3a071465dcabb6179b3cfdc179965c4530ad571f1d2
+AUX ubuntu-upstream-1.98/970_fix_locale_installation.diff 2332 RMD160 91465a322dc4fe64110b00c48e8364615b0dc8db SHA1 50489d6de1276e16970dce9fac894e5983f9be5d SHA256 b748151f4e16862136ac0f74604259a146ee9329043193230d44e9570e810456
+AUX ubuntu-upstream-1.98/971_langpacks.diff 1266 RMD160 a9dc3b8c32a4903b8cf8c3b0f65b538b46749100 SHA1 29c681dd01942760f078f889cb9bf66a8a2a24c6 SHA256 c2ec2b37b5fbdd10214150659bca41c3dc016d75060e17d36f191af314222bc5
+AUX ubuntu-upstream-1.98/974_drive_probe.diff 959 RMD160 639eb5037c1e1e6e3bb58282dc7dd41333a6a7a5 SHA1 1698d3366e2aeb7aeca906059544d955744dd071 SHA256 4e73d0330b5093f48151e65d7bf12bb2a968d6ecfeccf0bdc97a48000cb43b03
+AUX ubuntu-upstream-1.98/975_hostdisk_hd.diff 4125 RMD160 bc514a49151ca9e155be5bea0974dd564c922f8b SHA1 1bda370ec48ee6660fa6b8ed2c9eaf3c2a84504d SHA256 0c53c9ab6d161c316a0f0d0e9476004f66e44d664c95e23c6324ef821b2970a9
+AUX ubuntu-upstream/01_uuids_and_lvm_dont_play_along_nicely.diff 611 RMD160 0269ad21a4e5723383b2f04670088cc6b1a1e636 SHA1 344e63b80d9e3d057d41bc50e980a1b1c311a426 SHA256 282635fd75266dfe9222afc892f02a9f9fbc227f05556054531fb63704f9cd55
+AUX ubuntu-upstream/904_disable_floppies.diff 743 RMD160 bc98e9c85245edac6c666f0eeca51da2b6b9cfb6 SHA1 bdba3cfe65b73c86ab3e74858a6baa3f8b20cf1e SHA256 930b1d38af76e477d4c0d9e357441882da3367fbe107561aa7fc25e8ccad2a80
+DIST grub-0.97-patches-1.9.tar.bz2 51809 RMD160 a745902212dbd22f4d9f0bb0d563ffd44b429eaa SHA1 1d9da2df8bccef9821ebbbc2f5c5353dbd90bf4d SHA256 6b8445c9260803f059031cbe7475a45fee6499fc2dbd911288af6169455c4028
+DIST grub-0.97.tar.gz 971783 RMD160 7fb5674edf0c950bd38e94f85ff1e2909aa741f0 SHA1 2580626c4579bd99336d3af4482c346c95dac4fb SHA256 4e1d15d12dbd3e9208111d6b806ad5a9857ca8850c47877d36575b904559260b
+DIST grub-1.98.tar.gz 2449386 RMD160 197fb8d7c673bd67ae81eda53a2baa2968cc1e69 SHA1 e83a2c438f4773a2e272c225983c0145e1ffd641 SHA256 bef2c1892e052967b65aab6aa62ac702c0e50ef8848506eacf3c0b2f5007c614
+DIST grub-1.99.tar.xz 2639224 RMD160 d59a47fa40b2be0d5ea5b2b00ff5538cfa147747 SHA1 a5ae9558f30ce7757a76aa130088b053a87e2fb6 SHA256 f308148d4c83c6f16a73b58a0cd39381656edb740929028cae7ad5f0d651021b
+EBUILD grub-0.97-r22.ebuild 7588 RMD160 86e8c77ec7ee193919bdec359e53a8236a4b4c77 SHA1 212944ff569048769c15fd6676a63e6eea4c0cef SHA256 ff5b303cedd5a05c39f8903fbfb215512ab58f12ff023773d739eb3fa244f8bd
+EBUILD grub-1.98-r10.ebuild 3654 RMD160 872a03a3073ca18bc853048b65159af52495c915 SHA1 1cb89aa08a8265a97834964661999cfe93c99b6b SHA256 875e175940856ef613be27a65f136772a366c93289100abc07cb083333ae46df
+EBUILD grub-1.98-r9.ebuild 3799 RMD160 70067983c5394c5f2f876e8be18eee97bf1dd4dd SHA1 149c73a384e913b0d27b7fee61d4d0110cf0eb34 SHA256 271d79ea8be44a6aeebcf9af6676a2c90c4ec43120882225a5b5b8fe3ba4f6d5
+EBUILD grub-1.99.ebuild 7808 RMD160 0fa7ce32a511cf50f19f1fbda105895481dab7b3 SHA1 84442136e82509c963ee7ce390be794368f9fee7 SHA256 be84ddee0a8b02572b5b201afd4cd250fffe80f25a4524ce33c6e1dc7cf1cda2

diff --git a/sys-boot/grub/files/00_fonts b/sys-boot/grub/files/00_fonts
new file mode 100755
index 0000000..d2dcbaf
--- /dev/null
+++ b/sys-boot/grub/files/00_fonts
@@ -0,0 +1,14 @@
+# Create required fonts, otherwise graphic mode won't be loaded
+if [ -x "/bin/grub-mkfont" ]; then
+	# This is the bare minimum
+	grub-mkfont --output=/boot/grub/unifont.pf2 \
+		/usr/share/fonts/unifont/unifont.pcf.gz
+
+	# let's load DejaVu if exists, no deps against it
+	# to avoid crazy deps on critical pkg
+	if [ -x "/usr/share/fonts/dejavu/DejaVuSans.ttf" ]; then
+		grub-mkfont --output=/boot/grub/dejavu.pf2 \
+			/usr/share/fonts/dejavu/DejaVuSans.ttf
+	fi
+
+fi

diff --git a/sys-boot/grub/files/05_distro_theme b/sys-boot/grub/files/05_distro_theme
new file mode 100644
index 0000000..cb4c197
--- /dev/null
+++ b/sys-boot/grub/files/05_distro_theme
@@ -0,0 +1,51 @@
+#!/bin/bash -e
+
+. /lib/grub/grub-mkconfig_lib
+
+set_blue_theme()
+{
+  cat << EOF
+set menu_color_normal=cyan/blue
+set menu_color_highlight=white/blue
+EOF
+}
+
+# check for usable backgrounds
+use_bg=false
+if [ "$GRUB_TERMINAL_OUTPUT" = "gfxterm" ] && [ -n "${GRUB_WALLPAPER}" ]; then
+  for i in /boot/grub/`basename ${GRUB_WALLPAPER}` ${GRUB_WALLPAPER} ; do
+    if is_path_readable_by_grub $i ; then
+      bg=$i
+      case ${bg} in
+        *.png)     reader=png ;;
+        *.tga)     reader=tga ;;
+        *.jpg|*.jpeg)  reader=jpeg ;;
+      esac
+      if test -e /boot/grub/${reader}.mod ; then
+        echo "Found background image: `basename ${bg}`" >&2
+        use_bg=true
+        break
+      fi
+    fi
+  done
+fi
+
+# set the background if possible
+if ${use_bg} ; then
+  prepare_grub_to_access_device `${grub_probe} --target=device ${bg}`
+  cat << EOF
+insmod ${reader}
+if background_image `make_system_path_relative_to_its_root ${bg}` ; then
+  set color_normal=${GRUB_COLOR_NORMAL}
+  set color_highlight=${GRUB_COLOR_HIGHLIGHT}
+else
+EOF
+fi
+
+# otherwise, set the traditional Debian blue theme
+if ${use_bg} ; then
+  set_blue_theme | sed -e "s/^/  /g"
+  echo "fi"
+else
+  set_blue_theme
+fi

diff --git a/sys-boot/grub/files/default-splash-5.4.png b/sys-boot/grub/files/default-splash-5.4.png
new file mode 100644
index 0000000..2197887
Binary files /dev/null and b/sys-boot/grub/files/default-splash-5.4.png differ

diff --git a/sys-boot/grub/files/default-splash-6.png b/sys-boot/grub/files/default-splash-6.png
new file mode 100644
index 0000000..6e61b40
Binary files /dev/null and b/sys-boot/grub/files/default-splash-6.png differ

diff --git a/sys-boot/grub/files/default-splash.png b/sys-boot/grub/files/default-splash.png
new file mode 100644
index 0000000..263b1ee
Binary files /dev/null and b/sys-boot/grub/files/default-splash.png differ

diff --git a/sys-boot/grub/files/grub-0.97-gfxmenu-v8.patch b/sys-boot/grub/files/grub-0.97-gfxmenu-v8.patch
new file mode 100644
index 0000000..7921fc8
--- /dev/null
+++ b/sys-boot/grub/files/grub-0.97-gfxmenu-v8.patch
@@ -0,0 +1,1003 @@
+diff -Nurp grub-0.97.orig/docs/grub.texi grub-0.97/docs/grub.texi
+--- grub-0.97.orig/docs/grub.texi	2009-08-03 16:25:36.636294219 +0200
++++ grub-0.97/docs/grub.texi	2009-08-03 16:25:52.207398764 +0200
+@@ -2118,6 +2118,7 @@ These commands can only be used in the m
+ * default::                     Set the default entry
+ * fallback::                    Set the fallback entry
+ * hiddenmenu::                  Hide the menu interface
++* gfxmenu::                     Use graphical menu interface
+ * timeout::                     Set the timeout
+ * title::                       Start a menu entry
+ @end menu
+@@ -2150,6 +2151,15 @@ fallback entry numbers.
+ @end deffn
+ 
+ 
++@node gfxmenu
++@subsection gfxmenu
++
++@deffn Command gfxmenu file
++Use the graphical menu interface. The graphics data are taken from
++@var{file} and must be created using 'mkbootmsg' from the gfxboot package.
++@end deffn
++
++
+ @node hiddenmenu
+ @subsection hiddenmenu
+ 
+diff -Nurp grub-0.97.orig/grub/asmstub.c grub-0.97/grub/asmstub.c
+--- grub-0.97.orig/grub/asmstub.c	2009-08-03 16:25:36.483169221 +0200
++++ grub-0.97/grub/asmstub.c	2009-08-03 16:25:52.217342924 +0200
+@@ -480,6 +480,32 @@ set_vbe_mode (int mode_number)
+   return 0;
+ }
+ 
++/* graphical menu functions .  */
++int
++gfx_init (gfx_data_t *gfx_data)
++{
++  return 0;
++}
++
++int
++gfx_done (gfx_data_t *gfx_data)
++{
++  return 0;
++}
++
++int
++gfx_input (gfx_data_t *gfx_data, int *menu_entry)
++{
++  return 0;
++}
++
++int
++gfx_setup_menu (gfx_data_t *gfx_data)
++{
++  return 0;
++}
++
++
+ /* low-level timing info */
+ int
+ getrtsecs (void)
+diff -Nurp grub-0.97.orig/stage2/asm.S grub-0.97/stage2/asm.S
+--- grub-0.97.orig/stage2/asm.S	2004-06-19 18:55:22.000000000 +0200
++++ grub-0.97/stage2/asm.S	2009-08-03 16:25:52.218406926 +0200
+@@ -1610,6 +1610,286 @@ ENTRY(set_vbe_mode)
+ 	popl	%ebp
+ 	ret
+ 
++
++/*
++ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
++ *
++ * graphical menu functions
++ *
++ */
++
++/*
++ * int gfx_init (gfx_data_t *gfx_data)
++ *
++ * init gfx things
++ *
++ * return vales:
++ *   0: ok
++ *   1: failed
++ *   sets gfx_data->ok
++ */
++
++ENTRY(gfx_init)
++	pushl	%ebp
++	movl	%esp, %ebp
++	
++	pushl	%edi
++	pushl	%esi
++	pushl	%ebx
++
++	movl	8(%ebp),%edx
++	movl	%edx,%edi
++	leal	gfx_ofs_sys_cfg(%edx),%esi
++	andl	$0xf,%edi
++	shrl	$4,%edx
++
++	pushl	%ebp
++
++	call	EXT_C(prot_to_real)
++	.code16
++
++	pushw	%ds
++	movw	%dx,%ds
++
++	lcall	*gfx_ofs_jmp_table + 4 * 0 (%di)
++
++	sbbl	%ebx,%ebx
++	negl	%ebx
++
++	popw	%ds
++
++	DATA32	call	EXT_C(real_to_prot)
++	.code32
++
++	popl	%ebp
++
++	movl	%ebx,%eax
++	xorl	$1,%ebx
++	movl	8(%ebp),%edx
++	movl	%ebx,gfx_ofs_ok(%edx)
++
++	popl	%ebx
++	popl	%esi
++	popl	%edi
++
++	popl	%ebp
++	ret
++
++
++/*
++ * int gfx_done (gfx_data_t *gfx_data)
++ *
++ * shut down gfx things
++ *
++ * return vales:
++ *   always 0
++ *   sets gfx_data->ok
++ */
++
++ENTRY(gfx_done)
++	pushl	%ebp
++	movl	%esp, %ebp
++	
++	pushl	%edi
++	pushl	%esi
++	pushl	%ebx
++
++	movl	8(%ebp),%edx
++	movl	%edx,%ebx
++	andl	$0xf,%ebx
++	shrl	$4,%edx
++
++	pushl	%ebp
++
++	call	EXT_C(prot_to_real)
++	.code16
++
++	pushw	%ds
++
++	movw	%dx,%ds
++
++	lcall	*gfx_ofs_jmp_table + 4 * 1 (%bx)
++
++	popw	%ds
++
++	DATA32	call	EXT_C(real_to_prot)
++	.code32
++
++	popl	%ebp
++
++	xorl	%eax,%eax
++	movl	8(%ebp),%edx
++	movl	%eax,gfx_ofs_ok(%edx)
++
++	popl	%ebx
++	popl	%esi
++	popl	%edi
++
++	popl	%ebp
++	ret
++
++
++/*
++ * int gfx_input (gfx_data_t *gfx_data, int *menu_entry)
++ *
++ * let user enter a command line
++ *
++ * uses gfx_data->cmdline as buffer
++ *
++ * return values:
++ *   1: abort
++ *   2: boot
++ *   menu_entry: selected entry
++ */
++
++ENTRY(gfx_input)
++	pushl	%ebp
++	movl	%esp, %ebp
++	
++	pushl	%edi
++	pushl	%esi
++	pushl	%ebx
++
++	movl	8(%ebp),%edx
++	movl	%edx,%ebx
++	leal	gfx_ofs_sys_cfg(%edx),%esi
++	andl	$0xf,%ebx
++	shrl	$4,%edx
++
++	pushl	%ebp
++
++	call	EXT_C(prot_to_real)
++	.code16
++
++	pushw	%ds
++
++	movw	%dx,%ds
++
++	movl	gfx_ofs_cmdline(%bx),%edi
++	movl	gfx_ofs_cmdline_len(%bx),%ecx
++	movl	gfx_ofs_timeout(%bx),%eax
++	imull	$18,%eax
++
++	lcall	*gfx_ofs_jmp_table + 4 * 2 (%bx)
++
++	movl	%eax,%ecx
++
++	popw	%ds
++
++	DATA32	call	EXT_C(real_to_prot)
++	.code32
++
++	popl	%ebp
++
++	movl	12(%ebp),%edx
++	movl	%ebx,(%edx)
++
++	movl	%ecx,%eax
++
++	popl	%ebx
++	popl	%esi
++	popl	%edi
++
++	popl	%ebp
++	ret
++
++
++/*
++ * int gfx_setup_menu (gfx_data_t *gfx_data)
++ *
++ * draw boot menu
++ *
++ * return values:
++ *   always 0
++ */
++
++/* menu entry descriptor */
++#define menu_entries		0
++#define menu_default		2	/* seg:ofs */
++#define menu_ent_list		6	/* seg:ofs */
++#define menu_ent_size		10
++#define menu_arg_list		12	/* seg:ofs */
++#define menu_arg_size		16
++#define sizeof_menu_desc	18
++
++ENTRY(gfx_setup_menu)
++	pushl	%ebp
++	movl	%esp, %ebp
++	
++	pushl	%edi
++	pushl	%esi
++	pushl	%ebx
++
++	movl	8(%ebp),%edx
++	movl	%edx,%ebx
++	andl	$0xf,%ebx
++	shrl	$4,%edx
++
++	call	EXT_C(prot_to_real)
++	.code16
++
++	pushw	%ds
++
++	movw	%dx,%ds
++	shll	$4,%edx
++
++	subw	$sizeof_menu_desc,%sp
++	movw	%esp,%ebp
++
++	movl	gfx_ofs_menu_entries(%bx),%eax
++	movw	%ax,menu_entries(%bp)
++
++	movl	gfx_ofs_menu_default_entry(%bx),%eax
++	subl	%edx,%eax
++	movw	%ax,menu_default(%bp)
++	movw	%ds,menu_default+2(%bp)
++
++	movl	gfx_ofs_menu_list(%bx),%eax
++	subl	%edx,%eax
++	movw	%ax,menu_ent_list(%bp)
++	movw	%ds,menu_ent_list+2(%bp)
++
++	movl	gfx_ofs_menu_entry_len(%bx),%eax
++	movw	%ax,menu_ent_size(%bp)
++
++	movl	gfx_ofs_args_list(%bx),%eax
++	subl	%edx,%eax
++	movw	%ax,menu_arg_list(%bp)
++	movw	%ds,menu_arg_list+2(%bp)
++
++	movl	gfx_ofs_args_entry_len(%bx),%eax
++	movw	%ax,menu_arg_size(%bp)
++
++	movl	%ss,%esi
++	shll	$4,%esi
++	addl	%ebp,%esi
++	
++	lcall	%ds: *gfx_ofs_jmp_table + 4 * 3 (%bx)
++
++	addw	$sizeof_menu_desc,%sp
++
++	popw	%ds
++
++	DATA32	call	EXT_C(real_to_prot)
++	.code32
++
++	xorl	%eax,%eax
++
++	popl	%ebx
++	popl	%esi
++	popl	%edi
++
++	popl	%ebp
++	ret
++
++
++/*
++ *
++ * end graphics stuff
++ *
++ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
++ */
++
+ 		
+ /*
+  * gateA20(int linear)
+diff -Nurp grub-0.97.orig/stage2/builtins.c grub-0.97/stage2/builtins.c
+--- grub-0.97.orig/stage2/builtins.c	2009-08-03 16:25:36.601273171 +0200
++++ grub-0.97/stage2/builtins.c	2009-08-03 16:25:52.219523396 +0200
+@@ -67,6 +67,8 @@ int fallback_entryno;
+ int fallback_entries[MAX_FALLBACK_ENTRIES];
+ /* The number of current entry.  */
+ int current_entryno;
++/* graphics file */
++char graphics_file[64];
+ /* The address for Multiboot command-line buffer.  */
+ static char *mb_cmdline;
+ /* The password.  */
+@@ -1335,6 +1337,26 @@ static struct builtin builtin_fstest =
+ };
+ 
+ \f
++/* graphics */
++static int
++gfxmenu_func (char *arg, int flags)
++{
++  memmove(graphics_file, arg, sizeof graphics_file - 1);
++  graphics_file[sizeof graphics_file - 1] = 0;
++
++  return 0;
++}
++
++static struct builtin builtin_gfxmenu =
++{
++  "gfxmenu",
++  gfxmenu_func,
++  BUILTIN_MENU | BUILTIN_HELP_LIST,
++  "gfxmenu FILE",
++  "Use the graphical menu from FILE."
++};
++
++\f
+ /* geometry */
+ static int
+ geometry_func (char *arg, int flags)
+@@ -4989,6 +5011,7 @@ struct builtin *builtin_table[] =
+   &builtin_find,
+   &builtin_fstest,
+   &builtin_geometry,
++  &builtin_gfxmenu,
+   &builtin_halt,
+   &builtin_help,
+   &builtin_hiddenmenu,
+diff -Nurp grub-0.97.orig/stage2/shared.h grub-0.97/stage2/shared.h
+--- grub-0.97.orig/stage2/shared.h	2004-06-19 18:40:09.000000000 +0200
++++ grub-0.97/stage2/shared.h	2009-08-03 16:25:52.219523396 +0200
+@@ -374,6 +374,22 @@ extern char *grub_scratch_mem;
+ #endif /* WITHOUT_LIBC_STUBS */
+ 
+ 
++/* see typedef gfx_data_t below */
++#define gfx_ofs_ok			0x00
++#define gfx_ofs_code_seg		0x04
++#define gfx_ofs_jmp_table		0x08
++#define gfx_ofs_sys_cfg			0x38
++#define gfx_ofs_cmdline			0x6c
++#define gfx_ofs_cmdline_len		0x70
++#define gfx_ofs_menu_list		0x74
++#define gfx_ofs_menu_default_entry	0x78
++#define gfx_ofs_menu_entries		0x7c
++#define gfx_ofs_menu_entry_len		0x80
++#define gfx_ofs_args_list		0x84
++#define gfx_ofs_args_entry_len		0x88
++#define gfx_ofs_timeout			0x8c
++
++
+ #ifndef ASM_FILE
+ /*
+  *  Below this should be ONLY defines and other constructs for C code.
+@@ -595,6 +611,38 @@ extern int fallback_entryno;
+ extern int default_entry;
+ extern int current_entryno;
+ 
++
++/*
++ * graphics menu stuff
++ *
++ * Note: gfx_data and all data referred to in it must lie within a 64k area.
++ */
++typedef struct {
++  unsigned ok;			/* set while we're in graphics mode */
++  unsigned code_seg;		/* code segment of binary graphics code */
++  unsigned jmp_table[12];	/* link to graphics functions */
++  unsigned char sys_cfg[52];	/* sys_cfg[0]: identifies boot loader (grub == 2) */
++  char *cmdline;		/* command line returned by gfx_input() */
++  unsigned cmdline_len;		/* length of the above */
++  char *menu_list;		/* list of menu entries, each of fixed length (menu_entry_len) */
++  char *menu_default_entry;	/* the default entry */
++  unsigned menu_entries;	/* number of entries in menu_list */
++  unsigned menu_entry_len;	/* one entry */
++  char *args_list;		/* same structure as menu_list, menu_entries entries */
++  unsigned args_entry_len;	/* one entry */
++  unsigned timeout;		/* in seconds (0: no timeout) */
++} __attribute__ ((packed)) gfx_data_t;
++
++extern gfx_data_t *graphics_data;
++
++/* pointer to graphics image data */
++extern char graphics_file[64];
++
++int gfx_init(gfx_data_t *gfx_data);
++int gfx_done(gfx_data_t *gfx_data);
++int gfx_input(gfx_data_t *gfx_data, int *menu_entry);
++int gfx_setup_menu(gfx_data_t *gfx_data);
++
+ /* The constants for password types.  */
+ typedef enum
+ {
+diff -Nurp grub-0.97.orig/stage2/stage2.c grub-0.97/stage2/stage2.c
+--- grub-0.97.orig/stage2/stage2.c	2005-03-19 18:51:57.000000000 +0100
++++ grub-0.97/stage2/stage2.c	2009-08-03 16:25:52.220523160 +0200
+@@ -22,6 +22,8 @@
+ 
+ grub_jmp_buf restart_env;
+ 
++gfx_data_t *graphics_data;
++
+ #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
+ 
+ # if defined(PRESET_MENU_STRING)
+@@ -310,6 +312,12 @@ restart:
+       
+       if (! auth && password)
+ 	{
++	  if (*graphics_file)
++	    {
++	      printf ("\
++	WARNING: graphical menu doesn\'t work\
++	in conjunction with the password feature\n" );
++	    }
+ 	  printf ("\
+       Press enter to boot the selected OS or \'p\' to enter a\n\
+       password to unlock the next set of features.");
+@@ -753,6 +761,496 @@ restart:
+ }
+ 
+ 
++
++#if 0
++/* for debugging */
++static void hexdump(unsigned char *buf, unsigned len)
++{
++  int i, j = 0;
++  char s[17];
++  unsigned addr = (unsigned) buf;
++
++  s[16] = 0;
++  while(len--) {
++    i = buf[j];
++    i = i & 0xff;
++    s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.';
++    if(!(j & 15)) {
++      printf("%x  ", j + addr);
++    }
++    if(!(j & 7) && (j & 15)) printf(" ");
++    /* stupid grub_printf */
++    printf("%x", (i >> 4) & 0x0f);
++    printf("%x ", i & 0x0f);
++    if(!(++j & 15)) {
++      printf(" %s\n", s);
++    }
++  }
++
++  if(j & 15) {
++    s[j & 15] = 0;
++    if(!(j & 8)) printf(" ");
++    i = 1 + 3 * (16 - (j & 15));
++    while(i--) printf(" ");
++    printf("%s\n", s);
++  }
++}
++#endif
++
++
++/* kernel + (grub-)module options */
++#define GFX_CMD_BUF_SIZE 512
++
++/* command line separator char */
++#define GFX_CMD_SEP 1
++
++/*
++ * Go through config entry and find kernel args, if any.
++ * Put things into buf and return it.
++ */
++static char *get_kernel_args(char *cfg, char *buf)
++{
++  int i, j;
++  char *s, *t = "", *p, *t2;
++
++  *(p = buf) = 0;
++
++  for(j = 0; ; j++) {
++    s = get_entry(cfg, j, 0);
++    if(!*s) break;
++    if(
++      (!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) &&
++      (s[6] == ' ' || s[6] == '\t')
++    ) {
++      t = skip_to(0, s);
++      t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL;
++      if(*t) t = skip_to(0, t);
++      if(t2 && t2 < t) break;	/* module is likely a normal initrd -> skip */
++      i = strlen(t);
++      if(p - buf + i > GFX_CMD_BUF_SIZE - 2) break;
++      *p++ = GFX_CMD_SEP;
++      strcpy(p, t);
++      p += i;
++
++      continue;
++    }
++  }
++
++  if(*buf) buf++;	/* skip initial separator char */
++
++  return buf;
++}
++
++
++/*
++ * Check header and return code start offset.
++ */
++static unsigned magic_ok(unsigned char *buf)
++{
++  if(
++    *(unsigned *) buf == 0x0b2d97f00 &&		/* magic id */
++    (buf[4] == 8)				/* version 8 */
++  ) {
++    return *(unsigned *) (buf + 8);
++  }
++
++  return 0;
++}
++
++
++/*
++ * Search cpio archive for gfx file.
++ */
++static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len)
++{
++  unsigned i, fname_len, code_start = 0;
++
++  *gfx_file_start = 0;
++
++  for(i = 0; i < len;) {
++    if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) {
++      fname_len = *(unsigned short *) (buf + i + 20);
++      *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16);
++      i += 26 + fname_len;
++      i = ((i + 1) & ~1);
++      if((code_start = magic_ok(buf + i))) {
++        *gfx_file_start = i;
++        return code_start;
++      }
++      i += *file_len;
++      i = ((i + 1) & ~1);
++    }
++    else {
++      break;
++    }
++  }
++
++  return code_start;
++}
++
++static inline unsigned char * stack_ptr(void)
++{
++  unsigned char * u;
++
++  asm("movl %%esp, %0" : "=r" (u));
++
++  return u;
++}
++
++static void sleep(int delay)
++{
++  int tick, last_tick = currticks();
++
++  delay *= 18;
++
++  while(delay--) {
++    while((tick = currticks()) == last_tick) { }
++    last_tick = tick;
++  }
++}  
++
++static void wait_for_key()
++{
++  printf("Press a key to continue...");
++  getkey();
++  printf("\r                          \r");
++}
++
++
++/*
++ * Leave that much space on the heap. Everything else goes to the graphics
++ * functions.
++ *
++ * 0x2000 is _not_ enough
++ */
++#define MIN_HEAP_SIZE	0x4000
++#define MIN_GFX_FREE	0x1000
++
++#define SC_BOOTLOADER		0
++#define SC_FAILSAFE		3
++#define SC_SYSCONFIG_SIZE	4
++#define SC_BOOTLOADER_SEG	8
++#define SC_XMEM_0		24
++#define SC_XMEM_1		26
++#define SC_XMEM_2		28
++#define SC_XMEM_3		30
++#define SC_FILE			32
++#define SC_ARCHIVE_START	36
++#define SC_ARCHIVE_END		40
++#define SC_MEM0_START		44
++#define SC_MEM0_END		48
++
++/*
++ * Does normally not return.
++ */
++static void
++run_graphics_menu (char *menu_entries, char *config_entries, int num_entries,
++	  char *heap, int entryno)
++{
++  unsigned char *buf, *buf_ext;
++  unsigned buf_size, buf_ext_size, code_start, file_start;
++  char *s, *t, *t2, *cfg, *new_config, *p;
++  char *saved_heap;
++  int i, j, max_len, gfx_file_size, verbose;
++  int selected_entry;
++  gfx_data_t *gfx_data;
++  char *cmd_buf;
++  unsigned mem0_start, mem0_end, file_len;
++
++  /*
++   * check gfx_data_t struct offsets for consistency; gcc will optimize away
++   * the whole block
++   */
++
++  /* dummy function to make ld fail */
++  {
++    extern void wrong_struct_size(void);
++    #define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size();
++    gfx_ofs_check(ok);
++    gfx_ofs_check(code_seg);
++    gfx_ofs_check(jmp_table);
++    gfx_ofs_check(sys_cfg);
++    gfx_ofs_check(cmdline);
++    gfx_ofs_check(cmdline_len);
++    gfx_ofs_check(menu_list);
++    gfx_ofs_check(menu_default_entry);
++    gfx_ofs_check(menu_entries);
++    gfx_ofs_check(menu_entry_len);
++    gfx_ofs_check(args_list);
++    gfx_ofs_check(args_entry_len);
++    gfx_ofs_check(timeout);
++    #undef gfx_ofs_check
++  }
++
++  if(!num_entries) return;
++
++  graphics_data = gfx_data = (gfx_data_t *) heap;
++  heap += sizeof *gfx_data;
++  memset(gfx_data, 0, sizeof *gfx_data);
++
++  gfx_data->sys_cfg[SC_BOOTLOADER] = 2;			/* bootloader: grub */
++  gfx_data->sys_cfg[SC_SYSCONFIG_SIZE] = 52;		/* config data size */
++  *(unsigned short *) (gfx_data->sys_cfg + SC_BOOTLOADER_SEG) = (unsigned) gfx_data >> 4;	/* segment */
++  gfx_data->sys_cfg[SC_XMEM_0] = 0x28;			/* 8MB @ 2MB, see buf_ext below */
++  // gfx_data->sys_cfg[SC_XMEM_1] = 0xYZ;			/* Z MB @ Y MB */
++  verbose = (*(unsigned char *) 0x417) & 3 ? 1 : 0;	/* SHIFT pressed */
++  gfx_data->sys_cfg[SC_FAILSAFE] = verbose;
++
++  gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0;
++
++
++  /* setup command line edit buffer */
++
++  gfx_data->cmdline_len = 256;
++
++  gfx_data->cmdline = heap;
++  heap += gfx_data->cmdline_len;
++  memset(gfx_data->cmdline, 0, gfx_data->cmdline_len);
++
++  cmd_buf = heap;
++  heap += GFX_CMD_BUF_SIZE;
++
++  /* setup menu entries */
++
++  for(i = max_len = 0; i < num_entries; i++) {
++    j = strlen(get_entry(menu_entries, i, 0));
++    if(j > max_len) max_len = j;
++  }
++
++  if(!max_len) return;
++
++  gfx_data->menu_entry_len = max_len + 1;
++  gfx_data->menu_entries = num_entries;
++
++  gfx_data->menu_list = heap;
++  heap += gfx_data->menu_entry_len * gfx_data->menu_entries;
++
++  memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries);
++
++  for(i = 0; i < (int) gfx_data->menu_entries; i++) {
++    strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0));
++  }
++
++  gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len;
++
++
++  /* setup list of kernel args */
++
++  for(i = max_len = 0; i < num_entries; i++) {
++    s = get_kernel_args(get_entry(config_entries, i, 1), cmd_buf);
++    j = strlen(s);
++    if(j > max_len) max_len = j;
++  }
++
++  gfx_data->args_entry_len = max_len + 1;
++
++  gfx_data->args_list = heap;
++  heap += gfx_data->args_entry_len * gfx_data->menu_entries;
++
++  memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries);
++
++  for(i = 0; i < (int) gfx_data->menu_entries; i++) {
++    strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1), cmd_buf));
++  }
++
++
++  /* go back here when we no longer need the graphics data */
++  saved_heap = heap;
++
++
++  /* get memory area to be used by graphics functions */
++
++  /* use 8MB starting at 2MB as file buffer; see SC_XMEM_0 above (A20 is enabled anyway) */
++  buf_ext = (unsigned char *) (2 << 20);
++  buf_ext_size = 8 << 20;
++
++  /* must be 16-byte aligned */
++  buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf);
++
++  buf_size = stack_ptr() - buf - MIN_HEAP_SIZE;
++  buf_size &= ~0xf;
++
++  mem0_start = (unsigned) buf;
++  mem0_end = mem0_start + buf_size;
++
++  if(verbose) {
++    printf("low memory 0x%x - 0x%x (%d bytes)\n", mem0_start, mem0_end, buf_size);
++    wait_for_key();
++  }
++
++  heap += buf_size;
++
++  /* read the file */
++
++  if(!grub_open(graphics_file)) {
++    printf("%s: file not found\n", graphics_file);
++    sleep(5);
++    heap = saved_heap;
++    return;
++  }
++
++  gfx_file_size = grub_read(buf_ext, buf_ext_size);
++
++  grub_close();
++
++  if(gfx_file_size <= 0) {
++    printf("%s: read error\n", graphics_file);
++    sleep(5);
++    heap = saved_heap;
++    return;
++  }
++
++  if(verbose) {
++    printf("%s: %d bytes (%d bytes left)\n", graphics_file, gfx_file_size, buf_ext_size - gfx_file_size);
++    wait_for_key();
++  }
++
++  /* locate file inside cpio archive */
++  if(!(code_start = find_file(buf_ext, gfx_file_size, &file_start, &file_len))) {
++    printf("%s: invalid file format\n", graphics_file);
++    sleep(5);
++    heap = saved_heap;
++    return;
++  }
++
++  if(verbose) {
++    printf("init: start 0x%x, len %d; code offset 0x%x\n", file_start, file_len, code_start);
++    wait_for_key();
++  }
++
++  if(file_len - code_start + MIN_GFX_FREE > buf_size) {
++    printf("not enough free memory: %d extra bytes need\n", file_len - code_start + MIN_GFX_FREE - buf_size);
++    sleep(5);
++    heap = saved_heap;
++    return;
++  }
++
++  memcpy((void *) buf, (void *) (buf_ext + file_start + code_start), file_len - code_start);
++
++  mem0_start += file_len - code_start;
++  mem0_start = (mem0_start + 3) & ~3;		/* align */
++
++  /* init interface to graphics functions */
++
++  *(unsigned *) (gfx_data->sys_cfg + SC_FILE) = (unsigned) buf_ext + file_start;
++  *(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_START) = (unsigned) buf_ext;
++  *(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_END) = (unsigned) buf_ext + gfx_file_size;
++  *(unsigned *) (gfx_data->sys_cfg + SC_MEM0_START) = mem0_start;
++  *(unsigned *) (gfx_data->sys_cfg + SC_MEM0_END) = mem0_end;
++
++  gfx_data->code_seg = (unsigned) buf >> 4;
++
++  if(verbose) {
++    printf("init 0x%x, archive 0x%x - 0x%x, low mem 0x%x - 0x%x\ncode seg 0x%x\n",
++      (unsigned) buf_ext + file_start,
++      (unsigned) buf_ext, (unsigned) buf_ext + gfx_file_size,
++      mem0_start, mem0_end, gfx_data->code_seg
++    );
++    wait_for_key();
++  }
++
++  for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) {
++    gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) buf)[i];
++  }
++
++  if(verbose) {
++    for(i = 0; i < 12; i++) {
++      printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]);
++    }
++
++    for(i = 0; i < gfx_data->menu_entries; i++) {
++      printf("\"%s\"  --  \"%s\"\n",
++        gfx_data->menu_list + i * gfx_data->menu_entry_len,
++        gfx_data->args_list + i * gfx_data->args_entry_len
++      );
++    }
++
++    printf("default: \"%s\"\n", gfx_data->menu_default_entry);
++    wait_for_key();
++  }
++
++  /* switch to graphics mode */
++
++  if(gfx_init(gfx_data)) {
++    printf("graphics initialization failed\n");
++    sleep(5);
++    heap = saved_heap;
++    return;
++  }
++
++  gfx_setup_menu(gfx_data);
++
++  i = gfx_input(gfx_data, &selected_entry);
++
++  /* ESC -> show text menu */
++  if(i == 1) {
++    gfx_done(gfx_data);
++    grub_timeout = -1;
++
++    heap = saved_heap;
++    return;
++  }
++
++  gfx_done(gfx_data);
++
++  heap = saved_heap;	/* free most of the graphics data */
++
++  // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry);
++
++  if(selected_entry < 0 || selected_entry > num_entries) return;
++
++  /* for 'savedefault' */
++  current_entryno = selected_entry;
++
++
++  /* create new config with modified kernel option */
++
++  cfg = get_entry(config_entries, selected_entry, 1);
++
++  new_config = heap;
++
++  for(p = gfx_data->cmdline, i = 0; ; i++) {
++    s = get_entry(cfg, i, 0);
++    if(!*s) {
++      if(!i) *heap++ = 0;
++      *heap++ = 0;
++      break;
++    }
++    /* note: must match get_kernel_args() */
++    if(
++      (!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) &&
++      (s[6] == ' ' || s[6] == '\t')
++    ) {
++      t = skip_to(0, s);
++      t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL;
++      if(*t) t = skip_to(0, t);
++      if(t2 && t2 < t) {	/* module is likely a normal initrd -> skip */
++        strcpy(heap, s);
++        heap += strlen(s) + 1;
++        continue;
++      }
++      memmove(heap, s, t - s);
++      heap += t - s;
++      *heap++ = ' ';
++      while(*p && *p != GFX_CMD_SEP) *heap++ = *p++;
++      *heap++ = 0;
++      if(*p == GFX_CMD_SEP) p++;
++    }
++    else {
++      strcpy(heap, s);
++      heap += strlen(s) + 1;
++    }
++  }
++
++  *heap++ = 0;
++
++  // hexdump(new_config, heap - new_config);
++  // getkey();
++
++  run_script(new_config, heap);
++}
++
++
+ static int
+ get_line_from_config (char *cmdline, int maxlen, int read_from_file)
+ {
+@@ -1059,9 +1557,12 @@ cmain (void)
+ 	}
+       else
+ 	{
+-	  /* Run menu interface.  */
+-	  run_menu (menu_entries, config_entries, num_entries,
+-		    menu_entries + menu_len, default_entry);
++	  if (*graphics_file && !password && show_menu && grub_timeout)
++	    {
++	      run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry);
++	    }
++	    /* Run menu interface.  */
++            run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry);
+ 	}
+     }
+ }

diff --git a/sys-boot/grub/files/grub-0.97-uuid.patch b/sys-boot/grub/files/grub-0.97-uuid.patch
new file mode 100644
index 0000000..f99670a
--- /dev/null
+++ b/sys-boot/grub/files/grub-0.97-uuid.patch
@@ -0,0 +1,5406 @@
+=== modified file 'Makefile.am'
+--- grub-0.97.orig/Makefile.am	2004-04-23 13:39:01 +0000
++++ grub-0.97/Makefile.am	2008-07-09 17:23:44 +0000
+@@ -1,4 +1,9 @@
+ # Do not change this order if you don't know what you are doing.
+ AUTOMAKE_OPTIONS = 1.7 gnu
+-SUBDIRS = netboot stage2 stage1 lib grub util docs
++if UUID_SUPPORT
++SUBDIRS = libvolume_id netboot stage2 stage1 lib grub util docs 
++else
++SUBDIRS = netboot stage2 stage1 lib grub util docs 
++endif
++
+ EXTRA_DIST = BUGS MAINTENANCE
+
+=== modified file 'configure.ac'
+--- grub-0.97.orig/configure.ac	2008-01-28 18:41:45 +0000
++++ grub-0.97/configure.ac	2008-07-09 17:23:44 +0000
+@@ -605,6 +606,11 @@
+   [  --disable-serial        disable serial terminal support])
+ AM_CONDITIONAL(SERIAL_SUPPORT, test "x$enable_serial" != xno)
+ 
++dnl UUID scanning
++AC_ARG_ENABLE(uuid,
++  [  --disable-uuid          disable uuid scanning support])
++AM_CONDITIONAL(UUID_SUPPORT, test "x$enable_uuid" != xno)
++
+ dnl Simulation of the slowness of a serial device.
+ AC_ARG_ENABLE(serial-speed-simulation,
+   [  --enable-serial-speed-simulation
+@@ -666,5 +672,6 @@
+ 		 docs/Makefile lib/Makefile util/Makefile \
+ 		 grub/Makefile netboot/Makefile util/grub-image \
+ 		 util/grub-install util/grub-md5-crypt \
+-		 util/grub-terminfo util/grub-set-default])
++		 util/grub-terminfo util/grub-set-default \
++		 libvolume_id/Makefile])
+ AC_OUTPUT
+
+=== modified file 'grub/Makefile.am'
+--- grub-0.97.orig/grub/Makefile.am	2005-02-02 20:40:05 +0000
++++ grub-0.97/grub/Makefile.am	2008-07-09 17:23:44 +0000
+@@ -16,4 +16,9 @@
+ AM_CFLAGS = $(GRUB_CFLAGS)
+ 
+ grub_SOURCES = main.c asmstub.c
+-grub_LDADD = ../stage2/libgrub.a  ../lib/libcommon.a $(GRUB_LIBS)
++
++if UUID_SUPPORT
++grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a ../libvolume_id/libvolume_id.a $(GRUB_LIBS)
++else
++grub_LDADD = ../stage2/libgrub.a ../lib/libcommon.a $(GRUB_LIBS)
++endif
+
+=== added directory 'libvolume_id'
+=== added file 'libvolume_id/Makefile.am'
+--- grub-0.97.orig/libvolume_id/Makefile.am	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/Makefile.am	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,27 @@
++noinst_LIBRARIES = libvolume_id.a
++
++AM_CFLAGS = $(STAGE2_CFLAGS) -I$(top_srcdir)/stage2 -I$(top_srcdir)/stage1
++
++LIBVOLUME_ID_FS_SUPPORTED = 	ext.c fat.c hfs.c jfs.c  \
++			 	luks.c ntfs.c ocfs.c reiserfs.c \
++			 	xfs.c 
++
++LIBVOLUME_ID_FS_UNSUPPORTED = 	cramfs.c gfs.c hpfs.c iso9660.c \
++			 	lvm.c minix.c romfs.c squashfs.c \
++				sysv.c udf.c ufs.c vxfs.c
++
++LIBVOLUME_ID_RAID_SUPPORTED = 	ddf_raid.c 
++
++LIBVOLUME_ID_RAID_UNSUPPORTED = adaptec_raid.c highpoint.c isw_raid.c \
++				jmicron_raid.c linux_raid.c lsi_raid.c \
++				nvidia_raid.c promise_raid.c silicon_raid.c \
++				via_raid.c 
++
++LIBVOLUME_ID_MISC_UNSUPPORTED = linux_swap.c netware.c
++
++libvolume_id_a_SOURCES = 	$(LIBVOLUME_ID_FS_SUPPORTED) \
++   			 	$(LIBVOLUME_ID_RAID_SUPPORTED) \
++				$(LIBVOLUME_ID_FS_UNSUPPORTED) \
++				$(LIBVOLUME_ID_RAID_UNSUPPORTED) \
++			 	volume_id.h volume_id.c util.c util.h misc.c 
++
+
+=== added file 'libvolume_id/adaptec_raid.c'
+--- grub-0.97.orig/libvolume_id/adaptec_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/adaptec_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,107 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct adaptec_meta {
++	uint32_t	b0idcode;
++	uint8_t		lunsave[8];
++	uint16_t	sdtype;
++	uint16_t	ssavecyl;
++	uint8_t		ssavehed;
++	uint8_t		ssavesec;
++	uint8_t		sb0flags;
++	uint8_t		jbodEnable;
++	uint8_t		lundsave;
++	uint8_t		svpdirty;
++	uint16_t	biosInfo;
++	uint16_t	svwbskip;
++	uint16_t	svwbcln;
++	uint16_t	svwbmax;
++	uint16_t	res3;
++	uint16_t	svwbmin;
++	uint16_t	res4;
++	uint16_t	svrcacth;
++	uint16_t	svwcacth;
++	uint16_t	svwbdly;
++	uint8_t		svsdtime;
++	uint8_t		res5;
++	uint16_t	firmval;
++	uint16_t	firmbln;
++	uint32_t	firmblk;
++	uint32_t	fstrsvrb;
++	uint16_t	svBlockStorageTid;
++	uint16_t	svtid;
++	uint8_t		svseccfl;
++	uint8_t		res6;
++	uint8_t		svhbanum;
++	uint8_t		resver;
++	uint32_t	drivemagic;
++	uint8_t		reserved[20];
++	uint8_t		testnum;
++	uint8_t		testflags;
++	uint16_t	maxErrorCount;
++	uint32_t	count;
++	uint32_t	startTime;
++	uint32_t	interval;
++	uint8_t		tstxt0;
++	uint8_t		tstxt1;
++	uint8_t		serNum[32];
++	uint8_t		res8[102];
++	uint32_t	fwTestMagic;
++	uint32_t	fwTestSeqNum;
++	uint8_t		fwTestRes[8];
++	uint8_t		smagic[4];
++	uint32_t	raidtbl;
++	uint16_t	raidline;
++	uint8_t		res9[0xF6];
++} PACKED;
++
++int volume_id_probe_adaptec_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	uint64_t meta_off;
++	struct adaptec_meta *ad;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x10000)
++		return -1;
++
++	meta_off = ((size / 0x200)-1) * 0x200;
++	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	ad = (struct adaptec_meta *) buf;
++	if (memcmp((char*)ad->smagic, "DPTM", 4) != 0)
++		return -1;
++
++	if (ad->b0idcode != be32_to_cpu(0x37FC4D1E))
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	sprintf(id->type_version, "%u", ad->resver);
++	id->type = "adaptec_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/cramfs.c'
+--- grub-0.97.orig/libvolume_id/cramfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/cramfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,60 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct cramfs_super {
++	uint8_t		magic[4];
++	uint32_t	size;
++	uint32_t	flags;
++	uint32_t	future;
++	uint8_t		signature[16];
++	struct cramfs_info {
++		uint32_t	crc;
++		uint32_t	edition;
++		uint32_t	blocks;
++		uint32_t	files;
++	} PACKED info;
++	uint8_t		name[16];
++} PACKED;
++
++int volume_id_probe_cramfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct cramfs_super *cs;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	cs = (struct cramfs_super *) volume_id_get_buffer(id, off, 0x200);
++	if (cs == NULL)
++		return -1;
++
++	if (memcmp((char*)cs->magic, "\x45\x3d\xcd\x28", 4) == 0 || memcmp((char*)cs->magic, "\x28\xcd\x3d\x45", 4) == 0) {
++		volume_id_set_label_raw(id, cs->name, 16);
++		volume_id_set_label_string(id, cs->name, 16);
++
++		volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++		id->type = "cramfs";
++		return 0;
++	}
++
++	return -1;
++}
+
+=== added file 'libvolume_id/ddf_raid.c'
+--- grub-0.97.orig/libvolume_id/ddf_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/ddf_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,60 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++/* http://www.snia.org/standards/home */
++
++#define DDF_HEADER			0xDE11DE11
++#define DDF_GUID_LENGTH			24
++#define DDF_REV_LENGTH			8
++
++static struct ddf_header {
++	uint32_t	signature;
++	uint32_t	crc;
++	uint8_t		guid[DDF_GUID_LENGTH];
++	uint8_t		ddf_rev[DDF_REV_LENGTH];
++} PACKED *ddf;
++
++int volume_id_probe_ddf_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	uint64_t ddf_off = ((size / 0x200)-1) * 0x200;
++	const uint8_t *buf;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++	if (size < 0x10000)
++		return -1;
++
++	buf = volume_id_get_buffer(id, off + ddf_off, 0x200);
++	if (buf == NULL)
++		return -1;
++	ddf = (struct ddf_header *) buf;
++
++	if (ddf->signature != cpu_to_be32(DDF_HEADER))
++		return -1;
++
++	volume_id_set_uuid(id, ddf->guid, DDF_GUID_LENGTH, UUID_STRING);
++	strcpy(id->type_version, (char*) ddf->ddf_rev);
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "ddf_raid_member";
++	return 0;
++}
+
+=== added file 'libvolume_id/ext.c'
+--- grub-0.97.orig/libvolume_id/ext.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/ext.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,129 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct ext2_super_block {
++	uint32_t	s_inodes_count;
++	uint32_t	s_blocks_count;
++	uint32_t	s_r_blocks_count;
++	uint32_t	s_free_blocks_count;
++	uint32_t	s_free_inodes_count;
++	uint32_t	s_first_data_block;
++	uint32_t	s_log_block_size;
++	uint32_t	s_log_frag_size;
++	uint32_t	s_blocks_per_group;
++	uint32_t	s_frags_per_group;
++	uint32_t	s_inodes_per_group;
++	uint32_t	s_mtime;
++	uint32_t	s_wtime;
++	uint16_t	s_mnt_count;
++	uint16_t	s_max_mnt_count;
++	uint16_t	s_magic;
++	uint16_t	s_state;
++	uint16_t	s_errors;
++	uint16_t	s_minor_rev_level;
++	uint32_t	s_lastcheck;
++	uint32_t	s_checkinterval;
++	uint32_t	s_creator_os;
++	uint32_t	s_rev_level;
++	uint16_t	s_def_resuid;
++	uint16_t	s_def_resgid;
++	uint32_t	s_first_ino;
++	uint16_t	s_inode_size;
++	uint16_t	s_block_group_nr;
++	uint32_t	s_feature_compat;
++	uint32_t	s_feature_incompat;
++	uint32_t	s_feature_ro_compat;
++	uint8_t		s_uuid[16];
++	uint8_t		s_volume_name[16];
++} PACKED;
++
++#define EXT_SUPER_MAGIC				0xEF53
++#define EXT3_FEATURE_COMPAT_HAS_JOURNAL		0x0004
++#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008
++#define EXT3_FEATURE_INCOMPAT_EXTENTS		0x0040
++#define EXT4_FEATURE_INCOMPAT_64BIT		0x0080
++#define EXT4_FEATURE_INCOMPAT_MMP		0x0100
++
++#define EXT_SUPERBLOCK_OFFSET			0x400
++
++#define EXT3_MIN_BLOCK_SIZE			0x400
++#define EXT3_MAX_BLOCK_SIZE			0x1000
++
++int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct ext2_super_block *es;
++	size_t bsize;
++	uint32_t feature_compat;
++	uint32_t feature_incompat;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	es = (struct ext2_super_block *) volume_id_get_buffer(id, off + EXT_SUPERBLOCK_OFFSET, 0x200);
++	if (es == NULL)
++		return -1;
++
++	if (es->s_magic != cpu_to_le16(EXT_SUPER_MAGIC))
++		return -1;
++
++	bsize = 0x400 << le32_to_cpu(es->s_log_block_size);
++	dbg("ext blocksize 0x%zx", bsize);
++	if (bsize < EXT3_MIN_BLOCK_SIZE || bsize > EXT3_MAX_BLOCK_SIZE) {
++		dbg("invalid ext blocksize");
++		return -1;
++	}
++
++	volume_id_set_label_raw(id, es->s_volume_name, 16);
++	volume_id_set_label_string(id, es->s_volume_name, 16);
++	volume_id_set_uuid(id, es->s_uuid, 0, UUID_DCE);
++	sprintf(id->type_version, "%u.%u",
++		 le32_to_cpu(es->s_rev_level), le16_to_cpu(es->s_minor_rev_level));
++
++	feature_compat = le32_to_cpu(es->s_feature_compat);
++	feature_incompat = le32_to_cpu(es->s_feature_incompat);
++
++	/* check for external journal device */
++	if ((feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) != 0) {
++		volume_id_set_usage(id, VOLUME_ID_OTHER);
++		id->type = "jbd";
++		goto out;
++	}
++
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++
++	if ((feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) != 0 ||
++	    (feature_incompat & EXT4_FEATURE_INCOMPAT_64BIT) != 0 ||
++	    (feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) != 0) {
++		id->type = "ext4";
++		goto out;
++	}
++
++	if ((feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) != 0) {
++		id->type = "ext3";
++		goto out;
++	}
++
++	id->type = "ext2";
++
++out:
++	return 0;
++}
+
+=== added file 'libvolume_id/fat.c'
+--- grub-0.97.orig/libvolume_id/fat.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/fat.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,482 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004-2007 Kay Sievers <kay.sievers@vrfy.org>
++ * Copyright (C) 2007 Ryan Lortie <desrt@desrt.ca>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++#define FAT12_MAX			0xff5
++#define FAT16_MAX			0xfff5
++#define FAT_ATTR_VOLUME_ID		0x08
++#define FAT_ATTR_DIR			0x10
++#define FAT_ATTR_LONG_NAME		0x0f
++#define FAT_ATTR_MASK			0x3f
++#define FAT_ENTRY_FREE			0xe5
++
++#define VFAT_LFN_SEQ_MASK		0x3f
++#define VFAT_LFN_SEQ_LAST		0x40
++#define VFAT_LFN_SEQ_MAX		20
++#define VFAT_LFN_CHARS_PER_ENTRY	(5 + 6 + 2)
++#define VFAT_LOWERCASE_NAME		0x10
++#define VFAT_LOWERCASE_EXT		0x08
++
++struct vfat_super_block {
++	uint8_t		boot_jump[3];
++	uint8_t		sysid[8];
++	uint16_t	sector_size;
++	uint8_t		sectors_per_cluster;
++	uint16_t	reserved;
++	uint8_t		fats;
++	uint16_t	dir_entries;
++	uint16_t	sectors;
++	uint8_t		media;
++	uint16_t	fat_length;
++	uint16_t	secs_track;
++	uint16_t	heads;
++	uint32_t	hidden;
++	uint32_t	total_sect;
++	union {
++		struct fat_super_block {
++			uint8_t		unknown[3];
++			uint8_t		serno[4];
++			uint8_t		label[11];
++			uint8_t		magic[8];
++			uint8_t		dummy2[192];
++			uint8_t		pmagic[2];
++		} PACKED fat;
++		struct fat32_super_block {
++			uint32_t	fat32_length;
++			uint16_t	flags;
++			uint8_t		version[2];
++			uint32_t	root_cluster;
++			uint16_t	fsinfo_sector;
++			uint16_t	backup_boot;
++			uint16_t	reserved2[6];
++			uint8_t		unknown[3];
++			uint8_t		serno[4];
++			uint8_t		label[11];
++			uint8_t		magic[8];
++			uint8_t		dummy2[164];
++			uint8_t		pmagic[2];
++		} PACKED fat32;
++	} PACKED type;
++} PACKED;
++
++struct fat32_fsinfo {
++	uint8_t signature1[4];
++	uint32_t reserved1[120];
++	uint8_t signature2[4];
++	uint32_t free_clusters;
++	uint32_t next_cluster;
++	uint32_t reserved2[4];
++} PACKED;
++
++struct vfat_dir_entry {
++	uint8_t		name[11];
++	uint8_t		attr;
++	uint8_t		lowercase;
++	uint8_t		fine_time_creat;
++	uint16_t	time_creat;
++	uint16_t	date_creat;
++	uint16_t	date_acc;
++	uint16_t	cluster_high;
++	uint16_t	time_write;
++	uint16_t	date_write;
++	uint16_t	cluster_low;
++	uint32_t	size;
++} PACKED;
++
++
++struct vfat_lfn_entry {
++	uint8_t		seq;
++	uint16_t	name0[5];
++	uint8_t		attr;
++	uint8_t		reserved;
++	uint8_t		cksum;
++	uint16_t	name1[6];
++	uint16_t	cluster;
++	uint16_t	name2[2];
++} PACKED;
++
++static uint8_t fat_lfn_checksum(const uint8_t name[11])
++{
++	uint8_t cksum = 0;
++	int i;
++
++	/* http://en.wikipedia.org/wiki/File_Allocation_Table */
++	for (i = 0; i < 11; i++)
++		cksum = ((cksum & 1) ? 0x80 : 0) + (cksum >> 1) + name[i];
++
++	return cksum;
++}
++
++static size_t fat_read_lfn(uint8_t *filename, size_t fnsize,
++			   struct vfat_dir_entry *direntry,
++			   struct vfat_dir_entry *entry)
++{
++	uint8_t buffer[VFAT_LFN_SEQ_MAX * VFAT_LFN_CHARS_PER_ENTRY * 2];
++	uint8_t expected_seq = 1;
++	uint8_t cksum;
++	size_t len = 0;
++	size_t fnlen = 0;
++
++	cksum = fat_lfn_checksum(entry->name);
++
++	while (--entry >= direntry) {
++		struct vfat_lfn_entry *lfn = (struct vfat_lfn_entry *) entry;
++
++		if (expected_seq > VFAT_LFN_SEQ_MAX)
++			break;
++
++		if ((lfn->attr & FAT_ATTR_MASK) != FAT_ATTR_LONG_NAME)
++			break;
++
++		if (lfn->cksum != cksum)
++			break;
++
++		if ((lfn->seq & VFAT_LFN_SEQ_MASK) != expected_seq++)
++			break;
++
++		if (lfn->cluster != 0)
++			break;
++
++		/* extra paranoia -- should never happen */
++		if (len + sizeof(lfn->name0) + sizeof(lfn->name1) +
++		    sizeof(lfn->name2) > sizeof(buffer))
++			break;
++
++		memcpy (&buffer[len], lfn->name0, sizeof(lfn->name0));
++		len += sizeof(lfn->name0);
++		memcpy (&buffer[len], lfn->name1, sizeof(lfn->name1));
++		len += sizeof(lfn->name1);
++		memcpy (&buffer[len], lfn->name2, sizeof(lfn->name2));
++		len += sizeof(lfn->name2);
++
++		if (lfn->seq & VFAT_LFN_SEQ_LAST) {
++			fnlen = volume_id_set_unicode16(filename, fnsize, buffer, LE, len);
++			break;
++		}
++	}
++
++	return fnlen;
++}
++
++static size_t fat_read_filename(uint8_t *filename, size_t fnsize,
++				struct vfat_dir_entry *direntry, struct vfat_dir_entry *entry)
++{
++	size_t len;
++	int i;
++
++	/* check if maybe we have LFN entries */
++	len = fat_read_lfn(filename, fnsize, direntry, entry);
++	if (len > 0)
++		goto out;
++
++	/* else, read the normal 8.3 name */
++	for (i = 0; i < 11; i++) {
++		if (entry->lowercase & ((i < 8) ? VFAT_LOWERCASE_NAME : VFAT_LOWERCASE_EXT))
++			filename[i] = tolower(entry->name[i]);
++		else
++			filename[i] = entry->name[i];
++	}
++	len = 11;
++
++out:
++	filename[len] = '\0';
++	return len;
++}
++
++/* fills filename, returns string length */
++static size_t get_fat_attr_volume_id(uint8_t *filename, size_t fnsize,
++				     struct vfat_dir_entry *direntry, unsigned int count)
++{
++	unsigned int i;
++
++	for (i = 0; i < count; i++) {
++		/* end marker */
++		if (direntry[i].name[0] == 0x00) {
++			dbg("end of dir");
++			break;
++		}
++
++		/* empty entry */
++		if (direntry[i].name[0] == FAT_ENTRY_FREE)
++			continue;
++
++		/* long name */
++		if ((direntry[i].attr & FAT_ATTR_MASK) == FAT_ATTR_LONG_NAME)
++			continue;
++
++		if ((direntry[i].attr & (FAT_ATTR_VOLUME_ID | FAT_ATTR_DIR)) == FAT_ATTR_VOLUME_ID) {
++			/* labels do not have file data */
++			if (direntry[i].cluster_high != 0 || direntry[i].cluster_low != 0)
++				continue;
++
++			dbg("found ATTR_VOLUME_ID id in root dir");
++			return fat_read_filename(filename, fnsize, direntry, &direntry[i]);
++		}
++
++		dbg("skip dir entry");
++	}
++
++	return 0;
++}
++
++int volume_id_probe_vfat(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	uint8_t filename[255 * 3];
++	struct vfat_super_block *vs;
++	struct vfat_dir_entry *direntry;
++	struct fat32_fsinfo *fsinfo;
++	uint16_t sector_size;
++	uint16_t dir_entries;
++	uint32_t sect_count;
++	uint16_t reserved;
++	uint32_t fat_size;
++	uint32_t root_cluster;
++	uint32_t dir_size;
++	uint32_t cluster_count;
++	uint16_t fat_length;
++	uint32_t fat32_length;
++	uint64_t root_start;
++	uint32_t start_data_sect;
++	uint16_t root_dir_entries;
++	uint16_t fsinfo_sect;
++	uint8_t *buf;
++	uint32_t buf_size;
++	uint32_t next;
++	int maxloop;
++	size_t fnlen;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off, 0x400);
++	if (buf == NULL)
++		return -1;
++
++	/* check signature */
++	if (buf[510] != 0x55 || buf[511] != 0xaa)
++		return -1;
++
++	vs = (struct vfat_super_block *) buf;
++	if (memcmp((char*)vs->sysid, "NTFS", 4) == 0)
++		return -1;
++
++	/* believe only that's fat, don't trust the version */
++	if (memcmp((char*)vs->type.fat32.magic, "MSWIN", 5) == 0)
++		goto magic;
++
++	if (memcmp((char*)vs->type.fat32.magic, "FAT32   ", 8) == 0)
++		goto magic;
++
++	if (memcmp((char*)vs->type.fat.magic, "FAT16   ", 8) == 0)
++		goto magic;
++
++	if (memcmp((char*)vs->type.fat.magic, "MSDOS", 5) == 0)
++		goto magic;
++
++	if (memcmp((char*)vs->type.fat.magic, "FAT12   ", 8) == 0)
++		goto magic;
++
++	/* some old floppies don't have a magic, expect the boot jump address to match */
++	if ((vs->boot_jump[0] != 0xeb || vs->boot_jump[2] != 0x90) &&
++	     vs->boot_jump[0] != 0xe9)
++		return -1;
++
++magic:
++	/* reserverd sector count */
++	if (!vs->reserved)
++		return -1;
++
++	/* fat count */
++	if (!vs->fats)
++		return -1;
++
++	/* media check */
++	if (vs->media < 0xf8 && vs->media != 0xf0)
++		return -1;
++
++	/* cluster size check */
++	if (vs->sectors_per_cluster == 0 ||
++	    (vs->sectors_per_cluster & (vs->sectors_per_cluster-1)))
++		return -1;
++
++	/* sector size check */
++	sector_size = le16_to_cpu(vs->sector_size);
++	if (sector_size == 0 || ((sector_size & (sector_size-1)) != 0))
++		return -1;
++
++	dbg("sector_size 0x%x", sector_size);
++	dbg("sectors_per_cluster 0x%x", vs->sectors_per_cluster);
++
++	dir_entries = le16_to_cpu(vs->dir_entries);
++	reserved = le16_to_cpu(vs->reserved);
++	dbg("reserved 0x%x", reserved);
++
++	sect_count = le16_to_cpu(vs->sectors);
++	if (sect_count == 0)
++		sect_count = le32_to_cpu(vs->total_sect);
++	dbg("sect_count 0x%x", sect_count);
++
++	fat_length = le16_to_cpu(vs->fat_length);
++	dbg("fat_length 0x%x", fat_length);
++	fat32_length = le32_to_cpu(vs->type.fat32.fat32_length);
++	dbg("fat32_length 0x%x", fat32_length);
++
++	if (fat_length)
++		fat_size = fat_length * vs->fats;
++	else if (fat32_length)
++		fat_size = fat32_length * vs->fats;
++	else
++		return -1;
++	dbg("fat_size 0x%x", fat_size);
++
++	dir_size = ((dir_entries * sizeof(struct vfat_dir_entry)) +
++			(sector_size-1)) / sector_size;
++	dbg("dir_size 0x%x", dir_size);
++
++	cluster_count = sect_count - (reserved + fat_size + dir_size);
++	cluster_count /= vs->sectors_per_cluster;
++	dbg("cluster_count 0x%x", cluster_count);
++
++	/* must be FAT32 */
++	if (!fat_length && fat32_length)
++		goto fat32;
++
++	/* cluster_count tells us the format */
++	if (cluster_count < FAT12_MAX)
++		strcpy(id->type_version, "FAT12");
++	else if (cluster_count < FAT16_MAX)
++		strcpy(id->type_version, "FAT16");
++	else
++		goto fat32;
++
++	/* the label may be an attribute in the root directory */
++	root_start = (reserved + fat_size) * sector_size;
++	dbg("root dir start 0x%llx", (unsigned long long) root_start);
++	root_dir_entries = le16_to_cpu(vs->dir_entries);
++	dbg("expected entries 0x%x", root_dir_entries);
++
++	buf_size = root_dir_entries * sizeof(struct vfat_dir_entry);
++	buf = volume_id_get_buffer(id, off + root_start, buf_size);
++	if (buf == NULL)
++		goto found;
++
++	direntry = (struct vfat_dir_entry*) buf;
++
++	fnlen = get_fat_attr_volume_id(filename, sizeof(filename), direntry, root_dir_entries);
++
++	vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
++	if (vs == NULL)
++		return -1;
++
++	if (fnlen > 0 && memcmp((char*)filename, "NO NAME    ", 11) != 0) {
++		volume_id_set_label_raw(id, filename, fnlen);
++		volume_id_set_label_string(id, filename, fnlen);
++	} else if (memcmp((char*)vs->type.fat.label, "NO NAME    ", 11) != 0) {
++		volume_id_set_label_raw(id, vs->type.fat.label, 11);
++		volume_id_set_label_string(id, vs->type.fat.label, 11);
++	}
++	volume_id_set_uuid(id, vs->type.fat.serno, 0, UUID_DOS);
++	goto found;
++
++fat32:
++	/* FAT32 should have a valid signature in the fsinfo block */
++	fsinfo_sect = le16_to_cpu(vs->type.fat32.fsinfo_sector);
++	buf = volume_id_get_buffer(id, off + (fsinfo_sect * sector_size), 0x200);
++	if (buf == NULL)
++		return -1;
++	fsinfo = (struct fat32_fsinfo *) buf;
++	if (memcmp((char*)fsinfo->signature1, "\x52\x52\x61\x41", 4) != 0)
++		return -1;
++	if (memcmp((char*)fsinfo->signature2, "\x72\x72\x41\x61", 4) != 0)
++		return -1 ;
++
++	vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
++	if (vs == NULL)
++		return -1;
++
++	strcpy(id->type_version, "FAT32");
++
++	/* FAT32 root dir is a cluster chain like any other directory */
++	buf_size = vs->sectors_per_cluster * sector_size;
++	root_cluster = le32_to_cpu(vs->type.fat32.root_cluster);
++	dbg("root dir cluster %u", root_cluster);
++	start_data_sect = reserved + fat_size;
++
++	next = root_cluster;
++	maxloop = 100;
++	while (--maxloop) {
++		uint32_t next_sect_off;
++		uint64_t next_off;
++		uint64_t fat_entry_off;
++		int count;
++
++		dbg("next cluster %u", next);
++		next_sect_off = (next - 2) * vs->sectors_per_cluster;
++		next_off = (start_data_sect + next_sect_off) * sector_size;
++		dbg("cluster offset 0x%llx", (unsigned long long) next_off);
++
++		/* get cluster */
++		buf = volume_id_get_buffer(id, off + next_off, buf_size);
++		if (buf == NULL)
++			goto found;
++
++		direntry = (struct vfat_dir_entry*) buf;
++		count = buf_size / sizeof(struct vfat_dir_entry);
++		dbg("expected entries 0x%x", count);
++
++		fnlen = get_fat_attr_volume_id(filename, sizeof(filename), direntry, count);
++		if (fnlen > 0)
++			break;
++
++		/* get FAT entry */
++		fat_entry_off = (reserved * sector_size) + (next * sizeof(uint32_t));
++		buf = volume_id_get_buffer(id, off + fat_entry_off, buf_size);
++		if (buf == NULL)
++			goto found;
++
++		/* set next cluster */
++		next = le32_to_cpu(*((uint32_t *) buf)) & 0x0fffffff;
++		if (next < 2 || next >= 0x0ffffff0)
++			break;
++	}
++	if (maxloop == 0)
++		dbg("reached maximum follow count of root cluster chain, give up");
++
++	vs = (struct vfat_super_block *) volume_id_get_buffer(id, off, 0x200);
++	if (vs == NULL)
++		return -1;
++
++	if (fnlen > 0 && memcmp((char*)filename, "NO NAME    ", 11) != 0) {
++		volume_id_set_label_raw(id, filename, fnlen);
++		volume_id_set_label_string(id, filename, fnlen);
++	} else if (memcmp((char*)vs->type.fat32.label, "NO NAME    ", 11) != 0) {
++		volume_id_set_label_raw(id, vs->type.fat32.label, 11);
++		volume_id_set_label_string(id, vs->type.fat32.label, 11);
++	}
++	volume_id_set_uuid(id, vs->type.fat32.serno, 0, UUID_DOS);
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "vfat";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/gfs.c'
+--- grub-0.97.orig/libvolume_id/gfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/gfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,115 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2006 Red Hat, Inc. <redhat.com>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++/* Common gfs/gfs2 constants: */
++#define GFS_MAGIC		0x01161970
++#define GFS_DEFAULT_BSIZE	4096
++#define GFS_SUPERBLOCK_OFFSET	(0x10 * GFS_DEFAULT_BSIZE)
++#define GFS_METATYPE_SB		1
++#define GFS_FORMAT_SB		100
++#define GFS_LOCKNAME_LEN	64
++
++/* gfs1 constants: */
++#define GFS_FORMAT_FS		1309
++#define GFS_FORMAT_MULTI	1401
++/* gfs2 constants: */
++#define GFS2_FORMAT_FS		1801
++#define GFS2_FORMAT_MULTI	1900
++
++struct gfs2_meta_header {
++	uint32_t mh_magic;
++	uint32_t mh_type;
++	uint64_t __pad0;          /* Was generation number in gfs1 */
++	uint32_t mh_format;
++	uint32_t __pad1;          /* Was incarnation number in gfs1 */
++};
++
++struct gfs2_inum {
++	uint64_t no_formal_ino;
++	uint64_t no_addr;
++};
++
++struct gfs2_sb {
++	struct gfs2_meta_header sb_header;
++
++	uint32_t sb_fs_format;
++	uint32_t sb_multihost_format;
++	uint32_t  __pad0;  /* Was superblock flags in gfs1 */
++
++	uint32_t sb_bsize;
++	uint32_t sb_bsize_shift;
++	uint32_t __pad1;   /* Was journal segment size in gfs1 */
++
++	struct gfs2_inum sb_master_dir; /* Was jindex dinode in gfs1 */
++	struct gfs2_inum __pad2; /* Was rindex dinode in gfs1 */
++	struct gfs2_inum sb_root_dir;
++
++	char sb_lockproto[GFS_LOCKNAME_LEN];
++	char sb_locktable[GFS_LOCKNAME_LEN];
++	/* In gfs1, quota and license dinodes followed */
++} PACKED;
++
++static int volume_id_probe_gfs_generic(struct volume_id *id, uint64_t off, int vers)
++{
++	struct gfs2_sb *sbd;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	sbd = (struct gfs2_sb *)
++		volume_id_get_buffer(id, off + GFS_SUPERBLOCK_OFFSET, sizeof(struct gfs2_sb));
++	if (sbd == NULL)
++		return -1;
++
++	if (be32_to_cpu(sbd->sb_header.mh_magic) == GFS_MAGIC &&
++		be32_to_cpu(sbd->sb_header.mh_type) == GFS_METATYPE_SB &&
++		be32_to_cpu(sbd->sb_header.mh_format) == GFS_FORMAT_SB) {
++		if (vers == 1) {
++			if (be32_to_cpu(sbd->sb_fs_format) != GFS_FORMAT_FS ||
++				be32_to_cpu(sbd->sb_multihost_format) != GFS_FORMAT_MULTI)
++				return -1; /* not gfs1 */
++			id->type = "gfs";
++		}
++		else if (vers == 2) {
++			if (be32_to_cpu(sbd->sb_fs_format) != GFS2_FORMAT_FS ||
++				be32_to_cpu(sbd->sb_multihost_format) != GFS2_FORMAT_MULTI)
++				return -1; /* not gfs2 */
++			id->type = "gfs2";
++		}
++		else
++			return -1;
++		strcpy(id->type_version, "1");
++		volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++		return 0;
++	}
++	return -1;
++}
++
++int volume_id_probe_gfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	return volume_id_probe_gfs_generic(id, off, 1);
++}
++
++int volume_id_probe_gfs2(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	return volume_id_probe_gfs_generic(id, off, 2);
++}
+
+=== added file 'libvolume_id/hfs.c'
+--- grub-0.97.orig/libvolume_id/hfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/hfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,318 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct hfs_finder_info{
++	uint32_t	boot_folder;
++	uint32_t	start_app;
++	uint32_t	open_folder;
++	uint32_t	os9_folder;
++	uint32_t	reserved;
++	uint32_t	osx_folder;
++	uint8_t		id[8];
++} PACKED;
++
++static struct hfs_mdb {
++	uint8_t		signature[2];
++	uint32_t	cr_date;
++	uint32_t	ls_Mod;
++	uint16_t	atrb;
++	uint16_t	nm_fls;
++	uint16_t	vbm_st;
++	uint16_t	alloc_ptr;
++	uint16_t	nm_al_blks;
++	uint32_t	al_blk_size;
++	uint32_t	clp_size;
++	uint16_t	al_bl_st;
++	uint32_t	nxt_cnid;
++	uint16_t	free_bks;
++	uint8_t		label_len;
++	uint8_t		label[27];
++	uint32_t	vol_bkup;
++	uint16_t	vol_seq_num;
++	uint32_t	wr_cnt;
++	uint32_t	xt_clump_size;
++	uint32_t	ct_clump_size;
++	uint16_t	num_root_dirs;
++	uint32_t	file_count;
++	uint32_t	dir_count;
++	struct hfs_finder_info finder_info;
++	uint8_t		embed_sig[2];
++	uint16_t	embed_startblock;
++	uint16_t	embed_blockcount;
++} PACKED *hfs;
++
++struct hfsplus_bnode_descriptor {
++	uint32_t	next;
++	uint32_t	prev;
++	uint8_t		type;
++	uint8_t		height;
++	uint16_t	num_recs;
++	uint16_t	reserved;
++} PACKED;
++
++struct hfsplus_bheader_record {
++	uint16_t	depth;
++	uint32_t	root;
++	uint32_t	leaf_count;
++	uint32_t	leaf_head;
++	uint32_t	leaf_tail;
++	uint16_t	node_size;
++} PACKED;
++
++struct hfsplus_catalog_key {
++	uint16_t	key_len;
++	uint32_t	parent_id;
++	uint16_t	unicode_len;
++	uint8_t		unicode[255 * 2];
++} PACKED;
++
++struct hfsplus_extent {
++	uint32_t	start_block;
++	uint32_t	block_count;
++} PACKED;
++
++#define HFSPLUS_EXTENT_COUNT		8
++struct hfsplus_fork {
++	uint64_t	total_size;
++	uint32_t	clump_size;
++	uint32_t	total_blocks;
++	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
++} PACKED;
++
++static struct hfsplus_vol_header {
++	uint8_t		signature[2];
++	uint16_t	version;
++	uint32_t	attributes;
++	uint32_t	last_mount_vers;
++	uint32_t	reserved;
++	uint32_t	create_date;
++	uint32_t	modify_date;
++	uint32_t	backup_date;
++	uint32_t	checked_date;
++	uint32_t	file_count;
++	uint32_t	folder_count;
++	uint32_t	blocksize;
++	uint32_t	total_blocks;
++	uint32_t	free_blocks;
++	uint32_t	next_alloc;
++	uint32_t	rsrc_clump_sz;
++	uint32_t	data_clump_sz;
++	uint32_t	next_cnid;
++	uint32_t	write_count;
++	uint64_t	encodings_bmp;
++	struct hfs_finder_info finder_info;
++	struct hfsplus_fork alloc_file;
++	struct hfsplus_fork ext_file;
++	struct hfsplus_fork cat_file;
++	struct hfsplus_fork attr_file;
++	struct hfsplus_fork start_file;
++} PACKED *hfsplus;
++
++#define HFS_SUPERBLOCK_OFFSET		0x400
++#define HFS_NODE_LEAF			0xff
++#define HFSPLUS_POR_CNID		1
++
++static void hfsid_set_uuid(struct volume_id *id, const uint8_t *hfs_id)
++{
++#if 0
++	MD5_CTX md5c;
++	static const uint8_t hash_init[16] = {
++		0xb3, 0xe2, 0x0f, 0x39, 0xf2, 0x92, 0x11, 0xd6,
++		0x97, 0xa4, 0x00, 0x30, 0x65, 0x43, 0xec, 0xac
++	};
++	uint8_t uuid[16];
++
++	if (*((uint64_t *)hfs_id) == 0)
++		return;
++
++	MD5_Init(&md5c);
++	MD5_Update(&md5c, &hash_init, 16);
++	MD5_Update(&md5c, hfs_id, 8);
++	MD5_Final(uuid, &md5c);
++
++	uuid[6] = 0x30 | (uuid[6] & 0x0f);
++	uuid[8] = 0x80 | (uuid[8] & 0x3f);
++	volume_id_set_uuid(id, uuid, UUID_DCE);
++#endif
++
++	volume_id_set_uuid(id, hfs_id, 0, UUID_64BIT_BE);
++}
++
++int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	unsigned int blocksize;
++	unsigned int cat_block;
++	unsigned int ext_block_start;
++	unsigned int ext_block_count;
++	int ext;
++	unsigned int leaf_node_head;
++	unsigned int leaf_node_count;
++	unsigned int leaf_node_size;
++	unsigned int leaf_block;
++	uint64_t leaf_off;
++	unsigned int alloc_block_size;
++	unsigned int alloc_first_block;
++	unsigned int embed_first_block;
++	unsigned int record_count;
++	struct hfsplus_bnode_descriptor *descr;
++	struct hfsplus_bheader_record *bnode;
++	struct hfsplus_catalog_key *key;
++	unsigned int label_len;
++	struct hfsplus_extent extents[HFSPLUS_EXTENT_COUNT];
++	const uint8_t *buf;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
++	if (buf == NULL)
++                return -1;
++
++	hfs = (struct hfs_mdb *) buf;
++	if (memcmp((char *)hfs->signature, "BD", 2) != 0)
++		goto checkplus;
++
++	/* it may be just a hfs wrapper for hfs+ */
++	if (memcmp((char *)hfs->embed_sig, "H+", 2) == 0) {
++		alloc_block_size = be32_to_cpu(hfs->al_blk_size);
++		dbg("alloc_block_size 0x%x", alloc_block_size);
++
++		alloc_first_block = be16_to_cpu(hfs->al_bl_st);
++		dbg("alloc_first_block 0x%x", alloc_first_block);
++
++		embed_first_block = be16_to_cpu(hfs->embed_startblock);
++		dbg("embed_first_block 0x%x", embed_first_block);
++
++		off += (alloc_first_block * 512) +
++		       (embed_first_block * alloc_block_size);
++		dbg("hfs wrapped hfs+ found at offset 0x%llx", (unsigned long long) off);
++
++		buf = volume_id_get_buffer(id, off + HFS_SUPERBLOCK_OFFSET, 0x200);
++		if (buf == NULL)
++			return -1;
++		goto checkplus;
++	}
++
++	if (hfs->label_len > 0 && hfs->label_len < 28) {
++		volume_id_set_label_raw(id, hfs->label, hfs->label_len);
++		volume_id_set_label_string(id, hfs->label, hfs->label_len) ;
++	}
++
++	hfsid_set_uuid(id, hfs->finder_info.id);
++
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "hfs";
++
++	return 0;
++
++checkplus:
++	hfsplus = (struct hfsplus_vol_header *) buf;
++	if (memcmp((char *)hfsplus->signature, "H+", 2) == 0)
++		goto hfsplus;
++	if (memcmp((char *)hfsplus->signature, "HX", 2) == 0)
++		goto hfsplus;
++	return -1;
++
++hfsplus:
++	hfsid_set_uuid(id, hfsplus->finder_info.id);
++
++	blocksize = be32_to_cpu(hfsplus->blocksize);
++	dbg("blocksize %u", blocksize);
++
++	memcpy(extents, hfsplus->cat_file.extents, sizeof(extents));
++	cat_block = be32_to_cpu(extents[0].start_block);
++	dbg("catalog start block 0x%x", cat_block);
++
++	buf = volume_id_get_buffer(id, off + (cat_block * blocksize), 0x2000);
++	if (buf == NULL)
++		goto found;
++
++	bnode = (struct hfsplus_bheader_record *)
++		&buf[sizeof(struct hfsplus_bnode_descriptor)];
++
++	leaf_node_head = be32_to_cpu(bnode->leaf_head);
++	dbg("catalog leaf node 0x%x", leaf_node_head);
++
++	leaf_node_size = be16_to_cpu(bnode->node_size);
++	dbg("leaf node size 0x%x", leaf_node_size);
++
++	leaf_node_count = be32_to_cpu(bnode->leaf_count);
++	dbg("leaf node count 0x%x", leaf_node_count);
++	if (leaf_node_count == 0)
++		goto found;
++
++	leaf_block = (leaf_node_head * leaf_node_size) / blocksize;
++
++	/* get physical location */
++	for (ext = 0; ext < HFSPLUS_EXTENT_COUNT; ext++) {
++		ext_block_start = be32_to_cpu(extents[ext].start_block);
++		ext_block_count = be32_to_cpu(extents[ext].block_count);
++		dbg("extent start block 0x%x, count 0x%x", ext_block_start, ext_block_count);
++
++		if (ext_block_count == 0)
++			goto found;
++
++		/* this is our extent */
++		if (leaf_block < ext_block_count)
++			break;
++
++		leaf_block -= ext_block_count;
++	}
++	if (ext == HFSPLUS_EXTENT_COUNT)
++		goto found;
++	dbg("found block in extent %i", ext);
++
++	leaf_off = (ext_block_start + leaf_block) * blocksize;
++
++	buf = volume_id_get_buffer(id, off + leaf_off, leaf_node_size);
++	if (buf == NULL)
++		goto found;
++
++	descr = (struct hfsplus_bnode_descriptor *) buf;
++	dbg("descriptor type 0x%x", descr->type);
++
++	record_count = be16_to_cpu(descr->num_recs);
++	dbg("number of records %u", record_count);
++	if (record_count == 0)
++		goto found;
++
++	if (descr->type != HFS_NODE_LEAF)
++		goto found;
++
++	key = (struct hfsplus_catalog_key *)
++		&buf[sizeof(struct hfsplus_bnode_descriptor)];
++
++	dbg("parent id 0x%x", be32_to_cpu(key->parent_id));
++	if (be32_to_cpu(key->parent_id) != HFSPLUS_POR_CNID)
++		goto found;
++
++	label_len = be16_to_cpu(key->unicode_len) * 2;
++	dbg("label unicode16 len %i", label_len);
++	volume_id_set_label_raw(id, key->unicode, label_len);
++	volume_id_set_label_unicode16(id, key->unicode, BE, label_len);
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "hfsplus";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/highpoint.c'
+--- grub-0.97.orig/libvolume_id/highpoint.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/highpoint.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,91 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct hpt37x_meta {
++	uint8_t		filler1[32];
++	uint32_t	magic;
++} PACKED;
++
++struct hpt45x_meta {
++	uint32_t	magic;
++} PACKED;
++
++#define HPT37X_CONFIG_OFF		0x1200
++#define HPT37X_MAGIC_OK			0x5a7816f0
++#define HPT37X_MAGIC_BAD		0x5a7816fd
++
++#define HPT45X_MAGIC_OK			0x5a7816f3
++#define HPT45X_MAGIC_BAD		0x5a7816fd
++
++
++int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	struct hpt37x_meta *hpt;
++	uint32_t magic;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off + HPT37X_CONFIG_OFF, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	hpt = (struct hpt37x_meta *) buf;
++	magic = le32_to_cpu(hpt->magic);
++	if (magic != HPT37X_MAGIC_OK && magic != HPT37X_MAGIC_BAD)
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "highpoint_raid_member";
++
++	return 0;
++}
++
++int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	struct hpt45x_meta *hpt;
++	uint64_t meta_off;
++	uint32_t magic;
++
++	dbg("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x10000)
++		return -1;
++
++	meta_off = ((size / 0x200)-11) * 0x200;
++	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	hpt = (struct hpt45x_meta *) buf;
++	magic = le32_to_cpu(hpt->magic);
++	if (magic != HPT45X_MAGIC_OK && magic != HPT45X_MAGIC_BAD)
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "highpoint_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/hpfs.c'
+--- grub-0.97.orig/libvolume_id/hpfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/hpfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,51 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct hpfs_super
++{
++	uint8_t		magic[4];
++	uint8_t		version;
++} PACKED;
++
++#define HPFS_SUPERBLOCK_OFFSET			0x2000
++
++int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct hpfs_super *hs;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	hs = (struct hpfs_super *) volume_id_get_buffer(id, off + HPFS_SUPERBLOCK_OFFSET, 0x200);
++	if (hs == NULL)
++		return -1;
++
++	if (memcmp((char *)hs->magic, "\x49\xe8\x95\xf9", 4) == 0) {
++		sprintf(id->type_version, "%u", hs->version);
++
++		volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++		id->type = "hpfs";
++		return 0;
++	}
++
++	return -1;
++}
+
+=== added file 'libvolume_id/iso9660.c'
+--- grub-0.97.orig/libvolume_id/iso9660.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/iso9660.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,119 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++#define ISO_SUPERBLOCK_OFFSET		0x8000
++#define ISO_SECTOR_SIZE			0x800
++#define ISO_VD_OFFSET			(ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
++#define ISO_VD_PRIMARY			0x1
++#define ISO_VD_SUPPLEMENTARY		0x2
++#define ISO_VD_END			0xff
++#define ISO_VD_MAX			16
++
++struct iso_volume_descriptor {
++	uint8_t		type;
++	uint8_t		id[5];
++	uint8_t		version;
++	uint8_t		flags;
++	uint8_t		system_id[32];
++	uint8_t		volume_id[32];
++	uint8_t		unused[8];
++	uint8_t		space_size[8];
++	uint8_t		escape_sequences[8];
++} PACKED;
++
++struct high_sierra_volume_descriptor {
++	uint8_t		foo[8];
++	uint8_t		type;
++	uint8_t		id[5];
++	uint8_t		version;
++} PACKED;
++
++int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	uint8_t *buf;
++	struct iso_volume_descriptor *is;
++	struct high_sierra_volume_descriptor *hs;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off + ISO_SUPERBLOCK_OFFSET, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	is = (struct iso_volume_descriptor *) buf;
++
++	if (memcmp((char*)is->id, "CD001", 5) == 0) {
++		int vd_offset;
++		int i;
++
++		dbg("read label from PVD");
++		volume_id_set_label_raw(id, is->volume_id, 32);
++		volume_id_set_label_string(id, is->volume_id, 32);
++
++		dbg("looking for SVDs");
++		vd_offset = ISO_VD_OFFSET;
++		for (i = 0; i < ISO_VD_MAX; i++) {
++			uint8_t svd_label[64];
++
++			is = (struct iso_volume_descriptor *) volume_id_get_buffer(id, off + vd_offset, 0x200);
++			if (is == NULL || is->type == ISO_VD_END)
++				break;
++			if (is->type != ISO_VD_SUPPLEMENTARY)
++				continue;
++
++			dbg("found SVD at offset 0x%llx", (unsigned long long) (off + vd_offset));
++			if (memcmp((char *)is->escape_sequences, "%/@", 3) == 0||
++			    memcmp((char *)is->escape_sequences, "%/C", 3) == 0||
++			    memcmp((char *)is->escape_sequences, "%/E", 3) == 0) {
++				dbg("Joliet extension found");
++				volume_id_set_unicode16(svd_label, sizeof(svd_label), is->volume_id, BE, 32);
++				if (memcmp((char *)id->label, (char *)svd_label, 16) == 0) {
++					dbg("SVD label is identical, use the possibly longer PVD one");
++					break;
++				}
++
++				volume_id_set_label_raw(id, is->volume_id, 32);
++				volume_id_set_label_string(id, svd_label, 32);
++				strcpy(id->type_version, "Joliet Extension");
++				goto found;
++			}
++			vd_offset += ISO_SECTOR_SIZE;
++		}
++		goto found;
++	}
++
++	hs = (struct high_sierra_volume_descriptor *) buf;
++
++	if (memcmp((char *)hs->id, "CDROM", 5) == 0) {
++		strcpy(id->type_version, "High Sierra");
++		goto found;
++	}
++
++	return -1;
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "iso9660";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/isw_raid.c'
+--- grub-0.97.orig/libvolume_id/isw_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/isw_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,61 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct isw_meta {
++	uint8_t		sig[32];
++	uint32_t	check_sum;
++	uint32_t	mpb_size;
++	uint32_t	family_num;
++	uint32_t	generation_num;
++} PACKED;
++
++#define ISW_SIGNATURE		"Intel Raid ISM Cfg Sig. "
++
++
++int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	uint64_t meta_off;
++	struct isw_meta *isw;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x10000)
++		return -1;
++
++	meta_off = ((size / 0x200)-2) * 0x200;
++	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	isw = (struct isw_meta *) buf;
++	if (memcmp((char *)isw->sig, ISW_SIGNATURE, sizeof(ISW_SIGNATURE)-1) != 0)
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	memcpy(id->type_version, &isw->sig[sizeof(ISW_SIGNATURE)-1], 6);
++	id->type = "isw_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/jfs.c'
+--- grub-0.97.orig/libvolume_id/jfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/jfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,60 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct jfs_super_block {
++	uint8_t		magic[4];
++	uint32_t	version;
++	uint64_t	size;
++	uint32_t	bsize;
++	uint32_t	dummy1;
++	uint32_t	pbsize;
++	uint32_t	dummy2[27];
++	uint8_t		uuid[16];
++	uint8_t		label[16];
++	uint8_t		loguuid[16];
++} PACKED;
++
++#define JFS_SUPERBLOCK_OFFSET			0x8000
++
++int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct jfs_super_block *js;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	js = (struct jfs_super_block *) volume_id_get_buffer(id, off + JFS_SUPERBLOCK_OFFSET, 0x200);
++	if (js == NULL)
++		return -1;
++
++	if (memcmp((char *)js->magic, "JFS1", 4) != 0)
++		return -1;
++
++	volume_id_set_label_raw(id, js->label, 16);
++	volume_id_set_label_string(id, js->label, 16);
++	volume_id_set_uuid(id, js->uuid, 0, UUID_DCE);
++
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "jfs";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/jmicron_raid.c'
+--- grub-0.97.orig/libvolume_id/jmicron_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/jmicron_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,57 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct jmicron_meta {
++	int8_t		signature[2];
++	uint8_t		minor_version;
++	uint8_t		major_version;
++	uint16_t	checksum;
++} PACKED;
++
++int volume_id_probe_jmicron_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	uint64_t meta_off;
++	struct jmicron_meta *jm;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x10000)
++		return -1;
++
++	meta_off = ((size / 0x200)-1) * 0x200;
++	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	jm = (struct jmicron_meta *) buf;
++	if (memcmp((char *)jm->signature, "JM", 2) != 0)
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	sprintf(id->type_version, "%u.%u", jm->major_version, jm->minor_version);
++	id->type = "jmicron_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/linux_raid.c'
+--- grub-0.97.orig/libvolume_id/linux_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/linux_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,160 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++static struct mdp0_super_block {
++	uint32_t	md_magic;
++	uint32_t	major_version;
++	uint32_t	minor_version;
++	uint32_t	patch_version;
++	uint32_t	gvalid_words;
++	uint32_t	set_uuid0;
++	uint32_t	ctime;
++	uint32_t	level;
++	uint32_t	size;
++	uint32_t	nr_disks;
++	uint32_t	raid_disks;
++	uint32_t	md_minor;
++	uint32_t	not_persistent;
++	uint32_t	set_uuid1;
++	uint32_t	set_uuid2;
++	uint32_t	set_uuid3;
++} PACKED *mdp0;
++
++struct mdp1_super_block {
++	uint32_t	magic;
++	uint32_t	major_version;
++	uint32_t	feature_map;
++	uint32_t	pad0;
++	uint8_t		set_uuid[16];
++	uint8_t		set_name[32];
++} PACKED *mdp1;
++
++#define MD_RESERVED_BYTES		0x10000
++#define MD_SB_MAGIC			0xa92b4efc
++
++static int volume_id_probe_linux_raid0(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	union {
++		uint32_t ints[4];
++		uint8_t bytes[16];
++	} uuid;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++	if (size < 0x10000)
++		return -1;
++
++	buf = volume_id_get_buffer(id, off, 0x800);
++	if (buf == NULL)
++		return -1;
++	mdp0 = (struct mdp0_super_block *) buf;
++
++	if (le32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
++		uuid.ints[0] = bswap_32(mdp0->set_uuid0);
++		if (le32_to_cpu(mdp0->minor_version >= 90)) {
++			uuid.ints[1] = bswap_32(mdp0->set_uuid1);
++			uuid.ints[2] = bswap_32(mdp0->set_uuid2);
++			uuid.ints[3] = bswap_32(mdp0->set_uuid3);
++		} else {
++			uuid.ints[1] = 0;
++			uuid.ints[2] = 0;
++			uuid.ints[3] = 0;
++		}
++		volume_id_set_uuid(id, uuid.bytes, 0, UUID_FOURINT);
++		sprintf(id->type_version, "%u.%u.%u",
++			 le32_to_cpu(mdp0->major_version),
++			 le32_to_cpu(mdp0->minor_version),
++			 le32_to_cpu(mdp0->patch_version));
++	} else if (be32_to_cpu(mdp0->md_magic) == MD_SB_MAGIC) {
++		uuid.ints[0] = mdp0->set_uuid0;
++		if (be32_to_cpu(mdp0->minor_version >= 90)) {
++			uuid.ints[1] = mdp0->set_uuid1;
++			uuid.ints[2] = mdp0->set_uuid2;
++			uuid.ints[3] = mdp0->set_uuid3;
++		} else {
++			uuid.ints[1] = 0;
++			uuid.ints[2] = 0;
++			uuid.ints[3] = 0;
++		}
++		volume_id_set_uuid(id, uuid.bytes, 0, UUID_FOURINT);
++		sprintf(id->type_version, "%u.%u.%u",
++			 be32_to_cpu(mdp0->major_version),
++			 be32_to_cpu(mdp0->minor_version),
++			 be32_to_cpu(mdp0->patch_version));
++	} else
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "linux_raid_member";
++	return 0;
++}
++
++static int volume_id_probe_linux_raid1(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	buf = volume_id_get_buffer(id, off, 0x800);
++	if (buf == NULL)
++		return -1;
++	mdp1 = (struct mdp1_super_block *) buf;
++
++	if (le32_to_cpu(mdp1->magic) != MD_SB_MAGIC)
++		return -1;
++
++	volume_id_set_uuid(id, mdp1->set_uuid, 0, UUID_FOURINT);
++	volume_id_set_label_raw(id, mdp1->set_name, 32);
++	volume_id_set_label_string(id, mdp1->set_name, 32);
++	sprintf(id->type_version, "%u", le32_to_cpu(mdp1->major_version));
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "linux_raid_member";
++	return 0;
++}
++
++int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	uint64_t sboff;
++
++	/* version 0 at the end of the device */
++	sboff = (size & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES;
++	if (volume_id_probe_linux_raid0(id, off + sboff, size) == 0)
++		return 0;
++
++	/* version 1.0 at the end of the device */
++	sboff = (size & ~(0x1000 - 1)) - 0x2000;
++	if (volume_id_probe_linux_raid1(id, off + sboff, size) == 0)
++		return 0;
++
++	/* version 1.1 at the start of the device */
++	if (volume_id_probe_linux_raid1(id, off, size) == 0)
++		return 0;
++
++	/* version 1.2 at 4k offset from the start */
++	if (volume_id_probe_linux_raid1(id, off + 0x1000, size) == 0)
++		return 0;
++
++	return -1;
++}
+
+=== added file 'libvolume_id/linux_swap.c'
+--- grub-0.97.orig/libvolume_id/linux_swap.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/linux_swap.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,85 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct swap_header_v1_2 {
++	uint8_t		bootbits[1024];
++	uint32_t	version;
++	uint32_t	last_page;
++	uint32_t	nr_badpages;
++	uint8_t		uuid[16];
++	uint8_t		volume_name[16];
++} PACKED;
++
++#define LARGEST_PAGESIZE			0x4000
++
++int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	unsigned int page;
++	struct swap_header_v1_2 *sw;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	/* eek, the swap signature is at the end of the PAGE_SIZE */
++	for (page = 0x1000; page <= LARGEST_PAGESIZE; page <<= 1) {
++			buf = volume_id_get_buffer(id, off + page-10, 10);
++			if (buf == NULL)
++				return -1;
++
++			if (memcmp((char *)buf, "SWAP-SPACE", 10) == 0) {
++				strcpy(id->type_version, "1");
++				goto found;
++			}
++
++			if (memcmp((char *)buf, "SWAPSPACE2", 10) == 0) {
++				id->type = "swap";
++				strcpy(id->type_version, "2");
++				goto found_label;
++			}
++
++			if (memcmp((char *)buf, "S1SUSPEND", 9) == 0) {
++				id->type = "suspend";
++				strcpy(id->type_version, "s1suspend");
++				goto found_label;
++			}
++
++			if (memcmp((char *)buf, "ULSUSPEND", 9) == 0) {
++				id->type = "suspend";
++				strcpy(id->type_version, "ulsuspend");
++				goto found_label;
++			}
++	}
++	return -1;
++
++found_label:
++	sw = (struct swap_header_v1_2 *) volume_id_get_buffer(id, off, sizeof(struct swap_header_v1_2));
++	if (sw != NULL) {
++		volume_id_set_label_raw(id, sw->volume_name, 16);
++		volume_id_set_label_string(id, sw->volume_name, 16);
++		volume_id_set_uuid(id, sw->uuid, 0, UUID_DCE);
++	}
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_OTHER);
++	return 0;
++}
+
+=== added file 'libvolume_id/lsi_raid.c'
+--- grub-0.97.orig/libvolume_id/lsi_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/lsi_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,55 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct lsi_meta {
++	uint8_t		sig[6];
++} PACKED;
++
++#define LSI_SIGNATURE		"$XIDE$"
++
++int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	uint64_t meta_off;
++	struct lsi_meta *lsi;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x10000)
++		return -1;
++
++	meta_off = ((size / 0x200)-1) * 0x200;
++	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	lsi = (struct lsi_meta *) buf;
++	if (memcmp((char *)lsi->sig, LSI_SIGNATURE, sizeof(LSI_SIGNATURE)-1) != 0)
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "lsi_mega_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/luks.c'
+--- grub-0.97.orig/libvolume_id/luks.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/luks.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,76 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 W. Michael Petullo <mike@flyn.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++#define LUKS_SECTOR_SHIFT		9
++#define LUKS_SECTOR_SIZE		(1 << LUKS_SECTOR_SHIFT)
++
++#define LUKS_CIPHERNAME_L		32
++#define LUKS_CIPHERMODE_L		32
++#define LUKS_HASHSPEC_L			32
++#define LUKS_DIGESTSIZE			20
++#define LUKS_SALTSIZE			32
++#define LUKS_NUMKEYS			8
++
++#define LUKS_MAGIC_L			6
++#define LUKS_PHDR_SIZE			(sizeof(struct luks_phdr)/LUKS_SECTOR_SIZE+1)
++#define UUID_STRING_L			40
++static const uint8_t LUKS_MAGIC[] = {'L','U','K','S', 0xba, 0xbe};
++
++struct luks_phdr {
++	uint8_t		magic[LUKS_MAGIC_L];
++	uint16_t	version;
++	uint8_t		cipherName[LUKS_CIPHERNAME_L];
++	uint8_t		cipherMode[LUKS_CIPHERMODE_L];
++	uint8_t		hashSpec[LUKS_HASHSPEC_L];
++	uint32_t	payloadOffset;
++	uint32_t	keyBytes;
++	uint8_t		mkDigest[LUKS_DIGESTSIZE];
++	uint8_t		mkDigestSalt[LUKS_SALTSIZE];
++	uint32_t	mkDigestIterations;
++	uint8_t		uuid[UUID_STRING_L];
++	struct {
++		uint32_t	active;
++		uint32_t	passwordIterations;
++		uint8_t		passwordSalt[LUKS_SALTSIZE];
++		uint32_t	keyMaterialOffset;
++		uint32_t	stripes;
++	} keyblock[LUKS_NUMKEYS];
++};
++
++int volume_id_probe_luks(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct luks_phdr *header;
++
++	header = (struct luks_phdr*) volume_id_get_buffer(id, off, LUKS_PHDR_SIZE);
++	if (header == NULL)
++		return -1;
++
++	if (memcmp((char *)header->magic, (char *)LUKS_MAGIC, LUKS_MAGIC_L))
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_CRYPTO);
++	volume_id_set_uuid(id, header->uuid, 36, UUID_HEX_STRING);
++	sprintf(id->type_version, "%u", le16_to_cpu(header->version));
++	id->type = "crypto_LUKS";
++	return 0;
++}
+
+=== added file 'libvolume_id/lvm.c'
+--- grub-0.97.orig/libvolume_id/lvm.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/lvm.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,92 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct lvm1_super_block {
++	uint8_t	id[2];
++} PACKED;
++
++struct lvm2_super_block {
++	uint8_t		id[8];
++	uint64_t	sector_xl;
++	uint32_t	crc_xl;
++	uint32_t	offset_xl;
++	uint8_t		type[8];
++} PACKED;
++
++#define LVM1_SB_OFF			0x400
++#define LVM1_MAGIC			"HM"
++
++int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	struct lvm1_super_block *lvm;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off + LVM1_SB_OFF, 0x800);
++	if (buf == NULL)
++		return -1;
++
++	lvm = (struct lvm1_super_block *) buf;
++
++	if (memcmp((char *)lvm->id, LVM1_MAGIC, 2) != 0)
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "LVM1_member";
++
++	return 0;
++}
++
++#define LVM2_LABEL_ID			"LABELONE"
++#define LVM2LABEL_SCAN_SECTORS		4
++
++int volume_id_probe_lvm2(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	unsigned int soff;
++	struct lvm2_super_block *lvm;
++
++	dbg("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off, LVM2LABEL_SCAN_SECTORS * 0x200);
++	if (buf == NULL)
++		return -1;
++
++
++	for (soff = 0; soff < LVM2LABEL_SCAN_SECTORS * 0x200; soff += 0x200) {
++		lvm = (struct lvm2_super_block *) &buf[soff];
++
++		if (memcmp((char *)lvm->id, LVM2_LABEL_ID, 8) == 0)
++			goto found;
++	}
++
++	return -1;
++
++found:
++	memcpy(id->type_version, lvm->type, 8);
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "LVM2_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/minix.c'
+--- grub-0.97.orig/libvolume_id/minix.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/minix.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,112 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++#define MINIX_SUPERBLOCK_OFFSET			0x400
++
++#define MINIX_SUPER_MAGIC			0x137F
++#define MINIX_SUPER_MAGIC2			0x138F
++#define MINIX2_SUPER_MAGIC			0x2468
++#define MINIX2_SUPER_MAGIC2			0x2478
++#define MINIX3_SUPER_MAGIC			0x4d5a
++
++struct minix_super_block
++{
++	uint16_t	s_ninodes;
++	uint16_t	s_nzones;
++	uint16_t	s_imap_blocks;
++	uint16_t	s_zmap_blocks;
++	uint16_t	s_firstdatazone;
++	uint16_t	s_log_zone_size;
++	uint32_t	s_max_size;
++	uint16_t	s_magic;
++	uint16_t	s_state;
++	uint32_t	s_zones;
++} PACKED;
++
++struct minix3_super_block {
++	uint32_t	s_ninodes;
++	uint16_t	s_pad0;
++	uint16_t	s_imap_blocks;
++	uint16_t	s_zmap_blocks;
++	uint16_t	s_firstdatazone;
++	uint16_t	s_log_zone_size;
++	uint16_t	s_pad1;
++	uint32_t	s_max_size;
++	uint32_t	s_zones;
++	uint16_t	s_magic;
++	uint16_t	s_pad2;
++	uint16_t	s_blocksize;
++	uint8_t 	s_disk_version;
++} PACKED;
++
++int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	uint8_t *buf;
++	struct minix_super_block *ms;
++	struct minix3_super_block *m3s;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off + MINIX_SUPERBLOCK_OFFSET, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	ms = (struct minix_super_block *) buf;
++
++	if (ms->s_magic == MINIX_SUPER_MAGIC ||
++	    ms->s_magic == bswap_16(MINIX_SUPER_MAGIC)) {
++		strcpy(id->type_version, "1");
++		goto found;
++	}
++	if (ms->s_magic == MINIX_SUPER_MAGIC2 ||
++	    ms->s_magic == bswap_16(MINIX_SUPER_MAGIC2)) {
++		strcpy(id->type_version, "1");
++		goto found;
++	}
++	if (ms->s_magic == MINIX2_SUPER_MAGIC ||
++	    ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC)) {
++		strcpy(id->type_version, "2");
++		goto found;
++	}
++	if (ms->s_magic == MINIX2_SUPER_MAGIC2 ||
++	    ms->s_magic == bswap_16(MINIX2_SUPER_MAGIC2)) {
++		strcpy(id->type_version, "2");
++		goto found;
++	}
++
++	m3s = (struct minix3_super_block *) buf;
++	if (m3s->s_magic == MINIX3_SUPER_MAGIC ||
++	    m3s->s_magic == bswap_16(MINIX3_SUPER_MAGIC)) {
++		strcpy(id->type_version, "3");
++		goto found;
++	}
++	goto exit;
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "minix";
++	return 0;
++
++exit:
++	return -1;
++}
+
+=== added file 'libvolume_id/misc.c'
+--- grub-0.97.orig/libvolume_id/misc.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/misc.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,34 @@
++/*
++ * volume_id/misc.c
++ *
++ * Copyright (C) 2008 Canonical Ltd.
++ *
++ *      This program is free software; you can redistribute it and/or modify it
++ *      under the terms of the GNU General Public License as published by the
++ *      Free Software Foundation version 2 of the License.
++ */
++#define _GNU_SOURCE
++#include <string.h>
++
++/*
++ *  Misc auxiliary functions required for volume_id inside grub
++ */
++size_t strnlen(const char *s, size_t limit)
++{
++	size_t length = 0;
++	while ( (length < limit) && (*s++) ) 
++		length++;
++
++   	return length;
++}
++
++char *strchr (const char *s, int c)
++{
++	do {
++		if ( *s == c ) {
++			return (char*)s;
++      		}
++  	} while ( *s++ );
++
++  	return 0;
++}
+
+=== added file 'libvolume_id/netware.c'
+--- grub-0.97.orig/libvolume_id/netware.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/netware.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,98 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++#define NW_SUPERBLOCK_OFFSET			0x1000
++
++struct netware_super_block {
++	uint8_t		SBH_Signature[4];
++	uint16_t	SBH_VersionMajor;
++	uint16_t	SBH_VersionMinor;
++	uint16_t	SBH_VersionMediaMajor;
++	uint16_t	SBH_VersionMediaMinor;
++	uint32_t	SBH_ItemsMoved;
++	uint8_t		SBH_InternalID[16];
++	uint32_t	SBH_PackedSize;
++	uint32_t	SBH_Checksum;
++	uint32_t	supersyncid;
++	int64_t		superlocation[4];
++	uint32_t	physSizeUsed;
++	uint32_t	sizeUsed;
++	uint32_t	superTimeStamp;
++	uint32_t	reserved0[1];
++	int64_t		SBH_LoggedPoolDataBlk;
++	int64_t		SBH_PoolDataBlk;
++	uint8_t		SBH_OldInternalID[16];
++	uint32_t	SBH_PoolToLVStartUTC;
++	uint32_t	SBH_PoolToLVEndUTC;
++	uint16_t	SBH_VersionMediaMajorCreate;
++	uint16_t	SBH_VersionMediaMinorCreate;
++	uint32_t	SBH_BlocksMoved;
++	uint32_t	SBH_TempBTSpBlk;
++	uint32_t	SBH_TempFTSpBlk;
++	uint32_t	SBH_TempFTSpBlk1;
++	uint32_t	SBH_TempFTSpBlk2;
++	uint32_t 	nssMagicNumber;
++	uint32_t	poolClassID;
++	uint32_t 	poolID;
++	uint32_t	createTime;
++	int64_t		SBH_LoggedVolumeDataBlk;
++	int64_t		SBH_VolumeDataBlk;
++	int64_t		SBH_SystemBeastBlkNum;
++	uint64_t	totalblocks;
++	uint16_t 	SBH_Name[64];
++	uint8_t		SBH_VolumeID[16];
++	uint8_t		SBH_PoolID[16];
++	uint8_t		SBH_PoolInternalID[16];
++	uint64_t	SBH_Lsn;
++	uint32_t	SBH_SS_Enabled;
++	uint32_t	SBH_SS_CreateTime;
++	uint8_t		SBH_SS_OriginalPoolID[16];
++	uint8_t		SBH_SS_OriginalVolumeID[16];
++	uint8_t		SBH_SS_Guid[16];
++	uint16_t	SBH_SS_OriginalName[64];
++	uint32_t	reserved2[64-(2+46)];
++} PACKED;
++
++int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct netware_super_block *nw;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	nw = (struct netware_super_block *) volume_id_get_buffer(id, off + NW_SUPERBLOCK_OFFSET, 0x200);
++	if (nw == NULL)
++		return -1;
++
++	if (memcmp((char *)nw->SBH_Signature, "SPB5", 4) != 0)
++		return -1;
++
++	volume_id_set_uuid(id, nw->SBH_PoolID, 0, UUID_DCE);
++
++	sprintf(id->type_version, "%u.%02u",
++		 le16_to_cpu(nw->SBH_VersionMediaMajor), le16_to_cpu(nw->SBH_VersionMediaMinor));
++
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "nss";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/ntfs.c'
+--- grub-0.97.orig/libvolume_id/ntfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/ntfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,192 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++static struct ntfs_super_block {
++	uint8_t		jump[3];
++	uint8_t		oem_id[8];
++	uint16_t	bytes_per_sector;
++	uint8_t		sectors_per_cluster;
++	uint16_t	reserved_sectors;
++	uint8_t		fats;
++	uint16_t	root_entries;
++	uint16_t	sectors;
++	uint8_t		media_type;
++	uint16_t	sectors_per_fat;
++	uint16_t	sectors_per_track;
++	uint16_t	heads;
++	uint32_t	hidden_sectors;
++	uint32_t	large_sectors;
++	uint16_t	unused[2];
++	uint64_t	number_of_sectors;
++	uint64_t	mft_cluster_location;
++	uint64_t	mft_mirror_cluster_location;
++	int8_t		cluster_per_mft_record;
++	uint8_t		reserved1[3];
++	int8_t		cluster_per_index_record;
++	uint8_t		reserved2[3];
++	uint8_t		volume_serial[8];
++	uint16_t	checksum;
++} PACKED *ns;
++
++static struct master_file_table_record {
++	uint8_t		magic[4];
++	uint16_t	usa_ofs;
++	uint16_t	usa_count;
++	uint64_t	lsn;
++	uint16_t	sequence_number;
++	uint16_t	link_count;
++	uint16_t	attrs_offset;
++	uint16_t	flags;
++	uint32_t	bytes_in_use;
++	uint32_t	bytes_allocated;
++} PACKED *mftr;
++
++static struct file_attribute {
++	uint32_t	type;
++	uint32_t	len;
++	uint8_t		non_resident;
++	uint8_t		name_len;
++	uint16_t	name_offset;
++	uint16_t	flags;
++	uint16_t	instance;
++	uint32_t	value_len;
++	uint16_t	value_offset;
++} PACKED *attr;
++
++static struct volume_info {
++	uint64_t	reserved;
++	uint8_t		major_ver;
++	uint8_t		minor_ver;
++} PACKED *info;
++
++#define MFT_RECORD_VOLUME			3
++#define MFT_RECORD_ATTR_VOLUME_NAME		0x60
++#define MFT_RECORD_ATTR_VOLUME_INFO		0x70
++#define MFT_RECORD_ATTR_OBJECT_ID		0x40
++#define MFT_RECORD_ATTR_END			0xffffffffu
++
++#undef debug
++#define debug grub_printf
++
++int volume_id_probe_ntfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	unsigned int sector_size;
++	unsigned int cluster_size;
++	uint64_t mft_cluster;
++	uint64_t mft_off;
++	unsigned int mft_record_size;
++	unsigned int attr_type;
++	unsigned int attr_off;
++	unsigned int attr_len;
++	unsigned int val_off;
++	unsigned int val_len;
++	const uint8_t *buf;
++	const uint8_t *val;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	ns = (struct ntfs_super_block *) volume_id_get_buffer(id, off, 0x200);
++	if (ns == NULL)
++		return -1;
++
++	if (memcmp((char *)ns->oem_id, "NTFS", 4) != 0)
++		return -1;
++
++	volume_id_set_uuid(id, ns->volume_serial, 0, UUID_64BIT_LE);
++
++	sector_size = le16_to_cpu(ns->bytes_per_sector);
++	if (sector_size < 0x200)
++		return -1;
++
++	cluster_size = ns->sectors_per_cluster * sector_size;
++	mft_cluster = le64_to_cpu(ns->mft_cluster_location);
++	mft_off = mft_cluster * cluster_size;
++
++	if (ns->cluster_per_mft_record < 0)
++		/* size = -log2(mft_record_size); normally 1024 Bytes */
++		mft_record_size = 1 << -ns->cluster_per_mft_record;
++	else
++		mft_record_size = ns->cluster_per_mft_record * cluster_size;
++
++	dbg("sectorsize  0x%x", sector_size);
++	dbg("clustersize 0x%x", cluster_size);
++	dbg("mftcluster  %llu", (unsigned long long) mft_cluster);
++	dbg("mftoffset  0x%llx", (unsigned long long) mft_off);
++	dbg("cluster per mft_record  %i", ns->cluster_per_mft_record);
++	dbg("mft record size  %i", mft_record_size);
++
++	buf = volume_id_get_buffer(id, off + mft_off + (MFT_RECORD_VOLUME * mft_record_size),
++			 mft_record_size);
++	if (buf == NULL)
++		return -1;
++
++	mftr = (struct master_file_table_record*) buf;
++	dbg("mftr->magic '%c%c%c%c'", mftr->magic[0], mftr->magic[1], mftr->magic[2], mftr->magic[3]);
++	if (memcmp((char *)mftr->magic, "FILE", 4) != 0)
++		return -1;
++
++	attr_off = le16_to_cpu(mftr->attrs_offset);
++	dbg("file $Volume's attributes are at offset %i", attr_off);
++
++	while (1) {
++		attr = (struct file_attribute*) &buf[attr_off];
++		attr_type = le32_to_cpu(attr->type);
++		attr_len = le16_to_cpu(attr->len);
++		val_off = le16_to_cpu(attr->value_offset);
++		val_len = le32_to_cpu(attr->value_len);
++		attr_off += attr_len;
++
++		if (attr_len == 0)
++			break;
++
++		if (attr_off >= mft_record_size)
++			break;
++
++		if (attr_type == MFT_RECORD_ATTR_END)
++			break;
++
++		dbg("found attribute type 0x%x, len %i, at offset %i",
++		    attr_type, attr_len, attr_off);
++
++		if (attr_type == MFT_RECORD_ATTR_VOLUME_INFO) {
++			dbg("found info, len %i", val_len);
++			info = (struct volume_info*) (((uint8_t *) attr) + val_off);
++			sprintf(id->type_version, "%u.%u", info->major_ver, info->minor_ver);
++		}
++
++		if (attr_type == MFT_RECORD_ATTR_VOLUME_NAME) {
++			dbg("found label, len %i", val_len);
++			if (val_len > VOLUME_ID_LABEL_SIZE)
++				val_len = VOLUME_ID_LABEL_SIZE;
++
++			val = ((uint8_t *) attr) + val_off;
++			volume_id_set_label_raw(id, val, val_len);
++			volume_id_set_label_unicode16(id, val, LE, val_len);
++		}
++	}
++
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "ntfs";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/nvidia_raid.c'
+--- grub-0.97.orig/libvolume_id/nvidia_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/nvidia_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,59 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct nvidia_meta {
++	uint8_t		vendor[8];
++	uint32_t	size;
++	uint32_t	chksum;
++	uint16_t	version;
++} PACKED;
++
++#define NVIDIA_SIGNATURE		"NVIDIA"
++
++int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	uint64_t meta_off;
++	struct nvidia_meta *nv;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x10000)
++		return -1;
++
++	meta_off = ((size / 0x200)-2) * 0x200;
++	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	nv = (struct nvidia_meta *) buf;
++	if (memcmp((char *)nv->vendor, NVIDIA_SIGNATURE, sizeof(NVIDIA_SIGNATURE)-1) != 0)
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	sprintf(id->type_version, "%u", le16_to_cpu(nv->version));
++	id->type = "nvidia_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/ocfs.c'
+--- grub-0.97.orig/libvolume_id/ocfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/ocfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,186 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Andre Masella <andre@masella.no-ip.org>
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct ocfs1_super_block_header {
++	uint32_t	minor_version;
++	uint32_t	major_version;
++	uint8_t		signature[128];
++	uint8_t		mount_point[128];
++	uint64_t	serial_num;
++	uint64_t	device_size;
++	uint64_t	start_off;
++	uint64_t	bitmap_off;
++	uint64_t	publ_off;
++	uint64_t	vote_off;
++	uint64_t	root_bitmap_off;
++	uint64_t	data_start_off;
++	uint64_t	root_bitmap_size;
++	uint64_t	root_off;
++	uint64_t	root_size;
++	uint64_t	cluster_size;
++	uint64_t	num_nodes;
++	uint64_t	num_clusters;
++	uint64_t	dir_node_size;
++	uint64_t	file_node_size;
++	uint64_t	internal_off;
++	uint64_t	node_cfg_off;
++	uint64_t	node_cfg_size;
++	uint64_t	new_cfg_off;
++	uint32_t	prot_bits;
++	int32_t		excl_mount;
++} PACKED;
++
++struct ocfs1_super_block_label {
++	struct ocfs1_disk_lock {
++		uint32_t	curr_master;
++		uint8_t		file_lock;
++		uint8_t		compat_pad[3];
++		uint64_t	last_write_time;
++		uint64_t	last_read_time;
++		uint32_t	writer_node_num;
++		uint32_t	reader_node_num;
++		uint64_t	oin_node_map;
++		uint64_t	dlock_seq_num;
++	} PACKED disk_lock;
++	uint8_t		label[64];
++	uint16_t	label_len;
++	uint8_t		vol_id[16];
++	uint16_t	vol_id_len;
++	uint8_t		cluster_name[64];
++	uint16_t	cluster_name_len;
++} PACKED;
++
++struct ocfs2_super_block {
++	uint8_t		i_signature[8];
++	uint32_t	i_generation;
++	int16_t		i_suballoc_slot;
++	uint16_t	i_suballoc_bit;
++	uint32_t	i_reserved0;
++	uint32_t	i_clusters;
++	uint32_t	i_uid;
++	uint32_t	i_gid;
++	uint64_t	i_size;
++	uint16_t	i_mode;
++	uint16_t	i_links_count;
++	uint32_t	i_flags;
++	uint64_t	i_atime;
++	uint64_t	i_ctime;
++	uint64_t	i_mtime;
++	uint64_t	i_dtime;
++	uint64_t	i_blkno;
++	uint64_t	i_last_eb_blk;
++	uint32_t	i_fs_generation;
++	uint32_t	i_atime_nsec;
++	uint32_t	i_ctime_nsec;
++	uint32_t	i_mtime_nsec;
++	uint64_t	i_reserved1[9];
++	uint64_t	i_pad1;
++	uint16_t	s_major_rev_level;
++	uint16_t	s_minor_rev_level;
++	uint16_t	s_mnt_count;
++	int16_t		s_max_mnt_count;
++	uint16_t	s_state;
++	uint16_t	s_errors;
++	uint32_t	s_checkinterval;
++	uint64_t	s_lastcheck;
++	uint32_t	s_creator_os;
++	uint32_t	s_feature_compat;
++	uint32_t	s_feature_incompat;
++	uint32_t	s_feature_ro_compat;
++	uint64_t	s_root_blkno;
++	uint64_t	s_system_dir_blkno;
++	uint32_t	s_blocksize_bits;
++	uint32_t	s_clustersize_bits;
++	uint16_t	s_max_slots;
++	uint16_t	s_reserved1;
++	uint32_t	s_reserved2;
++	uint64_t	s_first_cluster_group;
++	uint8_t		s_label[64];
++	uint8_t		s_uuid[16];
++} PACKED;
++
++int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	struct ocfs1_super_block_header *osh;
++	struct ocfs1_super_block_label *osl;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	osh = (struct ocfs1_super_block_header *) buf;
++	if (memcmp((char *)osh->signature, "OracleCFS", 9) != 0)
++		return -1;
++	sprintf(id->type_version, "%u.%u", osh->major_version, osh->minor_version);
++
++	dbg("found OracleCFS signature, now reading label");
++	buf = volume_id_get_buffer(id, off + 0x200, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	osl = (struct ocfs1_super_block_label *) buf;
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	if (osl->label_len <= 64) {
++		volume_id_set_label_raw(id, osl->label, 64);
++		volume_id_set_label_string(id, osl->label, 64);
++	}
++	if (osl->vol_id_len == 16)
++		volume_id_set_uuid(id, osl->vol_id, 0, UUID_DCE);
++	id->type = "ocfs";
++	return 0;
++}
++
++#define OCFS2_MAX_BLOCKSIZE		0x1000
++#define OCFS2_SUPER_BLOCK_BLKNO		2
++
++int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	struct ocfs2_super_block *os;
++	size_t blksize;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	for (blksize = 0x200; blksize <= OCFS2_MAX_BLOCKSIZE; blksize <<= 1) {
++		buf = volume_id_get_buffer(id, off + OCFS2_SUPER_BLOCK_BLKNO * blksize, 0x200);
++		if (buf == NULL)
++			return -1;
++
++		os = (struct ocfs2_super_block *) buf;
++		if (memcmp((char *)os->i_signature, "OCFSV2", 6) != 0)
++			continue;
++
++		volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++		volume_id_set_label_raw(id, os->s_label, 64);
++		volume_id_set_label_string(id, os->s_label, 64);
++		volume_id_set_uuid(id, os->s_uuid, 0, UUID_DCE);
++		sprintf(id->type_version, "%u.%u", os->s_major_rev_level, os->s_minor_rev_level);
++		id->type = "ocfs2";
++		return 0;
++	}
++	return -1;
++}
+
+=== added file 'libvolume_id/promise_raid.c'
+--- grub-0.97.orig/libvolume_id/promise_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/promise_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,65 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct promise_meta {
++	uint8_t	sig[24];
++} PACKED;
++
++#define PDC_CONFIG_OFF		0x1200
++#define PDC_SIGNATURE		"Promise Technology, Inc."
++
++int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	struct promise_meta *pdc;
++	unsigned int i;
++	static unsigned int sectors[] = {
++		63, 255, 256, 16, 399, 0
++	};
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x40000)
++		return -1;
++
++	for (i = 0; sectors[i] != 0; i++) {
++		uint64_t meta_off;
++
++		meta_off = ((size / 0x200) - sectors[i]) * 0x200;
++		buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++		if (buf == NULL)
++			return -1;
++
++		pdc = (struct promise_meta *) buf;
++		if (memcmp((char *)pdc->sig, PDC_SIGNATURE, sizeof(PDC_SIGNATURE)-1) == 0)
++			goto found;
++	}
++	return -1;
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	id->type = "promise_fasttrack_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/reiserfs.c'
+--- grub-0.97.orig/libvolume_id/reiserfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/reiserfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,113 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Copyright (C) 2005 Tobias Klauser <tklauser@access.unizh.ch>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct reiserfs_super_block {
++	uint32_t	blocks_count;
++	uint32_t	free_blocks;
++	uint32_t	root_block;
++	uint32_t	journal_block;
++	uint32_t	journal_dev;
++	uint32_t	orig_journal_size;
++	uint32_t	dummy2[5];
++	uint16_t	blocksize;
++	uint16_t	dummy3[3];
++	uint8_t		magic[12];
++	uint32_t	dummy4[5];
++	uint8_t		uuid[16];
++	uint8_t		label[16];
++} PACKED;
++
++struct reiser4_super_block {
++	uint8_t		magic[16];
++	uint16_t	dummy[2];
++	uint8_t		uuid[16];
++	uint8_t		label[16];
++	uint64_t	dummy2;
++} PACKED;
++
++#define REISERFS1_SUPERBLOCK_OFFSET		0x2000
++#define REISERFS_SUPERBLOCK_OFFSET		0x10000
++
++int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct reiserfs_super_block *rs;
++	struct reiser4_super_block *rs4;
++	uint8_t	 *buf;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	buf = volume_id_get_buffer(id, off + REISERFS_SUPERBLOCK_OFFSET, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	rs = (struct reiserfs_super_block *) buf;
++	if (memcmp((char *)rs->magic, "ReIsErFs", 8) == 0) {
++		strcpy(id->type_version, "3.5");
++		id->type = "reiserfs";
++		goto found;
++	}
++	if (memcmp((char *)rs->magic, "ReIsEr2Fs", 9) == 0) {
++		strcpy(id->type_version, "3.6");
++		id->type = "reiserfs";
++		goto found_label;
++	}
++	if (memcmp((char *)rs->magic, "ReIsEr3Fs", 9) == 0) {
++		strcpy(id->type_version, "JR");
++		id->type = "reiserfs";
++		goto found_label;
++	}
++
++	rs4 = (struct reiser4_super_block *) buf;
++	if (memcmp((char *)rs4->magic, "ReIsEr4", 7) == 0) {
++		strcpy(id->type_version, "4");
++		volume_id_set_label_raw(id, rs4->label, 16);
++		volume_id_set_label_string(id, rs4->label, 16);
++		volume_id_set_uuid(id, rs4->uuid, 0, UUID_DCE);
++		id->type = "reiser4";
++		goto found;
++	}
++
++	buf = volume_id_get_buffer(id, off + REISERFS1_SUPERBLOCK_OFFSET, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	rs = (struct reiserfs_super_block *) buf;
++	if (memcmp((char *)rs->magic, "ReIsErFs", 8) == 0) {
++		strcpy(id->type_version, "3.5");
++		id->type = "reiserfs";
++		goto found;
++	}
++
++	return -1;
++
++found_label:
++	volume_id_set_label_raw(id, rs->label, 16);
++	volume_id_set_label_string(id, rs->label, 16);
++	volume_id_set_uuid(id, rs->uuid, 0, UUID_DCE);
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++
++	return 0;
++}
+
+=== added file 'libvolume_id/romfs.c'
+--- grub-0.97.orig/libvolume_id/romfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/romfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,55 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct romfs_super {
++	uint8_t magic[8];
++	uint32_t size;
++	uint32_t checksum;
++	uint8_t name[0];
++} PACKED;
++
++int volume_id_probe_romfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct romfs_super *rfs;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	rfs = (struct romfs_super *) volume_id_get_buffer(id, off, 0x200);
++	if (rfs == NULL)
++		return -1;
++
++	if (memcmp((char *)rfs->magic, "-rom1fs-", 4) == 0) {
++		size_t len = strlen((char *)rfs->name);
++
++		if (len) {
++			volume_id_set_label_raw(id, rfs->name, len);
++			volume_id_set_label_string(id, rfs->name, len);
++		}
++
++		volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++		id->type = "romfs";
++		return 0;
++	}
++
++	return -1;
++}
+
+=== added file 'libvolume_id/silicon_raid.c'
+--- grub-0.97.orig/libvolume_id/silicon_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/silicon_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,71 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct silicon_meta {
++	uint8_t		unknown0[0x2E];
++	uint8_t		ascii_version[0x36 - 0x2E];
++	uint8_t		diskname[0x56 - 0x36];
++	uint8_t		unknown1[0x60 - 0x56];
++	uint32_t	magic;
++	uint32_t	unknown1a[0x6C - 0x64];
++	uint32_t	array_sectors_low;
++	uint32_t	array_sectors_high;
++	uint8_t		unknown2[0x78 - 0x74];
++	uint32_t	thisdisk_sectors;
++	uint8_t		unknown3[0x100 - 0x7C];
++	uint8_t		unknown4[0x104 - 0x100];
++	uint16_t	product_id;
++	uint16_t	vendor_id;
++	uint16_t	minor_ver;
++	uint16_t	major_ver;
++} PACKED;
++
++#define SILICON_MAGIC		0x2F000000
++
++int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	uint64_t meta_off;
++	struct silicon_meta *sil;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x10000)
++		return -1;
++
++	meta_off = ((size / 0x200)-1) * 0x200;
++	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	sil = (struct silicon_meta *) buf;
++	if (le32_to_cpu(sil->magic) != SILICON_MAGIC)
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	sprintf(id->type_version, "%u.%u", le16_to_cpu(sil->major_ver), le16_to_cpu(sil->minor_ver));
++	id->type = "silicon_medley_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/squashfs.c'
+--- grub-0.97.orig/libvolume_id/squashfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/squashfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,63 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2006 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++#define SQUASHFS_MAGIC		0x73717368
++
++struct squashfs_super {
++	uint32_t	s_magic;
++	uint32_t	inodes;
++	uint32_t	bytes_used_2;
++	uint32_t	uid_start_2;
++	uint32_t	guid_start_2;
++	uint32_t	inode_table_start_2;
++	uint32_t	directory_table_start_2;
++	uint16_t	s_major;
++	uint16_t	s_minor;
++} PACKED;
++
++int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct squashfs_super *sqs;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	sqs = (struct squashfs_super *) volume_id_get_buffer(id, off, 0x200);
++	if (sqs == NULL)
++		return -1;
++
++	if (sqs->s_magic == SQUASHFS_MAGIC) {
++		sprintf(id->type_version, "%u.%u", sqs->s_major, sqs->s_minor);
++		goto found;
++	}
++	if (sqs->s_magic == bswap_32(SQUASHFS_MAGIC)) {
++		sprintf(id->type_version, "%u.%u", bswap_16(sqs->s_major), bswap_16(sqs->s_minor));
++		goto found;
++	}
++
++	return -1;
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "squashfs";
++	return 0;
++}
+
+=== added file 'libvolume_id/strfuncs.h'
+--- grub-0.97.orig/libvolume_id/strfuncs.h	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/strfuncs.h	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,5 @@
++
++#include <stdlib.h>
++
++size_t strnlen(const char *s, size_t limit);
++char  *strchr (const char *s, int c);
+
+=== added file 'libvolume_id/sysv.c'
+--- grub-0.97.orig/libvolume_id/sysv.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/sysv.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,128 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++#define SYSV_NICINOD			100
++#define SYSV_NICFREE			50
++
++struct sysv_super
++{
++	uint16_t	s_isize;
++	uint16_t	s_pad0;
++	uint32_t	s_fsize;
++	uint16_t	s_nfree;
++	uint16_t	s_pad1;
++	uint32_t	s_free[SYSV_NICFREE];
++	uint16_t	s_ninode;
++	uint16_t	s_pad2;
++	uint16_t	s_inode[SYSV_NICINOD];
++	uint8_t		s_flock;
++	uint8_t		s_ilock;
++	uint8_t		s_fmod;
++	uint8_t		s_ronly;
++	uint32_t	s_time;
++	uint16_t	s_dinfo[4];
++	uint32_t	s_tfree;
++	uint16_t	s_tinode;
++	uint16_t	s_pad3;
++	uint8_t		s_fname[6];
++	uint8_t		s_fpack[6];
++	uint32_t	s_fill[12];
++	uint32_t	s_state;
++	uint32_t	s_magic;
++	uint32_t	s_type;
++} PACKED;
++
++#define XENIX_NICINOD				100
++#define XENIX_NICFREE				100
++
++struct xenix_super {
++	uint16_t	s_isize;
++	uint32_t	s_fsize;
++	uint16_t	s_nfree;
++	uint32_t	s_free[XENIX_NICFREE];
++	uint16_t	s_ninode;
++	uint16_t	s_inode[XENIX_NICINOD];
++	uint8_t		s_flock;
++	uint8_t		s_ilock;
++	uint8_t		s_fmod;
++	uint8_t		s_ronly;
++	uint32_t	s_time;
++	uint32_t	s_tfree;
++	uint16_t	s_tinode;
++	uint16_t	s_dinfo[4];
++	uint8_t		s_fname[6];
++	uint8_t		s_fpack[6];
++	uint8_t		s_clean;
++	uint8_t		s_fill[371];
++	uint32_t	s_magic;
++	uint32_t	s_type;
++} PACKED;
++
++#define SYSV_SUPERBLOCK_BLOCK			0x01
++#define SYSV_MAGIC				0xfd187e20
++#define XENIX_SUPERBLOCK_BLOCK			0x18
++#define XENIX_MAGIC				0x2b5544
++#define SYSV_MAX_BLOCKSIZE			0x800
++
++int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct sysv_super *vs;
++	struct xenix_super *xs;
++	unsigned int boff;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
++		vs = (struct sysv_super *)
++			volume_id_get_buffer(id, off + (boff * SYSV_SUPERBLOCK_BLOCK), 0x200);
++		if (vs == NULL)
++			return -1;
++
++		if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) {
++			volume_id_set_label_raw(id, vs->s_fname, 6);
++			volume_id_set_label_string(id, vs->s_fname, 6);
++			id->type = "sysv";
++			goto found;
++		}
++	}
++
++	for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
++		xs = (struct xenix_super *)
++			volume_id_get_buffer(id, off + (boff + XENIX_SUPERBLOCK_BLOCK), 0x200);
++		if (xs == NULL)
++			return -1;
++
++		if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) {
++			volume_id_set_label_raw(id, xs->s_fname, 6);
++			volume_id_set_label_string(id, xs->s_fname, 6);
++			id->type = "xenix";
++			goto found;
++		}
++	}
++
++	return -1;
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	return 0;
++}
+
+=== added file 'libvolume_id/udf.c'
+--- grub-0.97.orig/libvolume_id/udf.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/udf.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,173 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct volume_descriptor {
++	struct descriptor_tag {
++		uint16_t	id;
++		uint16_t	version;
++		uint8_t		checksum;
++		uint8_t		reserved;
++		uint16_t	serial;
++		uint16_t	crc;
++		uint16_t	crc_len;
++		uint32_t	location;
++	} PACKED tag;
++	union {
++		struct anchor_descriptor {
++			uint32_t	length;
++			uint32_t	location;
++		} PACKED anchor;
++		struct primary_descriptor {
++			uint32_t	seq_num;
++			uint32_t	desc_num;
++			struct dstring {
++				uint8_t	clen;
++				uint8_t	c[31];
++			} PACKED ident;
++		} PACKED primary;
++	} PACKED type;
++} PACKED;
++
++struct volume_structure_descriptor {
++	uint8_t		type;
++	uint8_t		id[5];
++	uint8_t		version;
++} PACKED;
++
++#define UDF_VSD_OFFSET			0x8000
++
++int volume_id_probe_udf(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct volume_descriptor *vd;
++	struct volume_structure_descriptor *vsd;
++	unsigned int bs;
++	unsigned int b;
++	unsigned int type;
++	unsigned int count;
++	unsigned int loc;
++	unsigned int clen;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET, 0x200);
++	if (vsd == NULL)
++		return -1;
++
++	if (memcmp((char *)vsd->id, "NSR02", 5) == 0)
++		goto blocksize;
++	if (memcmp((char *)vsd->id, "NSR03", 5) == 0)
++		goto blocksize;
++	if (memcmp((char *)vsd->id, "BEA01", 5) == 0)
++		goto blocksize;
++	if (memcmp((char *)vsd->id, "BOOT2", 5) == 0)
++		goto blocksize;
++	if (memcmp((char *)vsd->id, "CD001", 5) == 0)
++		goto blocksize;
++	if (memcmp((char *)vsd->id, "CDW02", 5) == 0)
++		goto blocksize;
++	if (memcmp((char *)vsd->id, "TEA03", 5) == 0)
++		goto blocksize;
++	return -1;
++
++blocksize:
++	/* search the next VSD to get the logical block size of the volume */
++	for (bs = 0x800; bs < 0x8000; bs += 0x800) {
++		vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + bs, 0x800);
++		if (vsd == NULL)
++			return -1;
++		dbg("test for blocksize: 0x%x", bs);
++		if (vsd->id[0] != '\0')
++			goto nsr;
++	}
++	return -1;
++
++nsr:
++	/* search the list of VSDs for a NSR descriptor */
++	for (b = 0; b < 64; b++) {
++		vsd = (struct volume_structure_descriptor *) volume_id_get_buffer(id, off + UDF_VSD_OFFSET + (b * bs), 0x800);
++		if (vsd == NULL)
++			return -1;
++
++		dbg("vsd: %c%c%c%c%c",
++		    vsd->id[0], vsd->id[1], vsd->id[2], vsd->id[3], vsd->id[4]);
++
++		if (vsd->id[0] == '\0')
++			return -1;
++		if (memcmp((char *)vsd->id, "NSR02", 5) == 0)
++			goto anchor;
++		if (memcmp((char *)vsd->id, "NSR03", 5) == 0)
++			goto anchor;
++	}
++	return -1;
++
++anchor:
++	/* read anchor volume descriptor */
++	vd = (struct volume_descriptor *) volume_id_get_buffer(id, off + (256 * bs), 0x200);
++	if (vd == NULL)
++		return -1;
++
++	type = le16_to_cpu(vd->tag.id);
++	if (type != 2) /* TAG_ID_AVDP */
++		goto found;
++
++	/* get desriptor list address and block count */
++	count = le32_to_cpu(vd->type.anchor.length) / bs;
++	loc = le32_to_cpu(vd->type.anchor.location);
++	dbg("0x%x descriptors starting at logical secor 0x%x", count, loc);
++
++	/* pick the primary descriptor from the list */
++	for (b = 0; b < count; b++) {
++		vd = (struct volume_descriptor *) volume_id_get_buffer(id, off + ((loc + b) * bs), 0x200);
++		if (vd == NULL)
++			return -1;
++
++		type = le16_to_cpu(vd->tag.id);
++		dbg("descriptor type %i", type);
++
++		/* check validity */
++		if (type == 0)
++			goto found;
++		if (le32_to_cpu(vd->tag.location) != loc + b)
++			goto found;
++
++		if (type == 1) /* TAG_ID_PVD */
++			goto pvd;
++	}
++	goto found;
++
++pvd:
++	volume_id_set_label_raw(id, &(vd->type.primary.ident.clen), 32);
++
++	clen = vd->type.primary.ident.clen;
++	dbg("label string charsize=%i bit", clen);
++	if (clen == 8)
++		volume_id_set_label_string(id, vd->type.primary.ident.c, 31);
++	else if (clen == 16)
++		volume_id_set_label_unicode16(id, vd->type.primary.ident.c, BE,31);
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "udf";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/ufs.c'
+--- grub-0.97.orig/libvolume_id/ufs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/ufs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,217 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct ufs_super_block {
++	uint32_t	fs_link;
++	uint32_t	fs_rlink;
++	uint32_t	fs_sblkno;
++	uint32_t	fs_cblkno;
++	uint32_t	fs_iblkno;
++	uint32_t	fs_dblkno;
++	uint32_t	fs_cgoffset;
++	uint32_t	fs_cgmask;
++	uint32_t	fs_time;
++	uint32_t	fs_size;
++	uint32_t	fs_dsize;
++	uint32_t	fs_ncg;	
++	uint32_t	fs_bsize;
++	uint32_t	fs_fsize;
++	uint32_t	fs_frag;
++	uint32_t	fs_minfree;
++	uint32_t	fs_rotdelay;
++	uint32_t	fs_rps;	
++	uint32_t	fs_bmask;
++	uint32_t	fs_fmask;
++	uint32_t	fs_bshift;
++	uint32_t	fs_fshift;
++	uint32_t	fs_maxcontig;
++	uint32_t	fs_maxbpg;
++	uint32_t	fs_fragshift;
++	uint32_t	fs_fsbtodb;
++	uint32_t	fs_sbsize;
++	uint32_t	fs_csmask;
++	uint32_t	fs_csshift;
++	uint32_t	fs_nindir;
++	uint32_t	fs_inopb;
++	uint32_t	fs_nspf;
++	uint32_t	fs_optim;
++	uint32_t	fs_npsect_state;
++	uint32_t	fs_interleave;
++	uint32_t	fs_trackskew;
++	uint32_t	fs_id[2];
++	uint32_t	fs_csaddr;
++	uint32_t	fs_cssize;
++	uint32_t	fs_cgsize;
++	uint32_t	fs_ntrak;
++	uint32_t	fs_nsect;
++	uint32_t	fs_spc;	
++	uint32_t	fs_ncyl;
++	uint32_t	fs_cpg;
++	uint32_t	fs_ipg;
++	uint32_t	fs_fpg;
++	struct ufs_csum {
++		uint32_t	cs_ndir;
++		uint32_t	cs_nbfree;
++		uint32_t	cs_nifree;
++		uint32_t	cs_nffree;
++	} PACKED fs_cstotal;
++	int8_t		fs_fmod;
++	int8_t		fs_clean;
++	int8_t		fs_ronly;
++	int8_t		fs_flags;
++	union {
++		struct {
++			int8_t	fs_fsmnt[512];
++			uint32_t	fs_cgrotor;
++			uint32_t	fs_csp[31];
++			uint32_t	fs_maxcluster;
++			uint32_t	fs_cpc;
++			uint16_t	fs_opostbl[16][8];
++		} PACKED fs_u1;
++		struct {
++			int8_t		fs_fsmnt[468];
++			uint8_t		fs_volname[32];
++			uint64_t	fs_swuid;
++			int32_t		fs_pad;
++			uint32_t	fs_cgrotor;
++			uint32_t	fs_ocsp[28];
++			uint32_t	fs_contigdirs;
++			uint32_t	fs_csp;	
++			uint32_t	fs_maxcluster;
++			uint32_t	fs_active;
++			int32_t		fs_old_cpc;
++			int32_t		fs_maxbsize;
++			int64_t		fs_sparecon64[17];
++			int64_t		fs_sblockloc;
++			struct ufs2_csum_total {
++				uint64_t	cs_ndir;
++				uint64_t	cs_nbfree;
++				uint64_t	cs_nifree;
++				uint64_t	cs_nffree;
++				uint64_t	cs_numclusters;
++				uint64_t	cs_spare[3];
++			} PACKED fs_cstotal;
++			struct ufs_timeval {
++				int32_t		tv_sec;
++				int32_t		tv_usec;
++			} PACKED fs_time;
++			int64_t		fs_size;
++			int64_t		fs_dsize;
++			uint64_t	fs_csaddr;
++			int64_t		fs_pendingblocks;
++			int32_t		fs_pendinginodes;
++		} PACKED fs_u2;
++	}  fs_u11;
++	union {
++		struct {
++			int32_t		fs_sparecon[53];
++			int32_t		fs_reclaim;
++			int32_t		fs_sparecon2[1];
++			int32_t		fs_state;
++			uint32_t	fs_qbmask[2];
++			uint32_t	fs_qfmask[2];
++		} PACKED fs_sun;
++		struct {
++			int32_t		fs_sparecon[53];
++			int32_t		fs_reclaim;
++			int32_t		fs_sparecon2[1];
++			uint32_t	fs_npsect;
++			uint32_t	fs_qbmask[2];
++			uint32_t	fs_qfmask[2];
++		} PACKED fs_sunx86;
++		struct {
++			int32_t		fs_sparecon[50];
++			int32_t		fs_contigsumsize;
++			int32_t		fs_maxsymlinklen;
++			int32_t		fs_inodefmt;
++			uint32_t	fs_maxfilesize[2];
++			uint32_t	fs_qbmask[2];
++			uint32_t	fs_qfmask[2];
++			int32_t		fs_state;
++		} PACKED fs_44;
++	} fs_u2;
++	int32_t		fs_postblformat;
++	int32_t		fs_nrpos;
++	int32_t		fs_postbloff;
++	int32_t		fs_rotbloff;
++	uint32_t	fs_magic;
++	uint8_t		fs_space[1];
++} PACKED;
++
++#define UFS_MAGIC			0x00011954
++#define UFS2_MAGIC			0x19540119
++#define UFS_MAGIC_FEA			0x00195612
++#define UFS_MAGIC_LFN			0x00095014
++
++int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	uint32_t magic;
++	int i;
++	struct ufs_super_block *ufs;
++	int offsets[] = {0, 8, 64, 256, -1};
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	for (i = 0; offsets[i] >= 0; i++) {	
++		ufs = (struct ufs_super_block *) volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800);
++		if (ufs == NULL)
++			return -1;
++
++		dbg("offset 0x%x", offsets[i] * 0x400);
++		magic = be32_to_cpu(ufs->fs_magic);
++		if ((magic == UFS_MAGIC) ||
++		    (magic == UFS2_MAGIC) ||
++		    (magic == UFS_MAGIC_FEA) ||
++		    (magic == UFS_MAGIC_LFN)) {
++			dbg("magic 0x%08x(be)", magic);
++			goto found;
++		}
++		magic = le32_to_cpu(ufs->fs_magic);
++		if ((magic == UFS_MAGIC) ||
++		    (magic == UFS2_MAGIC) ||
++		    (magic == UFS_MAGIC_FEA) ||
++		    (magic == UFS_MAGIC_LFN)) {
++			dbg("magic 0x%08x(le)", magic);
++			goto found;
++		}
++	}
++	return -1;
++
++found:
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "ufs";
++	switch (magic) {
++	case UFS_MAGIC:
++		strcpy(id->type_version, "1");
++		break;
++	case UFS2_MAGIC:
++		strcpy(id->type_version, "2");
++		volume_id_set_label_raw(id, ufs->fs_u11.fs_u2.fs_volname, 32);
++		volume_id_set_label_string(id, ufs->fs_u11.fs_u2.fs_volname, 32);
++		break;
++	default:
++		break;
++	}
++
++	return 0;
++}
+
+=== added file 'libvolume_id/util.c'
+--- grub-0.97.orig/libvolume_id/util.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/util.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,472 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include <stdlib.h>
++
++#include "strfuncs.h"
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++static char hex[] = "0123456789abcdef";
++
++#define hexhi(val)   hex[val >> 4]
++#define hexlo(val)   hex[val & 0xf]
++
++/* count of characters used to encode one unicode char */
++static int utf8_encoded_expected_len(const char *str)
++{
++	unsigned char c = (unsigned char)str[0];
++
++	if (c < 0x80)
++		return 1;
++	if ((c & 0xe0) == 0xc0)
++		return 2;
++	if ((c & 0xf0) == 0xe0)
++		return 3;
++	if ((c & 0xf8) == 0xf0)
++		return 4;
++	if ((c & 0xfc) == 0xf8)
++		return 5;
++	if ((c & 0xfe) == 0xfc)
++		return 6;
++	return 0;
++}
++
++/* decode one unicode char */
++static int utf8_encoded_to_unichar(const char *str)
++{
++	int unichar;
++	int len;
++	int i;
++
++	len = utf8_encoded_expected_len(str);
++	switch (len) {
++	case 1:
++		return (int)str[0];
++	case 2:
++		unichar = str[0] & 0x1f;
++		break;
++	case 3:
++		unichar = (int)str[0] & 0x0f;
++		break;
++	case 4:
++		unichar = (int)str[0] & 0x07;
++		break;
++	case 5:
++		unichar = (int)str[0] & 0x03;
++		break;
++	case 6:
++		unichar = (int)str[0] & 0x01;
++		break;
++	default:
++		return -1;
++	}
++
++	for (i = 1; i < len; i++) {
++		if (((int)str[i] & 0xc0) != 0x80)
++			return -1;
++		unichar <<= 6;
++		unichar |= (int)str[i] & 0x3f;
++	}
++
++	return unichar;
++}
++
++/* expected size used to encode one unicode char */
++static int utf8_unichar_to_encoded_len(int unichar)
++{
++	if (unichar < 0x80)
++		return 1;
++	if (unichar < 0x800)
++		return 2;
++	if (unichar < 0x10000)
++		return 3;
++	if (unichar < 0x200000)
++		return 4;
++	if (unichar < 0x4000000)
++		return 5;
++	return 6;
++}
++
++/* check if unicode char has a valid numeric range */
++static int utf8_unichar_valid_range(int unichar)
++{
++	if (unichar > 0x10ffff)
++		return 0;
++	if ((unichar & 0xfffff800) == 0xd800)
++		return 0;
++	if ((unichar > 0xfdcf) && (unichar < 0xfdf0))
++		return 0;
++	if ((unichar & 0xffff) == 0xffff)
++		return 0;
++	return 1;
++}
++
++/* validate one encoded unicode char and return its length */
++int volume_id_utf8_encoded_valid_unichar(const char *str)
++{
++	int len;
++	int unichar;
++	int i;
++
++	len = utf8_encoded_expected_len(str);
++	if (len == 0)
++		return -1;
++
++	/* ascii is valid */
++	if (len == 1)
++		return 1;
++
++	/* check if expected encoded chars are available */
++	for (i = 0; i < len; i++)
++		if ((str[i] & 0x80) != 0x80)
++			return -1;
++
++	unichar = utf8_encoded_to_unichar(str);
++
++	/* check if encoded length matches encoded value */
++	if (utf8_unichar_to_encoded_len(unichar) != len)
++		return -1;
++
++	/* check if value has valid range */
++	if (!utf8_unichar_valid_range(unichar))
++		return -1;
++
++	return len;
++}
++
++size_t volume_id_set_unicode16(uint8_t *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count)
++{
++	size_t i, j;
++	uint16_t c;
++
++	j = 0;
++	for (i = 0; i + 2 <= count; i += 2) {
++		if (endianess == LE)
++			c = (buf[i+1] << 8) | buf[i];
++		else
++			c = (buf[i] << 8) | buf[i+1];
++		if (c == 0) {
++			str[j] = '\0';
++			break;
++		} else if (c < 0x80) {
++			if (j+1 >= len)
++				break;
++			str[j++] = (uint8_t) c;
++		} else if (c < 0x800) {
++			if (j+2 >= len)
++				break;
++			str[j++] = (uint8_t) (0xc0 | (c >> 6));
++			str[j++] = (uint8_t) (0x80 | (c & 0x3f));
++		} else {
++			if (j+3 >= len)
++				break;
++			str[j++] = (uint8_t) (0xe0 | (c >> 12));
++			str[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f));
++			str[j++] = (uint8_t) (0x80 | (c & 0x3f));
++		}
++	}
++	str[j] = '\0';
++	return j;
++}
++
++static char *usage_to_string(enum volume_id_usage usage_id)
++{
++	switch (usage_id) {
++	case VOLUME_ID_FILESYSTEM:
++		return "filesystem";
++	case VOLUME_ID_OTHER:
++		return "other";
++	case VOLUME_ID_RAID:
++		return "raid";
++	case VOLUME_ID_DISKLABEL:
++		return "disklabel";
++	case VOLUME_ID_CRYPTO:
++		return "crypto";
++	case VOLUME_ID_UNPROBED:
++		return "unprobed";
++	case VOLUME_ID_UNUSED:
++		return "unused";
++	}
++	return NULL;
++}
++
++void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id)
++{
++	id->usage_id = usage_id;
++	id->usage = usage_to_string(usage_id);
++}
++
++void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count)
++{
++	if (count > sizeof(id->label))
++		count = sizeof(id->label);
++
++	memcpy(id->label_raw, buf, count);
++	id->label_raw_len = count;
++}
++
++void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count)
++{
++	size_t i;
++
++	if (count >= sizeof(id->label))
++		count = sizeof(id->label)-1;
++
++	memcpy(id->label, buf, count);
++	id->label[count] = '\0';
++
++	/* remove trailing whitespace */
++	i = strnlen(id->label, count);
++	while (i--) {
++		if (!isspace(id->label[i]))
++			break;
++	}
++	id->label[i+1] = '\0';
++}
++
++void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count)
++{
++	if (count >= sizeof(id->label))
++		count = sizeof(id->label)-1;
++
++	 volume_id_set_unicode16((uint8_t *)id->label, sizeof(id->label), buf, endianess, count);
++}
++
++void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format)
++{
++	unsigned int i;
++	unsigned int count = 0;
++	char *uuid;
++
++	if (len > sizeof(id->uuid_raw))
++		len = sizeof(id->uuid_raw);
++
++	switch(format) {
++	case UUID_STRING:
++		count = len;
++		break;
++	case UUID_HEX_STRING:
++		count = len;
++		break;
++	case UUID_DOS:
++		count = 4;
++		break;
++	case UUID_64BIT_LE:
++	case UUID_64BIT_BE:
++		count = 8;
++		break;
++	case UUID_DCE:
++		count = 16;
++		break;
++	case UUID_FOURINT:
++		count = 35;
++		break;
++	}
++	memcpy(id->uuid_raw, buf, count);
++	id->uuid_raw_len = count;
++
++	/* if set, create string in the same format, the native platform uses */
++	for (i = 0; i < count; i++)
++		if (buf[i] != 0)
++			goto set;
++	return;
++
++set:
++	uuid = id->uuid;
++	switch(format) {
++	case UUID_DOS:
++		*uuid++ = hexhi(buf[3]);
++		*uuid++ = hexlo(buf[3]);
++		*uuid++ = hexhi(buf[2]);
++		*uuid++ = hexlo(buf[2]);
++		*uuid++ = '-';
++		*uuid++ = hexhi(buf[1]);
++		*uuid++ = hexlo(buf[1]);
++		*uuid++ = hexhi(buf[0]);
++		*uuid++ = hexlo(buf[0]);
++		*uuid = '\0';
++		break;
++	case UUID_64BIT_LE:
++		*uuid++ = hexhi(buf[7]);
++		*uuid++ = hexlo(buf[7]);
++		*uuid++ = hexhi(buf[6]);
++		*uuid++ = hexlo(buf[6]);
++		*uuid++ = hexhi(buf[5]);
++		*uuid++ = hexlo(buf[5]);
++		*uuid++ = hexhi(buf[4]);
++		*uuid++ = hexlo(buf[4]);
++		*uuid++ = hexhi(buf[3]);
++		*uuid++ = hexlo(buf[3]);
++		*uuid++ = hexhi(buf[2]);
++		*uuid++ = hexlo(buf[2]);
++		*uuid++ = hexhi(buf[1]);
++		*uuid++ = hexlo(buf[1]);
++		*uuid++ = hexhi(buf[0]);
++		*uuid++ = hexlo(buf[0]);
++		*uuid = '\0';
++		break;
++	case UUID_64BIT_BE:
++		*uuid++ = hexhi(buf[0]);
++		*uuid++ = hexlo(buf[0]);
++		*uuid++ = hexhi(buf[1]);
++		*uuid++ = hexlo(buf[1]);
++		*uuid++ = hexhi(buf[2]);
++		*uuid++ = hexlo(buf[2]);
++		*uuid++ = hexhi(buf[3]);
++		*uuid++ = hexlo(buf[3]);
++		*uuid++ = hexhi(buf[4]);
++		*uuid++ = hexlo(buf[4]);
++		*uuid++ = hexhi(buf[5]);
++		*uuid++ = hexlo(buf[5]);
++		*uuid++ = hexhi(buf[6]);
++		*uuid++ = hexlo(buf[6]);
++		*uuid++ = hexhi(buf[7]);
++		*uuid++ = hexlo(buf[7]);
++		*uuid = '\0';
++		break;
++	case UUID_DCE:
++		*uuid++ = hexhi(buf[0]);
++		*uuid++ = hexlo(buf[0]);
++		*uuid++ = hexhi(buf[1]);
++		*uuid++ = hexlo(buf[1]);
++		*uuid++ = hexhi(buf[2]);
++		*uuid++ = hexlo(buf[2]);
++		*uuid++ = hexhi(buf[3]);
++		*uuid++ = hexlo(buf[3]);
++		*uuid++ = '-';
++		*uuid++ = hexhi(buf[4]);
++		*uuid++ = hexlo(buf[4]);
++		*uuid++ = hexhi(buf[5]);
++		*uuid++ = hexlo(buf[5]);
++		*uuid++ = '-';
++		*uuid++ = hexhi(buf[6]);
++		*uuid++ = hexlo(buf[6]);
++		*uuid++ = hexhi(buf[7]);
++		*uuid++ = hexlo(buf[7]);
++		*uuid++ = '-';
++		*uuid++ = hexhi(buf[8]);
++		*uuid++ = hexlo(buf[8]);
++		*uuid++ = hexhi(buf[9]);
++		*uuid++ = hexlo(buf[9]);
++		*uuid++ = '-';
++		*uuid++ = hexhi(buf[10]);
++		*uuid++ = hexlo(buf[10]);
++		*uuid++ = hexhi(buf[11]);
++		*uuid++ = hexlo(buf[11]);
++		*uuid++ = hexhi(buf[12]);
++		*uuid++ = hexlo(buf[12]);
++		*uuid++ = hexhi(buf[13]);
++		*uuid++ = hexlo(buf[13]);
++		*uuid++ = hexhi(buf[14]);
++		*uuid++ = hexlo(buf[14]);
++		*uuid++ = hexhi(buf[15]);
++		*uuid++ = hexlo(buf[15]);
++		*uuid = '\0';
++		break;
++	case UUID_HEX_STRING:
++		/* translate A..F to a..f */
++		memcpy(id->uuid, buf, count);
++		for (i = 0; i < count; i++)
++			if (id->uuid[i] >= 'A' && id->uuid[i] <= 'F')
++				id->uuid[i] = (id->uuid[i] - 'A') + 'a';
++		id->uuid[count] = '\0';
++		break;
++	case UUID_STRING:
++		memcpy(id->uuid, buf, count);
++		id->uuid[count] = '\0';
++		break;
++	case UUID_FOURINT:
++		*uuid++ = hexhi(buf[0]);
++		*uuid++ = hexlo(buf[0]);
++		*uuid++ = hexhi(buf[1]);
++		*uuid++ = hexlo(buf[1]);
++		*uuid++ = hexhi(buf[2]);
++		*uuid++ = hexlo(buf[2]);
++		*uuid++ = hexhi(buf[3]);
++		*uuid++ = hexlo(buf[3]);
++		*uuid++ = ':';
++		*uuid++ = hexhi(buf[4]);
++		*uuid++ = hexlo(buf[4]);
++		*uuid++ = hexhi(buf[5]);
++		*uuid++ = hexlo(buf[5]);
++		*uuid++ = hexhi(buf[6]);
++		*uuid++ = hexlo(buf[6]);
++		*uuid++ = hexhi(buf[7]);
++		*uuid++ = hexlo(buf[7]);
++		*uuid++ = ':';
++		*uuid++ = hexhi(buf[8]);
++		*uuid++ = hexlo(buf[8]);
++		*uuid++ = hexhi(buf[9]);
++		*uuid++ = hexlo(buf[9]);
++		*uuid++ = hexhi(buf[10]);
++		*uuid++ = hexlo(buf[10]);
++		*uuid++ = hexhi(buf[11]);
++		*uuid++ = hexlo(buf[11]);
++		*uuid++ = ':';
++		*uuid++ = hexhi(buf[12]);
++		*uuid++ = hexlo(buf[12]);
++		*uuid++ = hexhi(buf[13]);
++		*uuid++ = hexlo(buf[13]);
++		*uuid++ = hexhi(buf[14]);
++		*uuid++ = hexlo(buf[14]);
++		*uuid++ = hexhi(buf[15]);
++		*uuid++ = hexlo(buf[15]);
++		*uuid = '\0';
++		break;
++	default:
++		*uuid = '\0';
++		break;
++	}
++}
++
++uint8_t *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len)
++{
++	info("get buffer off 0x%llx(%llu), len 0x%zx", (unsigned long long) off, (unsigned long long) off, len);
++	/* check if requested area fits in superblock buffer */
++	if (off + len <= SB_BUFFER_SIZE) {
++		/* check if we need to read */
++		if ((off + len) > id->sbbuf_len) {
++			if (devread (0, 0, off + len, (char*)id->sbbuf) == 0)
++                        {
++				return NULL;
++                        }
++			id->sbbuf_len = off + len;
++		}
++		return &(id->sbbuf[off]);
++	} else {
++		if (len > SEEK_BUFFER_SIZE) {
++			dbg("seek buffer too small %d", SEEK_BUFFER_SIZE);
++			return NULL;
++		}
++
++		/* check if we need to read */
++		if ((off < id->seekbuf_off) || ((off + len) > (id->seekbuf_off + id->seekbuf_len))) {
++			info("read seekbuf off:0x%llx len:0x%zx", (unsigned long long) off, len);
++			if (devread(off >> 9, off & 0x1ff, len, (char*)id->seekbuf) == 0)
++			{
++				return NULL;
++			}
++			id->seekbuf_off = off;
++			id->seekbuf_len = len;
++		}
++		return &(id->seekbuf[off - id->seekbuf_off]);
++	}
++}
+
+=== added file 'libvolume_id/util.h'
+--- grub-0.97.orig/libvolume_id/util.h	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/util.h	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,98 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005-2006 Kay Sievers <kay.sievers@vrfy.org>
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _VOLUME_ID_UTIL_
++#define _VOLUME_ID_UTIL_
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include <endian.h>
++#include <byteswap.h>
++#include <syslog.h>
++
++#define ALLOWED_CHARS				"#+-.:=@_"
++
++#ifndef PACKED
++#define PACKED				__attribute__((packed))
++#endif
++
++#define err(format, arg...)	volume_id_log_fn(LOG_ERR, __FILE__, __LINE__, format, ##arg)
++#ifdef INFO
++#define info(format, arg...)	volume_id_log_fn(LOG_INFO, __FILE__, __LINE__, format, ##arg)
++#else
++#define info(format, arg...)    do { } while (0)
++#endif
++
++#ifdef DEBUG
++#define dbg(format, arg...)	volume_id_log_fn(LOG_DEBUG, __FILE__, __LINE__, format, ##arg)
++#else
++#define dbg(format, arg...)	do { } while (0)
++#endif
++
++/* size of superblock buffer, reiserfs block is at 64k */
++#define SB_BUFFER_SIZE				0x11000
++/* size of seek buffer, FAT cluster is 32k max */
++#define SEEK_BUFFER_SIZE			0x10000
++
++#ifdef __BYTE_ORDER
++#if (__BYTE_ORDER == __LITTLE_ENDIAN)
++#define le16_to_cpu(x) (x)
++#define le32_to_cpu(x) (x)
++#define le64_to_cpu(x) (x)
++#define be16_to_cpu(x) bswap_16(x)
++#define be32_to_cpu(x) bswap_32(x)
++#define cpu_to_le16(x) (x)
++#define cpu_to_le32(x) (x)
++#define cpu_to_be32(x) bswap_32(x)
++#elif (__BYTE_ORDER == __BIG_ENDIAN)
++#define le16_to_cpu(x) bswap_16(x)
++#define le32_to_cpu(x) bswap_32(x)
++#define le64_to_cpu(x) bswap_64(x)
++#define be16_to_cpu(x) (x)
++#define be32_to_cpu(x) (x)
++#define cpu_to_le16(x) bswap_16(x)
++#define cpu_to_le32(x) bswap_32(x)
++#define cpu_to_be32(x) (x)
++#endif
++#endif /* __BYTE_ORDER */
++
++enum uuid_format {
++	UUID_STRING,
++	UUID_HEX_STRING,
++	UUID_DCE,
++	UUID_DOS,
++	UUID_64BIT_LE,
++	UUID_64BIT_BE,
++	UUID_FOURINT,
++};
++
++enum endian {
++	LE = 0,
++	BE = 1
++};
++
++extern int volume_id_utf8_encoded_valid_unichar(const char *str);
++extern size_t volume_id_set_unicode16(uint8_t *str, size_t len, const uint8_t *buf, enum endian endianess, size_t count);
++extern void volume_id_set_usage(struct volume_id *id, enum volume_id_usage usage_id);
++extern void volume_id_set_label_raw(struct volume_id *id, const uint8_t *buf, size_t count);
++extern void volume_id_set_label_string(struct volume_id *id, const uint8_t *buf, size_t count);
++extern void volume_id_set_label_unicode16(struct volume_id *id, const uint8_t *buf, enum endian endianess, size_t count);
++extern void volume_id_set_uuid(struct volume_id *id, const uint8_t *buf, size_t len, enum uuid_format format);
++extern uint8_t *volume_id_get_buffer(struct volume_id *id, uint64_t off, size_t len);
++extern void volume_id_free_buffer(struct volume_id *id);
++
++#endif /* _VOLUME_ID_UTIL_ */
++
+
+=== added file 'libvolume_id/via_raid.c'
+--- grub-0.97.orig/libvolume_id/via_raid.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/via_raid.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,88 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ * Based on information taken from dmraid:
++ * Copyright (C) 2004-2006 Heinz Mauelshagen, Red Hat GmbH
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct via_meta {
++	uint16_t	signature;
++	uint8_t		version_number;
++	struct via_array {
++		uint16_t	disk_bit_mask;
++		uint8_t		disk_array_ex;
++		uint32_t	capacity_low;
++		uint32_t	capacity_high;
++		uint32_t	serial_checksum;
++	} PACKED array;
++	uint32_t	serial_checksum[8];
++	uint8_t		checksum;
++} PACKED;
++
++#define VIA_SIGNATURE		0xAA55
++
++/* 8 bit checksum on first 50 bytes of metadata. */
++static uint8_t meta_checksum(struct via_meta *via)
++{
++	uint8_t i = 50, sum = 0;
++
++	while (i--)
++		sum += ((uint8_t*) via)[i];
++
++	return sum == via->checksum;
++}
++
++
++int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	const uint8_t *buf;
++	uint64_t meta_off;
++	struct via_meta *via;
++
++	dbg("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	if (size < 0x10000)
++		return -1;
++
++	meta_off = ((size / 0x200)-1) * 0x200;
++
++	buf = volume_id_get_buffer(id, off + meta_off, 0x200);
++	if (buf == NULL)
++		return -1;
++
++	via = (struct via_meta *) buf;
++	if (le16_to_cpu(via->signature) !=  VIA_SIGNATURE)
++		return -1;
++
++	if (via->version_number > 1)
++		return -1;
++
++	if (!meta_checksum(via))
++		return -1;
++
++	volume_id_set_usage(id, VOLUME_ID_RAID);
++	sprintf(id->type_version, "%u", via->version_number);
++	id->type = "via_raid_member";
++
++	return 0;
++}
+
+=== added file 'libvolume_id/volume_id.c'
+--- grub-0.97.orig/libvolume_id/volume_id.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/volume_id.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,222 @@
++/*
++ * volume_id - reads volume label and uuid
++ *
++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
++ * Grub Port, Copyright (C) 2008 Canonical Ltd.
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include <fcntl.h>
++#include <sys/stat.h>
++
++#include "volume_id.h"
++#include "util.h"
++#include "strfuncs.h"
++#include "shared.h"
++
++#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
++
++struct prober {
++	volume_id_probe_fn_t prober;
++	const char *name[4];
++};
++
++#define NOT_SUPPORTED(x)	
++#define SUPPORTED(x)	x
++
++static const struct prober prober_raid[] = {
++	{ volume_id_probe_ddf_raid, { "ddf_raid", } },
++
++	/* { volume_id_probe_linux_raid, { "linux_raid", } },  */
++	/* { volume_id_probe_intel_software_raid, { "isw_raid", } }, */
++	/* { volume_id_probe_lsi_mega_raid, { "lsi_mega_raid", } }, */
++	/* { volume_id_probe_via_raid, { "via_raid", } }, */
++	/* { volume_id_probe_silicon_medley_raid, { "silicon_medley_raid", } }, */
++	/* { volume_id_probe_nvidia_raid, { "nvidia_raid", } }, */
++	/* { volume_id_probe_promise_fasttrack_raid, { "promise_fasttrack_raid", } }, */
++	/* { volume_id_probe_highpoint_45x_raid, { "highpoint_raid", } }, */
++	/* { volume_id_probe_adaptec_raid, { "adaptec_raid", } }, */
++	/* { volume_id_probe_jmicron_raid, { "jmicron_raid", } }, */
++	/* { volume_id_probe_lvm1, { "lvm1", } }, */
++	/* { volume_id_probe_lvm2, { "lvm2", } }, */
++	/* { volume_id_probe_highpoint_37x_raid, { "highpoint_raid", } }, */
++};
++
++static const struct prober prober_filesystem[] = {
++	{ volume_id_probe_vfat, { "vfat", } }, 
++	{ volume_id_probe_luks, { "luks", } }, 
++	{ volume_id_probe_xfs, { "xfs", } }, 
++	{ volume_id_probe_ext, { "ext2", "ext3", "jbd", } }, 
++	{ volume_id_probe_reiserfs, { "reiserfs", "reiser4", } }, 
++	{ volume_id_probe_jfs, { "jfs", } }, 
++	{ volume_id_probe_hfs_hfsplus, { "hfs", "hfsplus", } }, 
++	{ volume_id_probe_ntfs, { "ntfs", } },
++ 	{ volume_id_probe_ocfs1, { "ocfs1", } },
++	{ volume_id_probe_ocfs2, { "ocfs2", } }, 
++
++	/* { volume_id_probe_linux_swap, { "swap", } }, */
++	/* { volume_id_probe_udf, { "udf", } }, */
++	/* { volume_id_probe_iso9660, { "iso9660", } }, */
++	/* { volume_id_probe_ufs, { "ufs", } },  */
++	/* { volume_id_probe_cramfs, { "cramfs", } }, */
++	/* { volume_id_probe_romfs, { "romfs", } }, */
++	/* { volume_id_probe_hpfs, { "hpfs", } }, */
++	/* { volume_id_probe_sysv, { "sysv", "xenix", } }, */
++	/* { volume_id_probe_minix, { "minix",  } }, */
++	/* { volume_id_probe_vxfs, { "vxfs", } }, */
++	/* { volume_id_probe_squashfs, { "squashfs", } }, */
++	/* { volume_id_probe_netware, { "netware", } }, */
++};
++
++/* the user can overwrite this log function */
++static void default_log(int priority, const char *file, int line, const char *format, ...)
++{
++	return;
++}
++
++volume_id_log_fn_t volume_id_log_fn = default_log;
++
++/**
++ * volume_id_get_type:
++ * @id: Probing context
++ * @type: Type string. Must not be freed by the caller.
++ *
++ * Get the type string after a successful probe.
++ *
++ * Returns: 1 if the value was set, 0 otherwise.
++ **/
++int volume_id_get_type(struct volume_id *id, const char **type)
++{
++	if (id == NULL)
++		return 0;
++	if (type == NULL)
++		return 0;
++	if (id->usage_id == VOLUME_ID_UNUSED)
++		return 0;
++
++	*type = id->type;
++	return 1;
++}
++
++
++/**
++ * volume_id_get_uuid:
++ * @id: Probing context.
++ * @uuid: UUID string. Must not be freed by the caller.
++ *
++ * Get the raw UUID string after a successful probe.
++ *
++ * Returns: 1 if the value was set, 0 otherwise.
++ **/
++int volume_id_get_uuid(struct volume_id *id, const char **uuid)
++{
++	if (id == NULL)
++		return 0;
++	if (uuid == NULL)
++		return 0;
++	if (id->usage_id == VOLUME_ID_UNUSED)
++		return 0;
++
++	*uuid = id->uuid;
++	return 1;
++}
++
++/**
++ * volume_id_probe_raid:
++ * @id: Probing context.
++ * @off: Probing offset relative to the start of the device.
++ * @size: Total size of the device.
++ *
++ * Probe device for all known raid signatures.
++ *
++ * Returns: 0 on successful probe, otherwise negative value.
++ **/
++int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	unsigned int i;
++
++	if (id == NULL)
++		return -1;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	for (i = 0; i < ARRAY_SIZE(prober_raid); i++)
++		if (prober_raid[i].prober(id, off, size) == 0)
++			goto found;
++	return -1;
++
++found:
++	return 0;
++}
++
++/**
++ * volume_id_probe_filesystem:
++ * @id: Probing context.
++ * @off: Probing offset relative to the start of the device.
++ * @size: Total size of the device.
++ *
++ * Probe device for all known filesystem signatures.
++ *
++ * Returns: 0 on successful probe, otherwise negative value.
++ **/
++int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	unsigned int i;
++
++	if (id == NULL)
++		return -1;
++
++	info("probing at offset 0x%llx, size 0x%llx",
++	    (unsigned long long) off, (unsigned long long) size);
++
++	for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++)
++		if (prober_filesystem[i].prober(id, off, size) == 0)
++			goto found;
++	return -1;
++
++found:
++	return 0;
++}
++
++/**
++ * volume_id_probe_raid:
++ * @all_probers_fn: prober function to called for all known probing routines.
++ * @id: Context passed to prober function.
++ * @off: Offset value passed to prober function.
++ * @size: Size value passed to prober function.
++ * @data: Arbitrary data passed to the prober function.
++ *
++ * Run a custom function for all known probing routines.
++ **/
++void volume_id_all_probers(all_probers_fn_t all_probers_fn,
++			   struct volume_id *id, uint64_t off, uint64_t size,
++			   void *data)
++{
++	unsigned int i;
++
++	if (all_probers_fn == NULL)
++		return;
++
++	for (i = 0; i < ARRAY_SIZE(prober_raid); i++) {	
++		if (all_probers_fn(prober_raid[i].prober, id, off, size, data) != 0)
++			goto out;
++	}
++	for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) {
++		if (all_probers_fn(prober_filesystem[i].prober, id, off, size, data) != 0)
++			goto out;
++	}
++out:
++	return;
++}
+
+=== added file 'libvolume_id/volume_id.h'
+--- grub-0.97.orig/libvolume_id/volume_id.h	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/volume_id.h	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,137 @@
++/*
++ * volume_id - reads volume label and uuid
++ *
++ * Copyright (C) 2005-2007 Kay Sievers <kay.sievers@vrfy.org>
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _LIBVOLUME_ID_H_
++#define _LIBVOLUME_ID_H_
++
++#include <stdint.h>
++#include <stddef.h>
++
++typedef void (*volume_id_log_fn_t)(int priority, const char *file, int line, const char *format, ...) ;
++
++extern volume_id_log_fn_t volume_id_log_fn;
++
++struct volume_id;
++typedef int (*volume_id_probe_fn_t)(struct volume_id *id, uint64_t off, uint64_t size);
++typedef int (*all_probers_fn_t)(volume_id_probe_fn_t probe_fn,
++				struct volume_id *id, uint64_t off, uint64_t size,
++				void *data);
++
++extern struct volume_id *volume_id_open_fd(int fd);
++extern void volume_id_close(struct volume_id *id);
++extern int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_all(struct volume_id *id, uint64_t off, uint64_t size);
++extern const volume_id_probe_fn_t *volume_id_get_prober_by_type(const char *type);
++extern void volume_id_all_probers(all_probers_fn_t all_probers_fn,
++				  struct volume_id *id, uint64_t off, uint64_t size,
++				  void *data);
++extern int volume_id_get_label(struct volume_id *id, const char **label);
++extern int volume_id_get_label_raw(struct volume_id *id, const uint8_t **label, size_t *len);
++extern int volume_id_get_uuid(struct volume_id *id, const char **uuid);
++extern int volume_id_get_uuid_raw(struct volume_id *id, const uint8_t **uuid, size_t *len);
++extern int volume_id_get_usage(struct volume_id *id, const char **usage);
++extern int volume_id_get_type(struct volume_id *id, const char **type);
++extern int volume_id_get_type_version(struct volume_id *id, const char **type_version);
++extern int volume_id_encode_string(const char *str, char *str_enc, size_t len);
++
++/*
++ * Note: everything below will be made private or removed from
++ * a future version, and a new major release of libvolume_id
++ */
++
++extern struct volume_id *volume_id_open_node(const char *path);
++
++#define VOLUME_ID_LABEL_SIZE		64
++#define VOLUME_ID_UUID_SIZE		36
++#define VOLUME_ID_FORMAT_SIZE		32
++#define VOLUME_ID_PATH_MAX		256
++#define VOLUME_ID_PARTITIONS_MAX	256
++
++enum volume_id_usage {
++	VOLUME_ID_UNUSED,
++	VOLUME_ID_UNPROBED,
++	VOLUME_ID_OTHER,
++	VOLUME_ID_FILESYSTEM,
++	VOLUME_ID_RAID,
++	VOLUME_ID_DISKLABEL,
++	VOLUME_ID_CRYPTO,
++};
++
++#include <util.h>
++
++struct volume_id {
++	uint8_t		label_raw[VOLUME_ID_LABEL_SIZE];
++	size_t		label_raw_len;
++	char		label[VOLUME_ID_LABEL_SIZE+1];
++	uint8_t		uuid_raw[VOLUME_ID_UUID_SIZE];
++	size_t		uuid_raw_len;
++	char		uuid[VOLUME_ID_UUID_SIZE+1];
++	enum		volume_id_usage usage_id;
++	char		*usage;
++	char		*type;
++	char		type_version[VOLUME_ID_FORMAT_SIZE];
++
++	int		fd;
++	uint8_t		sbbuf[SB_BUFFER_SIZE];
++	size_t		sbbuf_len;
++	uint8_t		seekbuf[SEEK_BUFFER_SIZE];
++	uint64_t	seekbuf_off;
++	size_t		seekbuf_len;
++	int		fd_close:1;
++};
++
++/* filesystems */
++extern int volume_id_probe_cramfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_ext(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_vfat(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_hfs_hfsplus(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_hpfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_iso9660(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_jfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_minix(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_ntfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_reiserfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_romfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_udf(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_ufs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_vxfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_xfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_squashfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_netware(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_gfs(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_gfs2(struct volume_id *id, uint64_t off, uint64_t size);
++
++/* special formats */
++extern int volume_id_probe_linux_swap(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_luks(struct volume_id *id, uint64_t off, uint64_t size);
++
++/* raid */
++extern int volume_id_probe_linux_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_lvm1(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_lvm2(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_ddf_raid(struct volume_id *id, uint64_t off, uint64_t size);
++
++/* bios raid */
++extern int volume_id_probe_intel_software_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_highpoint_37x_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_highpoint_45x_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_lsi_mega_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_nvidia_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_promise_fasttrack_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_silicon_medley_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_via_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_adaptec_raid(struct volume_id *id, uint64_t off, uint64_t size);
++extern int volume_id_probe_jmicron_raid(struct volume_id *id, uint64_t off, uint64_t size);
++
++#endif
+
+=== added file 'libvolume_id/vxfs.c'
+--- grub-0.97.orig/libvolume_id/vxfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/vxfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,49 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++#define VXFS_SUPER_MAGIC	0xa501FCF5
++
++struct vxfs_super {
++	uint32_t		vs_magic;
++	int32_t			vs_version;
++} PACKED;
++
++int volume_id_probe_vxfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct vxfs_super *vxs;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	vxs = (struct vxfs_super *) volume_id_get_buffer(id, off + 0x200, 0x200);
++	if (vxs == NULL)
++		return -1;
++
++	if (vxs->vs_magic == cpu_to_le32(VXFS_SUPER_MAGIC)) {
++		sprintf(id->type_version, "%u", (unsigned int) vxs->vs_version);
++		volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++		id->type = "vxfs";
++		return 0;
++	}
++
++	return -1;
++}
+
+=== added file 'libvolume_id/xfs.c'
+--- grub-0.97.orig/libvolume_id/xfs.c	1970-01-01 00:00:00 +0000
++++ grub-0.97/libvolume_id/xfs.c	2008-07-15 12:31:43 +0000
+@@ -0,0 +1,59 @@
++/*
++ * volume_id - reads filesystem label and uuid
++ *
++ * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
++ *
++ *	This program is free software; you can redistribute it and/or modify it
++ *	under the terms of the GNU General Public License as published by the
++ *	Free Software Foundation version 2 of the License.
++ */
++
++#ifndef _GNU_SOURCE
++#define _GNU_SOURCE 1
++#endif
++
++#ifdef HAVE_CONFIG_H
++#  include <config.h>
++#endif
++
++#include "volume_id.h"
++#include "util.h"
++#include "shared.h"
++
++struct xfs_super_block {
++	uint8_t	magic[4];
++	uint32_t	blocksize;
++	uint64_t	dblocks;
++	uint64_t	rblocks;
++	uint32_t	dummy1[2];
++	uint8_t	uuid[16];
++	uint32_t	dummy2[15];
++	uint8_t	fname[12];
++	uint32_t	dummy3[2];
++	uint64_t	icount;
++	uint64_t	ifree;
++	uint64_t	fdblocks;
++} PACKED;
++
++int volume_id_probe_xfs(struct volume_id *id, uint64_t off, uint64_t size)
++{
++	struct xfs_super_block *xs;
++
++	info("probing at offset 0x%llx", (unsigned long long) off);
++
++	xs = (struct xfs_super_block *) volume_id_get_buffer(id, off, 0x200);
++	if (xs == NULL)
++		return -1;
++
++	if (memcmp((char *)xs->magic, "XFSB", 4) != 0)
++		return -1;
++
++	volume_id_set_label_raw(id, xs->fname, 12);
++	volume_id_set_label_string(id, xs->fname, 12);
++	volume_id_set_uuid(id, xs->uuid, 0, UUID_DCE);
++
++	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
++	id->type = "xfs";
++
++	return 0;
++}
+
+=== modified file 'stage2/Makefile.am'
+--- grub-0.97.orig/stage2/Makefile.am	2005-02-02 20:40:05 +0000
++++ grub-0.97/stage2/Makefile.am	2008-07-09 17:23:44 +0000
+@@ -13,6 +13,10 @@
+ # For <stage1.h>.
+ INCLUDES = -I$(top_srcdir)/stage1
+ 
++if UUID_SUPPORT
++INCLUDES += -I$(top_srcdir)/libvolume_id
++endif
++
+ # The library for /sbin/grub.
+ noinst_LIBRARIES = libgrub.a
+ libgrub_a_SOURCES = boot.c builtins.c char_io.c cmdline.c common.c \
+@@ -61,6 +65,12 @@
+ PXELOADER_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00
+ START_ELTORITO_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,7C00
+ 
++if UUID_SUPPORT
++UUID_FLAGS = -DSUPPORT_UUID=1
++else
++UUID_FLAGS =
++endif
++
+ if NETBOOT_SUPPORT
+ NETBOOT_FLAGS = -I$(top_srcdir)/netboot -DSUPPORT_NETBOOT=1
+ else
+@@ -82,6 +92,8 @@
+ STAGE2_COMPILE = $(STAGE2_CFLAGS) -fno-builtin -nostdinc \
+ 	$(NETBOOT_FLAGS) $(SERIAL_FLAGS) $(HERCULES_FLAGS)
+ 
++STAGE2_COMPILE += $(UUID_FLAGS)
++
+ STAGE1_5_LINK = -nostdlib -Wl,-N -Wl,-Ttext -Wl,2000
+ STAGE1_5_COMPILE = $(STAGE2_COMPILE) -DNO_DECOMPRESSION=1 -DSTAGE1_5=1
+ 
+@@ -97,7 +109,12 @@
+ 
+ if NETBOOT_SUPPORT
+ pre_stage2_exec_LDADD = ../netboot/libdrivers.a
+-endif
++else
++if UUID_SUPPORT
++pre_stage2_exec_LDADD = ../libvolume_id/libvolume_id.a
++endif
++endif
++
+ 
+ if DISKLESS_SUPPORT
+ BUILT_SOURCES = stage2_size.h diskless_size.h
+
+=== modified file 'stage2/builtins.c'
+--- grub-0.97.orig/stage2/builtins.c	2008-01-28 18:15:31 +0000
++++ grub-0.97/stage2/builtins.c	2008-07-09 17:23:44 +0000
+@@ -49,6 +49,10 @@
+ # include <md5.h>
+ #endif
+ 
++#ifdef SUPPORT_UUID
++#include <volume_id.h>
++#endif
++
+ /* The type of kernel loaded.  */
+ kernel_t kernel_type;
+ /* The boot device.  */
+@@ -4790,6 +4794,168 @@
+   "Probe VBE information. If the mode number MODE is specified, show only"
+   " the information about only the mode."
+ };
++
++
++\f
++#ifdef SUPPORT_UUID
++
++struct uuid_callback_data
++{
++   int  found;	/* 1 if uuid matches */
++   char *uuid;  /* uuid to look for */
++};
++
++static void uuid_info_print(struct volume_id *id, const char *uuid)
++{
++  const char *type;
++  int i;
++
++  volume_id_get_type(id, &type);
++  grub_printf("(hd%d", current_drive - 0x80);
++  if ((current_partition & 0xFF0000) != 0xFF0000)
++    {
++      grub_printf (",%d", (current_partition >> 16) & 0xFF);
++    }
++  if ((current_partition & 0x00FF00) != 0x00FF00)
++    {
++      grub_printf (",%c", 'a' + ((current_partition >> 8) & 0xFF));
++    }
++  grub_printf(") %s",type);
++  for (i=0;i<6-strlen(type);i++)
++    {
++      grub_putchar(' ');
++    }
++  grub_printf(" %s\n",uuid);
++}
++
++static int uuid_all_probers(volume_id_probe_fn_t probe_fn,
++                            struct volume_id *id, 
++			    uint64_t off, 
++			    uint64_t size, 
++			    void *data)
++{
++  struct uuid_callback_data *uc_data = (struct uuid_callback_data*)data;
++
++  if (probe_fn(id, off, size) == 0)
++    {
++      const char *volume_uuid;
++      if (volume_id_get_uuid(id, &volume_uuid)) 
++        {
++          if (!*(uc_data->uuid))
++            { 
++              uuid_info_print(id, volume_uuid);
++            }
++          else
++           {
++              if (strcmp(volume_uuid, uc_data->uuid) == 0) 
++                {
++                  grub_printf("Boot from ");
++                  uuid_info_print(id, volume_uuid);
++                  uc_data->found = 1;
++                  return 1;
++                }
++            }
++        }
++    }
++  return 0;
++}
++
++/* uuid find */
++/* Search for the uuid arg in all of partitions.  */
++static int
++uuid_func(char *arg, int flag)
++{
++  unsigned long drive;
++  unsigned long tmp_drive = saved_drive;
++  unsigned long tmp_partition = saved_partition;
++  struct uuid_callback_data uc_data;
++
++  uc_data.uuid = arg;
++  uc_data.found = 0;
++
++  /* Just hard disks and USB drives supported by BIOS  */
++  for (drive = 0x80; drive < 0x88; drive++)
++    {
++      unsigned long part = 0xFFFFFF;
++      unsigned long start, len, offset, ext_offset, gpt_offset;
++      int type, entry, gpt_count, gpt_size;
++      char *buf = (char *) RAW_ADDR(0x100000);
++      struct volume_id *vol_id = (struct volume_id *) RAW_ADDR (0x100000 + SECTOR_SIZE);
++
++      current_drive = drive;
++      while (next_partition (drive, 0xFFFFFF, &part, &type,
++			     &start, &len, &offset, &entry,
++			     &ext_offset, &gpt_offset,
++			     &gpt_count, &gpt_size, buf))
++	{
++	  if (type != PC_SLICE_TYPE_NONE
++	      && ! IS_PC_SLICE_TYPE_BSD (type)
++	      && ! IS_PC_SLICE_TYPE_EXTENDED (type))
++	    {
++	      current_partition = part;
++              errnum = ERR_NONE;
++              /* Attempt to open device, conventional way */
++              if (! open_device ())
++                {
++                  errnum = ERR_NONE;
++                  /* Failed, like NTFS or FAT filesystems, so try the rootnoverify way */
++                  if (open_partition ())
++                    {
++                      set_bootdev (0);
++                      if (errnum)
++                        {
++                          /* Give up */
++                          errnum = ERR_NONE;
++                          continue;
++                        }
++                    }
++                }
++
++              /* And probe for uuid across all fs types */
++              saved_drive = current_drive;
++              saved_partition = current_partition;
++		
++              grub_memset(vol_id, 0, sizeof(struct volume_id) );
++              volume_id_all_probers(uuid_all_probers, vol_id, 0, len, (void*)&uc_data);
++              if (uc_data.found)
++                {
++                  /* Success! */
++                  errnum = ERR_NONE;
++                  return 0;
++                }
++	    }
++	  /* We want to ignore any error here.  */
++	  errnum = ERR_NONE;
++	}
++
++      /* next_partition always sets ERRNUM in the last call, so clear it.  */
++      errnum = ERR_NONE;
++    }
++
++  saved_drive = tmp_drive;
++  saved_partition = tmp_partition;
++  current_drive = GRUB_INVALID_DRIVE;
++  current_partition = 0xFFFFFF;
++  errnum = ERR_FILE_NOT_FOUND;
++
++  if (!*arg) 
++    {
++      errnum = ERR_NONE;
++      return 0;
++    }
++  return 1;
++}
++
++static struct builtin builtin_uuid =
++{
++  "uuid",
++  uuid_func,
++  BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
++  "uuid UUID",
++  "Set the current \"root device\" to the device with the uuid UUID,"
++  " then attempt to mount it"
++};
++#endif
+   
+ \f
+ /* The table of builtin commands. Sorted in dictionary order.  */
+@@ -4879,6 +5045,9 @@
+   &builtin_title,
+   &builtin_unhide,
+   &builtin_uppermem,
++#ifdef SUPPORT_UUID
++  &builtin_uuid,
++#endif
+   &builtin_vbeprobe,
+   0
+ };
+

diff --git a/sys-boot/grub/files/grub-0.97-uuid_doc.patch b/sys-boot/grub/files/grub-0.97-uuid_doc.patch
new file mode 100644
index 0000000..06bfbde
--- /dev/null
+++ b/sys-boot/grub/files/grub-0.97-uuid_doc.patch
@@ -0,0 +1,38 @@
+--- grub-0.97.orig/docs/grub.texi	2008-07-17 11:07:25.000000000 +0100
++++ grub-0.97/docs/grub.texi	2008-07-17 10:57:41.000000000 +0100
+@@ -2707,6 +2707,7 @@
+ * testload::                    Load a file for testing a filesystem
+ * testvbe::                     Test VESA BIOS EXTENSION
+ * uppermem::                    Set the upper memory size
++* uuid::                        Set GRUB's root device using UUID
+ * vbeprobe::                    Probe VESA BIOS EXTENSION
+ @end menu
+ 
+@@ -3266,6 +3267,27 @@
+ also be used for debugging purposes to lie to an OS.
+ @end deffn
+ 
++@node uuid
++@subsection uuid
++
++@deffn Command uuid [UUID]
++Set the current @dfn{root device} to the device with the universally 
++unique identifier @var{UUID}, then attempt to mount it.  This is 
++equivalent to the @ref{root} command, but allows one to select a 
++filesystem by UUID rather than by device.
++
++The command recognises ext2, ext3, fat, hfs, jfs, ntfs, ocfs, reiserfs 
++and xfs filesystems.
++
++@strong{Note:} grub detects and recognises fat UUIDs in lower case 
++whereas examining /dev/disk/by-uuid on Linux will report fat UUIDs 
++in upper case.
++
++By not specifying @var{UUID}, the command will scan partitions on 
++attached devices and will display the device, partition type and 
++UUID for each recognised filesystem.
++@end deffn
++
+ 
+ @node vbeprobe
+ @subsection vbeprobe

diff --git a/sys-boot/grub/files/grub-1.96-genkernel.patch b/sys-boot/grub/files/grub-1.96-genkernel.patch
new file mode 100644
index 0000000..e06f383
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.96-genkernel.patch
@@ -0,0 +1,19 @@
+--- util/grub.d/10_linux.in
++++ util/grub.d/10_linux.in
+@@ -61,7 +61,7 @@
+ EOF
+ }
+ 
+-list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
++list=`for i in /boot/kernel-* /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
+         if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+       done`
+ 
+@@ -78,6 +78,7 @@
+   initrd=
+   for i in "initrd.img-${version}" "initrd-${version}.img" \
+ 	   "initrd-${version}" "initrd.img-${alt_version}" \
++	   "initramfs-genkernel-${version}" "initramfs-genkernel-${alt_version}" \
+ 	   "initrd-${alt_version}.img" "initrd-${alt_version}"; do
+     if test -e "${dirname}/${i}" ; then
+       initrd="$i"

diff --git a/sys-boot/grub/files/grub-1.97-genkernel.patch b/sys-boot/grub/files/grub-1.97-genkernel.patch
new file mode 100644
index 0000000..ae64ae4
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.97-genkernel.patch
@@ -0,0 +1,28 @@
+--- grub-1.97.2.orig/util/grub.d/10_linux.in
++++ grub-1.97.2/util/grub.d/10_linux.in
+@@ -49,7 +49,7 @@ menuentry "$1" {
+ EOF
+   prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/"
+   cat << EOF
+-	linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro $2
++	linux	${rel_dirname}/${basename} ro $2
+ EOF
+   if test -n "${initrd}" ; then
+     cat << EOF
+@@ -61,7 +61,7 @@ EOF
+ EOF
+ }
+ 
+-list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
++list=`for i in /boot/kernel-* /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
+         if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+       done`
+ 
+@@ -78,6 +78,7 @@ while [ "x$list" != "x" ] ; do
+   initrd=
+   for i in "initrd.img-${version}" "initrd-${version}.img" \
+ 	   "initrd-${version}" "initrd.img-${alt_version}" \
++	   "initramfs-genkernel-${version}" "initramfs-genkernel-${alt_version}" \
+ 	   "initrd-${alt_version}.img" "initrd-${alt_version}"; do
+     if test -e "${dirname}/${i}" ; then
+       initrd="$i"

diff --git a/sys-boot/grub/files/grub-1.97-hostdisk.patch b/sys-boot/grub/files/grub-1.97-hostdisk.patch
new file mode 100644
index 0000000..6eb7fe4
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.97-hostdisk.patch
@@ -0,0 +1,60 @@
+--- util/hostdisk.c	2010-01-25 17:04:22 +0000
++++ util/hostdisk.c	2010-01-31 11:52:27 +0000
+@@ -336,7 +336,8 @@
+     char dev[PATH_MAX];
+ 
+     strcpy (dev, map[disk->id].device);
+-    if (disk->partition && strncmp (map[disk->id].device, "/dev/", 5) == 0)
++    if (disk->partition && sector >= disk->partition->start
++	&& strncmp (map[disk->id].device, "/dev/", 5) == 0)
+       is_partition = linux_find_partition (dev, disk->partition->start);
+ 
+     /* Open the partition.  */
+@@ -490,6 +491,23 @@
+ {
+   int fd;
+ 
++  /* Split pre-partition and partition reads.  */
++  if (disk->partition && sector < disk->partition->start
++      && sector + size > disk->partition->start)
++    {
++      grub_err_t err;
++      err = grub_util_biosdisk_read (disk, sector,
++				     disk->partition->start - sector,
++				     buf);
++      if (err)
++	return err;
++
++      return grub_util_biosdisk_read (disk, disk->partition->start,
++				      size - (disk->partition->start - sector),
++				      buf + ((disk->partition->start - sector)
++					     << GRUB_DISK_SECTOR_BITS));
++    }
++
+   fd = open_device (disk, sector, O_RDONLY);
+   if (fd < 0)
+     return grub_errno;
+@@ -527,6 +545,23 @@
+ {
+   int fd;
+ 
++  /* Split pre-partition and partition writes.  */
++  if (disk->partition && sector < disk->partition->start
++      && sector + size > disk->partition->start)
++    {
++      grub_err_t err;
++      err = grub_util_biosdisk_write (disk, sector,
++				      disk->partition->start - sector,
++				      buf);
++      if (err)
++	return err;
++
++      return grub_util_biosdisk_write (disk, disk->partition->start,
++				       size - (disk->partition->start - sector),
++				       buf + ((disk->partition->start - sector)
++					      << GRUB_DISK_SECTOR_BITS));
++    }
++
+   fd = open_device (disk, sector, O_WRONLY);
+   if (fd < 0)
+     return grub_errno;

diff --git a/sys-boot/grub/files/grub-1.97-vga-deprecated.patch b/sys-boot/grub/files/grub-1.97-vga-deprecated.patch
new file mode 100644
index 0000000..16b2ef7
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.97-vga-deprecated.patch
@@ -0,0 +1,12 @@
+--- grub-1.97.2.orig/util/grub.d/00_header.in
++++ grub-1.97.2/util/grub.d/00_header.in
+@@ -76,6 +76,9 @@ case x${GRUB_TERMINAL_OUTPUT} in
+     cat << EOF
+ if loadfont `make_system_path_relative_to_its_root ${GRUB_FONT_PATH}` ; then
+   set gfxmode=${GRUB_GFXMODE}
++  # vga= is deprecated, grub2 handles this just fine
++  # making grub2 res == linux fb res
++  set gfxpayload=keep
+   insmod gfxterm
+   insmod ${GRUB_VIDEO_BACKEND}
+   if terminal_output gfxterm ; then true ; else

diff --git a/sys-boot/grub/files/grub-1.97-wallpaper-settings-support.patch b/sys-boot/grub/files/grub-1.97-wallpaper-settings-support.patch
new file mode 100644
index 0000000..3bf4ffa
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.97-wallpaper-settings-support.patch
@@ -0,0 +1,15 @@
+diff -Nurp grub-1.97.2.orig/util/grub-mkconfig.in grub-1.97.2/util/grub-mkconfig.in
+--- grub-1.97.2.orig/util/grub-mkconfig.in	2010-01-24 19:13:30.000000000 +0100
++++ grub-1.97.2/util/grub-mkconfig.in	2010-02-17 21:01:08.762963506 +0100
+@@ -224,7 +224,10 @@ export GRUB_DEFAULT \
+   GRUB_DISABLE_LINUX_UUID \
+   GRUB_DISABLE_LINUX_RECOVERY \
+   GRUB_GFXMODE \
+-  GRUB_DISABLE_OS_PROBER
++  GRUB_DISABLE_OS_PROBER \
++  GRUB_WALLPAPER \
++  GRUB_COLOR_NORMAL \
++  GRUB_COLOR_HIGHLIGHT
+ 
+ if test "x${grub_cfg}" != "x"; then
+   rm -f ${grub_cfg}.new

diff --git a/sys-boot/grub/files/grub-1.98-add-legacy-rootfs-detection.patch b/sys-boot/grub/files/grub-1.98-add-legacy-rootfs-detection.patch
new file mode 100644
index 0000000..1fadd46
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.98-add-legacy-rootfs-detection.patch
@@ -0,0 +1,83 @@
+diff -ur grub2-orig/util/grub-mkconfig.in grub2-new/util/grub-mkconfig.in
+--- grub2-orig/util/grub-mkconfig.in	2010-01-28 15:01:46.746567396 +0100
++++ grub2-new/util/grub-mkconfig.in	2010-01-28 15:38:48.560587115 +0100
+@@ -119,8 +119,8 @@
+ fi
+ 
+ # Device containing our userland.  Typically used for root= parameter.
+-GRUB_DEVICE="`${grub_probe} --target=device /`"
+-GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true
++GRUB_DEVICE="`${grub_probe} --target=device /`" || GRUB_DEVICE="`legacy_find_root_device`"
++GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || GRUB_DEVICE_UUID="`legacy_convert_to_uuid ${GRUB_DEVICE}`"
+ 
+ # Device containing our /boot partition.  Usually the same as GRUB_DEVICE.
+ GRUB_DEVICE_BOOT="`${grub_probe} --target=device /boot`"
+diff -ur grub2-orig/util/grub-mkconfig_lib.in grub2-new/util/grub-mkconfig_lib.in
+--- grub2-orig/util/grub-mkconfig_lib.in	2010-01-28 15:01:46.740383831 +0100
++++ grub2-new/util/grub-mkconfig_lib.in	2010-01-28 15:38:10.474013430 +0100
+@@ -188,3 +188,65 @@
+   done
+   echo "$a"
+ }
++
++legacy_find_root_device ()
++{
++  mount_point=$1
++
++  # Autodetect current root device
++  device=
++  if [ -f /etc/fstab ] ; then
++    device="`awk '$1!~/^#/{
++      if ($2 ~ "^/+$") { $2 = "/"; } else { sub("/*$", "", $2); }
++      if ($2 == "'"$mount_point"'"){
++        print $1;
++      }
++    }' /etc/fstab | tail -n 1`"
++  fi
++
++  if [ -n "$device" ] ; then
++    case "$device" in
++      LABEL=* | UUID=*)
++        device="`findfs $device`"
++	device="`readlink -f "$device"`"
++      ;;
++      *)
++        device=`readlink -f "$device"`
++      ;;
++    esac
++  fi
++
++  echo $device
++}
++
++legacy_convert_to_uuid()
++{
++  echo "Cannot determine uuid of root device.  Trying legacy probe method" >&2
++  local dev; dev="$1"
++  
++  convert=false
++  case "$dev" in
++    /dev/disk/*)
++      ;;
++    /dev/mapper/*)
++      ;;
++    /dev/evms/[hs]d[a-z][0-9]*)
++      convert=:
++      ;;
++    /dev/evms/*)
++      ;;
++    /dev/md[0-9]*)
++      ;;
++    /dev/*)
++      convert=:
++      ;;
++  esac
++  if $convert; then
++    if [ -b "$dev" ]; then
++      uuid="`blkid -o value -s UUID "$dev" || true`"
++    fi
++  fi
++
++  echo "$uuid"
++}
++

diff --git a/sys-boot/grub/files/grub-1.98-follow-dev-mapper-symlinks.patch b/sys-boot/grub/files/grub-1.98-follow-dev-mapper-symlinks.patch
new file mode 100644
index 0000000..aead475
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.98-follow-dev-mapper-symlinks.patch
@@ -0,0 +1,25 @@
+--- a/util/getroot.c	2010-03-06 20:51:37.000000000 +0000
++++ b/util/getroot.c	2010-05-28 19:21:57.592307313 +0100
+@@ -222,9 +222,20 @@ find_root_device (const char *dir, dev_t
+ 	/* Ignore any error.  */
+ 	continue;
+ 
+-      if (S_ISLNK (st.st_mode))
+-	/* Don't follow symbolic links.  */
++      if (S_ISLNK (st.st_mode)) {
++#ifdef __linux__
++	if (strcmp (dir, "mapper") == 0) {
++	  /* Follow symbolic links under /dev/mapper/; the canonical name
++	     may be something like /dev/dm-0, but the names under
++	     /dev/mapper/ are more human-readable and so we prefer them if
++	     we can get them.  */
++	  if (stat (ent->d_name, &st) < 0)
++	    continue;
++	} else
++#endif /* __linux__ */
++	/* Don't follow other symbolic links.  */
+ 	continue;
++      }
+ 
+       if (S_ISDIR (st.st_mode))
+ 	{

diff --git a/sys-boot/grub/files/grub-1.98-genkernel-initramfs-single.patch b/sys-boot/grub/files/grub-1.98-genkernel-initramfs-single.patch
new file mode 100644
index 0000000..a79a3af
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.98-genkernel-initramfs-single.patch
@@ -0,0 +1,11 @@
+--- grub-1.98.orig/util/grub.d/10_linux.in
++++ grub-1.98/util/grub.d/10_linux.in
+@@ -139,7 +139,7 @@ while [ "x$list" != "x" ] ; do
+       "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}"
+   if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then
+     linux_entry "${OS}" "${version}" true \
+-	"single ${GRUB_CMDLINE_LINUX}"
++	"single init_opts=single ${GRUB_CMDLINE_LINUX}"
+   fi
+ 
+   list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '`

diff --git a/sys-boot/grub/files/grub-1.98-genkernel.patch b/sys-boot/grub/files/grub-1.98-genkernel.patch
new file mode 100644
index 0000000..8fbf39a
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.98-genkernel.patch
@@ -0,0 +1,28 @@
+--- grub-1.98.orig/util/grub.d/10_linux.in	2010-03-06 21:51:37.000000000 +0100
++++ grub-1.98/util/grub.d/10_linux.in	2010-04-12 11:25:51.982167950 +0200
+@@ -84,7 +84,7 @@ EOF
+   printf '%s\n' "${prepare_boot_cache}"
+   cat << EOF
+ 	echo	$(printf "$(gettext "Loading Linux %s ...")" ${version})
+-	linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
++	linux	${rel_dirname}/${basename} ro ${args}
+ EOF
+   if test -n "${initrd}" ; then
+     cat << EOF
+@@ -97,7 +97,7 @@ EOF
+ EOF
+ }
+ 
+-list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
++list=`for i in /boot/kernel-* /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do
+         if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi
+       done`
+ prepare_boot_cache=
+@@ -114,6 +114,7 @@ while [ "x$list" != "x" ] ; do
+ 
+   initrd=
+   for i in "initrd.img-${version}" "initrd-${version}.img" \
++	   "initramfs-genkernel-${version}" "initramfs-genkernel-${alt_version}" \
+ 	   "initrd-${version}" "initrd.img-${alt_version}" \
+ 	   "initrd-${alt_version}.img" "initrd-${alt_version}"; do
+     if test -e "${dirname}/${i}" ; then

diff --git a/sys-boot/grub/files/grub-1.98-wallpaper-settings-support.patch b/sys-boot/grub/files/grub-1.98-wallpaper-settings-support.patch
new file mode 100644
index 0000000..f34f393
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.98-wallpaper-settings-support.patch
@@ -0,0 +1,15 @@
+diff -Nurp grub-1.98.orig/util/grub-mkconfig.in grub-1.98/util/grub-mkconfig.in
+--- grub-1.98.orig/util/grub-mkconfig.in	2010-03-06 21:51:37.000000000 +0100
++++ grub-1.98/util/grub-mkconfig.in	2010-04-12 11:29:28.396075050 +0200
+@@ -224,7 +224,10 @@ export GRUB_DEFAULT \
+   GRUB_GFXPAYLOAD_LINUX \
+   GRUB_DISABLE_OS_PROBER \
+   GRUB_INIT_TUNE \
+-  GRUB_SAVEDEFAULT
++  GRUB_SAVEDEFAULT \
++  GRUB_WALLPAPER \
++  GRUB_COLOR_NORMAL \
++  GRUB_COLOR_HIGHLIGHT
+ 
+ if test "x${grub_cfg}" != "x"; then
+   rm -f ${grub_cfg}.new

diff --git a/sys-boot/grub/files/grub-1.99-disable-floppies.patch b/sys-boot/grub/files/grub-1.99-disable-floppies.patch
new file mode 100644
index 0000000..6bb2862
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.99-disable-floppies.patch
@@ -0,0 +1,28 @@
+
+Author: Robert Millan
+
+An ugly kludge.  Should this be merged upstream?
+
+Index: b/grub-core/kern/emu/hostdisk.c
+===================================================================
+--- a/grub-core/kern/emu/hostdisk.c
++++ b/grub-core/kern/emu/hostdisk.c
+@@ -1077,6 +1077,18 @@
+ 	  continue;
+ 	}
+ 
++      if (! strncmp (p, "/dev/fd", sizeof ("/dev/fd") - 1))
++	{
++	  char *q = p + sizeof ("/dev/fd") - 1;
++	  if (*q >= '0' && *q <= '9')
++	    {
++	      free (map[drive].drive);
++	      map[drive].drive = NULL;
++	      grub_util_info ("`%s' looks like a floppy drive, skipping", p);
++	      continue;
++	    }
++	}
++
+ #ifdef __linux__
+       /* On Linux, the devfs uses symbolic links horribly, and that
+ 	 confuses the interface very much, so use realpath to expand

diff --git a/sys-boot/grub/files/grub-1.99-genkernel.patch b/sys-boot/grub/files/grub-1.99-genkernel.patch
new file mode 100644
index 0000000..433e583
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.99-genkernel.patch
@@ -0,0 +1,11 @@
+--- grub-1.99.orig/util/grub.d/10_linux.in
++++ grub-1.99/util/grub.d/10_linux.in
+@@ -116,7 +116,7 @@ EOF
+   message="$(gettext_printf "Loading Linux %s ..." ${version})"
+   cat << EOF
+ 	echo	'$message'
+-	linux	${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args}
++	linux	${rel_dirname}/${basename} ro ${args}
+ EOF
+   if test -n "${initrd}" ; then
+     message="$(gettext_printf "Loading initial ramdisk ...")"

diff --git a/sys-boot/grub/files/grub-1.99-vga-deprecated-not-yet.patch b/sys-boot/grub/files/grub-1.99-vga-deprecated-not-yet.patch
new file mode 100644
index 0000000..d850c17
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.99-vga-deprecated-not-yet.patch
@@ -0,0 +1,14 @@
+diff -Nurp grub-1.99.orig/grub-core/loader/i386/linux.c grub-1.99/grub-core/loader/i386/linux.c
+--- grub-1.99.orig/grub-core/loader/i386/linux.c	2011-06-11 10:49:46.975998646 +0200
++++ grub-1.99/grub-core/loader/i386/linux.c	2011-06-11 11:52:14.419996325 +0200
+@@ -821,10 +821,6 @@ grub_cmd_linux (grub_command_t cmd __att
+ 	    if (! buf)
+ 	      goto fail;
+ 
+-	    grub_printf ("%s is deprecated. "
+-			 "Use set gfxpayload=%s before "
+-			 "linux command instead.\n",
+-			 argv[i], buf);
+ 	    err = grub_env_set ("gfxpayload", buf);
+ 	    grub_free (buf);
+ 	    if (err)

diff --git a/sys-boot/grub/files/grub-1.99-vga-deprecated.patch b/sys-boot/grub/files/grub-1.99-vga-deprecated.patch
new file mode 100644
index 0000000..20ea6d8
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.99-vga-deprecated.patch
@@ -0,0 +1,12 @@
+--- grub-1.99~rc1.orig/util/grub.d/00_header.in
++++ grub-1.99~rc1/util/grub.d/00_header.in
+@@ -131,6 +131,9 @@ if [ "x$gfxterm" = x1 ]; then
+ if loadfont `make_system_path_relative_to_its_root "${GRUB_FONT_PATH}"` ; then
+   set gfxmode=${GRUB_GFXMODE}
+   load_video
++  # vga= is deprecated, grub2 handles this just fine
++  # making grub2 res == linux fb res
++  set gfxpayload=keep
+   insmod gfxterm
+ fi
+ EOF

diff --git a/sys-boot/grub/files/grub-1.99-wallpaper-settings-support.patch b/sys-boot/grub/files/grub-1.99-wallpaper-settings-support.patch
new file mode 100644
index 0000000..6f3f374
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.99-wallpaper-settings-support.patch
@@ -0,0 +1,15 @@
+diff -Nurp grub-1.99~rc1.orig/util/grub-mkconfig.in grub-1.99~rc1/util/grub-mkconfig.in
+--- grub-1.99~rc1.orig/util/grub-mkconfig.in	2010-12-01 15:45:43.000000000 +0100
++++ grub-1.99~rc1/util/grub-mkconfig.in	2011-06-08 14:37:02.209761705 +0200
+@@ -254,7 +254,10 @@ export GRUB_DEFAULT \
+   GRUB_DISABLE_OS_PROBER \
+   GRUB_INIT_TUNE \
+   GRUB_SAVEDEFAULT \
+-  GRUB_BADRAM
++  GRUB_BADRAM \
++  GRUB_WALLPAPER \
++  GRUB_COLOR_NORMAL \
++  GRUB_COLOR_HIGHLIGHT
+ 
+ if test "x${grub_cfg}" != "x"; then
+   rm -f ${grub_cfg}.new

diff --git a/sys-boot/grub/files/grub-1.99-workaround-raid-bios-bug.patch b/sys-boot/grub/files/grub-1.99-workaround-raid-bios-bug.patch
new file mode 100644
index 0000000..391c40a
--- /dev/null
+++ b/sys-boot/grub/files/grub-1.99-workaround-raid-bios-bug.patch
@@ -0,0 +1,17 @@
+diff -Nurp grub-1.99.orig/grub-core/disk/raid.c grub-1.99/grub-core/disk/raid.c
+--- grub-1.99.orig/grub-core/disk/raid.c	2011-04-18 23:16:16.000000000 +0200
++++ grub-1.99/grub-core/disk/raid.c	2011-06-11 10:48:16.606998702 +0200
+@@ -562,13 +562,6 @@ insert_array (grub_disk_t disk, struct g
+ 			     "superfluous RAID member (%d found)",
+ 			     array->total_devs);
+ 
+-        if (array->members[new_array->index].device != NULL)
+-          /* We found multiple devices with the same number. Again,
+-             this shouldn't happen.  */
+-	  return grub_error (GRUB_ERR_BAD_DEVICE,
+-			     "found two disks with the index %d for RAID %s",
+-			     new_array->index, array->name);
+-
+         if (new_array->disk_size < array->disk_size)
+           array->disk_size = new_array->disk_size;
+         break;

diff --git a/sys-boot/grub/files/grub.conf.gentoo b/sys-boot/grub/files/grub.conf.gentoo
new file mode 100644
index 0000000..0027099
--- /dev/null
+++ b/sys-boot/grub/files/grub.conf.gentoo
@@ -0,0 +1,16 @@
+# This is a sample grub.conf for use with Genkernel, per the Gentoo handbook
+# http://www.gentoo.org/doc/en/handbook/handbook-x86.xml?part=1&chap=10#doc_chap2
+# If you are not using Genkernel and you need help creating this file, you
+# should consult the handbook. Alternatively, consult the grub.conf.sample that
+# is included with the Grub documentation.
+
+default 0
+timeout 30
+#splashimage=(hd0,0)/boot/grub/splash.xpm.gz
+
+#title Gentoo Linux 2.6.24-r5
+#root (hd0,0)
+#kernel /boot/kernel-genkernel-x86-2.6.24-gentoo-r5 root=/dev/ram0 real_root=/dev/sda3
+#initrd /boot/initramfs-genkernel-x86-2.6.24-gentoo-r5
+
+# vim:ft=conf:

diff --git a/sys-boot/grub/files/grub2-default b/sys-boot/grub/files/grub2-default
new file mode 100644
index 0000000..7f16ccc
--- /dev/null
+++ b/sys-boot/grub/files/grub2-default
@@ -0,0 +1,62 @@
+# /etc/default/grub
+# If you change this file, run 'grub-mkconfig -o /boot/grub/grub.cfg' afterwards to update
+# /boot/grub/grub.cfg.
+
+GRUB_DEFAULT=saved
+GRUB_DISTRIBUTOR="Sabayon"
+GRUB_HIDDEN_TIMEOUT=0
+GRUB_HIDDEN_TIMEOUT_QUIET=true
+GRUB_TIMEOUT=5
+
+# Add your extra parameters here below
+# Dear user, put your boot flags here ;-)
+GRUB_CMDLINE_LINUX_DEFAULT=""
+# ATTENTION ATTENTION ATTENTION
+# DO NOT EDIT THIS MANUALLY NOR SET IT TO EMPTY IF IT'S ALREADY FILLED WITH
+# SOMETHING (DONE BY THE INSTALLER). REALLY, DON'T !
+GRUB_CMDLINE_LINUX=""
+# ATTENTION ATTENTION ATTENTION
+
+# Uncomment to disable graphical terminal (grub-pc only)
+# GRUB_TERMINAL=console
+
+# The resolution used on graphical terminal
+# note that you can use only modes which your graphic card supports via VBE
+# you can see them in real GRUB with the command `vbeinfo'
+GRUB_GFXMODE=1024x768
+
+# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
+#GRUB_DISABLE_LINUX_UUID=true
+
+# Uncomment to disable generation of recovery mode menu entrys
+# GRUB_DISABLE_LINUX_RECOVERY="false"
+
+# Default wallpaper image path
+GRUB_WALLPAPER="/boot/grub/default-splash.png"
+
+# Boot menu option normal color
+GRUB_COLOR_NORMAL="white/black"
+
+# Boot menu option "highlight" color
+GRUB_COLOR_HIGHLIGHT="magenta/black"
+
+if [ -f "/etc/default/sabayon-grub" ]; then
+	# this file is placed by the Sabayon Installer and contains
+	# custom GRUB_CMDLINE_LINUX parameters created at install
+	# time.
+	source /etc/default/sabayon-grub
+fi
+
+# DO NOT REMOVE THIS IF YOUR GRUB_CMDLINE_LINUX IS EMPTY (BACKWARD COMPAT)
+if [ -z "${GRUB_CMDLINE_LINUX}" ]; then
+	if [ ! -e "/proc/cmdline" ]; then
+		echo "ATTENTION ATTENTION ATTENTION" >&2
+		echo "GRUB_CMDLINE_LINUX is not set inside /etc/default/grub" >&2
+		echo "  cannot generate a bootable configuration." >&2
+	else
+		echo "ATTENTION ATTENTION ATTENTION" >&2
+		echo "GRUB_CMDLINE_LINUX is not set inside /etc/default/grub" >&2
+		echo "  grub is going to use your /proc/cmdline content" >&2
+		GRUB_CMDLINE_LINUX="`cat /proc/cmdline | sed -e 's#BOOT_IMAGE=.* ro ##g'`"
+	fi
+fi

diff --git a/sys-boot/grub/files/grub2-default-1.99 b/sys-boot/grub/files/grub2-default-1.99
new file mode 100644
index 0000000..9bc0775
--- /dev/null
+++ b/sys-boot/grub/files/grub2-default-1.99
@@ -0,0 +1,63 @@
+# /etc/default/grub
+# If you change this file, run 'grub-mkconfig -o /boot/grub/grub.cfg' afterwards to update
+# /boot/grub/grub.cfg.
+
+GRUB_DEFAULT=saved
+GRUB_DISTRIBUTOR="Sabayon"
+GRUB_HIDDEN_TIMEOUT=0
+GRUB_HIDDEN_TIMEOUT_QUIET=true
+GRUB_TIMEOUT=5
+GRUB_DISABLE_LINUX_UUID=true
+
+# Add your extra parameters here below
+# Dear user, put your boot flags here ;-)
+GRUB_CMDLINE_LINUX_DEFAULT=""
+# ATTENTION ATTENTION ATTENTION
+# DO NOT EDIT THIS MANUALLY NOR SET IT TO EMPTY IF IT'S ALREADY FILLED WITH
+# SOMETHING (DONE BY THE INSTALLER). REALLY, DON'T !
+GRUB_CMDLINE_LINUX=""
+# ATTENTION ATTENTION ATTENTION
+
+# Uncomment to disable graphical terminal (grub-pc only)
+# GRUB_TERMINAL=console
+
+# The resolution used on graphical terminal
+# note that you can use only modes which your graphic card supports via VBE
+# you can see them in real GRUB with the command `vbeinfo'
+GRUB_GFXMODE=1024x768
+
+# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
+#GRUB_DISABLE_LINUX_UUID=true
+
+# Uncomment to disable generation of recovery mode menu entrys
+# GRUB_DISABLE_LINUX_RECOVERY="false"
+
+# Default wallpaper image path
+GRUB_WALLPAPER="/boot/grub/default-splash.png"
+
+# Boot menu option normal color
+GRUB_COLOR_NORMAL="white/black"
+
+# Boot menu option "highlight" color
+GRUB_COLOR_HIGHLIGHT="magenta/black"
+
+if [ -f "/etc/default/sabayon-grub" ]; then
+	# this file is placed by the Sabayon Installer and contains
+	# custom GRUB_CMDLINE_LINUX parameters created at install
+	# time.
+	source /etc/default/sabayon-grub
+fi
+
+# DO NOT REMOVE THIS IF YOUR GRUB_CMDLINE_LINUX IS EMPTY (BACKWARD COMPAT)
+if [ -z "${GRUB_CMDLINE_LINUX}" ]; then
+	if [ ! -e "/proc/cmdline" ]; then
+		echo "ATTENTION ATTENTION ATTENTION" >&2
+		echo "GRUB_CMDLINE_LINUX is not set inside /etc/default/grub" >&2
+		echo "  cannot generate a bootable configuration." >&2
+	else
+		echo "ATTENTION ATTENTION ATTENTION" >&2
+		echo "GRUB_CMDLINE_LINUX is not set inside /etc/default/grub" >&2
+		echo "  grub is going to use your /proc/cmdline content" >&2
+		GRUB_CMDLINE_LINUX="`cat /proc/cmdline | sed -e 's#BOOT_IMAGE=.* ro ##g'`"
+	fi
+fi

diff --git a/sys-boot/grub/files/splash.xpm.gz b/sys-boot/grub/files/splash.xpm.gz
new file mode 100644
index 0000000..f6836bd
Binary files /dev/null and b/sys-boot/grub/files/splash.xpm.gz differ

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/01_uuids_and_lvm_dont_play_along_nicely.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/01_uuids_and_lvm_dont_play_along_nicely.diff
new file mode 100644
index 0000000..c997b84
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/01_uuids_and_lvm_dont_play_along_nicely.diff
@@ -0,0 +1,14 @@
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index c2da413..cbd9d6b 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -36,7 +36,8 @@ case ${GRUB_DEVICE} in
+ esac
+
+ if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+-    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then
++    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
++    || [ "`grub-probe -t abstraction --device ${GRUB_DEVICE} | sed -e 's,.*\(lvm\).*,\1,'`" = "lvm"  ] ; then
+   LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+ else
+   LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/902_boot_blocklist_hack.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/902_boot_blocklist_hack.diff
new file mode 100644
index 0000000..63caf45
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/902_boot_blocklist_hack.diff
@@ -0,0 +1,20 @@
+Index: util/i386/pc/grub-setup.c
+===================================================================
+--- util/i386/pc/grub-setup.c	(revision 1836)
++++ util/i386/pc/grub-setup.c	(working copy)
+@@ -383,6 +383,15 @@
+       grub_disk_cache_invalidate_all ();
+
+       file = grub_file_open (core_path_dev);
++
++      if (grub_errno == GRUB_ERR_FILE_NOT_FOUND)
++	{
++	  /* Clean the previous grub_errno */
++	  grub_errno = GRUB_ERR_NONE;
++	  strcpy (core_path_dev, "/grub/core.img");
++	  file = grub_file_open (core_path_dev);
++	}
++
+       if (file)
+ 	{
+ 	  if (grub_file_size (file) != core_size)

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/904_disable_floppies.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/904_disable_floppies.diff
new file mode 100644
index 0000000..66a41cd
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/904_disable_floppies.diff
@@ -0,0 +1,28 @@
+
+Author: Robert Millan
+
+An ugly kludge.  Should this be merged upstream?
+
+Index: util/hostdisk.c
+===================================================================
+--- util/hostdisk.c	(revision 1832)
++++ util/hostdisk.c	(working copy)
+@@ -544,6 +544,18 @@
+ 	  continue;
+ 	}
+
++      if (! strncmp (p, "/dev/fd", sizeof ("/dev/fd") - 1))
++	{
++	  char *q = p + sizeof ("/dev/fd") - 1;
++	  if (*q >= '0' && *q <= '9')
++	    {
++	      free (map[drive].drive);
++	      map[drive].drive = NULL;
++	      grub_util_info ("`%s' looks like a floppy drive, skipping", p);
++	      continue;
++	    }
++	}
++
+ #ifdef __linux__
+       /* On Linux, the devfs uses symbolic links horribly, and that
+ 	 confuses the interface very much, so use realpath to expand

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/956_loopback_root.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/956_loopback_root.diff
new file mode 100644
index 0000000..ce54872
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/956_loopback_root.diff
@@ -0,0 +1,139 @@
+Upstream: http://lists.gnu.org/archive/html/grub-devel/2009-09/msg00210.html
+Description: If you set root after running loopback, any attempts to open
+ files on the loopback device resolve the loopback file name relative to the
+ *new* root, not the root at the time loopback was invoked, and so the above
+ recurses until it runs out of stack. This causes problems for Wubi. I think
+ it's fairly clear that only the root that was in place when you ran
+ loopback should be relevant to the loopback file name.
+
+diff -Nur -x '*.orig' -x '*~' grub2-1.97~beta2/disk/loopback.c grub2-1.97~beta2.new/disk/loopback.c
+--- grub2-1.97~beta2/disk/loopback.c	2009-06-10 22:04:23.000000000 +0100
++++ grub2-1.97~beta2.new/disk/loopback.c	2009-09-10 21:42:56.000000000 +0100
+@@ -28,6 +28,7 @@
+ {
+   char *devname;
+   char *filename;
++  grub_file_t file;
+   int has_partitions;
+   struct grub_loopback *next;
+ };
+@@ -61,6 +62,7 @@
+   /* Remove the device from the list.  */
+   *prev = dev->next;
+ 
++  grub_file_close (dev->file);
+   grub_free (dev->devname);
+   grub_free (dev->filename);
+   grub_free (dev);
+@@ -90,9 +92,6 @@
+   if (! file)
+     return grub_errno;
+ 
+-  /* Close the file, the only reason for opening it is validation.  */
+-  grub_file_close (file);
+-
+   /* First try to replace the old device.  */
+   for (newdev = loopback_list; newdev; newdev = newdev->next)
+     if (grub_strcmp (newdev->devname, args[0]) == 0)
+@@ -102,10 +101,12 @@
+     {
+       char *newname = grub_strdup (args[1]);
+       if (! newname)
+-	return grub_errno;
++	goto fail;
+ 
+       grub_free (newdev->filename);
+       newdev->filename = newname;
++      grub_file_close (newdev->file);
++      newdev->file = file;
+ 
+       /* Set has_partitions when `--partitions' was used.  */
+       newdev->has_partitions = state[1].set;
+@@ -116,13 +117,13 @@
+   /* Unable to replace it, make a new entry.  */
+   newdev = grub_malloc (sizeof (struct grub_loopback));
+   if (! newdev)
+-    return grub_errno;
++    goto fail;
+ 
+   newdev->devname = grub_strdup (args[0]);
+   if (! newdev->devname)
+     {
+       grub_free (newdev);
+-      return grub_errno;
++      goto fail;
+     }
+ 
+   newdev->filename = grub_strdup (args[1]);
+@@ -130,9 +131,11 @@
+     {
+       grub_free (newdev->devname);
+       grub_free (newdev);
+-      return grub_errno;
++      goto fail;
+     }
+ 
++  newdev->file = file;
++
+   /* Set has_partitions when `--partitions' was used.  */
+   newdev->has_partitions = state[1].set;
+ 
+@@ -141,6 +144,10 @@
+   loopback_list = newdev;
+ 
+   return 0;
++
++fail:
++  grub_file_close (file);
++  return grub_errno;
+ }
+ 
+ \f
+@@ -159,7 +166,6 @@
+ static grub_err_t
+ grub_loopback_open (const char *name, grub_disk_t disk)
+ {
+-  grub_file_t file;
+   struct grub_loopback *dev;
+ 
+   for (dev = loopback_list; dev; dev = dev->next)
+@@ -169,29 +175,17 @@
+   if (! dev)
+     return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device");
+ 
+-  file = grub_file_open (dev->filename);
+-  if (! file)
+-    return grub_errno;
+-
+   /* Use the filesize for the disk size, round up to a complete sector.  */
+-  disk->total_sectors = ((file->size + GRUB_DISK_SECTOR_SIZE - 1)
++  disk->total_sectors = ((dev->file->size + GRUB_DISK_SECTOR_SIZE - 1)
+ 			 / GRUB_DISK_SECTOR_SIZE);
+   disk->id = (unsigned long) dev;
+ 
+   disk->has_partitions = dev->has_partitions;
+-  disk->data = file;
++  disk->data = dev->file;
+ 
+   return 0;
+ }
+ 
+-static void
+-grub_loopback_close (grub_disk_t disk)
+-{
+-  grub_file_t file = (grub_file_t) disk->data;
+-
+-  grub_file_close (file);
+-}
+-
+ static grub_err_t
+ grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
+ 		    grub_size_t size, char *buf)
+@@ -233,7 +227,6 @@
+     .id = GRUB_DISK_DEVICE_LOOPBACK_ID,
+     .iterate = grub_loopback_iterate,
+     .open = grub_loopback_open,
+-    .close = grub_loopback_close,
+     .read = grub_loopback_read,
+     .write = grub_loopback_write,
+     .next = 0

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/957_handle_loopback.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/957_handle_loopback.diff
new file mode 100644
index 0000000..0ee868f
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/957_handle_loopback.diff
@@ -0,0 +1,45 @@
+Ubuntu: needed for Wubi
+Description: Change prepare_grub_to_access_device to handle filesystems
+ loop-mounted on file images.
+UbuntuSpecific: Not inherently. losetup and /proc/mounts are Linux-specific,
+ though, so we might need to refine this before sending it upstream.
+
+diff -Nur -x '*.orig' -x '*~' grub2-1.97~beta3/util/grub-mkconfig_lib.in grub2-1.97~beta3.new/util/grub-mkconfig_lib.in
+--- grub2-1.97~beta3/util/grub-mkconfig_lib.in	2009-09-15 00:23:50.000000000 +0100
++++ grub2-1.97~beta3.new/util/grub-mkconfig_lib.in	2009-09-15 00:31:31.000000000 +0100
+@@ -142,6 +142,20 @@
+ {
+   device=$1
+ 
++  loop_file=
++  case ${device} in
++    /dev/loop/*|/dev/loop[0-9])
++      loop_file=`losetup ${device} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
++      case $loop_file in
++        /dev/*) ;;
++        *)
++          loop_device=${device}
++          device=`${grub_probe} --target=device "${loop_file}"`
++        ;;
++      esac
++    ;;
++  esac
++
+   # Abstraction modules aren't auto-loaded.
+   abstraction="`${grub_probe} --device ${device} --target=abstraction`"
+   for module in ${abstraction} ; do 
+@@ -159,6 +173,14 @@
+   if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then
+     echo "search --no-floppy --fs-uuid --set ${fs_uuid}"
+   fi
++
++  if [ "x${loop_file}" != x ]; then
++    loop_mountpoint="$(awk '"'${loop_file}'" ~ "^"$2 && $2 != "/" { print $2 }' /proc/mounts | tail -n1)"
++    if [ "x${loop_mountpoint}" != x ]; then
++      echo "loopback loop0 ${loop_file#$loop_mountpoint}"
++      echo "set root=(loop0)"
++    fi
++  fi
+ }
+ 
+ grub_file_is_not_garbage ()

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/958_linux_no_loopmount.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/958_linux_no_loopmount.diff
new file mode 100644
index 0000000..9e0dfda
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/958_linux_no_loopmount.diff
@@ -0,0 +1,20 @@
+Ubuntu: needed for Wubi
+Description: Ignore devices loop-mounted from files in 10_linux.
+UbuntuSpecific: Not inherently, but perhaps we should integrate 10_lupin
+ properly instead.
+
+diff -Nur -x '*.orig' -x '*~' grub2-1.97~beta3/util/grub.d/10_linux.in grub2-1.97~beta3.new/util/grub.d/10_linux.in
+--- grub2-1.97~beta3/util/grub.d/10_linux.in	2009-09-16 17:41:06.000000000 +0100
++++ grub2-1.97~beta3.new/util/grub.d/10_linux.in	2009-09-16 17:44:52.000000000 +0100
+@@ -32,6 +32,11 @@
+ case ${GRUB_DEVICE} in
+   /dev/loop/*|/dev/loop[0-9])
+     GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"`
++    # We can't cope with devices loop-mounted from files here.
++    case ${GRUB_DEVICE} in
++      /dev/*) ;;
++      *) exit 0 ;;
++    esac
+   ;;
+ esac
+ 

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/960_raid_virtio.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/960_raid_virtio.diff
new file mode 100644
index 0000000..3b060ba
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/960_raid_virtio.diff
@@ -0,0 +1,158 @@
+diff -Nur -x '*.orig' -x '*~' grub2/include/grub/util/getroot.h grub2.new/include/grub/util/getroot.h
+--- grub2/include/grub/util/getroot.h	2009-11-29 18:42:14.000000000 -0800
++++ grub2.new/include/grub/util/getroot.h	2010-02-03 14:38:02.000000000 -0800
+@@ -19,12 +19,15 @@
+ #ifndef GRUB_UTIL_GETROOT_HEADER
+ #define GRUB_UTIL_GETROOT_HEADER	1
+ 
++#include <sys/types.h>
++
+ enum grub_dev_abstraction_types {
+   GRUB_DEV_ABSTRACTION_NONE,
+   GRUB_DEV_ABSTRACTION_LVM,
+   GRUB_DEV_ABSTRACTION_RAID,
+ };
+ 
++char *grub_find_device (const char *dir, dev_t dev);
+ char *grub_guess_root_device (const char *dir);
+ char *grub_get_prefix (const char *dir);
+ int grub_util_get_dev_abstraction (const char *os_dev);
+diff -Nur -x '*.orig' -x '*~' grub2/util/getroot.c grub2.new/util/getroot.c
+--- grub2/util/getroot.c	2010-02-01 14:33:16.000000000 -0800
++++ grub2.new/util/getroot.c	2010-02-03 14:38:02.000000000 -0800
+@@ -178,8 +178,8 @@
+ 
+ #ifdef __MINGW32__
+ 
+-static char *
+-find_root_device (const char *dir __attribute__ ((unused)),
++char *
++grub_find_device (const char *dir __attribute__ ((unused)),
+                   dev_t dev __attribute__ ((unused)))
+ {
+   return 0;
+@@ -187,13 +187,22 @@
+ 
+ #elif ! defined(__CYGWIN__)
+ 
+-static char *
+-find_root_device (const char *dir, dev_t dev)
++char *
++grub_find_device (const char *dir, dev_t dev)
+ {
+   DIR *dp;
+   char *saved_cwd;
+   struct dirent *ent;
+ 
++  if (! dir)
++    {
++#ifdef __CYGWIN__
++      return NULL;
++#else
++      dir = "/dev";
++#endif
++    }
++
+   dp = opendir (dir);
+   if (! dp)
+     return 0;
+@@ -231,7 +240,7 @@
+ 	  /* Find it recursively.  */
+ 	  char *res;
+ 
+-	  res = find_root_device (ent->d_name, dev);
++	  res = grub_find_device (ent->d_name, dev);
+ 
+ 	  if (res)
+ 	    {
+@@ -334,8 +343,8 @@
+   return serial;
+ }
+ 
+-static char *
+-find_cygwin_root_device (const char *path, dev_t dev)
++char *
++grub_find_device (const char *path, dev_t dev)
+ {
+   /* No root device for /cygdrive.  */
+   if (dev == (DEV_CYGDRIVE_MAJOR << 16))
+@@ -356,7 +365,7 @@
+ 
+   /* Cygwin returns the partition serial number in stat.st_dev.
+      This is never identical to the device number of the emulated
+-     /dev/sdXN device, so above find_root_device () does not work.
++     /dev/sdXN device, so above grub_find_device () does not work.
+      Search the partition with the same serial in boot sector instead.  */
+   char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia.  */
+   int d;
+@@ -449,12 +458,12 @@
+ 
+ #ifdef __CYGWIN__
+   /* Cygwin specific function.  */
+-  os_dev = find_cygwin_root_device (dir, st.st_dev);
++  os_dev = grub_find_device (dir, st.st_dev);
+ 
+ #else
+ 
+   /* This might be truly slow, but is there any better way?  */
+-  os_dev = find_root_device ("/dev", st.st_dev);
++  os_dev = grub_find_device ("/dev", st.st_dev);
+ #endif
+ #endif /* !__GNU__ */
+ 
+diff -Nur -x '*.orig' -x '*~' grub2/util/raid.c grub2.new/util/raid.c
+--- grub2/util/raid.c	2010-02-01 14:33:15.000000000 -0800
++++ grub2.new/util/raid.c	2010-02-03 14:39:38.000000000 -0800
+@@ -21,40 +21,19 @@
+ #ifdef __linux__
+ #include <grub/util/misc.h>
+ #include <grub/util/raid.h>
++#include <grub/util/getroot.h>
+ 
+ #include <string.h>
+ #include <fcntl.h>
+ #include <sys/ioctl.h>
+ #include <errno.h>
++#include <sys/types.h>
+ 
+ #include <linux/types.h>
+ #include <linux/major.h>
+ #include <linux/raid/md_p.h>
+ #include <linux/raid/md_u.h>
+ 
+-static char *
+-grub_util_getdiskname (int major, int minor)
+-{
+-  char *name = xmalloc (15);
+-
+-  if (major == LOOP_MAJOR)
+-    sprintf (name, "/dev/loop%d", minor);
+-  else if (major == IDE0_MAJOR)
+-    sprintf (name, "/dev/hd%c", 'a' + minor / 64);
+-  else if (major == IDE1_MAJOR)
+-    sprintf (name, "/dev/hd%c", 'c' + minor / 64);
+-  else if (major == IDE2_MAJOR)
+-    sprintf (name, "/dev/hd%c", 'e' + minor / 64);
+-  else if (major == IDE3_MAJOR)
+-    sprintf (name, "/dev/hd%c", 'g' + minor / 64);
+-  else if (major == SCSI_DISK0_MAJOR)
+-    sprintf (name, "/dev/sd%c", 'a' + minor / 16);
+-  else
+-    grub_util_error ("unknown device number: %d, %d", major, minor);
+-
+-  return name;
+-}
+-
+ char **
+ grub_util_raid_getmembers (char *name)
+ {
+@@ -99,7 +78,8 @@
+ 
+       if (disk.state & (1 << MD_DISK_ACTIVE))
+ 	{
+-	  devicelist[j] = grub_util_getdiskname (disk.major, disk.minor);
++	  devicelist[j] = grub_find_device (NULL,
++					    makedev (disk.major, disk.minor));
+ 	  j++;
+ 	}
+     }

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/961_dmraid_probe.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/961_dmraid_probe.diff
new file mode 100644
index 0000000..8bc9470
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/961_dmraid_probe.diff
@@ -0,0 +1,650 @@
+Description: Add DM-RAID probing support.
+Upstream: Maintained in an upstream branch,
+ sftp://bzr.sv.gnu.org/srv/bzr/grub/branches/dmraid-probe/; see
+ http://lists.gnu.org/archive/html/grub-devel/2010-01/msg00345.html
+
+diff -Nur -x '*.orig' -x '*~' grub2/ChangeLog.dmraid-probe grub2.new/ChangeLog.dmraid-probe
+--- grub2/ChangeLog.dmraid-probe	1969-12-31 16:00:00.000000000 -0800
++++ grub2.new/ChangeLog.dmraid-probe	2010-02-06 10:33:54.000000000 -0800
+@@ -0,0 +1,26 @@
++2010-01-31  Colin Watson  <cjwatson@ubuntu.com>
++
++	* configure.ac: Check for Linux device-mapper support.
++
++	* util/hostdisk.c (device_is_mapped): New function.
++	(find_partition_start): New function, partly broken out from
++	linux_find_partition and grub_util_biosdisk_get_grub_dev but with
++	device-mapper support added.
++	(linux_find_partition): Use find_partition_start.
++	(convert_system_partition_to_system_disk): Add `st' argument.
++	Support Linux /dev/mapper/* devices if device-mapper support is
++	available; only DM-RAID devices are understood at present.
++	(find_system_device): Add `st' argument.  Pass it to
++	convert_system_partition_to_system_disk.
++	(grub_util_biosdisk_get_grub_dev): Pass stat result to
++	find_system_device and convert_system_partition_to_system_disk.  Use
++	find_partition_start.
++
++	* conf/common.rmk (grub_mkdevicemap_SOURCES): Add kern/env.c,
++	kern/err.c, kern/list.c, and kern/misc.c.
++	* util/deviceiter.c [__linux__]: Define MINOR.
++	(grub_util_iterate_devices): Add support for DM-RAID disk devices.
++	* util/mkdevicemap.c (grub_putchar): New function.
++	(grub_getkey): New function.
++	(grub_refresh): New function.
++	(main): Set debug=all if -v -v is used.
+diff -Nur -x '*.orig' -x '*~' grub2/conf/common.rmk grub2.new/conf/common.rmk
+--- grub2/conf/common.rmk	2010-02-06 10:32:37.000000000 -0800
++++ grub2.new/conf/common.rmk	2010-02-06 10:33:54.000000000 -0800
+@@ -3,7 +3,8 @@
+ sbin_UTILITIES += grub-mkdevicemap
+ grub_mkdevicemap_SOURCES = gnulib/progname.c util/grub-mkdevicemap.c \
+ 	util/deviceiter.c \
+-	util/misc.c
++	util/misc.c \
++	kern/env.c kern/err.c kern/list.c kern/misc.c
+ 
+ ifeq ($(target_cpu)-$(platform), sparc64-ieee1275)
+ grub_mkdevicemap_SOURCES += util/ieee1275/ofpath.c util/ieee1275/devicemap.c
+diff -Nur -x '*.orig' -x '*~' grub2/configure.ac grub2.new/configure.ac
+--- grub2/configure.ac	2010-02-06 10:32:49.000000000 -0800
++++ grub2.new/configure.ac	2010-02-06 10:33:54.000000000 -0800
+@@ -660,6 +660,22 @@
+ AC_SUBST([freetype_cflags])
+ AC_SUBST([freetype_libs])
+ 
++AC_ARG_ENABLE([device-mapper],
++              [AS_HELP_STRING([--enable-device-mapper],
++                              [enable Linux device-mapper support (default=guessed)])])
++if test x"$enable_device_mapper" = xno ; then
++  device_mapper_excuse="explicitly disabled"
++fi
++
++if test x"$device_mapper_excuse" = x ; then
++  # Check for device-mapper library.
++  AC_CHECK_LIB([devmapper], [dm_task_create],
++               [LDFLAGS="$LDFLAGS -ldevmapper"
++                AC_DEFINE([HAVE_DEVICE_MAPPER], [1],
++                          [Define to 1 if you have the devmapper library.])],
++               [device_mapper_excuse="need devmapper library"])
++fi
++
+ AC_SUBST(ASFLAGS)
+ 
+ # Output files.
+diff -Nur -x '*.orig' -x '*~' grub2/util/deviceiter.c grub2.new/util/deviceiter.c
+--- grub2/util/deviceiter.c	2010-02-06 10:32:37.000000000 -0800
++++ grub2.new/util/deviceiter.c	2010-02-06 10:33:54.000000000 -0800
+@@ -31,6 +31,8 @@
+ 
+ #include <grub/util/misc.h>
+ #include <grub/util/deviceiter.h>
++#include <grub/list.h>
++#include <grub/misc.h>
+ 
+ #ifdef __linux__
+ # if !defined(__GLIBC__) || \
+@@ -62,12 +64,23 @@
+                  | ((unsigned int) (__dev >> 32) & ~0xfff); \
+   })
+ # endif /* ! MAJOR */
++# ifndef MINOR
++#  define MINOR(dev)	\
++  ({ \
++     unsigned long long __dev = (dev); \
++     (unsigned) (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); \
++  })
++# endif /* ! MINOR */
+ # ifndef CDROM_GET_CAPABILITY
+ #  define CDROM_GET_CAPABILITY	0x5331	/* get capabilities */
+ # endif /* ! CDROM_GET_CAPABILITY */
+ # ifndef BLKGETSIZE
+ #  define BLKGETSIZE	_IO(0x12,96)	/* return device size */
+ # endif /* ! BLKGETSIZE */
++
++#ifdef HAVE_DEVICE_MAPPER
++# include <libdevmapper.h>
++#endif
+ #endif /* __linux__ */
+ 
+ /* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with
+@@ -411,6 +424,16 @@
+   return 1;
+ }
+ 
++#ifdef __linux__
++# ifdef HAVE_DEVICE_MAPPER
++struct dmraid_seen
++{
++  struct dmraid_seen *next;
++  const char *name;
++};
++# endif /* HAVE_DEVICE_MAPPER */
++#endif /* __linux__ */
++
+ void
+ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int),
+ 			   int floppy_disks)
+@@ -643,6 +666,123 @@
+ 	    return;
+ 	}
+     }
++
++# ifdef HAVE_DEVICE_MAPPER
++#  define dmraid_check(cond, ...) \
++  if (! (cond)) \
++    { \
++      grub_dprintf ("deviceiter", __VA_ARGS__); \
++      goto dmraid_end; \
++    }
++
++  /* DM-RAID.  */
++  {
++    struct dm_tree *tree = NULL;
++    struct dm_task *task = NULL;
++    struct dm_names *names = NULL;
++    unsigned int next = 0;
++    void *top_handle, *second_handle;
++    struct dm_tree_node *root, *top, *second;
++    struct dmraid_seen *seen = NULL;
++
++    /* Build DM tree for all devices.  */
++    tree = dm_tree_create ();
++    dmraid_check (tree, "dm_tree_create failed\n");
++    task = dm_task_create (DM_DEVICE_LIST);
++    dmraid_check (task, "dm_task_create failed\n");
++    dmraid_check (dm_task_run (task), "dm_task_run failed\n");
++    names = dm_task_get_names (task);
++    dmraid_check (names, "dm_task_get_names failed\n");
++    dmraid_check (names->dev, "No DM devices found\n");
++    do
++      {
++	names = (void *) names + next;
++	dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev),
++				       MINOR (names->dev)),
++			 "dm_tree_add_dev (%s) failed\n", names->name);
++	next = names->next;
++      }
++    while (next);
++
++    /* Walk the second-level children of the inverted tree; that is, devices
++       which are directly composed of non-DM devices such as hard disks.
++       This class includes all DM-RAID disks and excludes all DM-RAID
++       partitions.  */
++    root = dm_tree_find_node (tree, 0, 0);
++    top_handle = NULL;
++    top = dm_tree_next_child (&top_handle, root, 1);
++    while (top)
++      {
++	second_handle = NULL;
++	second = dm_tree_next_child (&second_handle, top, 1);
++	while (second)
++	  {
++	    const char *node_name, *node_uuid;
++	    char *name;
++	    struct dmraid_seen *seen_elt;
++
++	    node_name = dm_tree_node_get_name (second);
++	    dmraid_check (node_name, "dm_tree_node_get_name failed\n");
++	    node_uuid = dm_tree_node_get_uuid (second);
++	    dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n");
++	    if (strncmp (node_uuid, "DMRAID-", 7) != 0)
++	      {
++		grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name);
++		goto dmraid_next_child;
++	      }
++
++	    /* Have we already seen this node?  There are typically very few
++	       DM-RAID disks, so a list should be fast enough.  */
++	    if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), node_name))
++	      {
++		grub_dprintf ("deviceiter", "Already seen DM device %s\n",
++			      node_name);
++		goto dmraid_next_child;
++	      }
++
++	    name = xasprintf ("/dev/mapper/%s", node_name);
++	    if (check_device (name))
++	      {
++		if (hook (name, 0))
++		  {
++		    free (name);
++		    while (seen)
++		      {
++			struct dmraid_seen *seen_elt =
++			  grub_list_pop (GRUB_AS_LIST_P (&seen));
++			free (seen_elt);
++		      }
++		    if (task)
++		      dm_task_destroy (task);
++		    if (tree)
++		      dm_tree_free (tree);
++		    return;
++		  }
++	      }
++	    free (name);
++
++	    seen_elt = xmalloc (sizeof *seen_elt);
++	    seen_elt->name = node_name;
++	    grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt));
++
++dmraid_next_child:
++	    second = dm_tree_next_child (&second_handle, top, 1);
++	  }
++	top = dm_tree_next_child (&top_handle, root, 1);
++      }
++
++dmraid_end:
++    while (seen)
++      {
++	struct dmraid_seen *seen_elt = grub_list_pop (GRUB_AS_LIST_P (&seen));
++	free (seen_elt);
++      }
++    if (task)
++      dm_task_destroy (task);
++    if (tree)
++      dm_tree_free (tree);
++  }
++# endif /* HAVE_DEVICE_MAPPER */
+ #endif /* __linux__ */
+ }
+ 
+diff -Nur -x '*.orig' -x '*~' grub2/util/grub-mkdevicemap.c grub2.new/util/grub-mkdevicemap.c
+--- grub2/util/grub-mkdevicemap.c	2010-02-06 10:32:37.000000000 -0800
++++ grub2.new/util/grub-mkdevicemap.c	2010-02-06 10:33:54.000000000 -0800
+@@ -31,6 +31,7 @@
+ 
+ #include <grub/util/misc.h>
+ #include <grub/util/deviceiter.h>
++#include <grub/env.h>
+ #include <grub/i18n.h>
+ 
+ #define _GNU_SOURCE	1
+@@ -38,6 +39,24 @@
+ 
+ #include "progname.h"
+ 
++void
++grub_putchar (int c)
++{
++  putchar (c);
++}
++
++int
++grub_getkey (void)
++{
++  return -1;
++}
++
++void
++grub_refresh (void)
++{
++  fflush (stdout);
++}
++
+ static void
+ make_device_map (const char *device_map, int floppy_disks)
+ {
+@@ -158,6 +177,9 @@
+ 	  }
+     }
+ 
++  if (verbosity > 1)
++    grub_env_set ("debug", "all");
++
+   make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks);
+ 
+   free (dev_map);
+diff -Nur -x '*.orig' -x '*~' grub2/util/hostdisk.c grub2.new/util/hostdisk.c
+--- grub2/util/hostdisk.c	2010-02-06 10:32:55.000000000 -0800
++++ grub2.new/util/hostdisk.c	2010-02-06 10:33:54.000000000 -0800
+@@ -97,6 +97,10 @@
+ # include <sys/disk.h>
+ #endif
+ 
++#ifdef HAVE_DEVICE_MAPPER
++# include <libdevmapper.h>
++#endif
++
+ struct
+ {
+   char *drive;
+@@ -253,6 +257,115 @@
+   return GRUB_ERR_NONE;
+ }
+ 
++#ifdef HAVE_DEVICE_MAPPER
++static int
++device_is_mapped (const char *dev)
++{
++  struct stat st;
++
++  if (stat (dev, &st) < 0)
++    return 0;
++
++  return dm_is_dm_major (major (st.st_rdev));
++}
++#endif /* HAVE_DEVICE_MAPPER */
++
++#if defined(__linux__) || defined(__CYGWIN__)
++static grub_disk_addr_t
++find_partition_start (const char *dev)
++{
++  int fd;
++  struct hd_geometry hdg;
++
++#ifdef HAVE_DEVICE_MAPPER
++  if (device_is_mapped (dev)) {
++    struct dm_task *task = NULL;
++    grub_uint64_t start, length;
++    char *target_type, *params, *space;
++    grub_disk_addr_t partition_start;
++
++    /* If any device-mapper operation fails, we fall back silently to
++       HDIO_GETGEO.  */
++    task = dm_task_create (DM_DEVICE_TABLE);
++    if (! task)
++      {
++	grub_dprintf ("hostdisk", "dm_task_create failed\n");
++	goto devmapper_fail;
++      }
++
++    if (! dm_task_set_name (task, dev))
++      {
++	grub_dprintf ("hostdisk", "dm_task_set_name failed\n");
++	goto devmapper_fail;
++      }
++
++    if (! dm_task_run (task))
++      {
++	grub_dprintf ("hostdisk", "dm_task_run failed\n");
++	goto devmapper_fail;
++      }
++
++    dm_get_next_target (task, NULL, &start, &length, &target_type, &params);
++    if (! target_type)
++      {
++	grub_dprintf ("hostdisk", "no dm target\n");
++	goto devmapper_fail;
++      }
++    if (strcmp (target_type, "linear") != 0)
++      {
++	grub_dprintf ("hostdisk", "ignoring dm target %s (not linear)\n",
++		      target_type);
++	goto devmapper_fail;
++      }
++    if (! params)
++      {
++	grub_dprintf ("hostdisk", "no dm params\n");
++	goto devmapper_fail;
++      }
++
++    /* The params string for a linear target looks like this:
++         DEVICE-NAME START-SECTOR
++       Parse this out.  */
++    space = strchr (params, ' ');
++    if (! space)
++      goto devmapper_fail;
++    errno = 0;
++    partition_start = strtoull (space + 1, NULL, 10);
++    if (errno == 0)
++      {
++	grub_dprintf ("hostdisk", "dm %s starts at %llu\n",
++		      dev, partition_start);
++	dm_task_destroy (task);
++	return partition_start;
++      }
++
++devmapper_fail:
++    if (task)
++      dm_task_destroy (task);
++  }
++#endif /* HAVE_DEVICE_MAPPER */
++
++  fd = open (dev, O_RDONLY);
++  if (fd == -1)
++    {
++      grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", dev);
++      return 0;
++    }
++
++  if (ioctl (fd, HDIO_GETGEO, &hdg))
++    {
++      grub_error (GRUB_ERR_BAD_DEVICE,
++		  "cannot get geometry of `%s'", dev);
++      close (fd);
++      return 0;
++    }
++
++  close (fd);
++
++  return hdg.start;
++}
++#endif /* __linux__ || __CYGWIN__ */
++
+ #ifdef __linux__
+ static int
+ linux_find_partition (char *dev, unsigned long sector)
+@@ -284,22 +397,20 @@
+   for (i = 1; i < 10000; i++)
+     {
+       int fd;
+-      struct hd_geometry hdg;
++      grub_disk_addr_t start;
+ 
+       sprintf (p, format, i);
++
+       fd = open (real_dev, O_RDONLY);
+       if (fd == -1)
+ 	return 0;
+-
+-      if (ioctl (fd, HDIO_GETGEO, &hdg))
+-	{
+-	  close (fd);
+-	  return 0;
+-	}
+-
+       close (fd);
+ 
+-      if (hdg.start == sector)
++      start = find_partition_start (real_dev);
++      /* We don't care about errors here.  */
++      grub_errno = GRUB_ERR_NONE;
++
++      if (start == sector)
+ 	{
+ 	  strcpy (dev, real_dev);
+ 	  return 1;
+@@ -711,7 +822,7 @@
+ }
+ 
+ static char *
+-convert_system_partition_to_system_disk (const char *os_dev)
++convert_system_partition_to_system_disk (const char *os_dev, struct stat *st)
+ {
+ #if defined(__linux__)
+   char *path = xmalloc (PATH_MAX);
+@@ -829,6 +940,96 @@
+ 	  p[4] = '\0';
+ 	  return path;
+ 	}
++
++#ifdef HAVE_DEVICE_MAPPER
++      /* If this is a DM-RAID device.  */
++      if ((strncmp ("mapper/", p, 7) == 0))
++	{
++	  static struct dm_tree *tree = NULL;
++	  uint32_t maj, min;
++	  struct dm_tree_node *node, *child;
++	  void *handle;
++	  const char *node_uuid, *mapper_name, *child_uuid, *child_name;
++
++	  if (! tree)
++	    tree = dm_tree_create ();
++
++	  if (! tree)
++	    {
++	      grub_dprintf ("hostdisk", "dm_tree_create failed\n");
++	      return NULL;
++	    }
++
++	  maj = major (st->st_rdev);
++	  min = minor (st->st_rdev);
++	  if (! dm_tree_add_dev (tree, maj, min))
++	    {
++	      grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n");
++	      return NULL;
++	    }
++
++	  node = dm_tree_find_node (tree, maj, min);
++	  if (! node)
++	    {
++	      grub_dprintf ("hostdisk", "dm_tree_find_node failed\n");
++	      return NULL;
++	    }
++	  node_uuid = dm_tree_node_get_uuid (node);
++	  if (! node_uuid)
++	    {
++	      grub_dprintf ("hostdisk", "%s has no DM uuid\n", path);
++	      return NULL;
++	    }
++	  else if (strncmp (node_uuid, "DMRAID-", 7) != 0)
++	    {
++	      grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path);
++	      return NULL;
++	    }
++
++	  handle = NULL;
++	  mapper_name = NULL;
++	  /* Counter-intuitively, device-mapper refers to the disk-like
++	     device containing a DM-RAID partition device as a "child" of
++	     the partition device.  */
++	  child = dm_tree_next_child (&handle, node, 0);
++	  if (! child)
++	    {
++	      grub_dprintf ("hostdisk", "%s has no DM children\n", path);
++	      goto devmapper_out;
++	    }
++	  child_uuid = dm_tree_node_get_uuid (child);
++	  if (! child_uuid)
++	    {
++	      grub_dprintf ("hostdisk", "%s child has no DM uuid\n", path);
++	      goto devmapper_out;
++	    }
++	  else if (strncmp (child_uuid, "DMRAID-", 7) != 0)
++	    {
++	      grub_dprintf ("hostdisk", "%s child is not DM-RAID\n", path);
++	      goto devmapper_out;
++	    }
++	  child_name = dm_tree_node_get_name (child);
++	  if (! child_name)
++	    {
++	      grub_dprintf ("hostdisk", "%s child has no DM name\n", path);
++	      goto devmapper_out;
++	    }
++	  mapper_name = child_name;
++
++devmapper_out:
++	  if (! mapper_name)
++	    {
++	      /* This is a DM-RAID disk, not a partition.  */
++	      mapper_name = dm_tree_node_get_name (node);
++	      if (! mapper_name)
++		{
++		  grub_dprintf ("hostdisk", "%s has no DM name\n", path);
++		  return NULL;
++		}
++	    }
++	  return xasprintf ("/dev/mapper/%s", mapper_name);
++	}
++#endif /* HAVE_DEVICE_MAPPER */
+     }
+ 
+   return path;
+@@ -884,12 +1085,12 @@
+ #endif
+ 
+ static int
+-find_system_device (const char *os_dev)
++find_system_device (const char *os_dev, struct stat *st)
+ {
+   unsigned int i;
+   char *os_disk;
+ 
+-  os_disk = convert_system_partition_to_system_disk (os_dev);
++  os_disk = convert_system_partition_to_system_disk (os_dev, st);
+   if (! os_disk)
+     return -1;
+ 
+@@ -923,7 +1124,7 @@
+       return 0;
+     }
+ 
+-  drive = find_system_device (os_dev);
++  drive = find_system_device (os_dev, &st);
+   if (drive < 0)
+     {
+       grub_error (GRUB_ERR_BAD_DEVICE,
+@@ -931,8 +1132,8 @@
+       return 0;
+     }
+ 
+-  if (grub_strcmp (os_dev, convert_system_partition_to_system_disk (os_dev))
+-      == 0)
++  if (grub_strcmp (os_dev,
++		   convert_system_partition_to_system_disk (os_dev, &st)) == 0)
+     return make_device_name (drive, -1, -1);
+ 
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)
+@@ -954,8 +1155,7 @@
+   {
+     char *name;
+     grub_disk_t disk;
+-    int fd;
+-    struct hd_geometry hdg;
++    grub_disk_addr_t start;
+     int dos_part = -1;
+     int bsd_part = -1;
+     auto int find_partition (grub_disk_t disk,
+@@ -985,7 +1185,7 @@
+ 			      partition->index, partition->start);
+ 	  }
+ 
+-	if (hdg.start == partition->start)
++	if (start == partition->start)
+ 	  {
+ 	    if (pcdata)
+ 	      {
+@@ -1008,28 +1208,16 @@
+     if (MAJOR (st.st_rdev) == FLOPPY_MAJOR)
+       return name;
+ 
+-    fd = open (os_dev, O_RDONLY);
+-    if (fd == -1)
+-      {
+-	grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", os_dev);
+-	free (name);
+-	return 0;
+-      }
+-
+-    if (ioctl (fd, HDIO_GETGEO, &hdg))
++    start = find_partition_start (os_dev);
++    if (grub_errno != GRUB_ERR_NONE)
+       {
+-	grub_error (GRUB_ERR_BAD_DEVICE,
+-		    "cannot get geometry of `%s'", os_dev);
+-	close (fd);
+ 	free (name);
+ 	return 0;
+       }
+ 
+-    close (fd);
+-
+-    grub_util_info ("%s starts from %lu", os_dev, hdg.start);
++    grub_util_info ("%s starts from %lu", os_dev, start);
+ 
+-    if (hdg.start == 0 && device_is_wholedisk (os_dev))
++    if (start == 0 && device_is_wholedisk (os_dev))
+       return name;
+ 
+     grub_util_info ("opening the device %s", name);

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/962_no_device_map.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/962_no_device_map.diff
new file mode 100644
index 0000000..c129254
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/962_no_device_map.diff
@@ -0,0 +1,112 @@
+Ubuntu: Don't generate a device map by default.
+
+diff -Nur -x '*.orig' -x '*~' grub2/util/grub-install.in grub2.new/util/grub-install.in
+--- grub2/util/grub-install.in	2010-03-22 14:11:42.000000000 +0000
++++ grub2.new/util/grub-install.in	2010-03-22 16:23:14.000000000 +0000
+@@ -39,7 +39,6 @@
+ else
+     grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}`
+ fi
+-grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
+ grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
+ grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}`
+ rootdir=
+@@ -74,7 +73,6 @@
+                           instead of the root directory
+   --grub-setup=FILE       use FILE as grub-setup
+   --grub-mkimage=FILE     use FILE as grub-mkimage
+-  --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap
+   --grub-probe=FILE       use FILE as grub-probe
+   --no-floppy             do not probe any floppy drive
+   --recheck               probe a device map even if it already exists
+@@ -124,7 +122,7 @@
+     --grub-mkimage=*)
+ 	grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;;
+     --grub-mkdevicemap=*)
+-	grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;;
++	: ;; # compatibility only
+     --grub-probe=*)
+ 	grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;;
+     --no-floppy)
+@@ -209,14 +207,6 @@
+     exit 1
+ fi
+ 
+-set $grub_mkdevicemap dummy
+-if test -f "$1"; then
+-    :
+-else
+-    echo "$1: Not found." 1>&2
+-    exit 1
+-fi
+-
+ # Create the GRUB directory if it is not present.
+ test -d "$bootdir" || mkdir "$bootdir" || exit 1
+ test -d "$grubdir" || mkdir "$grubdir" || exit 1
+@@ -226,22 +216,14 @@
+     rm -f $device_map
+ fi
+ 
+-# Create the device map file if it is not present.
++# Make sure that there is no duplicated entry in the device map.
+ if test -f "$device_map"; then
+-    :
+-else
+-    # Create a safe temporary file.
+-    test -n "$mklog" && log_file=`$mklog`
+-
+-    $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1
+-fi
+-
+-# Make sure that there is no duplicated entry.
+-tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
+-    | sort | uniq -d | sed -n 1p`
+-if test -n "$tmp"; then
+-    echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
+-    exit 1
++    tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \
++	| sort | uniq -d | sed -n 1p`
++    if test -n "$tmp"; then
++	echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2
++	exit 1
++    fi
+ fi
+ 
+ # Copy the GRUB images to the GRUB directory.
+diff -Nur -x '*.orig' -x '*~' grub2/util/grub-mkconfig.in grub2.new/util/grub-mkconfig.in
+--- grub2/util/grub-mkconfig.in	2010-03-22 16:23:13.000000000 +0000
++++ grub2.new/util/grub-mkconfig.in	2010-03-22 16:23:57.000000000 +0000
+@@ -31,7 +31,6 @@
+ grub_cfg=""
+ grub_mkconfig_dir=${sysconfdir}/grub.d
+ 
+-grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
+ grub_probe=${sbindir}/`echo grub-probe | sed ${transform}`
+ 
+ # Usage: usage
+@@ -96,14 +95,6 @@
+   fi
+ fi
+ 
+-set $grub_mkdevicemap dummy
+-if test -f "$1"; then
+-    :
+-else
+-    echo "$1: Not found." 1>&2
+-    exit 1
+-fi
+-
+ set $grub_probe dummy
+ if test -f "$1"; then
+     :
+@@ -114,10 +105,6 @@
+ 
+ mkdir -p ${grub_prefix}
+ 
+-if test -e ${grub_prefix}/device.map ; then : ; else
+-  ${grub_mkdevicemap}
+-fi
+-
+ # Device containing our userland.  Typically used for root= parameter.
+ GRUB_DEVICE="`${grub_probe} --target=device /`"
+ GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/968_hostdisk_speedup.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/968_hostdisk_speedup.diff
new file mode 100644
index 0000000..30ebcbe
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/968_hostdisk_speedup.diff
@@ -0,0 +1,310 @@
+Upstream: http://lists.gnu.org/archive/html/grub-devel/2010-03/msg00008.html
+Description: Optimise hostdisk device handling
+ This substantially speeds up grub-probe filesystem reads.
+
+diff -Nur -x '*.orig' -x '*~' grub2/ChangeLog.hostdisk-speedup grub2.new/ChangeLog.hostdisk-speedup
+--- grub2/ChangeLog.hostdisk-speedup	1970-01-01 01:00:00.000000000 +0100
++++ grub2.new/ChangeLog.hostdisk-speedup	2010-03-03 10:43:43.000000000 +0000
+@@ -0,0 +1,18 @@
++2010-03-03  Colin Watson  <cjwatson@ubuntu.com>
++
++	* util/hostdisk.c (struct grub_util_biosdisk_data): New structure.
++	(grub_util_biosdisk_open): Initialise disk->data.
++	(struct linux_partition_cache): New structure.
++	(linux_find_partition): Cache partition start positions; these are
++	expensive to compute on every read and write.
++	(open_device): Cache open file descriptor in disk->data, so that we
++	don't have to reopen it and flush the buffer cache for consecutive
++	operations on the same device.
++	(grub_util_biosdisk_close): New function.
++	(grub_util_biosdisk_dev): Set `close' member.
++
++	* conf/common.rmk (grub_probe_SOURCES): Add kern/list.c.
++	* conf/i386-efi.rmk (grub_setup_SOURCES): Likewise.
++	* conf/i386-pc.rmk (grub_setup_SOURCES): Likewise.
++	* conf/sparc64-ieee1275.rmk (grub_setup_SOURCES): Likewise.
++	* conf/x86_64-efi.rmk (grub_setup_SOURCES): Likewise.
+diff -Nur -x '*.orig' -x '*~' grub2/conf/common.rmk grub2.new/conf/common.rmk
+--- grub2/conf/common.rmk	2010-03-03 20:11:04.000000000 +0000
++++ grub2.new/conf/common.rmk	2010-03-03 20:11:05.000000000 +0000
+@@ -25,7 +25,7 @@
+ grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c	\
+ 	util/hostdisk.c	util/misc.c util/getroot.c		\
+ 	kern/device.c kern/disk.c kern/err.c kern/misc.c	\
+-	kern/parser.c kern/partition.c kern/file.c		\
++	kern/parser.c kern/partition.c kern/file.c kern/list.c	\
+ 	\
+ 	fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c		\
+ 	fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c	\
+diff -Nur -x '*.orig' -x '*~' grub2/conf/i386-efi.rmk grub2.new/conf/i386-efi.rmk
+--- grub2/conf/i386-efi.rmk	2010-03-03 20:08:04.000000000 +0000
++++ grub2.new/conf/i386-efi.rmk	2010-03-03 20:11:05.000000000 +0000
+@@ -21,7 +21,7 @@
+ #	kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c	\
+ #	fs/sfs.c kern/parser.c kern/partition.c partmap/msdos.c		\
+ #	fs/ufs.c fs/ufs2.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c	\
+-#	kern/fs.c kern/env.c fs/fshelp.c
++#	kern/fs.c kern/env.c kern/list.c fs/fshelp.c
+ 
+ # Scripts.
+ sbin_SCRIPTS = grub-install
+diff -Nur -x '*.orig' -x '*~' grub2/conf/i386-pc.rmk grub2.new/conf/i386-pc.rmk
+--- grub2/conf/i386-pc.rmk	2010-03-03 20:08:04.000000000 +0000
++++ grub2.new/conf/i386-pc.rmk	2010-03-03 20:11:05.000000000 +0000
+@@ -96,7 +96,8 @@
+ 	util/i386/pc/grub-setup.c util/hostdisk.c	\
+ 	util/misc.c util/getroot.c kern/device.c kern/disk.c	\
+ 	kern/err.c kern/misc.c kern/parser.c kern/partition.c	\
+-	kern/file.c kern/fs.c kern/env.c fs/fshelp.c		\
++	kern/file.c kern/fs.c kern/env.c kern/list.c		\
++	fs/fshelp.c						\
+ 	\
+ 	fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c		\
+ 	fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c	\
+diff -Nur -x '*.orig' -x '*~' grub2/conf/sparc64-ieee1275.rmk grub2.new/conf/sparc64-ieee1275.rmk
+--- grub2/conf/sparc64-ieee1275.rmk	2010-03-03 20:08:04.000000000 +0000
++++ grub2.new/conf/sparc64-ieee1275.rmk	2010-03-03 20:11:05.000000000 +0000
+@@ -70,7 +70,8 @@
+ grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c util/hostdisk.c	\
+ 	util/misc.c util/getroot.c kern/device.c kern/disk.c	\
+ 	kern/err.c kern/misc.c kern/parser.c kern/partition.c	\
+-	kern/file.c kern/fs.c kern/env.c fs/fshelp.c		\
++	kern/file.c kern/fs.c kern/env.c kern/list.c		\
++	fs/fshelp.c						\
+ 	\
+ 	fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c		\
+ 	fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c	\
+diff -Nur -x '*.orig' -x '*~' grub2/conf/x86_64-efi.rmk grub2.new/conf/x86_64-efi.rmk
+--- grub2/conf/x86_64-efi.rmk	2010-03-03 20:08:04.000000000 +0000
++++ grub2.new/conf/x86_64-efi.rmk	2010-03-03 20:11:05.000000000 +0000
+@@ -20,7 +20,7 @@
+ #	kern/err.c kern/misc.c fs/fat.c fs/ext2.c fs/xfs.c fs/affs.c	\
+ #	fs/sfs.c kern/parser.c kern/partition.c partmap/msdos.c		\
+ #	fs/ufs.c fs/ufs2.c fs/minix.c fs/hfs.c fs/jfs.c fs/hfsplus.c kern/file.c	\
+-#	kern/fs.c kern/env.c fs/fshelp.c
++#	kern/fs.c kern/env.c kern/list.c fs/fshelp.c
+ 
+ # Scripts.
+ sbin_SCRIPTS = grub-install
+diff -Nur -x '*.orig' -x '*~' grub2/util/hostdisk.c grub2.new/util/hostdisk.c
+--- grub2/util/hostdisk.c	2010-03-03 20:11:04.000000000 +0000
++++ grub2.new/util/hostdisk.c	2010-03-03 20:11:05.000000000 +0000
+@@ -26,6 +26,7 @@
+ #include <grub/util/hostdisk.h>
+ #include <grub/misc.h>
+ #include <grub/i18n.h>
++#include <grub/list.h>
+ 
+ #include <stdio.h>
+ #include <stdlib.h>
+@@ -107,6 +108,13 @@
+   char *device;
+ } map[256];
+ 
++struct grub_util_biosdisk_data
++{
++  char *dev;
++  int access_mode;
++  int fd;
++};
++
+ #ifdef __linux__
+ /* Check if we have devfs support.  */
+ static int
+@@ -169,6 +177,7 @@
+ {
+   int drive;
+   struct stat st;
++  struct grub_util_biosdisk_data *data;
+ 
+   drive = find_grub_drive (name);
+   if (drive < 0)
+@@ -177,6 +186,10 @@
+ 
+   disk->has_partitions = 1;
+   disk->id = drive;
++  disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data));
++  data->dev = NULL;
++  data->access_mode = 0;
++  data->fd = -1;
+ 
+   /* Get the size.  */
+ #if defined(__MINGW32__)
+@@ -367,6 +380,17 @@
+ #endif /* __linux__ || __CYGWIN__ */
+ 
+ #ifdef __linux__
++/* Cache of partition start sectors for each disk.  */
++struct linux_partition_cache
++{
++  struct linux_partition_cache *next;
++  char *dev;
++  unsigned long start;
++  int partno;
++};
++
++struct linux_partition_cache *linux_partition_cache_list;
++
+ static int
+ linux_find_partition (char *dev, unsigned long sector)
+ {
+@@ -375,6 +399,7 @@
+   char *p;
+   int i;
+   char real_dev[PATH_MAX];
++  struct linux_partition_cache *cache;
+ 
+   strcpy(real_dev, dev);
+ 
+@@ -394,6 +419,16 @@
+       format = "%d";
+     }
+ 
++  for (cache = linux_partition_cache_list; cache; cache = cache->next)
++    {
++      if (strcmp (cache->dev, dev) == 0 && cache->start == sector)
++	{
++	  sprintf (p, format, cache->partno);
++	  strcpy (dev, real_dev);
++	  return 1;
++	}
++    }
++
+   for (i = 1; i < 10000; i++)
+     {
+       int fd;
+@@ -412,6 +447,15 @@
+ 
+       if (start == sector)
+ 	{
++	  struct linux_partition_cache *new_cache_item;
++
++	  new_cache_item = xmalloc (sizeof *new_cache_item);
++	  new_cache_item->dev = xstrdup (dev);
++	  new_cache_item->start = start;
++	  new_cache_item->partno = i;
++	  grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list),
++			  GRUB_AS_LIST (new_cache_item));
++
+ 	  strcpy (dev, real_dev);
+ 	  return 1;
+ 	}
+@@ -425,6 +469,7 @@
+ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
+ {
+   int fd;
++  struct grub_util_biosdisk_data *data = disk->data;
+ 
+ #ifdef O_LARGEFILE
+   flags |= O_LARGEFILE;
+@@ -451,18 +496,35 @@
+ 	&& strncmp (map[disk->id].device, "/dev/", 5) == 0)
+       is_partition = linux_find_partition (dev, disk->partition->start);
+ 
+-    /* Open the partition.  */
+-    grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
+-    fd = open (dev, flags);
+-    if (fd < 0)
++    if (data->dev && strcmp (data->dev, dev) == 0 &&
++	data->access_mode == (flags & O_ACCMODE))
+       {
+-	grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev);
+-	return -1;
++	grub_dprintf ("hostdisk", "reusing open device `%s'\n", dev);
++	fd = data->fd;
+       }
++    else
++      {
++	free (data->dev);
++	if (data->fd != -1)
++	  close (data->fd);
++
++	/* Open the partition.  */
++	grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev);
++	fd = open (dev, flags);
++	if (fd < 0)
++	  {
++	    grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev);
++	    return -1;
++	  }
+ 
+-    /* Flush the buffer cache to the physical disk.
+-       XXX: This also empties the buffer cache.  */
+-    ioctl (fd, BLKFLSBUF, 0);
++	/* Flush the buffer cache to the physical disk.
++	   XXX: This also empties the buffer cache.  */
++	ioctl (fd, BLKFLSBUF, 0);
++
++	data->dev = xstrdup (dev);
++	data->access_mode = (flags & O_ACCMODE);
++	data->fd = fd;
++      }
+ 
+     if (is_partition)
+       sector -= disk->partition->start;
+@@ -486,7 +548,26 @@
+     }
+ #endif
+ 
+-  fd = open (map[disk->id].device, flags);
++  if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 &&
++      data->access_mode == (flags & O_ACCMODE))
++    {
++      grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev);
++      fd = data->fd;
++    }
++  else
++    {
++      free (data->dev);
++      if (data->fd != -1)
++	close (data->fd);
++
++      fd = open (map[disk->id].device, flags);
++      if (fd >= 0)
++	{
++	  data->dev = xstrdup (map[disk->id].device);
++	  data->access_mode = (flags & O_ACCMODE);
++	  data->fd = fd;
++	}
++    }
+ 
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
+   if (! (sysctl_oldflags & 0x10)
+@@ -646,7 +727,6 @@
+       != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+     grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
+ 
+-  close (fd);
+   return grub_errno;
+ }
+ 
+@@ -681,17 +761,27 @@
+       != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+     grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
+ 
+-  close (fd);
+   return grub_errno;
+ }
+ 
++static void
++grub_util_biosdisk_close (struct grub_disk *disk)
++{
++  struct grub_util_biosdisk_data *data = disk->data;
++
++  free (data->dev);
++  if (data->fd != -1)
++    close (data->fd);
++  free (data);
++}
++
+ static struct grub_disk_dev grub_util_biosdisk_dev =
+   {
+     .name = "biosdisk",
+     .id = GRUB_DISK_DEVICE_BIOSDISK_ID,
+     .iterate = grub_util_biosdisk_iterate,
+     .open = grub_util_biosdisk_open,
+-    .close = 0,
++    .close = grub_util_biosdisk_close,
+     .read = grub_util_biosdisk_read,
+     .write = grub_util_biosdisk_write,
+     .next = 0

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/969_lvm_raid_probe.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/969_lvm_raid_probe.diff
new file mode 100644
index 0000000..52a5c44
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/969_lvm_raid_probe.diff
@@ -0,0 +1,227 @@
+Description: Fix LVM/RAID probing without device.map
+ When probing LVM or RAID without a device.map, probe all devices in order
+ that we will know about the underlying physical volumes.
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/525085
+Forwarded: http://lists.gnu.org/archive/html/grub-devel/2010-03/msg00084.html
+Last-Update: 2010-03-22
+
+diff -Nur -x '*.orig' -x '*~' grub2/conf/common.rmk grub2.new/conf/common.rmk
+--- grub2/conf/common.rmk	2010-03-22 13:49:14.000000000 +0000
++++ grub2.new/conf/common.rmk	2010-03-22 13:53:20.000000000 +0000
+@@ -24,6 +24,7 @@
+ util/grub-probe.c_DEPENDENCIES = grub_probe_init.h
+ grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c	\
+ 	util/hostdisk.c	util/misc.c util/getroot.c		\
++	util/deviceiter.c					\
+ 	kern/device.c kern/disk.c kern/err.c kern/misc.c	\
+ 	kern/parser.c kern/partition.c kern/file.c kern/list.c	\
+ 	\
+diff -Nur -x '*.orig' -x '*~' grub2/conf/i386-pc.rmk grub2.new/conf/i386-pc.rmk
+--- grub2/conf/i386-pc.rmk	2010-03-22 13:49:14.000000000 +0000
++++ grub2.new/conf/i386-pc.rmk	2010-03-22 13:49:17.000000000 +0000
+@@ -94,7 +94,8 @@
+ util/i386/pc/grub-setup.c_DEPENDENCIES = grub_setup_init.h
+ grub_setup_SOURCES = gnulib/progname.c \
+ 	util/i386/pc/grub-setup.c util/hostdisk.c	\
+-	util/misc.c util/getroot.c kern/device.c kern/disk.c	\
++	util/misc.c util/getroot.c util/deviceiter.c		\
++	kern/device.c kern/disk.c				\
+ 	kern/err.c kern/misc.c kern/parser.c kern/partition.c	\
+ 	kern/file.c kern/fs.c kern/env.c kern/list.c		\
+ 	fs/fshelp.c						\
+diff -Nur -x '*.orig' -x '*~' grub2/conf/sparc64-ieee1275.rmk grub2.new/conf/sparc64-ieee1275.rmk
+--- grub2/conf/sparc64-ieee1275.rmk	2010-03-22 13:49:14.000000000 +0000
++++ grub2.new/conf/sparc64-ieee1275.rmk	2010-03-22 13:49:17.000000000 +0000
+@@ -68,7 +68,8 @@
+ # For grub-setup.
+ util/sparc64/ieee1275/grub-setup.c_DEPENDENCIES = grub_setup_init.h
+ grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c util/hostdisk.c	\
+-	util/misc.c util/getroot.c kern/device.c kern/disk.c	\
++	util/misc.c util/getroot.c util/deviceiter.c		\
++	kern/device.c kern/disk.c				\
+ 	kern/err.c kern/misc.c kern/parser.c kern/partition.c	\
+ 	kern/file.c kern/fs.c kern/env.c kern/list.c		\
+ 	fs/fshelp.c						\
+diff -Nur -x '*.orig' -x '*~' grub2/include/grub/util/hostdisk.h grub2.new/include/grub/util/hostdisk.h
+--- grub2/include/grub/util/hostdisk.h	2010-03-22 13:47:27.000000000 +0000
++++ grub2.new/include/grub/util/hostdisk.h	2010-03-22 13:51:33.000000000 +0000
+@@ -22,6 +22,7 @@
+ 
+ void grub_util_biosdisk_init (const char *dev_map);
+ void grub_util_biosdisk_fini (void);
++int grub_util_biosdisk_probe_device (const char *name, int is_floppy);
+ char *grub_util_biosdisk_get_grub_dev (const char *os_dev);
+ 
+ #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */
+diff -Nur -x '*.orig' -x '*~' grub2/util/grub-probe.c grub2.new/util/grub-probe.c
+--- grub2/util/grub-probe.c	2010-03-22 13:47:27.000000000 +0000
++++ grub2.new/util/grub-probe.c	2010-03-22 13:53:10.000000000 +0000
+@@ -28,6 +28,7 @@
+ #include <grub/msdos_partition.h>
+ #include <grub/util/hostdisk.h>
+ #include <grub/util/getroot.h>
++#include <grub/util/deviceiter.h>
+ #include <grub/term.h>
+ #include <grub/env.h>
+ #include <grub/raid.h>
+@@ -106,13 +107,14 @@
+ }
+ 
+ static void
+-probe (const char *path, char *device_name)
++probe (const char *path, char *device_name, const char *dev_map)
+ {
+   char *drive_name = NULL;
+   char *grub_path = NULL;
+   char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL;
+   grub_device_t dev = NULL;
+   grub_fs_t fs;
++  struct stat dev_map_stat;
+ 
+   if (path == NULL)
+     {
+@@ -136,6 +138,22 @@
+       goto end;
+     }
+ 
++  if (stat (dev_map, &dev_map_stat) == -1 &&
++      grub_util_get_dev_abstraction (device_name) != GRUB_DEV_ABSTRACTION_NONE)
++    {
++      /* If we don't have a device map, then we won't yet know about the
++         physical volumes underlying this device, so probe all devices.  */
++      grub_util_iterate_devices (grub_util_biosdisk_probe_device, 0);
++
++      /* Now reinitialise the higher layers.  */
++      grub_lvm_fini ();
++      grub_mdraid_fini ();
++      grub_raid_fini ();
++      grub_raid_init ();
++      grub_mdraid_init ();
++      grub_lvm_init ();
++    }
++
+   drive_name = grub_util_get_grub_dev (device_name);
+   if (! drive_name)
+     grub_util_error ("cannot find a GRUB drive for %s.  Check your device.map", device_name);
+@@ -428,9 +446,9 @@
+ 
+   /* Do it.  */
+   if (argument_is_device)
+-    probe (NULL, argument);
++    probe (NULL, argument, dev_map ? : DEFAULT_DEVICE_MAP);
+   else
+-    probe (argument, NULL);
++    probe (argument, NULL, dev_map ? : DEFAULT_DEVICE_MAP);
+ 
+   /* Free resources.  */
+   grub_fini_all ();
+diff -Nur -x '*.orig' -x '*~' grub2/util/hostdisk.c grub2.new/util/hostdisk.c
+--- grub2/util/hostdisk.c	2010-03-22 13:49:14.000000000 +0000
++++ grub2.new/util/hostdisk.c	2010-03-22 13:51:53.000000000 +0000
+@@ -1237,6 +1237,48 @@
+   return i;
+ }
+ 
++static void
++store_grub_dev (const char *grub_disk, const char *os_disk)
++{
++  unsigned int i;
++
++  for (i = 0; i < ARRAY_SIZE (map); i++)
++    if (! map[i].device)
++      break;
++    else if (strcmp (map[i].drive, grub_disk) == 0)
++      {
++	if (strcmp (map[i].device, os_disk) == 0)
++	  return;
++	grub_util_error (_("drive `%s' already mapped to `%s'"),
++			 map[i].drive, map[i].device);
++      }
++
++  if (i == ARRAY_SIZE (map))
++    grub_util_error (_("device count exceeds limit"));
++
++  map[i].drive = xstrdup (grub_disk);
++  map[i].device = xstrdup (os_disk);
++}
++
++static int num_hd = 0;
++static int num_fd = 0;
++
++int
++grub_util_biosdisk_probe_device (const char *name, int is_floppy)
++{
++  char *grub_disk;
++
++  if (is_floppy)
++    grub_disk = xasprintf ("fd%d", num_fd++);
++  else
++    grub_disk = xasprintf ("hd%d", num_hd++);
++
++  store_grub_dev (grub_disk, name);
++  free (grub_disk);
++
++  return 0;
++}
++
+ char *
+ grub_util_biosdisk_get_grub_dev (const char *os_dev)
+ {
+diff -Nur -x '*.orig' -x '*~' grub2/util/i386/pc/grub-setup.c grub2.new/util/i386/pc/grub-setup.c
+--- grub2/util/i386/pc/grub-setup.c	2010-03-22 13:49:13.000000000 +0000
++++ grub2.new/util/i386/pc/grub-setup.c	2010-03-22 13:53:10.000000000 +0000
+@@ -36,6 +36,7 @@
+ #include <grub/util/raid.h>
+ #include <grub/util/lvm.h>
+ #include <grub/util/getroot.h>
++#include <grub/util/deviceiter.h>
+ 
+ static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT;
+ 
+@@ -646,6 +647,7 @@
+   char *core_file = 0;
+   char *dir = 0;
+   char *dev_map = 0;
++  struct stat dev_map_stat;
+   char *root_dev = 0;
+   char *dest_dev;
+   int must_embed = 0, force = 0, fs_probe = 1;
+@@ -744,6 +746,9 @@
+   /* Initialize the emulated biosdisk driver.  */
+   grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP);
+ 
++  if (stat (dev_map ? : DEFAULT_DEVICE_MAP, &dev_map_stat) == -1)
++    grub_util_iterate_devices (grub_util_biosdisk_probe_device, 0);
++
+   /* Initialize all modules. */
+   grub_init_all ();
+ 
+diff -Nur -x '*.orig' -x '*~' grub2/util/sparc64/ieee1275/grub-setup.c grub2.new/util/sparc64/ieee1275/grub-setup.c
+--- grub2/util/sparc64/ieee1275/grub-setup.c	2010-03-22 13:47:27.000000000 +0000
++++ grub2.new/util/sparc64/ieee1275/grub-setup.c	2010-03-22 13:53:10.000000000 +0000
+@@ -46,6 +46,7 @@
+ #include <sys/stat.h>
+ #include <dirent.h>
+ #include <grub/util/getroot.h>
++#include <grub/util/deviceiter.h>
+ 
+ #define _GNU_SOURCE	1
+ #include <getopt.h>
+@@ -618,6 +619,7 @@
+ main (int argc, char *argv[])
+ {
+   struct grub_setup_info ginfo;
++  struct stat dev_map_stat;
+ 
+   set_program_name (argv[0]);
+ 
+@@ -630,6 +632,9 @@
+   /* Initialize the emulated biosdisk driver.  */
+   grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP);
+ 
++  if (stat (ginfo.dev_map ? : DEFAULT_DEVICE_MAP, &dev_map_stat) == -1)
++    grub_util_iterate_devices (grub_util_biosdisk_probe_device, 0);
++
+   /* Initialize all modules. */
+   grub_init_all ();
+ 

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/970_fix_locale_installation.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/970_fix_locale_installation.diff
new file mode 100644
index 0000000..ab20288
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/970_fix_locale_installation.diff
@@ -0,0 +1,55 @@
+Description: Copy .mo files from @datadir@/locale
+ This matches where 'make install' puts them.
+Origin: upstream, http://bazaar.launchpad.net/~vcs-imports/grub/grub2-bzr/revision/2265
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/537998
+Forwarded: http://lists.gnu.org/archive/html/grub-devel/2010-03/msg00074.html
+Last-Update: 2010-03-22
+
+diff -Nur -x '*.orig' -x '*~' grub2/util/grub-install.in grub2.new/util/grub-install.in
+--- grub2/util/grub-install.in	2010-03-22 15:49:32.000000000 +0000
++++ grub2.new/util/grub-install.in	2010-03-22 15:54:31.000000000 +0000
+@@ -32,6 +32,7 @@
+ host_os=@host_os@
+ font=@datadir@/@PACKAGE_TARNAME@/ascii.pf2
+ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
++localedir=@datadir@/locale
+ 
+ grub_setup=${sbindir}/`echo grub-setup | sed ${transform}`
+ if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] || [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then
+@@ -245,9 +246,9 @@
+ 
+ # Copy gettext files
+ mkdir -p ${grubdir}/locale/
+-for file in ${grubdir}/locale/*.mo ${pkglibdir}/locale/*.mo; do
+-    if test -f "$file"; then
+-        cp -f "$file" ${grubdir}/locale/
++for dir in ${localedir}/*; do
++    if test -f "$dir/LC_MESSAGES/grub.mo"; then
++        cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo"
+     fi
+ done
+ 
+diff -Nur -x '*.orig' -x '*~' grub2/util/i386/efi/grub-install.in grub2.new/util/i386/efi/grub-install.in
+--- grub2/util/i386/efi/grub-install.in	2010-03-09 16:14:00.000000000 +0000
++++ grub2.new/util/i386/efi/grub-install.in	2010-03-22 15:54:31.000000000 +0000
+@@ -31,6 +31,7 @@
+ platform=@platform@
+ host_os=@host_os@
+ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`
++localedir=@datadir@/locale
+ 
+ grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}`
+ grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}`
+@@ -182,9 +183,9 @@
+ 
+ # Copy gettext files
+ mkdir -p ${grubdir}/locale/
+-for file in ${grubdir}/locale/*.mo ${pkglibdir}/locale/*.mo; do
+-    if test -f "$file"; then
+-        cp -f "$file" ${grubdir}/locale/
++for dir in ${localedir}/*; do
++    if test -f "$dir/LC_MESSAGES/grub.mo"; then
++        cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo"
+     fi
+ done
+ 

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/971_langpacks.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/971_langpacks.diff
new file mode 100644
index 0000000..7e1cb89
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/971_langpacks.diff
@@ -0,0 +1,30 @@
+Description: Prefer translations from language packs
+Author: Colin Watson <cjwatson@ubuntu.com>
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/537998
+Forwarded: not-needed
+Last-Update: 2010-03-22
+
+diff -Nur -x '*.orig' -x '*~' grub2/util/grub-install.in grub2.new/util/grub-install.in
+--- grub2/util/grub-install.in	2010-03-22 15:58:16.000000000 +0000
++++ grub2.new/util/grub-install.in	2010-03-22 15:59:04.000000000 +0000
+@@ -246,7 +246,7 @@
+ 
+ # Copy gettext files
+ mkdir -p ${grubdir}/locale/
+-for dir in ${localedir}/*; do
++for dir in ${localedir}/* ${localedir}-langpack/*; do
+     if test -f "$dir/LC_MESSAGES/grub.mo"; then
+         cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo"
+     fi
+diff -Nur -x '*.orig' -x '*~' grub2/util/i386/efi/grub-install.in grub2.new/util/i386/efi/grub-install.in
+--- grub2/util/i386/efi/grub-install.in	2010-03-22 15:58:16.000000000 +0000
++++ grub2.new/util/i386/efi/grub-install.in	2010-03-22 15:59:17.000000000 +0000
+@@ -183,7 +183,7 @@
+ 
+ # Copy gettext files
+ mkdir -p ${grubdir}/locale/
+-for dir in ${localedir}/*; do
++for dir in ${localedir}/* ${localedir}-langpack/*; do
+     if test -f "$dir/LC_MESSAGES/grub.mo"; then
+         cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo"
+     fi

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/974_drive_probe.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/974_drive_probe.diff
new file mode 100644
index 0000000..0c9f364
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/974_drive_probe.diff
@@ -0,0 +1,23 @@
+Description: Probe all devices if we've been asked for a drive name
+ This allows --target=drive to work properly even without a device.map.
+ .
+ Depends on 969_lvm_raid_probe.diff.
+Author: Colin Watson <cjwatson@ubuntu.com>
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/549980
+Forwarded: no
+Last-Update: 2010-04-08
+
+diff -Nur -x '*.orig' -x '*~' grub2/util/grub-probe.c grub2.new/util/grub-probe.c
+--- grub2/util/grub-probe.c	2010-04-08 12:02:36.000000000 +0100
++++ grub2.new/util/grub-probe.c	2010-04-08 12:04:05.000000000 +0100
+@@ -139,7 +139,9 @@
+     }
+ 
+   if (stat (dev_map, &dev_map_stat) == -1 &&
+-      grub_util_get_dev_abstraction (device_name) != GRUB_DEV_ABSTRACTION_NONE)
++      (print == PRINT_DRIVE ||
++       grub_util_get_dev_abstraction (device_name) !=
++	 GRUB_DEV_ABSTRACTION_NONE))
+     {
+       /* If we don't have a device map, then we won't yet know about the
+          physical volumes underlying this device, so probe all devices.  */

diff --git a/sys-boot/grub/files/ubuntu-upstream-1.98/975_hostdisk_hd.diff b/sys-boot/grub/files/ubuntu-upstream-1.98/975_hostdisk_hd.diff
new file mode 100644
index 0000000..7ea7f5f
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream-1.98/975_hostdisk_hd.diff
@@ -0,0 +1,114 @@
+Description: Adjust hostdisk id for hard disks
+ This allows grub-setup to use its standard workaround for broken BIOSes.
+Author: Colin Watson <cjwatson@ubuntu.com>
+Bug: http://savannah.gnu.org/bugs/?29464
+Bug-Ubuntu: https://bugs.launchpad.net/bugs/555500
+Forwarded: http://savannah.gnu.org/bugs/?29464
+Last-Update: 2010-04-08
+
+diff -Nur -x '*.orig' -x '*~' grub2/util/hostdisk.c grub2.new/util/hostdisk.c
+--- grub2/util/hostdisk.c	2010-04-08 17:09:02.000000000 +0100
++++ grub2.new/util/hostdisk.c	2010-04-08 17:10:18.000000000 +0100
+@@ -186,6 +186,8 @@
+ 
+   disk->has_partitions = 1;
+   disk->id = drive;
++  if (strncmp (map[drive].drive, "hd", 2) == 0)
++    disk->id += 0x80;
+   disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data));
+   data->dev = NULL;
+   data->access_mode = 0;
+@@ -491,9 +493,9 @@
+     int is_partition = 0;
+     char dev[PATH_MAX];
+ 
+-    strcpy (dev, map[disk->id].device);
++    strcpy (dev, map[disk->id & 0x7f].device);
+     if (disk->partition && sector >= disk->partition->start
+-	&& strncmp (map[disk->id].device, "/dev/", 5) == 0)
++	&& strncmp (map[disk->id & 0x7f].device, "/dev/", 5) == 0)
+       is_partition = linux_find_partition (dev, disk->partition->start);
+ 
+     if (data->dev && strcmp (data->dev, dev) == 0 &&
+@@ -548,7 +550,7 @@
+     }
+ #endif
+ 
+-  if (data->dev && strcmp (data->dev, map[disk->id].device) == 0 &&
++  if (data->dev && strcmp (data->dev, map[disk->id & 0x7f].device) == 0 &&
+       data->access_mode == (flags & O_ACCMODE))
+     {
+       grub_dprintf ("hostdisk", "reusing open device `%s'\n", data->dev);
+@@ -560,10 +562,10 @@
+       if (data->fd != -1)
+ 	close (data->fd);
+ 
+-      fd = open (map[disk->id].device, flags);
++      fd = open (map[disk->id & 0x7f].device, flags);
+       if (fd >= 0)
+ 	{
+-	  data->dev = xstrdup (map[disk->id].device);
++	  data->dev = xstrdup (map[disk->id & 0x7f].device);
+ 	  data->access_mode = (flags & O_ACCMODE);
+ 	  data->fd = fd;
+ 	}
+@@ -581,12 +583,12 @@
+ #if defined(__APPLE__)
+   /* If we can't have exclusive access, try shared access */
+   if (fd < 0)
+-    fd = open(map[disk->id].device, flags | O_SHLOCK);
++    fd = open(map[disk->id & 0x7f].device, flags | O_SHLOCK);
+ #endif
+ 
+   if (fd < 0)
+     {
+-      grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' in open_device()", map[disk->id].device);
++      grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' in open_device()", map[disk->id & 0x7f].device);
+       return -1;
+     }
+ #endif /* ! __linux__ */
+@@ -604,7 +606,7 @@
+     offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
+     if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
+       {
+-	grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
++	grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id & 0x7f].device);
+ 	close (fd);
+ 	return -1;
+       }
+@@ -615,7 +617,7 @@
+ 
+     if (lseek (fd, offset, SEEK_SET) != offset)
+       {
+-	grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
++	grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id & 0x7f].device);
+ 	close (fd);
+ 	return -1;
+       }
+@@ -713,7 +715,7 @@
+ 	 parts. -jochen  */
+       if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
+ 	{
+-	  grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
++	  grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id & 0x7f].device);
+ 	  close (fd);
+ 	  return grub_errno;
+ 	}
+@@ -725,7 +727,7 @@
+ 
+   if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
+       != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+-    grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
++    grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id & 0x7f].device);
+ 
+   return grub_errno;
+ }
+@@ -759,7 +761,7 @@
+ 
+   if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
+       != (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
+-    grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
++    grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id & 0x7f].device);
+ 
+   return grub_errno;
+ }

diff --git a/sys-boot/grub/files/ubuntu-upstream/01_uuids_and_lvm_dont_play_along_nicely.diff b/sys-boot/grub/files/ubuntu-upstream/01_uuids_and_lvm_dont_play_along_nicely.diff
new file mode 100644
index 0000000..c997b84
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream/01_uuids_and_lvm_dont_play_along_nicely.diff
@@ -0,0 +1,14 @@
+diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in
+index c2da413..cbd9d6b 100644
+--- a/util/grub.d/10_linux.in
++++ b/util/grub.d/10_linux.in
+@@ -36,7 +36,8 @@ case ${GRUB_DEVICE} in
+ esac
+
+ if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \
+-    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then
++    || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" \
++    || [ "`grub-probe -t abstraction --device ${GRUB_DEVICE} | sed -e 's,.*\(lvm\).*,\1,'`" = "lvm"  ] ; then
+   LINUX_ROOT_DEVICE=${GRUB_DEVICE}
+ else
+   LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID}

diff --git a/sys-boot/grub/files/ubuntu-upstream/904_disable_floppies.diff b/sys-boot/grub/files/ubuntu-upstream/904_disable_floppies.diff
new file mode 100644
index 0000000..66a41cd
--- /dev/null
+++ b/sys-boot/grub/files/ubuntu-upstream/904_disable_floppies.diff
@@ -0,0 +1,28 @@
+
+Author: Robert Millan
+
+An ugly kludge.  Should this be merged upstream?
+
+Index: util/hostdisk.c
+===================================================================
+--- util/hostdisk.c	(revision 1832)
++++ util/hostdisk.c	(working copy)
+@@ -544,6 +544,18 @@
+ 	  continue;
+ 	}
+
++      if (! strncmp (p, "/dev/fd", sizeof ("/dev/fd") - 1))
++	{
++	  char *q = p + sizeof ("/dev/fd") - 1;
++	  if (*q >= '0' && *q <= '9')
++	    {
++	      free (map[drive].drive);
++	      map[drive].drive = NULL;
++	      grub_util_info ("`%s' looks like a floppy drive, skipping", p);
++	      continue;
++	    }
++	}
++
+ #ifdef __linux__
+       /* On Linux, the devfs uses symbolic links horribly, and that
+ 	 confuses the interface very much, so use realpath to expand

diff --git a/sys-boot/grub/grub-0.97-r22.ebuild b/sys-boot/grub/grub-0.97-r22.ebuild
new file mode 100644
index 0000000..0be60db
--- /dev/null
+++ b/sys-boot/grub/grub-0.97-r22.ebuild
@@ -0,0 +1,240 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-boot/grub/grub-0.97-r9.ebuild,v 1.4 2009/05/15 21:11:24 maekke Exp $
+
+# XXX: we need to review menu.lst vs grub.conf handling.  We've been converting
+#      all systems to grub.conf (and symlinking menu.lst to grub.conf), but
+#      we never updated any of the source code (it still all wants menu.lst),
+#      and there is no indication that upstream is making the transition.
+
+inherit mount-boot eutils flag-o-matic toolchain-funcs autotools multilib
+
+PATCHVER="1.9" # Should match the revision ideally
+DESCRIPTION="GNU GRUB Legacy boot loader"
+HOMEPAGE="http://www.gnu.org/software/grub/"
+SRC_URI="mirror://gentoo/${P}.tar.gz
+	ftp://alpha.gnu.org/gnu/${PN}/${P}.tar.gz
+	mirror://gentoo/${P}-patches-${PATCHVER}.tar.bz2"
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="amd64 x86 ~x86-fbsd"
+IUSE="custom-cflags ncurses netboot static"
+
+DEPEND="ncurses? (
+		>=sys-libs/ncurses-5.2-r5
+		amd64? ( app-emulation/emul-linux-x86-baselibs )
+	)"
+PROVIDE="virtual/bootloader"
+
+src_unpack() {
+	unpack ${A}
+	cd "${S}"
+
+	# patch breaks booting for some people #111885
+	rm "${WORKDIR}"/patch/400_*
+
+	# Grub will not handle a kernel larger than EXTENDED_MEMSIZE Mb as
+	# discovered in bug 160801. We can change this, however, using larger values
+	# for this variable means that Grub needs more memory to run and boot. For a
+	# kernel of size N, Grub needs (N+1)*2.  Advanced users should set a custom
+	# value in make.conf, it is possible to make kernels ~16Mb in size, but it
+	# needs the kitchen sink built-in.
+	local t="custom"
+	if [[ -z ${GRUB_MAX_KERNEL_SIZE} ]] ; then
+		case $(tc-arch) in
+			amd64) GRUB_MAX_KERNEL_SIZE=7 ;;
+			x86)   GRUB_MAX_KERNEL_SIZE=3 ;;
+		esac
+		t="default"
+	fi
+	einfo "Grub will support the ${t} maximum kernel size of ${GRUB_MAX_KERNEL_SIZE} Mb (GRUB_MAX_KERNEL_SIZE)"
+
+	sed -i \
+		-e "/^#define.*EXTENDED_MEMSIZE/s,3,${GRUB_MAX_KERNEL_SIZE},g" \
+		"${S}"/grub/asmstub.c \
+		|| die "Failed to hack memory size"
+
+	# UUID support
+	epatch "${FILESDIR}/${P}-uuid.patch"
+	epatch "${FILESDIR}/${P}-uuid_doc.patch"
+	# Gfxmenu support
+	epatch "${FILESDIR}/${P}-gfxmenu-v8.patch"
+
+	if [[ -n ${PATCHVER} ]] ; then
+		EPATCH_SUFFIX="patch"
+		epatch "${WORKDIR}"/patch
+		eautoreconf
+	fi
+}
+
+src_compile() {
+	filter-flags -fPIE #168834
+
+	# Fix libvolume_id build (UUID)
+	export CPPFLAGS="${CPPFLAGS} -I/usr/include -I/usr/$(get_libdir)/gcc/${CHOST}/$(gcc-fullversion)/include"
+
+	use amd64 && multilib_toolchain_setup x86
+
+	unset BLOCK_SIZE #73499
+
+	### i686-specific code in the boot loader is a bad idea; disabling to ensure
+	### at least some compatibility if the hard drive is moved to an older or
+	### incompatible system.
+
+	# grub-0.95 added -fno-stack-protector detection, to disable ssp for stage2,
+	# but the objcopy's (faulty) test fails if -fstack-protector is default.
+	# create a cache telling configure that objcopy is ok, and add -C to econf
+	# to make use of the cache.
+	#
+	# CFLAGS has to be undefined running econf, else -fno-stack-protector detection fails.
+	# STAGE2_CFLAGS is not allowed to be used on emake command-line, it overwrites
+	# -fno-stack-protector detected by configure, removed from netboot's emake.
+	use custom-cflags || unset CFLAGS
+
+	export grub_cv_prog_objcopy_absolute=yes #79734
+	use static && append-ldflags -static
+
+	# Per bug 216625, the emul packages do not provide .a libs for performing
+	# suitable static linking
+	if use amd64 && use static ; then
+		if [ -z "${GRUB_STATIC_PACKAGE_BUILDING}" ]; then
+			die "You must use the grub-static package if you want a static Grub on amd64!"
+		else
+			eerror "You have set GRUB_STATIC_PACKAGE_BUILDING. This"
+			eerror "is specifically intended for building the tarballs for the"
+			eerror "grub-static package via USE='static -ncurses'."
+			eerror "All bets are now off."
+			ebeep 10
+		fi
+	fi
+
+	# build the net-bootable grub first, but only if "netboot" is set
+	if use netboot ; then
+		econf \
+		--libdir=/lib \
+		--datadir=/usr/lib/grub \
+		--exec-prefix=/ \
+		--disable-auto-linux-mem-opt \
+		--enable-diskless \
+		--enable-{3c{5{03,07,09,29,95},90x},cs89x0,davicom,depca,eepro{,100}} \
+		--enable-{epic100,exos205,ni5210,lance,ne2100,ni{50,65}10,natsemi} \
+		--enable-{ne,ns8390,wd,otulip,rtl8139,sis900,sk-g16,smc9000,tiara} \
+		--enable-{tulip,via-rhine,w89c840} || die "netboot econf failed"
+
+		emake w89c840_o_CFLAGS="-O" || die "making netboot stuff"
+
+		mv -f stage2/{nbgrub,pxegrub} "${S}"/
+		mv -f stage2/stage2 stage2/stage2.netboot
+
+		make clean || die "make clean failed"
+	fi
+
+	# Now build the regular grub
+	# Note that FFS and UFS2 support are broken for now - stage1_5 files too big
+	econf \
+		--libdir=/lib \
+		--datadir=/usr/lib/grub \
+		--exec-prefix=/ \
+		--disable-auto-linux-mem-opt \
+		$(use_with ncurses curses) \
+		|| die "econf failed"
+
+	# sanity check due to common failure
+	use ncurses && ! grep -qs "HAVE_LIBCURSES.*1" config.h && die "USE=ncurses but curses not found"
+
+	emake || die "making regular stuff"
+}
+
+src_test() {
+	# non-default block size also give false pass/fails.
+	unset BLOCK_SIZE
+	make check || die "make check failed"
+}
+
+src_install() {
+	emake DESTDIR="${D}" install || die
+	if use netboot ; then
+		exeinto /usr/lib/grub/${CHOST}
+		doexe nbgrub pxegrub stage2/stage2.netboot || die "netboot install"
+	fi
+
+	dodoc AUTHORS BUGS ChangeLog NEWS README THANKS TODO
+	newdoc docs/menu.lst grub.conf.sample
+	dodoc "${FILESDIR}"/grub.conf.gentoo
+	prepalldocs
+
+	[ -n "${GRUB_STATIC_PACKAGE_BUILDING}" ] && \
+		mv \
+		"${D}"/usr/share/doc/${PF} \
+		"${D}"/usr/share/doc/grub-static-${PF/grub-}
+
+	insinto /usr/share/grub
+	doins "${FILESDIR}"/splash.xpm.gz
+
+}
+
+setup_boot_dir() {
+	local boot_dir=$1
+	local dir=${boot_dir}
+
+	mkdir -p "${dir}"
+	[[ ! -L ${dir}/boot ]] && ln -s . "${dir}/boot"
+	dir="${dir}/grub"
+	if [[ ! -e ${dir} ]] ; then
+		mkdir "${dir}" || die "${dir} does not exist!"
+	fi
+
+	# change menu.lst to grub.conf
+	if [[ ! -e ${dir}/grub.conf ]] && [[ -e ${dir}/menu.lst ]] ; then
+		mv -f "${dir}"/menu.lst "${dir}"/grub.conf
+		ewarn
+		ewarn "*** IMPORTANT NOTE: menu.lst has been renamed to grub.conf"
+		ewarn
+	fi
+
+	if [[ ! -e ${dir}/menu.lst ]]; then
+		einfo "Linking from new grub.conf name to menu.lst"
+		ln -snf grub.conf "${dir}"/menu.lst
+	fi
+
+	if [[ ! -e ${dir}/grub.conf ]] ; then
+		s="${ROOT}/usr/share/doc/${PF}/grub.conf.gentoo"
+		[[ -e "${s}" ]] && cat "${s}" >${dir}/grub.conf
+		[[ -e "${s}.gz" ]] && zcat "${s}.gz" >${dir}/grub.conf
+		[[ -e "${s}.bz2" ]] && bzcat "${s}.bz2" >${dir}/grub.conf
+	fi
+
+	einfo "Grub has been installed to ${boot_dir} successfully."
+}
+
+pkg_postinst() {
+	if [[ -n ${DONT_MOUNT_BOOT} ]]; then
+		elog "WARNING: you have DONT_MOUNT_BOOT in effect, so you must apply"
+		elog "the following instructions for your /boot!"
+		elog "Neglecting to do so may cause your system to fail to boot!"
+		elog
+	else
+		setup_boot_dir "${ROOT}"/boot
+		# Trailing output because if this is run from pkg_postinst, it gets mixed into
+		# the other output.
+		einfo ""
+	fi
+	elog "To interactively install grub files to another device such as a USB"
+	elog "stick, just run the following and specify the directory as prompted:"
+	elog "   emerge --config =${PF}"
+	elog "Alternately, you can export GRUB_ALT_INSTALLDIR=/path/to/use to tell"
+	elog "grub where to install in a non-interactive way."
+
+}
+
+pkg_config() {
+	local dir
+	if [ ! -d "${GRUB_ALT_INSTALLDIR}" ]; then
+		einfo "Enter the directory where you want to setup grub:"
+		read dir
+	else
+		dir="${GRUB_ALT_INSTALLDIR}"
+	fi
+	setup_boot_dir "${dir}"
+}

diff --git a/sys-boot/grub/grub-1.98-r10.ebuild b/sys-boot/grub/grub-1.98-r10.ebuild
new file mode 100644
index 0000000..bc0710a
--- /dev/null
+++ b/sys-boot/grub/grub-1.98-r10.ebuild
@@ -0,0 +1,141 @@
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-boot/grub/grub-1.98.ebuild,v 1.1 2010/03/10 19:47:34 vapier Exp $
+
+inherit mount-boot eutils flag-o-matic toolchain-funcs
+
+if [[ ${PV} == "9999" ]] ; then
+	EBZR_REPO_URI="http://bzr.savannah.gnu.org/r/grub/trunk/grub"
+	inherit autotools bzr
+	SRC_URI=""
+else
+	SRC_URI="ftp://alpha.gnu.org/gnu/${PN}/${P}.tar.gz
+		mirror://gentoo/${P}.tar.gz"
+fi
+
+DESCRIPTION="GNU GRUB 2 boot loader"
+HOMEPAGE="http://www.gnu.org/software/grub/"
+
+LICENSE="GPL-3"
+use multislot && SLOT="2" || SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="custom-cflags truetype multislot static"
+
+RDEPEND=">=sys-libs/ncurses-5.2-r5
+	dev-libs/lzo
+	truetype? (
+		media-libs/freetype
+		media-fonts/unifont
+	)"
+DEPEND="${RDEPEND}
+	dev-lang/ruby"
+PDEPEND="${PDEPEND}
+	sys-boot/os-prober"
+PROVIDE="virtual/bootloader"
+
+export STRIP_MASK="*/grub/*/*.mod"
+QA_EXECSTACK="sbin/grub-probe sbin/grub-setup sbin/grub-mkdevicemap"
+
+src_unpack() {
+	if [[ ${PV} == "9999" ]] ; then
+		bzr_src_unpack
+	else
+		unpack ${A}
+	fi
+	cd "${S}"
+	epatch "${FILESDIR}"/${PN}-1.98-genkernel.patch
+	epatch "${FILESDIR}"/${PN}-1.97-vga-deprecated.patch
+	epatch "${FILESDIR}"/${PN}-1.98-wallpaper-settings-support.patch
+	# see Gentoo #302634
+	epatch "${FILESDIR}"/${PN}-1.98-add-legacy-rootfs-detection.patch
+
+	# Ubuntu and upstream patches
+	epatch "${FILESDIR}"/ubuntu-upstream-${PV}/*.diff
+
+	epatch_user
+
+	# see Gentoo #321569
+	epatch "${FILESDIR}"/${PN}-1.98-follow-dev-mapper-symlinks.patch
+
+	# Genkernel doesn't support "single" for rescue mode
+	# but rather init_opts=single
+	epatch "${FILESDIR}"/${PN}-1.98-genkernel-initramfs-single.patch
+
+	# autogen.sh does more than just run autotools
+	# need to eautomake due to weirdness #296013
+	if [[ ${PV} == "9999" ]] ; then
+		sed -i \
+			-e '/^\(auto\|ac\)/s:^:e:' \
+			-e "s:^eautomake:`which automake`:" \
+			autogen.sh
+		(. ./autogen.sh) || die
+	fi
+}
+
+src_compile() {
+	use custom-cflags || unset CFLAGS CPPFLAGS LDFLAGS
+	use static && append-ldflags -static
+
+	econf \
+		--disable-werror \
+		--sbindir=/sbin \
+		--bindir=/bin \
+		--libdir=/$(get_libdir) \
+		--disable-efiemu \
+		$(use_enable truetype grub-mkfont)
+	emake -j1 || die "making regular stuff"
+}
+
+src_install() {
+	emake DESTDIR="${D}" install || die
+	dodoc AUTHORS ChangeLog NEWS README THANKS TODO
+	if use multislot ; then
+		sed -i "s:grub-install:grub2-install:" "${D}"/sbin/grub-install || die
+		mv "${D}"/sbin/grub{,2}-install || die
+		mv "${D}"/sbin/grub{,2}-set-default || die
+		mv "${D}"/usr/share/info/grub{,2}.info || die
+	fi
+
+	# install /etc/default/grub
+	cp "${FILESDIR}/grub2-default" grub
+	dodir /etc/default
+	insinto /etc/default
+	doins grub
+
+	# Install fonts setup hook
+	exeinto /etc/grub.d
+	doexe "${FILESDIR}/00_fonts"
+	doexe "${FILESDIR}/05_distro_theme"
+
+	dodir /boot/grub
+	insinto /boot/grub
+	newins "${FILESDIR}/default-splash-6.png" default-splash.png
+	# keep backward compat
+	dodir /usr/share/grub
+	insinto /usr/share/grub
+	newins "${FILESDIR}/default-splash-6.png" default-splash.png
+
+}
+
+setup_boot_dir() {
+	local boot_dir=$1
+	local dir=${boot_dir}/grub
+
+	if [[ ! -e ${dir}/grub.cfg ]] ; then
+		einfo "Running: grub-mkconfig -o '${dir}/grub.cfg'"
+		grub-mkconfig -o "${dir}/grub.cfg"
+	fi
+
+	#local install=grub-install
+	#use multislot && install="grub2-install --grub-setup=/bin/true"
+	#einfo "Running: ${install} "
+	#${install}
+}
+
+pkg_postinst() {
+	if use multislot ; then
+		elog "You have installed grub2 with USE=multislot, so to coexist"
+		elog "with grub1, the grub2 install binary is named grub2-install."
+	fi
+	setup_boot_dir "${ROOT}"boot
+}

diff --git a/sys-boot/grub/grub-1.98-r9.ebuild b/sys-boot/grub/grub-1.98-r9.ebuild
new file mode 100644
index 0000000..43a8bf4
--- /dev/null
+++ b/sys-boot/grub/grub-1.98-r9.ebuild
@@ -0,0 +1,145 @@
+# Copyright 1999-2010 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/sys-boot/grub/grub-1.98.ebuild,v 1.1 2010/03/10 19:47:34 vapier Exp $
+
+inherit mount-boot eutils flag-o-matic toolchain-funcs
+
+if [[ ${PV} == "9999" ]] ; then
+	EBZR_REPO_URI="http://bzr.savannah.gnu.org/r/grub/trunk/grub"
+	inherit autotools bzr
+	SRC_URI=""
+else
+	SRC_URI="ftp://alpha.gnu.org/gnu/${PN}/${P}.tar.gz
+		mirror://gentoo/${P}.tar.gz"
+fi
+
+DESCRIPTION="GNU GRUB 2 boot loader"
+HOMEPAGE="http://www.gnu.org/software/grub/"
+
+LICENSE="GPL-3"
+use multislot && SLOT="2" || SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="custom-cflags debug truetype multislot static"
+
+RDEPEND=">=sys-libs/ncurses-5.2-r5
+	dev-libs/lzo
+	truetype? (
+		media-libs/freetype
+		media-fonts/unifont
+	)"
+DEPEND="${RDEPEND}
+	dev-lang/ruby"
+PDEPEND="${PDEPEND}
+	sys-boot/os-prober"
+PROVIDE="virtual/bootloader"
+
+export STRIP_MASK="*/grub/*/*.mod"
+QA_EXECSTACK="sbin/grub-probe sbin/grub-setup sbin/grub-mkdevicemap"
+
+src_unpack() {
+	if [[ ${PV} == "9999" ]] ; then
+		bzr_src_unpack
+	else
+		unpack ${A}
+	fi
+	cd "${S}"
+	epatch "${FILESDIR}"/${PN}-1.98-genkernel.patch
+	epatch "${FILESDIR}"/${PN}-1.97-vga-deprecated.patch
+	epatch "${FILESDIR}"/${PN}-1.98-wallpaper-settings-support.patch
+	# see Gentoo #302634
+	epatch "${FILESDIR}"/${PN}-1.98-add-legacy-rootfs-detection.patch
+
+	# Ubuntu and upstream patches
+	epatch "${FILESDIR}"/ubuntu-upstream-${PV}/*.diff
+
+	epatch_user
+
+	# see Gentoo #321569
+	epatch "${FILESDIR}"/${PN}-1.98-follow-dev-mapper-symlinks.patch
+
+	# Genkernel doesn't support "single" for rescue mode
+	# but rather init_opts=single
+	epatch "${FILESDIR}"/${PN}-1.98-genkernel-initramfs-single.patch
+
+	# autogen.sh does more than just run autotools
+	# need to eautomake due to weirdness #296013
+	if [[ ${PV} == "9999" ]] ; then
+		sed -i \
+			-e '/^\(auto\|ac\)/s:^:e:' \
+			-e "s:^eautomake:`which automake`:" \
+			autogen.sh
+		(. ./autogen.sh) || die
+	fi
+}
+
+src_compile() {
+	use custom-cflags || unset CFLAGS CPPFLAGS LDFLAGS
+	use static && append-ldflags -static
+
+	econf \
+		--disable-werror \
+		--sbindir=/sbin \
+		--bindir=/bin \
+		--libdir=/$(get_libdir) \
+		--disable-efiemu \
+		$(use_enable truetype grub-mkfont) \
+		$(use_enable debug mm-debug) \
+		$(use_enable debug grub-emu) \
+		$(use_enable debug grub-emu-usb) \
+		$(use_enable debug grub-fstest)
+	emake -j1 || die "making regular stuff"
+}
+
+src_install() {
+	emake DESTDIR="${D}" install || die
+	dodoc AUTHORS ChangeLog NEWS README THANKS TODO
+	if use multislot ; then
+		sed -i "s:grub-install:grub2-install:" "${D}"/sbin/grub-install || die
+		mv "${D}"/sbin/grub{,2}-install || die
+		mv "${D}"/sbin/grub{,2}-set-default || die
+		mv "${D}"/usr/share/info/grub{,2}.info || die
+	fi
+
+	# install /etc/default/grub
+	cp "${FILESDIR}/grub2-default" grub
+	dodir /etc/default
+	insinto /etc/default
+	doins grub
+
+	# Install fonts setup hook
+	exeinto /etc/grub.d
+	doexe "${FILESDIR}/00_fonts"
+	doexe "${FILESDIR}/05_distro_theme"
+
+	dodir /boot/grub
+	insinto /boot/grub
+	newins "${FILESDIR}/default-splash-6.png" default-splash.png
+	# keep backward compat
+	dodir /usr/share/grub
+	insinto /usr/share/grub
+	newins "${FILESDIR}/default-splash-6.png" default-splash.png
+
+}
+
+setup_boot_dir() {
+	local boot_dir=$1
+	local dir=${boot_dir}/grub
+
+	if [[ ! -e ${dir}/grub.cfg ]] ; then
+		einfo "Running: grub-mkconfig -o '${dir}/grub.cfg'"
+		grub-mkconfig -o "${dir}/grub.cfg"
+	fi
+
+	#local install=grub-install
+	#use multislot && install="grub2-install --grub-setup=/bin/true"
+	#einfo "Running: ${install} "
+	#${install}
+}
+
+pkg_postinst() {
+	if use multislot ; then
+		elog "You have installed grub2 with USE=multislot, so to coexist"
+		elog "with grub1, the grub2 install binary is named grub2-install."
+	fi
+	setup_boot_dir "${ROOT}"boot
+}

diff --git a/sys-boot/grub/grub-1.99.ebuild b/sys-boot/grub/grub-1.99.ebuild
new file mode 100644
index 0000000..3ca30a1
--- /dev/null
+++ b/sys-boot/grub/grub-1.99.ebuild
@@ -0,0 +1,279 @@
+# Copyright 1999-2011 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: $
+
+EAPI=4
+
+if [[ ${PV} == "9999" ]] ; then
+	EBZR_REPO_URI="http://bzr.savannah.gnu.org/r/grub/trunk/grub/"
+	LIVE_ECLASS="autotools bzr"
+	SRC_URI=""
+else
+	MY_P=${P/_/\~}
+	SRC_URI="mirror://gnu/${PN}/${MY_P}.tar.xz
+		mirror://gentoo/${MY_P}.tar.xz"
+	S=${WORKDIR}/${MY_P}
+fi
+
+inherit mount-boot eutils flag-o-matic toolchain-funcs autotools ${LIVE_ECLASS}
+unset LIVE_ECLASS
+
+DESCRIPTION="GNU GRUB boot loader"
+HOMEPAGE="http://www.gnu.org/software/grub/"
+
+LICENSE="GPL-3"
+use multislot && SLOT="2" || SLOT="0"
+[[ ${PV} != "9999" ]] && KEYWORDS="~amd64 ~x86 ~mips ~ppc ~ppc64"
+IUSE="custom-cflags debug +device-mapper multislot nls static sdl +truetype"
+
+GRUB_PLATFORMS="coreboot efi-32 efi-64 emu ieee1275 multiboot pc yeeloong"
+# everywhere:
+#     emu
+# mips only:
+#     qemu-mips, yeelong
+# amd64, x86, ppc, ppc64
+#     ieee1275
+# amd64, x86
+#     coreboot, multiboot, efi-32, pc, qemu
+# amd64
+#     efi-64
+for i in ${GRUB_PLATFORMS}; do
+	IUSE+=" grub_platforms_${i}"
+done
+unset i
+
+# os-prober: Used on runtime to detect other OSes
+# xorriso (dev-libs/libisoburn): Used on runtime for mkrescue
+RDEPEND="
+	dev-libs/libisoburn
+	dev-libs/lzo
+	sys-boot/os-prober
+	>=sys-libs/ncurses-5.2-r5
+	debug? (
+		sdl? ( media-libs/libsdl )
+	)
+	device-mapper? ( >=sys-fs/lvm2-2.02.45 )
+	truetype? ( media-libs/freetype >=media-fonts/unifont-5 )"
+DEPEND="${RDEPEND}
+	>=dev-lang/python-2.5.2
+"
+if [[ ${PV} == "9999" ]]; then
+	DEPEND+=" >=sys-devel/autogen-5.10 sys-apps/help2man"
+else
+	DEPEND+=" >=sys-devel/autogen-5.10 app-arch/xz-utils"
+fi
+
+export STRIP_MASK="*/grub/*/*.mod"
+QA_EXECSTACK="
+	sbin/grub-probe
+	sbin/grub-setup
+	sbin/grub-mkdevicemap
+	bin/grub-script-check
+	bin/grub-fstest
+"
+
+grub_run_phase() {
+	local phase=$1
+	local platform=$2
+	[[ -z ${phase} ]] && die "${FUNCNAME}: Phase is undefined"
+	[[ -z ${platform} ]] && die "${FUNCNAME}: Platform is undefined"
+
+	[[ -d "${WORKDIR}/build-${platform}" ]] || \
+		{ mkdir "${WORKDIR}/build-${platform}" || die ; }
+	pushd "${WORKDIR}/build-${platform}" > /dev/null || die
+
+	echo ">>> Running ${phase} for platform \"${platform}\""
+	echo ">>> Working in: \"${WORKDIR}/build-${platform}\""
+
+	grub_${phase} ${platform}
+
+	popd > /dev/null || die
+}
+
+grub_src_configure() {
+	local platform=$1
+	local target
+
+	[[ -z ${platform} ]] && die "${FUNCNAME}: Platform is undefined"
+
+	# if we have no platform then --with-platform=guessed does not work
+	[[ ${platform} == "guessed" ]] && platform=""
+
+	# check if we have to specify the target (EFI)
+	# or just append correct --with-platform
+	if [[ -n ${platform} ]]; then
+		if [[ ${platform/-*} == ${platform} ]]; then
+			platform=" --with-platform=${platform}"
+		else
+			# EFI platform hack
+			[[ ${platform/*-} == 32 ]] && target=i386
+			[[ ${platform/*-} == 64 ]] && target=x86_64
+			# program-prefix is required empty because otherwise it is equal to
+			# target variable, which we do not want at all
+			platform="
+				--with-platform=${platform/-*}
+				--target=${target}
+				--program-prefix=
+			"
+		fi
+	fi
+
+	ECONF_SOURCE="${WORKDIR}/${P}/" \
+	econf \
+		--disable-werror \
+		--sbindir=/sbin \
+		--bindir=/bin \
+		--libdir=/$(get_libdir) \
+		--disable-efiemu \
+		$(use_enable device-mapper) \
+		$(use_enable truetype grub-mkfont) \
+		$(use_enable nls) \
+		$(use_enable debug mm-debug) \
+		$(use sdl && use_enable debug grub-emu-sdl) \
+		$(use_enable debug grub-emu-usb) \
+		${platform}
+}
+
+grub_src_compile() {
+	default_src_compile
+}
+
+grub_src_install() {
+	default_src_install
+}
+
+src_prepare() {
+	local i j archs
+
+	epatch "${FILESDIR}"/${PN}-1.99-genkernel.patch #256335
+	epatch "${FILESDIR}"/${PN}-1.99-vga-deprecated.patch
+	epatch "${FILESDIR}"/${PN}-1.99-wallpaper-settings-support.patch
+	# This happens with md raid metadata 0.90. Due to limitations of the format
+	epatch "${FILESDIR}"/${PN}-1.99-workaround-raid-bios-bug.patch
+	# vga= not yet deprecated for us
+	epatch "${FILESDIR}"/${PN}-1.99-vga-deprecated-not-yet.patch
+	epatch "${FILESDIR}"/${PN}-1.99-disable-floppies.patch
+	epatch_user
+	# Genkernel doesn't support "single" for rescue mode
+	# but rather init_opts=single
+	epatch "${FILESDIR}"/${PN}-1.98-genkernel-initramfs-single.patch
+
+	sed -i -e '/^autoreconf/ d' autogen.sh || die
+	(. ./autogen.sh) || die
+	eautoreconf
+
+	# get enabled platforms
+	GRUB_ENABLED_PLATFORMS=""
+	for i in ${GRUB_PLATFORMS}; do
+		use grub_platforms_${i} && GRUB_ENABLED_PLATFORMS+=" ${i}"
+	done
+	[[ -z ${GRUB_ENABLED_PLATFORMS} ]] && GRUB_ENABLED_PLATFORMS="guessed"
+	einfo "Going to build following platforms: ${GRUB_ENABLED_PLATFORMS}"
+}
+
+src_configure() {
+	local i
+
+	use custom-cflags || unset CFLAGS CPPFLAGS LDFLAGS
+	use static && append-ldflags -static
+
+	for i in ${GRUB_ENABLED_PLATFORMS}; do
+		grub_run_phase ${FUNCNAME} ${i}
+	done
+}
+
+src_compile() {
+	local i
+
+	for i in ${GRUB_ENABLED_PLATFORMS}; do
+		grub_run_phase ${FUNCNAME} ${i}
+	done
+}
+
+src_install() {
+	local i
+
+	for i in ${GRUB_ENABLED_PLATFORMS}; do
+		grub_run_phase ${FUNCNAME} ${i}
+	done
+	if use multislot ; then
+		sed -i "s:grub-install:grub2-install:" "${D}"/sbin/grub-install || die
+		mv "${D}"/sbin/grub{,2}-install || die
+		mv "${D}"/sbin/grub{,2}-set-default || die
+		mv "${D}"/usr/share/info/grub{,2}.info || die
+	fi
+
+	# can't be in docs array as we use defualt_src_install in different builddir
+	dodoc AUTHORS ChangeLog NEWS README THANKS TODO
+	insinto /etc/default
+	newins "${FILESDIR}"/grub2-default-1.99 grub
+	cat <<-EOF >> "${D}"/lib*/grub/grub-mkconfig_lib
+	GRUB_DISTRIBUTOR="Sabayon"
+EOF
+
+	# Install fonts setup hook
+	exeinto /etc/grub.d
+	doexe "${FILESDIR}/00_fonts"
+	doexe "${FILESDIR}/05_distro_theme"
+
+	dodir /boot/grub
+	insinto /boot/grub
+	newins "${FILESDIR}/default-splash-6.png" default-splash.png
+	# keep backward compat
+	dodir /usr/share/grub
+	insinto /usr/share/grub
+	newins "${FILESDIR}/default-splash-6.png" default-splash.png
+
+	dodir /etc/env.d
+	echo 'CONFIG_PROTECT_MASK="/etc/grub.d"' > "${D}/etc/env.d/10grub2"
+
+}
+
+setup_boot_dir() {
+	local dir=$1
+
+	if [[ ! -e ${dir}/grub.cfg ]]; then
+		# display the link to guide if user didn't set up anything yet.
+		elog "For informations how to configure grub-2 please reffer to guide:"
+		# FIXME: we don't have any guide yet!
+		# Lets just use archlinux wiki until we have some.
+		elog "    https://wiki.archlinux.org/index.php/GRUB2"
+	fi
+
+	if [[ ! -e ${dir}/grub.cfg && -e ${dir}/menu.lst ]] ; then
+		# This is first grub2 install and we have old configuraton for
+		# grub1 around. Lets try to generate grub.cfg from it so user
+		# does not loose any stuff when rebooting.
+		# NOTE: in long term he still NEEDS to migrate to grub.d stuff.
+		einfo "Running: grub-menulst2cfg '${dir}/menu.lst' '${dir}/grub.cfg'"
+		grub-menulst2cfg "${dir}/menu.lst" "${dir}/grub.cfg" || \
+			ewarn "Running grub-menulst2cfg failed!"
+
+		einfo "Even if we just created configuration for your grub-2 using old"
+		einfo "grub-1 configuration file you should migrate to use new style"
+		einfo "configuration in '${ROOT}/etc/grub.d'."
+		einfo
+		elog "Remember to run grub-install to install your grub!"
+	else
+		# we need to refresh the grub.cfg everytime just to play it safe
+		einfo "Running: grub-mkconfig -o '${dir}/grub.cfg'"
+		grub-mkconfig -o "${dir}/grub.cfg" || \
+			ewarn "Running grub-mkconfig failed! Check your configuration files!"
+	fi
+
+	elog "Remember to run \"grub-mkconfig -o '${dir}/grub.cfg'\" every time"
+	elog "you update the configuration files."
+}
+
+pkg_postinst() {
+	if use multislot ; then
+		elog "You have installed grub2 with USE=multislot, so to coexist"
+		elog "with grub1, the grub2 install binary is named grub2-install."
+	fi
+	mount-boot_mount_boot_partition
+
+	setup_boot_dir "${ROOT}"boot/grub
+
+	# needs to be called after we call setup_boot_dir
+	mount-boot_pkg_postinst
+}

diff --git a/sys-libs/libuser/.libuser-0.57.1.ebuild.swp b/sys-libs/libuser/.libuser-0.57.1.ebuild.swp
new file mode 100644
index 0000000..a0c5ac4
Binary files /dev/null and b/sys-libs/libuser/.libuser-0.57.1.ebuild.swp differ



^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2011-07-07 22:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-07 22:43 [gentoo-commits] proj/anaconda-overlay:master commit in: sys-boot/grub/files/ubuntu-upstream-1.98/, sys-boot/grub/files/, Wiktor W Brodlo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox