Created
February 9, 2018 08:51
-
-
Save kyujin-cho/e1cd6ef3ab16648973e21d7e4f3330cb to your computer and use it in GitHub Desktop.
ipTIME-device uImage firmware Header Rewrite Script
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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)) | |
Author
kyujin-cho
commented
Feb 9, 2018
- ipTIME 기기의 펌웨어 체크섬은 CRC 검사 및 모델내임 검사를 같이 하므로, 모델네임을 기기로 바꿔서 CRC 체크섬을 재작성해주는 스크립트임.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment