From mboxrd@z Thu Jan 1 00:00:00 1970 From: David Markey Subject: Re: [PATCH] pygrub: look in every partition for something to boot Date: Tue, 6 Jul 2010 11:47:35 +0100 Message-ID: References: <20100706104553.GN31695@whitby.uk.xensource.com> Reply-To: admin@dmarkey.com Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="===============0425306436==" Return-path: In-Reply-To: <20100706104553.GN31695@whitby.uk.xensource.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: Tim Deegan Cc: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org --===============0425306436== Content-Type: multipart/alternative; boundary=001485f62950f451e2048ab5c703 --001485f62950f451e2048ab5c703 Content-Type: text/plain; charset=ISO-8859-1 Good job. I've come across this problem before. On 6 July 2010 11:45, Tim Deegan 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 > > 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(" - 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(" + fd = os.open(file, os.O_RDONLY) > + buf = os.read(fd, 512) > + for poff in (446, 462, 478, 494): # partition offsets > > - type = struct.unpack(" + # MBR contains a 16 byte descriptor per partition > + partbuf = buf[poff:poff+16] > + offset = struct.unpack(" + type = struct.unpack(" + > + # 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(" + 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"] = "" % chosencfg["kernel"] > > _______________________________________________ > Xen-devel mailing list > Xen-devel@lists.xensource.com > http://lists.xensource.com/xen-devel > --001485f62950f451e2048ab5c703 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Good job. I've come across this problem before.

On 6 July 2010 11:45, Tim Deegan <Tim.Deegan@citrix.com> wrot= e:
pygrub: look in every partition for somethi= ng 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@citrix.com>

diff -r 78b2f1e04c73 tools/pygrub/src/pygrub
--- a/tools/pygrub/src/pygrub =A0 Tue Jul 06 11:09:36 2010 +0100
+++ b/tools/pygrub/src/pygrub =A0 Tue Jul 06 11:38:42 2010 +0100
@@ -50,21 +50,6 @@
=A0 =A0 =A0 =A0 return True
=A0 =A0 return False

-def get_active_partition(file):
- =A0 =A0"""Find the offset for the start of the first activ= e partition "
- =A0 =A0"in the disk image file."""
-
- =A0 =A0fd =3D os.open(file, os.O_RDONLY)
- =A0 =A0buf =3D os.read(fd, 512)
- =A0 =A0for poff in (446, 462, 478, 494): # partition offsets
- =A0 =A0 =A0 =A0# active partition has 0x80 as the first byte
- =A0 =A0 =A0 =A0if struct.unpack("<c", buf[poff:poff+1]) =3D= =3D ('\x80',):
- =A0 =A0 =A0 =A0 =A0 =A0return buf[poff:poff+16]
-
- =A0 =A0# if there's not a partition marked as active, fall back to - =A0 =A0# the first partition
- =A0 =A0return buf[446:446+16]
-
=A0SECTOR_SIZE=3D512
=A0DK_LABEL_LOC=3D1
=A0DKL_MAGIC=3D0xdabe
@@ -101,25 +86,44 @@
=A0FDISK_PART_SOLARIS_OLD=3D0x82
=A0FDISK_PART_GPT=3D0xee

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

- =A0 =A0partbuf =3D get_active_partition(file)
- =A0 =A0if len(partbuf) =3D=3D 0:
- =A0 =A0 =A0 =A0raise RuntimeError, "Unable to find active partition = on disk"
+ =A0 =A0part_offs =3D []

- =A0 =A0offset =3D struct.unpack("<L", partbuf[8:12])[0] * SE= CTOR_SIZE
+ =A0 =A0fd =3D os.open(file, os.O_RDONLY)
+ =A0 =A0buf =3D os.read(fd, 512)
+ =A0 =A0for poff in (446, 462, 478, 494): # partition offsets

- =A0 =A0type =3D struct.unpack("<B", partbuf[4:5])[0]
+ =A0 =A0 =A0 =A0# MBR contains a 16 byte descriptor per partition
+ =A0 =A0 =A0 =A0partbuf =3D buf[poff:poff+16]
+ =A0 =A0 =A0 =A0offset =A0=3D struct.unpack("<L", partbuf[8:1= 2])[0] * SECTOR_SIZE
+ =A0 =A0 =A0 =A0type =A0 =A0=3D struct.unpack("<B", partbuf[4= :5])[0]
+
+ =A0 =A0 =A0 =A0# offset =3D=3D 0 implies this partition is not enabled + =A0 =A0 =A0 =A0if offset =3D=3D 0:
+ =A0 =A0 =A0 =A0 =A0 =A0continue

