Use pyparted to check for bootflag [Closes: issue1248]
authorMichael Prokop <mika@grml.org>
Wed, 25 Sep 2013 12:54:06 +0000 (14:54 +0200)
committerEvgeni Golov <evgeni@golov.de>
Tue, 7 Oct 2014 05:40:39 +0000 (07:40 +0200)
The approach to check the 7th field in the MBR for the
bootable flag being set isn't enough. This fails to detect
bootable partitions if they aren't the first primary ones.

pyparted provides a way to check whether the specified
partition really has the boot flag set, so let's use this
approach, iff pyparted is available.

The check can also be completely skipped using the
--skip-bootflag parameter.

Took the get_partition_for_path function from Evgeni Golov's
https://github.com/evgeni/grml2usb/tree/pyparted with his
permission.

debian/control
grml2usb

index 11e8036..e2fbeb7 100644 (file)
@@ -19,6 +19,7 @@ Package: grml2usb
 Architecture: amd64 i386
 Depends: mtools,
          python,
+         python-parted,
          realpath,
          rsync,
          syslinux | grub-pc,
index 844d87b..9321b98 100755 (executable)
--- a/grml2usb
+++ b/grml2usb
@@ -105,6 +105,8 @@ parser.add_option("--remove-bootoption", dest="removeoption", action="append",
                   help="regex for removing existing bootoptions")
 parser.add_option("--skip-addons", dest="skipaddons", action="store_true",
                   help="do not install /boot/addons/ files")
+parser.add_option("--skip-bootflag", dest="skipbootflag", action="store_true",
+                  help="do not try to check whether the destination has the bootflag set")
 parser.add_option("--skip-grub-config", dest="skipgrubconfig", action="store_true",
                   help="skip generation of grub configuration files")
 parser.add_option("--skip-mbr", dest="skipmbr", action="store_true",
@@ -335,9 +337,28 @@ def check_uid_root():
         raise CriticalException("please run this script with uid 0 (root).")
 
 
+# for usage inside check_boot_flag
+def get_partition_for_path(path):
+    import parted
+
+    boot_dev, x = get_device_from_partition(path)
+
+    d = parted.getDevice(boot_dev)
+    disk = parted.Disk(d)
+    return disk.getPartitionByPath(path)
+
+
 def check_boot_flag(device):
     boot_dev, x = get_device_from_partition(device)
 
+    try:
+        part = get_partition_for_path(device)
+        if part.getFlag(parted.PARTITION_BOOT):
+            logging.debug("bootflag is enabled on %s" % device)
+            return
+    except ImportError, e:
+        logging.debug("could not import parted, falling back to old bootflag detection")
+
     with open(boot_dev, 'r') as image:
         data = image.read(520)
         bootcode = data[440:]
@@ -350,7 +371,7 @@ def check_boot_flag(device):
         else:
             logging.debug("bootflag is NOT enabled")
             raise VerifyException("Device %s does not have the bootflag set. "
-                "Please enable it to be able to boot." % boot_dev)
+                "Please enable it to be able to boot." % device)
 
 
 def mkfs_fat16(device):
@@ -1530,7 +1551,8 @@ def install_grml(mountpoint, device):
         remove_device_mountpoint = True
         try:
             check_for_fat(device)
-            check_boot_flag(device)
+            if not options.skipbootflag:
+                check_boot_flag(device)
             mount(device, device_mountpoint, ['-o', 'utf8,iocharset=iso8859-1'])
         except CriticalException as error:
             mount(device, device_mountpoint, "")