Example #1
0
 def get_backup_gpt(self,
                    lun,
                    gpt_num_part_entries,
                    gpt_part_entry_size,
                    gpt_part_entry_start_lba,
                    parttype="user"):
     data = self.readflash(addr=0,
                           length=2 * self.config.pagesize,
                           filename="",
                           parttype=parttype,
                           display=False)
     if data == b"":
         return None
     guid_gpt = gpt(
         num_part_entries=gpt_num_part_entries,
         part_entry_size=gpt_part_entry_size,
         part_entry_start_lba=gpt_part_entry_start_lba,
     )
     header = guid_gpt.parseheader(data, self.config.SECTOR_SIZE_IN_BYTES)
     if "backup_lba" in header:
         sectors = header["first_usable_lba"] - 1
         data = self.readflash(addr=header["backup_lba"] *
                               self.config.pagesize,
                               length=sectors * self.config.pagesize,
                               filename="",
                               display=False)
         if data == b"":
             return None
         return data
     else:
         return None
Example #2
0
 def get_backup_gpt(self, lun, gpt_num_part_entries, gpt_part_entry_size, gpt_part_entry_start_lba):
     data = self.cmd_read_buffer(lun, 0, 2, False)
     if data == b"":
         return None
     guid_gpt = gpt(
         num_part_entries=gpt_num_part_entries,
         part_entry_size=gpt_part_entry_size,
         part_entry_start_lba=gpt_part_entry_start_lba,
     )
     header = guid_gpt.parseheader(data, self.cfg.SECTOR_SIZE_IN_BYTES)
     if "backup_lba" in header:
         sectors = header["first_usable_lba"] - 1
         data = self.cmd_read_buffer(lun, header["backup_lba"], sectors, False)
         if data==b"":
             return None
         return data
     else:
         return None
Example #3
0
 def get_gpt(self, lun, gpt_num_part_entries, gpt_part_entry_size,
             gpt_part_entry_start_lba):
     data = self.cmd_read_buffer(lun, 0, 2, False)
     if data == "":
         return None, None
     guid_gpt = gpt(
         num_part_entries=gpt_num_part_entries,
         part_entry_size=gpt_part_entry_size,
         part_entry_start_lba=gpt_part_entry_start_lba,
     )
     header = guid_gpt.parseheader(data, self.cfg.SECTOR_SIZE_IN_BYTES)
     if "first_usable_lba" in header:
         sectors = header["first_usable_lba"]
         if sectors == 0:
             return None, None
         data = self.cmd_read_buffer(lun, 0, sectors, False)
         guid_gpt.parse(data, self.cfg.SECTOR_SIZE_IN_BYTES)
         return data, guid_gpt
     else:
         return None, None
Example #4
0
 def get_gpt(self,
             gpt_num_part_entries,
             gpt_part_entry_size,
             gpt_part_entry_start_lba,
             parttype="user"):
     data = self.readflash(addr=0,
                           length=2 * self.config.pagesize,
                           filename="",
                           parttype=parttype,
                           display=False)
     if data[:9] == b"EMMC_BOOT" and self.read_pmt:
         partdata, partentries = self.read_pmt()
         if partdata == b"":
             return None, None
         else:
             return partdata, partentries
     if data == b"":
         return None, None
     guid_gpt = gpt(
         num_part_entries=gpt_num_part_entries,
         part_entry_size=gpt_part_entry_size,
         part_entry_start_lba=gpt_part_entry_start_lba,
     )
     header = guid_gpt.parseheader(data, self.config.pagesize)
     if "first_usable_lba" in header:
         sectors = header["first_usable_lba"]
         if sectors == 0:
             return None, None
         data = self.readflash(addr=0,
                               length=sectors * self.config.pagesize,
                               filename="",
                               parttype=parttype,
                               display=False)
         if data == b"":
             return None, None
         guid_gpt.parse(data, self.config.pagesize)
         return data, guid_gpt
     else:
         return None, None
Example #5
0
File: edl.py Project: vforkliu/edl
def main():
    info = 'Qualcomm Sahara / Firehose Client (c) B.Kerler 2018-2019.'
    parser = argparse.ArgumentParser(description=info)
    print("\n" + info + "\n\n")
    parser.add_argument(
        '-loader',
        metavar="none,<filename>",
        help='[Option] Flash programmer to load e.g. prog_emmc_firehose.elf',
        default='')
    parser.add_argument('-vid',
                        metavar="<vid>",
                        help='[Option] Specify vid, default=0x05c6)',
                        default="0x05C6")
    parser.add_argument('-pid',
                        metavar="<pid>",
                        help='[Option] Specify pid, default=0x9008)',
                        default="0x9008")
    parser.add_argument(
        '-maxpayload',
        metavar="<bytes>",
        help=
        '[Option] The max bytes to transfer in firehose mode (default=1048576)',
        type=int,
        default=1048576)
    parser.add_argument(
        '-skipwrite',
        help=
        '[Option] Do not write actual data to disk (use this for UFS provisioning)',
        action="store_true")
    parser.add_argument(
        '-skipstorageinit',
        help=
        '[Option] Do not initialize storage device (use this for UFS provisioning)',
        action="store_true")
    parser.add_argument('-memory',
                        metavar="<UFS/eMMC>",
                        help='[Option] Memory type (default=UFS)',
                        default='UFS')
    parser.add_argument('-sectorsize',
                        metavar="<bytes>",
                        help='[Option] Define Disk Sector Size (default=512)',
                        type=int,
                        default=512)
    parser.add_argument('-lun',
                        metavar="<num>",
                        help='[Option] Define LUN',
                        type=int,
                        default=0)
    #parser.add_argument('-debug', help='[Option] Enable debug output', action="store_true")
    parser.add_argument(
        '-debugmode',
        help='[CMD:Sahara] Switch to Memory Dump mode (Debug only)',
        action="store_true")
    parser.add_argument('-debugread',
                        help='[CMD:Sahara] Read Debug Logs',
                        action="store_true")
    parser.add_argument('-dmss',
                        help='[CMD:Sahara] Switch to DMSS Download mode',
                        action="store_true")
    parser.add_argument('-streaming',
                        help='[CMD:Sahara] Switch to Streaming Download mode',
                        action="store_true")
    parser.add_argument(
        '-r',
        metavar=("<PartName>", "<filename>"),
        help='[CMD:Firehose] Dump entire partition based on partition name',
        nargs=2,
        default=[])
    parser.add_argument('-rf',
                        metavar=("<filename>"),
                        help='[CMD:Firehose] Dump whole lun',
                        default="")
    parser.add_argument(
        '-rs',
        metavar=("<start_sector>", "<sectors>", "<filename>"),
        help='[CMD:Firehose] Dump from start sector to end sector to file',
        nargs=3,
        default=[])
    parser.add_argument('-pbl',
                        metavar=("<filename>"),
                        help='[CMD:Firehose] Dump boot rom (pbl)',
                        default="")
    parser.add_argument('-qfp',
                        metavar=("<filename>"),
                        help='[CMD:Firehose] Dump qfprom',
                        default="")
    parser.add_argument('-memtbl',
                        metavar=("<filename>"),
                        help='[CMD:Firehose] Dump memory table',
                        default="")
    parser.add_argument('-footer',
                        metavar=("<filename>"),
                        help='[CMD:Firehose] Dump crypto footer',
                        default="")
    parser.add_argument('-gpt',
                        metavar="<filename>",
                        help='[CMD:Firehose] Dump gpt to file',
                        default="")
    parser.add_argument('-printgpt',
                        help='[CMD:Firehose] Print gpt',
                        action="store_true")
    parser.add_argument(
        '-peek',
        metavar=("<offset>", "<length>", "<filename>"),
        help='[CMD:Firehose] Read memory from offset,length to file',
        nargs=3,
        default=[])
    parser.add_argument('-w',
                        metavar=("<partitionname>", "<filename>"),
                        help='[CMD:Firehose] Write filename to GPT partition',
                        nargs=2,
                        default=[])
    parser.add_argument(
        '-ws',
        metavar=("<start_sector>", "<filename>"),
        help='[CMD:Firehose] Write filename at sector <start_sector>',
        nargs=2,
        default=[])
    parser.add_argument(
        '-e',
        metavar="<partitionname>",
        help='[CMD:Firehose] Erase the entire partition specified',
        default='')
    parser.add_argument(
        '-es',
        metavar=("<start_sector>", "<num_sectors>"),
        help=
        '[CMD:Firehose] Erase disk from start sector for number of sectors',
        nargs=2,
        default=[])
    parser.add_argument('-reset',
                        help='[CMD:Firehose] Reset device',
                        action="store_true")
    parser.add_argument('-getstorageinfo',
                        help='[CMD:Firehose] Get Storage/Flash Info',
                        action="store_true")
    parser.add_argument(
        '-setbootablestoragedrive',
        metavar="<number>",
        help=
        '[CMD:Firehose] Set the physical partition number active for booting',
        default='')
    parser.add_argument('-x',
                        metavar="<xmldata>",
                        help='[CMD:Firehose] XML to run in firehose mode',
                        default='')
    parser.add_argument('-gpt-num-part-entries',
                        metavar="<number>",
                        type=int,
                        help='[CMD:Firehose] Number of partitions',
                        default=None)
    parser.add_argument('-gpt-part-entry-size',
                        metavar="<number>",
                        type=int,
                        help='[CMD:Firehose] Size of partition entry',
                        default=None)
    parser.add_argument('-gpt-part-entry-start-lba',
                        metavar="<number>",
                        type=int,
                        help='[CMD:Firehose] Beginning of partition entries',
                        default=None)

    args = parser.parse_args()
    xml = xmlparser()

    mode = ""
    loop = 0
    if args.vid != "":
        vid = int(args.vid, 16)
    if args.pid != "":
        pid = int(args.pid, 16)
    cdc = usb_class(vid=vid, pid=pid)
    sahara = qualcomm_sahara(cdc)

    if args.loader == 'none':
        print("Trying with no loader given ...")
        sahara.programmer = None
    elif (args.loader == ""):
        print("Trying with loaders in Loader directory ...")
        sahara.programmer = None
    elif (args.loader != ''):
        print(f"Using loader {args.loader} ...")
        with open(args.loader, "rb") as rf:
            sahara.programmer = rf.read()
    else:
        print(
            "Sorry, you need a firehose loader (-loader) or try without loader \"-loader none\" !"
        )
        print("Use with -h for displaying help.")
        exit(0)

    print("Waiting for the device")

    while (cdc.connected == False):
        cdc.connected = cdc.connect()
        if cdc.connected == False:
            sys.stdout.write('.')
            if (loop >= 20):
                sys.stdout.write('\n')
                loop = 0
            loop += 1
            time.sleep(1)
            sys.stdout.flush()
        else:
            print("Device detected :)")
            mode = sahara.connect()
            print(f"Mode detected: {mode}")
            break

    if mode == "Sahara":
        m = sahara.info()
        if args.debugmode:
            sahara.debug_mode()
            exit(0)
        elif args.debugread:
            sahara.cmdexec_read_debug_data()
        elif args.dmss:
            sahara.cmdexec_switch_to_dmss_dload()
            exit(0)
        elif args.streaming:
            sahara.cmdexec_switch_to_stream_dload()
            exit(0)
        else:
            if sahara.upload_firehoseloader() == True:
                time.sleep(0.3)
                mode = "Firehose"
                print("Successfully uploaded programmer :)")
    else:
        sahara.bit64 = True

    if mode == "Firehose":
        cfg = qualcomm_firehose.cfg()
        cfg.MemoryName = args.memory
        cfg.ZLPAwareHost = 1
        cfg.SkipStorageInit = args.skipstorageinit
        cfg.SkipWrite = args.skipwrite
        cfg.MaxPayloadSizeToTargetInBytes = args.maxpayload
        cfg.SECTOR_SIZE_IN_BYTES = args.sectorsize
        cfg.bit64 = sahara.bit64
        fh = qualcomm_firehose(cdc, xml, cfg)
        info = fh.connect(0)
        if args.gpt != '':
            fh.cmd_read(args.lun, 0, 0x4000 // cfg.SECTOR_SIZE_IN_BYTES,
                        args.gpt)
            print(f"Dumped GPT to {args.gpt}")
            exit(0)
        elif args.printgpt == True:
            data = fh.cmd_read_buffer(args.lun, 0,
                                      0x4000 // cfg.SECTOR_SIZE_IN_BYTES)
            if data != '':
                guid_gpt = gpt(
                    num_part_entries=args.gpt_num_part_entries,
                    part_entry_size=args.gpt_part_entry_size,
                    part_entry_start_lba=args.gpt_part_entry_start_lba,
                )
                guid_gpt.parse(data, cfg.SECTOR_SIZE_IN_BYTES)
                guid_gpt.print()
            else:
                print("Error on reading GPT, maybe wrong memoryname given ?")
            exit(0)
        elif len(args.r) != 0:
            if len(args.r) != 2:
                print("Usage: -r <partitionname> <filename>")
                exit(0)
            partitionname = args.r[0]
            filename = args.r[1]
            data = fh.cmd_read_buffer(args.lun, 0,
                                      0x4000 // cfg.SECTOR_SIZE_IN_BYTES,
                                      False)
            guid_gpt = gpt(
                num_part_entries=args.gpt_num_part_entries,
                part_entry_size=args.gpt_part_entry_size,
                part_entry_start_lba=args.gpt_part_entry_start_lba,
            )
            guid_gpt.parse(data, cfg.SECTOR_SIZE_IN_BYTES)

            for partition in guid_gpt.partentries:
                if partition.name == partitionname:
                    data = fh.cmd_read(args.lun, partition.sector,
                                       partition.sectors, filename)
                    print(
                        f"Dumped sector {str(partition.sector)} with sector count {str(partition.sectors)} as {filename}."
                    )
                    exit(0)
            print(f"Error: Couldn't detect partition: {partitionname}")
            exit(0)
        elif args.rf != '':
            filename = args.rf
            data = fh.cmd_read_buffer(args.lun, 0,
                                      0x4000 // cfg.SECTOR_SIZE_IN_BYTES,
                                      False)
            guid_gpt = gpt(
                num_part_entries=args.gpt_num_part_entries,
                part_entry_size=args.gpt_part_entry_size,
                part_entry_start_lba=args.gpt_part_entry_start_lba,
            )
            guid_gpt.parse(data, cfg.SECTOR_SIZE_IN_BYTES)
            data = fh.cmd_read(args.lun, 0, guid_gpt.totalsectors, filename)
            print(
                f"Dumped sector 0 with sector count {str(guid_gpt.totalsectors)} as {filename}."
            )
            exit(0)
        elif args.pbl != '':
            filename = args.pbl
            if fh.cfg.TargetName in infotbl:
                v = infotbl[fh.cfg.TargetName]
                if len(v[0]) > 0:
                    if fh.cmd_peek(v[0][0], v[0][1], filename):
                        print(
                            f"Dumped pbl at offset {hex(v[0][0])} as {filename}."
                        )
                        exit(0)
                else:
                    print("No known pbl offset for this chipset")
            else:
                print("Unknown target chipset")
            print("Error on dumping pbl")
            exit(0)
        elif args.qfp != '':
            filename = args.qfp
            if fh.cfg.TargetName in infotbl:
                v = infotbl[fh.cfg.TargetName]
                if len(v[1]) > 0:
                    if fh.cmd_peek(v[1][0], v[1][1], filename):
                        print(
                            f"Dumped qfprom at offset {hex(v[1][0])} as {filename}."
                        )
                        exit(0)
                else:
                    print("No known qfprom offset for this chipset")
            else:
                print("Unknown target chipset")
            print("Error on dumping pbl")
            exit(0)
        elif args.memtbl != '':
            filename = args.memtbl
            if fh.cfg.TargetName in infotbl:
                v = infotbl[fh.cfg.TargetName]
                if len(v[2]) > 0:
                    if fh.cmd_peek(v[2][0], v[2][1], filename):
                        print(
                            f"Dumped qfprom at offset {hex(v[2][0])} as {filename}."
                        )
                        exit(0)
                else:
                    print("No known qfprom offset for this chipset")
            else:
                print("Unknown target chipset")
            print("Error on dumping pbl")
            exit(0)
        elif args.footer != '':
            filename = args.footer
            data = fh.cmd_read_buffer(args.lun, 0,
                                      0x4000 // cfg.SECTOR_SIZE_IN_BYTES,
                                      False)
            guid_gpt = gpt(
                num_part_entries=args.gpt_num_part_entries,
                part_entry_size=args.gpt_part_entry_size,
                part_entry_start_lba=args.gpt_part_entry_start_lba,
            )
            guid_gpt.parse(data, cfg.SECTOR_SIZE_IN_BYTES)
            pnames = [
                "userdata2", "metadata", "userdata", "reserved1", "reserved2",
                "reserved3"
            ]
            for partition in guid_gpt.partentries:
                if partition.name in pnames:
                    print(f"Detected partition: {partition.name}")
                    data = fh.cmd_read_buffer(
                        args.lun, partition.sector +
                        (partition.sectors -
                         (0x4000 // cfg.SECTOR_SIZE_IN_BYTES)),
                        (0x4000 // cfg.SECTOR_SIZE_IN_BYTES), filename)
                    val = struct.unpack("<I", data[:4])[0]
                    if ((val & 0xFFFFFFF0) == 0xD0B5B1C0):
                        with open(filename, "wb") as wf:
                            wf.write(data)
                            print(
                                f"Dumped footer from {partition.name} as {filename}."
                            )
                            exit(0)
            print(f"Error: Couldn't detect partition: {partitionname}")
            exit(0)
        elif len(args.rs) != 0:
            if len(args.rs) != 3:
                print("Usage: -rs <start_sector> <sectors> <filename>")
                exit(0)
            start = int(args.rs[0])
            sectors = int(args.rs[1])
            filename = args.rs[2]
            data = fh.cmd_read(args.lun, start, sectors, filename)
            print(
                f"Dumped sector {str(start)} with sector count {str(sectors)} as {filename}."
            )
            exit(0)
        elif len(args.peek) != 0:
            if len(args.peek) != 3:
                print("Usage: -peek <offset> <length> <filename>")
                exit(0)
            offset = int(args.peek[0], 16)
            length = int(args.peek[1], 16)
            filename = args.peek[2]
            fh.cmd_peek(offset, length, filename)
            exit(0)
        elif args.reset:
            fh.cmd_reset()
            exit(0)
        elif args.setbootablestoragedrive != '':
            fh.cmd_setbootablestoragedrive(int(args.setbootablestoragedrive))
            exit(0)
        elif args.getstorageinfo:
            fh.cmd_getstorageinfo()
            exit(0)
        elif len(args.w) != 0:
            if len(args.w) != 2:
                print("Usage: -w <partitionname> <filename>")
                exit(0)
            partitionname = args.w[0]
            filename = args.w[1]
            if not os.path.exists(filename):
                print(f"Error: Couldn't find file: {filename}")
                exit(0)
            data = fh.cmd_read_buffer(args.lun, 0,
                                      0x4000 // cfg.SECTOR_SIZE_IN_BYTES,
                                      False)
            guid_gpt = gpt(
                num_part_entries=args.gpt_num_part_entries,
                part_entry_size=args.gpt_part_entry_size,
                part_entry_start_lba=args.gpt_part_entry_start_lba,
            )
            guid_gpt.parse(data, cfg.SECTOR_SIZE_IN_BYTES)

            for partition in guid_gpt.partentries:
                if partition.name == partitionname:
                    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:
                        print(
                            f"Error: {filename} has {sectors} sectors but partition only has {partition.sectors}."
                        )
                        exit(0)
                    data = fh.cmd_write(args.lun, partition.sector, filename)
                    print(
                        f"Wrote {filename} to sector {str(partition.sector)}.")
                    exit(0)
            print(f"Error: Couldn't detect partition: {partitionname}")
            exit(0)
        elif len(args.ws) != 0:
            if len(args.ws) != 2:
                print("Usage: -ws <start_sector> <filename>")
                exit(0)
            start = int(args.ws[0])
            filename = args.ws[1]
            if not os.path.exists(filename):
                print(f"Error: Couldn't find file: {filename}")
                exit(0)
            if fh.cmd_write(args.lun, start, filename) == True:
                print(f"Wrote {filename} to sector {str(start)}.")
            else:
                print(f"Error on writing {filename} to sector {str(start)}")
            exit(0)
        elif args.e != '':
            partitionname = args.e
            data = fh.cmd_read_buffer(args.lun, 0,
                                      0x4000 // cfg.SECTOR_SIZE_IN_BYTES,
                                      False)
            guid_gpt = gpt(
                num_part_entries=args.gpt_num_part_entries,
                part_entry_size=args.gpt_part_entry_size,
                part_entry_start_lba=args.gpt_part_entry_start_lba,
            )
            guid_gpt.parse(data, cfg.SECTOR_SIZE_IN_BYTES)

            for partition in guid_gpt.partentries:
                if partition.name == partitionname:
                    fh.cmd_erase(args.lun, partition.sector, partition.sectors)
                    print(
                        f"Erased {partitionname} starting at sector {str(partition.sector)} with sector count {str(partition.sectors)}."
                    )
                    exit(0)
            print(f"Error: Couldn't detect partition: {partitionname}")
            exit(0)
        elif len(args.es) != 0:
            if len(args.es) != 2:
                print("Usage: -ws <start_sector> <sectors>")
                exit(0)
            start = int(args.es[0])
            sectors = int(args.es[1])
            data = fh.cmd_erase(args.lun, start, sectors)
            print(
                f"Erased sector {str(start)} with sector count {str(sectors)}."
            )
            exit(0)
        elif args.x != '':
            data = fh.cmd_xml(args.x)
            exit(0)
        else:
            print("Unknown/Missing command, a command is required.")
            exit(0)
    else:
        print("Sorry, couldn't talk to Sahara, please reboot the device !")
        exit(0)

    exit(0)