blob: 14ad07a103eacc0e0d407ed61c16095bb6a53c9d [file] [log] [blame]
Balint Matyi3bae8832020-06-22 15:34:12 +02001#! /usr/bin/env python3
2#
3# -----------------------------------------------------------------------------
4# Copyright (c) 2020, Arm Limited. All rights reserved.
5#
6# SPDX-License-Identifier: BSD-3-Clause
7#
8# -----------------------------------------------------------------------------
9
10import re
11import os
12import sys
13import click
14import macro_parser
15# Import the external MCUBoot repo's imgtool script
16scripts_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
17 '../../../../../mcuboot/scripts'))
18sys.path.insert(0, scripts_path)
19import imgtool
20import imgtool.main
21
22sign_bin_size_re = re.compile(r"^\s*RE_SIGN_BIN_SIZE\s*=\s*(.*)")
23load_addr_re = re.compile(r"^\s*RE_IMAGE_LOAD_ADDRESS\s*=\s*(.*)")
24
25#This works around Python 2 and Python 3 handling character encodings
26#differently. More information about this issue at
27#https://click.palletsprojects.com/en/5.x/python3
28os.environ['LC_ALL'] = 'C.UTF-8'
29os.environ['LANG'] = 'C.UTF-8'
30
31@click.argument('outfile')
32@click.argument('infile')
33@click.option('-R', '--erased-val', type=click.Choice(['0', '0xff']),
34 required=False, help='The value that is read back from erased '
35 'flash.')
36@click.option('-x', '--hex-addr', type=imgtool.main.BasedIntParamType(),
37 required=False, help='Adjust address in hex output file.')
38@click.option('--save-enctlv', default=False, is_flag=True,
39 help='When upgrading, save encrypted key TLVs instead of plain '
40 'keys. Enable when BOOT_SWAP_SAVE_ENCTLV config option '
41 'was set.')
42@click.option('-E', '--encrypt', metavar='filename',
43 help='Encrypt image using the provided public key')
44@click.option('-e', '--endian', type=click.Choice(['little', 'big']),
45 default='little', help="Select little or big endian")
46@click.option('--overwrite-only', default=False, is_flag=True,
47 help='Use overwrite-only instead of swap upgrades')
48@click.option('-M', '--max-sectors', type=int,
49 help='When padding allow for this amount of sectors (defaults '
50 'to 128)')
51@click.option('--confirm', default=False, is_flag=True,
52 help='When padding the image, mark it as confirmed')
53@click.option('--pad', default=False, is_flag=True,
54 help='Pad image to the size determined by --layout, adding '
55 'trailer magic')
56@click.option('-l', '--layout', help='The file containing the macros of the '
57 'slot sizes')
58@click.option('--pad-header', default=False, is_flag=True,
59 help='Adds --erased-val (defaults to 0xff) --header-size times '
60 'at the beginning of the image')
61@click.option('-H', '--header-size',
62 callback=imgtool.main.validate_header_size,
63 type=imgtool.main.BasedIntParamType(), required=True)
64@click.option('-d', '--dependencies', callback=imgtool.main.get_dependencies,
65 required=False, help='''Add dependence on another image, format:
66 "(<image_ID>,<image_version>), ... "''')
67@click.option('-s', '--security-counter',
68 callback=imgtool.main.validate_security_counter,
69 help='Specify the value of security counter. Use the `auto` '
70 'keyword to automatically generate it from the image version.')
71@click.option('-v', '--version', callback=imgtool.main.validate_version,
72 required=True)
73@click.option('--align', type=click.Choice(['1', '2', '4', '8']),
74 required=True)
75@click.option('--public-key-format', type=click.Choice(['hash', 'full']),
76 default='hash', help='In what format to add the public key to '
77 'the image manifest: full key or hash of the key.')
78@click.option('-k', '--key', metavar='filename')
79@click.command(help='''Create a signed or unsigned image\n
80 INFILE and OUTFILE are parsed as Intel HEX if the params have
81 .hex extension, otherwise binary format is used''')
82def wrap(key, align, version, header_size, pad_header, layout, pad, confirm,
83 max_sectors, overwrite_only, endian, encrypt, infile, outfile,
84 dependencies, hex_addr, erased_val, save_enctlv, public_key_format,
85 security_counter):
86
87 slot_size = macro_parser.evaluate_macro(layout, sign_bin_size_re, 0, 1)
88 load_addr = macro_parser.evaluate_macro(layout, load_addr_re, 0, 1)
89
90 if "_s.c" in layout:
91 boot_record = "SPE"
92 elif "_ns.c" in layout:
93 boot_record = "NSPE"
94 else:
95 boot_record = "NSPE_SPE"
96
97 img = imgtool.image.Image(version=imgtool.version.decode_version(version),
98 header_size=header_size, pad_header=pad_header,
99 pad=pad, confirm=confirm, align=int(align),
100 slot_size=slot_size, max_sectors=max_sectors,
101 overwrite_only=overwrite_only, endian=endian,
102 load_addr=load_addr, erased_val=erased_val,
103 save_enctlv=save_enctlv,
104 security_counter=security_counter)
105
106 img.load(infile)
107 key = imgtool.main.load_key(key) if key else None
108 enckey = imgtool.main.load_key(encrypt) if encrypt else None
109 if enckey and key:
110 if (isinstance(key, imgtool.keys.RSA) and
111 not isinstance(enckey, imgtool.keys.RSAPublic)):
112 # FIXME
113 raise click.UsageError("Signing and encryption must use the same "
114 "type of key")
115
116 img.create(key, public_key_format, enckey, dependencies, boot_record)
117 img.save(outfile, hex_addr)
118
119
120if __name__ == '__main__':
121 wrap()