=== modified file 'linaro_image_tools/hwpack/config.py'
--- linaro_image_tools/hwpack/config.py	2011-07-01 14:33:32 +0000
+++ linaro_image_tools/hwpack/config.py	2011-07-01 14:55:14 +0000
@@ -58,6 +58,9 @@
     PARTITION_LAYOUT_KEY = "partition_layout"
     MMC_ID_KEY = "mmc_id"
     FORMAT_KEY = "format"
+    BOOT_MIN_SIZE_KEY = "boot_min_size"
+    ROOT_MIN_SIZE_KEY = "root_min_size"
+    LOADER_MIN_SIZE_KEY = "loader_min_size"
 
     DEFINED_PARTITION_LAYOUTS = [
         'bootfs16_rootfs',
@@ -100,6 +103,9 @@
             self._validate_wireless_interfaces()
             self._validate_partition_layout()
             self._validate_mmc_id()
+            self._validate_boot_min_size()
+            self._validate_root_min_size()
+            self._validate_loader_min_size()
 
         self._validate_sections()
 
@@ -224,6 +230,30 @@
         return self._get_option_from_main_section(self.MMC_ID_KEY)
 
     @property
+    def root_min_size(self):
+        """Minimum size of the root partition, in MiB.
+
+        An int.
+        """
+        return self._get_option_from_main_section(self.ROOT_MIN_SIZE_KEY)
+
+    @property
+    def boot_min_size(self):
+        """Minimum size of the boot partition, in MiB.
+
+        An int.
+        """
+        return self._get_option_from_main_section(self.BOOT_MIN_SIZE_KEY)
+
+    @property
+    def loader_min_size(self):
+        """Minimum size of the optional loader partition, in MiB.
+
+        An int.
+        """
+        return self._get_option_from_main_section(self.LOADER_MIN_SIZE_KEY)
+
+    @property
     def origin(self):
         """The origin that should be recorded in the hwpack.
 
@@ -398,6 +428,36 @@
         except:
             raise HwpackConfigError("Invalid mmc id %s" % (mmc_id))
 
+    def _validate_root_min_size(self):
+        root_min_size = self.root_min_size
+        if root_min_size is None:
+            return
+        try:
+            assert int(root_min_size) > 0
+        except:
+            raise HwpackConfigError(
+                "Invalid root min size %s" % (root_min_size))
+
+    def _validate_boot_min_size(self):
+        boot_min_size = self.boot_min_size
+        if boot_min_size is None:
+            return
+        try:
+            assert int(boot_min_size) > 0
+        except:
+            raise HwpackConfigError(
+                "Invalid boot min size %s" % (boot_min_size))
+
+    def _validate_loader_min_size(self):
+        loader_min_size = self.loader_min_size
+        if loader_min_size is None:
+            return
+        try:
+            assert int(loader_min_size) > 0
+        except:
+            raise HwpackConfigError(
+                "Invalid loader min size %s" % (loader_min_size))
+
     def _validate_include_debs(self):
         try:
             self.include_debs

=== modified file 'linaro_image_tools/hwpack/hardwarepack.py'
--- linaro_image_tools/hwpack/hardwarepack.py	2011-06-20 13:46:16 +0000
+++ linaro_image_tools/hwpack/hardwarepack.py	2011-06-29 14:25:49 +0000
@@ -80,7 +80,8 @@
     def add_v2_config(self, serial_tty=None, kernel_addr=None, initrd_addr=None,
                       load_addr=None, fdt=None, wired_interfaces=[],
                       wireless_interfaces=[], partition_layout=None,
-                      mmc_id=None):
+                      mmc_id=None, boot_min_size=None, root_min_size=None,
+                      loader_min_size=None):
         """Add fields that are specific to the new format.
 
         These fields are not present in earlier config files.
@@ -94,6 +95,9 @@
         self.wireless_interfaces = wireless_interfaces
         self.partition_layout = partition_layout
         self.mmc_id = mmc_id
+        self.boot_min_size = boot_min_size
+        self.root_min_size = root_min_size
+        self.loader_min_size = loader_min_size
 
     @classmethod
     def from_config(cls, config, version, architecture):
@@ -126,7 +130,10 @@
                                    wired_interfaces=config.wired_interfaces,
                                    wireless_interfaces=config.wireless_interfaces,
                                    partition_layout=config.partition_layout,
-                                   mmc_id=config.mmc_id)
+                                   mmc_id=config.mmc_id,
+                                   boot_min_size=config.boot_min_size,
+                                   root_min_size=config.root_min_size,
+                                   loader_min_size=config.loader_min_size)
         return metadata
 
     def __str__(self):
