Allow passing max sectors as parameter to imgtool

This adds a new command line flag to allow passing in the max number of
sectors for a swap when the image is padded. It defaults to 128 and
should match the value configured in the bootloader.

Fixes #285

Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/scripts/imgtool.py b/scripts/imgtool.py
index c7c17a4..f102111 100755
--- a/scripts/imgtool.py
+++ b/scripts/imgtool.py
@@ -114,7 +114,9 @@
 
 @click.argument('outfile')
 @click.argument('infile')
-@click.option('--pad', type=int,
+@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('--included-header', default=False, is_flag=True,
               help='Image has gap for header')
@@ -124,8 +126,8 @@
               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, infile,
-         outfile):
+def sign(key, align, version, header_size, included_header, pad, max_sectors,
+         infile, outfile):
     img = image.Image.load(infile, version=decode_version(version),
                            header_size=header_size,
                            included_header=included_header, pad=pad)
@@ -133,7 +135,7 @@
     img.sign(key)
 
     if pad is not None:
-        img.pad_to(pad, align)
+        img.pad_to(pad, int(align), max_sectors)
 
     img.save(outfile)
 
diff --git a/scripts/imgtool/image.py b/scripts/imgtool/image.py
index 887ed97..cca8231 100644
--- a/scripts/imgtool/image.py
+++ b/scripts/imgtool/image.py
@@ -27,6 +27,7 @@
 IMAGE_HEADER_SIZE = 32
 BIN_EXT = "bin"
 INTEL_HEX_EXT = "hex"
+DEFAULT_MAX_SECTORS = 128
 
 # Image header flags.
 IMAGE_F = {
@@ -43,12 +44,6 @@
 TLV_INFO_SIZE = 4
 TLV_INFO_MAGIC = 0x6907
 
-# Sizes of the image trailer, depending on flash write size.
-trailer_sizes = {
-    write_size: 128 * 3 * write_size + 8 * 2 + 16
-    for write_size in [1, 2, 4, 8]
-}
-
 boot_magic = bytes([
     0x77, 0xc2, 0x95, 0xf3,
     0x60, 0xd2, 0xef, 0x7f,
@@ -172,9 +167,16 @@
         self.payload = bytearray(self.payload)
         self.payload[:len(header)] = header
 
-    def pad_to(self, size, align):
+    def _trailer_size(self, write_size, max_sectors):
+        # NOTE: should already be checked by the argument parser
+        if write_size not in set([1, 2, 4, 8]):
+            raise Exception("Invalid alignment: {}".format(write_size))
+        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):
         """Pad the image to the given size, with the given flash alignment."""
-        tsize = trailer_sizes[align]
+        tsize = self._trailer_size(align, 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(