WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

Re: [Xen-devel] [PATCH] pygrub: look in every partition for something to

To: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
Subject: Re: [Xen-devel] [PATCH] pygrub: look in every partition for something to boot
From: David Markey <admin@xxxxxxxxxxx>
Date: Tue, 6 Jul 2010 11:47:35 +0100
Cc: xen-devel@xxxxxxxxxxxxxxxxxxx
Delivery-date: Tue, 06 Jul 2010 03:54:07 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <20100706104553.GN31695@xxxxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <20100706104553.GN31695@xxxxxxxxxxxxxxxxxxxxxxx>
Reply-to: admin@xxxxxxxxxxx
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Good job. I've come across this problem before.

On 6 July 2010 11:45, Tim Deegan <Tim.Deegan@xxxxxxxxxx> wrote:
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>

diff -r 78b2f1e04c73 tools/pygrub/src/pygrub
--- a/tools/pygrub/src/pygrub   Tue Jul 06 11:09:36 2010 +0100
+++ b/tools/pygrub/src/pygrub   Tue Jul 06 11:38:42 2010 +0100
@@ -50,21 +50,6 @@
        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_GPT=0xee

-def get_fs_offset(file):
+def get_partition_offsets(file):
    if not is_disk_image(file):
-        return 0
+        # No MBR: assume whole disk filesystem, which is like a
+        # single partition starting at 0
+        return [0]

-    partbuf = get_active_partition(file)
-    if len(partbuf) == 0:
-        raise RuntimeError, "Unable to find active partition on disk"
+    part_offs = []

-    offset = struct.unpack("<L", partbuf[8:12])[0] * SECTOR_SIZE
+    fd = os.open(file, os.O_RDONLY)
+    buf = os.read(fd, 512)
+    for poff in (446, 462, 478, 494): # partition offsets

-    type = struct.unpack("<B", partbuf[4:5])[0]
+        # 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:
-        offset += get_solaris_slice(file, offset)
+        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)
-
-    return offset
+        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 = ""):
@@ -703,17 +711,40 @@
    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))
+        bootfsoptions = ""

-    chosencfg = sniff_solaris(fs, incfg)
+    # get list of offsets into file which start partitions
+    part_offs = get_partition_offsets(file)

-    if not chosencfg["kernel"]:
-        chosencfg = sniff_netware(fs, incfg)
+    for offset in part_offs:
+        try:
+            fs = fsimage.open(file, offset, bootfsoptions)

-    if not chosencfg["kernel"]:
-        chosencfg = run_grub(file, entry, fs, incfg["args"])
+            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-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
<Prev in Thread] Current Thread [Next in Thread>