@@ -163,6 +170,13 @@
             metadata += "PARTITION_LAYOUT=%s\n" % self.partition_layout
         if self.mmc_id is not None:
             metadata += "MMC_ID=%s\n" % self.mmc_id
+        if self.boot_min_size is not None:
+            metadata += "BOOT_MIN_SIZE=%s\n" % self.boot_min_size
+        if self.root_min_size is not None:
+            metadata += "ROOT_MIN_SIZE=%s\n" % self.root_min_size
+        if self.loader_min_size is not None:
+            metadata += "LOADER_MIN_SIZE=%s\n" % self.loader_min_size
+
         return metadata
 
 

=== modified file 'linaro_image_tools/hwpack/tests/test_config.py'
--- linaro_image_tools/hwpack/tests/test_config.py	2011-06-29 07:18:40 +0000
+++ linaro_image_tools/hwpack/tests/test_config.py	2011-06-29 14:25:49 +0000
@@ -249,6 +249,21 @@
                                  "mmc_id = x\n")
         self.assertValidationError("Invalid mmc id x", config)
 
+    def test_validate_boot_min_size(self):
+        config = self.get_config(self.valid_complete_v2 + 
+                                 "boot_min_size = x\n")
+        self.assertValidationError("Invalid boot min size x", config)
+
+    def test_validate_root_min_size(self):
+        config = self.get_config(self.valid_complete_v2 + 
+                                 "root_min_size = x\n")
+        self.assertValidationError("Invalid root min size x", config)
+
+    def test_validate_loader_min_size(self):
+        config = self.get_config(self.valid_complete_v2 + 
+                                 "loader_min_size = x\n")
+        self.assertValidationError("Invalid loader min size x", config)
+
     def test_validate_kernel_addr(self):
         config = self.get_config(self.valid_complete_v2 + 
                                  "kernel_addr = 0x8000000\n")
@@ -330,6 +345,27 @@
         config.validate()
         self.assertEqual("1", config.mmc_id)
 
+    def test_boot_min_size(self):
+        config = self.get_config(self.valid_complete_v2 + 
+                                 "boot_min_size = 50\n" + 
+                                 self.valid_end)
+        config.validate()
+        self.assertEqual("50", config.boot_min_size)
+
+    def test_root_min_size(self):
+        config = self.get_config(self.valid_complete_v2 + 
+                                 "root_min_size = 50\n" + 
+                                 self.valid_end)
+        config.validate()
+        self.assertEqual("50", config.root_min_size)
+
+    def test_loader_min_size(self):
+        config = self.get_config(self.valid_complete_v2 + 
+                                 "loader_min_size = 2\n" + 
+                                 self.valid_end)
+        config.validate()
+        self.assertEqual("2", config.loader_min_size)
+
     def test_kernel_addr(self):
         config = self.get_config(self.valid_complete_v2 + 
                                  "kernel_addr = 0x80000000\n" + 

=== modified file 'linaro_image_tools/hwpack/tests/test_hardwarepack.py'
--- linaro_image_tools/hwpack/tests/test_hardwarepack.py	2011-06-17 15:10:49 +0000
+++ linaro_image_tools/hwpack/tests/test_hardwarepack.py	2011-06-29 14:30:25 +0000
@@ -183,6 +183,33 @@
             "MMC_ID=1\n",
             str(metadata))
 
