Example #1
0
    def dumpV2(self, all):
        start_address = 0x3ff2 if all else 0x37f8
        cmd_verif = [0xa6, 0, 0, 0, 0, 0, 0, 0]
        cmd_verif[1] = 5 + 8
        # find block of 8 0xFF at the end of the device memory
        block = [0xff] * 8
        found = False
        data = [d ^ self.scrambleCodeV2[i % 8] for i, d in enumerate(block)]
        for address in range(start_address, -1, -1):
            print('Looking for 0xFF block at address 0x{:04X}'.format(
                address), end='\n')
            cmd_verif[3:5] = address & 0xFF, (address >> 8) & 0xFF
            r, _ = self.cmd_verify_v2(bin_str_of_list(cmd_verif + data))
            if r == 0:
                print('\nFound 0xFF block at address 0x{:04X}'.format(address))
                found = True
                break
        if not found:
            print('\nUnable to find 0xFF block')
            return
        memdump = IntelHex()
        memdump.puts(address, bin_str_of_list(block))

        print('Starting flash dumping')
        for i in reversed(block):
            print('{:02X} '.format(i), end='')
        sys.stdout.flush()

        nTry = 0
        nBytes = 0
        for address in range(address - 1, -1, -1):
            block[1:] = block[:-1]  # shift
            cmd_verif[3:5] = address & 0xFF, (address >> 8) & 0xFF
            found = False
            for i in range(256):
                val = stats[i]
                block[0] = val
                nTry += 1
                data = [d ^ self.scrambleCodeV2[i % 8]
                        for i, d in enumerate(block)]
                r, _ = self.cmd_verify_v2(bin_str_of_list(cmd_verif + data),9)
                if r == 0:  # verification ok, we found the correct byte
                    print('{:02X} '.format(val), end='')
                    sys.stdout.flush()
                    found = True
                    nBytes += 1
                    memdump[address] = val
                    break
            if not found:
                raise ValueError('Unable to find correct '
                                 'byte for address 0x{:04X}'.format(address))

        output_bin = 'out.bin'
        output_hex = 'out.hex'
        print('\nDone, writing output files {} and {}'.format(output_bin,
                                                              output_hex))
        print('Ntry = {} {:.2f}try/bytes'.format(nTry, float(nTry) / nBytes))
        memdump.tobinfile(output_bin)
        memdump.tofile(output_hex, format='hex')
Example #2
0
    def post_process(self):
        logging.info("Processing binaries")
        
        # save original dir
        cwd = os.getcwd()

        # change to target dir
        os.chdir(self.target_dir)

        ih = IntelHex('main.hex')
        
        fwid = uuid.UUID('{' + self.settings["FWID"] + '}')
        
        size = ih.maxaddr() - ih.minaddr() + 1
        
        # get os info
        os_project = get_project_builder(self.settings["OS_PROJECT"])

        # create firmware info structure
        fw_info = struct.pack('<I16s128s16s128s16s', 
                                size, 
                                fwid.bytes, 
                                os_project.proj_name, 
                                os_project.version, 
                                self.proj_name,
                                self.version)
        
        # insert fw info into hex
        ih.puts(0x120, fw_info)

        # compute crc
        crc_func = crcmod.predefined.mkCrcFun('crc-aug-ccitt')

        crc = crc_func(ih.tobinstr())

        logging.info("size: %d" % (size))
        logging.info("fwid: %s" % (fwid))
        logging.info("crc: 0x%x" % (crc))
        logging.info("os name: %s" % (os_project.proj_name))
        logging.info("os version: %s" % (os_project.version))
        logging.info("app name: %s" % (self.proj_name))
        logging.info("app version: %s" % (self.version))

        ih.puts(ih.maxaddr() + 1, struct.pack('>H', crc))

        ih.write_hex_file('main.hex')
        ih.tobinfile('firmware.bin')
        
        # get loader info
        loader_project = get_project_builder(self.settings["LOADER_PROJECT"])

        # create loader image
        loader_hex = os.path.join(loader_project.target_dir, "main.hex")
        self.merge_hex('main.hex', loader_hex, 'loader_image.hex')
        
        # change back to original dir
        os.chdir(cwd)
Example #3
0
 def tofile(self, outfile: Union[str, IO]) -> None:
     ih = IntelHex()
     ih.puts(self.base or 0, bytes(self.fw))
     if Firmware._ishex(outfile):
         if not isinstance(outfile, str):
             outfile = io.TextIOWrapper(outfile)
         ih.write_hex_file(outfile)
     else:
         ih.tobinfile(outfile)
Example #4
0
    def dump(self):
        end_address = 0x3ff0
        # send the key
        b = '\xa6\x04' + struct.pack('BBBB', *scrambleCode)
        self.xcmd(b, 0)
        # find block of 16 0xFF at the end of the device memory
        block = [0xff] * 16
        found = False
        for address in range(end_address, -1, -1):
            print('\rLooking for address 0x{:04X}'.format(address), end='')
            r = self.cmd('\xa7\16' + struct.pack('<H', address) +
                         bin_str_of_list(scramble(block)))
            if r == 0:
                print('\nFound 0xFF block at address 0x{:04X}'.format(address))
                found = True
                break
        if not found:
            print('\nUnable to find 0xFF block')
            return

        memdump = IntelHex()
        memdump.puts(address, bin_str_of_list(block))
  
        print('Starting flash dumping')
        base = [0xa7, 16, 0, 0]
        nTry = 0
        nBytes = 0
        for address in range(address - 1, - 1, -1):
            block[1:] = block[:-1]  # shift
            base[2:4] = address & 0xFF, address >> 8
            found = False
            for i in range(256):
                i = stats[i]
                block[0] = i
                nTry += 1
                r = self.cmd(bin_str_of_list(base + scramble(block)), 4)
                if r == 0:  # verification ok, we found the correct byte
                    print('{:02X} '.format(i), end='')
                    sys.stdout.flush()
                    found = True
                    nBytes += 1
                    memdump[address] = i
                    break
            if not found:
                raise ValueError('Unable to find correct '
                                 'byte for address 0x{:04X}'.format(address))

        output_bin = 'out.bin'
        output_hex = 'out.hex'
        print('\nDone, writing output files {} and {}'.format(output_bin,
                                                              output_hex))
        print('Ntry = {} {:.2f}try/bytes'.format(nTry, float(nTry) / nBytes))
        memdump.tobinfile(output_bin)
        memdump.tofile(output_hex, format='hex')
Example #5
0
    def build_target_firmware(self, parent_test):
        """
        Build test firmware for the board

        Login credentials must have been set with set_build_login.
        """
        prebuilt = self._target_dir is not None
        build_login = (self._username is not None and
                       self._password is not None)
        assert prebuilt or build_login
        if prebuilt:
            destdir = self._target_dir
        else:
            destdir = 'tmp'
        build_name = board_id_to_build_target[self.get_board_id()]
        name_base = os.path.normpath(destdir + os.sep + build_name)
        self._target_hex_path = name_base + '.hex'
        self._target_bin_path = name_base + '.bin'
        # Build target test image if a prebuild location is not specified
        if not prebuilt:
            test_info = parent_test.create_subtest('build_target_test_firmware')
            if not os.path.isdir(destdir):
                os.mkdir(destdir)
            # Remove previous build files
            if os.path.isfile(self._target_hex_path):
                os.remove(self._target_hex_path)
            if os.path.isfile(self._target_bin_path):
                os.remove(self._target_bin_path)
            test_info.info('Starting remote build')
            start = time.time()
            built_file = mbedapi.build_repo(self._username, self._password,
                                            TEST_REPO, build_name, destdir)
            stop = time.time()
            test_info.info("Build took %s seconds" % (stop - start))
            extension = os.path.splitext(built_file)[1].lower()
            assert extension == '.hex' or extension == '.bin'
            if extension == '.hex':
                intel_hex = IntelHex(built_file)
                # Only supporting devices with the starting
                # address at 0 currently
                assert intel_hex.minaddr() == 0
                intel_hex.tobinfile(self._target_bin_path)
                os.rename(built_file, self._target_hex_path)
            if extension == '.bin':
                intel_hex = IntelHex()
                intel_hex.loadbin(built_file, offset=0)
                intel_hex.tofile(self._target_hex_path, 'hex')
                os.rename(built_file, self._target_bin_path)
        # Assert that required files are present
        assert os.path.isfile(self._target_hex_path)
        assert os.path.isfile(self._target_bin_path)
        self._target_firmware_present = True
    def program(self, args):
        board = self._setup()
        board.flash.init()

        tmp_bin_file = 'tmp.bin'

        if args.sectorsanduicrerase:
            self._erase_uicr(board.target) # TODO: May not be needed if pyOCD does this. Double check before removing.

        hex_file = IntelHex(args.file)
        hex_file.tobinfile(tmp_bin_file)
        board.flash.flashBinary(tmp_bin_file, chip_erase=args.eraseall, fast_verify=args.verify)

        if args.debugreset or args.pinreset or args.systemreset:
            board.target.reset()

        os.remove(tmp_bin_file)
