Revision 644066961423ffec502046315053b44a601148a2 authored by g3gg0 on 25 October 2013, 21:46:47 UTC, committed by g3gg0 on 25 October 2013, 21:46:47 UTC
1 parent e9dbc02
dump_srec.py
# parses Canon SRec records (stored with tag #0x200) of Canon DSLR updates
# version 0.6 (17Sep2011)
# by Arm.Indy, based on initial work by JollyRoger who identified the format
# See http://en.wikipedia.org/wiki/SREC_%28file_format%29
"""
record format is: type(1byte), len(1byte), address(depending on type), data (0 to 16 bytes), checksum(1 byte)
length is including fields [len, address if present, data]
checksum is computed on same fields as length
record types are:
00, len, 0000, filename, checksum
01, len, address(2bytes), data, checksum
03, len, address(4bytes), data, checksum
07, len, data, checksum
09, len, data, checksum
"""
from struct import unpack
import os
import sys
import array
import ctypes
import string
from optparse import OptionParser
from binascii import hexlify
def getByteLE(d, a):
return unpack('<B',(d)[a:a+1])[0]
def getLongLE(d, a):
return unpack('<L',(d)[a:a+4])[0]
def getShortLE(d, a):
return unpack('<H',(d)[a:a+2])[0]
def getShortBE(d, a):
return unpack('>H',(d)[a:a+2])[0]
def getLongBE(d, a):
return unpack('>L',(d)[a:a+4])[0]
parser = OptionParser(usage="usage: %prog filename")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False, help="verbose mode")
parser.add_option("-x", "--extract", action="store_true", dest="extract", default=False, help="extract files")
parser.add_option("-c", "--convert", action="store_true", dest="convert", default=False, help="convert files to S19")
(options, args) = parser.parse_args()
f = open(args[0], 'rb')
m = f.read()
size = f.tell()
f.close()
# Find blocks
currentAddress = 0
print 'Dump Canon SRec, v0.5'
print
while currentAddress < size:
rtype = getByteLE(m, currentAddress) #S0
if rtype <> 0:
print 'error rtype<>0'
offset = currentAddress+1
rlen = getByteLE(m, currentAddress+1)
#Extract filename
fileNameLen = rlen - 3
if options.verbose:
print "0x%06x: %02x %02x %04x" % ( currentAddress, rtype, rlen, getShortBE(m, currentAddress+2) ),
currentAddress += 4
# fileName = m[ currentAddress: currentAddress+fileNameLen ]
i = currentAddress
while m[ i: i+1 ] in string.printable and i<(currentAddress+fileNameLen):
i+=1
fileName = m[ currentAddress: i ]
print '%s' % fileName,
fileLen = 0
csum = sum( array.array('B', m[ currentAddress-3: currentAddress+fileNameLen ]) )
if options.verbose:
print '%02x' % ( ctypes.c_uint32(~csum).value & 0xff ),
currentAddress += fileNameLen
rsum = getByteLE(m, currentAddress)
if options.verbose:
print '%02x' % ( rsum )
currentAddress += 1
if options.convert: #prepare S0 record in S19 record
dataS0 = hexlify(m[offset:offset+rlen+1])
endBlockFound = False
fileOpen = False
fileConvertOpen = False
startAddr = -1
while not endBlockFound:
offset = currentAddress
rtype = getByteLE(m, currentAddress)
rlen = getByteLE(m, currentAddress+1)
currentAddress += 2
if rtype == 3: #like S3
addrLen = 4
addr = getLongBE(m, currentAddress)
dataLen = rlen-addrLen-1
elif rtype == 1: #like S1
addrLen = 2
addr = getShortBE(m, currentAddress)
dataLen = rlen-addrLen-1
elif rtype == 7 or rtype == 9: #like S7 and S9
addrLen = 0
dataLen = rlen-1
endBlockFound = True
endAddr = addr
else:
print 'unsupported record type = %x' % rtype
if startAddr <0:
startAddr = addr
if options.extract and not fileOpen:
fileName = fileName+'_'+'{0:08x}'.format(addr)+'.bin'
f = open(fileName, 'wb')
fileOpen = True
if options.convert: #write S0 record in S19 record
if not fileConvertOpen:
fc = open(fileName+'_'+'{0:08x}'.format(addr)+'.s19', 'w')
fileConvertOpen = True
fc.write('S0'+dataS0+'\n')
fc.write('S'+'{0:1}'.format(rtype)+hexlify(m[offset+1:offset+rlen+2])+'\n')
currentAddress += addrLen
if addrLen == 4:
if options.verbose:
print "0x%06x: %02x %02x %08x" % ( offset, rtype, rlen, addr ),
elif addrLen == 2:
if options.verbose:
print "0x%06x: %02x %02x %04x" % ( offset, rtype, rlen, addr ),
else:
if options.verbose:
print "0x%06x: %02x %02x %s" % ( offset, rtype, rlen, addrLen*" " ),
data = m[currentAddress: currentAddress+dataLen]
dataAscii = ''
for c in data:
if c in string.printable:
dataAscii.join(c)
else:
dataAscii.join('.')
if options.extract:
f.write( data )
fileLen += dataLen
if options.verbose:
print "= %-32s %-32s" % ( hexlify( data ), dataAscii ),
csum = sum( array.array('B', m[ offset+1: currentAddress+dataLen ]) )
csum = ctypes.c_uint32(~csum).value & 0xff
if options.verbose:
print '%02x' % csum,
currentAddress += dataLen
rsum = getByteLE(m, currentAddress)
if options.verbose:
if rsum == csum:
print 'OK'
else:
print 'KO'
currentAddress += 1
if options.convert: #write S0 record in S19 record
fc.close()
if options.extract:
f.close()
print "%d bytes saved, " % fileLen,
else:
print "%d bytes, " % fileLen,
print "0x%x-0x%x" % (startAddr, endAddr)
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...