+def install_mir_mbr(mbrtemplate, device, partition, ismirbsdmbr=True):
+ """install 'mbr' master boot record (MBR) on a device
+
+ Retrieve the partition table from "device", install an MBR from the
+ "mbrtemplate" file, set the "partition" (0..3) active, and install the
+ result back to "device".
+
+ @mbrtemplate: default MBR file
+
+ @device: name of a file assumed to be a hard disc (or USB stick) image, or
+ something like "/dev/sdb"
+
+ @partition: must be a number between 0 and 3, inclusive
+
+ @mbrtemplate: must be a valid MBR file of at least 440 (or 439 if
+ ismirbsdmbr) bytes.
+
+ @ismirbsdmbr: if true then ignore the active flag, set the mirbsdmbr
+ specific flag to 0/1/2/3 and set the MBR's default value accordingly. If
+ false then leave the mirbsdmbr specific flag set to FFh, set all
+ active flags to 0 and set the active flag of the partition to 80h. Note:
+ behaviour of mirbsdmbr: if flag = 0/1/2/3 then use it, otherwise search for
+ the active flag."""
+
+ logging.info("Installing default MBR")
+
+ if not os.path.isfile(mbrtemplate):
+ logging.critical("Error: %s can not be read.", mbrtemplate)
+ raise CriticalException("Error installing MBR (either try --syslinux-mbr or install missing file?)")
+
+ if (partition < 0) or (partition > 3):
+ raise ValueError("partition must be between 0 and 3")
+
+ if ismirbsdmbr:
+ nmbrbytes = 439
+ else:
+ nmbrbytes = 440
+
+ tmpf = tempfile.NamedTemporaryFile()
+
+ logging.debug("executing: dd if='%s' of='%s' bs=512 count=1", device, tmpf.name)
+ proc = subprocess.Popen(["dd", "if=%s" % device, "of=%s" % tmpf.name, "bs=512", "count=1"], stderr=file(os.devnull, "r+"))
+ proc.wait()
+ if proc.returncode != 0:
+ raise Exception("error executing dd (first run)")
+
+ logging.debug("executing: dd if=%s of=%s bs=%s count=1 conv=notrunc", mbrtemplate,
+ tmpf.name, nmbrbytes)
+ proc = subprocess.Popen(["dd", "if=%s" % mbrtemplate, "of=%s" % tmpf.name, "bs=%s" % nmbrbytes,
+ "count=1", "conv=notrunc"], stderr=file(os.devnull, "r+"))
+ proc.wait()
+ if proc.returncode != 0:
+ raise Exception("error executing dd (second run)")
+
+ mbrcode = tmpf.file.read(512)
+ if len(mbrcode) < 512:
+ raise EOFError("MBR size (%d) < 512" % len(mbrcode))
+
+ if ismirbsdmbr:
+ mbrcode = mbrcode[0:439] + chr(partition) + \
+ mbrcode[440:510] + "\x55\xAA"
+ else:
+ actives = ["\x00", "\x00", "\x00", "\x00"]
+ actives[partition] = "\x80"
+ mbrcode = mbrcode[0:446] + actives[0] + \
+ mbrcode[447:462] + actives[1] + \
+ mbrcode[463:478] + actives[2] + \
+ mbrcode[479:494] + actives[3] + \
+ mbrcode[495:510] + "\x55\xAA"
+
+ tmpf.file.seek(0)
+ tmpf.file.truncate()
+ tmpf.file.write(mbrcode)
+ tmpf.file.close()
+
+ logging.debug("executing: dd if='%s' of='%s' bs=512 count=1 conv=notrunc", tmpf.name, device)
+ proc = subprocess.Popen(["dd", "if=%s" % tmpf.name, "of=%s" % device, "bs=512", "count=1",
+ "conv=notrunc"], stderr=file(os.devnull, "r+"))
+ proc.wait()
+ if proc.returncode != 0:
+ raise Exception("error executing dd (third run)")
+ del tmpf
+
+
+def handle_syslinux_mbr(device):
+ """Install syslinux master boot record on given device