=== modified file 'linaro_image_tools/media_create/partitions.py'
--- linaro_image_tools/media_create/partitions.py	2012-05-09 21:25:20 +0000
+++ linaro_image_tools/media_create/partitions.py	2012-06-13 13:42:08 +0000
@@ -17,15 +17,16 @@
 # You should have received a copy of the GNU General Public License
 # along with Linaro Image Tools.  If not, see <http://www.gnu.org/licenses/>.
 
+from contextlib import contextmanager
+from math import ceil
 import atexit
-from contextlib import contextmanager
+import dbus
 import glob
 import logging
 import re
 import subprocess
 import time
 
-import dbus
 from parted import (
     Device,
     Disk,
@@ -35,7 +36,6 @@
 
 from linaro_image_tools import cmd_runner
 
-
 HEADS = 128
 SECTORS = 32
 SECTOR_SIZE = 512  # bytes
@@ -45,13 +45,17 @@
 # Max number of attempts to sleep (total sleep time in seconds =
 # 1+2+...+MAX_TTS)
 MAX_TTS = 10
+# Image size should be a multiple of 1MiB, expressed in bytes. This is also
+# the minimum image size possible.
+ROUND_IMAGE_TO = 2 ** 20
+MIN_IMAGE_SIZE = ROUND_IMAGE_TO
 
 
 def setup_android_partitions(board_config, media, image_size, bootfs_label,
                      should_create_partitions, should_align_boot_part=False):
     cylinders = None
     if not media.is_block_device:
-        image_size_in_bytes = convert_size_to_bytes(image_size)
+        image_size_in_bytes = get_partition_size_in_bytes(image_size)
         cylinders = image_size_in_bytes / CYLINDER_SIZE
         proc = cmd_runner.run(
             ['dd', 'of=%s' % media.path,
@@ -131,7 +135,7 @@
     """
     cylinders = None
     if not media.is_block_device:
-        image_size_in_bytes = convert_size_to_bytes(image_size)
+        image_size_in_bytes = get_partition_size_in_bytes(image_size)
         cylinders = image_size_in_bytes / CYLINDER_SIZE
         proc = cmd_runner.run(
             ['dd', 'of=%s' % media.path,
@@ -478,14 +482,20 @@
             path, 'DeviceFile', dbus_interface=DBUS_PROPERTIES))
 
 
-def convert_size_to_bytes(size):
-    """Convert a size string in Kbytes, Mbytes or Gbytes to bytes."""
+def get_partition_size_in_bytes(size):
+    """Convert a size string in Kbytes, Mbytes or Gbytes to bytes.
+
+    The conversion rounds-up the size to the nearest MiB, considering a minimum
+    size of MIN_IMAGE_SIZE bytes. The conversion always assures to have a big
+    enough size for the partition.
+    """
     unit = size[-1].upper()
+    real_size = float(size[:-1])
+
     # no unit? (ends with a digit)
     if unit in '0123456789':
-        return int(round(float(size)))
-    real_size = float(size[:-1])
-    if unit == 'K':
+        real_size = float(size)
+    elif unit == 'K':
         real_size = real_size * 1024
     elif unit == 'M':
         real_size = real_size * 1024 * 1024
@@ -494,8 +504,20 @@
     else:
         raise ValueError("Unknown size format: %s.  Use K[bytes], M[bytes] "
                          "or G[bytes]" % size)
-
-    return int(round(real_size))
+    # Guarantee that is a multiple of ROUND_IMAGE_TO
+    real_size = _check_min_size(int(ceil(real_size / ROUND_IMAGE_TO) *
+                                    ROUND_IMAGE_TO))
+    return real_size
+
+
+def _check_min_size(size):
+    """Check that the image size is at least MIN_IMAGE_SIZE bytes.
+
+    :param size: The size of the image to check, as a number.
+    """
+    if (size < MIN_IMAGE_SIZE):
+        size = MIN_IMAGE_SIZE
+    return size
 
 
 def run_sfdisk_commands(commands, heads, sectors, cylinders, device,

=== modified file 'linaro_image_tools/media_create/tests/test_media_create.py'
--- linaro_image_tools/media_create/tests/test_media_create.py	2012-06-07 13:12:42 +0000
+++ linaro_image_tools/media_create/tests/test_media_create.py	2012-06-12 14:08:45 +0000
@@ -38,11 +38,11 @@
 from linaro_image_tools import cmd_runner
 import linaro_image_tools.media_create
 from linaro_image_tools.media_create import (
+    android_boards,
+    boards,
     check_device,
-    boards,
     partitions,
     rootfs,
-    android_boards,
     )
 from linaro_image_tools.media_create.boards import (
     SECTOR_SIZE,
@@ -64,8 +64,8 @@
     BoardConfig,
     )
 from linaro_image_tools.media_create.android_boards import (
+    AndroidSnowballEmmcConfig,
     android_board_configs,
-    AndroidSnowballEmmcConfig,
     )
 from linaro_image_tools.media_create.chroot_utils import (
     copy_file,
@@ -79,23 +79,25 @@
     )
 from linaro_image_tools.media_create.partitions import (
     HEADS,
+    MIN_IMAGE_SIZE,
+    Media,
     SECTORS,
+    _check_min_size,
+    _get_device_file_for_partition_number,
+    _parse_blkid_output,
+    calculate_android_partition_size_and_offset,
     calculate_partition_size_and_offset,
-    calculate_android_partition_size_and_offset,
-    convert_size_to_bytes,
     create_partitions,
     ensure_partition_is_not_mounted,
+    get_android_loopback_devices,
     get_boot_and_root_loopback_devices,
-    get_android_loopback_devices,
     get_boot_and_root_partitions_for_media,
-    Media,
+    get_partition_size_in_bytes,
+    get_uuid,
     partition_mounted,
     run_sfdisk_commands,
     setup_partitions,
-    get_uuid,
-    _parse_blkid_output,
     wait_partition_to_settle,
-    _get_device_file_for_partition_number,
     )
 from linaro_image_tools.media_create.rootfs import (
     append_to_fstab,
@@ -104,8 +106,8 @@
     move_contents,
     populate_rootfs,
     rootfs_mount_options,
+    update_network_interfaces,
     write_data_to_protected_file,
-    update_network_interfaces,
     )
 from linaro_image_tools.media_create.tests.fixtures import (
     CreateTarballFixture,
@@ -492,7 +494,9 @@
 
         class config(BoardConfig):
             pass
-        self.assertRaises(AssertionError, config.set_metadata, 'ahwpack.tar.gz')
+        self.assertRaises(AssertionError,
+                          config.set_metadata,
+                          'ahwpack.tar.gz')
 
 
 class TestGetMLOFile(TestCaseWithFixtures):
@@ -767,8 +771,11 @@
         uboot_file = os.path.join(uboot_dir, 'u-boot.bin')
         uboot_relative_file = uboot_file.replace(self.tempdir, '')
         with open(cfg_file, 'w') as f:
-                f.write('%s %s %i %#x %s\n' % ('NORMAL', uboot_relative_file, 0,
-                                               0xBA0000, '9'))
+                f.write('%s %s %i %#x %s\n' % ('NORMAL',
+                                               uboot_relative_file,
+                                               0,
+                                               0xBA0000,
+                                               '9'))
         with open(uboot_file, 'w') as f:
             file_info = boards.SnowballEmmcConfig.get_file_info(
                 self.tempdir, self.temp_bootdir_path)
@@ -781,8 +788,10 @@
         with open(cfg_file, 'w') as f:
                 f.write('%s %s %i %#x %s\n' % ('NORMAL', 'u-boot.bin', 0,
                                                0xBA0000, '9'))
-        self.assertRaises(AssertionError, boards.SnowballEmmcConfig.get_file_info,
-                          self.tempdir, self.temp_bootdir_path)
+        self.assertRaises(AssertionError,
+                          boards.SnowballEmmcConfig.get_file_info,
+                          self.tempdir,
+                          self.temp_bootdir_path)
 
     def test_file_name_size(self):
         ''' Test using a to large toc file '''
@@ -961,7 +970,8 @@
         super(TestBootSteps, self).setUp()
         self.funcs_calls = []
         self.mock_all_boards_funcs()
-        linaro_image_tools.media_create.boards.BoardConfig.hwpack_format = '1.0'
+        linaro_image_tools.media_create.boards.BoardConfig.hwpack_format = \
+        '1.0'
 
     def mock_all_boards_funcs(self):
         """Mock functions of boards module with a call tracer."""
@@ -1037,8 +1047,8 @@
             lambda: '1.0')
         self.make_boot_files(boards.SMDKV310Config)
         expected = [
-            'install_samsung_boot_loader', 'make_flashable_env', '_dd', 'make_uImage',
-            'make_uInitrd', 'make_boot_script']
+            'install_samsung_boot_loader', 'make_flashable_env', '_dd',
+            'make_uImage', 'make_uInitrd', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_origen_steps(self):
@@ -1058,8 +1068,8 @@
             lambda: '1.0')
         self.make_boot_files(boards.OrigenConfig)
         expected = [
-            'install_samsung_boot_loader', 'make_flashable_env', '_dd', 'make_uImage',
-            'make_uInitrd', 'make_boot_script']
+            'install_samsung_boot_loader', 'make_flashable_env', '_dd',
+            'make_uImage', 'make_uInitrd', 'make_boot_script']
         self.assertEqual(expected, self.funcs_calls)
 
     def test_ux500_steps(self):
@@ -2424,32 +2434,46 @@
             '98367,-,E\n98367,65536,L\n294975,131072,L\n' \
             '426047,,,-', '%s' % self.android_image_size)
 
+    def test_check_min_size_small(self):
+        """Check that we get back the minimum size as expeceted."""
+        self.assertEqual(MIN_IMAGE_SIZE, _check_min_size(12345))
+
+    def test_check_min_size_big(self):
+        """Check that we get back the same value we pass."""
+        self.assertEqual(MIN_IMAGE_SIZE * 3, _check_min_size(3145728))
+
+    def test_convert_size_wrong_suffix(self):
+        self.assertRaises(ValueError, get_partition_size_in_bytes, "123456H")
+
     def test_convert_size_no_suffix(self):
-        self.assertEqual(524288, convert_size_to_bytes('524288'))
+        self.assertEqual(2 ** 20, get_partition_size_in_bytes('123456'))
+
+    def test_convert_size_one_mbyte(self):
+        self.assertEqual(2 ** 20, get_partition_size_in_bytes('1M'))
 
     def test_convert_size_in_kbytes_to_bytes(self):
-        self.assertEqual(512 * 1024, convert_size_to_bytes('512K'))
+        self.assertEqual(2 * 2 ** 20, get_partition_size_in_bytes('2048K'))
 
     def test_convert_size_in_mbytes_to_bytes(self):
-        self.assertEqual(100 * 1024 ** 2, convert_size_to_bytes('100M'))
+        self.assertEqual(100 * 2 ** 20, get_partition_size_in_bytes('100M'))
 
     def test_convert_size_in_gbytes_to_bytes(self):
-        self.assertEqual(12 * 1024 ** 3, convert_size_to_bytes('12G'))
+        self.assertEqual(12 * 2 ** 30, get_partition_size_in_bytes('12G'))
 
     def test_convert_size_float_no_suffix(self):
-        self.assertEqual(1539, convert_size_to_bytes('1539.49'))
-
-    def test_convert_size_float_round_up(self):
-        self.assertEqual(1540, convert_size_to_bytes('1539.50'))
+        self.assertEqual(3 * 2 ** 20, get_partition_size_in_bytes('2348576.91'))
 
     def test_convert_size_float_in_kbytes_to_bytes(self):
-        self.assertEqual(int(round(234.8 * 1024)), convert_size_to_bytes('234.8K'))
+        self.assertEqual(3 * 2 ** 20, get_partition_size_in_bytes('2345.8K'))
+
+    def test_convert_size_float_in_mbytes_to_bytes_double(self):
+        self.assertEqual(2 * 2 ** 20, get_partition_size_in_bytes('1.0000001M'))
 
     def test_convert_size_float_in_mbytes_to_bytes(self):
-        self.assertEqual(int(round(876.123 * 1024 ** 2)), convert_size_to_bytes('876.123M'))
+        self.assertEqual(877 * 2 ** 20, get_partition_size_in_bytes('876.123M'))
 
     def test_convert_size_float_in_gbytes_to_bytes(self):
-        self.assertEqual(int(round(1.9 * 1024 ** 3)), convert_size_to_bytes('1.9G'))
+        self.assertEqual(1946 * 2 ** 20, get_partition_size_in_bytes('1.9G'))
 
     def test_calculate_partition_size_and_offset(self):
         tmpfile = self._create_tmpfile()
@@ -3400,6 +3424,7 @@
 
         # Ensure the list of cleanup functions gets cleared to make sure tests
         # don't interfere with one another.
+
         def clear_atexits():
             linaro_image_tools.media_create.chroot_utils.local_atexit = []
         self.addCleanup(clear_atexits)

