debuggers.hg
changeset 21854:c4a83e3cc6b4
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@citrix.com>
Acked-by: David Markey <admin@dmarkey.com>
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@citrix.com>
Acked-by: David Markey <admin@dmarkey.com>
author | Ian Jackson <Ian.Jackson@eu.citrix.com> |
---|---|
date | Thu Jul 15 18:18:16 2010 +0100 (2010-07-15) |
parents | 6fdb00dc93a5 |
children | 1f7c2418e58c 91ce0b0953ca |
files | tools/pygrub/src/pygrub |
line diff
1.1 --- a/tools/pygrub/src/pygrub Thu Jul 15 16:32:50 2010 +0100 1.2 +++ b/tools/pygrub/src/pygrub Thu Jul 15 18:18:16 2010 +0100 1.3 @@ -50,21 +50,6 @@ def is_disk_image(file): 1.4 return True 1.5 return False 1.6 1.7 -def get_active_partition(file): 1.8 - """Find the offset for the start of the first active partition " 1.9 - "in the disk image file.""" 1.10 - 1.11 - fd = os.open(file, os.O_RDONLY) 1.12 - buf = os.read(fd, 512) 1.13 - for poff in (446, 462, 478, 494): # partition offsets 1.14 - # active partition has 0x80 as the first byte 1.15 - if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',): 1.16 - return buf[poff:poff+16] 1.17 - 1.18 - # if there's not a partition marked as active, fall back to 1.19 - # the first partition 1.20 - return buf[446:446+16] 1.21 - 1.22 SECTOR_SIZE=512 1.23 DK_LABEL_LOC=1 1.24 DKL_MAGIC=0xdabe 1.25 @@ -101,25 +86,44 @@ FDISK_PART_SOLARIS=0xbf 1.26 FDISK_PART_SOLARIS_OLD=0x82 1.27 FDISK_PART_GPT=0xee 1.28 1.29 -def get_fs_offset(file): 1.30 +def get_partition_offsets(file): 1.31 if not is_disk_image(file): 1.32 - return 0 1.33 + # No MBR: assume whole disk filesystem, which is like a 1.34 + # single partition starting at 0 1.35 + return [0] 1.36 1.37 - partbuf = get_active_partition(file) 1.38 - if len(partbuf) == 0: 1.39 - raise RuntimeError, "Unable to find active partition on disk" 1.40 + part_offs = [] 1.41 1.42 - offset = struct.unpack("<L", partbuf[8:12])[0] * SECTOR_SIZE 1.43 + fd = os.open(file, os.O_RDONLY) 1.44 + buf = os.read(fd, 512) 1.45 + for poff in (446, 462, 478, 494): # partition offsets 1.46 1.47 - type = struct.unpack("<B", partbuf[4:5])[0] 1.48 - 1.49 - if type == FDISK_PART_SOLARIS or type == FDISK_PART_SOLARIS_OLD: 1.50 - offset += get_solaris_slice(file, offset) 1.51 + # MBR contains a 16 byte descriptor per partition 1.52 + partbuf = buf[poff:poff+16] 1.53 + offset = struct.unpack("<L", partbuf[8:12])[0] * SECTOR_SIZE 1.54 + type = struct.unpack("<B", partbuf[4:5])[0] 1.55 + 1.56 + # offset == 0 implies this partition is not enabled 1.57 + if offset == 0: 1.58 + continue 1.59 1.60 - if type == FDISK_PART_GPT: 1.61 - offset = get_fs_offset_gpt(file) 1.62 - 1.63 - return offset 1.64 + if type == FDISK_PART_SOLARIS or type == FDISK_PART_SOLARIS_OLD: 1.65 + try: 1.66 + offset += get_solaris_slice(file, offset) 1.67 + except RuntimeError: 1.68 + continue # no solaris magic at that offset, ignore partition 1.69 + 1.70 + if type == FDISK_PART_GPT: 1.71 + offset = get_fs_offset_gpt(file) 1.72 + 1.73 + # Active partition has 0x80 as the first byte. 1.74 + # If active, prepend to front of list, otherwise append to back. 1.75 + if struct.unpack("<c", buf[poff:poff+1]) == ('\x80',): 1.76 + part_offs.insert(0, offset) 1.77 + else: 1.78 + part_offs.append(offset) 1.79 + 1.80 + return part_offs 1.81 1.82 class GrubLineEditor(curses.textpad.Textbox): 1.83 def __init__(self, screen, startx, starty, line = ""): 1.84 @@ -734,17 +738,40 @@ if __name__ == "__main__": 1.85 bootfsargs = '"%s"' % incfg["args"] 1.86 bootfsgroup = re.findall('zfs-bootfs=(.*?)[\s\,\"]', bootfsargs) 1.87 if bootfsgroup: 1.88 - fs = fsimage.open(file, get_fs_offset(file), bootfsgroup[0]) 1.89 + bootfsoptions = bootfsgroup[0] 1.90 else: 1.91 - fs = fsimage.open(file, get_fs_offset(file)) 1.92 + bootfsoptions = "" 1.93 + 1.94 + # get list of offsets into file which start partitions 1.95 + part_offs = get_partition_offsets(file) 1.96 1.97 - chosencfg = sniff_solaris(fs, incfg) 1.98 + for offset in part_offs: 1.99 + try: 1.100 + fs = fsimage.open(file, offset, bootfsoptions) 1.101 + 1.102 + chosencfg = sniff_solaris(fs, incfg) 1.103 + 1.104 + if not chosencfg["kernel"]: 1.105 + chosencfg = sniff_netware(fs, incfg) 1.106 1.107 - if not chosencfg["kernel"]: 1.108 - chosencfg = sniff_netware(fs, incfg) 1.109 + if not chosencfg["kernel"]: 1.110 + chosencfg = run_grub(file, entry, fs, incfg["args"]) 1.111 + 1.112 + # Break as soon as we've found the kernel so that we continue 1.113 + # to use this fsimage object 1.114 + if chosencfg["kernel"]: 1.115 + break 1.116 + fs = None 1.117 1.118 - if not chosencfg["kernel"]: 1.119 - chosencfg = run_grub(file, entry, fs, incfg["args"]) 1.120 + except: 1.121 + # IOErrors raised by fsimage.open 1.122 + # RuntimeErrors raised by run_grub if no menu.lst present 1.123 + fs = None 1.124 + continue 1.125 + 1.126 + # Did looping through partitions find us a kernel? 1.127 + if not fs: 1.128 + raise RuntimeError, "Unable to find partition containing kernel" 1.129 1.130 if not_really: 1.131 bootcfg["kernel"] = "<kernel:%s>" % chosencfg["kernel"]