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