summaryrefslogtreecommitdiffstats
path: root/bootloader.py
diff options
context:
space:
mode:
Diffstat (limited to 'bootloader.py')
-rw-r--r--bootloader.py407
1 files changed, 407 insertions, 0 deletions
diff --git a/bootloader.py b/bootloader.py
new file mode 100644
index 000000000..8576ff370
--- /dev/null
+++ b/bootloader.py
@@ -0,0 +1,407 @@
+import isys
+import partitioning
+from translate import _
+from lilo import LiloConfigFile
+import os
+import language
+from flags import flags
+import iutil
+import string
+from log import log
+
+initrdsMade = {}
+
+class KernelArguments:
+
+ def get(self):
+ return self.args
+
+ def set(self, args):
+ self.args = args
+
+ def __init__(self):
+ cdrw = isys.ideCdRwList()
+ str = ""
+ for device in cdrw:
+ if str: str = str + " "
+ str = str + ("%s=ide-scsi" % device)
+
+ self.args = str
+
+class BootImages:
+
+ # returns dictionary of (label, devtype) pairs indexed by device
+ def getImages(self):
+ # return a copy so users can modify it w/o affecting us
+
+ dict = {}
+ for key in self.images.keys():
+ dict[key] = self.images[key]
+
+ return dict
+
+ def setImageLabel(self, dev, label):
+ self.images[dev] = (label, self.images[dev][1])
+
+ # default is a device
+ def setDefault(self, default):
+ self.default = default
+
+ def getDefault(self):
+ return self.default
+
+ def setup(self, diskSet, fsset):
+ devices = {}
+ devs = availableBootDevices(diskSet, fsset)
+ for (dev, type) in devs:
+ devices[dev] = 1
+
+ # These partitions have disappeared
+ for dev in self.images.keys():
+ if devices.has_key(dev): del self.images[dev]
+
+ # These have appeared
+ for (dev, type) in devs:
+ if not self.images.has_key(dev):
+ self.images[dev] = (None, type)
+
+ if not self.images.has_key(self.default):
+ entry = fsset.getEntryByMountPoint('/')
+ self.default = entry.device.getDevice()
+ (label, type) = self.images[self.default]
+ if not label:
+ self.images[self.default] = ("Red Hat Linux 7.2", type)
+
+ def __init__(self):
+ self.default = None
+ self.images = {}
+
+class x86BootloaderInfo:
+
+ def getDevice(self):
+ return self.device
+
+ def setDevice(self, device):
+ self.device = device
+
+ def setUseGrub(self, val):
+ self.useGrubVal = val
+
+ def useGrub(self):
+ return self.useGrubVal
+
+ def writeGrub(self, instRoot, fsset, bl, langs, kernelList, chainList,
+ defaultDev, justConfigFile):
+ images = bl.images.getImages()
+ rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
+ grubRootDev = grubbyPartitionName(rootDev)
+
+ cf = '/boot/grub/grub.conf'
+ perms = 0644
+ if os.access (instRoot + cf, os.R_OK):
+ perms = os.stat(instRoot + cf)[0] & 0777
+ os.rename(instRoot + cf,
+ instRoot + cf + '.rpmsave')
+
+ f = open(instRoot + cf, "w+")
+
+
+ bootDev = fsset.getEntryByMountPoint("/boot")
+ grubPath = "/grub"
+ cfPath = ""
+ if not bootDev:
+ bootDev = fsset.getEntryByMountPoint("/")
+ grubPath = "/boot/grub"
+ cfPath = "/boot"
+ else:
+ f.write ("# NOTICE: You have a /boot partition. This means that\n")
+ f.write ("# all kernel paths are relative to /boot/\n")
+
+ bootDev = bootDev.device.getDevice()
+
+ f.write('default=0\n')
+ f.write('timeout=30\n')
+
+ for (label, version) in kernelList:
+ kernelTag = "-" + version
+ kernelFile = cfPath + "/vmlinuz" + kernelTag
+
+ initrd = makeInitrd (kernelTag, instRoot)
+
+ f.write('title Red Hat Linux 7.2 (%s)\n' % version)
+ f.write('\troot %s\n' % grubRootDev)
+ f.write('\tkernel %s ro root=/dev/%s' % (kernelFile, rootDev))
+ if self.args.get():
+ f.write(' %s' % self.args.get())
+ f.write('\n')
+
+ if os.access (instRoot + initrd, os.R_OK):
+ f.write('\tinitrd %s\n' % (initrd[len(cfPath):], ))
+
+ f.close()
+
+ part = grubbyPartitionName(bootDev)
+ prefix = grubbyPartitionName(bootDev) + "/" + grubPath
+ cmd = "root %s\ninstall %s/i386-pc/stage1 d (%s) %s/i386-pc/stage2 p %s%s/grub.conf" % \
+ (part, grubPath, grubbyDiskName(bl.getDevice()), grubPath,
+ part, grubPath)
+
+ log("GRUB command %s", cmd)
+
+ if not justConfigFile:
+ p = os.pipe()
+ os.write(p[1], cmd + '\n')
+ os.close(p[1])
+
+ iutil.execWithRedirect('/sbin/grub' ,
+ [ "grub", "--batch" ], stdin = p[0],
+ stdout = "/dev/tty5", stderr = "/dev/tty5",
+ root = instRoot)
+ os.close(p[0])
+
+ return None
+
+ def writeLilo(self, instRoot, fsset, bl, langs, kernelList, chainList,
+ defaultDev, justConfigFile):
+ images = bl.images.getImages()
+
+ # on upgrade read in the lilo config file
+ lilo = LiloConfigFile ()
+ perms = 0644
+ if os.access (instRoot + '/etc/lilo.conf', os.R_OK):
+ perms = os.stat(instRoot + '/etc/lilo.conf')[0] & 0777
+ lilo.read (instRoot + '/etc/lilo.conf')
+ os.rename(instRoot + '/etc/lilo.conf',
+ instRoot + '/etc/lilo.conf.rpmsave')
+
+ # Remove any invalid entries that are in the file; we probably
+ # just removed those kernels.
+ for label in lilo.listImages():
+ (fsType, sl) = lilo.getImage(label)
+ if fsType == "other": continue
+
+ if not os.access(instRoot + sl.getPath(), os.R_OK):
+ lilo.delImage(label)
+
+ liloTarget = bl.getDevice()
+
+ lilo.addEntry("boot", '/dev/' + liloTarget, replace = 0)
+ lilo.addEntry("map", "/boot/map", replace = 0)
+ lilo.addEntry("install", "/boot/boot.b", replace = 0)
+ lilo.addEntry("prompt", replace = 0)
+ lilo.addEntry("timeout", "50", replace = 0)
+ message = "/boot/message"
+ for lang in language.expandLangs(langs.getDefault()):
+ fn = "/boot/message." + lang
+ if os.access(instRoot + fn, os.R_OK):
+ message = fn
+ break
+
+ lilo.addEntry("message", message, replace = 0)
+
+ if not lilo.testEntry('lba32') and not lilo.testEntry('linear'):
+ lilo.addEntry("linear", replace = 0)
+
+ rootDev = fsset.getEntryByMountPoint("/").device.getDevice()
+ if not rootDev:
+ raise RuntimeError, "Installing lilo, but there is no root device"
+
+ if rootDev == defaultDev:
+ lilo.addEntry("default", kernelList[0][0])
+ else:
+ lilo.addEntry("default", otherList[0][0])
+
+ for (label, version) in kernelList:
+ kernelTag = "-" + version
+ kernelFile = "/boot/vmlinuz" + kernelTag
+
+ try:
+ lilo.delImage(label)
+ except IndexError, msg:
+ pass
+
+ sl = LiloConfigFile(imageType = "image", path = kernelFile)
+
+ initrd = makeInitrd (kernelTag, instRoot)
+
+ sl.addEntry("label", label)
+ if os.access (instRoot + initrd, os.R_OK):
+ sl.addEntry("initrd", initrd)
+
+ sl.addEntry("read-only")
+ sl.addEntry("root", '/dev/' + rootDev)
+
+ if self.args.get():
+ sl.addEntry('append', '"%s"' % self.args.get())
+
+ lilo.addImage (sl)
+
+ for (label, device) in chainList:
+ try:
+ (fsType, sl) = lilo.getImage(label)
+ lilo.delImage(label)
+ except IndexError:
+ sl = LiloConfigFile(imageType = "other", path = device)
+ sl.addEntry("optional")
+
+ sl.addEntry("label", label)
+ lilo.addImage (sl)
+
+ # Sanity check #1. There could be aliases in sections which conflict
+ # with the new images we just created. If so, erase those aliases
+ imageNames = {}
+ for label in lilo.listImages():
+ imageNames[label] = 1
+
+ for label in lilo.listImages():
+ (fsType, sl) = lilo.getImage(label)
+ if sl.testEntry('alias'):
+ alias = sl.getEntry('alias')
+ if imageNames.has_key(alias):
+ sl.delEntry('alias')
+ imageNames[alias] = 1
+
+ # Sanity check #2. If single-key is turned on, go through all of
+ # the image names (including aliases) (we just built the list) and
+ # see if single-key will still work.
+ if lilo.testEntry('single-key'):
+ singleKeys = {}
+ turnOff = 0
+ for label in imageNames.keys():
+ l = label[0]
+ if singleKeys.has_key(l):
+ turnOff = 1
+ singleKeys[l] = 1
+ if turnOff:
+ lilo.delEntry('single-key')
+
+ lilo.write(instRoot + "/etc/lilo.conf", perms = perms)
+
+ if not justConfigFile:
+ # throw away stdout, catch stderr
+ str = iutil.execWithCapture(instRoot + '/sbin/lilo' ,
+ [ "lilo", "-r", instRoot ],
+ catchfd = 2, closefd = 1)
+ else:
+ str = ""
+
+ return str
+
+ def write(self, instRoot, fsset, bl, langs, kernelList, chainList,
+ defaultDev, justConfig):
+ if self.useGrubVal:
+ str = self.writeGrub(instRoot, fsset, bl, langs, kernelList,
+ chainList, defaultDev, justConfig)
+ else:
+ str = self.writeLilo(instRoot, fsset, bl, langs, kernelList,
+ chainList, defaultDev, justConfig)
+
+
+ def __init__(self):
+ self.args = KernelArguments()
+ self.images = BootImages()
+ self.useGrubVal = 1 # use lilo otherwise
+ self.device = None
+
+def availableBootDevices(diskSet, fsset):
+ devs = []
+ foundDos = 0
+ for (dev, type) in diskSet.partitionTypes():
+ if type == 'FAT' and not foundDos:
+ foundDos = 1
+ isys.makeDevInode(dev, '/tmp/' + dev)
+
+ try:
+ bootable = isys.checkBoot('/tmp/' + dev)
+ devs.append((dev, type))
+ except:
+ pass
+ elif type == 'ntfs' or type =='hpfs':
+ devs.append((dev, type))
+
+ devs.append((fsset.getEntryByMountPoint('/').device.getDevice(), 'ext2'))
+
+ devs.sort()
+
+ return devs
+
+def partitioningComplete(dispatch, bl, fsset, diskSet):
+ choices = fsset.bootloaderChoices(diskSet)
+ if not choices:
+ dispatch.skipStep("instbootloader")
+ else:
+ dispatch.skipStep("instbootloader", skip = 0)
+
+ bl.images.setup(diskSet, fsset)
+
+def writeBootloader(intf, instRoot, fsset, bl, langs, comps):
+ justConfigFile = not flags.setupFilesystems
+
+ w = intf.waitWindow(_("Bootloader"), _("Installing bootloader..."))
+
+ kernelList = []
+ otherList = []
+ rootDev = fsset.getEntryByMountPoint('/').device.getDevice()
+ defaultDev = bl.images.getDefault()
+
+ for (dev, (label, type)) in bl.images.getImages().items():
+ if dev == rootDev:
+ kernelLabel = label
+ elif dev == defaultDev:
+ otherList = [(label, dev)] + otherList
+ else:
+ otherList.append(label, dev)
+
+ plainLabelUsed = 0
+ for (version, nick) in comps.kernelVersionList():
+ if plainLabelUsed:
+ kernelList.append(kernelLabel + "-" + nick, version)
+ else:
+ kernelList.append(kernelLabel, version)
+ plainLabelUsed = 1
+
+ bl.write(instRoot, fsset, bl, langs, kernelList, otherList, defaultDev,
+ justConfigFile)
+
+ w.pop()
+
+def makeInitrd (kernelTag, instRoot):
+ global initrdsMade
+
+ initrd = "/boot/initrd%s.img" % (kernelTag, )
+
+ if not initrdsMade.has_key(initrd) and flags.setupFilesystems:
+ iutil.execWithRedirect("/sbin/mkinitrd",
+ [ "/sbin/mkinitrd",
+ "--ifneeded",
+ "-f",
+ initrd,
+ kernelTag[1:] ],
+ stdout = None, stderr = None, searchPath = 1,
+ root = instRoot)
+ initrdsMade[kernelTag] = 1
+
+ return initrd
+
+def grubbyDiskName(name):
+ drives = isys.hardDriveDict().keys()
+ drives.sort (isys.compareDrives)
+
+ return "hd%d" % drives.index(name)
+
+def grubbyPartitionName(dev):
+ cut = -1
+ if dev[-2] in string.digits:
+ cut = -2
+
+ partNum = int(dev[cut:]) - 1
+ name = dev[:cut]
+
+ # hack off the trailing 'p' from /dev/cciss/*, for example
+ if name[-1] == 'p':
+ for letter in name:
+ if letter not in string.letters and letter != "/":
+ name = name[:-1]
+ break
+
+ return "(%s,%d)" % (grubbyDiskName(name), partNum)