Boot: Add version number from command line
- Add an optional command line argument that can be used to set an
image's version number at build-time (using
-DIMAGE_VERSION=maj.min.rev+build) so that the Cmake command within
bl2/ext/mcuboot/MCUBoot.cmake doesn't need to be edited each time the
specified version number needs to be changed
- If the version number is not defined in the command line, use a
default value and automatically increment it in the next build
Signed-off-by: Oliver Swede <oli.swede@arm.com>
Change-Id: I3ff44ffb8219d7ea1a441d918cceb525e7af60f2
diff --git a/bl2/ext/mcuboot/scripts/imgtool.py b/bl2/ext/mcuboot/scripts/imgtool.py
index 9420d2b..4c5b451 100644
--- a/bl2/ext/mcuboot/scripts/imgtool.py
+++ b/bl2/ext/mcuboot/scripts/imgtool.py
@@ -1,6 +1,7 @@
#! /usr/bin/env python3
#
# Copyright 2017 Linaro Limited
+# Copyright (c) 2018, Arm Limited.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -14,12 +15,46 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+import os
import argparse
from imgtool import keys
from imgtool import image
from imgtool import version
import sys
+# Returns the last version number if present, or None if not
+def get_last_version(path):
+ if (os.path.isfile(path) == False): # Version file not present
+ return None
+ else: # Version file is present, check it has a valid number inside it
+ with open(path, "r") as oldFile:
+ fileContents = oldFile.read()
+ if version.version_re.match(fileContents): # number is valid
+ return version.decode_version(fileContents)
+ else:
+ return None
+
+def next_version_number(args, defaultVersion, path):
+ newVersion = None
+ if (version.compare(args.version, defaultVersion) == 0): # Default version
+ lastVersion = get_last_version(path)
+ if (lastVersion is not None):
+ newVersion = version.increment_build_num(lastVersion)
+ else:
+ newVersion = version.increment_build_num(defaultVersion)
+ else: # Version number has been explicitly provided (not using the default)
+ newVersion = args.version
+ versionString = "{a}.{b}.{c}+{d}".format(
+ a=str(newVersion.major),
+ b=str(newVersion.minor),
+ c=str(newVersion.revision),
+ d=str(newVersion.build)
+ )
+ with open(path, "w") as newFile:
+ newFile.write(versionString)
+ print("**[INFO]** Image version number set to " + versionString)
+ return newVersion
+
def gen_rsa2048(args):
keys.RSA2048.generate().export_private(args.key)
@@ -43,7 +78,10 @@
def do_sign(args):
if args.rsa_pkcs1_15:
keys.sign_rsa_pss = False
- img = image.Image.load(args.infile, version=args.version,
+ img = image.Image.load(args.infile,
+ version=next_version_number(args,
+ version.decode_version("0"),
+ "lastVerNum.txt"),
header_size=args.header_size,
included_header=args.included_header,
pad=args.pad)
@@ -80,7 +118,7 @@
keygenp = subs.add_parser('keygen', help='Generate pub/private keypair')
keygenp.add_argument('-k', '--key', metavar='filename', required=True)
keygenp.add_argument('-t', '--type', metavar='type',
- choices=keygens.keys(), required=True)
+ choices=keygens.keys(), required=True)
getpub = subs.add_parser('getpub', help='Get public key from keypair')
getpub.add_argument('-k', '--key', metavar='filename', required=True)
@@ -89,14 +127,16 @@
sign = subs.add_parser('sign', help='Sign an image with a private key')
sign.add_argument('-k', '--key', metavar='filename')
sign.add_argument("--align", type=alignment_value, required=True)
- sign.add_argument("-v", "--version", type=version.decode_version, required=True)
+ sign.add_argument("-v", "--version", type=version.decode_version,
+ default="0.0.0+0")
sign.add_argument("-H", "--header-size", type=intparse, required=True)
sign.add_argument("--included-header", default=False, action='store_true',
- help='Image has gap for header')
+ help='Image has gap for header')
sign.add_argument("--pad", type=intparse,
- help='Pad image to this many bytes, adding trailer magic')
- sign.add_argument("--rsa-pkcs1-15", help='Use old PKCS#1 v1.5 signature algorithm',
- default=False, action='store_true')
+ help='Pad image to this many bytes, adding trailer magic')
+ sign.add_argument("--rsa-pkcs1-15",
+ help='Use old PKCS#1 v1.5 signature algorithm',
+ default=False, action='store_true')
sign.add_argument("infile")
sign.add_argument("outfile")
@@ -108,4 +148,4 @@
subcmds[args.subcmd](args)
if __name__ == '__main__':
- args()
+ args()
\ No newline at end of file
diff --git a/bl2/ext/mcuboot/scripts/imgtool/image.py b/bl2/ext/mcuboot/scripts/imgtool/image.py
index f8309b3..9731844 100644
--- a/bl2/ext/mcuboot/scripts/imgtool/image.py
+++ b/bl2/ext/mcuboot/scripts/imgtool/image.py
@@ -79,8 +79,8 @@
obj.check()
return obj
- def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, pad=0):
- self.version = version or versmod.decode_version("0")
+ def __init__(self, version, header_size=IMAGE_HEADER_SIZE, pad=0):
+ self.version = version
self.header_size = header_size or IMAGE_HEADER_SIZE
self.pad = pad
@@ -182,4 +182,4 @@
pbytes = b'\xff' * padding
pbytes += b'\xff' * (tsize - len(boot_magic))
pbytes += boot_magic
- self.payload += pbytes
+ self.payload += pbytes
\ No newline at end of file
diff --git a/bl2/ext/mcuboot/scripts/imgtool/version.py b/bl2/ext/mcuboot/scripts/imgtool/version.py
index 64962e9..d1d45f0 100644
--- a/bl2/ext/mcuboot/scripts/imgtool/version.py
+++ b/bl2/ext/mcuboot/scripts/imgtool/version.py
@@ -1,4 +1,5 @@
# Copyright 2017 Linaro Limited
+# Copyright (c) 2018, Arm Limited.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -24,11 +25,29 @@
SemiSemVersion = namedtuple('SemiSemVersion', ['major', 'minor', 'revision', 'build'])
+def increment_build_num(lastVer):
+ newVer = SemiSemVersion(lastVer.major, lastVer.minor, lastVer.revision, lastVer.build + 1)
+ return newVer
+
+# -1 if a is older than b; 0 if they're the same version; 1 if a is newer than b
+def compare(a, b):
+ if (a.major > b.major): return 1
+ elif (a.major < b.major): return -1
+ else:
+ if (a.minor > b.minor): return 1
+ elif (a.minor < b.minor): return -1
+ else:
+ if (a.revision > b.revision): return 1
+ elif (a.revision < b.revision): return -1
+ else:
+ if (a.build > b.build): return 1
+ elif (a.build < b.build): return -1
+ else: return 0
+
version_re = re.compile(r"""^([1-9]\d*|0)(\.([1-9]\d*|0)(\.([1-9]\d*|0)(\+([1-9]\d*|0))?)?)?$""")
def decode_version(text):
"""Decode the version string, which should be of the form maj.min.rev+build"""
m = version_re.match(text)
- # print("decode:", text, m.groups())
if m:
result = SemiSemVersion(
int(m.group(1)) if m.group(1) else 0,