=== modified file 'linaro_image_tools/media_create/partitions.py'
@@ -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'
@@ -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)