From 263d4398fabcf9c132f3b2887d7ae45a4a625036 Mon Sep 17 00:00:00 2001 From: Fabio Utzig Date: Tue, 5 Jun 2018 10:37:35 -0300 Subject: [PATCH] Add --slot-size to allow size checking without pad Add the new `--slot-size` and make `--pad` a bool flag, to allow checking that firmware fits in the slot without overflowing into the trailer region even when no padding was requested. Fixes #241 Signed-off-by: Fabio Utzig --- samples/zephyr/Makefile | 4 +++- scripts/imgtool.py | 18 +++++++++++------- scripts/imgtool/image.py | 41 +++++++++++++++++++++++++--------------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/samples/zephyr/Makefile b/samples/zephyr/Makefile index 9b246b75..1477bbf6 100644 --- a/samples/zephyr/Makefile +++ b/samples/zephyr/Makefile @@ -130,6 +130,7 @@ hello1: check --align $(FLASH_ALIGNMENT) \ --version 1.2 \ --included-header \ + --slot-size 0x60000 $(BUILD_DIR_HELLO1)/zephyr/zephyr.bin \ signed-hello1.bin @@ -155,7 +156,8 @@ hello2: check --align $(FLASH_ALIGNMENT) \ --version 1.2 \ --included-header \ - --pad 0x60000 \ + --slot-size 0x60000 \ + --pad \ $(BUILD_DIR_HELLO2)/zephyr/zephyr.bin \ signed-hello2.bin diff --git a/scripts/imgtool.py b/scripts/imgtool.py index f1021111..f3bd016a 100755 --- a/scripts/imgtool.py +++ b/scripts/imgtool.py @@ -116,8 +116,10 @@ class BasedIntParamType(click.ParamType): @click.argument('infile') @click.option('-M', '--max-sectors', type=int, help='When padding allow for this amount of sectors (defaults to 128)') -@click.option('--pad', type=BasedIntParamType(), - help='Pad image to this many bytes, adding trailer magic') +@click.option('--pad', default=False, is_flag=True, + help='Pad image to --slot-size bytes, adding trailer magic') +@click.option('-S', '--slot-size', type=BasedIntParamType(), required=True, + help='Size of the slot where the image will be written') @click.option('--included-header', default=False, is_flag=True, help='Image has gap for header') @click.option('-H', '--header-size', type=BasedIntParamType(), required=True) @@ -126,16 +128,18 @@ class BasedIntParamType(click.ParamType): required=True) @click.option('-k', '--key', metavar='filename') @click.command(help='Create a signed or unsigned image') -def sign(key, align, version, header_size, included_header, pad, max_sectors, - infile, outfile): +def sign(key, align, version, header_size, included_header, slot_size, pad, + max_sectors, infile, outfile): img = image.Image.load(infile, version=decode_version(version), header_size=header_size, - included_header=included_header, pad=pad) + included_header=included_header, pad=pad, + align=int(align), slot_size=slot_size, + max_sectors=max_sectors) key = load_key(key) if key else None img.sign(key) - if pad is not None: - img.pad_to(pad, int(align), max_sectors) + if pad: + img.pad_to(slot_size) img.save(outfile) diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py index cca82313..bb7a1f63 100644 --- a/scripts/imgtool/image.py +++ b/scripts/imgtool/image.py @@ -84,20 +84,27 @@ class Image(): obj.check() return obj - def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, pad=0): + def __init__(self, version=None, header_size=IMAGE_HEADER_SIZE, pad=0, + align=1, slot_size=0, max_sectors=DEFAULT_MAX_SECTORS): self.version = version or versmod.decode_version("0") self.header_size = header_size or IMAGE_HEADER_SIZE self.pad = pad + self.align = align + self.slot_size = slot_size + self.max_sectors = max_sectors def __repr__(self): - return "".format( - self.version, - self.header_size, - self.base_addr if self.base_addr is not None else "N/A", - self.pad, - self.__class__.__name__, - len(self.payload)) + return "".format( + self.version, + self.header_size, + self.base_addr if self.base_addr is not None else "N/A", + self.align, + self.slot_size, + self.max_sectors, + self.__class__.__name__, + len(self.payload)) def check(self): """Perform some sanity checking of the image.""" @@ -106,6 +113,13 @@ class Image(): if self.header_size > 0: if any(v != 0 for v in self.payload[0:self.header_size]): raise Exception("Padding requested, but image does not start with zeros") + if self.slot_size > 0: + tsize = self._trailer_size(self.align, self.max_sectors) + padding = self.slot_size - (len(self.payload) + tsize) + if padding < 0: + msg = "Image size (0x{:x}) + trailer (0x{:x}) exceeds requested size 0x{:x}".format( + len(self.payload), tsize, self.slot_size) + raise Exception(msg) def sign(self, key): self.add_header(key) @@ -174,19 +188,16 @@ class Image(): m = DEFAULT_MAX_SECTORS if max_sectors is None else max_sectors return m * 3 * write_size + 8 * 2 + 16 - def pad_to(self, size, align, max_sectors): + def pad_to(self, size): """Pad the image to the given size, with the given flash alignment.""" - tsize = self._trailer_size(align, max_sectors) + tsize = self._trailer_size(self.align, self.max_sectors) padding = size - (len(self.payload) + tsize) - if padding < 0: - msg = "Image size (0x{:x}) + trailer (0x{:x}) exceeds requested size 0x{:x}".format( - len(self.payload), tsize, size) - raise Exception(msg) pbytes = b'\xff' * padding pbytes += b'\xff' * (tsize - len(boot_magic)) pbytes += boot_magic self.payload += pbytes + class HexImage(Image): def load(self, path):