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