Skip to content

Commit a3b53c9

Browse files
author
Bjoern Kerler
committed
Add sparse, improve logging.
1 parent 2908728 commit a3b53c9

File tree

9 files changed

+208
-273
lines changed

9 files changed

+208
-273
lines changed

Config/qualcomm_config.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ class memory_type:
408408
nand = 0
409409
emmc = 1
410410
ufs = 2
411+
spinor = 3
411412

412413
preferred_memory = {
413414
"QDF2432": emmc,
@@ -473,12 +474,12 @@ class memory_type:
473474
"MDM9250": emmc,
474475
"MDM9350": emmc,
475476
"MDM9650": emmc,
476-
"SDM429": ufs,
477-
"SDM439": ufs,
478-
"SDM450": ufs,
479-
"SDM632": ufs,
480-
"SDA632": ufs,
481-
"SDX50M": ufs,
477+
"SDM429": emmc,
478+
"SDM439": emmc,
479+
"SDM450": emmc,
480+
"SDM632": emmc,
481+
"SDA632": emmc,
482+
"SDX50M": emmc,
482483
"qcs403": emmc,
483484
"qcs405": emmc,
484485
"ipq5018": emmc,
@@ -489,29 +490,29 @@ class memory_type:
489490
"MSM8930": emmc,
490491
"MSM8936": emmc,
491492

492-
"APQ8098": ufs,
493+
"APQ8098": emmc,
493494
"MSM8998": ufs,
494-
"SDM630": ufs,
495-
"SDM636": ufs,
496-
"SDM660": ufs,
497-
"SDM670": ufs,
498-
"SDA670": ufs,
499-
"SDM710": ufs,
500-
"QCS605": ufs,
495+
"SDM630": emmc,
496+
"SDM636": emmc,
497+
"SDM660": emmc,
498+
"SDM670": emmc,
499+
"SDA670": emmc,
500+
"SDM710": emmc,
501+
"QCS605": emmc,
501502
"SXR1120": emmc,
502503
"SXR1130": emmc,
503504
"SDM845": ufs,
504505
"SDM850": ufs,
505506
"SDX24": emmc,
506507
"SDX24M": emmc,
507-
"SDX55M": emmc,
508-
"SDX55:CD90-PG591": emmc,
509-
"SDX55:CD90-PH809": emmc,
510-
"SA515M": ufs,
511-
"SM6150": ufs,
512-
"SM6150p": ufs,
513-
"SM7150": ufs,
514-
"SM7150p": ufs,
508+
"SDX55M": ufs,
509+
"SDX55:CD90-PG591": ufs,
510+
"SDX55:CD90-PH809": ufs,
511+
"SA515M": emmc,
512+
"SM6150": emmc,
513+
"SM6150p": emmc,
514+
"SM7150": emmc,
515+
"SM7150p": emmc,
515516
"SDM855_SM8150": ufs,
516517
"SDM855p_SM8150p": ufs,
517518
"SM8250": ufs,

Library/firehose.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import time
44
from Library.utils import *
55
from Library.gpt import gpt
6-
6+
from Library.sparse import QCSparse
77

88
try:
99
from Library.Modules.init import modules
@@ -54,7 +54,7 @@ class cfg:
5454
MaxXMLSizeInBytes = 4096
5555
bit64 = True
5656

57-
def __init__(self, cdc, xml, cfg, log, devicemodel, serial, skipresponse, luns, args):
57+
def __init__(self, cdc, xml, cfg, loglevel, devicemodel, serial, skipresponse, luns, args):
5858
self.cdc = cdc
5959
self.lasterror = b""
6060
self.args = args
@@ -67,8 +67,14 @@ def __init__(self, cdc, xml, cfg, log, devicemodel, serial, skipresponse, luns,
6767
self.skipresponse = skipresponse
6868
self.luns = luns
6969
self.supported_functions = []
70-
if self.cfg.MemoryName == "UFS":
70+
if self.cfg.MemoryName == "UFS" or self.cfg.MemoryName == "spinor":
7171
self.cfg.SECTOR_SIZE_IN_BYTES = 4096
72+
self.__logger.setLevel(loglevel)
73+
if loglevel==logging.DEBUG:
74+
logfilename = "log.txt"
75+
fh = logging.FileHandler(logfilename)
76+
self.__logger.addHandler(fh)
77+
7278

7379
def detect_partition(self, arguments, partitionname):
7480
fpartitions = {}
@@ -275,7 +281,10 @@ def cmd_patch(self, physical_partition_number, start_sector, byte_offset, value,
275281
def cmd_program(self, physical_partition_number, start_sector, filename, display=True):
276282
size = os.stat(filename).st_size
277283
fsize = os.stat(filename).st_size
278-
fname = os.path.basename(filename)
284+
sparse = QCSparse(filename)
285+
sparseformat = False
286+
if sparse.readheader():
287+
sparseformat = True
279288
with open(filename, "rb") as rf:
280289
# Make sure we fill data up to the sector size
281290
num_partition_sectors = size // self.cfg.SECTOR_SIZE_IN_BYTES
@@ -293,7 +302,6 @@ def cmd_program(self, physical_partition_number, start_sector, filename, display
293302
old = 0
294303
if num_partition_sectors<maxsectors:
295304
maxsectors=num_partition_sectors
296-
297305
for cursector in range(start_sector, start_sector + num_partition_sectors, maxsectors):
298306
data = f"<?xml version=\"1.0\" ?><data>\n" + \
299307
f"<program SECTOR_SIZE_IN_BYTES=\"{self.cfg.SECTOR_SIZE_IN_BYTES}\"" + \
@@ -313,7 +321,10 @@ def cmd_program(self, physical_partition_number, start_sector, filename, display
313321
wlen = self.cfg.MaxPayloadSizeToTargetInBytes
314322
if fsize < wlen:
315323
wlen = fsize
316-
wdata = rf.read(wlen)
324+
if sparseformat:
325+
wdata=sparse.read(wlen)
326+
else:
327+
wdata = rf.read(wlen)
317328
wlen=len(wdata)
318329
bytesToWrite -= wlen
319330
fsize -= wlen
@@ -740,15 +751,15 @@ def configure(self,lvl):
740751
self.__logger.info(f"TargetName={self.cfg.TargetName}")
741752
self.__logger.info(f"MemoryName={self.cfg.MemoryName}")
742753
self.__logger.info(f"Version={self.cfg.Version}")
743-
if self.cfg.MemoryName.lower() == "emmc":
754+
if self.cfg.MemoryName.lower() == "emmc" or self.cfg.MemoryName.lower()=="nand":
744755
self.cfg.SECTOR_SIZE_IN_BYTES = 512
745-
elif self.cfg.MemoryName.lower() == "ufs":
756+
elif self.cfg.MemoryName.lower() == "ufs" or self.cfg.MemoryName.lower() == "spinor":
746757
self.cfg.SECTOR_SIZE_IN_BYTES = 4096
747758

748759
rsp=self.cmd_read_buffer(0,1,1,False)
749760
if rsp==-1:
750761
if b"ERROR: Failed to initialize (open whole lun) UFS Device slot" in self.lasterror:
751-
self.__logger.warning("Memory type UFS doesn't seem to match (Failed to init). Use eMMC instead.")
762+
self.__logger.warning("Memory type UFS doesn't seem to match (Failed to init). Trying to use eMMC instead.")
752763
self.cfg.MemoryName="eMMC"
753764
return self.configure(0)
754765

Library/firehose_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ def __init__(self, arguments, cdc, sahara, loglevel, printer):
6565
type=memory_type.preferred_memory[self.target_name]
6666
if type==memory_type.nand:
6767
self.cfg.MemoryName = "nand"
68+
if type==memory_type.spinor:
69+
self.cfg.MemoryName = "spinor"
6870
elif type==memory_type.emmc:
6971
self.cfg.MemoryName = "eMMC"
7072
elif type==memory_type.ufs:

Library/gpt.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#!/usr/bin/env python3
12
import binascii
23
from Library.utils import *
34

@@ -237,3 +238,23 @@ def generate_rawprogram(self, lun, sectorsize, directory):
237238
mstr += "</data>"
238239
wf.write(bytes(mstr, 'utf-8'))
239240
print(f"Wrote partition xml as {fname}")
241+
242+
def print_gptfile(self,filename):
243+
with open(filename, "rb") as rf:
244+
sectorsize = 4096
245+
result=self.parse(rf.read(), sectorsize)
246+
if result:
247+
print(self.tostring())
248+
return result
249+
return False
250+
251+
def test_gpt(self):
252+
res=self.print_gptfile(os.path.join("TestFiles", "gpt_sm8180x.bin"))
253+
assert res,"GPT Partition wasn't decoded properly"
254+
255+
if __name__=="__main__":
256+
if len(sys.argv)<2:
257+
print("Usage: ./gpt.py <filename>")
258+
sys.exit()
259+
gp = gpt()
260+
gp.print_gptfile(sys.argv[1])

Library/sahara.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import time
33
import os
44
import sys
5+
import logging
56
from struct import unpack, pack
67
from Library.utils import read_object, print_progress, rmrf, LogBase
78
from Config.qualcomm_config import sochw, msmids, root_cert_hash
@@ -273,7 +274,7 @@ def get_error_desc(self, status):
273274
('filename', '20s')
274275
]
275276

276-
def __init__(self, cdc):
277+
def __init__(self, cdc, loglevel):
277278
self.cdc = cdc
278279
self.init_loader_db()
279280
self.version=2.1
@@ -291,6 +292,12 @@ def __init__(self, cdc):
291292
self.model_id = None
292293
self.oem_str = None
293294
self.msm_str = None
295+
self.__logger.setLevel(loglevel)
296+
if loglevel==logging.DEBUG:
297+
logfilename = "log.txt"
298+
fh = logging.FileHandler(logfilename)
299+
self.__logger.addHandler(fh)
300+
294301

295302
def get_rsp(self):
296303
data = []
@@ -454,8 +461,8 @@ def info(self):
454461
self.serials = "{:08x}".format(self.serial)
455462
self.hwid = self.cmdexec_get_msm_hwid()
456463
self.pkhash = self.cmdexec_get_pkhash()
457-
if self.version>=2.4:
458-
self.sblversion = "{:08x}".format(self.cmdexec_get_sbl_version())
464+
#if self.version>=2.4:
465+
# self.sblversion = "{:08x}".format(self.cmdexec_get_sbl_version())
459466
if self.hwid is not None:
460467
self.hwidstr = "{:016x}".format(self.hwid)
461468
self.msm_id = int(self.hwidstr[2:8], 16)
@@ -464,6 +471,7 @@ def info(self):
464471
self.oem_str = "{:04x}".format(self.oem_id)
465472
self.model_id = "{:04x}".format(self.model_id)
466473
self.msm_str = "{:08x}".format(self.msm_id)
474+
"""
467475
if self.version >= 2.4:
468476
self.__logger.info(f"\n------------------------\n" +
469477
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
@@ -473,7 +481,8 @@ def info(self):
473481
f"Serial: 0x{self.serials}\n" +
474482
f"SBL Version: 0x{self.sblversion}\n")
475483
else:
476-
self.__logger.info(f"\n------------------------\n" +
484+
"""
485+
self.__logger.info(f"\n------------------------\n" +
477486
f"HWID: 0x{self.hwidstr} (MSM_ID:0x{self.msm_str}," +
478487
f"OEM_ID:0x{self.oem_str}," +
479488
f"MODEL_ID:0x{self.model_id})\n" +
@@ -702,7 +711,7 @@ def upload_loader(self):
702711
if self.programmer == "":
703712
return ""
704713
try:
705-
self.__logger.info(f"Using loader {self.programmer} ...")
714+
self.__logger.info(f"Uploading loader {self.programmer} ...")
706715
with open(self.programmer, "rb") as rf:
707716
programmer = rf.read()
708717
except Exception as e:

Library/sparse.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/usr/bin/env python3
2+
import sys
3+
from struct import unpack
4+
from queue import Queue
5+
try:
6+
from Library.utils import LogBase, print_progress
7+
except Exception as e:
8+
import os,sys,inspect
9+
current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
10+
parent_dir = os.path.dirname(current_dir)
11+
sys.path.insert(0, parent_dir)
12+
from Library.utils import LogBase, print_progress
13+
14+
15+
class QCSparse(metaclass=LogBase):
16+
def __init__(self,filename):
17+
self.rf=open(filename,'rb')
18+
self.data=Queue()
19+
self.offset=0
20+
self.tmpdata=bytearray()
21+
22+
def readheader(self):
23+
header = unpack("<I4H4I", self.rf.read(0x1C))
24+
magic = header[0]
25+
self.major_version = header[1]
26+
self.minor_version = header[2]
27+
self.file_hdr_sz = header[3]
28+
self.chunk_hdr_sz = header[4]
29+
self.blk_sz = header[5]
30+
self.total_blks = header[6]
31+
self.total_chunks = header[7]
32+
self.image_checksum = header[8]
33+
if magic!=0xED26FF3A:
34+
return False
35+
if self.file_hdr_sz != 28:
36+
self.__logger.error("The file header size was expected to be 28, but is %u." % self.file_hdr_sz)
37+
return False
38+
if self.chunk_hdr_sz != 12:
39+
self.__logger.error("The chunk header size was expected to be 12, but is %u." % self.chunk_hdr_sz)
40+
return False
41+
return True
42+
43+
def unsparse(self):
44+
if self.total_blks < self.offset:
45+
self.__logger.error("The header said we should have %u output blocks, but we saw %u" % (self.total_blks, self.offset))
46+
return -1
47+
header = unpack("<2H2I", self.rf.read(self.chunk_hdr_sz))
48+
chunk_type = header[0]
49+
chunk_sz = header[2]
50+
total_sz = header[3]
51+
data_sz = total_sz - 12
52+
if chunk_type == 0xCAC1:
53+
if data_sz != (chunk_sz * self.blk_sz):
54+
self.__logger.error("Raw chunk input size (%u) does not match output size (%u)" % (data_sz, chunk_sz * self.blk_sz))
55+
return -1
56+
else:
57+
self.__logger.debug("Raw data")
58+
data = self.rf.read(chunk_sz * self.blk_sz)
59+
self.offset += chunk_sz
60+
return data
61+
elif chunk_type == 0xCAC2:
62+
if data_sz != 4:
63+
self.__logger.error("Fill chunk should have 4 bytes of fill, but this has %u" % data_sz)
64+
return -1
65+
else:
66+
fill_bin = self.rf.read(4)
67+
fill = unpack("<I", fill_bin)
68+
self.__logger.debug(format("Fill with 0x%08X" % fill))
69+
data = fill_bin * (chunk_sz * self.blk_sz // 4)
70+
self.offset += chunk_sz
71+
return data
72+
elif chunk_type == 0xCAC3:
73+
data=b'\x00' * chunk_sz * self.blk_sz
74+
self.offset += chunk_sz
75+
return data
76+
elif chunk_type == 0xCAC4:
77+
if data_sz != 4:
78+
self.__logger.error("CRC32 chunk should have 4 bytes of CRC, but this has %u" % data_sz)
79+
return -1
80+
else:
81+
crc_bin = self.rf.read(4)
82+
crc = unpack("<I", crc_bin)
83+
self.__logger.debug(format("Unverified CRC32 0x%08X" % crc))
84+
return b""
85+
else:
86+
self.__logger.debug("Unknown chunk type 0x%04X" % chunk_type)
87+
return -1
88+
89+
def read(self,length=None):
90+
if length==None:
91+
return self.unsparse()
92+
if length<=len(self.tmpdata):
93+
tdata=self.tmpdata[:length]
94+
self.tmpdata=self.tmpdata[length:]
95+
return tdata
96+
while len(self.tmpdata)<length:
97+
self.tmpdata.extend(self.unsparse())
98+
if length<=len(self.tmpdata):
99+
tdata = self.tmpdata[:length]
100+
self.tmpdata = self.tmpdata[length:]
101+
return tdata
102+
103+
if __name__=="__main__":
104+
if len(sys.argv)<3:
105+
print("./sparse.py <sparse_partition.img> <outfile>")
106+
sys.exit()
107+
sp=QCSparse(sys.argv[1])
108+
if sp.readheader():
109+
print("Extracting sectors to "+sys.argv[2])
110+
with open(sys.argv[2],"wb") as wf:
111+
old=0
112+
while sp.offset<sp.total_blks:
113+
prog=int(sp.offset / sp.total_blks * 100)
114+
if prog>old:
115+
print_progress(prog, 100, prefix='Progress:', suffix='Complete', bar_length=50)
116+
old=prog
117+
data=sp.read()
118+
if data==b"" or data==-1:
119+
break
120+
wf.write(data)
121+
if len(sp.tmpdata)>0:
122+
wf.write(sp.tmpdata)
123+
sp.tmpdata=bytearray()
124+
print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50)
125+
print("Done.")

Library/usblib.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ def __init__(self, loglevel=logging.INFO, portconfig=None, devclass=-1):
5858
self.__logger.addHandler(fh)
5959

6060
def verify_data(self, data, pre="RX:"):
61+
self.__logger.debug("",stack_info=True)
6162
if isinstance(data, bytes) or isinstance(data, bytearray):
6263
if data[:5] == b"<?xml":
6364
try:

0 commit comments

Comments
 (0)