Mbed Cloud Connect for Ethernet Platforms
Fork of example-Ethernet-mbed-Cloud-connect by
tools/combine_bootloader_with_app.py@12:ca4ab5d7e52b, 2018-06-04 (annotated)
- Committer:
- davwal04@E108444.Emea.Arm.com
- Date:
- Mon Jun 04 17:03:57 2018 +0100
- Branch:
- update-1.3.0
- Revision:
- 12:ca4ab5d7e52b
- Parent:
- 6:2d0e0866f2e7
Fixed SOTP address
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 1 | #!/usr/bin/env python |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 2 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 3 | ## ---------------------------------------------------------------------------- |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 4 | ## Copyright 2016-2017 ARM Ltd. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 5 | ## |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 6 | ## SPDX-License-Identifier: Apache-2.0 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 7 | ## |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 8 | ## Licensed under the Apache License, Version 2.0 (the "License"); |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 9 | ## you may not use this file except in compliance with the License. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 10 | ## You may obtain a copy of the License at |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 11 | ## |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 12 | ## http://www.apache.org/licenses/LICENSE-2.0 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 13 | ## |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 14 | ## Unless required by applicable law or agreed to in writing, software |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 15 | ## distributed under the License is distributed on an "AS IS" BASIS, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 16 | ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 17 | ## See the License for the specific language governing permissions and |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 18 | ## limitations under the License. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 19 | ## ---------------------------------------------------------------------------- |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 20 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 21 | from os import path |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 22 | import json |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 23 | import hashlib, zlib, struct |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 24 | import time |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 25 | import sys |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 26 | from intelhex import IntelHex |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 27 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 28 | ''' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 29 | define FIRMWARE_HEADER_MAGIC 0x5a51b3d4UL |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 30 | define FIRMWARE_HEADER_VERSION 2 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 31 | define ARM_UC_SHA512_SIZE (512/8) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 32 | define ARM_UC_GUID_SIZE (128/8) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 33 | typedef struct _arm_uc_internal_header_t |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 34 | { |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 35 | /* Metadata-header specific magic code */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 36 | uint32_t headerMagic; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 37 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 38 | /* Revision number for metadata header. */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 39 | uint32_t headerVersion; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 40 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 41 | /* Version number accompanying the firmware. Larger numbers imply more |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 42 | recent and preferred versions. This is used for determining the |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 43 | selection order when multiple versions are available. For downloaded |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 44 | firmware the manifest timestamp is used as the firmware version. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 45 | */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 46 | uint64_t firmwareVersion; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 47 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 48 | /* Total space (in bytes) occupied by the firmware BLOB. */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 49 | uint64_t firmwareSize; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 50 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 51 | /* Firmware hash calculated over the firmware size. Should match the hash |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 52 | generated by standard command line tools, e.g., shasum on Linux/Mac. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 53 | */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 54 | uint8_t firmwareHash[ARM_UC_SHA512_SIZE]; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 55 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 56 | /* The ID for the update campaign that resulted in the firmware update. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 57 | */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 58 | uint8_t campaign[ARM_UC_GUID_SIZE]; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 59 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 60 | /* Size of the firmware signature. Must be 0 if no signature is supplied. */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 61 | uint32_t firmwareSignatureSize; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 62 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 63 | /* Header 32 bit CRC. Calculated over the entire header, including the CRC |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 64 | field, but with the CRC set to zero. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 65 | */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 66 | uint32_t headerCRC; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 67 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 68 | /* Optional firmware signature. Hashing algorithm should be the same as the |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 69 | one used for the firmware hash. The firmwareSignatureSize must be set. |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 70 | */ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 71 | uint8_t firmwareSignature[0]; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 72 | } arm_uc_internal_header_t; |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 73 | ''' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 74 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 75 | # define defaults to go into the metadata header |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 76 | SIZEOF_SHA512 = int(512/8) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 77 | SIZEOF_GUID = int(128/8) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 78 | FIRMWARE_HEADER_MAGIC = 0x5a51b3d4 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 79 | FIRMWARE_HEADER_VERSION = 2 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 80 | header_format = ">2I2Q{}s{}s2I".format(SIZEOF_SHA512, SIZEOF_GUID) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 81 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 82 | if sys.version_info < (3,): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 83 | def b(x): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 84 | return bytearray(x) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 85 | else: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 86 | def b(x): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 87 | return x |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 88 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 89 | def create_header(app_blob, firmwareVersion): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 90 | # calculate the hash of the application |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 91 | firmwareHash = hashlib.sha256(app_blob).digest() |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 92 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 93 | # calculate the total size which is defined as the application size + metadata header |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 94 | firmwareSize = len(app_blob) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 95 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 96 | # set campaign GUID to 0 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 97 | campaign = b'\00' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 98 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 99 | # signature not supported, set size to 0 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 100 | signatureSize = 0 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 101 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 102 | print ('imageSize: {}'.format(firmwareSize)) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 103 | print ('imageHash: {}'.format(''.join(['{:0>2x}'.format(c) for c in b(firmwareHash)]))) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 104 | print ('imageversion: {}'.format(firmwareVersion)) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 105 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 106 | # construct struct for CRC calculation |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 107 | headerCRC = 0 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 108 | FirmwareHeader = struct.pack(header_format, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 109 | FIRMWARE_HEADER_MAGIC, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 110 | FIRMWARE_HEADER_VERSION, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 111 | firmwareVersion, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 112 | firmwareSize, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 113 | firmwareHash, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 114 | campaign, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 115 | signatureSize, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 116 | headerCRC) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 117 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 118 | # calculate checksum over header, including signatureSize but without headerCRC |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 119 | headerCRC = zlib.crc32(FirmwareHeader[:-4]) & 0xffffffff |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 120 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 121 | # Pack the data into a binary blob |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 122 | FirmwareHeader = struct.pack(header_format, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 123 | FIRMWARE_HEADER_MAGIC, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 124 | FIRMWARE_HEADER_VERSION, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 125 | firmwareVersion, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 126 | firmwareSize, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 127 | firmwareHash, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 128 | campaign, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 129 | signatureSize, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 130 | headerCRC) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 131 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 132 | return FirmwareHeader |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 133 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 134 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 135 | def combine(bootloader_fn, app_fn, app_addr, hdr_addr, bootloader_addr, output_fn, version, no_bootloader): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 136 | ih = IntelHex() |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 137 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 138 | bootloader_format = bootloader_fn.split('.')[-1] |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 139 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 140 | # write the bootloader |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 141 | if not no_bootloader: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 142 | print("Using bootloader %s" % bootloader_fn) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 143 | if bootloader_format == 'hex': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 144 | print("Loading bootloader from hex file.") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 145 | ih.fromfile(bootloader_fn, format=bootloader_format) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 146 | elif bootloader_format == 'bin': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 147 | print("Loading bootloader to address 0x%08x." % bootloader_addr) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 148 | ih.loadbin(bootloader_fn, offset=bootloader_addr) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 149 | else: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 150 | print('Bootloader format can only be .bin or .hex') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 151 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 152 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 153 | # write firmware header |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 154 | app_format=app_fn.split('.')[-1] |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 155 | if app_format == 'bin': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 156 | with open(app_fn, 'rb') as fd: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 157 | app_blob = fd.read() |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 158 | elif app_format == 'hex': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 159 | application = IntelHex(app_fn) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 160 | app_blob = application.tobinstr() |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 161 | FirmwareHeader = create_header(app_blob, version) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 162 | print("Writing header to address 0x%08x." % hdr_addr) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 163 | ih.puts(hdr_addr, FirmwareHeader) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 164 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 165 | # write the application |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 166 | if app_format == 'bin': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 167 | print("Loading application to address 0x%08x." % app_addr) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 168 | ih.loadbin(app_fn, offset=app_addr) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 169 | elif app_format == 'hex': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 170 | print("Loading application from hex file") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 171 | ih.fromfile(app_fn, format=app_format) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 172 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 173 | # output to file |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 174 | ih.tofile(output_fn, format=output_fn.split('.')[-1]) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 175 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 176 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 177 | if __name__ == '__main__': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 178 | from glob import glob |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 179 | import argparse |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 180 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 181 | parser = argparse.ArgumentParser( |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 182 | description='Combine bootloader with application adding metadata header.') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 183 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 184 | def addr_arg(s): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 185 | if not isinstance(s, int): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 186 | s = eval(s) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 187 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 188 | return s |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 189 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 190 | bin_map = { |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 191 | 'k64f': { |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 192 | 'mem_start': '0x0' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 193 | }, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 194 | 'ublox_evk_odin_w2': { |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 195 | 'mem_start': '0x08000000' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 196 | }, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 197 | 'nucleo_f429zi': { |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 198 | 'mem_start': '0x08000000' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 199 | } |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 200 | } |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 201 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 202 | curdir = path.dirname(path.abspath(__file__)) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 203 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 204 | def parse_mbed_app_addr(mcu, key): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 205 | mem_start = bin_map[mcu]["mem_start"] |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 206 | with open(path.join(curdir, "..", "mbed_app.json")) as fd: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 207 | mbed_json = json.load(fd) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 208 | addr = mbed_json["target_overrides"][mcu.upper()][key] |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 209 | return addr_arg(addr) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 210 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 211 | # specify arguments |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 212 | parser.add_argument('-m', '--mcu', type=lambda s : s.lower().replace("-","_"), required=False, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 213 | help='mcu', choices=bin_map.keys()) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 214 | parser.add_argument('-b', '--bootloader', type=argparse.FileType('rb'), required=False, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 215 | help='path to the bootloader binary') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 216 | parser.add_argument('-a', '--app', type=argparse.FileType('rb'), required=True, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 217 | help='path to application binary') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 218 | parser.add_argument('-c', '--app-addr', type=addr_arg, required=False, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 219 | help='address of the application') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 220 | parser.add_argument('-d', '--header-addr', type=addr_arg, required=False, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 221 | help='address of the firmware metadata header') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 222 | parser.add_argument('-o', '--output', type=argparse.FileType('wb'), required=True, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 223 | help='output combined file path') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 224 | parser.add_argument('-s', '--set-version', type=int, required=False, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 225 | help='set version number', default=int(time.time())) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 226 | parser.add_argument('-nb', '--no-bootloader',action='store_true', required=False, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 227 | help='Produce output without bootloader. The output only '+ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 228 | 'contains header + app. requires hex output format') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 229 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 230 | # workaround for http://bugs.python.org/issue9694 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 231 | parser._optionals.title = "arguments" |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 232 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 233 | # get and validate arguments |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 234 | args = parser.parse_args() |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 235 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 236 | # validate the output format |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 237 | f = args.output.name.split('.')[-1] |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 238 | if f == 'hex': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 239 | output_format = 'hex' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 240 | elif f == 'bin': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 241 | output_format = 'bin' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 242 | else: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 243 | print('Output format can only be .bin or .hex') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 244 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 245 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 246 | # validate no-bootloader option |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 247 | if args.no_bootloader and output_format == 'bin': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 248 | print('--no-bootloader option requires the output format to be .hex') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 249 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 250 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 251 | # validate that we can find a bootloader or no_bootloader is specified |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 252 | bootloader = None |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 253 | if not args.no_bootloader: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 254 | if args.mcu and not args.bootloader: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 255 | bl_list = glob("tools/mbed-bootloader-{}-*".format(args.mcu)) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 256 | if len(bl_list) == 0: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 257 | print("Specified MCU does not have a binary in this location " + \ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 258 | "Please specify bootloader location with -b") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 259 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 260 | elif len(bl_list) > 1: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 261 | print("Specified MCU have more than one binary in this location " + \ |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 262 | "Please specify bootloader location with -b") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 263 | print(bl_list) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 264 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 265 | else: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 266 | fname = bl_list[0] |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 267 | bootloader = open(fname, 'rb') |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 268 | elif args.bootloader: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 269 | bootloader = args.bootloader |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 270 | elif not (args.mcu or args.bootloader): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 271 | print("Please specify bootloader location -b or MCU -m") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 272 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 273 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 274 | # get the path of bootloader, application and output |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 275 | if bootloader: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 276 | bootloader_fn = path.abspath(bootloader.name) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 277 | bootloader.close() |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 278 | else: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 279 | bootloader_fn = '' |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 280 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 281 | if bootloader_fn.split('.')[-1] != 'hex' and not args.mcu: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 282 | print("Please provide a bootloader in hex format or specify MCU -m") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 283 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 284 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 285 | app_fn = path.abspath(args.app.name) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 286 | args.app.close() |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 287 | output_fn = path.abspath(args.output.name) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 288 | args.output.close() |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 289 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 290 | # Use specified addresses or default if none are provided |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 291 | app_format = app_fn.split('.')[-1] |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 292 | if(not (args.mcu or args.app_addr or app_format == 'hex')): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 293 | print("Please specify app address or MCU") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 294 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 295 | if app_format != 'hex': |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 296 | app_addr = args.app_addr or parse_mbed_app_addr(args.mcu, "target.mbed_app_start") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 297 | else: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 298 | app_addr = None |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 299 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 300 | if args.mcu: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 301 | mem_start = addr_arg(bin_map[args.mcu]["mem_start"]) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 302 | else: |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 303 | mem_start = 0 |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 304 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 305 | if(not (args.mcu or args.header_addr)): |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 306 | print("Please specify header address or MCU") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 307 | exit(-1) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 308 | header_addr = args.header_addr or parse_mbed_app_addr(args.mcu, "update-client.application-details") |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 309 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 310 | # combine application and bootloader adding metadata info |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 311 | combine(bootloader_fn, app_fn, app_addr, header_addr, mem_start, |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 312 | output_fn, args.set_version, args.no_bootloader) |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 313 | |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 314 | # print the output file path |
davwal04@E108444.Emea.Arm.com | 6:2d0e0866f2e7 | 315 | print('Combined binary:' + output_fn) |