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 <utzig@apache.org>
This commit is contained in:
Fabio Utzig 2018-06-05 10:37:35 -03:00 committed by Fabio Utzig
parent 806af0ed87
commit 263d4398fa
3 changed files with 40 additions and 23 deletions

View File

@ -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

View File

@ -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)

View File

@ -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 "<Image version={}, header_size={}, base_addr={}, pad={}, \
format={}, payloadlen=0x{:x}>".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 "<Image version={}, header_size={}, base_addr={}, \
align={}, slot_size={}, max_sectors={}, format={}, \
payloadlen=0x{:x}>".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):