Example #7
0
def build_target_bundle(directory, username, password, parent_test=None):
    """Build target firmware package"""
    if parent_test is None:
        parent_test = TestInfoStub()
    target_names = info.TARGET_NAME_TO_BOARD_ID.keys()
    for build_name in target_names:
        name_base = os.path.normpath(directory + os.sep + build_name)
        target_hex_path = name_base + '.hex'
        target_bin_path = name_base + '.bin'

        # Build target test image
        test_info = parent_test.create_subtest('Building target %s' %
                                               build_name)
        if not os.path.isdir(directory):
            os.mkdir(directory)
        # Remove previous build files
        if os.path.isfile(target_hex_path):
            os.remove(target_hex_path)
        if os.path.isfile(target_bin_path):
            os.remove(target_bin_path)
        test_info.info('Starting remote build')
        start = time.time()
        built_file = mbedapi.build_repo(username, password,
                                        TEST_REPO, build_name,
                                        directory)
        stop = time.time()
        test_info.info("Build took %s seconds" % (stop - start))
        extension = os.path.splitext(built_file)[1].lower()
        assert extension == '.hex' or extension == '.bin'
        if extension == '.hex':
            intel_hex = IntelHex(built_file)
            # Only supporting devices with the starting
            # address at 0 currently
            assert intel_hex.minaddr() == 0
            intel_hex.tobinfile(target_bin_path)
            os.rename(built_file, target_hex_path)
        if extension == '.bin':
            intel_hex = IntelHex()
            intel_hex.loadbin(built_file, offset=0)
            intel_hex.tofile(target_hex_path, 'hex')
            os.rename(built_file, target_bin_path)

        # Assert that required files are present
        assert os.path.isfile(target_hex_path)
        assert os.path.isfile(target_bin_path)
Example #8
0
def build_target_bundle(directory, username, password, parent_test=None):
    """Build target firmware package"""
    if parent_test is None:
        parent_test = TestInfoStub()
    target_names = info.TARGET_WITH_COMPILE_API_LIST
    for build_name in target_names:
        name_base = os.path.normpath(directory + os.sep + build_name)
        target_hex_path = name_base + '.hex'
        target_bin_path = name_base + '.bin'

        # Build target test image
        test_info = parent_test.create_subtest('Building target %s' %
                                               build_name)
        if not os.path.isdir(directory):
            os.mkdir(directory)
        # Remove previous build files
        if os.path.isfile(target_hex_path):
            os.remove(target_hex_path)
        if os.path.isfile(target_bin_path):
            os.remove(target_bin_path)
        test_info.info('Starting remote build')
        start = time.time()
        built_file = mbedapi.build_repo(username, password,
                                        TEST_REPO, build_name,
                                        directory)
        stop = time.time()
        test_info.info("Build took %s seconds" % (stop - start))
        extension = os.path.splitext(built_file)[1].lower()
        assert extension == '.hex' or extension == '.bin'
        if extension == '.hex':
            intel_hex = IntelHex(built_file)
            # Only supporting devices with the starting
            # address at 0 currently
            assert intel_hex.minaddr() == 0
            intel_hex.tobinfile(target_bin_path)
            os.rename(built_file, target_hex_path)
        if extension == '.bin':
            intel_hex = IntelHex()
            intel_hex.loadbin(built_file, offset=0)
            intel_hex.tofile(target_hex_path, 'hex')
            os.rename(built_file, target_bin_path)

        # Assert that required files are present
        assert os.path.isfile(target_hex_path)
        assert os.path.isfile(target_bin_path)
Example #9
0
def separate():

    softdeviceDir = os.getcwd() + r'/softdevice/'

    if not os.path.exists(softdeviceDir):
        print u'创建softdevice文件夹'
        os.mkdir(softdeviceDir)

    # softdeviceFileDir, softdeviceFileName = os.path.split(config.SOFTDEVICE_FILE)
    # softdeviceFileName, softdeviceFileExt = os.path.splitext(softdeviceFileName)

    # mianFileName = softdeviceDir + softdeviceFileName + '_main.bin'
    # uicrFileName = softdeviceDir + softdeviceFileName + '_uicr.bin'

    mianFileName = softdeviceDir + 'softdevice_main.bin'
    uicrFileName = softdeviceDir + 'softdevice_uicr.bin'

    softdeviceFile = IntelHex(config.SOFTDEVICE_FILE)

    softdeviceFile.tobinfile(fobj=mianFileName, start=0, size=80*1024)
    softdeviceFile.tobinfile(fobj=uicrFileName, start=0x10001000, size=0x20)
Example #10
0
    def program(self, args):
        board = self._setup()
        board.flash.init()

        tmp_bin_file = 'tmp.bin'

        if args.sectorsanduicrerase:
            # TODO: May not be needed if pyOCD does this. Double check before
            # removing.
            self._erase_uicr(board.target)

        hex_file = IntelHex(args.file)
        hex_file.tobinfile(tmp_bin_file)
        board.flash.flashBinary(
            tmp_bin_file,
            chip_erase=args.eraseall,
            fast_verify=args.verify)

        if args.debugreset or args.pinreset or args.systemreset:
            board.target.reset()

        os.remove(tmp_bin_file)
Example #11
0
from intelhex import IntelHex

ih = IntelHex()
ih.padding = 0
ih.fromfile("sbos.hex", format="hex")
start = ih.segments()[0][0]
ih.tobinfile("sbos.bin", start=start, size=8192)
Example #12
0
                    help="output file name",
                    default="output.bin")
args = parser.parse_args()

if not args.input:
    print("Input file must be specified")

if os.path.exists(args.output):
    try:
        os.path.delete(args.output)
    except FileError as e:
        print("File error ({0}): {1}".format(e.errno, e.strerror))
    except:
        print("Filesystem Error!")

try:
    if (os.path.exists(args.input) == False):
        errorHandler("Application file missing!")

    filename, file_ext = os.path.splitext(args.input)
    #convert hex to bin
    if file_ext == ".hex":
        print("Convert HEX to Binary: " + args.input)
        ih = IntelHex(args.input)
        ih.tobinfile(args.output)
    else:
        print("File is not HEX type; aborting!")
except FileError as e:
    print("File error ({0}): {1}".format(e.errno, e.strerror))
except:
    errorHandler("Filesystem Error!")
Example #13
0
def dump_header(infile, image, header):
    inhex = IntelHex(infile)
    (start, end) = inhex.segments()[0]
    inhex.tobinfile(image, start=start, end=end - 1)
    (start, end) = inhex.segments()[-1]
    inhex.tobinfile(header, start=start, end=end - 1)
Example #14
0
class PartitionCreator:
    """
    Class to create nrfconnect partition containing FactoryData

    :param offset: This is a partition offset where data will be stored in device's flash memory
    :param length: This is a maximum partition size
    :param input: This is a path to input JSON file
    :param output: This is a path to output directory

    """
    def __init__(self, offset: int, length: int, input: str,
                 output: str) -> None:
        self._ih = IntelHex()
        self._length = length
        self._offset = offset
        self._data_ready = False
        self._output = output
        self._input = input
        try:
            self.__data_to_save = self._convert_to_dict(self._load_json())
        except IOError:
            sys.exit(-1)

    def generate_cbor(self):
        """
        Generates .cbor file using cbor2 library.
        It generate a CBORTag 55799 which is user-specific tag

        """
        if self.__data_to_save:
            # prepare raw data from Json
            cbor_data = cbor.dumps(self.__data_to_save)
            return cbor_data

    def create_hex(self, data: bytes):
        """
        Creates .hex file from CBOR.
        This file can be write directly to device.

        """
        if len(data) > self._length:
            raise ValueError(
                "generated CBOR file exceeds declared maximum partition size! {} > {}"
                .format(len(data), self._length))
        self._ih.putsz(self._offset, data)
        self._ih.write_hex_file(self._output + ".hex", True)
        self._data_ready = True
        return True

    def create_bin(self):
        """
        Creates raw binary data of created previously .hex file

        """
        if not self._data_ready:
            log.error("Please create hex file first!")
            return False
        self._ih.tobinfile(self._output + ".bin")
        return True

    @staticmethod
    def _convert_to_dict(data):
        """
        Converts a list containing tuples ("key_name", "key_value") to a dictionary

        If "key_value" of data entry is a string-type variable and contains a HEX_PREFIX algorithm decodes it 
        to hex format to be sure that a cbor file will contain proper bytes.

        If "key_value" of data entry is a dictionary, algorithm appends it to the created dictionary.
        """
        output_dict = dict()
        for entry in data:
            if not isinstance(entry, dict):
                log.debug("Processing entry {}".format(entry))
                if isinstance(data[entry],
                              str) and data[entry].startswith(HEX_PREFIX):
                    output_dict[entry] = codecs.decode(
                        data[entry][len(HEX_PREFIX):], "hex")
                elif isinstance(data[entry], str):
                    output_dict[entry] = data[entry].encode("utf-8")
                else:
                    output_dict[entry] = data[entry]
            else:
                output_dict[entry] = entry
        return output_dict

    def _load_json(self):
        """
        Loads file containing a JSON data and converts it to JSON format

        :raises IOError: if provided JSON file can not be read out.
        """
        try:
            with open(self._input, "rb") as json_file:
                return json.loads(json_file.read())
        except IOError as e:
            log.error("Can not read Json file {}".format(self._input))
            raise e
Example #15
0
def m2354_tfm_bin(t_self, non_secure_image, secure_bin):

    assert os.path.isfile(secure_bin)
    assert os.path.isfile(non_secure_image)

    secure_bin = abspath(secure_bin)
    non_secure_image = abspath(non_secure_image)

    build_dir = dirname(non_secure_image)
    tempdir = path_join(build_dir, 'temp')
    if not isdir(tempdir):
        os.makedirs(tempdir)

    flash_layout = path_join(SECURE_ROOT, 'partition', 'flash_layout.h')

    bl2_bin = path_join(SECURE_ROOT, 'bl2.bin')
    s_bin_basename = splitext(basename(secure_bin))[0]
    ns_bin_basename, output_ext = splitext(basename(non_secure_image))

    # Convert NS image to BIN format if it is HEX
    if output_ext == ".hex":
        non_secure_bin = abspath(path_join(tempdir, ns_bin_basename + ".bin"))
        ns_ih = IntelHex(non_secure_image)
        ns_ih.tobinfile(non_secure_bin)
    else:
        non_secure_bin = non_secure_image

    signing_key = path_join(SCRIPT_DIR, 'nuvoton_m2354-root-rsa-3072.pem')
    assert os.path.isfile(signing_key)

    # Find Python 3 command name across platforms
    python3_cmd = "python3" if shutil.which(
        "python3") is not None else "python"

    # Specify image version
    #
    # MCUboot image version format: Major.Minor.Revision+Build
    #
    # Requirements for image version:
    # 1. Major.Minor.Revision must be non-decremental when used to derive security
    #    counter (-s 'auto').
    # 2. Make Major.Minor.Revision+Build incremental to identify the firmware
    #    itself uniquely through psa_fwu_query().
    # 3. Get around MCUboot failure with:
    #    [INF] Starting bootloader
    #    [INF] Swap type: none
    #    [ERR] Failed to add Image 0 data to shared memory area
    #    [ERR] Unable to find bootable image
    #    This is because TF-M underestimates MAX_BOOT_RECORD_SZ for boot record
    #    where Major.Minor.Revision will pack into during signing. The more digits
    #    of the Major.Minor.Revision, the larger the needed boot record size. And
    #    then MCUboot errors in boot_save_boot_status().
    #
    # To meet all the above requirements, we apply the following policy:
    # 1. To not change MAX_BOOT_RECORD_SZ in TF-M, specify Major.Minor.Revision
    #    with TF-M version instead of modified Unix timestamp. This needs less digits to
    #    fit into MAX_BOOT_RECORD_SZ.
    # 2. To make Major.Minor.Revision+Build incremental, specify the Build part with
    #    modified Unix timestamp.
    # 3. To make security counter non-decremental, we can derive it from
    #    Major.Minor.Revision (-s 'auto') or explicitly specify it with modified
    #    Unix timestamp, depending on security consideration.
    #
    # NOTE: To get around Y2038 problem, we modify Unix timestamp by setting new base
    #       point. Using 32-bit unsigned integer to hold the modified Unix timestamp,
    #       it will break (wrap around) after Y2156 (2106 + 2020 - 1970).
    #       https://en.wikipedia.org/wiki/Year_2038_problem
    #
    modified_timestamp = int(datetime.now().timestamp()) - int(
        datetime(2020, 1, 1).timestamp())
    img_ver_major = 1  # Instead of (modified_timestamp >> 24) & 0xFF
    img_ver_minor = 4  # Instead of (modified_timestamp >> 16) & 0xFF
    img_ver_revision = 0  # Instead of modified_timestamp & 0xFFFF
    img_ver_build = modified_timestamp

    # wrapper.py command template
    cmd_wrapper = [
        python3_cmd,
        path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils",
                  "wrapper.py"),
        "-v",
        "{}.{}.{}+{}".format(img_ver_major, img_ver_minor, img_ver_revision,
                             img_ver_build),
        "-k",
        "SIGNING_KEY_PATH",
        "--layout",
        "IMAGE_MACRO_PATH",
        "--public-key-format",
        'full',
        "--align",
        '1',
        # Reasons for removing padding and boot magic option "--pad":
        # 1. PSA FWU API psa_fwu_install() will be responsible for writing boot magic to enable upgradeable.
        # 2. The image size gets smaller instead of slot size.
        #"--pad",
        "--pad-header",
        "-H",
        '0x400',
        "--overwrite-only",
        "-s",
        'auto',  # Or modified_timestamp
        "-d",
        '(IMAGE_ID,MAJOR.MINOR.REVISION+BUILD)',
        "RAW_BIN_PATH",
        "SIGNED_BIN_PATH",
    ]
    pos_wrapper_signing_key = cmd_wrapper.index("-k") + 1
    pos_wrapper_layout = cmd_wrapper.index("--layout") + 1
    pos_wrapper_dependency = cmd_wrapper.index("-d") + 1
    pos_wrapper_raw_bin = len(cmd_wrapper) - 2
    pos_wrapper_signed_bin = len(cmd_wrapper) - 1

    # assemble.py command template
    cmd_assemble = [
        python3_cmd,
        path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils",
                  "assemble.py"),
        "--layout",
        "IMAGE_MACRO_PATH",
        "-s",
        "SECURE_BIN_PATH",
        "-n",
        "NONSECURE_BIN_PATH",
        "-o",
        "CONCATENATED_BIN_PATH",
    ]
    pos_assemble_layout = cmd_assemble.index("--layout") + 1
    pos_assemble_secure_bin = cmd_assemble.index("-s") + 1
    pos_assemble_nonsecure_bin = cmd_assemble.index("-n") + 1
    pos_assemble_concat_bin = cmd_assemble.index("-o") + 1

    # If second signing key is passed down, go signing separately; otherwise, go signing together.
    if os.path.isfile(
            path_join(SECURE_ROOT, 'partition',
                      'signing_layout_ns_preprocessed.h')):
        signing_key_1 = 'nuvoton_m2354-root-rsa-3072_1.pem'
    else:
        signing_key_1 = None

    if signing_key_1 is not None:
        signing_key_1 = path_join(SCRIPT_DIR, signing_key_1)
        assert os.path.isfile(signing_key_1)

        image_macros_s = path_join(SECURE_ROOT, 'partition',
                                   'signing_layout_s_preprocessed.h')
        image_macros_ns = path_join(SECURE_ROOT, 'partition',
                                    'signing_layout_ns_preprocessed.h')
        assert os.path.isfile(image_macros_s)
        assert os.path.isfile(image_macros_ns)

        s_signed_bin = abspath(path_join(tempdir, 'tfm_s_signed' + '.bin'))
        ns_signed_bin = abspath(
            path_join(tempdir, 'tfm_' + ns_bin_basename + '_signed' + '.bin'))
        signed_concat_bin = abspath(
            path_join(
                tempdir,
                'tfm_s_signed_' + ns_bin_basename + '_signed_concat' + '.bin'))
        s_update_bin = abspath(
            path_join(build_dir, s_bin_basename + '_update' + '.bin'))
        ns_update_bin = abspath(
            path_join(build_dir, ns_bin_basename + '_update' + '.bin'))

        #1. Run wrapper to sign the secure TF-M binary
        cmd_wrapper[pos_wrapper_signing_key] = signing_key
        cmd_wrapper[pos_wrapper_layout] = image_macros_s
        cmd_wrapper[
            pos_wrapper_dependency] = '(1,0.0.0+0)'  # Minimum version of non-secure image required for upgrading to the secure image
        cmd_wrapper[pos_wrapper_raw_bin] = secure_bin
        cmd_wrapper[pos_wrapper_signed_bin] = s_signed_bin

        retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to sign " + "TF-M Secure" +
                            " binary, Error code: " + str(retcode))
            return

        #2. Run wrapper to sign the non-secure mbed binary
        cmd_wrapper[pos_wrapper_signing_key] = signing_key_1
        cmd_wrapper[pos_wrapper_layout] = image_macros_ns
        cmd_wrapper[
            pos_wrapper_dependency] = '(0,0.0.0+0)'  # Minimum version of secure image required for upgrading to the non-secure image
        cmd_wrapper[pos_wrapper_raw_bin] = non_secure_bin
        cmd_wrapper[pos_wrapper_signed_bin] = ns_signed_bin

        retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to sign " + "TF-M Secure" +
                            " binary, Error code: " + str(retcode))
            return

        #3. Concatenate signed secure TF-M binary and signed non-secure mbed binary
        cmd_assemble[pos_assemble_layout] = image_macros_s
        cmd_assemble[pos_assemble_secure_bin] = s_signed_bin
        cmd_assemble[pos_assemble_nonsecure_bin] = ns_signed_bin
        cmd_assemble[pos_assemble_concat_bin] = signed_concat_bin

        retcode = run_cmd(cmd_assemble, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to concatenate " +
                            "Secure TF-M (signed)/Non-secure Mbed (signed)" +
                            " binaries, Error code: " + str(retcode))
            return

        #4. Concatenate MCUboot and concatenated signed secure TF-M binary/signed non-secure mbed binary
        flash_area_0_offset = find_flash_area_0_offset(flash_layout)
        out_ih = IntelHex()
        out_ih.loadbin(bl2_bin)
        out_ih.loadbin(signed_concat_bin, flash_area_0_offset)
        out_ih.tofile(non_secure_image,
                      'hex' if output_ext == ".hex" else "bin")

        # Generate firmware update file for PSA Firmware Update
        shutil.copy(s_signed_bin, s_update_bin)
        shutil.copy(ns_signed_bin, ns_update_bin)
    else:
        image_macros_s_ns = path_join(SECURE_ROOT, 'partition',
                                      'signing_layout_preprocessed.h')
        assert os.path.isfile(image_macros_s_ns)

        concat_bin = abspath(
            path_join(tempdir, 'tfm_s_' + ns_bin_basename + ".bin"))
        concat_signed_bin = abspath(
            path_join(tempdir,
                      'tfm_s_' + ns_bin_basename + '_signed' + ".bin"))
        update_bin = abspath(
            path_join(build_dir, ns_bin_basename + '_update' + '.bin'))

        #1. Concatenate secure TFM and non-secure mbed binaries
        cmd_assemble[pos_assemble_layout] = image_macros_s_ns
        cmd_assemble[pos_assemble_secure_bin] = secure_bin
        cmd_assemble[pos_assemble_nonsecure_bin] = non_secure_bin
        cmd_assemble[pos_assemble_concat_bin] = concat_bin

        retcode = run_cmd(cmd_assemble, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to concatenate " +
                            "Secure TF-M/Non-secure Mbed" +
                            " binaries, Error code: " + str(retcode))
            return

        #2. Run wrapper to sign the concatenated binary
        cmd_wrapper[pos_wrapper_signing_key] = signing_key
        cmd_wrapper[pos_wrapper_layout] = image_macros_s_ns
        cmd_wrapper[
            pos_wrapper_dependency] = '(1,0.0.0+0)'  # No effect for single image boot
        cmd_wrapper[pos_wrapper_raw_bin] = concat_bin
        cmd_wrapper[pos_wrapper_signed_bin] = concat_signed_bin

        retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to sign " + "concatenated" +
                            " binary, Error code: " + str(retcode))
            return

        #3. Concatenate MCUboot and signed binary
        flash_area_0_offset = find_flash_area_0_offset(flash_layout)
        out_ih = IntelHex()
        out_ih.loadbin(bl2_bin)
        out_ih.loadbin(concat_signed_bin, flash_area_0_offset)
        out_ih.tofile(non_secure_image,
                      'hex' if output_ext == ".hex" else "bin")

        # Generate firmware update file for PSA Firmware Update
        shutil.copy(concat_signed_bin, update_bin)
Example #16
0
def main():
    parser = argparse.ArgumentParser(
        "Create the flash data for a queercon 14 badge.")

    # 0x000000 - reserved
    # 0x001000 - first ID in here
    # 0x002000 - main conf in here
    # 0x003000 - boot anim here
    # 0x004000 - tiles live in here
    # 0x008000 - backup conf here
    # 0x009000 - second ID copy here
    # 0x00a000 - icons live in here
    # 0x010000 - frames live here
    # 0x200000 - end of memory (real)

    parser.add_argument(
        '--workaround',
        action='store_true',
        help=
        "Work around the issue where we cannot use odd numbered pages. Note that this must be paired with using the `skipodd` versions of the flash functions on the badge."
    )
    parser.add_argument('--boot-addr',
                        type=int,
                        default=0x003000,
                        help="Address of the boot animation struct")
    parser.add_argument('--poof-addr',
                        type=int,
                        default=0x004000,
                        help="Address of the boot animation struct")
    parser.add_argument('--tile-addr',
                        type=int,
                        default=0x005000,
                        help="Address of the tile animation buffer")
    parser.add_argument('--game-addr',
                        type=int,
                        default=0x00a000,
                        help="Address of the game animation struct")
    parser.add_argument('--frame-addr',
                        type=int,
                        default=0x010000,
                        help='Starting offset for animation frames')
    parser.add_argument('--id-addr',
                        type=int,
                        default=0x001000,
                        help="Address of the badge ID.")
    parser.add_argument('--id-addr2',
                        type=int,
                        default=0x009000,
                        help="Address of the badge ID.")

    parser.add_argument('-o',
                        '--hexpath',
                        action='store',
                        type=str,
                        default='a.bin',
                        help='Output file path')
    parser.add_argument('-d',
                        '--frame-delay',
                        type=int,
                        default=30,
                        help="Default frame delay for animations")
    parser.add_argument('-n',
                        '--handle',
                        action='store',
                        type=str,
                        default='Human')
    parser.add_argument('id', type=int, action='store', default=1)

    args = parser.parse_args()

    flash = IntelHex()
    all_frames = []
    curr_frame_index = 0
    tile_animations = []  # This is a bit sequence
    game_animations = []  # This is a bit sequence (not nested)

    put_bytes_at(flash, 0, [0xaa], args.workaround)

    # OK. The badge will handle the main and backup confs.
    # All we need along those lines is to give it the ID.
    put_bytes_at(flash, args.id_addr, map(ord, struct.pack('<H', args.id)),
                 args.workaround)
    put_bytes_at(flash, args.id_addr2, map(ord, struct.pack('<H', args.id)),
                 args.workaround)

    # Load up the boot animation
    imgs = image_list_from_directory('_badge_graphics/bootup')
    boot_anim = anim_struct_bytes(
        0, len(imgs),
        get_frame_delay('_badge_graphics/bootup', args.frame_delay))
    put_bytes_at(flash, args.boot_addr, boot_anim, args.workaround)

    all_frames += imgs

    imgs = image_list_from_directory('_badge_graphics/poof')
    poof_anim = anim_struct_bytes(
        len(all_frames), len(imgs),
        get_frame_delay('_badge_graphics/poof', args.frame_delay))
    put_bytes_at(flash, args.poof_addr, poof_anim, args.workaround)

    all_frames += imgs

    # Load up the tile animations

    assert os.path.isdir('_badge_graphics/tiles')  # TODO: Demeter
    for dirname in os.listdir('_badge_graphics/tiles'):
        dpath = os.path.join('_badge_graphics/tiles', dirname)
        if not os.path.isdir(dpath): continue
        # Each of these corresponds to a tile.
        imgs = image_list_from_directory(dpath)
        tile_animations += anim_struct_bytes(
            len(all_frames),  # starting index
            len(imgs),  # length
            get_frame_delay(dpath, args.frame_delay)  # delay
        )
        all_frames += imgs

    put_bytes_at(flash, args.tile_addr, tile_animations, args.workaround)

    # Load up the game icons
    # These are a little different. They look, for now, like:
    # typedef struct {
    # uint16_t mate_icon_id;
    # uint16_t result_icon_id;
    # uint16_t arm_anim_id;
    # uint8_t sufficient_flag;
    # uint8_t other_arm_id;
    # } mate_spec_t;

    # typedef struct {
    # uint16_t id;
    # screen_anim_t animation;
    # mate_spec_t arms[4];
    # } game_icon_t;

    icon_connections = make_game.get_icons()

    icon_id = 0

    assert os.path.isdir('_badge_graphics/game')  # TODO: Demeter
    for dirname in os.listdir('_badge_graphics/game'):
        dpath = os.path.join('_badge_graphics/game', dirname)
        if not os.path.isdir(dpath): continue
        # Each of these corresponds to an icon.
        imgs = image_list_from_directory(dpath)
        game_animations += icon_struct_bytes(
            icon_id,
            anim_struct_bytes(
                len(all_frames),  # starting index
                len(imgs),  # length
                get_frame_delay(dpath,
                                args.frame_delay)  # delay # TODO: Demeter
            ),
            icon_connections[icon_id])
        all_frames += imgs
        icon_id += 1

    put_bytes_at(flash, args.game_addr, game_animations, args.workaround)

    # OK, so now we've got the animation structs for the boot-up,
    #  game, and tiles all loaded up. Now we just need to add
    #  all the actual frames.

    # This part's pretty easy, actually.
    flattened_frames = reduce(lambda a, b: a + b, map(bmp_bytes, all_frames))
    last_byte = put_bytes_at(flash, args.frame_addr, flattened_frames,
                             args.workaround)

    if args.hexpath.endswith('.hex'):
        flash.write_hex_file(args.hexpath)
    else:
        flash.tobinfile(args.hexpath)

    print last_byte
Example #17
0
def tfm_sign_image_tgt(tfm_import_path, signing_key, non_secure_bin):

    SECURE_ROOT = abspath(tfm_import_path)

    secure_bin = path_join(SECURE_ROOT, 'tfm_s.bin') 
    assert os.path.isfile(secure_bin)

    non_secure_bin = abspath(non_secure_bin)
    assert os.path.isfile(non_secure_bin)

    build_dir = dirname(non_secure_bin)
    tempdir = path_join(build_dir, 'temp')
    if not isdir(tempdir):
        os.makedirs(tempdir)

    flash_layout = path_join(SECURE_ROOT, 'partition', 'flash_layout.h')

    bl2_bin = path_join(SECURE_ROOT, 'bl2.bin')
    image_macros_s_ns = path_join(SECURE_ROOT, 'partition', 'signing_layout_preprocessed.h')
    ns_bin_basename = splitext(basename(non_secure_bin))[0]
    concatenated_bin = abspath(path_join(tempdir, 'tfm_' + ns_bin_basename + ".bin"))
    signed_bin = abspath(path_join(tempdir, 'tfm_' + ns_bin_basename + '_signed' + ".bin"))
    signed_nopad_bin = abspath(path_join(tempdir, 'tfm_' + ns_bin_basename + '_signed_nopad' + ".bin"))

    assert os.path.isfile(image_macros_s_ns)

    signing_key = path_join(SECURE_ROOT, 'signing_key', signing_key)
    assert os.path.isfile(signing_key)

    # Find Python 3 command name across platforms
    python3_cmd = "python3" if shutil.which("python3") is not None else "python"

    #1. Concatenate secure TFM and non-secure mbed binaries
    cmd = [
        python3_cmd,
        path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils", "assemble.py"),
        "--layout",
        image_macros_s_ns,
        "-s",
        secure_bin,
        "-n",
        non_secure_bin,
        "-o",
        concatenated_bin,
    ]

    retcode = run_cmd(cmd, MBED_OS_ROOT)
    if retcode:
        raise Exception("Unable to concatenate " + "TF-M Secure/Mbed Non-secure" +
                            " binaries, Error code: " + str(retcode))
        return

    #2.1 Run wrapper to sign the concatenated binary with padding ("--pad"), so upgradeable by mcuboot
    cmd = [
        python3_cmd,
        path_join(MBED_OS_ROOT, "tools", "psa","tfm", "bin_utils", "wrapper.py"),
        "-v",
        '1.2.0',
        "-k",
        signing_key,
        "--layout",
        image_macros_s_ns,
        "--public-key-format",
        'full',
        "--align",
        '1',
        "--pad",
        "--pad-header",
        "-H",
        '0x400',
        "--overwrite-only",
        "-s",
        'auto',
        "-d",
        '(0,0.0.0+0)',
        concatenated_bin,
        signed_bin,
    ]

    retcode = run_cmd(cmd, MBED_OS_ROOT)
    if retcode:
        raise Exception("Unable to sign " + "concatenated" +
                            " binary, Error code: " + str(retcode))
        return

    #2.2. Re-run above but without padding ("--pad"), so non-upgradeable by mcuboot
    cmd.remove("--pad")
    cmd.pop()
    cmd.append(signed_nopad_bin)

    retcode = run_cmd(cmd, MBED_OS_ROOT)
    if retcode:
        raise Exception("Unable to sign " + "concatenated" +
                            " binary, Error code: " + str(retcode))
        return

    #3. Concatenate mcuboot and signed binary and overwrite mbed built bin/hex file
    flash_area_0_offset = find_flash_area_0_offset(flash_layout)
    out_ih = IntelHex()
    out_ih.loadbin(bl2_bin)
    out_ih.loadbin(signed_nopad_bin, flash_area_0_offset)
    out_ih.tofile(splitext(non_secure_bin)[0] + ".hex", 'hex')
    out_ih.tobinfile(non_secure_bin)
Example #18
0
def main():
    # Default param
    hex_path = "D:\Projects\Keil Project\WS_test_boot\MDK-ARM\WS_test_task"
    input_hex = ''
    firmware_addr = '0x8030000'
    c_file_name = 'firmware'
    bin_file = 'app.bin'
    bin_out = False

    try:
        opts, args = getopt.getopt(sys.argv[1:], 'hi:o:b',
                                   ["input=", "offset=", "bin"])
    except getopt.GetoptError as err:
        usage()  # print help information and exit:
        SystemExit(2)
    for o, a in opts:
        if o in ('-h'):
            usage()
            return
        elif o in ("-i", "--input"):
            hex_path = a
        elif o in ("-o", "--offset"):
            firmware_addr = a
        elif o in ("-b", "--bin"):
            bin_out = True
        else:
            return print("Undefined param" + o)

    # Copy hex
    hex_path = find_hex_path(hex_path)

    try:
        shutil.copy(hex_path, os.getcwd())
    except:
        print('[ERROR] : .hex path is EMPTY')
        raise SystemExit(0)

    input_hex = hex_path.split('\\')[-1]

    with open(input_hex, 'rb+') as f:
        last = get_last_line(f, -1)
        prelast = get_last_line(f, -2)
        if ':040000' in prelast:  # delete expanded addres
            pos = f.tell() - len(last) - len(prelast)
            f.seek(pos, os.SEEK_SET)
            f.truncate()
            f.write(bytes(last, "utf8"))

    # Create bin
    ih = IntelHex(input_hex)
    ih.tobinfile(bin_file)

    if os.path.isfile(c_file_name + '.h'):
        os.remove(c_file_name + '.h')

    print('[INFO]: Input HEX: ' + input_hex)
    print('[INFO]: Input bin: ' + bin_file)
    print('[INFO]: Firmware addr: ' + firmware_addr)

    create_array(bin_file, c_file_name, offset=firmware_addr)
    print('[INFO]: ' + c_file_name + '.h' + ' -- Created successful')

    if not bin_out:
        os.remove(bin_file)

    os.remove(input_hex)
Example #19
0
 def generatebin(self):
     if self.hexfilename.text() != "" and self.binfilename.text() != "":
         hex = IntelHex(self.lastfiledir + "/" + self.hexfilename.text())
         hex.tobinfile(self.lastfiledir + "/" + self.binfilename.text())
         self.statusbar.showMessage("格式转换完毕", msecs=2000)
Example #20
0
def tfm_sign_image(tfm_import_path, signing_key, signing_key_1,
                   non_secure_bin):
    SECURE_ROOT = abspath(tfm_import_path)

    secure_bin = path_join(SECURE_ROOT, 'tfm_s.bin')
    assert os.path.isfile(secure_bin)

    non_secure_bin = abspath(non_secure_bin)
    assert os.path.isfile(non_secure_bin)

    build_dir = dirname(non_secure_bin)
    tempdir = path_join(build_dir, 'temp')
    if not isdir(tempdir):
        os.makedirs(tempdir)

    flash_layout = path_join(SECURE_ROOT, 'partition', 'flash_layout.h')

    bl2_bin = path_join(SECURE_ROOT, 'bl2.bin')
    s_bin_basename = splitext(basename(secure_bin))[0]
    ns_bin_basename = splitext(basename(non_secure_bin))[0]

    signing_key = path_join(SECURE_ROOT, 'signing_key', signing_key)
    assert os.path.isfile(signing_key)

    # Find Python 3 command name across platforms
    python3_cmd = "python3" if shutil.which(
        "python3") is not None else "python"

    img_ver_major = 1
    img_ver_minor = 3
    img_ver_revision = 0
    img_ver_build = 0

    # wrapper.py command template
    cmd_wrapper = [
        python3_cmd,
        path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils",
                  "wrapper.py"),
        "-v",
        "{}.{}.{}+{}".format(img_ver_major, img_ver_minor, img_ver_revision,
                             img_ver_build),
        "-k",
        "SIGNING_KEY_PATH",
        "--layout",
        "IMAGE_MACRO_PATH",
        "--public-key-format",
        'full',
        "--align",
        '1',
        # Reasons for removing padding and boot magic option "--pad":
        # 1. PSA FWU API psa_fwu_install() will be responsible for writing boot magic to enable upgradeable.
        # 2. The image size gets smaller instead of slot size.
        #"--pad",
        "--pad-header",
        "-H",
        '0x400',
        "--overwrite-only",
        "-s",
        'auto',
        "-d",
        '(IMAGE_ID,MAJOR.MINOR.REVISION+BUILD)',
        "RAW_BIN_PATH",
        "SIGNED_BIN_PATH",
    ]
    pos_wrapper_signing_key = cmd_wrapper.index("-k") + 1
    pos_wrapper_layout = cmd_wrapper.index("--layout") + 1
    pos_wrapper_dependency = cmd_wrapper.index("-d") + 1
    pos_wrapper_raw_bin = len(cmd_wrapper) - 2
    pos_wrapper_signed_bin = len(cmd_wrapper) - 1

    # assemble.py command template
    cmd_assemble = [
        python3_cmd,
        path_join(MBED_OS_ROOT, "tools", "psa", "tfm", "bin_utils",
                  "assemble.py"),
        "--layout",
        "IMAGE_MACRO_PATH",
        "-s",
        "SECURE_BIN_PATH",
        "-n",
        "NONSECURE_BIN_PATH",
        "-o",
        "CONCATENATED_BIN_PATH",
    ]
    pos_assemble_layout = cmd_assemble.index("--layout") + 1
    pos_assemble_secure_bin = cmd_assemble.index("-s") + 1
    pos_assemble_nonsecure_bin = cmd_assemble.index("-n") + 1
    pos_assemble_concat_bin = cmd_assemble.index("-o") + 1

    # If second signing key is passed down, go signing separately; otherwise, go signing together.
    if signing_key_1 is not None:
        signing_key_1 = path_join(SECURE_ROOT, 'signing_key', signing_key_1)
        assert os.path.isfile(signing_key_1)

        image_macros_s = path_join(SECURE_ROOT, 'partition',
                                   'signing_layout_s_preprocessed.h')
        image_macros_ns = path_join(SECURE_ROOT, 'partition',
                                    'signing_layout_ns_preprocessed.h')
        assert os.path.isfile(image_macros_s)
        assert os.path.isfile(image_macros_ns)

        s_signed_bin = abspath(path_join(tempdir, 'tfm_s_signed' + '.bin'))
        ns_signed_bin = abspath(
            path_join(tempdir, 'tfm_' + ns_bin_basename + '_signed' + '.bin'))
        signed_concat_bin = abspath(
            path_join(
                tempdir,
                'tfm_s_signed_' + ns_bin_basename + '_signed_concat' + '.bin'))
        s_update_bin = abspath(
            path_join(build_dir, s_bin_basename + '_update' + '.bin'))
        ns_update_bin = abspath(
            path_join(build_dir, ns_bin_basename + '_update' + '.bin'))

        #1. Run wrapper to sign the secure TF-M binary
        cmd_wrapper[pos_wrapper_signing_key] = signing_key
        cmd_wrapper[pos_wrapper_layout] = image_macros_s
        cmd_wrapper[
            pos_wrapper_dependency] = '(1,0.0.0+0)'  # Minimum version of non-secure image required for upgrading to the secure image
        cmd_wrapper[pos_wrapper_raw_bin] = secure_bin
        cmd_wrapper[pos_wrapper_signed_bin] = s_signed_bin

        retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to sign " + "TF-M Secure" +
                            " binary, Error code: " + str(retcode))
            return

        #2. Run wrapper to sign the non-secure mbed binary
        cmd_wrapper[pos_wrapper_signing_key] = signing_key_1
        cmd_wrapper[pos_wrapper_layout] = image_macros_ns
        cmd_wrapper[
            pos_wrapper_dependency] = '(0,0.0.0+0)'  # Minimum version of secure image required for upgrading to the non-secure image
        cmd_wrapper[pos_wrapper_raw_bin] = non_secure_bin
        cmd_wrapper[pos_wrapper_signed_bin] = ns_signed_bin

        retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to sign " + "TF-M Secure" +
                            " binary, Error code: " + str(retcode))
            return

        #3. Concatenate signed secure TF-M binary and signed non-secure mbed binary
        cmd_assemble[pos_assemble_layout] = image_macros_s
        cmd_assemble[pos_assemble_secure_bin] = s_signed_bin
        cmd_assemble[pos_assemble_nonsecure_bin] = ns_signed_bin
        cmd_assemble[pos_assemble_concat_bin] = signed_concat_bin

        retcode = run_cmd(cmd_assemble, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to concatenate " +
                            "Secure TF-M (signed)/Non-secure Mbed (signed)" +
                            " binaries, Error code: " + str(retcode))
            return

        #4. Concatenate MCUboot and concatenated signed secure TF-M binary/signed non-secure mbed binary
        flash_area_0_offset = find_flash_area_0_offset(flash_layout)
        out_ih = IntelHex()
        out_ih.loadbin(bl2_bin)
        out_ih.loadbin(signed_concat_bin, flash_area_0_offset)
        out_ih.tofile(splitext(non_secure_bin)[0] + ".hex", 'hex')
        out_ih.tobinfile(non_secure_bin)

        # Generate firmware update file for PSA Firmware Update
        shutil.copy(s_signed_bin, s_update_bin)
        shutil.copy(ns_signed_bin, ns_update_bin)
    else:
        image_macros_s_ns = path_join(SECURE_ROOT, 'partition',
                                      'signing_layout_preprocessed.h')
        assert os.path.isfile(image_macros_s_ns)

        concat_bin = abspath(
            path_join(tempdir, 'tfm_s_' + ns_bin_basename + ".bin"))
        concat_signed_bin = abspath(
            path_join(tempdir,
                      'tfm_s_' + ns_bin_basename + '_signed' + ".bin"))
        update_bin = abspath(
            path_join(build_dir, ns_bin_basename + '_update' + '.bin'))

        #1. Concatenate secure TFM and non-secure mbed binaries
        cmd_assemble[pos_assemble_layout] = image_macros_s_ns
        cmd_assemble[pos_assemble_secure_bin] = secure_bin
        cmd_assemble[pos_assemble_nonsecure_bin] = non_secure_bin
        cmd_assemble[pos_assemble_concat_bin] = concat_bin

        retcode = run_cmd(cmd_assemble, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to concatenate " +
                            "Secure TF-M/Non-secure Mbed" +
                            " binaries, Error code: " + str(retcode))
            return

        #2. Run wrapper to sign the concatenated binary
        cmd_wrapper[pos_wrapper_signing_key] = signing_key
        cmd_wrapper[pos_wrapper_layout] = image_macros_s_ns
        cmd_wrapper[
            pos_wrapper_dependency] = '(1,0.0.0+0)'  # No effect for single image boot
        cmd_wrapper[pos_wrapper_raw_bin] = concat_bin
        cmd_wrapper[pos_wrapper_signed_bin] = concat_signed_bin

        retcode = run_cmd(cmd_wrapper, MBED_OS_ROOT)
        if retcode:
            raise Exception("Unable to sign " + "concatenated" +
                            " binary, Error code: " + str(retcode))
            return

        #3. Concatenate MCUboot and signed binary
        flash_area_0_offset = find_flash_area_0_offset(flash_layout)
        out_ih = IntelHex()
        out_ih.loadbin(bl2_bin)
        out_ih.loadbin(concat_signed_bin, flash_area_0_offset)
        out_ih.tofile(splitext(non_secure_bin)[0] + ".hex", 'hex')
        out_ih.tobinfile(non_secure_bin)

        # Generate firmware update file for PSA Firmware Update
        shutil.copy(concat_signed_bin, update_bin)
