Advertisement
Guest User

gibMacOS MakeInstall.py - older Clover version

a guest
Oct 6th, 2019
3,461
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.81 KB | None | 0 0
  1. from Scripts import utils, diskwin, downloader, run
  2. import os, sys, tempfile, shutil, zipfile, platform, json, time
  3.  
  4. class WinUSB:
  5.  
  6. def __init__(self):
  7. self.u = utils.Utils("MakeInstall")
  8. self.min_plat = 9600
  9. # Make sure we're on windows
  10. self.verify_os()
  11. # Setup initial vars
  12. self.d = diskwin.Disk()
  13. self.dl = downloader.Downloader()
  14. self.r = run.Run()
  15. self.scripts = "Scripts"
  16. self.s_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), self.scripts)
  17. self.dd_url = "http://www.chrysocome.net/downloads/ddrelease64.exe"
  18. self.dd_name = os.path.basename(self.dd_url)
  19. self.z_json = "https://sourceforge.net/projects/sevenzip/best_release.json"
  20. self.z_url2 = "https://www.7-zip.org/a/7z1806-x64.msi"
  21. self.z_url = "https://www.7-zip.org/a/7z[[vers]]-x64.msi"
  22. self.z_name = "7z.exe"
  23. self.bi_url = "https://raw.githubusercontent.com/corpnewt/gibMacOS/master/Scripts/BOOTICEx64.exe"
  24. self.bi_name = "BOOTICEx64.exe"
  25. #self.clover_url = "https://api.github.com/repos/dids/clover-builder/releases/latest"
  26. #TODO: Testing out an older version of Clover
  27. self.clover_url = "https://api.github.com/repos/Dids/clover-builder/releases/20325367"
  28. # From Tim Sutton's brigadier: https://github.com/timsutton/brigadier/blob/master/brigadier
  29. self.z_path = None
  30. self.z_path64 = os.path.join(os.environ['SYSTEMDRIVE'] + "\\", "Program Files", "7-Zip", "7z.exe")
  31. self.z_path32 = os.path.join(os.environ['SYSTEMDRIVE'] + "\\", "Program Files (x86)", "7-Zip", "7z.exe")
  32. self.recovery_suffixes = (
  33. "recoveryhdupdate.pkg",
  34. "recoveryhdmetadmg.pkg"
  35. )
  36. self.dd_bootsector = True
  37. self.boot0 = "boot0af"
  38. self.boot1 = "boot1f32alt"
  39. self.boot = "boot6"
  40. self.efi_id = "c12a7328-f81f-11d2-ba4b-00a0c93ec93b" # EFI
  41. self.bas_id = "ebd0a0a2-b9e5-4433-87c0-68b6b72699c7" # Microsoft Basic Data
  42. self.hfs_id = "48465300-0000-11AA-AA11-00306543ECAC" # HFS+
  43. self.rec_id = "426F6F74-0000-11AA-AA11-00306543ECAC" # Apple Boot partition (Recovery HD)
  44. self.show_all_disks = False
  45.  
  46. def verify_os(self):
  47. self.u.head("Verifying OS")
  48. print("")
  49. print("Verifying OS name...")
  50. if not os.name=="nt":
  51. print("")
  52. print("This script is only for Windows!")
  53. print("")
  54. self.u.grab("Press [enter] to exit...")
  55. exit(1)
  56. print(" - Name = NT")
  57. print("Verifying OS version...")
  58. # Verify we're at version 9600 or greater
  59. try:
  60. # Set plat to the last item of the output split by . - looks like:
  61. # Windows-8.1-6.3.9600
  62. # or this:
  63. # Windows-10-10.0.17134-SP0
  64. plat = int(platform.platform().split(".")[-1].split("-")[0])
  65. except:
  66. plat = 0
  67. if plat < self.min_plat:
  68. print("")
  69. print("Currently running {}, this script requires version {} or newer.".format(platform.platform(), self.min_plat))
  70. print("")
  71. self.u.grab("Press [enter] to exit...")
  72. exit(1)
  73. print(" - Version = {}".format(plat))
  74. print("")
  75. print("{} >= {}, continuing...".format(plat, self.min_plat))
  76.  
  77. def get_disks_of_type(self, disk_list, disk_type=(0,2)):
  78. disks = {}
  79. for disk in disk_list:
  80. if disk_list[disk].get("type",0) in disk_type:
  81. disks[disk] = disk_list[disk]
  82. return disks
  83.  
  84. def check_dd(self):
  85. # Checks if ddrelease64.exe exists in our Scripts dir
  86. # and if not - downloads it
  87. #
  88. # Returns True if exists/downloaded successfully
  89. # or False if issues.
  90. # Check for dd.exe in the current dir
  91. if os.path.exists(os.path.join(self.s_path, self.dd_name)):
  92. # print("Located {}!".format(self.dd_name))
  93. # Got it
  94. return True
  95. print("Couldn't locate {} - downloading...".format(self.dd_name))
  96. # Now we need to download
  97. self.dl.stream_to_file(self.dd_url, os.path.join(self.s_path, self.dd_name))
  98. print("")
  99. return os.path.exists(os.path.join(self.s_path, self.dd_name))
  100.  
  101. def check_7z(self):
  102. # Check for 7z.exe in Program Files and if not - download the 7z msi and install
  103. #
  104. # Returns True if found, False if not
  105. if os.path.exists(self.z_path64):
  106. # Got it
  107. self.z_path = self.z_path64
  108. return True
  109. elif os.path.exists(self.z_path32):
  110. # Found the 32 bit version
  111. self.z_path = self.z_path32
  112. return True
  113. print("Didn't locate {} - downloading...".format(self.z_name))
  114. # Didn't find it - let's do some stupid stuff
  115. # First we get our json response - or rather, try to, then parse it
  116. # looking for the current version
  117. dl_url = None
  118. try:
  119. json_data = json.loads(self.dl.get_string(self.z_json))
  120. v_num = json_data.get("release",{}).get("filename","").split("/")[-1].lower().split("-")[0].replace("7z","").replace(".exe","")
  121. if len(v_num):
  122. dl_url = self.z_url.replace("[[vers]]",v_num)
  123. except:
  124. pass
  125. if not dl_url:
  126. dl_url = self.z_url2
  127. temp = tempfile.mkdtemp()
  128. self.dl.stream_to_file(dl_url, os.path.join(temp, self.z_name))
  129. print("")
  130. print("Installing 7zip...")
  131. # From Tim Sutton's brigadier: https://github.com/timsutton/brigadier/blob/master/brigadier
  132. out = self.r.run({"args":["msiexec", "/qn", "/i", os.path.join(temp, self.z_name)],"stream":True})
  133. if out[2] != 0:
  134. print("Error ({})".format(out[2]))
  135. print("")
  136. self.u.grab("Press [enter] to exit...")
  137. exit(1)
  138. # Set the z_path to the 64 bit
  139. self.z_path = self.z_path64
  140. print("")
  141. return os.path.exists(self.z_path)
  142.  
  143. def check_bi(self):
  144. # Checks for BOOTICEx64.exe in our scripts dir
  145. # and downloads it if need be
  146. if os.path.exists(os.path.join(self.s_path, self.bi_name)):
  147. # print("Located {}!".format(self.bi_name))
  148. # Got it
  149. return True
  150. print("Couldn't locate {} - downloading...".format(self.bi_name))
  151. self.dl.stream_to_file(self.bi_url, os.path.join(self.s_path, self.bi_name))
  152. print("")
  153. return os.path.exists(os.path.join(self.s_path,self.bi_name))
  154.  
  155. def get_dl_info(self):
  156. # Returns the latest download package and info in a
  157. # dictionary: { "url" : dl_url, "name" : name, "info" : update_info }
  158. json_data = self.dl.get_string(self.clover_url, False)
  159. if not json_data or not len(json_data):
  160. return None
  161. try:
  162. j = json.loads(json_data)
  163. except:
  164. return None
  165. dl_link = next((x.get("browser_download_url", None) for x in j.get("assets", []) if x.get("browser_download_url", "").lower().endswith(".lzma")), None)
  166. if not dl_link:
  167. return None
  168. return { "url" : dl_link, "name" : os.path.basename(dl_link), "info" : j.get("body", None) }
  169.  
  170. def diskpart_flag(self, disk, as_efi=False):
  171. # Sets and unsets the GUID needed for a GPT EFI partition ID
  172. self.u.head("Changing ID With DiskPart")
  173. print("")
  174. print("Setting type as {}...".format("EFI" if as_efi else "Basic Data"))
  175. print("")
  176. # - EFI system partition: c12a7328-f81f-11d2-ba4b-00a0c93ec93b
  177. # - Basic data partition: ebd0a0a2-b9e5-4433-87c0-68b6b72699c7
  178. dp_script = "\n".join([
  179. "select disk {}".format(disk.get("index",-1)),
  180. "sel part 1",
  181. "set id={}".format(self.efi_id if as_efi else self.bas_id)
  182. ])
  183. temp = tempfile.mkdtemp()
  184. script = os.path.join(temp, "diskpart.txt")
  185. try:
  186. with open(script,"w") as f:
  187. f.write(dp_script)
  188. except:
  189. shutil.rmtree(temp)
  190. print("Error creating script!")
  191. print("")
  192. self.u.grab("Press [enter] to return...")
  193. return
  194. # Let's try to run it!
  195. out = self.r.run({"args":["diskpart","/s",script],"stream":True})
  196. # Ditch our script regardless of whether diskpart worked or not
  197. shutil.rmtree(temp)
  198. print("")
  199. if out[2] != 0:
  200. # Error city!
  201. print("DiskPart exited with non-zero status ({}). Aborting.".format(out[2]))
  202. else:
  203. print("Done - You may need to replug your drive for the")
  204. print("changes to take effect.")
  205. print("")
  206. self.u.grab("Press [enter] to return...")
  207.  
  208. def diskpart_erase(self, disk, gpt=False):
  209. # Generate a script that we can pipe to diskpart to erase our disk
  210. self.u.head("Erasing With DiskPart")
  211. print("")
  212. # Then we'll re-gather our disk info on success and move forward
  213. # Using MBR to effectively set the individual partition types
  214. # Keeps us from having issues mounting the EFI on Windows -
  215. # and also lets us explicitly set the partition id for the main
  216. # data partition.
  217. if not gpt:
  218. print("Using MBR...")
  219. dp_script = "\n".join([
  220. "select disk {}".format(disk.get("index",-1)),
  221. "clean",
  222. "convert mbr",
  223. "create partition primary size=200",
  224. "format quick fs=fat32 label='CLOVER'",
  225. "active",
  226. "create partition primary id=AB" # AF = HFS, AB = Recovery
  227. ])
  228. else:
  229. print("Using GPT...")
  230. dp_script = "\n".join([
  231. "select disk {}".format(disk.get("index",-1)),
  232. "clean",
  233. "convert gpt",
  234. "create partition primary size=200",
  235. "format quick fs=fat32 label='CLOVER'",
  236. "create partition primary id={}".format(self.hfs_id)
  237. ])
  238. temp = tempfile.mkdtemp()
  239. script = os.path.join(temp, "diskpart.txt")
  240. try:
  241. with open(script,"w") as f:
  242. f.write(dp_script)
  243. except:
  244. shutil.rmtree(temp)
  245. print("Error creating script!")
  246. print("")
  247. self.u.grab("Press [enter] to return...")
  248. return
  249. # Let's try to run it!
  250. out = self.r.run({"args":["diskpart","/s",script],"stream":True})
  251. # Ditch our script regardless of whether diskpart worked or not
  252. shutil.rmtree(temp)
  253. if out[2] != 0:
  254. # Error city!
  255. print("")
  256. print("DiskPart exited with non-zero status ({}). Aborting.".format(out[2]))
  257. print("")
  258. self.u.grab("Press [enter] to return...")
  259. return
  260. # We should now have a fresh drive to work with
  261. # Let's write an image or something
  262. self.u.head("Updating Disk Information")
  263. print("")
  264. print("Re-populating list...")
  265. self.d.update()
  266. print("Relocating disk {}".format(disk["index"]))
  267. disk = self.d.disks[str(disk["index"])]
  268. self.select_package(disk)
  269.  
  270. def select_package(self, disk):
  271. self.u.head("Select Recovery Package")
  272. print("")
  273. print("{}. {} - {} ({})".format(
  274. disk.get("index",-1),
  275. disk.get("model","Unknown"),
  276. self.dl.get_size(disk.get("size",-1),strip_zeroes=True),
  277. ["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][disk.get("type",0)]
  278. ))
  279. print("")
  280. print("M. Main Menu")
  281. print("Q. Quit")
  282. print("")
  283. menu = self.u.grab("Please paste the recovery update pkg path to extract: ")
  284. if menu.lower() == "q":
  285. self.u.custom_quit()
  286. if menu.lower() == "m":
  287. return
  288. path = self.u.check_path(menu)
  289. if not path:
  290. self.select_package(disk)
  291. return
  292. # Got the package - let's make sure it's named right - just in case
  293. if os.path.basename(path).lower().endswith(".hfs"):
  294. # We have an hfs image already - bypass extraction
  295. self.dd_image(disk, path)
  296. return
  297. # If it's a directory, find the first recovery hit
  298. if os.path.isdir(path):
  299. for f in os.listdir(path):
  300. if f.lower().endswith(self.recovery_suffixes):
  301. path = os.path.join(path, f)
  302. break
  303. # Make sure it's named right for recovery stuffs
  304. if not path.lower().endswith(self.recovery_suffixes):
  305. self.u.head("Invalid Package")
  306. print("")
  307. print("{} is not in the available recovery package names:\n{}".format(os.path.basename(path), ", ".join(self.recovery_suffixes)))
  308. print("")
  309. print("Ensure you're passing a proper recovery package.")
  310. print("")
  311. self.u.grab("Press [enter] to return to package selection...")
  312. self.select_package(disk)
  313. return
  314. self.u.head("Extracting Package")
  315. print("")
  316. temp = tempfile.mkdtemp()
  317. cwd = os.getcwd()
  318. os.chdir(temp)
  319. # Extract in sections and remove any files we run into
  320. print("Extracting Recovery dmg...")
  321. out = self.r.run({"args":[self.z_path, "e", "-txar", path, "*.dmg"]})
  322. if out[2] != 0:
  323. shutil.rmtree(temp,ignore_errors=True)
  324. print("An error occurred extracting: {}".format(out[2]))
  325. print("")
  326. self.u.grab("Press [enter] to return...")
  327. return
  328. print("Extracting BaseSystem.dmg...")
  329. # No files to delete here - let's extract the next part
  330. out = self.r.run({"args":[self.z_path, "e", "*.dmg", "*/Base*.dmg"]})
  331. if out[2] != 0:
  332. shutil.rmtree(temp,ignore_errors=True)
  333. print("An error occurred extracting: {}".format(out[2]))
  334. print("")
  335. self.u.grab("Press [enter] to return...")
  336. return
  337. # If we got here - we should delete everything in the temp folder except
  338. # for a .dmg that starts with Base
  339. del_list = [x for x in os.listdir(temp) if not (x.lower().startswith("base") and x.lower().endswith(".dmg"))]
  340. for d in del_list:
  341. os.remove(os.path.join(temp, d))
  342. # Onto the last command
  343. print("Extracting hfs...")
  344. out = self.r.run({"args":[self.z_path, "e", "-tdmg", "Base*.dmg", "*.hfs"]})
  345. if out[2] != 0:
  346. shutil.rmtree(temp,ignore_errors=True)
  347. print("An error occurred extracting: {}".format(out[2]))
  348. print("")
  349. self.u.grab("Press [enter] to return...")
  350. return
  351. # If we got here - we should delete everything in the temp folder except
  352. # for a .dmg that starts with Base
  353. del_list = [x for x in os.listdir(temp) if not x.lower().endswith(".hfs")]
  354. for d in del_list:
  355. os.remove(os.path.join(temp, d))
  356. print("Extracted successfully!")
  357. hfs = next((x for x in os.listdir(temp) if x.lower().endswith(".hfs")),None)
  358. # Now to dd our image - if it exists
  359. if not hfs:
  360. print("Missing the .hfs file! Aborting.")
  361. print("")
  362. self.u.grab("Press [enter] to return...")
  363. else:
  364. self.dd_image(disk, os.path.join(temp, hfs))
  365. shutil.rmtree(temp,ignore_errors=True)
  366.  
  367. def dd_image(self, disk, image):
  368. # Let's dd the shit out of our disk
  369. self.u.head("Copying Image To Drive")
  370. print("")
  371. print("Image: {}".format(image))
  372. print("")
  373. print("Disk {}. {} - {} ({})".format(
  374. disk.get("index",-1),
  375. disk.get("model","Unknown"),
  376. self.dl.get_size(disk.get("size",-1),strip_zeroes=True),
  377. ["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][disk.get("type",0)]
  378. ))
  379. print("")
  380. args = [
  381. os.path.join(self.s_path, self.dd_name),
  382. "if={}".format(image),
  383. "of=\\\\?\\Device\Harddisk{}\Partition2".format(disk.get("index",-1)),
  384. "bs=8M",
  385. "--progress"
  386. ]
  387. print(" ".join(args))
  388. print("")
  389. print("This may take some time!")
  390. print("")
  391. out = self.r.run({"args":args})
  392. if len(out[1].split("Error")) > 1:
  393. # We had some error text - dd, even when failing likes to give us a 0
  394. # status code. It also sends a ton of text through stderr - so we comb
  395. # that for "Error" then split by that to skip the extra fluff and show only
  396. # the error.
  397. print("An error occurred:\n\n{}".format("Error"+out[1].split("Error")[1]))
  398. print("")
  399. self.u.grab("Press [enter] to return to the main menu...")
  400. return
  401. # Install Clover to the target drive
  402. self.install_clover(disk)
  403.  
  404. def install_clover(self, disk):
  405. self.u.head("Installing Clover")
  406. print("")
  407. print("Gathering info...")
  408. c = self.get_dl_info()
  409. if c == None:
  410. print(" - Error communicating with github!")
  411. print("")
  412. self.u.grab("Press [enter] to return...")
  413. return
  414. print(" - Got {}".format(c.get("name","Unknown Version")))
  415. print("Downloading...")
  416. temp = tempfile.mkdtemp()
  417. os.chdir(temp)
  418. clover_lzma = c["name"]
  419. self.dl.stream_to_file(c["url"], os.path.join(temp, c["name"]))
  420. print("") # Empty space to clear the download progress
  421. if not os.path.exists(os.path.join(temp, c["name"])):
  422. print(" - Download failed. Aborting...")
  423. print("")
  424. self.u.grab("Press [enter] to return...")
  425. return
  426. # Got a valid file in our temp dir
  427. print("Extracting {}...".format(clover_lzma))
  428. out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_lzma)]})
  429. if out[2] != 0:
  430. shutil.rmtree(temp,ignore_errors=True)
  431. print(" - An error occurred extracting: {}".format(out[2]))
  432. print("")
  433. self.u.grab("Press [enter] to return...")
  434. return
  435. # Should result in a .tar file
  436. clover_tar = next((x for x in os.listdir(temp) if x.lower().endswith(".tar")),None)
  437. if not clover_tar:
  438. print(" - No .tar archive found - aborting...")
  439. print("")
  440. self.u.grab("Press [enter] to return...")
  441. return
  442. # Got the .tar archive - get the .iso
  443. print("Extracting {}...".format(clover_tar))
  444. out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_tar)]})
  445. if out[2] != 0:
  446. shutil.rmtree(temp,ignore_errors=True)
  447. print(" - An error occurred extracting: {}".format(out[2]))
  448. print("")
  449. self.u.grab("Press [enter] to return...")
  450. return
  451. # Should result in a .iso file
  452. clover_iso = next((x for x in os.listdir(temp) if x.lower().endswith(".iso")),None)
  453. if not clover_tar:
  454. print(" - No .iso found - aborting...")
  455. print("")
  456. self.u.grab("Press [enter] to return...")
  457. return
  458. # Got the .iso - let's extract the needed parts
  459. print("Extracting EFI from {}...".format(clover_iso))
  460. out = self.r.run({"args":[self.z_path, "x", os.path.join(temp,clover_iso), "EFI*"]})
  461. if out[2] != 0:
  462. shutil.rmtree(temp,ignore_errors=True)
  463. print(" - An error occurred extracting: {}".format(out[2]))
  464. print("")
  465. self.u.grab("Press [enter] to return...")
  466. return
  467. print("Extracting {} from {}...".format(self.boot0,clover_iso))
  468. out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_iso), self.boot0, "-r"]})
  469. if out[2] != 0:
  470. shutil.rmtree(temp,ignore_errors=True)
  471. print(" - An error occurred extracting: {}".format(out[2]))
  472. print("")
  473. self.u.grab("Press [enter] to return...")
  474. return
  475. print("Extracting {} from {}...".format(self.boot1,clover_iso))
  476. out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_iso), self.boot1, "-r"]})
  477. if out[2] != 0:
  478. shutil.rmtree(temp,ignore_errors=True)
  479. print(" - An error occurred extracting: {}".format(out[2]))
  480. print("")
  481. self.u.grab("Press [enter] to return...")
  482. return
  483. print("Extracting {} from {}...".format(self.boot,clover_iso))
  484. out = self.r.run({"args":[self.z_path, "e", os.path.join(temp,clover_iso), self.boot, "-r"]})
  485. if out[2] != 0:
  486. shutil.rmtree(temp,ignore_errors=True)
  487. print(" - An error occurred extracting: {}".format(out[2]))
  488. print("")
  489. self.u.grab("Press [enter] to return...")
  490. return
  491. # At this point, we should have a boot0xx file and an EFI folder in the temp dir
  492. # We need to udpate the disk list though - to reflect the current file system on part 1
  493. # of our current disk
  494. self.d.update() # assumes our disk number stays the same
  495. # Some users are having issues with the "partitions" key not populating - possibly a 3rd party disk management soft?
  496. # Possibly a bad USB?
  497. # We'll see if the key exists - if not, we'll throw an error.
  498. if self.d.disks[str(disk["index"])].get("partitions",None) == None:
  499. # No partitions found.
  500. shutil.rmtree(temp,ignore_errors=True)
  501. print("No partitions located on disk!")
  502. print("")
  503. self.u.grab("Press [enter] to return...")
  504. return
  505. part = self.d.disks[str(disk["index"])]["partitions"].get("0",{}).get("letter",None) # get the first partition's letter
  506. if part == None:
  507. shutil.rmtree(temp,ignore_errors=True)
  508. print("Lost original disk - or formatting failed!")
  509. print("")
  510. self.u.grab("Press [enter] to return...")
  511. return
  512. # Here we have our disk and partitions and such - the CLOVER partition
  513. # will be the first partition
  514. # Let's copy over the EFI folder and then dd the boot0xx file
  515. print("Copying EFI folder to {}/EFI...".format(part))
  516. if os.path.exists("{}/EFI".format(part)):
  517. print(" - EFI exists - removing...")
  518. shutil.rmtree("{}/EFI".format(part),ignore_errors=True)
  519. time.sleep(1) # Added because windows is dumb
  520. shutil.copytree(os.path.join(temp,"EFI"), "{}/EFI".format(part))
  521. # Copy boot6 over to the root of the EFI volume - and rename it to boot
  522. print("Copying {} to {}/boot...".format(self.boot,part))
  523. shutil.copy(os.path.join(temp,self.boot),"{}/boot".format(part))
  524. # Use bootice to update the MBR and PBR - always on the first
  525. # partition (which is 0 in bootice)
  526. print("Updating the MBR with {}...".format(self.boot0))
  527. args = [
  528. os.path.join(self.s_path,self.bi_name),
  529. "/device={}".format(disk.get("index",-1)),
  530. "/mbr",
  531. "/restore",
  532. "/file={}".format(os.path.join(temp,self.boot0)),
  533. "/keep_dpt",
  534. "/quiet"
  535. ]
  536. out = self.r.run({"args":args})
  537. if out[2] != 0:
  538. shutil.rmtree(temp,ignore_errors=True)
  539. print(" - An error occurred updating the MBR: {}".format(out[2]))
  540. print("")
  541. self.u.grab("Press [enter] to return...")
  542. return
  543. print("Updating the PBR with {}...".format(self.boot1))
  544. args = [
  545. os.path.join(self.s_path,self.bi_name),
  546. "/device={}:0".format(disk.get("index",-1)),
  547. "/pbr",
  548. "/restore",
  549. "/file={}".format(os.path.join(temp,self.boot1)),
  550. "/keep_bpb",
  551. "/quiet"
  552. ]
  553. out = self.r.run({"args":args})
  554. if out[2] != 0:
  555. shutil.rmtree(temp,ignore_errors=True)
  556. print(" - An error occurred updating the PBR: {}".format(out[2]))
  557. print("")
  558. self.u.grab("Press [enter] to return...")
  559. return
  560. print("Cleaning up...")
  561. shutil.rmtree(temp,ignore_errors=True)
  562. print("")
  563. print("Done.")
  564. print("")
  565. self.u.grab("Press [enter] to return to the main menu...")
  566.  
  567. def main(self):
  568. # Start out with our cd in the right spot.
  569. os.chdir(os.path.dirname(os.path.realpath(__file__)))
  570. # Let's make sure we have the required files needed
  571. self.u.head("Checking Required Tools")
  572. print("")
  573. if not self.check_dd():
  574. print("Couldn't find or install {} - aborting!".format(self.dd_name))
  575. exit(1)
  576. if not self.check_7z():
  577. print("Couldn't find or install {} - aborting!".format(self.z_name))
  578. exit(1)
  579. if not self.check_bi():
  580. print("Couldn't find or install {} - aborting!".format(self.bi_name))
  581. exit(1)
  582. # Let's just setup a real simple interface and try to write some data
  583. self.u.head("Gathering Disk Info")
  584. print("")
  585. print("Populating list...")
  586. self.d.update()
  587. print("")
  588. print("Done!")
  589. # Let's serve up a list of *only* removable media
  590. self.u.head("Potential Removable Media")
  591. print("")
  592. rem_disks = self.get_disks_of_type(self.d.disks) if not self.show_all_disks else self.d.disks
  593.  
  594. # Types: 0 = Unknown, 1 = No Root Dir, 2 = Removable, 3 = Local, 4 = Network, 5 = Disc, 6 = RAM disk
  595.  
  596. if self.show_all_disks:
  597. print("!WARNING! This list includes ALL disk types.")
  598. print("!WARNING! Be ABSOLUTELY sure before selecting")
  599. print("!WARNING! a disk!")
  600. else:
  601. print("!WARNING! This list includes both Removable AND")
  602. print("!WARNING! Unknown disk types. Be ABSOLUTELY sure")
  603. print("!WARNING! before selecting a disk!")
  604. print("")
  605. for disk in sorted(rem_disks):
  606. print("{}. {} - {} ({})".format(
  607. disk,
  608. rem_disks[disk].get("model","Unknown"),
  609. self.dl.get_size(rem_disks[disk].get("size",-1),strip_zeroes=True),
  610. ["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][rem_disks[disk].get("type",0)]
  611. ))
  612. if not len(rem_disks[disk].get("partitions",{})):
  613. print(" No Mounted Partitions")
  614. else:
  615. parts = rem_disks[disk]["partitions"]
  616. for p in sorted(parts):
  617. print(" {}. {} ({}) {} - {}".format(
  618. p,
  619. parts[p].get("letter","No Letter"),
  620. "No Name" if not parts[p].get("name",None) else parts[p].get("name","No Name"),
  621. parts[p].get("file system","Unknown FS"),
  622. self.dl.get_size(parts[p].get("size",-1),strip_zeroes=True)
  623. ))
  624. print("")
  625. print("Q. Quit")
  626. print("")
  627. print("Usage: [drive number][option (only one allowed)] (eg. 1C)")
  628. print(" Options are as follows with precedence C > E > U > G:")
  629. print(" C = Only install Clover to the drive's first partition.")
  630. print(" E = Sets the type of the drive's first partition to EFI.")
  631. print(" U = Similar to E, but sets the type to Basic Data (useful for editing).")
  632. print(" G = Format as GPT (default is MBR).")
  633. print(" D = Used without a drive number, toggles showing all disks.")
  634. print("")
  635. menu = self.u.grab("Please select a disk or press [enter] with no options to refresh: ")
  636. if not len(menu):
  637. self.main()
  638. return
  639. if menu.lower() == "q":
  640. self.u.custom_quit()
  641. if menu.lower() == "d":
  642. self.show_all_disks ^= True
  643. self.main()
  644. return
  645. only_clover = set_efi = unset_efi = use_gpt = False
  646. if "c" in menu.lower():
  647. only_clover = True
  648. menu = menu.lower().replace("c","")
  649. if "e" in menu.lower():
  650. set_efi = True
  651. menu = menu.lower().replace("e","")
  652. if "u" in menu.lower():
  653. unset_efi = True
  654. menu = menu.lower().replace("u","")
  655. if "g" in menu.lower():
  656. use_gpt = True
  657. menu = menu.lower().replace("g","")
  658.  
  659. selected_disk = rem_disks.get(menu,None)
  660. if not selected_disk:
  661. self.u.head("Invalid Choice")
  662. print("")
  663. print("Disk {} is not an option.".format(menu))
  664. print("")
  665. self.u.grab("Returning in 5 seconds...", timeout=5)
  666. self.main()
  667. return
  668. # Got a disk!
  669. if only_clover:
  670. self.install_clover(selected_disk)
  671. elif set_efi:
  672. self.diskpart_flag(selected_disk, True)
  673. elif unset_efi:
  674. self.diskpart_flag(selected_disk, False)
  675. else:
  676. # Check erase
  677. while True:
  678. self.u.head("Erase {}".format(selected_disk.get("model","Unknown")))
  679. print("")
  680. print("{}. {} - {} ({})".format(
  681. selected_disk.get("index",-1),
  682. selected_disk.get("model","Unknown"),
  683. self.dl.get_size(selected_disk.get("size",-1),strip_zeroes=True),
  684. ["Unknown","No Root Dir","Removable","Local","Network","Disc","RAM Disk"][selected_disk.get("type",0)]
  685. ))
  686. print("")
  687. print("If you continue - THIS DISK WILL BE ERASED")
  688. print("ALL DATA WILL BE LOST AND ALL PARTITIONS WILL")
  689. print("BE REMOVED!!!!!!!")
  690. print("")
  691. yn = self.u.grab("Continue? (y/n): ")
  692. if yn.lower() == "n":
  693. self.main()
  694. return
  695. if yn.lower() == "y":
  696. break
  697. # Got the OK to erase! Let's format a diskpart script!
  698. self.diskpart_erase(selected_disk, use_gpt)
  699. self.main()
  700.  
  701. if __name__ == '__main__':
  702. w = WinUSB()
  703. w.main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement