Fill header in application

pull/5950/head
Jimmy Brisson 2018-01-25 15:57:48 -06:00
parent b2c71c0fce
commit 4c47f21cac
2 changed files with 85 additions and 16 deletions

View File

@ -20,6 +20,9 @@ import re
import tempfile
import datetime
import uuid
import struct
import zlib
import hashlib
from shutil import rmtree
from os.path import join, exists, dirname, basename, abspath, normpath, splitext
from os.path import relpath
@ -339,8 +342,65 @@ def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
return toolchain
def _printihex(ihex):
import pprint
pprint.PrettyPrinter().pprint(ihex.todict())
def _real_region_size(region):
try:
part = intelhex_offset(region.filename, offset=region.start)
return (part.maxaddr() - part.minaddr()) + 1
except AttributeError:
return region.size
def _fill_header(region_list, current_region):
"""Fill an application header region
This is done it three steps:
* Fill the whole region with zeros
* Fill const, timestamp and size entries with their data
* Fill the digests using this header as the header region
"""
region_dict = {r.name: r for r in region_list}
header = IntelHex()
header.puts(current_region.start, b'\x00' * current_region.size)
start = current_region.start
for member in current_region.filename:
_, type, subtype, data = member
member_size = Config.header_member_size(member)
if type == "const":
fmt = {"8": "<B", "16": "<H", "32": "<L", "64": "<Q"}[subtype]
header.puts(start, struct.pack(fmt, int(data, 0)))
elif type == "timestamp":
fmt = {"32": "<L", "64": "<Q"}[subtype]
header.puts(start, struct.pack(fmt, time()))
elif type == "size":
fmt = {"32": "<L", "64": "<Q"}[subtype]
size = sum(_real_region_size(region_dict[r]) for r in data)
header.puts(start, struct.pack(fmt, size))
start += Config.header_member_size(member)
start = current_region.start
for member in current_region.filename:
_, type, subtype, data = member
if type == "digest":
if data == "header":
ih = header
else:
ih = intelhex_offset(region_dict[data].filename, offset=region_dict[data].start)
if subtype == "CRCITT32":
header.puts(start, struct.pack("<l", zlib.crc32(ih.tobinarray())))
elif subtype.startswith("SHA"):
if subtype == "SHA256":
hash = hashlib.sha256()
elif subtype == "SHA512":
hash = hashlib.sha512()
hash.update(ih.tobinarray())
header.puts(start, hash.digest())
start += Config.header_member_size(member)
return header
def merge_region_list(region_list, destination, padding=b'\xFF'):
"""Merege the region_list into a single image
"""Merge the region_list into a single image
Positional Arguments:
region_list - list of regions, which should contain filenames
@ -355,6 +415,11 @@ def merge_region_list(region_list, destination, padding=b'\xFF'):
for region in region_list:
if region.active and not region.filename:
raise ToolException("Active region has no contents: No file found.")
if isinstance(region.filename, list):
header_basename, _ = splitext(destination)
header_filename = header_basename + "_header.hex"
_fill_header(region_list, region).tofile(header_filename, format='hex')
region = region._replace(filename=header_filename)
if region.filename:
print(" Filling region %s with %s" % (region.name, region.filename))
part = intelhex_offset(region.filename, offset=region.start)

View File

@ -569,25 +569,29 @@ class Config(object):
raise ConfigException(
"Bootloader build requested but no bootlader configuration")
@staticmethod
def header_member_size(member):
_, _, subtype, _ = member
try:
return int(subtype) // 8
except:
if subtype == "CRCITT32":
return 32 // 8
elif subtype == "SHA256":
return 256 // 8
elif subtype == "SHA512":
return 512 // 8
else:
raise ValueError("target.header_format: subtype %s is not "
"understood" % subtype)
@staticmethod
def _header_size(format):
size_in_bytes = 0
for _, _, subtype, _ in format:
try:
size_in_bytes += int(subtype) // 8
except:
if subtype == "CRCITT32":
size_in_bytes += 32 // 8
elif subtype == "SHA256":
size_in_bytes += 256 // 8
else:
raise ValueError("target.header_format: subtype %s is not "
"understood" % subtype)
return size_in_bytes
return sum(Config.header_member_size(m) for m in format)
def _make_header_region(self, start, header_format):
size = self._header_size(header_format)
region = Region("application_header", start, size, False, None)
region = Region("header", start, size, False, None)
start += size
start = ((start + 7) // 8) * 8
return (start, region)
@ -615,7 +619,7 @@ class Config(object):
if self.target.header_format:
start, region = self._make_header_region(
start, self.target.header_format)
yield region
yield region._replace(filename=self.target.header_format)
if self.target.restrict_size is not None:
new_size = int(self.target.restrict_size, 0)
new_size = Config._align_floor(start + new_size, self.sectors) - start