[elbe-devel] [PATCH 2/3] Add support for UEFI boot with grub

Martin Kaistra martin.kaistra at linutronix.de
Mon Mar 26 10:10:57 CEST 2018


If the package grub-efi-amd64 is installed and <grub-install/> is
used in the xml, try to install grub on the boot partition
to the default fallback location \EFI\boot\bootx64.efi

Use grub_fw_type to differentiate between "bios" and "efi", so we can
call a seperate grub installer function for efi (class grubinstaller202efi)
which is based on the version for bios (class grubinstaller202)

This is currently specific to amd64, but it shouldn't be too difficult
to expand it to other target platforms which support uefi.

Signed-off-by: Martin Kaistra <martin.kaistra at linutronix.de>
---
 elbepack/efilesystem.py |   5 ++-
 elbepack/elbeproject.py |   8 +++-
 elbepack/hdimg.py       | 108 ++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 114 insertions(+), 7 deletions(-)

diff --git a/elbepack/efilesystem.py b/elbepack/efilesystem.py
index e1bab181..a2781b5f 100644
--- a/elbepack/efilesystem.py
+++ b/elbepack/efilesystem.py
@@ -309,7 +309,7 @@ class TargetFs(ChRootFilesystem):
                     f.write(fstab.get_str())
             f.close()
 
-    def part_target(self, targetdir, grub_version):
+    def part_target(self, targetdir, grub_version, grub_fw_type):
 
         # create target images and copy the rfs into them
         self.images = do_hdimg(
@@ -317,7 +317,8 @@ class TargetFs(ChRootFilesystem):
             self.xml,
             targetdir,
             self,
-            grub_version)
+            grub_version,
+            grub_fw_type)
 
         if self.xml.has("target/package/tar"):
             targz_name = self.xml.text("target/package/tar/name")
diff --git a/elbepack/elbeproject.py b/elbepack/elbeproject.py
index be2b25f5..047020bc 100644
--- a/elbepack/elbeproject.py
+++ b/elbepack/elbeproject.py
@@ -471,15 +471,21 @@ class ElbeProject (object):
                 grub_version = 199
             else:
                 grub_version = 202
+                grub_fw_type = "bios"
+        elif self.get_rpcaptcache().is_installed('grub-efi-amd64'):
+            grub_version = 202
+            grub_fw_type = "efi"
         elif self.get_rpcaptcache().is_installed('grub-legacy'):
             self.log.printo("package grub-legacy is installed, "
                             "this is obsolete, skipping grub")
             grub_version = 0
+            grub_fw_type = ""
         else:
             self.log.printo("package grub-pc is not installed, skipping grub")
             # version 0 == skip_grub
             grub_version = 0
-        self.targetfs.part_target(self.builddir, grub_version)
+            grub_fw_type = ""
+        self.targetfs.part_target(self.builddir, grub_version, grub_fw_type)
 
         # Build cdrom images
         self.repo_images = []
diff --git a/elbepack/hdimg.py b/elbepack/hdimg.py
index e1dc2aae..ead4c923 100644
--- a/elbepack/hdimg.py
+++ b/elbepack/hdimg.py
@@ -287,6 +287,92 @@ class grubinstaller202(grubinstaller_base):
             self.outf.do("losetup -d /dev/poop0", allow_fail=True)
 
 