- =A0 =A0if type =3D=3D FDISK_PART_SOLARIS or type =3D=3D FDISK_PART_SOLARI= S_OLD:
- =A0 =A0 =A0 =A0offset +=3D get_solaris_slice(file, offset)
+ =A0 =A0 =A0 =A0if type =3D=3D FDISK_PART_SOLARIS or type =3D=3D FDISK_PAR= T_SOLARIS_OLD:
+ =A0 =A0 =A0 =A0 =A0 =A0try:
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0offset +=3D get_solaris_slice(file, offset= )
+ =A0 =A0 =A0 =A0 =A0 =A0except RuntimeError:
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0continue # no solaris magic at that offset= , ignore partition

- =A0 =A0if type =3D=3D FDISK_PART_GPT:
- =A0 =A0 =A0 =A0offset =3D get_fs_offset_gpt(file)
-
- =A0 =A0return offset
+ =A0 =A0 =A0 =A0if type =3D=3D FDISK_PART_GPT:
+ =A0 =A0 =A0 =A0 =A0 =A0offset =3D get_fs_offset_gpt(file)
+
+ =A0 =A0 =A0 =A0# Active partition has 0x80 as the first byte.
+ =A0 =A0 =A0 =A0# If active, prepend to front of list, otherwise append to= back.
+ =A0 =A0 =A0 =A0if struct.unpack("<c", buf[poff:poff+1]) =3D= =3D ('\x80',):
+ =A0 =A0 =A0 =A0 =A0 =A0part_offs.insert(0, offset)
+ =A0 =A0 =A0 =A0else:
+ =A0 =A0 =A0 =A0 =A0 =A0part_offs.append(offset)
+
+ =A0 =A0return part_offs

=A0class GrubLineEditor(curses.textpad.Textbox):
=A0 =A0 def __init__(self, screen, startx, starty, line =3D ""):=
@@ -703,17 +711,40 @@
=A0 =A0 bootfsargs =3D '"%s"' % incfg["args"]<= br> =A0 =A0 bootfsgroup =3D re.findall('zfs-bootfs=3D(.*?)[\s\,\"]= 9;, bootfsargs)
=A0 =A0 if bootfsgroup:
- =A0 =A0 =A0 =A0fs =3D fsimage.open(file, get_fs_offset(file), bootfsgroup= [0])
+ =A0 =A0 =A0 =A0bootfsoptions =3D bootfsgroup[0]
=A0 =A0 else:
- =A0 =A0 =A0 =A0fs =3D fsimage.open(file, get_fs_offset(file))
+ =A0 =A0 =A0 =A0bootfsoptions =3D ""

- =A0 =A0chosencfg =3D sniff_solaris(fs, incfg)
+ =A0 =A0# get list of offsets into file which start partitions
+ =A0 =A0part_offs =3D get_partition_offsets(file)

- =A0 =A0if not chosencfg["kernel"]:
- =A0 =A0 =A0 =A0chosencfg =3D sniff_netware(fs, incfg)
+ =A0 =A0for offset in part_offs:
+ =A0 =A0 =A0 =A0try:
+ =A0 =A0 =A0 =A0 =A0 =A0fs =3D fsimage.open(file, offset, bootfsoptions)
- =A0 =A0if not chosencfg["kernel"]:
- =A0 =A0 =A0 =A0chosencfg =3D run_grub(file, entry, fs, incfg["args&q= uot;])
+ =A0 =A0 =A0 =A0 =A0 =A0chosencfg =3D sniff_solaris(fs, incfg)
+
+ =A0 =A0 =A0 =A0 =A0 =A0if not chosencfg["kernel"]:
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0chosencfg =3D sniff_netware(fs, incfg)
+
+ =A0 =A0 =A0 =A0 =A0 =A0if not chosencfg["kernel"]:
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0chosencfg =3D run_grub(file, entry, fs, in= cfg["args"])
+
+ =A0 =A0 =A0 =A0 =A0 =A0# Break as soon as we've found the kernel so t= hat we continue
+ =A0 =A0 =A0 =A0 =A0 =A0# to use this fsimage object
+ =A0 =A0 =A0 =A0 =A0 =A0if chosencfg["kernel"]:
+ =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break
+ =A0 =A0 =A0 =A0 =A0 =A0fs =3D None
+
+ =A0 =A0 =A0 =A0except:
+ =A0 =A0 =A0 =A0 =A0 =A0# IOErrors raised by fsimage.open
+ =A0 =A0 =A0 =A0 =A0 =A0# RuntimeErrors raised by run_grub if no menu.lst = present
+ =A0 =A0 =A0 =A0 =A0 =A0fs =3D None
+ =A0 =A0 =A0 =A0 =A0 =A0continue
+
+ =A0 =A0# Did looping through partitions find us a kernel?
+ =A0 =A0if not fs:
+ =A0 =A0 =A0 =A0raise RuntimeError, "Unable to find partition contain= ing kernel"

=A0 =A0 if not_really:
=A0 =A0 =A0 =A0 bootcfg["kernel"] =3D "<kernel:%s>&qu= ot; % chosencfg["kernel"]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.= com
http://l= ists.xensource.com/xen-devel

--001485f62950f451e2048ab5c703-- --===============0425306436== Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Disposition: inline _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel --===============0425306436==--