[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] pygrub: look in every partition for something to boot



# HG changeset patch
# User Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
# Date 1279214296 -3600
# Node ID c4a83e3cc6b435cc559450bbcd8b2ba7a801964f
# Parent  6fdb00dc93a5d4d8a29b2af52053f3e65b645c93
pygrub: look in every partition for something to boot

pygrub: look in every partition for something to boot, in case
the OS installer (SLES 10 sp1 in particular) forgets to mark the
boot partition as active.

Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
Acked-by: David Markey <admin@xxxxxxxxxxx>
---
 tools/pygrub/src/pygrub |  113 +++++++++++++++++++++++++++++-------------------
 1 files changed, 70 insertions(+), 43 deletions(-)

diff -r 6fdb00dc93a5 -r c4a83e3cc6b4 tools/pygrub/src/pygrub
--- a/tools/pygrub/src/pygrub   Thu Jul 15 16:32:50 2010 +0100
+++ b/tools/pygrub/src/pygrub   Thu Jul 15 18:18:16 2010 +0100
@@ -50,21 +50,6 @@ def is_disk_image(file):
         return True
     return False
 
-def get_active_partition(file):
-    """Find the offset for the start of the first active partition "
-    "in the disk image file."""
-
-    fd = os.open(file, os.O_RDONLY)
-    buf = os.read(fd, 512)
-    for poff in (446, 462, 478, 494): # partition offsets
-        # active partition has 0x80 as the first byte
-        if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',):
-            return buf[poff:poff+16]
-
-    # if there's not a partition marked as active, fall back to
-    # the first partition
-    return buf[446:446+16]
-
 SECTOR_SIZE=512
 DK_LABEL_LOC=1
 DKL_MAGIC=0xdabe
@@ -101,25 +86,44 @@ FDISK_PART_SOLARIS_OLD=0x82
 FDISK_PART_SOLARIS_OLD=0x82
 FDISK_PART_GPT=0xee
 
-def get_fs_offset(file):
+def get_partition_offsets(file):
     if not is_disk_image(file):
-        return 0
-
-    partbuf = get_active_partition(file)
-    if len(partbuf) == 0:
-        raise RuntimeError, "Unable to find active partition on disk"
-
-    offset = struct.unpack("<L", partbuf[8:12])[0] * SECTOR_SIZE
-
-    type = struct.unpack("<B", partbuf[4:5])[0]
-
-    if type == FDISK_PART_SOLARIS or type == FDISK_PART_SOLARIS_OLD:
-        offset += get_solaris_slice(file, offset)
-
-    if type == FDISK_PART_GPT:
-        offset = get_fs_offset_gpt(file)
-    
-    return offset
+        # No MBR: assume whole disk filesystem, which is like a 
+        # single partition starting at 0
+        return [0]
+
+    part_offs = []
+
+    fd = os.open(file, os.O_RDONLY)
+    buf = os.read(fd, 512)
+    for poff in (446, 462, 478, 494): # partition offsets
+
+        # MBR contains a 16 byte descriptor per partition
+        partbuf = buf[poff:poff+16]
+        offset  = struct.unpack("<L", partbuf[8:12])[0] * SECTOR_SIZE
+        type    = struct.unpack("<B", partbuf[4:5])[0]
+        
+        # offset == 0 implies this partition is not enabled
+        if offset == 0:
+            continue
+
+        if type == FDISK_PART_SOLARIS or type == FDISK_PART_SOLARIS_OLD:
+            try:
+                offset += get_solaris_slice(file, offset)
+            except RuntimeError:
+                continue # no solaris magic at that offset, ignore partition
+
+        if type == FDISK_PART_GPT:
+            offset = get_fs_offset_gpt(file)
+
+        # Active partition has 0x80 as the first byte.
+        # If active, prepend to front of list, otherwise append to back.
+        if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',):
+            part_offs.insert(0, offset)
+        else:
+            part_offs.append(offset)
+
+    return part_offs
 
 class GrubLineEditor(curses.textpad.Textbox):
     def __init__(self, screen, startx, starty, line = ""):
@@ -734,17 +738,40 @@ if __name__ == "__main__":
     bootfsargs = '"%s"' % incfg["args"]
     bootfsgroup = re.findall('zfs-bootfs=(.*?)[\s\,\"]', bootfsargs)
     if bootfsgroup:
-        fs = fsimage.open(file, get_fs_offset(file), bootfsgroup[0])
+        bootfsoptions = bootfsgroup[0]
     else:
-        fs = fsimage.open(file, get_fs_offset(file))
-
-    chosencfg = sniff_solaris(fs, incfg)
-
-    if not chosencfg["kernel"]:
-        chosencfg = sniff_netware(fs, incfg)
-
-    if not chosencfg["kernel"]:
-        chosencfg = run_grub(file, entry, fs, incfg["args"])
+        bootfsoptions = ""
+
+    # get list of offsets into file which start partitions
+    part_offs = get_partition_offsets(file)
+
+    for offset in part_offs:
+        try:
+            fs = fsimage.open(file, offset, bootfsoptions)
+
+            chosencfg = sniff_solaris(fs, incfg)
+
+            if not chosencfg["kernel"]:
+                chosencfg = sniff_netware(fs, incfg)
+
+            if not chosencfg["kernel"]:
+                chosencfg = run_grub(file, entry, fs, incfg["args"])
+
+            # Break as soon as we've found the kernel so that we continue
+            # to use this fsimage object
+            if chosencfg["kernel"]:
+                break
+            fs = None
+
+        except:
+            # IOErrors raised by fsimage.open
+            # RuntimeErrors raised by run_grub if no menu.lst present
+            fs = None
+            continue
+
+    # Did looping through partitions find us a kernel?
+    if not fs:
+        raise RuntimeError, "Unable to find partition containing kernel"
 
     if not_really:
         bootcfg["kernel"] = "<kernel:%s>" % chosencfg["kernel"]

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.