+class grubinstaller202efi(grubinstaller_base):
+
+    def install(self, target):
+        if not self.root:
+            return
+
+        imagemnt = os.path.join(target, "imagemnt")
+        try:
+            self.outf.do('cp -a /dev/loop0 /dev/poop0')
+
+            self.outf.do('losetup /dev/poop0 "%s"' % self.root.filename)
+            self.outf.do('kpartx -as /dev/poop0')
+            self.outf.do(
+                'mount /dev/mapper/poop0p%d %s' %
+                (self.root.partnum, imagemnt))
+
+            if self.boot:
+                self.outf.do(
+                    'mount /dev/mapper/poop0p%d %s' %
+                    (self.boot.partnum, os.path.join(
+                        imagemnt, "boot")))
+
+            self.outf.do(
+                "mount --bind /dev %s" %
+                os.path.join(
+                    imagemnt,
+                    "dev"))
+            self.outf.do(
+                "mount --bind /proc %s" %
+                os.path.join(
+                    imagemnt,
+                    "proc"))
+            self.outf.do(
+                "mount --bind /sys %s" %
+                os.path.join(
+                    imagemnt,
+                    "sys"))
+
+            self.outf.do('mkdir -p "%s"' % os.path.join(imagemnt, "boot/grub"))
+
+            devmap = open(os.path.join(imagemnt, "boot/grub/device.map"), "w")
+            devmap.write("(hd0) /dev/poop0\n")
+            devmap.close()
+
+            self.outf.do("chroot %s  update-initramfs -u -k all" % imagemnt)
+            self.outf.do("chroot %s  update-grub2" % imagemnt)
+
+            self.outf.do(
+                "chroot %s grub-install --target=x86_64-efi "
+                "--efi-directory=/boot --removable --no-floppy /dev/poop0" %
+                (imagemnt))
+
+        finally:
+            os.unlink(os.path.join(imagemnt, "boot/grub/device.map"))
+            self.outf.do(
+                "umount %s" %
+                os.path.join(
+                    imagemnt,
+                    "dev"),
+                allow_fail=True)
+            self.outf.do(
+                "umount %s" %
+                os.path.join(
+                    imagemnt,
+                    "proc"),
+                allow_fail=True)
+            self.outf.do(
+                "umount %s" %
+                os.path.join(
+                    imagemnt,
+                    "sys"),
+                allow_fail=True)
+
+            if self.boot:
+                self.outf.do(
+                    'umount /dev/mapper/poop0p%d' %
+                    self.boot.partnum, allow_fail=True)
+
+            self.outf.do(
+                'umount /dev/mapper/poop0p%d' %
+                self.root.partnum, allow_fail=True)
+
+            self.outf.do('kpartx -d /dev/poop0', allow_fail=True)
+            self.outf.do("losetup -d /dev/poop0", allow_fail=True)
+
+
 class grubinstaller199(grubinstaller_base):
 
     def install(self, target):
@@ -480,7 +566,7 @@ def create_logical_partitions(
         current_sector += lpart.getLength()
 
 
-def do_image_hd(outf, hd, fslabel, target, grub_version):
+def do_image_hd(outf, hd, fslabel, target, grub_version, grub_fw_type):
 
     sector_size = 512
     s = size_to_int(hd.text("size"))
@@ -500,6 +586,8 @@ def do_image_hd(outf, hd, fslabel, target, grub_version):
 
     if grub_version == 199:
         grub = grubinstaller199(outf)
+    elif grub_version == 202 and grub_fw_type == "efi":
+        grub = grubinstaller202efi(outf)
     elif grub_version == 202:
         grub = grubinstaller202(outf)
     else:
@@ -574,7 +662,7 @@ def add_binary_blob(outf, hd, target):
             bs))
 
 
-def do_hdimg(outf, xml, target, rfs, grub_version):
+def do_hdimg(outf, xml, target, rfs, grub_version, grub_fw_type):
     # list of created files
     img_files = []
 
@@ -623,11 +711,23 @@ def do_hdimg(outf, xml, target, rfs, grub_version):
         # Now iterate over all images and create filesystems and partitions
         for i in xml.tgt.node("images"):
             if i.tag == "msdoshd":
-                img = do_image_hd(outf, i, fslabel, target, grub_version)
+                img = do_image_hd(
+                    outf,
+                    i,
+                    fslabel,
+                    target,
+                    grub_version,
+                    grub_fw_type)
                 img_files.append(img)
 
             if i.tag == "gpthd":
-                img = do_image_hd(outf, i, fslabel, target, grub_version)
+                img = do_image_hd(
+                    outf,
+                    i,
+                    fslabel,
+                    target,
+                    grub_version,
+                    grub_fw_type)
                 img_files.append(img)
 
             if i.tag == "mtd":
-- 
2.11.0




More information about the elbe-devel mailing list