+    def test_str_with_boot_min_size(self):
+        metadata = Metadata("ahwpack", "4", "armel",
+                            format=HardwarePackFormatV2())
+        metadata.add_v2_config(boot_min_size='50')
+        self.assertEqual(
+            "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\n"
+            "BOOT_MIN_SIZE=50\n",
+            str(metadata))
+
+    def test_str_with_root_min_size(self):
+        metadata = Metadata("ahwpack", "4", "armel",
+                            format=HardwarePackFormatV2())
+        metadata.add_v2_config(root_min_size='100')
+        self.assertEqual(
+            "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\n"
+            "ROOT_MIN_SIZE=100\n",
+            str(metadata))
+
+    def test_str_with_loader_min_size(self):
+        metadata = Metadata("ahwpack", "4", "armel",
+                            format=HardwarePackFormatV2())
+        metadata.add_v2_config(loader_min_size='1')
+        self.assertEqual(
+            "NAME=ahwpack\nVERSION=4\nARCHITECTURE=armel\n"
+            "LOADER_MIN_SIZE=1\n",
+            str(metadata))
+
     def test_from_config(self):
         class Config:
             name = "foo"

=== modified file 'linaro_image_tools/media_create/boards.py'
--- linaro_image_tools/media_create/boards.py	2011-07-01 14:51:46 +0000
+++ linaro_image_tools/media_create/boards.py	2011-07-01 14:55:14 +0000
@@ -67,17 +67,6 @@
     """Round value to the next multiple of align."""
     return (value + align - 1) / align * align
 
-# optional bootloader partition; at least 1 MiB; in theory, an i.MX5x
-# bootloader partition could hold RedBoot, FIS table, RedBoot config, kernel,
-# and initrd, but we typically use U-Boot which is about 167 KiB as of
-# 2011/02/11 and currently doesn't even store its environment there, so this
-# should be enough
-LOADER_MIN_SIZE_S = align_up(1 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-# boot partition; at least 50 MiB; XXX this shouldn't be hardcoded
-BOOT_MIN_SIZE_S = align_up(50 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-# root partition; at least 50 MiB; XXX this shouldn't be hardcoded
-ROOT_MIN_SIZE_S = align_up(50 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-
 # Samsung v310 implementation notes and terminology
 #
 # * BL0, BL1 etc. are the various bootloaders in order of execution
@@ -241,6 +230,9 @@
     _live_serial_opts = ''
     extra_boot_args_options = None
     supports_writing_to_mmc = True
+    LOADER_MIN_SIZE_S = align_up(1 * 1024**2, SECTOR_SIZE) / SECTOR_SIZE
+    BOOT_MIN_SIZE_S = align_up(50 * 1024**2, SECTOR_SIZE) / SECTOR_SIZE
+    ROOT_MIN_SIZE_S = align_up(50 * 1024**2, SECTOR_SIZE) / SECTOR_SIZE
 
     # These attributes must be defined on all subclasses for backwards
     # compatibility with hwpacks v1 format. Hwpacks v2 format allows these to
@@ -283,6 +275,9 @@
                 cls.load_addr = None
                 cls.serial_tty = None
                 cls.fat_size = None
+                cls.BOOT_MIN_SIZE_S = None
+                cls.ROOT_MIN_SIZE_S = None
+                cls.LOADER_MIN_SIZE_S = None
 
             # Set new values from metadata.
             cls.kernel_addr = cls.get_metadata_field(
@@ -308,6 +303,23 @@
             else:
                 raise AssertionError("Unknown partition layout '%s'." % partition_layout)
 
+            boot_min_size = cls.get_metadata_field(
+                cls.BOOT_MIN_SIZE_S, 'boot_min_size')
+            if boot_min_size is not None:
+                cls.BOOT_MIN_SIZE_S = align_up(int(boot_min_size) * 1024**2,
+                                               SECTOR_SIZE) / SECTOR_SIZE
+            root_min_size = cls.get_metadata_field(
+                cls.ROOT_MIN_SIZE_S, 'root_min_size')
+            if root_min_size is not None:
+                cls.ROOT_MIN_SIZE_S = align_up(int(root_min_size) * 1024**2,
+                                               SECTOR_SIZE) / SECTOR_SIZE
+            loader_min_size = cls.get_metadata_field(
+                cls.LOADER_MIN_SIZE_S, 'loader_min_size')
+            if loader_min_size is not None:
+                cls.LOADER_MIN_SIZE_S = align_up(int(loader_min_size) * 1024**2,
+                                               SECTOR_SIZE) / SECTOR_SIZE
+
+
     @classmethod
     def get_file(cls, file_alias, default=None):
         file_in_hwpack = cls.hardwarepack_handler.get_file(file_alias)
@@ -330,9 +342,6 @@
         else:
             partition_type = '0x0E'
 
-        BOOT_MIN_SIZE_S = align_up(50 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-        ROOT_MIN_SIZE_S = align_up(50 * 1024 * 1024, SECTOR_SIZE) / SECTOR_SIZE
-
         # align on sector 63 for compatibility with broken versions of x-loader
         # unless align_boot_part is set
         boot_align = 63
@@ -341,7 +350,7 @@
 
         # can only start on sector 1 (sector 0 is MBR / partition table)
         boot_start, boot_end, boot_len = align_partition(
-            1, BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)
+            1, cls.BOOT_MIN_SIZE_S, boot_align, PART_ALIGN_S)
         # apparently OMAP3 ROMs require the vfat length to be an even number
         # of sectors (multiple of 1 KiB); decrease the length if it's odd,
         # there should still be enough room
@@ -352,7 +361,7 @@
         # instruct the use of all remaining space; XXX if we had some root size
         # config, we could do something more sensible
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,%s,*\n%s,,,-' % (
             boot_start, boot_len, partition_type, root_start)
@@ -720,15 +729,15 @@
         # (sector 0 is MBR / partition table)
         loader_start, loader_end, loader_len = align_partition(
             SnowballEmmcConfig.SNOWBALL_LOADER_START_S,
-            LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
+            cls.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
 
         boot_start, boot_end, boot_len = align_partition(
-            loader_end + 1, BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            loader_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
         # we ignore _root_end / _root_len and return an sfdisk command to
         # instruct the use of all remaining space; XXX if we had some root size
         # config, we could do something more sensible
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
         loader_start, loader_len, boot_start, boot_len, root_start)
@@ -866,15 +875,15 @@
         # onwards, so it's safer to just start at the first sector, sector 1
         # (sector 0 is MBR / partition table)
         loader_start, loader_end, loader_len = align_partition(
-            1, LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
+            1, cls.LOADER_MIN_SIZE_S, 1, PART_ALIGN_S)
 
         boot_start, boot_end, boot_len = align_partition(
-            loader_end + 1, BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            loader_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
         # we ignore _root_end / _root_len and return a sfdisk command to
         # instruct the use of all remaining space; XXX if we had some root size
         # config, we could do something more sensible
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
             loader_start, loader_len, boot_start, boot_len, root_start)
@@ -887,7 +896,8 @@
             uboot_file = cls.get_file('u_boot', default=os.path.join(
                     chroot_dir, 'usr', 'lib', 'u-boot', cls.uboot_flavor,
                     'u-boot.imx'))
-            install_mx5_boot_loader(uboot_file, boot_device_or_file)
+            install_mx5_boot_loader(uboot_file, boot_device_or_file,
+                                    cls.LOADER_MIN_SIZE_S)
         make_uImage(cls.load_addr, k_img_data, boot_dir)
         make_uInitrd(i_img_data, boot_dir)
         make_dtb(d_img_data, boot_dir)
@@ -991,14 +1001,14 @@
 
         # FAT boot partition
         boot_start, boot_end, boot_len = align_partition(
-            loaders_end + 1, BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            loaders_end + 1, cls.BOOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         # root partition
         # we ignore _root_end / _root_len and return a sfdisk command to
         # instruct the use of all remaining space; XXX if we had some root size
         # config, we could do something more sensible
         root_start, _root_end, _root_len = align_partition(
-            boot_end + 1, ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
+            boot_end + 1, cls.ROOT_MIN_SIZE_S, PART_ALIGN_S, PART_ALIGN_S)
 
         return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
             loaders_start, loaders_len, boot_start, boot_len, root_start)
@@ -1207,13 +1217,13 @@
     return tmpfile
 
 
-def install_mx5_boot_loader(imx_file, boot_device_or_file):
+def install_mx5_boot_loader(imx_file, boot_device_or_file, loader_min_size):
     # bootloader partition starts at +1s but we write the file at +2s, so we
     # need to check that the bootloader partition minus 1s is at least as large
     # as the u-boot binary; note that the real bootloader partition might be
     # larger than LOADER_MIN_SIZE_S, but if u-boot is larger it's a sign we
     # need to bump LOADER_MIN_SIZE_S
-    max_size = (LOADER_MIN_SIZE_S - 1) * SECTOR_SIZE
+    max_size = (loader_min_size - 1) * SECTOR_SIZE
     assert os.path.getsize(imx_file) <= max_size, (
         "%s is larger than guaranteed bootloader partition size" % imx_file)
     _dd(imx_file, boot_device_or_file, seek=2)

=== modified file 'linaro_image_tools/media_create/tests/test_media_create.py'
--- linaro_image_tools/media_create/tests/test_media_create.py	2011-07-01 14:51:46 +0000
+++ linaro_image_tools/media_create/tests/test_media_create.py	2011-07-01 14:55:14 +0000
@@ -44,7 +44,6 @@
     android_boards,
     )
 from linaro_image_tools.media_create.boards import (
-    LOADER_MIN_SIZE_S,
     SAMSUNG_V310_BL1_START,
     SAMSUNG_V310_BL2_START,
     SECTOR_SIZE,
@@ -387,6 +386,54 @@
         config.set_metadata('ahwpack.tar.gz')
         self.assertEquals(data_to_set, config.mmc_id)
 
+    def test_sets_boot_min_size(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'boot_min_size'
+        data_to_set = '100'
+        expected = align_up(int(data_to_set) * 1024 * 1024,
+                            SECTOR_SIZE) / SECTOR_SIZE
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(expected, config.BOOT_MIN_SIZE_S)
+
+    def test_sets_root_min_size(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'root_min_size'
+        data_to_set = '3'
+        expected = align_up(int(data_to_set) * 1024 * 1024,
+                            SECTOR_SIZE) / SECTOR_SIZE
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(expected, config.ROOT_MIN_SIZE_S)
+
+    def test_sets_loader_min_size(self):
+        self.useFixture(MockSomethingFixture(
+                linaro_image_tools.media_create.boards, 'HardwarepackHandler',
+                self.MockHardwarepackHandler))
+        field_to_test = 'loader_min_size'
+        data_to_set = '2'
+        expected = align_up(int(data_to_set) * 1024 * 1024,
+                            SECTOR_SIZE) / SECTOR_SIZE
+        self.MockHardwarepackHandler.metadata_dict = {
+            field_to_test: data_to_set,
+            }
+        class config(BoardConfig):
+            pass
+        config.set_metadata('ahwpack.tar.gz')
+        self.assertEquals(expected, config.LOADER_MIN_SIZE_S)
+
     def test_sets_partition_layout_32(self):
         self.useFixture(MockSomethingFixture(
                 linaro_image_tools.media_create.boards, 'HardwarepackHandler',
@@ -1289,7 +1336,8 @@
     def test_install_mx5_boot_loader(self):
         fixture = self._mock_Popen()
         imx_file = self.createTempFileAsFixture()
-        install_mx5_boot_loader(imx_file, "boot_device_or_file")
+        install_mx5_boot_loader(imx_file, "boot_device_or_file",
+                                BoardConfig.LOADER_MIN_SIZE_S)
         expected = [
             '%s dd if=%s of=boot_device_or_file bs=512 '
             'conv=notrunc seek=2' % (sudo_args, imx_file)]
@@ -1298,9 +1346,10 @@
     def test_install_mx5_boot_loader_too_large(self):
         self.useFixture(MockSomethingFixture(
             os.path, "getsize",
-            lambda s: (LOADER_MIN_SIZE_S - 1) * SECTOR_SIZE + 1))
+            lambda s: (BoardConfig.LOADER_MIN_SIZE_S - 1) * SECTOR_SIZE + 1))
         self.assertRaises(AssertionError,
-            install_mx5_boot_loader, "imx_file", "boot_device_or_file")
+            install_mx5_boot_loader, "imx_file", "boot_device_or_file",
+                          BoardConfig.LOADER_MIN_SIZE_S)
 
     def test_install_omap_boot_loader(self):
         fixture = self._mock_Popen()

