1#!/usr/bin/env python3 2# encoding=utf-8 3# ============================================================================ 4# @brief Packing Scripts file 5# Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED. 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18# ============================================================================ 19 20import struct 21import sys 22import os 23import hashlib 24# only use for nbiot 25 26class crc16: 27 POLYNOMIAL = 0x1021 28 PRESET = 0x0000 29 _tab = [] 30 def __init__(self): 31 self._tab = [self._initial(i) for i in range(256)] 32 33 def _initial(self, c): 34 crc = 0 35 c = c << 8 36 for j in range(8): 37 if (crc ^ c) & 0x8000: 38 crc = (crc << 1) ^ self.POLYNOMIAL 39 else: 40 crc = crc << 1 41 c = c << 1 42 return crc 43 44 def _update_crc(self, crc, c): 45 cc = 0xff & int(c) 46 47 tmp = (crc >> 8) ^ cc 48 crc = (crc << 8) ^ self._tab[tmp & 0xff] 49 crc = crc & 0xffff 50 51 return crc 52 53 def crc(self, str): 54 crc = self.PRESET 55 for c in str: 56 crc = self._update_crc(crc, ord(c)) 57 return crc 58 59 def crcb(self, i): 60 crc = self.PRESET 61 for c in i: 62 crc = self._update_crc(crc, c) 63 return crc 64 65t = crc16() 66ignoreFlag = 1 67def parse_param(pathNameListNew, burnAddrListNew, burnSizeListNew, imageSizeListNew, typeListNew, inputList): 68 for item in inputList: 69 if '|' in item: 70 path, burnAddr, burnSize, type = item.split("|") 71 if ignoreFlag == 1 and not os.path.exists(path): 72 continue 73 imageSize = os.path.getsize(path) 74 pathNameListNew.append(path) 75 burnAddrListNew.append(int(burnAddr, 16)) 76 burnSizeListNew.append(int(burnSize, 16)) 77 imageSizeListNew.append(imageSize) 78 typeListNew.append(int(type)) 79 else: 80 pathNameListNew.append(item) 81 imageSize = os.path.getsize(item) 82 imageSizeListNew.append(imageSize) 83 84def create_sha_file(source, target): 85 for src in source: 86 with open(src, "rb" ) as bin_file: 87 sha = hashlib.sha256( bin_file.read() ) 88 bin_file.close() 89 with open( str(target), "wb") as sha_file: 90 sha_file.write( sha.digest()) 91 92def create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, outputPath): 93 flag = 0xefbeaddf 94 crc = 0 95 imageNum = len(pathNameList) 96 # sizeof(IMAGE_INFO) is 52, sizeof(FWPKG_HEAD) is 12 97 headLen = imageNum * 52 + 12 98 # each image has 16byte 0 in the end 99 padLen = 16 * imageNum 100 totalFileSize = sum(imageSizeList) + headLen + padLen 101 # prepare 102 outputRoot = os.path.dirname(outputPath) 103 if not os.path.isdir(outputRoot): 104 os.makedirs(outputRoot) 105 with open(outputPath, 'wb+') as file: 106 file.write(struct.pack('IHHI', flag, crc, imageNum, totalFileSize)) 107 startIndex = headLen 108 times = 0 109 for path in pathNameList: 110 pathName = os.path.basename(path) 111 file.write( 112 struct.pack('32sIIIII', bytes(pathName, 'ascii'), startIndex, imageSizeList[times], burnAddrList[times], 113 burnSizeList[times], typeList[times])) 114 # separate each image with 16 bytes 0 115 startIndex = startIndex + imageSizeList[times] + 16 116 times += 1 117 118 for info in fileInfoList: 119 file.write(info) 120 file.write(struct.pack('IIII', 0, 0, 0, 0)) 121 122 file.flush() 123 # crc range is FWPKG_HEAD.imageNum to end, begin index is 6bytes 124 file.seek(6) 125 newdata = file.read(headLen - 6) 126 crc16 = t.crcb(newdata) 127 file.seek(4) 128 file.write(struct.pack('H', crc16)) 129 file.close() 130def parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList, packet_path): 131 with open(packet_path, 'rb+') as file: 132 info = file.read(struct.calcsize('IHHI')) 133 flag, crc, imageNum, totalFileSize = struct.unpack('IHHI', info) 134 times = 0 135 for index in range(0, imageNum): 136 info = file.read(struct.calcsize('32sIIIII')) 137 pathName, startIndex, imageSize, burnAddr, burnSize, type2 = struct.unpack('32sIIIII', info) 138 #separate each image with 16 bytes 0 139 pathName = str(pathName, encoding="utf-8") 140 pathNameNew = '' 141 for char in pathName: 142 if char != '\x00': 143 pathNameNew += char 144 print(pathNameNew) 145 pathNameList.append(pathNameNew) 146 startIndexList.append(startIndex) 147 burnAddrList.append(burnAddr) 148 burnSizeList.append(burnSize) 149 imageSizeList.append(imageSize) 150 typeList.append(type2) 151 152 for index in range(0, imageNum): 153 file.seek(startIndexList[index]) 154 fileInfoList.append(file.read(imageSizeList[index])) 155 file.close() 156 157def packet_bin(outputPath, inputList): 158 pathNameList = [] 159 burnAddrList = [] 160 burnSizeList = [] 161 imageSizeList = [] 162 typeList = [] 163 fileInfoList = [] 164 parse_param(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, inputList) 165 for path in pathNameList: 166 with open(path, 'rb+') as subfile: 167 data = subfile.read() 168 fileInfoList.append(data) 169 subfile.close() 170 print(pathNameList) 171 print(burnAddrList) 172 print(burnSizeList) 173 print(imageSizeList) 174 print(typeList) 175 176 create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, outputPath) 177def update_bin(packet_path, inputList): 178 pathNameList = [] 179 burnAddrList = [] 180 burnSizeList = [] 181 imageSizeList = [] 182 typeList = [] 183 startIndexList = [] 184 fileInfoList = [] 185 186 pathNameListNew = [] 187 burnAddrListNew = [] 188 burnSizeListNew = [] 189 imageSizeListNew = [] 190 typeListNew = [] 191 parse_param(pathNameListNew, burnAddrListNew, burnSizeListNew, imageSizeListNew, typeListNew, inputList) 192 parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList, 193 packet_path) 194 195 for index in range(0, len(pathNameListNew)): 196 pathNew = pathNameListNew[index] 197 print(os.path.basename(pathNew)) 198 pathIn32Byte = os.path.basename(pathNew) 199 if len(pathIn32Byte) > 32: 200 pathIn32Byte = pathIn32Byte[0:32] 201 if pathIn32Byte in pathNameList: 202 for index2 in range(0, len(pathNameList)): 203 path = pathNameList[index2] 204 if path == pathIn32Byte: 205 with open(pathNew, 'rb+') as subfile: 206 fileInfoList[index2] = subfile.read() 207 pathNameList[index2] = os.path.basename(pathNew) 208 if len(burnAddrListNew) > index: 209 burnAddrList[index2] = burnAddrListNew[index] 210 if len(burnSizeListNew) > index: 211 burnSizeList[index2] = burnSizeListNew[index] 212 imageSizeList[index2] = imageSizeListNew[index] 213 if len(typeListNew) > index: 214 typeList[index2] = typeListNew[index] 215 break 216 else: 217 pathNameList.append(pathNameListNew[index]) 218 burnAddrList.append(burnAddrListNew[index]) 219 burnSizeList.append(burnSizeListNew[index]) 220 imageSizeList.append(imageSizeListNew[index]) 221 typeList.append(typeListNew[index]) 222 with open(pathNew, 'rb+') as subfile: 223 fileInfoList.append(subfile.read()) 224 print(pathNameList) 225 print(burnAddrList) 226 print(burnSizeList) 227 print(imageSizeList) 228 print(typeList) 229 230 create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, packet_path) 231def delete_bin(packet_path, name_list): 232 pathNameList = [] 233 burnAddrList = [] 234 burnSizeList = [] 235 imageSizeList = [] 236 typeList = [] 237 startIndexList = [] 238 fileInfoList = [] 239 240 pathNameListNew = name_list 241 242 parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList, 243 packet_path) 244 245 for pathNew in pathNameListNew: 246 print(os.path.basename(pathNew)) 247 pathIn32Byte = os.path.basename(pathNew) 248 if len(pathIn32Byte) > 32: 249 pathIn32Byte = pathIn32Byte[0:32] 250 if pathIn32Byte in pathNameList: 251 for index2 in range(0, len(pathNameList)): 252 path = pathNameList[index2] 253 if path == pathIn32Byte: 254 del fileInfoList[index2] 255 del pathNameList[index2] 256 del burnAddrList[index2] 257 del burnSizeList[index2] 258 del imageSizeList[index2] 259 del typeList[index2] 260 break 261 print(pathNameList) 262 print(burnAddrList) 263 print(burnSizeList) 264 print(imageSizeList) 265 print(typeList) 266 267 create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, packet_path) 268def split_bin(packet_path, output_path): 269 pathNameList = [] 270 burnAddrList = [] 271 burnSizeList = [] 272 imageSizeList = [] 273 typeList = [] 274 startIndexList = [] 275 fileInfoList = [] 276 277 parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList, 278 packet_path) 279 print(pathNameList) 280 print(burnAddrList) 281 print(burnSizeList) 282 print(imageSizeList) 283 print(typeList) 284 285 imageNum = len(pathNameList) 286 for index in range(0, imageNum): 287 pathName = os.path.join(output_path, pathNameList[index]) 288 print(pathName) 289 with open(pathName, 'wb+') as file: 290 file.write(fileInfoList[index]) 291 file.close() 292def show_bin(packet_path): 293 pathNameList = [] 294 burnAddrList = [] 295 burnSizeList = [] 296 imageSizeList = [] 297 typeList = [] 298 startIndexList = [] 299 fileInfoList = [] 300 301 parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList, 302 packet_path) 303 print("pathNameList") 304 print(pathNameList) 305 print("burnAddrList") 306 print(burnAddrList) 307 print("burnSizeList") 308 print(burnSizeList) 309 print("imageSizeList") 310 print(imageSizeList) 311 print("typeList") 312 print(typeList) 313''' 314def merge_bin(packet_path, inputList): 315 pathNameList = [] 316 burnAddrList = [] 317 burnSizeList = [] 318 imageSizeList = [] 319 typeList = [] 320 startIndexList = [] 321 fileInfoList = [] 322 323 parse_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, startIndexList, fileInfoList, 324 packet_path) 325 326 hasKvBin = False 327 kvBinIndex = -1 328 for typeItem in typeList: 329 kvBinIndex += 1 330 if typeItem == 2: 331 hasKvBin = True 332 break 333 if hasKvBin is False: 334 return 335 pathNew = inputList[0] 336 subfile = open(pathNew, 'rb+') 337 newBinArray = subfile.read() 338 subfile.close() 339 newKv = kv_create.decode_kv_bin(bytearray(newBinArray)) 340 srcBinArray = fileInfoList[kvBinIndex] 341 srcKv = kv_create.decode_kv_bin(bytearray(srcBinArray)) 342 srcKv[0xb0].update(newKv[0xb0]) 343 srcKv[0xb2].update(newKv[0xb2]) 344 srcKv[0xb4].update(newKv[0xb4]) 345 fileInfoList[kvBinIndex] = kv_create.get_kv_bin(srcKv) 346 347 print(pathNameList) 348 print(burnAddrList) 349 print(burnSizeList) 350 print(imageSizeList) 351 print(typeList) 352 353 create_allinone(pathNameList, burnAddrList, burnSizeList, imageSizeList, typeList, fileInfoList, packet_path) 354''' 355if __name__=="__main__": 356 args = len(sys.argv) 357 argv = sys.argv 358 if(args <= 1): 359 print("parma error, please use -help for usage") 360 sys.exit() 361 if (argv[1] == '-hard'): 362 ignoreFlag = 0 363 del argv[1] 364 if (argv[1] == '-packet'): 365 outputPath = argv[2] 366 print(outputPath) 367 del argv[2] 368 del argv[1] 369 del argv[0] 370 packet_bin(outputPath, argv) 371 elif (argv[1] == '-update'): 372 outputPath = argv[2] 373 print(outputPath) 374 del argv[2] 375 del argv[1] 376 del argv[0] 377 update_bin(outputPath, argv) 378 elif (argv[1] == '-split'): 379 input_file = argv[2] 380 outputPath = argv[3] 381 split_bin(input_file, outputPath) 382 elif (argv[1] == '-show'): 383 input_file = argv[2] 384 show_bin(input_file) 385 elif (argv[1] == '-delete'): 386 outputPath = argv[2] 387 print(outputPath) 388 del argv[2] 389 del argv[1] 390 del argv[0] 391 delete_bin(outputPath, argv) 392 elif (argv[1] == '-merge'): 393 outputPath = argv[2] 394 print(outputPath) 395 del argv[2] 396 del argv[1] 397 del argv[0] 398 merge_bin(outputPath, argv) 399 elif (argv[1] == '-sha256'): 400 outputPath = argv[2] 401 print(outputPath) 402 del argv[2] 403 del argv[1] 404 del argv[0] 405 create_sha_file(argv, outputPath) 406 elif (argv[1] == '-help'): 407 print("\ 408 -packet, packet all bins as one\r\n\ 409 param should be : -packet \"outputfile\" \"binName1|burnAddr|burnSize|type\"...\r\n\ 410 -split, split inputefile as several bins\r\n\ 411 param should be : -split inputefile outputPath\r\n\ 412 -update, update bins in inputefile, if bin not in inputefile, it will be add.\r\n\ 413 param should be : -update \"inputefile\" \"binName1|burnAddr|burnSize|type\"...\r\n\ 414 -delete, delete bins in inputfile\r\n\ 415 param should be : -delete inputefile binName1 binName2...\r\n\ 416 -merge, merge kv bin in inputefile, if bin not in inputefile, it will be add.\r\n\ 417 param should be : -merge inputefile binName1...\r\n\ 418 -show, show the bins in inputfile\r\n\ 419 param should be : -show \"inputefile\"\r\n\ 420 -help\r\n") 421 else: 422 outputPath = argv[1] 423 print(outputPath) 424 del argv[1] 425 del argv[0] 426 packet_bin(outputPath, argv) 427 428