diff --git a/Library/firehose.py b/Library/firehose.py index 6cd149d..65ed1d8 100755 --- a/Library/firehose.py +++ b/Library/firehose.py @@ -254,7 +254,8 @@ class qualcomm_firehose: if (rsp[0])==True: if "value" in rsp[1]: if rsp[1]["value"]=="NAK": - logger.error(rsp[2].decode('utf-8')) + if Display: + logger.error(rsp[2].decode('utf-8')) return "" bytesToRead=self.cfg.SECTOR_SIZE_IN_BYTES*num_partition_sectors total=bytesToRead diff --git a/Library/gpt.py b/Library/gpt.py index 4664e08..5014a20 100755 --- a/Library/gpt.py +++ b/Library/gpt.py @@ -14,7 +14,9 @@ class gpt: ('first_usable_lba', 'Q'), ('last_usable_lba', 'Q'), ('disk_guid', '16s'), - ('part_entry_start_lba', 'Q') + ('part_entry_start_lba', 'Q'), + ('num_part_entries', 'I'), + ('part_entry_size', 'I') ] gpt_partition = [ @@ -116,11 +118,12 @@ class gpt: self.num_part_entries = num_part_entries self.part_entry_size = part_entry_size self.part_entry_start_lba = part_entry_start_lba + ''' if num_part_entries is 0: self.gpt_header += [('num_part_entries', 'I'),] if part_entry_size is 0: self.gpt_header += [('part_entry_size', 'I'),] - + ''' def parse(self, gptdata, sectorsize=512): self.header = read_object(gptdata[sectorsize:sectorsize+0x5C], self.gpt_header) diff --git a/README.md b/README.md index 0c30643..02f733f 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Windows: - "./edl.py rs 0 15 data.bin" -> to dump 15 sectors from starting sector 0 to file data.bin for device with emmc - "./edl.py r boot_a boot.img" -> to dump the partition "boot_a" to the filename boot.img for device with emmc - "./edl.py footer footer.bin" -> to dump the crypto footer for Androids with emmc flash -- "./edl.py w boot boot.img" -> to write boot.img to the "boot" partition on lun 0 on the device with emmc flash +- "./edl.py w boot_a boot.img" -> to write boot.img to the "boot" partition on lun 0 on the device with emmc flash - "./edl.py wl dumps" -> to write all files from "dumps" folder to according partitions to flash - "./edl.py wf dump.bin" -> to write the rawimage dump.bin to flash - "./edl.py e misc" -> to erase the partition misc on emmc flash @@ -51,12 +51,14 @@ Windows: - "./edl.py printgpt --memory=ufs --lun=0" -> to print gpt on lun 0 on device with ufs - "./edl.py rf lun0.bin --memory=ufs --lun=0" -> to dump whole lun 0 for device with ufs -- "./edl.py rl dumps --memory=ufs --lun=0 --skip=userdata" -> to dump all partitions from lun0 to directory dumps for device with ufs and skip userdata partition +- "./edl.py rl dumps --memory=ufs --lun=0 --skip=userdata,vendor_a" -> to dump all partitions from lun0 to directory dumps for device with ufs and skip userdata and vendor_a partition +- "./edl.py rl dumps --memory=ufs --autolun --skip=userdata" -> to dump all partitions from all lun to directory dumps for device with ufs and skip userdata partition - "./edl.py rs 0 15 data.bin --memory=ufs --lun=0" -> to dump 15 sectors from starting sector 0 from lun 0 to file data.bin for device with emmc - "./edl.py r boot_a boot.img --memory=ufs --lun=4" -> to dump the partition "boot_a" from lun 4 to the filename boot.img for device with emmc -- "./edl.py footer footer.bin --memory=ufs --lun=4" -> to dump the crypto footer for Androids from lun4 -- "./edl.py w boot boot.img --memory=ufs --lun=0" -> to write boot.img to the "boot" partition on lun 0 on the device with ufs flash +- "./edl.py footer footer.bin --memory=ufs --lun=0" -> to dump the crypto footer for Androids from lun 0 +- "./edl.py w boot boot.img --memory=ufs --lun=4" -> to write boot.img to the "boot" partition on lun 4 on the device with ufs flash - "./edl.py wl dumps --memory=ufs --lun=0" -> to write all files from "dumps" folder to according partitions to flash lun 0 +- "./edl.py wl dumps --memory=ufs --autolun" -> to write all files from "dumps" folder to according partitions to flash and try to autodetect lun - "./edl.py wf dump.bin --memory=ufs --lun=0" -> to write the rawimage dump.bin to flash lun 0 - "./edl.py e misc --memory=ufs --lun=0" -> to erase the partition misc on lun 0 diff --git a/edl.py b/edl.py index ae7236d..7c46f1c 100755 --- a/edl.py +++ b/edl.py @@ -10,14 +10,14 @@ Usage: edl.py [--gpt-num-part-entries=number] [--gpt-part-entry-size=number] [--gpt-part-entry-start-lba=number] edl.py [--memory=memtype] [--skipstorageinit] [--maxpayload=bytes] [--sectorsize==bytes] edl.py server [--tcpport=portnumber] - edl.py printgpt [--lun=lun] + edl.py printgpt [--memory=memtype] [--lun=lun] edl.py gpt [--memory=memtype] [--lun=lun] edl.py r [--memory=memtype] [--lun=lun] - edl.py rl [--memory=memtype] [--lun=lun] [--skip=partname] + edl.py rl [--memory=memtype] [--lun=lun] [--skip=partnames] [--autolun] edl.py rf [--memory=memtype] [--lun=lun] edl.py rs [--lun=lun] edl.py w [--memory=memtype] [--lun=lun] [--skipwrite] - edl.py wl [--memory=memtype] [--lun=lun] + edl.py wl [--memory=memtype] [--lun=lun] [--skip=partnames] [--autolun] edl.py wf [--memory=memtype] [--lun=lun] edl.py ws [--memory=memtype] [--lun=lun] [--skipwrite] edl.py e [--memory=memtype] [--skipwrite] [--lun=lun] @@ -45,7 +45,7 @@ Usage: Description: server [--tcpport=portnumber] # Run tcp/ip server - printgpt [--lun=lun] # Print GPT Table information + printgpt [--memory=memtype] [--lun=lun] # Print GPT Table information gpt [--memory=memtype] [--lun=lun] # Save gpt table to file r [--memory=memtype] [--lun=lun] # Read flash to filename rl [--memory=memtype] [--lun=lun] [--skip=partname] # Read all partitions from flash to a directory @@ -93,7 +93,7 @@ Options: --gpt-part-entry-size=number Set GPT entry size [default: 0] --gpt-part-entry-start-lba=number Set GPT entry start lba sector [default: 0] --tcpport=portnumber Set port for tcp server [default:1340] - --skip=partname Skip reading partition with name "partname" + --skip=partnames Skip reading partition with names "partname1,partname2,etc." """ print("Qualcomm Sahara / Firehose Client (c) B.Kerler 2018-2019.") @@ -1037,13 +1037,13 @@ def handle_firehose(args, cdc, sahara): TargetName = msmids[hwid] if args["gpt"]: - lun=int(args[""]) + lun=int(args["--lun"]) filename = args[""] fh.cmd_read(lun, 0, 0x4000 // cfg.SECTOR_SIZE_IN_BYTES, filename) print(f"Dumped GPT to {filename}") exit(0) elif args["printgpt"]: - lun=int(args[""]) + lun=int(args["--lun"]) guid_gpt = fh.get_gpt(lun, int(args["--gpt-num-part-entries"]), int(args["--gpt-part-entry-size"]), int(args["--gpt-part-entry-start-lba"])) if guid_gpt == None: @@ -1074,22 +1074,37 @@ def handle_firehose(args, cdc, sahara): elif args["rl"]: lun = int(args["--lun"]) directory = args[""] - skip = args["--skip"] - guid_gpt = fh.get_gpt(lun, int(args["--gpt-num-part-entries"]), int(args["--gpt-part-entry-size"]), - int(args["--gpt-part-entry-start-lba"])) - if guid_gpt == None: - logger.error("Error on reading GPT, maybe wrong memoryname given ?") + skip = args["--skip"].split(",") + autolun = args["--autolun"] + luns=[] + if autolun and not args["--memory"].lower()=="emmc": + for i in range(0,99): + luns.append(i) else: - if not os.path.exists(directory): - os.mkdir(directory) - for partition in guid_gpt.partentries: - partitionname=partition.name - if skip==partition.name: - continue - filename=os.path.join(directory,partitionname+".bin") - logging.info(f"Dumping partition {str(partition.name)} with sector count {str(partition.sectors)} as {filename}.") - fh.cmd_read(lun, partition.sector, partition.sectors, filename) - exit(0) + luns=[lun] + + if not os.path.exists(directory): + os.mkdir(directory) + + for slun in luns: + guid_gpt = fh.get_gpt(slun, int(args["--gpt-num-part-entries"]), int(args["--gpt-part-entry-size"]), + int(args["--gpt-part-entry-start-lba"])) + if guid_gpt == None: + break + else: + if len(luns)>1: + storedir=os.path.join(directory,"lun"+str(slun)) + else: + storedir=directory + if not os.path.exists(storedir): + os.mkdir(storedir) + for partition in guid_gpt.partentries: + partitionname=partition.name + if partition.name in skip: + continue + filename=os.path.join(storedir,partitionname+".bin") + logging.info(f"Dumping partition {str(partition.name)} with sector count {str(partition.sectors)} as {filename}.") + fh.cmd_read(slun, partition.sector, partition.sectors, filename) exit(0) elif args["rf"]: lun = int(args["--lun"]) @@ -1359,7 +1374,15 @@ def handle_firehose(args, cdc, sahara): exit(0) elif args["wl"]: directory=args[""] - lun = int(args["--lun"]) + skip = args["--skip"].split(",") + luns = [] + autolun=args["--autolun"] + if autolun: + for i in range(0,99): + luns.append(i) + else: + luns=[int(args["--lun"])] + if not os.path.exists(directory): logger.error(f"Error: Couldn't find directory: {directory}") exit(0) @@ -1367,29 +1390,31 @@ def handle_firehose(args, cdc, sahara): for dirName, subdirList, fileList in os.walk(directory): for fname in fileList: filenames.append(os.path.join(dirName, fname)) - - guid_gpt = fh.get_gpt(lun, int(args["--gpt-num-part-entries"]), int(args["--gpt-part-entry-size"]), - int(args["--gpt-part-entry-start-lba"])) - if guid_gpt == None: - logger.error("Error on reading GPT, maybe wrong memoryname given ?") - else: - if "partentries" in dir(guid_gpt): - for filename in filenames: - for partition in guid_gpt.partentries: - partname=filename[filename.rfind("/")+1:] - if ".bin" in partname[-4:]: - partname=partname[:-4] - if partition.name == partname: - sectors = os.stat(filename).st_size // fh.cfg.SECTOR_SIZE_IN_BYTES - if (os.stat(filename).st_size % fh.cfg.SECTOR_SIZE_IN_BYTES) > 0: - sectors += 1 - if sectors > partition.sectors: - logger.error(f"Error: {filename} has {sectors} sectors but partition only has {partition.sectors}.") - exit(0) - print(f"Writing {filename} to partition {str(partition.name)}.") - fh.cmd_write(lun, partition.sector, filename) + for lun in luns: + guid_gpt = fh.get_gpt(lun, int(args["--gpt-num-part-entries"]), int(args["--gpt-part-entry-size"]), + int(args["--gpt-part-entry-start-lba"])) + if guid_gpt == None: + break else: - print("Couldn't write partition. Either wrong memorytype given or no gpt partition.") + if "partentries" in dir(guid_gpt): + for filename in filenames: + for partition in guid_gpt.partentries: + partname=filename[filename.rfind("/")+1:] + if ".bin" in partname[-4:]: + partname=partname[:-4] + if partition.name == partname: + if partition.name in skip: + continue + sectors = os.stat(filename).st_size // fh.cfg.SECTOR_SIZE_IN_BYTES + if (os.stat(filename).st_size % fh.cfg.SECTOR_SIZE_IN_BYTES) > 0: + sectors += 1 + if sectors > partition.sectors: + logger.error(f"Error: {filename} has {sectors} sectors but partition only has {partition.sectors}.") + exit(0) + print(f"Writing {filename} to partition {str(partition.name)}.") + fh.cmd_write(lun, partition.sector, filename) + else: + print("Couldn't write partition. Either wrong memorytype given or no gpt partition.") exit(0) elif args["ws"]: lun = int(args["--lun"])