From: Brian C. Lane <bcl@xxxxxxxxxx> NOTE: This requires grub-0.97-66 to work correctly. On EFI we map the boot drive so that there is no question as to where /boot is located. This requires a change in grub to parse the EFI device path from the map command. Also make all efibootmgr invocations use PATH instead of hardcoded locations. Related: rhbz#598572 --- booty/bootloaderInfo.py | 42 +++++++++++++++++++++++++++++++++++++++--- booty/x86.py | 25 +++++++++++++++++++------ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/booty/bootloaderInfo.py b/booty/bootloaderInfo.py index 7647fb8..d9ab62e 100644 --- a/booty/bootloaderInfo.py +++ b/booty/bootloaderInfo.py @@ -599,7 +599,7 @@ class efiBootloaderInfo(bootloaderInfo): # XXX wouldn't it be nice to have a real interface to use efibootmgr from? def removeOldEfiEntries(self, instRoot): p = os.pipe() - rc = iutil.execWithRedirect('/usr/sbin/efibootmgr', [], + rc = iutil.execWithRedirect('efibootmgr', [], root = instRoot, stdout = p[1]) os.close(p[1]) if rc: @@ -618,7 +618,7 @@ class efiBootloaderInfo(bootloaderInfo): continue if string.join(fields[1:], " ") == productName: entry = fields[0][4:8] - rc = iutil.execWithRedirect('/usr/sbin/efibootmgr', + rc = iutil.execWithRedirect('efibootmgr', ["-b", entry, "-B"], root = instRoot, stdout="/dev/tty5", stderr="/dev/tty5") @@ -650,7 +650,7 @@ class efiBootloaderInfo(bootloaderInfo): bootdisk.startswith('rd/') or bootdisk.startswith('sx8/')): bootdisk = bootdisk[:-1] - argv = [ "/usr/sbin/efibootmgr", "-c" , "-w", "-L", + argv = [ "efibootmgr", "-c" , "-w", "-L", productName, "-d", "/dev/%s" % bootdisk, "-p", bootpart, "-l", "\\EFI\\redhat\\" + self.bootloader ] rc = iutil.execWithRedirect(argv[0], argv[1:], root = instRoot, @@ -658,6 +658,40 @@ class efiBootloaderInfo(bootloaderInfo): stderr = "/dev/tty5") return rc + def getEfiProductPath(self, productName, force=False): + """ Return the full EFI path of the installed product. + eg. HD(4,2c8800,64000,902c1655-2677-4455-b2a5-29d0ce835610) + + pass force=True to skip the cache and rerun efibootmgr + """ + if not force and self._efiProductPath: + return self._efiProductPath + + argv = [ "efibootmgr", "-v" ] + buf = iutil.execWithCapture(argv[0], argv[1:], + stderr="/dev/tty5") + + efiProductPath = None + for line in buf.splitlines(): + line = line.strip() + if not line: + continue + if productName in line: + efiProductPath = line[line.rfind(productName)+len(productName):].strip() + break + + if efiProductPath: + # Grab just the drive path + import re + m = re.match("(.*?\(.*?\)).*", efiProductPath) + if m: + efiProductPath = m.group(1) + else: + efiProductPath = None + + self._efiProductPath = efiProductPath + return self._efiProductPath + def installGrub(self, instRoot, bootDev, grubTarget, grubPath, cfPath): if not iutil.isEfi(): raise EnvironmentError @@ -672,6 +706,8 @@ class efiBootloaderInfo(bootloaderInfo): else: self.storage = instData.storage + self._efiProductPath = None + if iutil.isEfi(): self._configdir = "/boot/efi/EFI/redhat" self._configname = "grub.conf" diff --git a/booty/x86.py b/booty/x86.py index 39c9c88..2688e71 100644 --- a/booty/x86.py +++ b/booty/x86.py @@ -219,9 +219,10 @@ class x86BootloaderInfo(efiBootloaderInfo): grubPath = "/boot/grub" cfPath = "/boot/" - if not upgrade: - self.writeGrubConf(instRoot, bootDev, rootDev, defaultDev, kernelList, - chainList, grubTarget, grubPath, cfPath) + if not upgrade and not iutil.isEfi(): + self.writeGrubConf(instRoot, bootDev, rootDev, defaultDev, + kernelList, chainList, grubTarget, grubPath, + cfPath) # keep track of which devices are used for the device.map usedDevs = set() @@ -233,7 +234,12 @@ class x86BootloaderInfo(efiBootloaderInfo): self.writeDeviceMap(instRoot, usedDevs, upgrade) self.writeSysconfig(instRoot, grubTarget, upgrade) - return self.installGrub(instRoot, bootDev, grubTarget, grubPath, cfPath) + ret = self.installGrub(instRoot, bootDev, grubTarget, grubPath, cfPath) + if iutil.isEfi(): + self.writeGrubConf(instRoot, bootDev, rootDev, defaultDev, + kernelList, chainList, grubTarget, grubPath, + cfPath) + return ret def writeGrubConf(self, instRoot, bootDev, rootDev, defaultDev, kernelList, chainList, grubTarget, grubPath, cfPath): @@ -264,13 +270,20 @@ class x86BootloaderInfo(efiBootloaderInfo): f.write("# NOTICE: You do not have a /boot partition. " "This means that\n") f.write("# all kernel and initrd paths are relative " - "to /, eg.\n") - + "to /, eg.\n") + f.write('# root %s\n' % self.grubbyPartitionName(bootDevs[0])) f.write("# kernel %svmlinuz-version ro root=%s\n" % (cfPath, rootDev.path)) f.write("# initrd %sinitrd-[generic-]version.img\n" % (cfPath)) f.write("#boot=/dev/%s\n" % (grubTarget)) + if iutil.isEfi(): + from product import productName + # Map the target device to the full EFI path + if self.getEfiProductPath(productName): + (n, pn) = getDiskPart(bootDevs[0], self.storage) + f.write("device (%s) %s\n" % (self.grubbyDiskName(n), self.getEfiProductPath(productName))) + # get the default image to boot... we have to walk and find it # since grub indexes by where it is in the config file if defaultDev.name == rootDev.name: -- 1.7.2 _______________________________________________ Anaconda-devel-list mailing list Anaconda-devel-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/anaconda-devel-list