Example #21
0
class FWInfo:
    def __init__(self,
                 app_hex_file,
                 sd_hex_file,
                 app_version,
                 ebin_file=None,
                 aes_key=None,
                 aes_iv=None,
                 mbr_size=DEFAULT_MBR_SIZE,
                 padding=DEFAULT_PADDING):

        self.ihex = IntelHex()
        self.ihex.padding = padding & 0xff

        if sd_hex_file:
            self.ihex.merge(
                IntelHex(sd_hex_file))  # default response to overlap is error.

        if app_hex_file:
            self.ihex.merge(IntelHex(app_hex_file))
        else:
            raise OTAGeneratorError("Application hex file is required.")

        # Check for MBR overlap and find fp_base.
        start, end = self.ihex.segments()[0]  # segment 0.
        fp_base = 0
        if sd_hex_file is None:
            if start < mbr_size:
                raise OTAGeneratorError(
                    "Application overlaps with MBR {:x}.".format(mbr_size))
            else:
                fp_base = start
        else:
            if end > mbr_size:
                raise OTAGeneratorError(
                    "Integrated MBR with softdevice is "
                    " larger than given MBR size. {:x} > {:x}".format(
                        end, mbr_size))
            else:
                fp_base = self.ihex.segments()[1][
                    0]  # start address of next segment.

        # self.ihex.write_hex_file("ota.hex")
        # self.ihex.tobinfile("ota.pbin", start = fp_base)

        self.ebin_file = ebin_file

        self.fw_info = {}
        self.fw_info.setdefault('fp_base', fp_base)
        self.fw_info.setdefault('app_version', app_version)
        self.fw_info.setdefault('ebin_hash', '')
        self.fw_info.setdefault('pbin_hash', '')

        if aes_key is None:
            aes_key = os.urandom(AES_KEY_SIZE)
        else:
            aes_key = bytes.fromhex(aes_key)

        if aes_iv is None:
            aes_iv = os.urandom(AES_KEY_SIZE)
        else:
            aes_iv = bytes.fromhex(aes_iv)

        self.fw_info.setdefault('aes_key', aes_key)
        self.fw_info.setdefault('aes_iv', aes_iv)
        self.fw_info.setdefault('ebin_size', 0)
        self.fw_info.setdefault('pbin_size', 0)

        self._compute_fw_info()

    def _compute_fw_info(self):
        try:
            writer = FWInfoWriter(self.fw_info['aes_key'],
                                  self.fw_info['aes_iv'], self.ebin_file)
            self.ihex.tobinfile(writer, start=self.fw_info['fp_base'])
            writer.close()
            self.fw_info['pbin_size'] = writer.pbin_size
            self.fw_info['ebin_size'] = writer.ebin_size
            self.fw_info['ebin_hash'] = writer.ebin_hash.digest()
            self.fw_info['pbin_hash'] = writer.pbin_hash.digest()
        except Exception as e:
            raise (e)

        if self.fw_info['ebin_size'] == 0:
            raise OTAGeneratorError("No output generated.")

    def to_nrf52_hex_string(self):
        """
        Keep the struct members type, order same in C code.
        """
        """
        struct {
            unsigned long version;
            unsigned long fp_base;
            unsigned long pbin_size;
            unsigned long ebin_size;
            unsigned char aes_key[16];
            unsigned char aes_iv[16];
            unsigned char pbin_hash[32]; 
            unsigned char ebin_hash[32];
        }
        """
        fw_info_struct = struct.pack(
            "<LLLL16s16s32s32s", self.fw_info['app_version'],
            self.fw_info['fp_base'], self.fw_info['pbin_size'],
            self.fw_info['ebin_size'], self.fw_info['aes_key'],
            self.fw_info['aes_iv'], self.fw_info['pbin_hash'],
            self.fw_info['ebin_hash'])

        return fw_info_struct.hex()

    def gen_bl_settings_init_code(self, cfile):
        pbin_hash_str = ""
        for b in self.fw_info['pbin_hash']:
            pbin_hash_str += hex(b) + ','

        ebin_hash_str = ""
        for b in self.fw_info['ebin_hash']:
            ebin_hash_str += hex(b) + ','

        aes_key_str = ""
        for b in self.fw_info['aes_key']:
            aes_key_str += hex(b) + ','

        aes_iv_str = ""
        for b in self.fw_info['aes_iv']:
            aes_iv_str += hex(b) + ','

        with open(str(cfile), "w") as fobj:
            fobj.write(
                BL_SETTINGS_C_GEN.format(bl_settings_code=BL_SETTINGS_CODE,
                                         version=self.fw_info['app_version'],
                                         fp_base=self.fw_info['fp_base'],
                                         pbin_size=self.fw_info['pbin_size'],
                                         pbin_hash=pbin_hash_str,
                                         ebin_hash=ebin_hash_str,
                                         aes_key=aes_key_str,
                                         aes_iv=aes_iv_str,
                                         ebin_size=self.fw_info['ebin_size']))
