Skip to content

Instantly share code, notes, and snippets.

@kyujin-cho
Created February 9, 2018 08:51
Show Gist options
  • Save kyujin-cho/e1cd6ef3ab16648973e21d7e4f3330cb to your computer and use it in GitHub Desktop.
Save kyujin-cho/e1cd6ef3ab16648973e21d7e4f3330cb to your computer and use it in GitHub Desktop.
ipTIME-device uImage firmware Header Rewrite Script
#!/usr/local/bin/python
#######################################################
# ipTIME uImage Firmware Header Rewriter
#######################################################
import os, zlib
import binascii
import sys
from struct import *
HEADER_FORMAT = '!7L4B32s' ### (Big-endian, 7 ULONGS, 4 UCHARs, 32-byte string)
HEADER_SIZE=calcsize(HEADER_FORMAT) ### Should be 64-bytes
name = 'a1004ns'
name_size = 32
################################################################################
###
### parseHeader(fh, offset=0) - Parse uImage header located at offset in file
###
### Parameters: fh: file handle
### offset: Optional location of header within file
###
### Returns: Dictionary of header information
###
def parseHeader(fh, offset=0):
### Save current position and seek to start position
startpos = fh.tell()
fh.seek(offset)
try:
block = fh.read(HEADER_SIZE)
except IOError:
print("File read error")
exit(1)
### Names of fields in the image header
keys = ['magic', 'headerCrc', 'time', 'size', 'loadAddr', 'entryAddr',
'dataCrc', 'osType', 'arch', 'imageType', 'compression', 'name']
### Unpack the header into a dictionary of (key,value) pairs
values = unpack(HEADER_FORMAT, block)
hd = dict(zip(keys, values))
### if Multi-file image, append file information
if hd['imageType'] == 4:
hd['files'] = getMultiFileLengths(fh, fh.tell())
### Restore saved file position
fh.seek(startpos)
return hd
def calculateHeaderCrc(hd):
### Re-pack the list into a binary string
### Must calclate header CRC with CRC field set to 0.
header = pack(HEADER_FORMAT, hd['magic'], 0, hd['time'], hd['size'],\
hd['loadAddr'], hd['entryAddr'], hd['dataCrc'], hd['osType'], \
hd['arch'], hd['imageType'], hd['compression'], hd['name'])
return zlib.crc32(header)
filename = sys.argv[1]
modelname = sys.argv[2]
size = -1
data = None
try:
size = os.path.getsize(filename)
except IOError:
print("inavlid filename:", filename)
exit(1)
if size < HEADER_SIZE:
print("File too small! Not a uImage file.")
exit(1)
f = open(filename, "rb")
header = parseHeader(f)
header['name'] = str.encode(modelname)
header_crc = (calculateHeaderCrc(header) & 0xffffffff)
print(hex(header['headerCrc']), 'to', hex(header_crc))
print('Rewriting header...')
header_crc = header_crc.to_bytes(4, byteorder='big')
modelname_bytes = str.encode(modelname + ('\0'*(32-len(modelname))))
f.close()
f = open(filename, "rb")
header_bytes = f.read(HEADER_SIZE)
header_bytes = header_bytes[:4] + header_crc + header_bytes[8:32] + modelname_bytes
print(binascii.hexlify(header_bytes))
f.close()
with open('new_' + filename, 'wb') as fw:
fw.write(header_bytes)
with open(filename, 'rb') as fr:
fr.seek(HEADER_SIZE)
fw.write(fr.read(size))
@kyujin-cho
Copy link
Author

  • ipTIME 기기의 펌웨어 체크섬은 CRC 검사 및 모델내임 검사를 같이 하므로, 모델네임을 기기로 바꿔서 CRC 체크섬을 재작성해주는 스크립트임.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment