# # bootloader.py: anaconda bootloader shims # # Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Author(s): Erik Troan # Jeremy Katz # import isys import partedUtils import os, sys import iutil import string from flags import flags from constants import * import gettext _ = lambda x: gettext.ldgettext("anaconda", x) import logging log = logging.getLogger("anaconda") import booty import bootloaderInfo from fsset import * def bootloaderSetupChoices(anaconda): if anaconda.dir == DISPATCH_BACK: rc = anaconda.intf.messageWindow(_("Warning"), _("Your filesystems have already been activated. You " "cannot go back past this point.\n\nWould you like to " "continue with the installation?"), type="custom", custom_icon=["error","error"], custom_buttons=[_("_Exit installer"), _("_Continue")]) if rc == 0: sys.exit(0) return DISPATCH_FORWARD if anaconda.id.ksdata and anaconda.id.ksdata.bootloader.driveorder: anaconda.id.bootloader.updateDriveList(anaconda.id.ksdata.bootloader.driveorder) else: #We want the selected bootloader drive to be preferred pref = anaconda.id.bootloader.drivelist[:1] anaconda.id.bootloader.updateDriveList(pref) if iutil.isEfi() and not anaconda.id.bootloader.device: drives = anaconda.id.diskset.disks.keys() drives.sort() bootPart = None for drive in drives: disk = anaconda.id.diskset.disks[drive] part = disk.next_partition() while part: if part.is_active() and partedUtils.isEfiSystemPartition(part): bootPart = partedUtils.get_partition_name(part) break part = disk.next_partition(part) if bootPart: break if bootPart: anaconda.id.bootloader.setDevice(bootPart) dev = Device() dev.device = bootPart anaconda.id.fsset.add(FileSystemSetEntry(dev, None, fileSystemTypeGet("efi"))) # iSeries bootloader on upgrades if iutil.getPPCMachine() == "iSeries" and not anaconda.id.bootloader.device: drives = anaconda.id.diskset.disks.keys() drives.sort() bootPart = None for drive in drives: disk = anaconda.id.diskset.disks[drive] part = disk.next_partition() while part: if part.is_active() and part.native_type == 0x41: bootPart = partedUtils.get_partition_name(part) break part = disk.next_partition(part) if bootPart: break if bootPart: anaconda.id.bootloader.setDevice(bootPart) dev = Device() dev.device = bootPart anaconda.id.fsset.add(FileSystemSetEntry(dev, None, fileSystemTypeGet("PPC PReP Boot"))) choices = anaconda.id.fsset.bootloaderChoices(anaconda.id.diskset, anaconda.id.bootloader) if not choices and iutil.getPPCMachine() != "iSeries": anaconda.dispatch.skipStep("instbootloader") else: anaconda.dispatch.skipStep("instbootloader", skip = 0) anaconda.id.bootloader.images.setup(anaconda.id.diskset, anaconda.id.fsset) if anaconda.id.bootloader.defaultDevice != None and choices: keys = choices.keys() # there are only two possible things that can be in the keys # mbr and boot. boot is ALWAYS present. so if the dev isn't # listed, it was mbr and we should nicely fall back to boot if anaconda.id.bootloader.defaultDevice not in keys: log.warning("MBR not suitable as boot device; installing to partition") anaconda.id.bootloader.defaultDevice = "boot" anaconda.id.bootloader.setDevice(choices[anaconda.id.bootloader.defaultDevice][0]) elif choices and iutil.isMactel() and choices.has_key("boot"): # haccckkkk anaconda.id.bootloader.setDevice(choices["boot"][0]) elif choices and choices.has_key("mbr"): anaconda.id.bootloader.setDevice(choices["mbr"][0]) elif choices and choices.has_key("boot"): anaconda.id.bootloader.setDevice(choices["boot"][0]) bootDev = anaconda.id.fsset.getEntryByMountPoint("/") if not bootDev: bootDev = anaconda.id.fsset.getEntryByMountPoint("/boot") part = partedUtils.get_partition_by_name(anaconda.id.diskset.disks, bootDev.device.getDevice()) if part and partedUtils.end_sector_to_cyl(part.geom.dev, part.geom.end) >= 1024: anaconda.id.bootloader.above1024 = 1 def writeBootloader(anaconda): def dosync(): isys.sync() isys.sync() isys.sync() justConfigFile = not flags.setupFilesystems if anaconda.id.bootloader.defaultDevice == -1: return # now make the upgrade stuff work for kickstart too. ick. if anaconda.isKickstart and anaconda.id.bootloader.doUpgradeOnly: import checkbootloader (bootType, theDev) = checkbootloader.getBootloaderTypeAndBoot(anaconda.rootPath) anaconda.id.bootloader.doUpgradeonly = 1 if bootType == "GRUB": anaconda.id.bootloader.useGrubVal = 1 anaconda.id.bootloader.setDevice(theDev) else: anaconda.id.bootloader.doUpgradeOnly = 0 # We don't need to let the user know if we're just doing the bootloader. if not justConfigFile: w = anaconda.intf.waitWindow(_("Bootloader"), _("Installing bootloader...")) kernelList = [] otherList = [] root = anaconda.id.fsset.getEntryByMountPoint('/') if root: rootDev = root.device.getDevice() else: rootDev = None defaultDev = anaconda.id.bootloader.images.getDefault() kernelLabel = None kernelLongLabel = None for (dev, (label, longlabel, type)) in anaconda.id.bootloader.images.getImages().items(): if (dev == rootDev) or (rootDev is None and kernelLabel is None): kernelLabel = label kernelLongLabel = longlabel elif dev == defaultDev: otherList = [(label, longlabel, dev)] + otherList else: otherList.append((label, longlabel, dev)) if kernelLabel is None: log.error("unable to find default image, bailing") if not justConfigFile: w.pop() return plainLabelUsed = 0 defkern = "kernel" for (version, arch, nick) in \ anaconda.backend.kernelVersionList(anaconda.rootPath): if plainLabelUsed: kernelList.append(("%s-%s" %(kernelLabel, nick), "%s-%s" %(kernelLongLabel, nick), version)) else: kernelList.append((kernelLabel, kernelLongLabel, version)) if nick in ("hypervisor", "guest"): # XXX: *sigh* inconsistent defkern = "kernel-xen-%s" %(nick,) elif nick != "base": defkern = "kernel-%s" %(nick,) plainLabelUsed = 1 f = open(anaconda.rootPath + "/etc/sysconfig/kernel", "w+") f.write("# UPDATEDEFAULT specifies if new-kernel-pkg should make\n" "# new kernels the default\n") # only update the default if we're setting the default to linux (#156678) if rootDev == defaultDev: f.write("UPDATEDEFAULT=yes\n") else: f.write("UPDATEDEFAULT=no\n") f.write("\n") f.write("# DEFAULTKERNEL specifies the default kernel package type\n") f.write("DEFAULTKERNEL=%s\n" %(defkern,)) f.close() dosync() try: anaconda.id.bootloader.write(anaconda.rootPath, anaconda.id.fsset, anaconda.id.bootloader, anaconda.id.instLanguage, kernelList, otherList, defaultDev, justConfigFile, anaconda.intf) if not justConfigFile: w.pop() except bootloaderInfo.BootyNoKernelWarning: if not justConfigFile: w.pop() if anaconda.intf: anaconda.intf.messageWindow(_("Warning"), _("No kernel packages were installed on your " "system. Your boot loader configuration " "will not be changed.")) dosync() # return instance of the appropriate bootloader for our arch def getBootloader(): return booty.getBootloader() def hasWindows(bl): foundWindows = False for (k,v) in bl.images.getImages().iteritems(): if v[0].lower() == 'other' and v[2] in bootloaderInfo.dosFilesystems: foundWindows = True break return foundWindows