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
@@ -339,8 +342,65 @@ 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
+ def _fill_header (region_list , current_region ):
357
+ """Fill an application header region
358
+
359
+ This is done it three steps:
360
+ * Fill the whole region with zeros
361
+ * Fill const, timestamp and size entries with their data
362
+ * Fill the digests using this header as the header region
363
+ """
364
+ region_dict = {r .name : r for r in region_list }
365
+ header = IntelHex ()
366
+ header .puts (current_region .start , b'\x00 ' * current_region .size )
367
+ start = current_region .start
368
+ for member in current_region .filename :
369
+ _ , type , subtype , data = member
370
+ member_size = Config .header_member_size (member )
371
+ if type == "const" :
372
+ fmt = {"8" : "<B" , "16" : "<H" , "32" : "<L" , "64" : "<Q" }[subtype ]
373
+ header .puts (start , struct .pack (fmt , int (data , 0 )))
374
+ elif type == "timestamp" :
375
+ fmt = {"32" : "<L" , "64" : "<Q" }[subtype ]
376
+ header .puts (start , struct .pack (fmt , time ()))
377
+ elif type == "size" :
378
+ fmt = {"32" : "<L" , "64" : "<Q" }[subtype ]
379
+ size = sum (_real_region_size (region_dict [r ]) for r in data )
380
+ header .puts (start , struct .pack (fmt , size ))
381
+ start += Config .header_member_size (member )
382
+ start = current_region .start
383
+ for member in current_region .filename :
384
+ _ , type , subtype , data = member
385
+ if type == "digest" :
386
+ if data == "header" :
387
+ ih = header
388
+ else :
389
+ ih = intelhex_offset (region_dict [data ].filename , offset = region_dict [data ].start )
390
+ if subtype == "CRCITT32" :
391
+ header .puts (start , struct .pack ("<l" , zlib .crc32 (ih .tobinarray ())))
392
+ elif subtype .startswith ("SHA" ):
393
+ if subtype == "SHA256" :
394
+ hash = hashlib .sha256 ()
395
+ elif subtype == "SHA512" :
396
+ hash = hashlib .sha512 ()
397
+ hash .update (ih .tobinarray ())
398
+ header .puts (start , hash .digest ())
399
+ start += Config .header_member_size (member )
400
+ return header
401
+
342
402
def merge_region_list (region_list , destination , padding = b'\xFF ' ):
343
- """Merege the region_list into a single image
403
+ """Merge the region_list into a single image
344
404
345
405
Positional Arguments:
346
406
region_list - list of regions, which should contain filenames
@@ -355,6 +415,11 @@ def merge_region_list(region_list, destination, padding=b'\xFF'):
355
415
for region in region_list :
356
416
if region .active and not region .filename :
357
417
raise ToolException ("Active region has no contents: No file found." )
418
+ if isinstance (region .filename , list ):
419
+ header_basename , _ = splitext (destination )
420
+ header_filename = header_basename + "_header.hex"
421
+ _fill_header (region_list , region ).tofile (header_filename , format = 'hex' )
422
+ region = region ._replace (filename = header_filename )
358
423
if region .filename :
359
424
print (" Filling region %s with %s" % (region .name , region .filename ))
360
425
part = intelhex_offset (region .filename , offset = region .start )
0 commit comments