Implemented SC6531C readback and target system

This commit is contained in:
Luxferre
2021-12-21 16:15:47 +02:00
parent 23817f3b09
commit 2215104d81
3 changed files with 91 additions and 20 deletions
+64 -16
View File
@@ -82,6 +82,8 @@ def send_file_to_addr(fname, faddr, fdlBooted = False, flashMode = False, fbs =
resp = reqresp(unicmd.cmd_data_start(faddr, flen, dataCrc), fdlBooted)
rcode, rlen, r = unicmd.resp_decode(resp, fdlBooted)
assert rcode == unicmd.BSL_REP_ACK, 'Could not start data transfer, response code is %X' % rcode
if rcode == unicmd.BSL_REP_LOG:
print(r)
print('Starting data transfer...')
while fdata:
buf = fdata[:pSize]
@@ -148,30 +150,33 @@ def write_flash_mem(infile, offset, blocksize, forceErase):
erase_flash_mem(flen, startAddr)
send_file_to_addr(fdata, startAddr, True, True, blocksize)
# main code start
def auto_int(x):
return int(x,0)
# main code start
if __name__ == '__main__': # main app start
from argparse import ArgumentParser
rootdir = os.path.dirname(os.path.realpath(__file__))
parser = ArgumentParser(description='UniFlash: an opensource Unisoc SC6531E/F/M phone flash reader/writer', epilog='(c) Luxferre 2021 --- No rights reserved <https://unlicense.org>')
parser = ArgumentParser(description='UniFlash: an opensource Unisoc/Spreadtrum feature phone flash reader/writer', epilog='(c) Luxferre 2021 --- No rights reserved <https://unlicense.org>')
parser.add_argument('mode', help='Operation mode (flash/dump)')
parser.add_argument('file', help='File to read the flash data from or write the dump into')
parser.add_argument('-p','--partid', type=auto_int, default=0x80000003, help='partition ID for readback (defaults to 0x80000003 that can address full flash space on SC6531E/F/M)')
parser.add_argument('-s','--start', type=auto_int, default=0, help='start position (in the partition, defaults to 0)')
parser.add_argument('-l', '--length', type=auto_int, default=0x400000, help='data length in bytes to read/write, defaults to 0x400000')
parser.add_argument('-e','--force-erase', type=bool, default=False, help='Erase target flash memory area before writing')
parser.add_argument('-t','--target', default='sc6531efm_generic', help='Preinstalled target (defaults to sc6531efm_generic, overridable with individual FDL parameters)')
parser.add_argument('-nr','--flash-noremap', action='store_true', help='Disable base address remapping for flashing')
parser.add_argument('-e','--force-erase', action='store_true', help='Erase target flash memory area before flashing')
parser.add_argument('-wf','--enable-write-flash', action='store_true', help='Send the write flash enable command before flashing (if necessary and supported)')
parser.add_argument('-bs','--block-size', type=auto_int, default=4096, help='Readback/write block size (in bytes), defaults to 4096')
parser.add_argument('-dv','--device-vid', type=auto_int, default=UNISOC_VID, help='Override device vendor ID')
parser.add_argument('-dp','--device-pid', type=auto_int, default=UNISOC_PID, help='Override device product ID')
parser.add_argument('-fdl1','--fdl1-file', default=rootdir+'/fdls/sc6531efm_generic_0x40004000_fdl1.bin', help='Path to FDL1, defaults to the generic SC6531E/F/M FDL1 shipped with UniFlash')
parser.add_argument('-addr1','--fdl1-addr', type=auto_int, default=0x40004000, help='Address to load FDL1 into, defaults to 0x40004000')
parser.add_argument('-fdl2','--fdl2-file', default=rootdir+'/fdls/sc6531efm_generic_0x14000000_fdl2.bin', help='Path to FDL2, defaults to the generic SC6531E/F/M FDL2 shipped with UniFlash')
parser.add_argument('-addr2','--fdl2-addr', type=auto_int, default=0x14000000, help='Address to load FDL2 into, defaults to 0x14000000')
parser.add_argument('-sfdl','--single-fdl-file', default=None, help='Path to a single FDL (for old Spreadtrum chipsets)')
parser.add_argument('-saddr','--single-fdl-addr', type=auto_int, default=0x34000000, help='Address to load the single FDL into, defaults to 0x34000000')
parser.add_argument('-fdl1','--fdl1-file', default=None, help='Path to FDL1, overrides the target')
parser.add_argument('-addr1','--fdl1-addr', type=auto_int, default=None, help='Address to load FDL1 into, overrides the target')
parser.add_argument('-fdl2','--fdl2-file', default=None, help='Path to FDL2, overrides the target')
parser.add_argument('-addr2','--fdl2-addr', type=auto_int, default=None, help='Address to load FDL2 into, overrides the target')
parser.add_argument('-sfdl','--single-fdl-file', default=None, help='Path to a single FDL (for old Spreadtrum chipsets), overrides the target')
parser.add_argument('-saddr','--single-fdl-addr', type=auto_int, default=None, help='Address to load the single FDL into, overrides the target')
args = parser.parse_args()
@@ -179,24 +184,61 @@ if __name__ == '__main__': # main app start
if args.mode == 'flash':
is_flash = True
# parse target and resolve the parameters from it first
paramdelim = '_'
target = args.target + paramdelim
fdlDir = rootdir + '/fdls'
fdlList = []
for root, dirs, files in os.walk(fdlDir):
for name in files:
if name.startswith(target):
paramstr = os.path.splitext(name)[0].split(target)[1]
params = paramstr.split(paramdelim)
fdlList.append((params[1], params[0], fdlDir+'/'+name))
# resulting fdl list: (tag, address, path)
fdlSingleName = None
fdlSingleAddr = None
for tag, addr, path in fdlList:
if tag == 'single':
fdlSingleName = path
fdlSingleAddr = auto_int(addr)
elif tag == 'fdl1':
fdl1Name = path
fdl1Addr = auto_int(addr)
elif tag == 'fdl2':
fdl2Name = path
fdl2Addr = auto_int(addr)
# override target with the individual parameters if necessary
UNISOC_VID = args.device_vid
UNISOC_PID = args.device_pid
fdl1Addr = args.fdl1_addr
fdl2Addr = args.fdl2_addr
fdl1Name = args.fdl1_file
fdl2Name = args.fdl2_file
fdlSingleName = args.single_fdl_file
fdlSingleAddr = args.single_fdl_addr
if args.fdl1_addr is not None:
fdl1Addr = args.fdl1_addr
if args.fdl2_addr is not None:
fdl2Addr = args.fdl2_addr
if args.fdl1_file is not None:
fdl1Name = args.fdl1_file
if args.fdl2_file is not None:
fdl2Name = args.fdl2_file
if args.single_fdl_file is not None:
fdlSingleName = args.single_fdl_file
if args.single_fdl_addr is not None:
fdlSingleAddr = args.single_fdl_addr
outfile = args.file
partitionId = args.partid
readbs = args.block_size
readoffset = args.start
readlen = args.length
forceErase = args.force_erase
sendEnableWriteFlash = args.enable_write_flash
singleFdlMode = False
fdl1Label = 'FDL1'
fdl2Label = 'FDL2'
if args.flash_noremap == True:
print('Flash remapping disabled')
UNISOC_FLASH_BASE_ADDR = 0
if fdlSingleName is not None:
singleFdlMode = True
fdl1Addr = fdlSingleAddr
@@ -250,6 +292,12 @@ if __name__ == '__main__': # main app start
print(fdl2Label + ' running, may start interacting with flash memory')
if is_flash:
if sendEnableWriteFlash:
resp = reqresp(unicmd.cmd_enable_write_flash(), True)
rcode, rlen, r = unicmd.resp_decode(resp, True)
assert rcode == unicmd.BSL_REP_ACK, 'Could not send the flash write request, response code is %X' % rcode
print('Writing flash at offset 0x%X from %s...' % (readoffset, outfile))
write_flash_mem(outfile, readoffset, readbs, forceErase)
print('Flash memory written, disconnect the device!')