mcu_hi3321_watch/tools/pkg/packet_create.py
2025-06-06 15:13:55 +08:00

415 lines
14 KiB
Python

#!/usr/bin/env python3
# encoding=utf-8
# ============================================================================
# @brief Packing Scripts file
# ============================================================================
import struct
import sys
import os
import hashlib
# only use for nbiot
class crc16:
POLYNOMIAL = 0x1021
PRESET = 0x0000
_tab = []
def __init__(self):
self._tab = [self._initial(i) for i in range(256)]
def _initial(self, c):
crc = 0
c = c << 8
for j in range(8):
if (crc ^ c) & 0x8000:
crc = (crc << 1) ^ self.POLYNOMIAL
else:
crc = crc << 1
c = c << 1
return crc
def _update_crc(self, crc, c):
cc = 0xff & int(c)
tmp = (crc >> 8) ^ cc
crc = (crc << 8) ^ self._tab[tmp & 0xff]
crc = crc & 0xffff
return crc
def crc(self, str):
crc = self.PRESET
for c in str:
crc = self._update_crc(crc, ord(c))
return crc
def crcb(self, i):
crc = self.PRESET
for c in i:
crc = self._update_crc(crc, c)
return crc
t = crc16()
ignoreFlag = 1
def parse_param(pathNameListNew, burnAddrListNew, burnSizeListNew, imageSizeListNew, typeListNew, inputList):
for item in inputList:
if '|' in item:
path, burnAddr, burnSize, type = item.split("|")
if ignoreFlag == 1 and not os.path.exists(path):
continue
imageSize = os.path.getsize(path)
pathNameListNew.append(path)
burnAddrListNew.append(int(burnAddr, 16))
burnSizeListNew.append(int(burnSize, 16))
imageSizeListNew.append(imageSize)
typeListNew.append(int(type))
else:
pathNameListNew.append(item)
imageSize = os.path.getsize(item)
imageSizeListNew.append(imageSize)
def create_sha_file(source, target):
for src in source:
with open(src, "rb" ) as bin_file:
sha = hashlib.sha256( bin_file.read() )
bin_file.close()
with open( str(target), "wb") as sha_file:
sha_file.write( sha.digest())
def create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, outputPath):
flag = 0xefbeaddf
crc = 0
imageNum = len(pathNameList)
# sizeof(IMAGE_INFO) is 52, sizeof(FWPKG_HEAD) is 12
headLen = imageNum * 52 + 12
# each image has 16byte 0 in the end
padLen = 16 * imageNum
totalFileSize = sum(imageSizeList) + headLen + padLen
# prepare
outputRoot = os.path.dirname(outputPath)
if not os.path.isdir(outputRoot):
os.makedirs(outputRoot)
with open(outputPath, 'wb+') as file:
file.write(struct.pack('IHHI', flag, crc, imageNum, totalFileSize))
startIndex = headLen
times = 0
for path in pathNameList:
pathName = os.path.basename(path)
file.write(
struct.pack('32sIIIII', bytes(pathName, 'ascii'), startIndex, imageSizeList[times], burnAddrList[times],
burnSizeList[times], typeList[times]))
# separate each image with 16 bytes 0
startIndex = startIndex + imageSizeList[times] + 16
times += 1
for info in fileInfoList:
file.write(info)
file.write(struct.pack('IIII', 0, 0, 0, 0))
file.flush()
# crc range is FWPKG_HEAD.imageNum to end, begin index is 6bytes
file.seek(6)
newdata = file.read(headLen - 6)
crc16 = t.crcb(newdata)
file.seek(4)
file.write(struct.pack('H', crc16))
file.close()
def parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList, packet_path):
with open(packet_path, 'rb+') as file:
info = file.read(struct.calcsize('IHHI'))
flag, crc, imageNum, totalFileSize = struct.unpack('IHHI', info)
times = 0
for index in range(0, imageNum):
info = file.read(struct.calcsize('32sIIIII'))
pathName, startIndex, imageSize, burnAddr, burnSize, type2 = struct.unpack('32sIIIII', info)
#separate each image with 16 bytes 0
pathName = str(pathName, encoding="utf-8")
pathNameNew = ''
for char in pathName:
if char != '\x00':
pathNameNew += char
print(pathNameNew)
pathNameList.append(pathNameNew)
startIndexList.append(startIndex)
burnAddrList.append(burnAddr)
burnSizeList.append(burnSize)
imageSizeList.append(imageSize)
typeList.append(type2)
for index in range(0, imageNum):
file.seek(startIndexList[index])
fileInfoList.append(file.read(imageSizeList[index]))
file.close()
def packet_bin(outputPath, inputList):
pathNameList = []
burnAddrList = []
burnSizeList = []
imageSizeList = []
typeList = []
fileInfoList = []
parse_param(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, inputList)
for path in pathNameList:
with open(path, 'rb+') as subfile:
data = subfile.read()
fileInfoList.append(data)
subfile.close()
print(pathNameList)
print(burnAddrList)
print(burnSizeList)
print(imageSizeList)
print(typeList)
create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, outputPath)
def update_bin(packet_path, inputList):
pathNameList = []
burnAddrList = []
burnSizeList = []
imageSizeList = []
typeList = []
startIndexList = []
fileInfoList = []
pathNameListNew = []
burnAddrListNew = []
burnSizeListNew = []
imageSizeListNew = []
typeListNew = []
parse_param(pathNameListNew, burnAddrListNew, burnSizeListNew, imageSizeListNew, typeListNew, inputList)
parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList,
packet_path)
for index in range(0, len(pathNameListNew)):
pathNew = pathNameListNew[index]
print(os.path.basename(pathNew))
pathIn32Byte = os.path.basename(pathNew)
if len(pathIn32Byte) > 32:
pathIn32Byte = pathIn32Byte[0:32]
if pathIn32Byte in pathNameList:
for index2 in range(0, len(pathNameList)):
path = pathNameList[index2]
if path == pathIn32Byte:
with open(pathNew, 'rb+') as subfile:
fileInfoList[index2] = subfile.read()
pathNameList[index2] = os.path.basename(pathNew)
if len(burnAddrListNew) > index:
burnAddrList[index2] = burnAddrListNew[index]
if len(burnSizeListNew) > index:
burnSizeList[index2] = burnSizeListNew[index]
imageSizeList[index2] = imageSizeListNew[index]
if len(typeListNew) > index:
typeList[index2] = typeListNew[index]
break
else:
pathNameList.append(pathNameListNew[index])
burnAddrList.append(burnAddrListNew[index])
burnSizeList.append(burnSizeListNew[index])
imageSizeList.append(imageSizeListNew[index])
typeList.append(typeListNew[index])
with open(pathNew, 'rb+') as subfile:
fileInfoList.append(subfile.read())
print(pathNameList)
print(burnAddrList)
print(burnSizeList)
print(imageSizeList)
print(typeList)
create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, packet_path)
def delete_bin(packet_path, name_list):
pathNameList = []
burnAddrList = []
burnSizeList = []
imageSizeList = []
typeList = []
startIndexList = []
fileInfoList = []
pathNameListNew = name_list
parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList,
packet_path)
for pathNew in pathNameListNew:
print(os.path.basename(pathNew))
pathIn32Byte = os.path.basename(pathNew)
if len(pathIn32Byte) > 32:
pathIn32Byte = pathIn32Byte[0:32]
if pathIn32Byte in pathNameList:
for index2 in range(0, len(pathNameList)):
path = pathNameList[index2]
if path == pathIn32Byte:
del fileInfoList[index2]
del pathNameList[index2]
del burnAddrList[index2]
del burnSizeList[index2]
del imageSizeList[index2]
del typeList[index2]
break
print(pathNameList)
print(burnAddrList)
print(burnSizeList)
print(imageSizeList)
print(typeList)
create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, packet_path)
def split_bin(packet_path, output_path):
pathNameList = []
burnAddrList = []
burnSizeList = []
imageSizeList = []
typeList = []
startIndexList = []
fileInfoList = []
parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList,
packet_path)
print(pathNameList)
print(burnAddrList)
print(burnSizeList)
print(imageSizeList)
print(typeList)
imageNum = len(pathNameList)
for index in range(0, imageNum):
pathName = os.path.join(output_path, pathNameList[index])
print(pathName)
with open(pathName, 'wb+') as file:
file.write(fileInfoList[index])
file.close()
def show_bin(packet_path):
pathNameList = []
burnAddrList = []
burnSizeList = []
imageSizeList = []
typeList = []
startIndexList = []
fileInfoList = []
parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList,
packet_path)
print("pathNameList")
print(pathNameList)
print("burnAddrList")
print(burnAddrList)
print("burnSizeList")
print(burnSizeList)
print("imageSizeList")
print(imageSizeList)
print("typeList")
print(typeList)
'''
def merge_bin(packet_path, inputList):
pathNameList = []
burnAddrList = []
burnSizeList = []
imageSizeList = []
typeList = []
startIndexList = []
fileInfoList = []
parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList,
packet_path)
hasKvBin = False
kvBinIndex = -1
for typeItem in typeList:
kvBinIndex += 1
if typeItem == 2:
hasKvBin = True
break
if hasKvBin is False:
return
pathNew = inputList[0]
subfile = open(pathNew, 'rb+')
newBinArray = subfile.read()
subfile.close()
newKv = kv_create.decode_kv_bin(bytearray(newBinArray))
srcBinArray = fileInfoList[kvBinIndex]
srcKv = kv_create.decode_kv_bin(bytearray(srcBinArray))
srcKv[0xb0].update(newKv[0xb0])
srcKv[0xb2].update(newKv[0xb2])
srcKv[0xb4].update(newKv[0xb4])
fileInfoList[kvBinIndex] = kv_create.get_kv_bin(srcKv)
print(pathNameList)
print(burnAddrList)
print(burnSizeList)
print(imageSizeList)
print(typeList)
create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, packet_path)
'''
if __name__=="__main__":
args = len(sys.argv)
argv = sys.argv
if(args <= 1):
print("parma error, please use -help for usage")
sys.exit()
if (argv[1] == '-hard'):
ignoreFlag = 0
del argv[1]
if (argv[1] == '-packet'):
outputPath = argv[2]
print(outputPath)
del argv[2]
del argv[1]
del argv[0]
packet_bin(outputPath, argv)
elif (argv[1] == '-update'):
outputPath = argv[2]
print(outputPath)
del argv[2]
del argv[1]
del argv[0]
update_bin(outputPath, argv)
elif (argv[1] == '-split'):
input_file = argv[2]
outputPath = argv[3]
split_bin(input_file, outputPath)
elif (argv[1] == '-show'):
input_file = argv[2]
show_bin(input_file)
elif (argv[1] == '-delete'):
outputPath = argv[2]
print(outputPath)
del argv[2]
del argv[1]
del argv[0]
delete_bin(outputPath, argv)
elif (argv[1] == '-merge'):
outputPath = argv[2]
print(outputPath)
del argv[2]
del argv[1]
del argv[0]
merge_bin(outputPath, argv)
elif (argv[1] == '-sha256'):
outputPath = argv[2]
print(outputPath)
del argv[2]
del argv[1]
del argv[0]
create_sha_file(argv, outputPath)
elif (argv[1] == '-help'):
print("\
-packet, packet all bins as one\r\n\
param should be : -packet \"outputfile\" \"binName1|burnAddr|burnSize|type\"...\r\n\
-split, split inputefile as several bins\r\n\
param should be : -split inputefile outputPath\r\n\
-update, update bins in inputefile, if bin not in inputefile, it will be add.\r\n\
param should be : -update \"inputefile\" \"binName1|burnAddr|burnSize|type\"...\r\n\
-delete, delete bins in inputfile\r\n\
param should be : -delete inputefile binName1 binName2...\r\n\
-merge, merge kv bin in inputefile, if bin not in inputefile, it will be add.\r\n\
param should be : -merge inputefile binName1...\r\n\
-show, show the bins in inputfile\r\n\
param should be : -show \"inputefile\"\r\n\
-help\r\n")
else:
outputPath = argv[1]
print(outputPath)
del argv[1]
del argv[0]
packet_bin(outputPath, argv)