Example #22
0
            import subprocess
            subprocess.check_call(
                [sys.executable, '-m', 'pip', 'install', 'intelhex', '--user'])
            from intelhex import IntelHex
        except:
            traceback.print_exc()
            print(
                "\n*** Please try manually with raised privileges: 'sudo python -m pip install intelhex'\n"
            )
            sys.exit(1)

    if len(sys.argv) >= 4:
        binfile = sys.argv[1]
        hexfile1 = sys.argv[2]
        hexfile2 = sys.argv[3]
    else:
        print('Usage: python hexfile.py outfile hexfile1 hexfile2')
        sys.exit(1)

    try:
        c7 = IntelHex(hexfile1)
        c4 = IntelHex(hexfile2)
        c7.merge(c4, overlap='ignore')
        fout = open(binfile, 'wb')
        c7.tobinfile(fout)
        fout.close()
        print('Combined image file ' + binfile + ' created')
    except:
        traceback.print_exc()
        sys.exit(1)
Example #23
0
mac = None
if args.savemac:
    mac = jlink.make_mac_bin(None, device)
else:
    mac = jlink.make_mac_bin(args.mac, None)

if args.app:
    appStr = args.app

    #get size of app and create binary file
    filename, extension = os.path.splitext(args.app)
    appSize = 0
    if extension == '.hex':
        utils.deleteIfExists('temp.bin', None)
        ih = IntelHex(args.app)
        ih.tobinfile('temp.bin')
        appSize = os.path.getsize('temp.bin')
    else:
        appSize = os.path.getsize(args.app)
    jlink.make_bl_settings_bin(appSize)
    print(appSize)
    utils.deleteIfExists('temp.bin', None)
else:
    jlink.make_bl_settings_bin(0)

#validate existence of all necessary binary files; application validated earlier in script

if cfg.softdevice.compatible == 'True':
    if not os.path.exists(softdeviceStr):
        if args.softdevice != 'none':
            utils.errorHandler(
Example #24
0
    def post_process(self):
        logging.info("Processing binaries")

        fw_info_fmt = '<I16s128s16s128s16s'

        fw_info_addr = int(self.settings["FW_INFO_ADDR"], 16)

        # save original dir
        cwd = os.getcwd()

        # change to target dir
        os.chdir(self.target_dir)

        ih = IntelHex('main.hex')

        fwid = uuid.UUID('{' + self.settings["FWID"] + '}')

        # get KV meta start
        kv_meta_addr = fw_info_addr + struct.calcsize(fw_info_fmt)
        kv_meta_len = KVMetaField().size()

        bindata = ih.tobinstr()

        kv_meta_data = []

        while True:
            kv_meta = KVMetaField().unpack(bindata[kv_meta_addr:kv_meta_addr +
                                                   kv_meta_len])

            kv_meta_addr += kv_meta_len

            if kv_meta.param_name == "kvstart":
                continue

            elif kv_meta.param_name == "kvend":
                break

            else:
                kv_meta_data.append(kv_meta)

        kv_meta_by_hash = {}

        logging.info("Hash type: FNV1A_32")

        # create lookups by 32 bit hash
        index = 0
        for kv in kv_meta_data:
            hash32 = fnv1a_32(str(kv.param_name))

            if hash32 in kv_meta_by_hash:
                raise Exception("Hash collision!")

            kv_meta_by_hash[hash32] = (kv, index)

            index += 1

        # sort indexes
        sorted_hashes = sorted(kv_meta_by_hash.keys())

        # create binary look up table
        kv_index = ''
        for a in sorted_hashes:
            kv_index += struct.pack('<LB', a, kv_meta_by_hash[a][1])

        # write to end of hex file
        ih.puts(ih.maxaddr() + 1, kv_index)

        size = ih.maxaddr() - ih.minaddr() + 1

        # get os info
        try:
            os_project = get_project_builder(self.settings["OS_PROJECT"],
                                             target=self.target_type)
        except KeyError:
            os_project = ""

        # create firmware info structure
        fw_info = struct.pack(fw_info_fmt, size, fwid.bytes,
                              os_project.proj_name, os_project.version,
                              str(self.settings['PROJ_NAME']), self.version)

        # insert fw info into hex
        ih.puts(fw_info_addr, fw_info)

        # compute crc
        crc_func = crcmod.predefined.mkCrcFun('crc-aug-ccitt')

        crc = crc_func(ih.tobinstr())

        logging.info("size: %d" % (size))
        logging.info("fwid: %s" % (fwid))
        logging.info("fwinfo: %x" % (fw_info_addr))
        logging.info("kv index len: %d" % (len(kv_index)))
        logging.info("crc: 0x%x" % (crc))
        logging.info("os name: %s" % (os_project.proj_name))
        logging.info("os version: %s" % (os_project.version))
        logging.info("app name: %s" % (self.settings['PROJ_NAME']))
        logging.info("app version: %s" % (self.version))

        ih.puts(ih.maxaddr() + 1, struct.pack('>H', crc))

        ih.write_hex_file('main.hex')
        ih.tobinfile('firmware.bin')

        # get loader info
        loader_project = get_project_builder(self.settings["LOADER_PROJECT"],
                                             target=self.target_type)

        # create loader image
        loader_hex = os.path.join(loader_project.target_dir, "main.hex")
        self.merge_hex('main.hex', loader_hex, 'loader_image.hex')

        # create sha256 of binary
        sha256 = hashlib.sha256(ih.tobinstr())

        # create manifest file
        data = {
            'name': self.settings['FULL_NAME'],
            'timestamp': datetime.utcnow().isoformat(),
            'sha256': sha256.hexdigest(),
            'fwid': self.settings['FWID'],
            'version': self.version
        }

        with open('manifest.txt', 'w+') as f:
            f.write(json.dumps(data))

        # create firmware zip file
        zf = zipfile.ZipFile('chromatron_main_fw.zip', 'w')
        zf.write('manifest.txt')
        zf.write('firmware.bin')
        zf.close()

        # create second, project specific zip
        # we'll remove the first zip after
        # we update the firmware tools
        zf = zipfile.ZipFile('%s.zip' % (self.settings['PROJ_NAME']), 'w')
        zf.write('manifest.txt')
        zf.write('firmware.bin')
        zf.close()

        # change back to original dir
        os.chdir(cwd)

        logging.info("Package dir: %s" % (get_build_package_dir()))

        # make sure we have the firmware package dir
        try:
            os.makedirs(get_build_package_dir())

        except OSError:
            pass

        # copy firmware zip
        try:
            shutil.copy(
                os.path.join(self.target_dir, '%s.zip' % (self.proj_name)),
                get_build_package_dir())

        except IOError:
            raise AppZipNotFound

        # update build date
        with open(
                os.path.join(get_build_package_dir(),
                             firmware_package.PUBLISHED_AT_FILENAME),
                'w') as f:
            f.write(util.now().isoformat())
Example #25
0
#!/usr/bin/python
import sys
from intelhex import IntelHex

basename = sys.argv[1].rsplit(".", 1)[0]
outfile = open(basename + ".rmh", 'w')
outfile_bin = open(basename + ".bin", 'wb')
ih = IntelHex(sys.argv[1])
arr = ih.tobinarray()
outfile.write("@0000\n")
for i, e in enumerate(arr):
    outfile.write("{0:02x}\n".format(e))
ih.tobinfile(outfile_bin)
Example #26
0
        line = sp.read(45)
        lines.append(line)

        if line == b":00000001FF\r\n":
            break
        if line == '':
            break

    sublines = [line.decode() for line in lines]
    return ''.join(sublines)


def usage():
    print("usage: {} <serial_port> <bootloader_filename>".format(sys.argv[0]))


# Ensure we have proper-ish arguments.
if len(sys.argv) != 3:
    usage()
    sys.exit(0)

serial_port = sys.argv[1]
out_file = sys.argv[2]

# Read the bootloader into an intel hex file...
raw_ihex = read_bootloader_ihex(sys.argv[1])

# ... and produce the output binary.
ihex = IntelHex(StringIO(raw_ihex))
ihex.tobinfile(out_file)