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 tempfile
import datetime import datetime
import uuid import uuid
import struct
import zlib
import hashlib
from shutil import rmtree from shutil import rmtree
from os.path import join, exists, dirname, basename, abspath, normpath, splitext from os.path import join, exists, dirname, basename, abspath, normpath, splitext
from os.path import relpath from os.path import relpath
@ -339,8 +342,65 @@ def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
return toolchain 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'): 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: Positional Arguments:
region_list - list of regions, which should contain filenames 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: for region in region_list:
if region.active and not region.filename: if region.active and not region.filename:
raise ToolException("Active region has no contents: No file found.") 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: if region.filename:
print(" Filling region %s with %s" % (region.name, region.filename)) print(" Filling region %s with %s" % (region.name, region.filename))
part = intelhex_offset(region.filename, offset=region.start) part = intelhex_offset(region.filename, offset=region.start)

View File

@ -569,25 +569,29 @@ class Config(object):
raise ConfigException( raise ConfigException(
"Bootloader build requested but no bootlader configuration") "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 @staticmethod
def _header_size(format): def _header_size(format):
size_in_bytes = 0 return sum(Config.header_member_size(m) for m in format)
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
def _make_header_region(self, start, header_format): def _make_header_region(self, start, header_format):
size = self._header_size(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 += size
start = ((start + 7) // 8) * 8 start = ((start + 7) // 8) * 8
return (start, region) return (start, region)
@ -615,7 +619,7 @@ class Config(object):
if self.target.header_format: if self.target.header_format:
start, region = self._make_header_region( start, region = self._make_header_region(
start, self.target.header_format) start, self.target.header_format)
yield region yield region._replace(filename=self.target.header_format)
if self.target.restrict_size is not None: if self.target.restrict_size is not None:
new_size = int(self.target.restrict_size, 0) new_size = int(self.target.restrict_size, 0)
new_size = Config._align_floor(start + new_size, self.sectors) - start new_size = Config._align_floor(start + new_size, self.sectors) - start