from Scripts import utils, diskwin, downloader, run
import os, sys, tempfile, shutil, zipfile, platform, json, time
class WinUSB:
def __init__(self):
self.u = utils.Utils("MakeInstall")
if not self.u.check_admin():
self.u.elevate(os.path.realpath(__file__))
exit()
self.min_plat = 9600
self.verify_os()
self.d = diskwin.Disk()
self.dl = downloader.Downloader()
self.r = run.Run()
self.scripts = "Scripts"
self.s_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.scripts)
self.dd_url = "https://github.com/corpnewt/gibMacOS/files/4573241/ddrelease64.exe.zip"
self.dd_name = ".".join(os.path.basename(self.dd_url).split(".")[:-1])
self.z_json = "https://sourceforge.net/projects/sevenzip/best_release.json"
self.z_url2 = "https://www.7-zip.org/a/7z1806-x64.msi"
self.z_url = "https://www.7-zip.org/a/7z[[vers]]-x64.msi"
self.z_name = "7z.exe"
self.bi_url = "https://raw.githubusercontent.com/corpnewt/gibMacOS/master/Scripts/BOOTICEx64.exe"
self.bi_name = "BOOTICEx64.exe"
self.clover_url = "https://api.github.com/repos/CloverHackyColor/CloverBootloader/releases"
self.dids_url = "https://api.github.com/repos/dids/clover-builder/releases"
self.oc_url = "https://api.github.com/repos/acidanthera/OpenCorePkg/releases"
self.oc_boot = "boot"
self.oc_boot_alt = "bootX64"
self.oc_boot0 = "boot0"
self.oc_boot1 = "boot1f32"
self.oc_boot_url = "https://github.com/acidanthera/OpenCorePkg/raw/870017d0e5d53abeaf0347997da912c3e382a04a/Utilities/LegacyBoot/"
self.diskpart = os.path.join(os.environ['SYSTEMDRIVE'] + "\\", "Windows", "System32", "diskpart.exe")
self.z_path = None
self.z_path64 = os.path.join(os.environ['SYSTEMDRIVE'] + "\\", "Program Files", "7-Zip", "7z.exe")
self.z_path32 = os.path.join(os.environ['SYSTEMDRIVE'] + "\\", "Program Files (x86)", "7-Zip", "7z.exe")
self.recovery_suffixes = (
"recoveryhdupdate.pkg",
"recoveryhdmetadmg.pkg",
"basesystem.dmg",
"recoveryimage.dmg"
)
self.dd_bootsector = True
self.boot0 = "boot0af"
self.boot1 = "boot1f32alt"
self.boot = "boot6"
self.efi_id = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b"
self.bas_id = "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7"
self.hfs_id = "48465300-0000-11AA-AA11-00306543ECAC"
self.rec_id = "426F6F74-0000-11AA-AA11-00306543ECAC"
self.show_all_disks = False
def verify_os(self):
self.u.head("Verifying OS")
print("")
print("Verifying OS name...")
if not os.name=="nt":
print("")
print("This script is only for Windows!")
print("")
self.u.grab("Press [enter] to exit...")
exit(1)
print(" - Name = NT")
print("Verifying OS version...")
try:
plat = int(platform.platform().split(".")[-1].split("-")[0])
except:
plat = 0
if plat < self.min_plat:
print("")
print("Currently running {}, this script requires version {} or newer.".format(platform.platform(), self.min_plat))
print("")
self.u.grab("Press [enter] to exit...")
exit(1)
print(" - Version = {}".format(plat))
print("")
print("{} >= {}, continuing...".format(plat, self.min_plat))
def get_disks_of_type(self, disk_list, disk_type=(0,2)):
disks = {}
for disk in disk_list:
if disk_list[disk].get("type",0) in disk_type:
disks[disk] = disk_list[disk]
return disks
def check_dd(self):
if os.path.exists(os.path.join(self.s_path, self.dd_name)):
return True
print("Couldn't locate {} - downloading...".format(self.dd_name))
temp = tempfile.mkdtemp()
z_file = os.path.basename(self.dd_url)
self.dl.stream_to_file(self.dd_url, os.path.join(temp,z_file))
print(" - Extracting...")
cwd = os.getcwd()
os.chdir(temp)
with zipfile.ZipFile(os.path.join(temp,z_file)) as z:
z.extractall(temp)
for x in os.listdir(temp):
if self.dd_name.lower() == x.lower():
print(" - Found {}".format(x))
print(" - Copying to {} directory...".format(self.scripts))
shutil.copy(os.path.join(temp,x), os.path.join(self.s_path,x))
os.chdir(cwd)
shutil.rmtree(temp,ignore_errors=True)
print("")
return os.path.exists(os.path.join(self.s_path, self.dd_name))
def check_7z(self):
z_path = self.r.run({"args":["where.exe","7z.exe"]})[0].split("\n")[0].rstrip("\r")
self.z_path = next((x for x in (z_path,self.z_path64,self.z_path32) if x and os.path.isfile(x)),None)
if self.z_path:
return True
print("Didn't locate {} - downloading...".format(self.z_name))
dl_url = None
try:
json_data = json.loads(self.dl.get_string(self.z_json))
v_num = json_data.get("release",{}).get("filename","").split("/")[-1].lower().split("-")[0].replace("7z","").replace(".exe","")
if len(v_num):
dl_url = self.z_url.replace("[[vers]]",v_num)
except:
pass
if not dl_url:
dl_url = self.z_url2
temp = tempfile.mkdtemp()
dl_file = self.dl.stream_to_file(dl_url, os.path.join(temp, self.z_name))
if not dl_file:
shutil.rmtree(temp,ignore_errors=True)
return False
print("")
print("Installing 7zip...")
out = self.r.run({"args":["msiexec", "/qn", "/i", os.path.join(temp, self.z_name)],"stream":True})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print("Error ({})".format(out[2]))
print("")
self.u.grab("Press [enter] to exit...")
exit(1)
print("")
self.z_path = self.z_path64 if os.path.exists(self.z_path64) else self.z_path32 if os.path.exists(self.z_path32) else None
return self.z_path and os.path.exists(self.z_path)
def check_bi(self):
if os.path.exists(os.path.join(self.s_path, self.bi_name)):
return True
print("Couldn't locate {} - downloading...".format(self.bi_name))
self.dl.stream_to_file(self.bi_url, os.path.join(self.s_path, self.bi_name))
print("")
return os.path.exists(os.path.join(self.s_path,self.bi_name))
def get_dl_url_from_json(self,json_data,suffix=(".lzma",".iso.7z")):
try: j_list = json.loads(json_data)
except: return None
j_list = j_list if isinstance(j_list,list) else [j_list]
for j in j_list:
dl_link = next((x.get("browser_download_url", None) for x in j.get("assets", []) if x.get("browser_download_url", "").endswith(suffix)), None)
if dl_link: break
if not dl_link:
return None
return { "url" : dl_link, "name" : os.path.basename(dl_link), "info" : j.get("body", None) }
def get_dl_info(self,clover_version=None):
clover_urls = (self.clover_url,self.dids_url)
try:
assert int(clover_version) <= 5122
clover_urls = (self.dids_url,self.clover_url)
except:
pass
for url in clover_urls:
if not clover_version:
search_url = url
elif url == self.clover_url:
search_url = "{}/tags/{}".format(url,clover_version)
else:
search_url = "{}/tags/v{}_r{}".format(url,"5.0" if clover_version >= "5118" else "2.5k",clover_version)
print(" - Checking {}".format(search_url))
json_data = self.dl.get_string(search_url, False)
if not json_data: print(" --> Not found!")
else: return self.get_dl_url_from_json(json_data)
return None
def get_oc_dl_info(self):
json_data = self.dl.get_string(self.oc_url, False)
if not json_data: print(" --> Not found!")
else: return self.get_dl_url_from_json(json_data,suffix="-RELEASE.zip")
def diskpart_flag(self, disk, as_efi=False):
self.u.head("Changing ID With DiskPart")
print("")
print("Setting type as {}...".format("EFI" if as_efi else "Basic Data"))
print("")
dp_script = "\n".join([
"select disk {}".format(disk.get("index",-1)),
"sel part 1",
"set id={}".format(self.efi_id if as_efi else self.bas_id)
])
temp = tempfile.mkdtemp()
script = os.path.join(temp, "diskpart.txt")
try:
with open(script,"w") as f:
f.write(dp_script)
except:
shutil.rmtree(temp)
print("Error creating script!")
print("")
self.u.grab("Press [enter] to return...")
return
out = self.r.run({"args":[self.diskpart,"/s",script],"stream":True})
shutil.rmtree(temp)
print("")
if out[2] != 0:
print("DiskPart exited with non-zero status ({}). Aborting.".format(out[2]))
else:
print("Done - You may need to replug your drive for the")
print("changes to take effect.")
print("")
self.u.grab("Press [enter] to return...")
def diskpart_erase(self, disk, gpt=False, clover_version = None, local_file = None):
self.u.head("Erasing With DiskPart")
print("")
if not gpt:
print("Using MBR...")
dp_script = "\n".join([
"select disk {}".format(disk.get("index",-1)),
"clean",
"convert mbr",
"create partition primary size=200",
"format quick fs=fat32 label='BOOT'",
"active",
"create partition primary",
"select part 2",
"set id=AB",
"select part 1",
"assign"
])
else:
print("Using GPT...")
dp_script = "\n".join([
"select disk {}".format(disk.get("index",-1)),
"clean",
"convert gpt",
"create partition primary size=200",
"format quick fs=fat32 label='BOOT'",
"create partition primary id={}".format(self.hfs_id)
])
temp = tempfile.mkdtemp()
script = os.path.join(temp, "diskpart.txt")
try:
with open(script,"w") as f:
f.write(dp_script)
except:
shutil.rmtree(temp)
print("Error creating script!")
print("")
self.u.grab("Press [enter] to return...")
return
out = self.r.run({"args":[self.diskpart,"/s",script],"stream":True})
shutil.rmtree(temp)
if out[2] != 0:
print("")
print("DiskPart exited with non-zero status ({}). Aborting.".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
self.u.head("Updating Disk Information")
print("")
print("Re-populating list...")
self.d.update()
print("Relocating disk {}".format(disk["index"]))
disk = self.d.disks[str(disk["index"])]
self.select_package(disk, clover_version, local_file=local_file)
def select_package(self, disk, clover_version = None, local_file = None):
self.u.head("Select Recovery Package")
print("")
print("{}. {} - {} ({})".format(
disk.get("index",-1),
disk.get("model","Unknown"),
self.dl.get_size(disk.get("size",-1),strip_zeroes=True),
["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][disk.get("type",0)]
))
print("")
print("M. Main Menu")
print("Q. Quit")
print("")
print("(To copy a file's path, shift + right-click in Explorer and select 'Copy as path')\n")
menu = self.u.grab("Please paste the recovery update pkg/dmg path to extract: ")
if menu.lower() == "q":
self.u.custom_quit()
if menu.lower() == "m":
return
path = self.u.check_path(menu)
if not path:
self.select_package(disk, clover_version, local_file=local_file)
return
if os.path.basename(path).lower().endswith(".hfs"):
self.dd_image(disk, path, clover_version, local_file=local_file)
return
if os.path.isdir(path):
for f in os.listdir(path):
if f.lower().endswith(self.recovery_suffixes):
path = os.path.join(path, f)
break
if not path.lower().endswith(self.recovery_suffixes):
self.u.head("Invalid Package")
print("")
print("{} is not in the available recovery package names:\n{}".format(os.path.basename(path), ", ".join(self.recovery_suffixes)))
print("")
print("Ensure you're passing a proper recovery package.")
print("")
self.u.grab("Press [enter] to return to package selection...")
self.select_package(disk, clover_version, local_file=local_file)
return
self.u.head("Extracting Package")
print("")
temp = tempfile.mkdtemp()
cwd = os.getcwd()
os.chdir(temp)
print("Located {}...".format(os.path.basename(path)))
if not path.lower().endswith(".dmg"):
print("Extracting Recovery dmg...")
out = self.r.run({"args":[self.z_path, "e", "-txar", path, "*.dmg"]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print("An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Extracting BaseSystem.dmg...")
out = self.r.run({"args":[self.z_path, "e", "*.dmg", "*/Base*.dmg"]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print("An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
del_list = [x for x in os.listdir(temp) if not (x.lower().startswith("base") and x.lower().endswith(".dmg"))]
for d in del_list:
os.remove(os.path.join(temp, d))
print("Extracting hfs...")
out = self.r.run({"args":[self.z_path, "e", "-tdmg", path if path.lower().endswith(".dmg") else "Base*.dmg", "*.hfs"]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print("An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
del_list = [x for x in os.listdir(temp) if not x.lower().endswith(".hfs")]
for d in del_list:
os.remove(os.path.join(temp, d))
print("Extracted successfully!")
hfs = next((x for x in os.listdir(temp) if x.lower().endswith(".hfs")),None)
if not hfs:
print("Missing the .hfs file! Aborting.")
print("")
self.u.grab("Press [enter] to return...")
else:
self.dd_image(disk, os.path.join(temp, hfs), clover_version, local_file=local_file)
shutil.rmtree(temp,ignore_errors=True)
def dd_image(self, disk, image, clover_version = None, local_file = None):
self.u.head("Copying Image To Drive")
print("")
print("Image: {}".format(image))
print("")
print("Disk {}. {} - {} ({})".format(
disk.get("index",-1),
disk.get("model","Unknown"),
self.dl.get_size(disk.get("size",-1),strip_zeroes=True),
["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][disk.get("type",0)]
))
print("")
args = [
os.path.join(self.s_path, self.dd_name),
"if={}".format(image),
"of=\\\\?\\Device\\Harddisk{}\\Partition2".format(disk.get("index",-1)),
"bs=8M",
"--progress"
]
print(" ".join(args))
print("")
print("This may take some time!")
print("")
out = self.r.run({"args":args})
if len(out[1].split("Error")) > 1:
print("An error occurred:\n\n{}".format("Error"+out[1].split("Error")[1]))
print("")
self.u.grab("Press [enter] to return to the main menu...")
return
if clover_version == "OpenCore": self.install_oc(disk, local_file=local_file)
else: self.install_clover(disk, clover_version, local_file=local_file)
def install_oc(self, disk, local_file = None):
self.u.head("Installing OpenCore")
print("")
print("Gathering info...")
if not local_file:
o = self.get_oc_dl_info()
if o is None:
print(" - Error communicating with github!")
print("")
self.u.grab("Press [enter] to return...")
return
print(" - Got {}".format(o.get("name","Unknown Version")))
print("Downloading...")
temp = tempfile.mkdtemp()
os.chdir(temp)
self.dl.stream_to_file(o["url"], os.path.join(temp, o["name"]))
else:
print("Using local file: {}".format(local_file))
temp = tempfile.mkdtemp()
os.chdir(temp)
o = {"name":os.path.basename(local_file)}
shutil.copy(local_file,os.path.join(temp,o["name"]))
print("")
if not os.path.exists(os.path.join(temp, o["name"])):
shutil.rmtree(temp,ignore_errors=True)
print(" - Download failed. Aborting...")
print("")
self.u.grab("Press [enter] to return...")
return
oc_zip = o["name"]
print("Extracting {}...".format(oc_zip))
out = self.r.run({"args":[self.z_path, "x", os.path.join(temp,oc_zip)]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Gathering DUET boot files...")
uefi_only = False
duet_loc = os.path.join(temp,"Utilities","LegacyBoot")
for x in (self.oc_boot,self.oc_boot_alt,self.oc_boot0,self.oc_boot1):
if os.path.exists(os.path.join(duet_loc,x)):
print(" - {}".format(x))
target_name = self.oc_boot if x == self.oc_boot_alt else x
shutil.copy(os.path.join(duet_loc,x), os.path.join(temp,target_name))
missing_list = [x for x in (self.oc_boot,self.oc_boot0,self.oc_boot1) if not os.path.exists(os.path.join(temp,x))]
if missing_list:
print(" - Missing: {}".format(", ".join(missing_list)))
print("Attempting to download...")
for x in missing_list:
print(" - {}".format(x))
self.dl.stream_to_file(self.oc_boot_url + x, os.path.join(temp,x),False)
if not all((os.path.exists(os.path.join(temp,x)) for x in missing_list)):
print("Could not located all required DUET files - USB will be UEFI ONLY")
uefi_only = True
self.d.update()
if self.d.disks[str(disk["index"])].get("partitions",None) is None:
shutil.rmtree(temp,ignore_errors=True)
print("No partitions located on disk!")
print("")
self.u.grab("Press [enter] to return...")
return
part = self.d.disks[str(disk["index"])]["partitions"].get("0",{}).get("letter",None)
if part is None:
shutil.rmtree(temp,ignore_errors=True)
print("Lost original disk - or formatting failed!")
print("")
self.u.grab("Press [enter] to return...")
return
print("Copying EFI folder to {}/EFI...".format(part))
source_efi = None
if os.path.exists(os.path.join(temp,"EFI")):
source_efi = os.path.join(temp,"EFI")
elif os.path.exists(os.path.join(temp,"X64","EFI")):
source_efi = os.path.join(temp,"X64","EFI")
if not source_efi:
print(" - Source EFI not found!")
print("")
self.u.grab("Press [enter] to return...")
return
if os.path.exists("{}/EFI".format(part)):
print(" - EFI exists - removing...")
shutil.rmtree("{}/EFI".format(part),ignore_errors=True)
time.sleep(1)
shutil.copytree(source_efi, "{}/EFI".format(part))
if not uefi_only:
print("Copying {} to {}/boot...".format(self.oc_boot,part))
shutil.copy(os.path.join(temp,self.oc_boot),"{}/boot".format(part))
print("Updating the MBR with {}...".format(self.oc_boot0))
args = [
os.path.join(self.s_path,self.bi_name),
"/device={}".format(disk.get("index",-1)),
"/mbr",
"/restore",
"/file={}".format(os.path.join(temp,self.oc_boot0)),
"/keep_dpt",
"/quiet"
]
out = self.r.run({"args":args})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred updating the MBR: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Updating the PBR with {}...".format(self.oc_boot1))
args = [
os.path.join(self.s_path,self.bi_name),
"/device={}:0".format(disk.get("index",-1)),
"/pbr",
"/restore",
"/file={}".format(os.path.join(temp,self.oc_boot1)),
"/keep_bpb",
"/quiet"
]
out = self.r.run({"args":args})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred updating the PBR: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Cleaning up...")
shutil.rmtree(temp,ignore_errors=True)
print("")
print("Done.")
print("")
self.u.grab("Press [enter] to return to the main menu...")
def install_clover(self, disk, clover_version = None, local_file = None):
self.u.head("Installing Clover - {}".format("Latest" if not clover_version else "r"+clover_version))
print("")
print("Gathering info...")
if not local_file:
c = self.get_dl_info(clover_version)
if c is None:
if clover_version is None: print(" - Error communicating with github!")
else: print(" - Error gathering info for Clover r{}".format(clover_version))
print("")
self.u.grab("Press [enter] to return...")
return
print(" - Got {}".format(c.get("name","Unknown Version")))
print("Downloading...")
temp = tempfile.mkdtemp()
os.chdir(temp)
self.dl.stream_to_file(c["url"], os.path.join(temp, c["name"]))
else:
print("Using local file: {}".format(local_file))
temp = tempfile.mkdtemp()
os.chdir(temp)
c = {"name":os.path.basename(local_file)}
shutil.copy(local_file,os.path.join(temp,c["name"]))
print("")
if not os.path.exists(os.path.join(temp, c["name"])):
shutil.rmtree(temp,ignore_errors=True)
print(" - Download failed. Aborting...")
print("")
self.u.grab("Press [enter] to return...")
return
clover_archive = c["name"]
print("Extracting {}...".format(clover_archive))
out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_archive)]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
clover_tar = next((x for x in os.listdir(temp) if x.lower().endswith(".tar")),None)
if clover_tar:
print("Extracting {}...".format(clover_tar))
out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_tar)]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
clover_iso = next((x for x in os.listdir(temp) if x.lower().endswith(".iso")),None)
if not clover_iso:
shutil.rmtree(temp,ignore_errors=True)
print(" - No .iso found - aborting...")
print("")
self.u.grab("Press [enter] to return...")
return
print("Extracting EFI from {}...".format(clover_iso))
out = self.r.run({"args":[self.z_path, "x", os.path.join(temp,clover_iso), "EFI*"]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Extracting {} from {}...".format(self.boot0,clover_iso))
out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_iso), self.boot0, "-r"]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Extracting {} from {}...".format(self.boot1,clover_iso))
out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_iso), self.boot1, "-r"]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Extracting {} from {}...".format(self.boot,clover_iso))
out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_iso), self.boot, "-r"]})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred extracting: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
self.d.update()
if self.d.disks[str(disk["index"])].get("partitions",None) is None:
shutil.rmtree(temp,ignore_errors=True)
print("No partitions located on disk!")
print("")
self.u.grab("Press [enter] to return...")
return
part = self.d.disks[str(disk["index"])]["partitions"].get("0",{}).get("letter",None)
if part is None:
shutil.rmtree(temp,ignore_errors=True)
print("Lost original disk - or formatting failed!")
print("")
self.u.grab("Press [enter] to return...")
return
print("Copying EFI folder to {}/EFI...".format(part))
if os.path.exists("{}/EFI".format(part)):
print(" - EFI exists - removing...")
shutil.rmtree("{}/EFI".format(part),ignore_errors=True)
time.sleep(1)
shutil.copytree(os.path.join(temp,"EFI"), "{}/EFI".format(part))
print("Copying {} to {}/boot...".format(self.boot,part))
shutil.copy(os.path.join(temp,self.boot),"{}/boot".format(part))
print("Updating the MBR with {}...".format(self.boot0))
args = [
os.path.join(self.s_path,self.bi_name),
"/device={}".format(disk.get("index",-1)),
"/mbr",
"/restore",
"/file={}".format(os.path.join(temp,self.boot0)),
"/keep_dpt",
"/quiet"
]
out = self.r.run({"args":args})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred updating the MBR: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Updating the PBR with {}...".format(self.boot1))
args = [
os.path.join(self.s_path,self.bi_name),
"/device={}:0".format(disk.get("index",-1)),
"/pbr",
"/restore",
"/file={}".format(os.path.join(temp,self.boot1)),
"/keep_bpb",
"/quiet"
]
out = self.r.run({"args":args})
if out[2] != 0:
shutil.rmtree(temp,ignore_errors=True)
print(" - An error occurred updating the PBR: {}".format(out[2]))
print("")
self.u.grab("Press [enter] to return...")
return
print("Cleaning up...")
shutil.rmtree(temp,ignore_errors=True)
print("")
print("Done.")
print("")
self.u.grab("Press [enter] to return to the main menu...")
def main(self):
os.chdir(os.path.dirname(os.path.realpath(__file__)))
self.u.head("Checking Required Tools")
print("")
if not self.check_dd():
print("Couldn't find or install {} - aborting!\n".format(self.dd_name))
self.u.grab("Press [enter] to exit...")
exit(1)
if not self.check_7z():
print("Couldn't find or install {} - aborting!\n".format(self.z_name))
self.u.grab("Press [enter] to exit...")
exit(1)
if not self.check_bi():
print("Couldn't find or install {} - aborting!\n".format(self.bi_name))
self.u.grab("Press [enter] to exit...")
exit(1)
self.u.head("Gathering Disk Info")
print("")
print("Populating list...")
self.d.update()
print("")
print("Done!")
self.u.head("Potential Removable Media")
print("")
rem_disks = self.get_disks_of_type(self.d.disks) if not self.show_all_disks else self.d.disks
if self.show_all_disks:
print("!WARNING! This list includes ALL disk types.")
print("!WARNING! Be ABSOLUTELY sure before selecting")
print("!WARNING! a disk!")
else:
print("!WARNING! This list includes both Removable AND")
print("!WARNING! Unknown disk types. Be ABSOLUTELY sure")
print("!WARNING! before selecting a disk!")
print("")
for disk in sorted(rem_disks,key=lambda x:int(x)):
print("{}. {} - {} ({})".format(
disk,
rem_disks[disk].get("model","Unknown"),
self.dl.get_size(rem_disks[disk].get("size",-1),strip_zeroes=True),
["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][rem_disks[disk].get("type",0)]
))
if not len(rem_disks[disk].get("partitions",{})):
print(" No Mounted Partitions")
else:
parts = rem_disks[disk]["partitions"]
for p in sorted(parts,key=lambda x:int(x)):
print(" {}. {} ({}) {} - {}".format(
p,
parts[p].get("letter","No Letter"),
"No Name" if not parts[p].get("name",None) else parts[p].get("name","No Name"),
parts[p].get("file system","Unknown FS"),
self.dl.get_size(parts[p].get("size",-1),strip_zeroes=True)
))
print("")
print("Q. Quit")
print("")
print("Usage: [drive number][options] r[Clover revision (optional), requires C]\n (eg. 1B C r5092)")
print(" Options are as follows with precedence B > F > E > U > G:")
print(" B = Only install the boot manager to the drive's first partition.")
print(" F = Skip formatting the disk - will install the boot manager to the first")
print(" partition, and dd the recovery image to the second.")
print(" E = Sets the type of the drive's first partition to EFI.")
print(" U = Similar to E, but sets the type to Basic Data (useful for editing).")
print(" G = Format as GPT (default is MBR).")
print(" C = Use Clover instead of OpenCore.")
print(" L = Provide a local archive for the boot manager - must still use C if Clover.")
print(" D = Used without a drive number, toggles showing all disks (currently {}).".format("ENABLED" if self.show_all_disks else "DISABLED"))
print("")
menu = self.u.grab("Please select a disk or press [enter] with no options to refresh: ")
if not len(menu):
self.main()
return
if menu.lower() == "q":
self.u.custom_quit()
if menu.lower() == "d":
self.show_all_disks ^= True
self.main()
return
only_boot = set_efi = unset_efi = use_gpt = user_provided = no_format = False
local_file = None
use_oc = True
if "b" in menu.lower():
only_boot = True
menu = menu.lower().replace("b","")
if "c" in menu.lower():
use_oc = False
menu = menu.lower().replace("c","")
if "o" in menu.lower():
menu = menu.lower().replace("o","")
if "e" in menu.lower():
set_efi = True
menu = menu.lower().replace("e","")
if "u" in menu.lower():
unset_efi = True
menu = menu.lower().replace("u","")
if "g" in menu.lower():
use_gpt = True
menu = menu.lower().replace("g","")
if "l" in menu.lower():
user_provided = True
menu = menu.lower().replace("l","")
if "f" in menu.lower():
no_format = True
menu = menu.lower().replace("f","")
clover_list = [x for x in menu.split() if x.lower().startswith("r") and all(y in "0123456789" for y in x[1:])]
menu = " ".join([x for x in menu.split() if not x in clover_list])
clover_version = None if not len(clover_list) else clover_list[0][1:]
if use_oc: clover_version = "OpenCore"
selected_disk = rem_disks.get(menu.strip(),None)
if not selected_disk:
self.u.head("Invalid Choice")
print("")
print("Disk {} is not an option.".format(menu))
print("")
self.u.grab("Returning in 5 seconds...", timeout=5)
self.main()
return
if user_provided:
while True:
self.u.head("Local Archive")
print("")
if use_oc:
print("NOTE: OpenCore archives are expected to be .zip!")
else:
print("NOTE: Clover archives are expected to be an ISO packed in either .tar.lzma or .7z!")
print("")
print("M. Return to the menu")
print("Q. Quit")
print("")
print("(To copy a file's path, shift + right-click in Explorer and select 'Copy as path')\n")
l = self.u.grab("Please {} archive path here: ".format("OpenCore" if use_oc else "Clover"))
if not len(l):
continue
if l.lower() == "m":
break
elif l.lower() == "q":
self.u.custom_quit()
l_check = self.u.check_path(l)
if not l_check or not l_check.lower().endswith(".zip" if use_oc else (".tar.lzma",".7z")):
continue
local_file = l_check
break
if not local_file:
self.main()
return
if only_boot:
if use_oc: self.install_oc(selected_disk, local_file=local_file)
else: self.install_clover(selected_disk, clover_version, local_file=local_file)
elif no_format:
while True:
self.u.head("WARNING")
print("")
print("{}. {} - {} ({})".format(
selected_disk.get("index",-1),
selected_disk.get("model","Unknown"),
self.dl.get_size(selected_disk.get("size",-1),strip_zeroes=True),
["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][selected_disk.get("type",0)]
))
print("")
print("In order to continue without formatting, the selected disk's first")
print("partition MUST be FAT32, and the second MUST be RAW. If that is not")
print("the case, the operation WILL fail.")
print("")
yn = self.u.grab("Continue? (y/n): ")
if yn.lower() == "n":
self.main()
return
if yn.lower() == "y":
break
self.select_package(selected_disk, clover_version, local_file=local_file)
elif set_efi:
self.diskpart_flag(selected_disk, True)
elif unset_efi:
self.diskpart_flag(selected_disk, False)
else:
while True:
self.u.head("Erase {}".format(selected_disk.get("model","Unknown")))
print("")
print("{}. {} - {} ({})".format(
selected_disk.get("index",-1),
selected_disk.get("model","Unknown"),
self.dl.get_size(selected_disk.get("size",-1),strip_zeroes=True),
["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][selected_disk.get("type",0)]
))
print("")
print("If you continue - THIS DISK WILL BE ERASED")
print("ALL DATA WILL BE LOST AND ALL PARTITIONS WILL")
print("BE REMOVED!!!!!!!")
print("")
yn = self.u.grab("Continue? (y/n): ")
if yn.lower() == "n":
self.main()
return
if yn.lower() == "y":
break
self.diskpart_erase(selected_disk, use_gpt, clover_version, local_file=local_file)
self.main()
if __name__ == '__main__':
w = WinUSB()
w.main()