2018-10-22 12:10:10 +00:00
|
|
|
#
|
|
|
|
# Copyright (c) 2017-2018 Future Electronics
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
|
|
|
#
|
|
|
|
|
|
|
|
import os
|
|
|
|
import platform
|
|
|
|
import subprocess
|
|
|
|
import errno
|
|
|
|
from array import array
|
2018-10-25 17:48:41 +00:00
|
|
|
from struct import (pack, unpack)
|
2018-10-22 12:10:10 +00:00
|
|
|
from distutils.spawn import find_executable
|
|
|
|
from shutil import copyfile
|
|
|
|
from intelhex import IntelHex
|
|
|
|
from intelhex.compat import asbytes
|
|
|
|
|
|
|
|
from ..config import ConfigException
|
2018-10-25 17:48:41 +00:00
|
|
|
from ..targets import HookError
|
2018-10-22 12:10:10 +00:00
|
|
|
|
|
|
|
|
|
|
|
# Patch Cypress hex file:
|
|
|
|
# - update checksum
|
|
|
|
# - update metadata
|
|
|
|
# - align regions to page (256 bytes) boundary
|
|
|
|
def patch(message_func, ihex, hexf, align=256):
|
|
|
|
#calculate checksum
|
|
|
|
checksum = 0
|
|
|
|
for start, end in ihex.segments():
|
|
|
|
if start >= 0x090000000:
|
|
|
|
continue
|
2018-10-25 17:48:41 +00:00
|
|
|
segment = ihex.tobinarray(start, end)
|
2018-10-22 12:10:10 +00:00
|
|
|
checksum += sum(segment)
|
|
|
|
|
|
|
|
lowchecksum = checksum & 0x0FFFF
|
2018-10-25 17:48:41 +00:00
|
|
|
message_func("Calculated checksum for %s is 0x%04x" % (hexf, lowchecksum))
|
2018-10-22 12:10:10 +00:00
|
|
|
|
|
|
|
# update checksum
|
2018-10-25 17:48:41 +00:00
|
|
|
checksum_str = pack('>H', lowchecksum)
|
|
|
|
ihex.frombytes(array('B', checksum_str), offset=0x90300000)
|
2018-10-22 12:10:10 +00:00
|
|
|
|
|
|
|
# update metadata
|
2018-10-25 17:48:41 +00:00
|
|
|
signature = unpack('>L', ihex.tobinstr(start=0x90500002, size=4))[0]
|
|
|
|
sigcheck = pack('>L', (checksum + signature) & 0x0FFFF)
|
|
|
|
ihex.frombytes(array('B',sigcheck), offset=0x90500008)
|
2018-10-22 12:10:10 +00:00
|
|
|
|
|
|
|
# align flash segments
|
|
|
|
align_mask = align - 1
|
|
|
|
alignments = IntelHex()
|
|
|
|
for start, end in ihex.segments():
|
|
|
|
if start >= 0x090000000:
|
|
|
|
continue
|
|
|
|
aligned_start = start & ~align_mask
|
|
|
|
if start != aligned_start:
|
|
|
|
message_func("Aligning start from 0x%x to 0x%x" % (start, aligned_start))
|
|
|
|
alignments.frombytes(ihex.tobinarray(aligned_start, start - 1), aligned_start)
|
|
|
|
aligned_end = end & ~align_mask
|
|
|
|
if end != aligned_end:
|
|
|
|
aligned_end += align
|
|
|
|
message_func("Aligning end from 0x%x to 0x%x" % (end, aligned_end))
|
|
|
|
alignments.frombytes(ihex.tobinarray(end, aligned_end - 1), end)
|
|
|
|
ihex.merge(alignments)
|
|
|
|
|
|
|
|
def merge_images(hexf0, hexf1=None):
|
|
|
|
ihex = IntelHex()
|
|
|
|
ihex.padding = 0x00
|
|
|
|
ihex.loadfile(hexf0, "hex")
|
|
|
|
if hexf1 is not None:
|
|
|
|
# get chip ID from metadata and compare
|
|
|
|
ihex1 = IntelHex(hexf1)
|
|
|
|
type0 = ihex.tobinarray(start=0x90500002, size=4)
|
|
|
|
type1 = ihex1.tobinarray(start=0x90500002, size=4)
|
|
|
|
if type0 != type1:
|
|
|
|
raise HookError(
|
|
|
|
"Incompatible processor type: %s in '%s' and 0x%s in '%s'"
|
|
|
|
% (hexf0, type0, hexf1, type1))
|
|
|
|
ihex.merge(ihex1, 'ignore')
|
|
|
|
return ihex
|
|
|
|
|
|
|
|
def complete_func(message_func, elf0, hexf0, hexf1=None, dest=None):
|
|
|
|
message_func("Postprocessing %s -> %s" % (elf0, hexf0))
|
|
|
|
ihex = merge_images(hexf0, hexf1)
|
|
|
|
patch(message_func, ihex, hexf0)
|
|
|
|
ihex.write_hex_file(dest if dest else hexf0, write_start_addr=False, byte_count=64)
|
|
|
|
|
2018-10-25 17:48:41 +00:00
|
|
|
# Find Cortex M0 image.
|
|
|
|
def find_cm0_image(toolchain, resources, elf, hexf):
|
|
|
|
# Locate user-specified image
|
|
|
|
from tools.resources import FileType
|
|
|
|
hex_files = resources.get_file_paths(FileType.HEX)
|
2018-12-06 07:16:49 +00:00
|
|
|
m0hexf = next((f for f in hex_files if os.path.basename(f) == toolchain.target.m0_core_img), None)
|
2018-12-04 13:21:10 +00:00
|
|
|
if toolchain.target.name.endswith('_PSA'):
|
2018-12-06 07:16:49 +00:00
|
|
|
m0hexf = next((f for f in hex_files if os.path.basename(f) == os.path.basename(hexf)), m0hexf)
|
2018-10-22 12:10:10 +00:00
|
|
|
|
|
|
|
if m0hexf:
|
2018-12-06 07:16:49 +00:00
|
|
|
toolchain.notify.debug("M0 core image file found: %s." % os.path.basename(m0hexf))
|
2018-10-22 12:10:10 +00:00
|
|
|
else:
|
2018-10-25 17:48:41 +00:00
|
|
|
toolchain.notify.debug("M0 core hex image file %s not found. Aborting." % toolchain.target.m0_core_img)
|
|
|
|
raise ConfigException("Required M0 core hex image not found.")
|
2018-10-22 12:10:10 +00:00
|
|
|
|
2018-10-25 17:48:41 +00:00
|
|
|
return m0hexf
|
2018-10-22 12:10:10 +00:00
|
|
|
|
|
|
|
def complete(toolchain, elf0, hexf0, hexf1=None):
|
|
|
|
complete_func(toolchain.notify.debug, elf0, hexf0, hexf1)
|