diff --git a/CHANGELOG b/CHANGELOG
index c7a4bef3..ef4b1ba1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,17 @@
+Version - 8.9.0
+---------------
+* Support for GPT based USB disks. BIOS mode works only under USB created under Linux. UEFI for on Windows and Linux
+* Added command line option to install sysinux on multibootusb director (use -s or --syslinux)
+* Added command line option to direct ISO writing to USB disk (use -r or --raw)
+* Boot ISO and IMG directly using memdisk
+* Added feature for selecting ISO, IMG, Zip and all files options in file chooser dialog
+* Corrected path to menu.lst file for distrs based on grub4dos
+* Fix for crash when multicard reader is inserted on the system without a SD card
+* Correctly detect USB disk information using udisk2-dbus without crash under Linux
+* Fixed an issue where using a path with spaces would cause a qemu boot error
+* If distro is not supported, ISO is automatically added using memdisk. You can uninstall later if it does not work
+* Added Nano Linux
+
Version - 8.8.0
---------------
* Fix for crash when listing fixed partition
diff --git a/data/EFI/BOOT/bootx64-gpt.efi b/data/EFI/BOOT/bootx64-gpt.efi
new file mode 100644
index 00000000..6751971f
Binary files /dev/null and b/data/EFI/BOOT/bootx64-gpt.efi differ
diff --git a/data/EFI/BOOT/bootx64-msdos.efi b/data/EFI/BOOT/bootx64-msdos.efi
new file mode 100644
index 00000000..84c47456
Binary files /dev/null and b/data/EFI/BOOT/bootx64-msdos.efi differ
diff --git a/data/multibootusb/grub/core-gpt.img b/data/multibootusb/grub/core-gpt.img
new file mode 100644
index 00000000..385e0ca8
Binary files /dev/null and b/data/multibootusb/grub/core-gpt.img differ
diff --git a/data/multibootusb/grub/core-msdos.img b/data/multibootusb/grub/core-msdos.img
new file mode 100644
index 00000000..d81bc24a
Binary files /dev/null and b/data/multibootusb/grub/core-msdos.img differ
diff --git a/data/tools/EFI/BOOT/bootx64-gpt.efi b/data/tools/EFI/BOOT/bootx64-gpt.efi
new file mode 100644
index 00000000..6751971f
Binary files /dev/null and b/data/tools/EFI/BOOT/bootx64-gpt.efi differ
diff --git a/data/tools/EFI/BOOT/bootx64-msdos.efi b/data/tools/EFI/BOOT/bootx64-msdos.efi
new file mode 100644
index 00000000..84c47456
Binary files /dev/null and b/data/tools/EFI/BOOT/bootx64-msdos.efi differ
diff --git a/data/tools/gdisk/gdisk.exe b/data/tools/gdisk/gdisk.exe
new file mode 100644
index 00000000..237f004e
Binary files /dev/null and b/data/tools/gdisk/gdisk.exe differ
diff --git a/data/tools/gdisk/list-disk.txt b/data/tools/gdisk/list-disk.txt
new file mode 100644
index 00000000..61f1273f
--- /dev/null
+++ b/data/tools/gdisk/list-disk.txt
@@ -0,0 +1 @@
+list disk
\ No newline at end of file
diff --git a/data/tools/gptmbr.bin b/data/tools/gptmbr.bin
new file mode 100644
index 00000000..c9781b0f
Binary files /dev/null and b/data/tools/gptmbr.bin differ
diff --git a/data/version.txt b/data/version.txt
index 3b682537..e5c15102 100644
--- a/data/version.txt
+++ b/data/version.txt
@@ -1 +1 @@
-8.8.0
+8.9.0
diff --git a/multibootusb b/multibootusb
index 3340d351..05a6f551 100644
--- a/multibootusb
+++ b/multibootusb
@@ -101,7 +101,7 @@ Example for writing ISO image to target USB disk (will destroy data on USB disk)
Windows:
python3 multibootusb -c -i -r ../../favourite.iso -t G:
''')
- exit(2)
+ sys.exit(2)
def start_gui():
@@ -121,9 +121,9 @@ if __name__ == '__main__':
admin.runAsAdmin()
sys.exit(0)
try:
- opts, args = getopt.getopt(sys.argv[1:], 'i:t:yvhcudr',
+ opts, args = getopt.getopt(sys.argv[1:], 'i:t:yvhcudrs',
['iso=', 'target=', 'yes', 'version', 'help', 'command', 'uninstall', 'debug',
- 'raw'])
+ 'raw', 'syslinux'])
except getopt.GetoptError:
usage()
sys.exit(2)
@@ -151,6 +151,8 @@ if __name__ == '__main__':
config.yes = True
elif opt in ('-r', '--raw'):
config.cli_dd = True
+ elif opt in ('-s', '--syslinux'):
+ config.cli_syslinux = True
else:
gui = True
#start_gui()
@@ -174,6 +176,8 @@ if gui is False:
elif config.image_path is '' and config.usb_disk is '':
log('\nNo option provided. See the usage below.')
usage()
+ elif config.cli_syslinux is True and config.usb_disk is not '':
+ cli_install_syslinux()
elif config.image_path is '' or config.usb_disk is '':
log('\nOptions \'-i\' and \'-t\' must be supplied together. See the usage below.')
usage()
diff --git a/scripts/_7zip.py b/scripts/_7zip.py
index 668ab4e8..d5b16bb5 100644
--- a/scripts/_7zip.py
+++ b/scripts/_7zip.py
@@ -75,7 +75,8 @@ def list_iso(iso_link, suppress_out=True):
file_list = []
_cmd = _7zip + ' l ' + gen.quote(iso_link) + suppress_out
try:
- _cmd_out = subprocess.check_output(_cmd, stderr=subprocess.PIPE, shell=True).decode('utf-8', 'ignore').splitlines()
+ _cmd_out = subprocess.check_output(_cmd, stderr=subprocess.PIPE, stdin=subprocess.DEVNULL,
+ shell=True).decode('utf-8', 'ignore').splitlines()
except Exception as e:
gen.log(e)
_cmd_out = ''
@@ -84,18 +85,6 @@ def list_iso(iso_link, suppress_out=True):
line = line.split()
_path = line[-1]
file_list.append(_path)
- '''
- for line in _cmd_out:
- line = line.split()
- if '.....' in line:
- if gen.has_digit(line[2]) or gen.has_digit(line[4]):
- if len(line) > 6:
- f_path = " ".join(line[5:])
- file_list.append(f_path)
- else:
- f_path = line[-1]
- file_list.append(f_path)
- '''
return file_list
diff --git a/scripts/config.py b/scripts/config.py
index ed997560..3a9c5083 100644
--- a/scripts/config.py
+++ b/scripts/config.py
@@ -27,6 +27,8 @@
process_exist = None
yes = False
cli_dd = False
+cli_syslinux = False
+usb_gpt = ''
imager_iso_link = ""
imager_usb_disk_selected = ""
diff --git a/scripts/gen.py b/scripts/gen.py
index d024aaca..5f832731 100644
--- a/scripts/gen.py
+++ b/scripts/gen.py
@@ -229,6 +229,23 @@ def copy_mbusb_dir_usb(usb_disk):
else:
log('EFI directory already exist. Not copying.')
+ # For backward compatibility
+ if not os.path.exists(os.path.join(usb_mount_path, 'EFI', 'BOOT', 'bootx64-gpt.efi')):
+ shutil.copy(resource_path(os.path.join('data', 'EFI', 'BOOT', 'bootx64-gpt.efi')),
+ os.path.join(usb_mount_path, 'EFI', 'BOOT', 'bootx64-gpt.efi'))
+
+ if not os.path.exists(os.path.join(usb_mount_path, 'EFI', 'BOOT', 'bootx64-msdos.efi')):
+ shutil.copy(resource_path(os.path.join('data', 'EFI', 'BOOT', 'bootx64-msdos.efi')),
+ os.path.join(usb_mount_path, 'EFI', 'BOOT', 'bootx64-msdos.efi'))
+
+ if not os.path.exists(os.path.join(usb_mount_path, 'multibootusb', 'grub', 'core-gpt.img')):
+ shutil.copy(resource_path(os.path.join('data', 'multibootusb', 'grub', 'core-gpt.img')),
+ os.path.join(usb_mount_path, 'multibootusb', 'grub', 'core-gpt.img'))
+
+ if not os.path.exists(os.path.join(usb_mount_path, 'multibootusb', 'grub', 'core-msdos.img')):
+ shutil.copy(resource_path(os.path.join('data', 'multibootusb', 'grub', 'core-msdos.img')),
+ os.path.join(usb_mount_path, 'multibootusb', 'grub', 'core-msdos.img'))
+
return result
diff --git a/scripts/gui/about.ui b/scripts/gui/about.ui
index 2d92633d..be6770e9 100644
--- a/scripts/gui/about.ui
+++ b/scripts/gui/about.ui
@@ -25,7 +25,7 @@
-
- <html><head/><body><p align="center">An advanced bootable usb creator with option to install/uninstall multiple distros.</p><p align="center">This software is written in Python and PyQt. </p><p align="center">Copyright 2010-2017 Sundar</p><p align="center"><span style=" font-weight:600;">Author(s)</span>: Sundar, Ian Bruce, LiQiong Lee and Alin Trăistaru (alindt)</p><p align="center"><span style=" font-weight:600;">Licence</span>: GPL version 2 or later</p><p align="center"><span style=" font-weight:600;">Home page</span>: <a href=" http://multibootusb.org"><span style=" text-decoration: underline; color:#0000ff;">http://multibootusb.org</span></a></p><p align="center"><span style=" font-weight:600;">Help/Email</span>: feedback.multibootusb@gmail.com</p><p align="center"><span style=" font-weight:600;">Source Code</span>: <a href="https://github.com/mbusb/multibootusb"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/mbusb/multibootusb</span></a></p><p><br/></p></body></html>
+ <html><head/><body><p align="center">An advanced bootable usb creator with option to install/uninstall multiple distros.</p><p align="center">This software is written in Python and PyQt. </p><p align="center">Copyright 2010-2017 Sundar</p><p align="center"><span style=" font-weight:600;">Author(s)</span>: Sundar, Ian Bruce, LiQiong Lee and Alin Trăistaru (alindt)</p><p align="center"><span style=" font-weight:600;">Licence</span>: GPL version 2 or later</p><p align="center"><span style=" font-weight:600;">Home page</span>: <a href="http://multibootusb.org"><span style=" text-decoration: underline; color:#0000ff;">http://multibootusb.org</span></a></p><p align="center"><span style=" font-weight:600;">Help/Email</span>: feedback.multibootusb@gmail.com</p><p align="center"><span style=" font-weight:600;">Source Code</span>: <a href="https://github.com/mbusb/multibootusb"><span style=" text-decoration: underline; color:#0000ff;">https://github.com/mbusb/multibootusb</span></a></p><p><br/></p></body></html>
diff --git a/scripts/gui/ui_about.py b/scripts/gui/ui_about.py
index 4f8246f5..c16b68df 100644
--- a/scripts/gui/ui_about.py
+++ b/scripts/gui/ui_about.py
@@ -48,7 +48,7 @@ def setupUi(self, About):
def retranslateUi(self, About):
_translate = QtCore.QCoreApplication.translate
About.setWindowTitle(_translate("About", "Dialog"))
- self.label_6.setText(_translate("About", "
An advanced bootable usb creator with option to install/uninstall multiple distros.
This software is written in Python and PyQt.
Copyright 2010-2017 Sundar
Author(s): Sundar, Ian Bruce, LiQiong Lee and Alin Trăistaru (alindt)
Licence: GPL version 2 or later
Home page: http://multibootusb.org
Help/Email: feedback.multibootusb@gmail.com
Source Code: https://github.com/mbusb/multibootusb
"))
+ self.label_6.setText(_translate("About", "An advanced bootable usb creator with option to install/uninstall multiple distros.
This software is written in Python and PyQt.
Copyright 2010-2017 Sundar
Author(s): Sundar, Ian Bruce, LiQiong Lee and Alin Trăistaru (alindt)
Licence: GPL version 2 or later
Home page: http://multibootusb.org
Help/Email: feedback.multibootusb@gmail.com
Source Code: https://github.com/mbusb/multibootusb
"))
self.button_close.setText(_translate("About", "Close"))
@@ -60,4 +60,3 @@ def retranslateUi(self, About):
ui.setupUi(About)
About.show()
sys.exit(app.exec_())
-
diff --git a/scripts/iso.py b/scripts/iso.py
index 6c46fbf6..93a20c81 100644
--- a/scripts/iso.py
+++ b/scripts/iso.py
@@ -60,12 +60,20 @@ def iso_size(iso_link):
return os.path.getsize(iso_link)
+def is_readable(iso_link):
+ return os.access(iso_link, os.R_OK)
+
+
def is_bootable(iso_link):
"""
Check if an ISO has the ability to boot.
:return: True if ISO is bootable and False if not.
"""
- iso9660fs = ISO9660(iso_link)
+ try:
+ iso9660fs = ISO9660(iso_link)
+ except IOError as e:
+ log(str(e))
+ raise
isBootable = iso9660fs.checkISOBootable()
return bool(isBootable)
diff --git a/scripts/isodump3.py b/scripts/isodump3.py
index f6ee215c..8c536754 100644
--- a/scripts/isodump3.py
+++ b/scripts/isodump3.py
@@ -44,21 +44,21 @@
E_DEVICEFILE = -2 # can't write device file
class PrimaryVolume(Structure):
- def __init__(self):
- self.sysIdentifier = ""
- self.volIdentifier = ""
- self.volSize = 0
- self.volSeq = 0
- self.blockSize = 0
- self.ptSize = 0
- self.ptLRd = 0
- self.fsVer = 0
- self.rootLoc = 0
- self.rootTotal = 0
+ def __init__(self):
+ self.sysIdentifier = ""
+ self.volIdentifier = ""
+ self.volSize = 0
+ self.volSeq = 0
+ self.blockSize = 0
+ self.ptSize = 0
+ self.ptLRd = 0
+ self.fsVer = 0
+ self.rootLoc = 0
+ self.rootTotal = 0
class Rrip(Structure):
def __init__(self):
- self.offset = -1
+ self.offset = -1
self.altname = ""
self.devH = 0
self.devL = 0
@@ -106,7 +106,10 @@ def __init__(self, isofile):
f = open(isofile, 'rb')
except(IOError):
sys.stderr.write("can't open {0}".format(isofile))
- sys.exit(-1)
+ raise
+
+ if os.path.getsize(isofile) == 0:
+ raise IOError("File {0} appears to be empty".format(isofile))
self.isoFile = f
self.priVol = None
@@ -803,4 +806,3 @@ def usage():
else:
gen.log("writeDir(%s)->(%s) with pattern(%s)"%(isodir, o_path, pattern))
sys.exit(iso9660fs.writeDir(isodir, o_path, pattern, r, True))
-
diff --git a/scripts/mbusb_cli.py b/scripts/mbusb_cli.py
index 71e3a9b2..a01cb0dc 100644
--- a/scripts/mbusb_cli.py
+++ b/scripts/mbusb_cli.py
@@ -16,6 +16,7 @@
from .syslinux import *
from .install import *
from . import imager
+from . import syslinux
def read_input_uninstall():
@@ -99,6 +100,7 @@ def iso_install(iso_image):
install_progress()
syslinux_distro_dir(config.usb_disk, iso_image, _distro)
syslinux_default(config.usb_disk)
+ replace_grub_binary()
update_distro_cfg_files(iso_image, config.usb_disk, _distro)
log('Finished installing ' + iso.iso_basename(iso_image))
else:
@@ -110,6 +112,7 @@ def iso_install(iso_image):
install_progress()
syslinux_distro_dir(config.usb_disk, iso_image, _distro)
syslinux_default(config.usb_disk)
+ replace_grub_binary()
update_distro_cfg_files(iso_image, config.usb_disk, _distro)
log('Finished installing ' + iso.iso_basename(iso_image))
else:
@@ -167,3 +170,40 @@ def cli_dd():
else:
log('\nAuto install is not recommended in direct writing method. Please choose without \'-y\' option.\n')
sys.exit(2)
+
+
+def cli_install_syslinux():
+ """
+ Install syslinux on a target USB disk. It will installed on 'multibootusb' directory
+ :return:
+ """
+ if platform.system() == 'Linux':
+ if config.usb_disk[-1].isdigit() is not True:
+ log('Selected USB disk is not a partition. Please enter the partition eg. \'/dev/sdb1\'')
+ sys.exit(2)
+ elif is_root() is False:
+ log("You need to have root privileges to run this script.\nPlease try again using admin privilege (sudo).")
+ sys.exit(2)
+
+ if config.yes is not True:
+ log('\nInitiating process for installing syslinux on ' + config.usb_disk)
+ log('Selected target device is : ' + quote(config.usb_disk))
+ log('Syslinux install directory : \'multibootusb\'\n')
+ log('Please confirm the option.')
+ log('Y/y/Yes/yes/YES or N/n/No/no/NO')
+ if read_input_yes() is True:
+ if syslinux.syslinux_default(config.usb_disk) is True:
+ log('Syslinux successfully installed on ' + config.usb_disk)
+ else:
+ log('Failed to install syslinux on ' + config.usb_disk)
+ else:
+ log('Operation cancelled by user. Exiting...')
+ sys.exit(2)
+ else:
+ log('\nSkipping user input and installing syslinux on ' + config.usb_disk)
+ if syslinux.syslinux_default(config.usb_disk) is True:
+ log('Syslinux successfully installed on ' + config.usb_disk)
+ else:
+ log('Failed to install syslinux on ' + config.usb_disk)
+ sys.exit(2)
+
diff --git a/scripts/mbusb_gui.py b/scripts/mbusb_gui.py
index f47bc595..a35d7ce9 100644
--- a/scripts/mbusb_gui.py
+++ b/scripts/mbusb_gui.py
@@ -13,6 +13,7 @@
from PyQt5 import QtCore, QtGui, QtWidgets
import subprocess
import time
+import webbrowser
from scripts.gui.ui_multibootusb import Ui_MainWindow
from scripts.gui.ui_about import Ui_About
from . import usb
@@ -130,7 +131,7 @@ def onAboutClick(self):
about.setWindowTitle("About MultiBootUSB - " + mbusb_version())
about.setWindowIcon(QtGui.QIcon(resource_path(os.path.join("data", "tools", "multibootusb.png"))))
about.ui.button_close.clicked.connect(about.close)
-
+ about.ui.label_6.linkActivated.connect(webbrowser.open_new_tab)
about.exec_()
def onComboChange(self):
@@ -157,6 +158,9 @@ def onComboChange(self):
self.ui.usb_type.setText(config.usb_details.get('devtype', ""))
self.ui.usb_fs.setText(config.usb_details.get('file_system', ""))
+ # Get the GPT status of the disk and store it on a variable
+ usb.gpt_device(config.usb_disk)
+
self.update_list_box(config.usb_disk)
self.ui_update_persistence()
else:
@@ -214,6 +218,22 @@ def browse_iso(self):
'Img Files(*.img);; All Files(*.*)')[0]
if config.image_path:
+ # sanity checks
+ if not is_readable(config.image_path):
+ QtWidgets.QMessageBox.critical(
+ self,
+ "ISO Not readable",
+ "Sorry, the file \"{0}\" is not readable.".format(config.image_path)
+ )
+ return
+ if iso_size(config.image_path) == 0:
+ QtWidgets.QMessageBox.critical(
+ self,
+ "ISO is an empty file",
+ "Sorry, the file \"{0}\" contains no data.".format(config.image_path)
+ )
+ return
+
default_dir_path = os.path.dirname(config.image_path)
gen.write_to_file(preference_file_path, default_dir_path)
@@ -309,6 +329,7 @@ def install_syslinux(self):
self.ui.statusbar.showMessage(str("Status: Installing Syslinux..."))
syslinux_distro_dir(config.usb_disk, config.image_path, config.distro)
syslinux_default(config.usb_disk)
+ replace_grub_binary()
update_distro_cfg_files(config.image_path, config.usb_disk, config.distro, config.persistence)
self.update_list_box(config.usb_disk)
if sys.platform.startswith("linux"):
@@ -508,14 +529,23 @@ def onCreateClick(self):
"No space available on " + config.usb_disk)
self.ui_enable_controls()
else:
- reply = QtWidgets.QMessageBox.question(self, 'Review selection...',
- 'Selected USB disk: %s\n' % config.usb_disk +
- 'USB mount point: %s\n' % config.usb_mount +
- 'Selected distro: %s\n\n' % iso_name(
- config.image_path) +
- 'Proceed with installation?',
- QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
- QtWidgets.QMessageBox.No)
+ if config.distro == 'memdisk_iso':
+ reply = QtWidgets.QMessageBox.question(self, 'Review selection...',
+ 'The ISO sleceted is not supported at the moment.\n'
+ 'You can try booting ISO using memdisk.\n'
+ 'Distro can be uninstalled anytime from main menu.\n\n'
+ 'Proceed with installation?',
+ QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
+ QtWidgets.QMessageBox.No)
+ else:
+ reply = QtWidgets.QMessageBox.question(self, 'Review selection...',
+ 'Selected USB disk: %s\n' % config.usb_disk +
+ 'USB mount point: %s\n' % config.usb_mount +
+ 'Selected distro: %s\n\n' % iso_name(
+ config.image_path) +
+ 'Proceed with installation?',
+ QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
+ QtWidgets.QMessageBox.No)
if reply == QtWidgets.QMessageBox.Yes:
self.ui.slider_persistence.setEnabled(False)
diff --git a/scripts/syslinux.py b/scripts/syslinux.py
index 96cc9505..f195e7dc 100644
--- a/scripts/syslinux.py
+++ b/scripts/syslinux.py
@@ -19,23 +19,72 @@
extlinux_fs = ["ext2", "ext3", "ext4", "Btrfs"]
syslinux_fs = ["vfat", "ntfs", "FAT32", "NTFS"]
mbr_bin = resource_path(os.path.join("data", "tools", "mbr.bin"))
+win_gdisk = resource_path(os.path.join('data', 'tools', 'gdisk', 'gdisk.exe'))
+
+
+def gpt_part_table(usb_disk):
+ """
+ Check if selected USB contain GPT or MBR partition table
+ :return: True if GPT else False
+ """
+ if platform.system() == "Linux":
+ _cmd_out = subprocess.check_output("parted " + usb_disk[:-1] + " print", shell=True)
+ if b'msdos' in _cmd_out:
+ return False
+ elif b'gpt' in _cmd_out:
+ return True
+ elif platform.system() == 'Windows':
+ win_usb_disk_no = str(usb.get_physical_disk_number(config.usb_disk))
+ if config.usb_gpt is True:
+ return True
+ elif config.usb_gpt is False:
+ return False
+
+
+def get_mbr_bin_path(usb_disk):
+ """
+ Check if partition table type is mbr or gpr using parted command under Linux
+ :param usb_disk: path to whole USB disk '/dev/sdb'
+ :return: Path to mbr.bin for use
+ """
+ if config.usb_gpt is False:
+ log('Using mbr.bin msdos mbr install.')
+ return resource_path(os.path.join("data", "tools", "mbr.bin"))
+ elif config.usb_gpt is True:
+ log('Using gptmbr.bin for mbr install.')
+ return resource_path(os.path.join("data", "tools", "gptmbr.bin"))
+
+ return False
def set_boot_flag(usb_disk):
if platform.system() == "Linux":
log("\nChecking boot flag on " + usb_disk[:-1], '\n')
cmd_out = subprocess.check_output("parted -m -s " + usb_disk[:-1] + " print", shell=True)
- if b'boot' in cmd_out:
- log("\nDisk " + usb_disk[:-1] + " already has boot flag.\n")
- return True
- else:
- log("\nExecuting ==> parted " + usb_disk[:-1] + " set 1 boot on", '\n')
- if subprocess.call("parted " + usb_disk[:-1] + " set 1 boot on", shell=True) == 0:
- log("\nBoot flag set to bootable " + usb_disk[:-1], '\n')
+ if gpt_part_table(usb_disk) is False:
+ if b'boot' in cmd_out:
+ log("\nDisk " + usb_disk[:-1] + " already has boot flag.\n")
return True
else:
- log("\nUnable to set boot flag on " + usb_disk[:-1], '\n')
- return False
+ log("\nExecuting ==> parted " + usb_disk[:-1] + " set 1 boot on", '\n')
+ if subprocess.call("parted " + usb_disk[:-1] + " set 1 boot on", shell=True) == 0:
+ log("\nBoot flag set to bootable " + usb_disk[:-1], '\n')
+ return True
+ else:
+ log("\nUnable to set boot flag on " + usb_disk[:-1], '\n')
+ return False
+ elif gpt_part_table(usb_disk) is True:
+ if b'legacy_boot' in cmd_out:
+ log("\nGPT Disk " + usb_disk[:-1] + " already has legacy_boot flag.\n")
+ return True
+ else:
+ log("\nExecuting ==> parted " + usb_disk[:-1] + " set 1 legacy_boot on", '\n')
+ if subprocess.call("parted " + usb_disk[:-1] + " set 1 legacy_boot on", shell=True) == 0:
+ log("\nBoot flag set to legacy_boot " + usb_disk[:-1], '\n')
+ return True
+ else:
+ log("\nUnable to set legacy_boot flag on " + usb_disk[:-1], '\n')
+ return False
def syslinux_default(usb_disk):
@@ -48,8 +97,17 @@ def syslinux_default(usb_disk):
usb_details = usb.details(usb_disk)
usb_fs = usb_details['file_system']
usb_mount = usb_details['mount_point']
- mbr_install_cmd = 'dd bs=440 count=1 conv=notrunc if=' + mbr_bin + ' of=' + usb_disk[:-1]
- # log(usb_fs)
+ mbr_bin = get_mbr_bin_path(usb_disk)
+
+ if platform.system() == 'Linux':
+ mbr_install_cmd = 'dd bs=440 count=1 conv=notrunc if=' + mbr_bin + ' of=' + usb_disk[:-1]
+ else:
+ win_usb_disk_no = str(usb.get_physical_disk_number(config.usb_disk))
+ _windd = resource_path(os.path.join("data", "tools", "dd", "dd.exe"))
+ _input = "if=" + mbr_bin
+ _output = 'of=\\\.\\physicaldrive' + win_usb_disk_no
+ mbr_install_cmd = _windd + ' ' + _input + ' ' + _output + ' count=1'
+
if usb_fs in extlinux_fs:
extlinu_cmd = extlinux_path + ' --install ' + os.path.join(usb_mount, 'multibootusb')
if os.access(extlinux_path, os.X_OK) is False:
@@ -78,6 +136,7 @@ def syslinux_default(usb_disk):
if subprocess.call(syslinux_cmd, shell=True) == 0:
log("\nDefault syslinux install is success...\n")
config.status_text = 'Default syslinux successfully installed...'
+ log('\nExecuting ==> ' + mbr_install_cmd)
if subprocess.call(mbr_install_cmd, shell=True) == 0:
config.status_text = 'mbr install is success...'
log("\nmbr install is success...\n")
@@ -90,12 +149,35 @@ def syslinux_default(usb_disk):
elif platform.system() == "Windows":
syslinux = resource_path(os.path.join(multibootusb_host_dir(), "syslinux", "bin", "syslinux4.exe"))
- log('Executing ==>' + syslinux + ' -maf -d multibootusb ' + usb_disk)
config.status_text = 'Installing default syslinux version 4...'
- if subprocess.call(syslinux + ' -maf -d multibootusb ' + usb_disk, shell=True) == 0:
+ # syslinux_cmd = syslinux + ' -maf -d multibootusb ' + usb_disk
+ if config.usb_gpt is False:
+ syslinux_cmd = syslinux + ' -maf -d multibootusb ' + usb_disk
+ else:
+ syslinux_cmd = syslinux + ' -af -d multibootusb ' + usb_disk
+ log('Executing ==> ' + syslinux_cmd)
+ '''
+ if gpt_part_table(config.usb_disk) is False:
+ syslinux_cmd = syslinux + ' -maf -d multibootusb ' + usb_disk
+ else:
+ syslinux_cmd = syslinux + ' -af -d multibootusb ' + usb_disk
+ '''
+ if subprocess.call(syslinux_cmd, shell=True) == 0:
config.status_text = 'Default syslinux successfully installed...'
log("\nDefault syslinux install is success...\n")
- return True
+ # We will need to flash gptmbr.bin only for GPT disk. As of version 8.9.0 this corrupts the gpt disk.
+ # Therefore not included for BIOS booting. GPT disk may work on UEFI system.
+ # if gpt_part_table(config.usb_disk) is True:
+ '''
+ if config.usb_gpt is False:
+ log('\nExecuting ==> ' + mbr_install_cmd)
+ if subprocess.call(mbr_install_cmd, shell=True) == 0:
+ log("\nmbr install is success...\n")
+ return True
+ else:
+ log('Disk uses GPT and mbr install is not required...')
+ '''
+
else:
log("\nFailed to install default syslinux...\n")
config.status_text = 'Failed to install default syslinux...'
@@ -203,6 +285,51 @@ def syslinux_distro_dir(usb_disk, iso_link, distro):
else:
log("\nFailed to install syslinux on distro directory...\n")
+
+def replace_grub_binary():
+ """
+ This function checks if correct binary is installed on grub and EFI directory.
+ If mismatch is found between partition table and binary, replace it correct one.
+ Default binaries will work for msdos partition table and therefore need not be replaced.
+ :return:
+ """
+ grub_efi_bin_path = os.path.join(config.usb_mount, 'EFI', 'BOOT', 'bootx64.efi')
+ grub_efi_bin_gpt_path = os.path.join(config.usb_mount, 'EFI', 'BOOT', 'bootx64-gpt.efi')
+ grub_efi_bin_msdos_path = os.path.join(config.usb_mount, 'EFI', 'BOOT', 'bootx64-msdos.efi')
+ core_img_bin_path = os.path.join(config.usb_mount, 'multibootusb', 'grub', 'core.img')
+ core_img_bin_msdos_path = os.path.join(config.usb_mount, 'multibootusb', 'grub', 'core-msdos.img')
+ core_img_bin_gpt_path = os.path.join(config.usb_mount, 'multibootusb', 'grub', 'core-gpt.img')
+
+ if platform.system() in ['Linux', 'Windows']:
+ if gpt_part_table(config.usb_disk) is True:
+ log('Replacing efi binary with gpt compatible one...')
+ try:
+ shutil.copy(grub_efi_bin_gpt_path, grub_efi_bin_path)
+ except Exception as e:
+ log(e)
+ log('Failed to replace efi binary...')
+ log('Replacing core.img binary with gpt compatible one...')
+ try:
+ shutil.copy(core_img_bin_gpt_path, core_img_bin_path)
+ except Exception as e:
+ log(e)
+ log('Failed to replace efi binary...')
+ else:
+ log('Replacing efi binary with msdos compatible one...')
+ try:
+ # shutil.copy(core_img_bin_gpt_path, core_img_bin_path)
+ shutil.copy(grub_efi_bin_msdos_path, grub_efi_bin_path)
+ except Exception as e:
+ log(e)
+ log('Failed to replace efi binary...')
+ try:
+ log('Replacing core.img with msdos compatible one...')
+ shutil.copy(core_img_bin_msdos_path, core_img_bin_path)
+ except Exception as e:
+ log(e)
+ log('Failed to replace core.img binary...')
+
+
if __name__ == '__main__':
if os.geteuid() != 0:
log('Please running this script with sudo/root/admin privilage.')
diff --git a/scripts/usb.py b/scripts/usb.py
index 6dfdd894..d214fa3f 100644
--- a/scripts/usb.py
+++ b/scripts/usb.py
@@ -13,6 +13,7 @@
import collections
import ctypes
import subprocess
+from . import config
from . import gen
if platform.system() == 'Linux':
from . import udisks
@@ -218,7 +219,11 @@ def details_udev(usb_disk_part):
gen.log("ERROR: Unknown disk/partition (%s)" % str(usb_disk_part))
return None
- fdisk_cmd_out = subprocess.check_output('fdisk -l ' + usb_disk_part, shell=True)
+ try:
+ fdisk_cmd_out = subprocess.check_output('fdisk -l ' + usb_disk_part, shell=True)
+ except subprocess.CalledProcessError:
+ gen.log("ERROR: fdisk failed on disk/partition (%s)" % str(usb_disk_part))
+ return None
if b'Extended' in fdisk_cmd_out:
mount_point = ''
@@ -349,6 +354,43 @@ def bytes2human(n):
return "%sB" % n
+def gpt_device(dev_name):
+ """
+ Find if the device inserted is GPT or not. We will just change the variable parameter in config file for later use
+ :param dev_name:
+ :return: True if GPT else False
+ """
+ if platform.system() == 'Windows':
+ diskpart_cmd = 'diskpart.exe /s ' + os.path.join('data', 'tools', 'gdisk', 'list-disk.txt')
+ dev_no = get_physical_disk_number(dev_name)
+ cmd_out = subprocess.check_output(diskpart_cmd)
+ cmd_spt = cmd_out.split(b'\r')
+ for line in cmd_spt:
+ line = line.decode('utf-8')
+ if 'Disk ' + dev_no in line:
+ if '*' not in line.split()[-1]:
+ config.usb_gpt = False
+ gen.log('Device ' + dev_name + ' is a MBR disk...')
+ return False
+ else:
+ config.usb_gpt = True
+ gen.log('Device ' + dev_name + ' is a GPT disk...')
+ return False
+ if platform.system() == "Linux":
+ if gen.has_digit(dev_name):
+ _cmd_out = subprocess.check_output("parted " + dev_name[:-1] + " print", shell=True)
+ else:
+ _cmd_out = subprocess.check_output("parted " + dev_name + " print", shell=True)
+ if b'msdos' in _cmd_out:
+ config.usb_gpt = False
+ gen.log('Device ' + dev_name + ' is a MBR disk...')
+ return False
+ elif b'gpt' in _cmd_out:
+ config.usb_gpt = True
+ gen.log('Device ' + dev_name + ' is a GPT disk...')
+ return True
+
+
def win_disk_details(disk_drive):
"""
Populate and get details of an USB disk under windows. Minimum required windows version is Vista.
@@ -421,8 +463,26 @@ def details(usb_disk_part):
details = details_udisks2(usb_disk_part)
elif platform.system() == 'Windows':
details = win_disk_details(usb_disk_part)
+
return details
+
+def get_physical_disk_number(usb_disk):
+ """
+ Get the physical disk number as detected ny Windows.
+ :param usb_disk: USB disk (Like F:)
+ :return: Disk number.
+ """
+ import wmi
+ c = wmi.WMI()
+ for physical_disk in c.Win32_DiskDrive():
+ for partition in physical_disk.associators("Win32_DiskDriveToDiskPartition"):
+ for logical_disk in partition.associators("Win32_LogicalDiskToPartition"):
+ if logical_disk.Caption == usb_disk:
+ # gen.log("Physical Device Number is " + partition.Caption[6:-14])
+ return str(partition.Caption[6:-14])
+
+
if __name__ == '__main__':
usb_devices = list_devices()
if usb_devices is not None: