Skip to content

Commit 4c47f21

Browse files
committed
Fill header in application
1 parent b2c71c0 commit 4c47f21

File tree

2 files changed

+85
-16
lines changed

2 files changed

+85
-16
lines changed

tools/build_api.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
import tempfile
2121
import datetime
2222
import uuid
23+
import struct
24+
import zlib
25+
import hashlib
2326
from shutil import rmtree
2427
from os.path import join, exists, dirname, basename, abspath, normpath, splitext
2528
from os.path import relpath
@@ -339,8 +342,65 @@ def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
339342

340343
return toolchain
341344

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+
342402
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
344404
345405
Positional Arguments:
346406
region_list - list of regions, which should contain filenames
@@ -355,6 +415,11 @@ def merge_region_list(region_list, destination, padding=b'\xFF'):
355415
for region in region_list:
356416
if region.active and not region.filename:
357417
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)
358423
if region.filename:
359424
print(" Filling region %s with %s" % (region.name, region.filename))
360425
part = intelhex_offset(region.filename, offset=region.start)

tools/config/__init__.py

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -569,25 +569,29 @@ def regions(self):
569569
raise ConfigException(
570570
"Bootloader build requested but no bootlader configuration")
571571

572+
@staticmethod
573+
def header_member_size(member):
574+
_, _, subtype, _ = member
575+
try:
576+
return int(subtype) // 8
577+
except:
578+
if subtype == "CRCITT32":
579+
return 32 // 8
580+
elif subtype == "SHA256":
581+
return 256 // 8
582+
elif subtype == "SHA512":
583+
return 512 // 8
584+
else:
585+
raise ValueError("target.header_format: subtype %s is not "
586+
"understood" % subtype)
587+
572588
@staticmethod
573589
def _header_size(format):
574-
size_in_bytes = 0
575-
for _, _, subtype, _ in format:
576-
try:
577-
size_in_bytes += int(subtype) // 8
578-
except:
579-
if subtype == "CRCITT32":
580-
size_in_bytes += 32 // 8
581-
elif subtype == "SHA256":
582-
size_in_bytes += 256 // 8
583-
else:
584-
raise ValueError("target.header_format: subtype %s is not "
585-
"understood" % subtype)
586-
return size_in_bytes
590+
return sum(Config.header_member_size(m) for m in format)
587591

588592
def _make_header_region(self, start, header_format):
589593
size = self._header_size(header_format)
590-
region = Region("application_header", start, size, False, None)
594+
region = Region("header", start, size, False, None)
591595
start += size
592596
start = ((start + 7) // 8) * 8
593597
return (start, region)
@@ -615,7 +619,7 @@ def _generate_bootloader_build(self, rom_start, rom_size):
615619
if self.target.header_format:
616620
start, region = self._make_header_region(
617621
start, self.target.header_format)
618-
yield region
622+
yield region._replace(filename=self.target.header_format)
619623
if self.target.restrict_size is not None:
620624
new_size = int(self.target.restrict_size, 0)
621625
new_size = Config._align_floor(start + new_size, self.sectors) - start

0 commit comments

Comments
 (0)