mirror of https://github.com/ARMmbed/mbed-os.git
Fill header in application
parent
b2c71c0fce
commit
4c47f21cac
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue