Fixed writing. Yay.

This commit is contained in:
Bjoern Kerler 2021-01-20 17:24:54 +01:00
parent 63e7aa3394
commit 65c3ad9277
3 changed files with 451 additions and 358 deletions

File diff suppressed because it is too large Load diff

View file

@ -613,7 +613,7 @@ class firehose_client(metaclass=LogBase):
for filename in filenames:
for partition in guid_gpt.partentries:
partname = filename[filename.rfind("/") + 1:]
if ".bin" in partname[-4:]:
if ".bin" in partname[-4:] or ".img" in partname[-4:] or ".mbn" in partname[-4:]:
partname = partname[:-4]
if partition.name == partname:
if partition.name in skip:

View file

@ -2,6 +2,8 @@
import sys
from struct import unpack
from queue import Queue
import logging
try:
from Library.utils import LogBase, print_progress
except Exception as e:
@ -13,11 +15,16 @@ except Exception as e:
class QCSparse(metaclass=LogBase):
def __init__(self,filename):
def __init__(self,filename,loglevel):
self.rf=open(filename,'rb')
self.data=Queue()
self.offset=0
self.tmpdata=bytearray()
self.__logger.setLevel(loglevel)
if loglevel == logging.DEBUG:
logfilename = "log.txt"
fh = logging.FileHandler(logfilename)
self.__logger.addHandler(fh)
def readheader(self):
header = unpack("<I4H4I", self.rf.read(0x1C))
@ -38,8 +45,44 @@ class QCSparse(metaclass=LogBase):
if self.chunk_hdr_sz != 12:
self.__logger.error("The chunk header size was expected to be 12, but is %u." % self.chunk_hdr_sz)
return False
self.__logger.info("Sparse Format detected. Using unpacked image.")
return True
def get_chunk_size(self):
if self.total_blks < self.offset:
self.__logger.error("The header said we should have %u output blocks, but we saw %u" % (self.total_blks, self.offset))
return -1
header = unpack("<2H2I", self.rf.read(self.chunk_hdr_sz))
chunk_type = header[0]
chunk_sz = header[2]
total_sz = header[3]
data_sz = total_sz - 12
if chunk_type == 0xCAC1:
if data_sz != (chunk_sz * self.blk_sz):
self.__logger.error("Raw chunk input size (%u) does not match output size (%u)" % (data_sz, chunk_sz * self.blk_sz))
return -1
else:
self.rf.seek(self.rf.tell()+chunk_sz * self.blk_sz)
return chunk_sz * self.blk_sz
elif chunk_type == 0xCAC2:
if data_sz != 4:
self.__logger.error("Fill chunk should have 4 bytes of fill, but this has %u" % data_sz)
return -1
else:
return (chunk_sz * self.blk_sz // 4)
elif chunk_type == 0xCAC3:
return chunk_sz * self.blk_sz
elif chunk_type == 0xCAC4:
if data_sz != 4:
self.__logger.error("CRC32 chunk should have 4 bytes of CRC, but this has %u" % data_sz)
return -1
else:
self.rf.seek(self.rf.tell() + 4)
return 0
else:
self.__logger.debug("Unknown chunk type 0x%04X" % chunk_type)
return -1
def unsparse(self):
if self.total_blks < self.offset:
self.__logger.error("The header said we should have %u output blocks, but we saw %u" % (self.total_blks, self.offset))
@ -86,6 +129,19 @@ class QCSparse(metaclass=LogBase):
self.__logger.debug("Unknown chunk type 0x%04X" % chunk_type)
return -1
def getsize(self):
self.rf.seek(0x1C)
length=0
chunk=0
while chunk<self.total_chunks:
tlen=self.get_chunk_size()
if tlen==-1:
break
length+=tlen
chunk+=1
self.rf.seek(0x1C)
return length
def read(self,length=None):
if length==None:
return self.unsparse()
@ -104,10 +160,11 @@ if __name__=="__main__":
if len(sys.argv)<3:
print("./sparse.py <sparse_partition.img> <outfile>")
sys.exit()
sp=QCSparse(sys.argv[1])
sp=QCSparse(sys.argv[1],logging.INFO)
if sp.readheader():
print("Extracting sectors to "+sys.argv[2])
with open(sys.argv[2],"wb") as wf:
"""
old=0
while sp.offset<sp.total_blks:
prog=int(sp.offset / sp.total_blks * 100)
@ -122,4 +179,37 @@ if __name__=="__main__":
wf.write(sp.tmpdata)
sp.tmpdata=bytearray()
print_progress(100, 100, prefix='Progress:', suffix='Complete', bar_length=50)
"""
fsize=sp.getsize()
SECTOR_SIZE_IN_BYTES=4096
num_partition_sectors=5469709
MaxPayloadSizeToTargetInBytes=0x200000
bytesToWrite = SECTOR_SIZE_IN_BYTES * num_partition_sectors
total = SECTOR_SIZE_IN_BYTES * num_partition_sectors
old = 0
pos=0
while fsize > 0:
wlen = MaxPayloadSizeToTargetInBytes // SECTOR_SIZE_IN_BYTES * SECTOR_SIZE_IN_BYTES
if fsize < wlen:
wlen = fsize
wdata = sp.read(wlen)
bytesToWrite -= wlen
fsize -= wlen
pos += wlen
pv=wlen % SECTOR_SIZE_IN_BYTES
if pv != 0:
filllen = (wlen // SECTOR_SIZE_IN_BYTES * SECTOR_SIZE_IN_BYTES) + \
SECTOR_SIZE_IN_BYTES
wdata += b"\x00" * (filllen - wlen)
wlen = len(wdata)
wf.write(wdata)
prog = int(float(pos) / float(total) * float(100))
if prog > old:
print_progress(prog, 100, prefix='Progress:', suffix='Complete (Sector %d)'
% (pos // SECTOR_SIZE_IN_BYTES),
bar_length=50)
print("Done.")