20
20
import tempfile
21
21
import datetime
22
22
import uuid
23
+ import struct
24
+ import zlib
25
+ import hashlib
23
26
from shutil import rmtree
24
27
from os .path import join , exists , dirname , basename , abspath , normpath , splitext
25
28
from os .path import relpath
33
36
from .arm_pack_manager import Cache
34
37
from .utils import (mkdir , run_cmd , run_cmd_ext , NotSupportedException ,
35
38
ToolException , InvalidReleaseTargetException ,
36
- intelhex_offset )
39
+ intelhex_offset , integer )
37
40
from .paths import (MBED_CMSIS_PATH , MBED_TARGETS_PATH , MBED_LIBRARIES ,
38
41
MBED_HEADER , MBED_DRIVERS , MBED_PLATFORM , MBED_HAL ,
39
42
MBED_CONFIG_FILE , MBED_LIBRARIES_DRIVERS ,
@@ -339,8 +342,68 @@ def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
339
342
340
343
return toolchain
341
344
345
+ def _printihex (ihex ):
346
+ import pprint
347
+ pprint .PrettyPrinter ().pprint (ihex .todict ())
348
+
349
+ def _real_region_size (region ):
350
+ try :
351
+ part = intelhex_offset (region .filename , offset = region .start )
352
+ return (part .maxaddr () - part .minaddr ()) + 1
353
+ except AttributeError :
354
+ return region .size
355
+
356
+
357
+ def _fill_header (region_list , current_region ):
358
+ """Fill an application header region
359
+
360
+ This is done it three steps:
361
+ * Fill the whole region with zeros
362
+ * Fill const, timestamp and size entries with their data
363
+ * Fill the digests using this header as the header region
364
+ """
365
+ region_dict = {r .name : r for r in region_list }
366
+ header = IntelHex ()
367
+ header .puts (current_region .start , b'\x00 ' * current_region .size )
368
+ start = current_region .start
369
+ for member in current_region .filename :
370
+ _ , type , subtype , data = member
371
+ member_size = Config .header_member_size (member )
372
+ if type == "const" :
373
+ fmt = {
374
+ "8le" : ">B" , "16le" : "<H" , "32le" : "<L" , "64le" : "<Q" ,
375
+ "8be" : "<B" , "16be" : ">H" , "32be" : ">L" , "64be" : ">Q"
376
+ }[subtype ]
377
+ header .puts (start , struct .pack (fmt , integer (data , 0 )))
378
+ elif type == "timestamp" :
379
+ fmt = {"32le" : "<L" , "64le" : "<Q" ,
380
+ "32be" : ">L" , "64be" : ">Q" }[subtype ]
381
+ header .puts (start , struct .pack (fmt , time ()))
382
+ elif type == "size" :
383
+ fmt = {"32le" : "<L" , "64le" : "<Q" ,
384
+ "32be" : ">L" , "64be" : ">Q" }[subtype ]
385
+ size = sum (_real_region_size (region_dict [r ]) for r in data )
386
+ header .puts (start , struct .pack (fmt , size ))
387
+ elif type == "digest" :
388
+ if data == "header" :
389
+ ih = header [:start ]
390
+ else :
391
+ ih = intelhex_offset (region_dict [data ].filename , offset = region_dict [data ].start )
392
+ if subtype .startswith ("CRCITT32" ):
393
+ fmt = {"CRCITT32be" : ">l" , "CRCITT32le" : "<l" }[subtype ]
394
+ header .puts (start , struct .pack (fmt , zlib .crc32 (ih .tobinarray ())))
395
+ elif subtype .startswith ("SHA" ):
396
+ if subtype == "SHA256" :
397
+ hash = hashlib .sha256 ()
398
+ elif subtype == "SHA512" :
399
+ hash = hashlib .sha512 ()
400
+ hash .update (ih .tobinarray ())
401
+ header .puts (start , hash .digest ())
402
+ start += Config .header_member_size (member )
403
+ return header
404
+
342
405
def merge_region_list (region_list , destination , padding = b'\xFF ' ):
343
- """Merege the region_list into a single image
406
+ """Merge the region_list into a single image
344
407
345
408
Positional Arguments:
346
409
region_list - list of regions, which should contain filenames
@@ -355,6 +418,11 @@ def merge_region_list(region_list, destination, padding=b'\xFF'):
355
418
for region in region_list :
356
419
if region .active and not region .filename :
357
420
raise ToolException ("Active region has no contents: No file found." )
421
+ if isinstance (region .filename , list ):
422
+ header_basename , _ = splitext (destination )
423
+ header_filename = header_basename + "_header.hex"
424
+ _fill_header (region_list , region ).tofile (header_filename , format = 'hex' )
425
+ region = region ._replace (filename = header_filename )
358
426
if region .filename :
359
427
print (" Filling region %s with %s" % (region .name , region .filename ))
360
428
part = intelhex_offset (region .filename , offset = region .start )
0 commit comments