Simple Mbed Cloud client application using features of K64 & K66 including Ethernet and SD Card

Fork of mbed-cloud-example_K64_K66 by Mac Lobdell

DEPRECATED

This example application is not maintained and not recommended. It uses an old version of Mbed OS, Pelion DM, and Arm toolchain. It doesn't work with Mbed Studio.

Please use: https://os.mbed.com/teams/mbed-os-examples/code/mbed-os-example-pelion/

Committer:
MarceloSalazar
Date:
Tue Feb 13 10:07:23 2018 +0000
Revision:
0:e13a8a944e25
First version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MarceloSalazar 0:e13a8a944e25 1 #!/usr/bin/env python
MarceloSalazar 0:e13a8a944e25 2
MarceloSalazar 0:e13a8a944e25 3 ## ----------------------------------------------------------------------------
MarceloSalazar 0:e13a8a944e25 4 ## Copyright 2016-2017 ARM Ltd.
MarceloSalazar 0:e13a8a944e25 5 ##
MarceloSalazar 0:e13a8a944e25 6 ## SPDX-License-Identifier: Apache-2.0
MarceloSalazar 0:e13a8a944e25 7 ##
MarceloSalazar 0:e13a8a944e25 8 ## Licensed under the Apache License, Version 2.0 (the "License");
MarceloSalazar 0:e13a8a944e25 9 ## you may not use this file except in compliance with the License.
MarceloSalazar 0:e13a8a944e25 10 ## You may obtain a copy of the License at
MarceloSalazar 0:e13a8a944e25 11 ##
MarceloSalazar 0:e13a8a944e25 12 ## http://www.apache.org/licenses/LICENSE-2.0
MarceloSalazar 0:e13a8a944e25 13 ##
MarceloSalazar 0:e13a8a944e25 14 ## Unless required by applicable law or agreed to in writing, software
MarceloSalazar 0:e13a8a944e25 15 ## distributed under the License is distributed on an "AS IS" BASIS,
MarceloSalazar 0:e13a8a944e25 16 ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
MarceloSalazar 0:e13a8a944e25 17 ## See the License for the specific language governing permissions and
MarceloSalazar 0:e13a8a944e25 18 ## limitations under the License.
MarceloSalazar 0:e13a8a944e25 19 ## ----------------------------------------------------------------------------
MarceloSalazar 0:e13a8a944e25 20
MarceloSalazar 0:e13a8a944e25 21 from os import path
MarceloSalazar 0:e13a8a944e25 22 import json
MarceloSalazar 0:e13a8a944e25 23 import hashlib, zlib, struct
MarceloSalazar 0:e13a8a944e25 24 import time
MarceloSalazar 0:e13a8a944e25 25 import sys
MarceloSalazar 0:e13a8a944e25 26
MarceloSalazar 0:e13a8a944e25 27 '''
MarceloSalazar 0:e13a8a944e25 28 define FIRMWARE_HEADER_MAGIC 0x5a51b3d4UL
MarceloSalazar 0:e13a8a944e25 29 define FIRMWARE_HEADER_VERSION 2
MarceloSalazar 0:e13a8a944e25 30 define ARM_UC_SHA512_SIZE (512/8)
MarceloSalazar 0:e13a8a944e25 31 define ARM_UC_GUID_SIZE (128/8)
MarceloSalazar 0:e13a8a944e25 32 typedef struct _arm_uc_internal_header_t
MarceloSalazar 0:e13a8a944e25 33 {
MarceloSalazar 0:e13a8a944e25 34 /* Metadata-header specific magic code */
MarceloSalazar 0:e13a8a944e25 35 uint32_t headerMagic;
MarceloSalazar 0:e13a8a944e25 36
MarceloSalazar 0:e13a8a944e25 37 /* Revision number for metadata header. */
MarceloSalazar 0:e13a8a944e25 38 uint32_t headerVersion;
MarceloSalazar 0:e13a8a944e25 39
MarceloSalazar 0:e13a8a944e25 40 /* Version number accompanying the firmware. Larger numbers imply more
MarceloSalazar 0:e13a8a944e25 41 recent and preferred versions. This is used for determining the
MarceloSalazar 0:e13a8a944e25 42 selection order when multiple versions are available. For downloaded
MarceloSalazar 0:e13a8a944e25 43 firmware the manifest timestamp is used as the firmware version.
MarceloSalazar 0:e13a8a944e25 44 */
MarceloSalazar 0:e13a8a944e25 45 uint64_t firmwareVersion;
MarceloSalazar 0:e13a8a944e25 46
MarceloSalazar 0:e13a8a944e25 47 /* Total space (in bytes) occupied by the firmware BLOB. */
MarceloSalazar 0:e13a8a944e25 48 uint64_t firmwareSize;
MarceloSalazar 0:e13a8a944e25 49
MarceloSalazar 0:e13a8a944e25 50 /* Firmware hash calculated over the firmware size. Should match the hash
MarceloSalazar 0:e13a8a944e25 51 generated by standard command line tools, e.g., shasum on Linux/Mac.
MarceloSalazar 0:e13a8a944e25 52 */
MarceloSalazar 0:e13a8a944e25 53 uint8_t firmwareHash[ARM_UC_SHA512_SIZE];
MarceloSalazar 0:e13a8a944e25 54
MarceloSalazar 0:e13a8a944e25 55 /* The ID for the update campaign that resulted in the firmware update.
MarceloSalazar 0:e13a8a944e25 56 */
MarceloSalazar 0:e13a8a944e25 57 uint8_t campaign[ARM_UC_GUID_SIZE];
MarceloSalazar 0:e13a8a944e25 58
MarceloSalazar 0:e13a8a944e25 59 /* Size of the firmware signature. Must be 0 if no signature is supplied. */
MarceloSalazar 0:e13a8a944e25 60 uint32_t firmwareSignatureSize;
MarceloSalazar 0:e13a8a944e25 61
MarceloSalazar 0:e13a8a944e25 62 /* Header 32 bit CRC. Calculated over the entire header, including the CRC
MarceloSalazar 0:e13a8a944e25 63 field, but with the CRC set to zero.
MarceloSalazar 0:e13a8a944e25 64 */
MarceloSalazar 0:e13a8a944e25 65 uint32_t headerCRC;
MarceloSalazar 0:e13a8a944e25 66
MarceloSalazar 0:e13a8a944e25 67 /* Optional firmware signature. Hashing algorithm should be the same as the
MarceloSalazar 0:e13a8a944e25 68 one used for the firmware hash. The firmwareSignatureSize must be set.
MarceloSalazar 0:e13a8a944e25 69 */
MarceloSalazar 0:e13a8a944e25 70 uint8_t firmwareSignature[0];
MarceloSalazar 0:e13a8a944e25 71 } arm_uc_internal_header_t;
MarceloSalazar 0:e13a8a944e25 72 '''
MarceloSalazar 0:e13a8a944e25 73
MarceloSalazar 0:e13a8a944e25 74 # define defaults to go into the metadata header
MarceloSalazar 0:e13a8a944e25 75 SIZEOF_SHA512 = int(512/8)
MarceloSalazar 0:e13a8a944e25 76 SIZEOF_GUID = int(128/8)
MarceloSalazar 0:e13a8a944e25 77 FIRMWARE_HEADER_MAGIC = 0x5a51b3d4
MarceloSalazar 0:e13a8a944e25 78 FIRMWARE_HEADER_VERSION = 2
MarceloSalazar 0:e13a8a944e25 79 header_format = ">2I2Q{}s{}s2I".format(SIZEOF_SHA512, SIZEOF_GUID)
MarceloSalazar 0:e13a8a944e25 80
MarceloSalazar 0:e13a8a944e25 81 if sys.version_info < (3,):
MarceloSalazar 0:e13a8a944e25 82 def b(x):
MarceloSalazar 0:e13a8a944e25 83 return bytearray(x)
MarceloSalazar 0:e13a8a944e25 84 else:
MarceloSalazar 0:e13a8a944e25 85 def b(x):
MarceloSalazar 0:e13a8a944e25 86 return x
MarceloSalazar 0:e13a8a944e25 87
MarceloSalazar 0:e13a8a944e25 88 def create_header(app_blob, firmwareVersion):
MarceloSalazar 0:e13a8a944e25 89 # calculate the hash of the application
MarceloSalazar 0:e13a8a944e25 90 firmwareHash = hashlib.sha256(app_blob).digest()
MarceloSalazar 0:e13a8a944e25 91
MarceloSalazar 0:e13a8a944e25 92 # calculate the total size which is defined as the application size + metadata header
MarceloSalazar 0:e13a8a944e25 93 firmwareSize = len(app_blob)
MarceloSalazar 0:e13a8a944e25 94
MarceloSalazar 0:e13a8a944e25 95 # set campaign GUID to 0
MarceloSalazar 0:e13a8a944e25 96 campaign = b'\00'
MarceloSalazar 0:e13a8a944e25 97
MarceloSalazar 0:e13a8a944e25 98 # signature not supported, set size to 0
MarceloSalazar 0:e13a8a944e25 99 signatureSize = 0
MarceloSalazar 0:e13a8a944e25 100
MarceloSalazar 0:e13a8a944e25 101 print ('imageSize: {}'.format(firmwareSize))
MarceloSalazar 0:e13a8a944e25 102 print ('imageHash: {}'.format(''.join(['{:0>2x}'.format(c) for c in b(firmwareHash)])))
MarceloSalazar 0:e13a8a944e25 103 print ('imageversion: {}'.format(firmwareVersion))
MarceloSalazar 0:e13a8a944e25 104
MarceloSalazar 0:e13a8a944e25 105 # construct struct for CRC calculation
MarceloSalazar 0:e13a8a944e25 106 headerCRC = 0
MarceloSalazar 0:e13a8a944e25 107 FirmwareHeader = struct.pack(header_format,
MarceloSalazar 0:e13a8a944e25 108 FIRMWARE_HEADER_MAGIC,
MarceloSalazar 0:e13a8a944e25 109 FIRMWARE_HEADER_VERSION,
MarceloSalazar 0:e13a8a944e25 110 firmwareVersion,
MarceloSalazar 0:e13a8a944e25 111 firmwareSize,
MarceloSalazar 0:e13a8a944e25 112 firmwareHash,
MarceloSalazar 0:e13a8a944e25 113 campaign,
MarceloSalazar 0:e13a8a944e25 114 signatureSize,
MarceloSalazar 0:e13a8a944e25 115 headerCRC)
MarceloSalazar 0:e13a8a944e25 116
MarceloSalazar 0:e13a8a944e25 117 # calculate checksum over header, including signatureSize but without headerCRC
MarceloSalazar 0:e13a8a944e25 118 headerCRC = zlib.crc32(FirmwareHeader[:-4]) & 0xffffffff
MarceloSalazar 0:e13a8a944e25 119
MarceloSalazar 0:e13a8a944e25 120 # Pack the data into a binary blob
MarceloSalazar 0:e13a8a944e25 121 FirmwareHeader = struct.pack(header_format,
MarceloSalazar 0:e13a8a944e25 122 FIRMWARE_HEADER_MAGIC,
MarceloSalazar 0:e13a8a944e25 123 FIRMWARE_HEADER_VERSION,
MarceloSalazar 0:e13a8a944e25 124 firmwareVersion,
MarceloSalazar 0:e13a8a944e25 125 firmwareSize,
MarceloSalazar 0:e13a8a944e25 126 firmwareHash,
MarceloSalazar 0:e13a8a944e25 127 campaign,
MarceloSalazar 0:e13a8a944e25 128 signatureSize,
MarceloSalazar 0:e13a8a944e25 129 headerCRC)
MarceloSalazar 0:e13a8a944e25 130
MarceloSalazar 0:e13a8a944e25 131 return FirmwareHeader
MarceloSalazar 0:e13a8a944e25 132
MarceloSalazar 0:e13a8a944e25 133
MarceloSalazar 0:e13a8a944e25 134 def combine(bootloader_blob, app_blob, app_offset, hdr_offset, output, version):
MarceloSalazar 0:e13a8a944e25 135
MarceloSalazar 0:e13a8a944e25 136 # create header to go with the application binary
MarceloSalazar 0:e13a8a944e25 137 FirmwareHeader = create_header(app_blob, version)
MarceloSalazar 0:e13a8a944e25 138
MarceloSalazar 0:e13a8a944e25 139 # write the bootloader first
MarceloSalazar 0:e13a8a944e25 140 offset = 0
MarceloSalazar 0:e13a8a944e25 141 output.write(bootloader_blob)
MarceloSalazar 0:e13a8a944e25 142 offset += len(bootloader_blob)
MarceloSalazar 0:e13a8a944e25 143
MarceloSalazar 0:e13a8a944e25 144 # write the padding between bootloader and firmware header
MarceloSalazar 0:e13a8a944e25 145 output.write(b'\00' * (hdr_offset - offset))
MarceloSalazar 0:e13a8a944e25 146 offset += (hdr_offset - offset)
MarceloSalazar 0:e13a8a944e25 147
MarceloSalazar 0:e13a8a944e25 148 # write firmware header
MarceloSalazar 0:e13a8a944e25 149 output.write(FirmwareHeader)
MarceloSalazar 0:e13a8a944e25 150 offset += len(FirmwareHeader)
MarceloSalazar 0:e13a8a944e25 151
MarceloSalazar 0:e13a8a944e25 152 # write padding between header and application
MarceloSalazar 0:e13a8a944e25 153 output.write(b'\00' * (app_offset - offset))
MarceloSalazar 0:e13a8a944e25 154
MarceloSalazar 0:e13a8a944e25 155 # write the application
MarceloSalazar 0:e13a8a944e25 156 output.write(app_blob)
MarceloSalazar 0:e13a8a944e25 157
MarceloSalazar 0:e13a8a944e25 158
MarceloSalazar 0:e13a8a944e25 159 if __name__ == '__main__':
MarceloSalazar 0:e13a8a944e25 160 import argparse
MarceloSalazar 0:e13a8a944e25 161
MarceloSalazar 0:e13a8a944e25 162 parser = argparse.ArgumentParser(
MarceloSalazar 0:e13a8a944e25 163 description='Combine bootloader with application adding metadata header.')
MarceloSalazar 0:e13a8a944e25 164
MarceloSalazar 0:e13a8a944e25 165 def offset_arg(s):
MarceloSalazar 0:e13a8a944e25 166 if s.startswith('0x'):
MarceloSalazar 0:e13a8a944e25 167 return int(s, 16)
MarceloSalazar 0:e13a8a944e25 168 else:
MarceloSalazar 0:e13a8a944e25 169 return int(s)
MarceloSalazar 0:e13a8a944e25 170
MarceloSalazar 0:e13a8a944e25 171 bin_map = {
MarceloSalazar 0:e13a8a944e25 172 'k64f': {
MarceloSalazar 0:e13a8a944e25 173 'mem_start': '0x0'
MarceloSalazar 0:e13a8a944e25 174 },
MarceloSalazar 0:e13a8a944e25 175 'ublox_evk_odin_w2': {
MarceloSalazar 0:e13a8a944e25 176 'mem_start': '0x08000000'
MarceloSalazar 0:e13a8a944e25 177 },
MarceloSalazar 0:e13a8a944e25 178 'nucleo_f429zi': {
MarceloSalazar 0:e13a8a944e25 179 'mem_start': '0x08000000'
MarceloSalazar 0:e13a8a944e25 180 }
MarceloSalazar 0:e13a8a944e25 181 }
MarceloSalazar 0:e13a8a944e25 182
MarceloSalazar 0:e13a8a944e25 183 curdir = path.dirname(path.abspath(__file__))
MarceloSalazar 0:e13a8a944e25 184
MarceloSalazar 0:e13a8a944e25 185 def parse_mbed_app_offset(mcu, key):
MarceloSalazar 0:e13a8a944e25 186 mem_start = bin_map[mcu]["mem_start"]
MarceloSalazar 0:e13a8a944e25 187 with open(path.join(curdir, "..", "mbed_app.json")) as fd:
MarceloSalazar 0:e13a8a944e25 188 mbed_json = json.load(fd)
MarceloSalazar 0:e13a8a944e25 189 offset = mbed_json["target_overrides"][mcu.upper()][key]
MarceloSalazar 0:e13a8a944e25 190 return offset_arg(offset) - offset_arg(mem_start)
MarceloSalazar 0:e13a8a944e25 191
MarceloSalazar 0:e13a8a944e25 192 # specify arguments
MarceloSalazar 0:e13a8a944e25 193 parser.add_argument('-m', '--mcu', type=lambda s : s.lower().replace("-","_"), required=False,
MarceloSalazar 0:e13a8a944e25 194 help='mcu', choices=bin_map.keys())
MarceloSalazar 0:e13a8a944e25 195 parser.add_argument('-b', '--bootloader', type=argparse.FileType('rb'), required=False,
MarceloSalazar 0:e13a8a944e25 196 help='path to the bootloader binary')
MarceloSalazar 0:e13a8a944e25 197 parser.add_argument('-a', '--app', type=argparse.FileType('rb'), required=True,
MarceloSalazar 0:e13a8a944e25 198 help='path to application binary')
MarceloSalazar 0:e13a8a944e25 199 parser.add_argument('-c', '--app-offset', type=offset_arg, required=False,
MarceloSalazar 0:e13a8a944e25 200 help='offset of the application')
MarceloSalazar 0:e13a8a944e25 201 parser.add_argument('-d', '--header-offset', type=offset_arg, required=False,
MarceloSalazar 0:e13a8a944e25 202 help='offset of the firmware metadata header')
MarceloSalazar 0:e13a8a944e25 203 parser.add_argument('-o', '--output', type=argparse.FileType('wb'), required=True,
MarceloSalazar 0:e13a8a944e25 204 help='output combined file path')
MarceloSalazar 0:e13a8a944e25 205 parser.add_argument('-s', '--set-version', type=int, required=False,
MarceloSalazar 0:e13a8a944e25 206 help='set version number', default=int(time.time()))
MarceloSalazar 0:e13a8a944e25 207
MarceloSalazar 0:e13a8a944e25 208 # workaround for http://bugs.python.org/issue9694
MarceloSalazar 0:e13a8a944e25 209 parser._optionals.title = "arguments"
MarceloSalazar 0:e13a8a944e25 210
MarceloSalazar 0:e13a8a944e25 211 # get and validate arguments
MarceloSalazar 0:e13a8a944e25 212 args = parser.parse_args()
MarceloSalazar 0:e13a8a944e25 213
MarceloSalazar 0:e13a8a944e25 214 if(not (args.mcu or args.bootloader)):
MarceloSalazar 0:e13a8a944e25 215 print("Please specify bootloader location or MCU")
MarceloSalazar 0:e13a8a944e25 216 exit(-1)
MarceloSalazar 0:e13a8a944e25 217
MarceloSalazar 0:e13a8a944e25 218 fname = ''
MarceloSalazar 0:e13a8a944e25 219 if args.mcu:
MarceloSalazar 0:e13a8a944e25 220 fname = path.join(curdir, 'mbed-bootloader-' + args.mcu.replace('_', '-')+'.bin')
MarceloSalazar 0:e13a8a944e25 221 if not path.exists(fname):
MarceloSalazar 0:e13a8a944e25 222 print("Specified MCU does not have a binary in this location")
MarceloSalazar 0:e13a8a944e25 223 exit(-1)
MarceloSalazar 0:e13a8a944e25 224
MarceloSalazar 0:e13a8a944e25 225 # Use specified bootloader or default if none is provided
MarceloSalazar 0:e13a8a944e25 226 bootloader = args.bootloader or open(fname, 'rb')
MarceloSalazar 0:e13a8a944e25 227
MarceloSalazar 0:e13a8a944e25 228 # read the contents of bootloader and application binaries into buffers
MarceloSalazar 0:e13a8a944e25 229 bootloader_blob = bootloader.read()
MarceloSalazar 0:e13a8a944e25 230 bootloader.close()
MarceloSalazar 0:e13a8a944e25 231 app_blob = args.app.read()
MarceloSalazar 0:e13a8a944e25 232 args.app.close()
MarceloSalazar 0:e13a8a944e25 233
MarceloSalazar 0:e13a8a944e25 234 # Use specified offsets or default if none are provided
MarceloSalazar 0:e13a8a944e25 235 if(not (args.mcu or args.app_offset)):
MarceloSalazar 0:e13a8a944e25 236 print("Please specify app offset or MCU")
MarceloSalazar 0:e13a8a944e25 237 exit(-1)
MarceloSalazar 0:e13a8a944e25 238 app_offset = args.app_offset or parse_mbed_app_offset(args.mcu, "target.mbed_app_start")
MarceloSalazar 0:e13a8a944e25 239
MarceloSalazar 0:e13a8a944e25 240 if(not (args.mcu or args.header_offset)):
MarceloSalazar 0:e13a8a944e25 241 print("Please specify header offset or MCU")
MarceloSalazar 0:e13a8a944e25 242 exit(-1)
MarceloSalazar 0:e13a8a944e25 243 header_offset = args.header_offset or parse_mbed_app_offset(args.mcu, "update-client.application-details")
MarceloSalazar 0:e13a8a944e25 244
MarceloSalazar 0:e13a8a944e25 245 # combine application and bootloader adding metadata info
MarceloSalazar 0:e13a8a944e25 246 combine(bootloader_blob, app_blob, app_offset, header_offset, args.output, args.set_version)
MarceloSalazar 0:e13a8a944e25 247
MarceloSalazar 0:e13a8a944e25 248 # close output file
MarceloSalazar 0:e13a8a944e25 249 output_fn = path.abspath(args.output.name)
MarceloSalazar 0:e13a8a944e25 250 args.output.close()
MarceloSalazar 0:e13a8a944e25 251
MarceloSalazar 0:e13a8a944e25 252 # print the output file path
MarceloSalazar 0:e13a8a944e25 253 print('Combined binary:' + output_fn)