=== modified file 'linaro_media_create/boards.py'
@@ -29,6 +29,8 @@
import os
import re
import tempfile
+import struct
+from binascii import crc32
from linaro_media_create import cmd_runner
from linaro_media_create.partitions import SECTOR_SIZE
@@ -63,6 +65,44 @@
# 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
+# * BL1 (SPL) is expected at offset +1s and is 32s long
+# * BL2 (u-boot) is loaded at a raw MMC offset of +65s by BL1 which currently
+# doesn't support FAT
+# * the u-boot environment is at +33s and is 32s long (16 KiB)
+# * currently, some hardware issues on certain boards causes u-boot to not be
+# able to use FAT to load uImage and uInitrd (or boot.scr); as a temporary
+# workaround, these are loaded from +1089s and +9281s respectively
+# * hence we hardcode all offsets, make sure that the files aren't larger than
+# their reserved spot, and create a bootloader partition from the first
+# sector after MBR up to end of initrd
+SAMSUNG_V310_BL1_START = 1
+SAMSUNG_V310_BL1_LEN = 32
+SAMSUNG_V310_ENV_START = SAMSUNG_V310_BL1_START + SAMSUNG_V310_BL1_LEN
+SAMSUNG_V310_ENV_LEN = 32
+assert SAMSUNG_V310_ENV_START == 33, "BL1 expects u-boot environment at +33s"
+assert SAMSUNG_V310_ENV_LEN * SECTOR_SIZE == 16 * 1024, (
+ "BL1 expects u-boot environment to be 16 KiB")
+SAMSUNG_V310_BL2_START = SAMSUNG_V310_ENV_START + SAMSUNG_V310_ENV_LEN
+SAMSUNG_V310_BL2_LEN = 1024
+assert SAMSUNG_V310_BL2_LEN * SECTOR_SIZE == 512 * 1024, (
+ "BL1 expects BL2 (u-boot) to be 512 KiB")
+SAMSUNG_V310_UIMAGE_START = SAMSUNG_V310_BL2_START + SAMSUNG_V310_BL2_LEN
+SAMSUNG_V310_UIMAGE_LEN = 8192
+assert SAMSUNG_V310_UIMAGE_START == 1089, (
+ "BL2 (u-boot) expects uImage at +1089s")
+assert SAMSUNG_V310_UIMAGE_LEN * SECTOR_SIZE == 4 * 1024 * 1024, (
+ "BL2 (u-boot) expects uImage to be 4 MiB")
+SAMSUNG_V310_UINITRD_START = (
+ SAMSUNG_V310_UIMAGE_START + SAMSUNG_V310_UIMAGE_LEN)
+SAMSUNG_V310_UINITRD_RESERVED_LEN = 204800
+SAMSUNG_V310_UINITRD_COPY_LEN = 32768
+assert SAMSUNG_V310_UINITRD_START == 9281, (
+ "BL2 (u-boot) expects uInitrd at +9281s")
+assert SAMSUNG_V310_UINITRD_RESERVED_LEN * SECTOR_SIZE == 100 * 1024 * 1024, (
+ "BL2 (u-boot) expects uInitrd to be 100 MiB")
+assert SAMSUNG_V310_UINITRD_COPY_LEN * SECTOR_SIZE == 16 * 1024 * 1024, (
+ "Only copy 16MiB for a faster boot")
def align_partition(min_start, min_length, start_alignment, end_alignment):
"""Compute partition start and end offsets based on specified constraints.
@@ -81,6 +121,14 @@
return start, end, length
+class classproperty(object):
+ """A descriptor that provides @property behavior on class methods."""
+ def __init__(self, getter):
+ self.getter = getter
+ def __get__(self, instance, cls):
+ return self.getter(cls)
+
+
class BoardConfig(object):
"""The configuration used when building an image for a board."""
# These attributes may not need to be redefined on some subclasses.
@@ -139,9 +187,24 @@
return '%s,%s,%s,*\n%s,,,-' % (
boot_start, boot_len, partition_type, root_start)
+ @classproperty
+ def bootcmd(cls):
+ """Get the bootcmd for this board.
+
+ In general subclasses should not have to override this.
+ """
+ replacements = dict(
+ mmc_option=cls.mmc_option, kernel_addr=cls.kernel_addr,
+ initrd_addr=cls.initrd_addr)
+ return (
+ "fatload mmc %(mmc_option)s %(kernel_addr)s "
+ "uImage; fatload mmc %(mmc_option)s %(initrd_addr)s uInitrd; "
+ "bootm %(kernel_addr)s %(initrd_addr)s"
+ % replacements)
+
@classmethod
- def _get_boot_cmd(cls, is_live, is_lowmem, consoles, rootfs_uuid):
- """Get the boot command for this board.
+ def _get_bootargs(cls, is_live, is_lowmem, consoles, rootfs_uuid):
+ """Get the bootargs for this board.
In general subclasses should not have to override this.
"""
@@ -161,30 +224,37 @@
lowmem_opt = 'only-ubiquity'
replacements = dict(
- mmc_option=cls.mmc_option, kernel_addr=cls.kernel_addr,
- initrd_addr=cls.initrd_addr, serial_opts=serial_opts,
+ serial_opts=serial_opts,
lowmem_opt=lowmem_opt, boot_snippet=boot_snippet,
boot_args_options=boot_args_options)
return (
- "setenv bootcmd 'fatload mmc %(mmc_option)s %(kernel_addr)s "
- "uImage; fatload mmc %(mmc_option)s %(initrd_addr)s uInitrd; "
- "bootm %(kernel_addr)s %(initrd_addr)s'\n"
- "setenv bootargs '%(serial_opts)s %(lowmem_opt)s "
- "%(boot_snippet)s %(boot_args_options)s'\n"
- "boot" % replacements)
+ "%(serial_opts)s %(lowmem_opt)s "
+ "%(boot_snippet)s %(boot_args_options)s"
+ % replacements)
+
+ @classmethod
+ def _get_boot_env(cls, is_live, is_lowmem, consoles, rootfs_uuid):
+ """Get the boot environment for this board.
+
+ In general subclasses should not have to override this.
+ """
+ boot_env = {}
+ boot_env["bootargs"] = cls._get_bootargs(
+ is_live, is_lowmem, consoles, rootfs_uuid)
+ boot_env["bootcmd"] = cls.bootcmd
+ return boot_env
@classmethod
def make_boot_files(cls, uboot_parts_dir, is_live, is_lowmem, consoles,
- root_dir, rootfs_uuid, boot_dir, boot_script,
+ chroot_dir, rootfs_uuid, boot_dir, boot_script,
boot_device_or_file):
- boot_cmd = cls._get_boot_cmd(
- is_live, is_lowmem, consoles, rootfs_uuid)
+ boot_env = cls._get_boot_env(is_live, is_lowmem, consoles, rootfs_uuid)
cls._make_boot_files(
- uboot_parts_dir, boot_cmd, root_dir, boot_dir, boot_script,
+ uboot_parts_dir, boot_env, chroot_dir, boot_dir, boot_script,
boot_device_or_file)
@classmethod
- def _make_boot_files(cls, uboot_parts_dir, boot_cmd, root_dir, boot_dir,
+ def _make_boot_files(cls, uboot_parts_dir, boot_env, chroot_dir, boot_dir,
boot_script, boot_device_or_file):
"""Make the necessary boot files for this board.
@@ -194,14 +264,6 @@
raise NotImplementedError()
-class classproperty(object):
- """A descriptor that provides @property behavior on class methods."""
- def __init__(self, getter):
- self.getter = getter
- def __get__(self, instance, cls):
- return self.getter(cls)
-
-
class OmapConfig(BoardConfig):
kernel_suffix = 'linaro-omap'
uboot_in_boot_part = True
@@ -248,24 +310,24 @@
@classmethod
def make_boot_files(cls, uboot_parts_dir, is_live, is_lowmem, consoles,
- root_dir, rootfs_uuid, boot_dir, boot_script,
+ chroot_dir, rootfs_uuid, boot_dir, boot_script,
boot_device_or_file):
# XXX: This is also part of our temporary hack to fix bug 697824; we
# need to call set_appropriate_serial_tty() before doing anything that
# may use cls.serial_tty.
- cls.set_appropriate_serial_tty(root_dir)
+ cls.set_appropriate_serial_tty(chroot_dir)
super(OmapConfig, cls).make_boot_files(
- uboot_parts_dir, is_live, is_lowmem, consoles, root_dir,
+ uboot_parts_dir, is_live, is_lowmem, consoles, chroot_dir,
rootfs_uuid, boot_dir, boot_script, boot_device_or_file)
@classmethod
- def _make_boot_files(cls, uboot_parts_dir, boot_cmd, chroot_dir,
- boot_dir, boot_script, boot_device_or_file):
+ def _make_boot_files(cls, uboot_parts_dir, boot_env, chroot_dir, boot_dir,
+ boot_script, boot_device_or_file):
install_omap_boot_loader(chroot_dir, boot_dir)
make_uImage(
cls.load_addr, uboot_parts_dir, cls.kernel_suffix, boot_dir)
make_uInitrd(uboot_parts_dir, cls.kernel_suffix, boot_dir)
- make_boot_script(boot_cmd, boot_script)
+ make_boot_script(boot_env, boot_script)
make_boot_ini(boot_script, boot_dir)
@@ -315,12 +377,12 @@
uboot_flavor = None
@classmethod
- def _make_boot_files(cls, uboot_parts_dir, boot_cmd, chroot_dir,
- boot_dir, boot_script, boot_device_or_file):
+ def _make_boot_files(cls, uboot_parts_dir, boot_env, chroot_dir, boot_dir,
+ boot_script, boot_device_or_file):
make_uImage(
cls.load_addr, uboot_parts_dir, cls.kernel_suffix, boot_dir)
make_uInitrd(uboot_parts_dir, cls.kernel_suffix, boot_dir)
- make_boot_script(boot_cmd, boot_script)
+ make_boot_script(boot_env, boot_script)
make_boot_ini(boot_script, boot_dir)
@@ -341,12 +403,12 @@
mmc_option = '1:1'
@classmethod
- def _make_boot_files(cls, uboot_parts_dir, boot_cmd, chroot_dir,
- boot_dir, boot_script, boot_device_or_file):
+ def _make_boot_files(cls, uboot_parts_dir, boot_env, chroot_dir, boot_dir,
+ boot_script, boot_device_or_file):
make_uImage(
cls.load_addr, uboot_parts_dir, cls.kernel_suffix, boot_dir)
make_uInitrd(uboot_parts_dir, cls.kernel_suffix, boot_dir)
- make_boot_script(boot_cmd, boot_script)
+ make_boot_script(boot_env, boot_script)
class Mx5Config(BoardConfig):
@@ -390,15 +452,15 @@
loader_start, loader_len, boot_start, boot_len, root_start)
@classmethod
- def _make_boot_files(cls, uboot_parts_dir, boot_cmd, chroot_dir,
- boot_dir, boot_script, boot_device_or_file):
+ def _make_boot_files(cls, uboot_parts_dir, boot_env, chroot_dir, boot_dir,
+ boot_script, boot_device_or_file):
uboot_file = 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)
make_uImage(
cls.load_addr, uboot_parts_dir, cls.kernel_suffix, boot_dir)
make_uInitrd(uboot_parts_dir, cls.kernel_suffix, boot_dir)
- make_boot_script(boot_cmd, boot_script)
+ make_boot_script(boot_env, boot_script)
class EfikamxConfig(Mx5Config):
@@ -433,12 +495,90 @@
fat_size = 16
@classmethod
- def _make_boot_files(cls, uboot_parts_dir, boot_cmd, chroot_dir,
- boot_dir, boot_script, boot_device_or_file):
+ def _make_boot_files(cls, uboot_parts_dir, boot_env, chroot_dir, boot_dir,
+ boot_script, boot_device_or_file):
make_uImage(
cls.load_addr, uboot_parts_dir, cls.kernel_suffix, boot_dir)
make_uInitrd(uboot_parts_dir, cls.kernel_suffix, boot_dir)
+class SMDKV310Config(BoardConfig):
+ serial_tty = 'ttySAC1'
+ extra_serial_opts = 'console=%s,115200n8' % serial_tty
+ kernel_addr = '0x40007000'
+ initrd_addr = '0x41000000'
+ load_addr = '0x40008000'
+ kernel_suffix = 's5pv310'
+ boot_script = 'boot.scr'
+ mmc_part_offset = 1
+ mmc_option = '0:2'
+
+ @classmethod
+ def get_sfdisk_cmd(cls, should_align_boot_part=False):
+ # bootloader partition needs to hold everything from BL1 to uInitrd
+ # inclusive
+ min_len = (
+ SAMSUNG_V310_UINITRD_START + SAMSUNG_V310_UINITRD_RESERVED_LEN -
+ SAMSUNG_V310_BL1_START)
+
+ # bootloader partition
+ loader_start, loader_end, loader_len = align_partition(
+ 1, min_len, 1, PART_ALIGN_S)
+
+ # FAT boot partition
+ boot_start, boot_end, boot_len = align_partition(
+ loader_end + 1, 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)
+
+ return '%s,%s,0xDA\n%s,%s,0x0C,*\n%s,,,-' % (
+ loader_start, loader_len, boot_start, boot_len, root_start)
+
+ @classmethod
+ def _get_boot_env(cls, is_live, is_lowmem, consoles, rootfs_uuid):
+ boot_env = super(SMDKV310Config, cls)._get_boot_env(
+ is_live, is_lowmem, consoles, rootfs_uuid)
+
+ boot_env["ethact"] = "smc911x-0"
+ boot_env["ethaddr"] = "00:40:5c:26:0a:5b"
+ # XXX fixme once FAT support is fixed in u-boot bug 727978
+ boot_env["bootcmd"] = (
+ "movi read kernel %(kernel_addr)s; "
+ "movi read rootfs %(initrd_addr)s %(rootfs_size)s; "
+ "bootm %(kernel_addr)s %(initrd_addr)s" % {
+ 'kernel_addr': cls.kernel_addr,
+ 'initrd_addr': cls.initrd_addr,
+ 'rootfs_size': hex(SAMSUNG_V310_UINITRD_COPY_LEN * SECTOR_SIZE)})
+
+ return boot_env
+
+ @classmethod
+ def _make_boot_files(cls, uboot_parts_dir, boot_env, chroot_dir, boot_dir,
+ boot_script, boot_device_or_file):
+ uboot_file = os.path.join(
+ chroot_dir, 'usr', 'lib', 'u-boot', 'smdkv310', 'u-boot.v310')
+ install_smdkv310_boot_loader(uboot_file, boot_device_or_file)
+
+ env_size = SAMSUNG_V310_ENV_LEN * SECTOR_SIZE
+ env_file = make_flashable_env(boot_env, env_size)
+ install_smdkv310_boot_env(env_file, boot_device_or_file)
+
+ uImage_file = make_uImage(
+ cls.load_addr, uboot_parts_dir, cls.kernel_suffix, boot_dir)
+ install_smdkv310_uImage(uImage_file, boot_device_or_file)
+
+ uInitrd_file = make_uInitrd(
+ uboot_parts_dir, cls.kernel_suffix, boot_dir)
+ install_smdkv310_initrd(uInitrd_file, boot_device_or_file)
+
+ # unused at the moment once FAT support enabled for the
+ # Samsung u-boot this can be used bug 727978
+ #make_boot_script(boot_env, boot_script)
+
board_configs = {
'beagle': BeagleConfig,
@@ -450,9 +590,26 @@
'mx51evk': Mx51evkConfig,
'mx53loco' : Mx53LoCoConfig,
'overo': OveroConfig,
+ 'smdkv310': SMDKV310Config,
}
+def _dd(input_file, output_file, block_size=SECTOR_SIZE, count=None, seek=None,
+ skip=None):
+ """Wrapper around the dd command"""
+ cmd = [
+ "dd", "if=%s" % input_file, "of=%s" % output_file,
+ "bs=%s" % block_size, "conv=notrunc"]
+ if count is not None:
+ cmd.append("count=%s" % count)
+ if seek is not None:
+ cmd.append("seek=%s" % seek)
+ if skip is not None:
+ cmd.append("skip=%s" % skip)
+ proc = cmd_runner.run(cmd, as_root=True)
+ proc.wait()
+
+
def _run_mkimage(img_type, load_addr, entry_point, name, img_data, img,
stdout=None, as_root=True):
cmd = ['mkimage',
@@ -491,18 +648,26 @@
img_data = _get_file_matching(
'%s/vmlinuz-*-%s' % (uboot_parts_dir, suffix))
img = '%s/uImage' % boot_disk
- return _run_mkimage(
+ _run_mkimage(
'kernel', load_addr, load_addr, 'Linux', img_data, img)
+ return img
def make_uInitrd(uboot_parts_dir, suffix, boot_disk):
img_data = _get_file_matching(
'%s/initrd.img-*-%s' % (uboot_parts_dir, suffix))
img = '%s/uInitrd' % boot_disk
- return _run_mkimage('ramdisk', '0', '0', 'initramfs', img_data, img)
-
-
-def make_boot_script(boot_script_data, boot_script):
+ _run_mkimage('ramdisk', '0', '0', 'initramfs', img_data, img)
+ return img
+
+
+def make_boot_script(boot_env, boot_script):
+ boot_script_data = (
+ "setenv bootcmd '%(bootcmd)s'\n"
+ "setenv bootargs '%(bootargs)s'\n"
+ "boot"
+ % boot_env)
+
# Need to save the boot script data into a file that will be passed to
# mkimage.
_, tmpfile = tempfile.mkstemp()
@@ -516,15 +681,40 @@
'script', '0', '0', 'boot script', plain_boot_script, boot_script)
+def make_flashable_env(boot_env, env_size):
+ env_strings = ["%s=%s" % (k, v) for k, v in boot_env.items()]
+ env_strings.sort()
+ env = struct.pack('B', 0).join(env_strings)
+
+ # we still need to zero-terminate the last string, and 4 bytes for crc
+ assert len(env) + 1 + 4 <= env_size, (
+ "environment doesn't fit in %s bytes" % env_size)
+
+ # pad the rest of the env for the CRC calc; the "s" format will write zero
+ # bytes to pad the (empty) string to repeat count
+ env += struct.pack('%ss' % (env_size - len(env) - 4), '')
+
+ crc = crc32(env)
+ env = struct.pack('<i', crc) + env
+
+ _, tmpfile = tempfile.mkstemp()
+
+ with open(tmpfile, 'w') as fd:
+ fd.write(env)
+
+ return tmpfile
+
+
def install_mx5_boot_loader(imx_file, boot_device_or_file):
- proc = cmd_runner.run([
- "dd",
- "if=%s" % imx_file,
- "of=%s" % boot_device_or_file,
- "bs=1024",
- "seek=1",
- "conv=notrunc"], as_root=True)
- proc.wait()
+ # 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
+ 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)
def _get_mlo_file(chroot_dir):
@@ -561,3 +751,54 @@
proc = cmd_runner.run(
["cp", "-v", boot_script, "%s/boot.ini" % boot_disk], as_root=True)
proc.wait()
+
+
+def install_smdkv310_uImage(uImage_file, boot_device_or_file):
+ # the layout keeps SAMSUNG_V310_UIMAGE_LEN sectors for uImage; make sure
+ # uImage isn't actually larger or it would be truncated
+ max_size = SAMSUNG_V310_UIMAGE_LEN * SECTOR_SIZE
+ assert os.path.getsize(uImage_file) <= max_size, (
+ "%s is larger than the allocated v310 uImage length" % uImage_file)
+ _dd(uImage_file, boot_device_or_file, count=SAMSUNG_V310_UIMAGE_LEN,
+ seek=SAMSUNG_V310_UIMAGE_START)
+
+
+def install_smdkv310_initrd(initrd_file, boot_device_or_file):
+ # the layout keeps SAMSUNG_V310_UINITRD_RESERVED_LEN sectors for uInitrd
+ # but only SAMSUNG_V310_UINITRD_COPY_LEN sectors are loaded into memory;
+ # make sure uInitrd isn't actually larger or it would be truncated in
+ # memory
+ max_size = SAMSUNG_V310_UINITRD_COPY_LEN * SECTOR_SIZE
+ assert os.path.getsize(initrd_file) <= max_size, (
+ "%s is larger than the v310 uInitrd length as used by u-boot"
+ % initrd_file)
+ _dd(initrd_file, boot_device_or_file,
+ count=SAMSUNG_V310_UINITRD_COPY_LEN,
+ seek=SAMSUNG_V310_UINITRD_START)
+
+
+def install_smdkv310_boot_env(env_file, boot_device_or_file):
+ # the environment file is exactly SAMSUNG_V310_ENV_LEN as created by
+ # make_flashable_env(), so we don't need to check the size of env_file
+ _dd(env_file, boot_device_or_file, count=SAMSUNG_V310_ENV_LEN,
+ seek=SAMSUNG_V310_ENV_START)
+
+
+def install_smdkv310_boot_loader(v310_file, boot_device_or_file):
+ """Samsung specific terminology
+ BL0 is the first stage bootloader,
+ BL1 is the SPL (secondary program loader)
+ v310_file is a binary with the same layout as BL1 + u-boot environment +
+ BL2; write BL1 (SPL) piece first (SAMSUNG_V310_BL1_LEN sectors at +0s in
+ the file and +SAMSUNG_V310_BL1_START on disk), then write BL2 (u-boot)
+ piece (rest of the file starting at +(SAMSUNG_V310_BL1_LEN +
+ SAMSUNG_V310_ENV_LEN)s in the file which is the same as
+ +(SAMSUNG_V310_BL2_START - SAMSUNG_V310_BL1_START)s)
+ """
+ _dd(v310_file, boot_device_or_file, count=SAMSUNG_V310_BL1_LEN,
+ seek=SAMSUNG_V310_BL1_START)
+ # XXX need to check that the length of v310_file - 64s is smaller than
+ # SAMSUNG_V310_BL2_LEN
+ _dd(v310_file, boot_device_or_file, seek=SAMSUNG_V310_BL2_START,
+ skip=(SAMSUNG_V310_BL2_START - SAMSUNG_V310_BL1_START))
+
=== modified file 'linaro_media_create/tests/test_media_create.py'
@@ -43,9 +43,12 @@
)
import linaro_media_create
from linaro_media_create.boards import (
+ LOADER_MIN_SIZE_S,
+ SECTOR_SIZE,
align_up,
align_partition,
board_configs,
+ make_flashable_env,
install_mx5_boot_loader,
install_omap_boot_loader,
make_boot_script,
@@ -258,6 +261,15 @@
'make_boot_script']
self.assertEqual(expected, self.funcs_calls)
+ def test_smdkv310_steps(self):
+ self.make_boot_files(boards.SMDKV310Config)
+ expected = [
+ 'install_smdkv310_boot_loader', 'make_flashable_env',
+ 'install_smdkv310_boot_env', 'make_uImage',
+ 'install_smdkv310_uImage', 'make_uInitrd',
+ 'install_smdkv310_initrd',]
+ self.assertEqual(expected, self.funcs_calls)
+
def test_ux500_steps(self):
self.make_boot_files(boards.Ux500Config)
expected = ['make_uImage', 'make_uInitrd', 'make_boot_script']
@@ -372,44 +384,67 @@
'1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-',
boards.Mx5Config.get_sfdisk_cmd())
+ def test_smdkv310(self):
+ self.assertEquals(
+ '1,221183,0xDA\n221184,106496,0x0C,*\n327680,,,-',
+ board_configs['smdkv310'].get_sfdisk_cmd())
+
class TestGetBootCmd(TestCase):
def test_vexpress(self):
- boot_cmd = board_configs['vexpress']._get_boot_cmd(
+ boot_commands = board_configs['vexpress']._get_boot_env(
is_live=False, is_lowmem=False, consoles=['ttyXXX'],
rootfs_uuid="deadbeef")
- expected = (
- "setenv bootcmd 'fatload mmc 0:1 0x60008000 uImage; fatload mmc "
- "0:1 0x81000000 uInitrd; bootm 0x60008000 0x81000000'\nsetenv "
- "bootargs 'console=tty0 console=ttyAMA0,38400n8 console=ttyXXX "
- "root=UUID=deadbeef rootwait ro'\nboot")
- self.assertEqual(expected, boot_cmd)
+ expected = {
+ 'bootargs': 'console=tty0 console=ttyAMA0,38400n8 console=ttyXXX '
+ 'root=UUID=deadbeef rootwait ro',
+ 'bootcmd': 'fatload mmc 0:1 0x60008000 uImage; '
+ 'fatload mmc 0:1 0x81000000 uInitrd; '
+ 'bootm 0x60008000 0x81000000'}
+ self.assertEqual(expected, boot_commands)
def test_mx5(self):
- boot_cmd = boards.Mx5Config._get_boot_cmd(
- is_live=False, is_lowmem=False, consoles=[],
- rootfs_uuid="deadbeef")
- expected = (
- "setenv bootcmd 'fatload mmc 0:2 0x90000000 uImage; fatload mmc "
- "0:2 0x90800000 uInitrd; bootm 0x90000000 0x90800000'\nsetenv "
- "bootargs 'console=tty0 console=ttymxc0,115200n8 "
- "root=UUID=deadbeef rootwait ro'\nboot")
- self.assertEqual(expected, boot_cmd)
+ boot_commands = boards.Mx5Config._get_boot_env(
+ is_live=False, is_lowmem=False, consoles=[],
+ rootfs_uuid="deadbeef")
+ expected = {
+ 'bootargs': 'console=tty0 console=ttymxc0,115200n8 '
+ 'root=UUID=deadbeef rootwait ro',
+ 'bootcmd': 'fatload mmc 0:2 0x90000000 uImage; '
+ 'fatload mmc 0:2 0x90800000 uInitrd; '
+ 'bootm 0x90000000 0x90800000'}
+ self.assertEqual(expected, boot_commands)
+
+ def test_smdkv310(self):
+ boot_commands = board_configs['smdkv310']._get_boot_env(
+ is_live=False, is_lowmem=False, consoles=[],
+ rootfs_uuid="deadbeef")
+ expected = {
+ 'bootargs': 'console=ttySAC1,115200n8 root=UUID=deadbeef '
+ 'rootwait ro',
+ 'bootcmd': 'movi read kernel 0x40007000; '
+ 'movi read rootfs 0x41000000 0x1000000; '
+ 'bootm 0x40007000 0x41000000',
+ 'ethact': 'smc911x-0',
+ 'ethaddr': '00:40:5c:26:0a:5b'}
+ self.assertEqual(expected, boot_commands)
def test_ux500(self):
- boot_cmd = board_configs['ux500']._get_boot_cmd(
+ boot_commands = board_configs['ux500']._get_boot_env(
is_live=False, is_lowmem=False, consoles=[],
rootfs_uuid="deadbeef")
- expected = (
- "setenv bootcmd 'fatload mmc 1:1 0x00100000 uImage; fatload mmc "
- "1:1 0x08000000 uInitrd; bootm 0x00100000 0x08000000'\nsetenv "
- "bootargs 'console=tty0 console=ttyAMA2,115200n8 "
- "root=UUID=deadbeef rootwait ro earlyprintk rootdelay=1 fixrtc "
- "nocompcache mem=96M@0 mem_modem=32M@96M mem=44M@128M "
- "pmem=22M@172M mem=30M@194M mem_mali=32M@224M "
- "pmem_hwb=54M@256M hwmem=48M@302M mem=152M@360M'\nboot")
- self.assertEqual(expected, boot_cmd)
+ expected = {
+ 'bootargs': 'console=tty0 console=ttyAMA2,115200n8 '
+ 'root=UUID=deadbeef rootwait ro earlyprintk '
+ 'rootdelay=1 fixrtc nocompcache mem=96M@0 '
+ 'mem_modem=32M@96M mem=44M@128M pmem=22M@172M '
+ 'mem=30M@194M mem_mali=32M@224M pmem_hwb=54M@256M '
+ 'hwmem=48M@302M mem=152M@360M',
+ 'bootcmd': 'fatload mmc 1:1 0x00100000 uImage; '
+ 'fatload mmc 1:1 0x08000000 uInitrd; '
+ 'bootm 0x00100000 0x08000000'}
+ self.assertEqual(expected, boot_commands)
def test_panda(self):
# XXX: To fix bug 697824 we have to change class attributes of our
@@ -417,17 +452,18 @@
# don't interfere with us we'll reset that before doing anything.
config = board_configs['panda']
config.serial_tty = config._serial_tty
- boot_cmd = config._get_boot_cmd(
+ boot_commands = config._get_boot_env(
is_live=False, is_lowmem=False, consoles=[],
rootfs_uuid="deadbeef")
- expected = (
- "setenv bootcmd 'fatload mmc 0:1 0x80200000 uImage; fatload mmc "
- "0:1 0x81600000 uInitrd; bootm 0x80200000 0x81600000'\nsetenv "
- "bootargs 'console=tty0 console=ttyO2,115200n8 "
- "root=UUID=deadbeef rootwait ro earlyprintk fixrtc nocompcache "
- "vram=32M omapfb.vram=0:8M mem=463M "
- "ip=none'\nboot")
- self.assertEqual(expected, boot_cmd)
+ expected = {
+ 'bootargs': 'console=tty0 console=ttyO2,115200n8 '
+ 'root=UUID=deadbeef rootwait ro earlyprintk fixrtc '
+ 'nocompcache vram=32M omapfb.vram=0:8M mem=463M '
+ 'ip=none',
+ 'bootcmd': 'fatload mmc 0:1 0x80200000 uImage; '
+ 'fatload mmc 0:1 0x81600000 uInitrd; '
+ 'bootm 0x80200000 0x81600000'}
+ self.assertEqual(expected, boot_commands)
def test_beagle(self):
# XXX: To fix bug 697824 we have to change class attributes of our
@@ -435,17 +471,17 @@
# don't interfere with us we'll reset that before doing anything.
config = board_configs['beagle']
config.serial_tty = config._serial_tty
- boot_cmd = config._get_boot_cmd(
+ boot_commands = config._get_boot_env(
is_live=False, is_lowmem=False, consoles=[],
rootfs_uuid="deadbeef")
- expected = (
- "setenv bootcmd 'fatload mmc 0:1 0x80000000 uImage; "
- "fatload mmc 0:1 0x81600000 uInitrd; bootm 0x80000000 "
- "0x81600000'\nsetenv bootargs 'console=tty0 "
- "console=ttyO2,115200n8 root=UUID=deadbeef rootwait ro "
- "earlyprintk fixrtc nocompcache vram=12M "
- "omapfb.mode=dvi:1280x720MR-16@60'\nboot")
- self.assertEqual(expected, boot_cmd)
+ expected = {
+ 'bootargs': 'console=tty0 console=ttyO2,115200n8 '
+ 'root=UUID=deadbeef rootwait ro earlyprintk fixrtc '
+ 'nocompcache vram=12M omapfb.mode=dvi:1280x720MR-16@60',
+ 'bootcmd': 'fatload mmc 0:1 0x80000000 uImage; '
+ 'fatload mmc 0:1 0x81600000 uInitrd; '
+ 'bootm 0x80000000 0x81600000'}
+ self.assertEqual(expected, boot_commands)
def test_overo(self):
# XXX: To fix bug 697824 we have to change class attributes of our
@@ -453,17 +489,19 @@
# don't interfere with us we'll reset that before doing anything.
config = board_configs['overo']
config.serial_tty = config._serial_tty
- boot_cmd = config._get_boot_cmd(
+ boot_commands = config._get_boot_env(
is_live=False, is_lowmem=False, consoles=[],
rootfs_uuid="deadbeef")
- expected = (
- "setenv bootcmd 'fatload mmc 0:1 0x80000000 uImage; "
- "fatload mmc 0:1 0x81600000 uInitrd; bootm 0x80000000 "
- "0x81600000'\nsetenv bootargs 'console=tty0 "
- "console=ttyO2,115200n8 root=UUID=deadbeef rootwait ro "
- "earlyprintk mpurate=500 vram=12M "
- "omapfb.mode=dvi:1024x768MR-16@60 omapdss.def_disp=dvi'\nboot")
- self.assertEqual(expected, boot_cmd)
+ expected = {
+ 'bootargs': 'console=tty0 console=ttyO2,115200n8 '
+ 'root=UUID=deadbeef rootwait ro earlyprintk '
+ 'mpurate=500 vram=12M '
+ 'omapfb.mode=dvi:1024x768MR-16@60 '
+ 'omapdss.def_disp=dvi',
+ 'bootcmd': 'fatload mmc 0:1 0x80000000 uImage; '
+ 'fatload mmc 0:1 0x81600000 uInitrd; '
+ 'bootm 0x80000000 0x81600000'}
+ self.assertEqual(expected, boot_commands)
class TestUnpackBinaryTarball(TestCaseWithFixtures):
@@ -586,14 +624,35 @@
'-d', 'parts_dir/initrd.img-*-sub_arch', 'boot_disk/uInitrd']
self.assertEqual([expected], fixture.mock.calls)
+ def test_make_flashable_env_too_small_env(self):
+ env = {'verylong': 'evenlonger'}
+ self.assertRaises(AssertionError, make_flashable_env, env, 8)
+
+ def test_make_flashable_env(self):
+ env_file = self.createTempFileAsFixture()
+ self.useFixture(MockSomethingFixture(
+ tempfile, "mkstemp", lambda: (None, env_file)))
+ env = {'a': 'b', 'x': 'y'}
+ make_flashable_env(env, 12)
+ with open(env_file, "r") as fd:
+ self.assertEqual("\x80\x29\x2E\x89a=b\x00x=y\x00", fd.read())
+
def test_install_mx5_boot_loader(self):
fixture = self._mock_Popen()
- install_mx5_boot_loader("imx_file", "boot_device_or_file")
+ imx_file = self.createTempFileAsFixture()
+ install_mx5_boot_loader(imx_file, "boot_device_or_file")
expected = [
- 'sudo', 'dd', 'if=imx_file', 'of=boot_device_or_file', 'bs=1024',
- 'seek=1', 'conv=notrunc']
+ 'sudo', 'dd', 'if=%s' % imx_file, 'of=boot_device_or_file',
+ 'bs=512', 'conv=notrunc', 'seek=2']
self.assertEqual([expected], fixture.mock.calls)
+ 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))
+ self.assertRaises(AssertionError,
+ install_mx5_boot_loader, "imx_file", "boot_device_or_file")
+
def test_install_omap_boot_loader(self):
fixture = self._mock_Popen()
self.useFixture(MockSomethingFixture(
@@ -613,7 +672,8 @@
fixture = self._mock_Popen()
boot_script_path = os.path.join(tempdir, 'boot.scr')
plain_boot_script_path = os.path.join(tempdir, 'boot.txt')
- make_boot_script('boot script data', boot_script_path)
+ boot_env = {'bootargs': 'mybootargs', 'bootcmd': 'mybootcmd'}
+ make_boot_script(boot_env, boot_script_path)
expected = [
['sudo', 'cp', '/tmp/random-abxzr', plain_boot_script_path],
['sudo', 'mkimage', '-A', 'arm', '-O', 'linux', '-T', 'script',
@@ -692,6 +752,25 @@
[('1,8191,0xDA\n8192,106496,0x0C,*\n114688,,,-', 255, 63, '', self.media.path)],
sfdisk_fixture.mock.calls)
+ def test_create_partitions_for_smdkv310(self):
+ # For this board we create a one cylinder partition at the beginning.
+ popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
+ sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
+
+ create_partitions(
+ board_configs['smdkv310'], self.media, 255, 63, '')
+
+ self.assertEqual(
+ [['sudo', 'parted', '-s', self.media.path, 'mklabel', 'msdos'],
+ ['sync']],
+ popen_fixture.mock.calls)
+ # Notice that we create all partitions in a single sfdisk run because
+ # every time we run sfdisk it actually repartitions the device,
+ # erasing any partitions created previously.
+ self.assertEqual(
+ [('1,221183,0xDA\n221184,106496,0x0C,*\n327680,,,-', 255, 63, '',
+ self.media.path)], sfdisk_fixture.mock.calls)
+
def test_create_partitions_for_beagle(self):
popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
@@ -711,9 +790,9 @@
popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
sfdisk_fixture = self.useFixture(MockRunSfdiskCommandsFixture())
- tempfile = self.createTempFileAsFixture()
+ tmpfile = self.createTempFileAsFixture()
create_partitions(
- board_configs['beagle'], Media(tempfile), 255, 63, '')
+ board_configs['beagle'], Media(tmpfile), 255, 63, '')
# Unlike the test for partitioning of a regular block device, in this
# case parted was not called as there's no existing partition table
@@ -721,26 +800,26 @@
self.assertEqual([['sync']], popen_fixture.mock.calls)
self.assertEqual(
- [('63,106432,0x0C,*\n106496,,,-', 255, 63, '', tempfile)],
+ [('63,106432,0x0C,*\n106496,,,-', 255, 63, '', tmpfile)],
sfdisk_fixture.mock.calls)
def test_run_sfdisk_commands(self):
- tempfile = self.createTempFileAsFixture()
+ tmpfile = self.createTempFileAsFixture()
proc = cmd_runner.run(
- ['qemu-img', 'create', '-f', 'raw', tempfile, '10M'],
+ ['qemu-img', 'create', '-f', 'raw', tmpfile, '10M'],
stdout=subprocess.PIPE)
proc.communicate()
stdout, stderr = run_sfdisk_commands(
- '2,16063,0xDA', 255, 63, '', tempfile, as_root=False,
+ '2,16063,0xDA', 255, 63, '', tmpfile, as_root=False,
stderr=subprocess.PIPE)
self.assertIn('Successfully wrote the new partition table', stdout)
def test_run_sfdisk_commands_raises_on_non_zero_returncode(self):
- tempfile = self.createTempFileAsFixture()
+ tmpfile = self.createTempFileAsFixture()
self.assertRaises(
cmd_runner.SubcommandNonZeroReturnValue,
run_sfdisk_commands,
- ',1,0xDA', 255, 63, '', tempfile, as_root=False,
+ ',1,0xDA', 255, 63, '', tmpfile, as_root=False,
stderr=subprocess.PIPE)
@@ -756,7 +835,7 @@
super(TestPartitionSetup, self).tearDown()
time.sleep = self.orig_sleep
- def _create_tempfile(self):
+ def _create_tmpfile(self):
# boot part at +8 MiB, root part at +16 MiB
return self._create_qemu_img_with_partitions(
'16384,15746,0x0C,*\n32768,,,-')
@@ -771,19 +850,19 @@
self.assertEqual(12 * 1024**3, convert_size_to_bytes('12G'))
def test_calculate_partition_size_and_offset(self):
- tempfile = self._create_tempfile()
+ tmpfile = self._create_tmpfile()
vfat_size, vfat_offset, linux_size, linux_offset = (
- calculate_partition_size_and_offset(tempfile))
+ calculate_partition_size_and_offset(tmpfile))
self.assertEqual(
[8061952L, 8388608L, 14680064L, 16777216L],
[vfat_size, vfat_offset, linux_size, linux_offset])
def test_partition_numbering(self):
# another Linux partition at +24 MiB after the boot/root parts
- tempfile = self._create_qemu_img_with_partitions(
+ tmpfile = self._create_qemu_img_with_partitions(
'16384,15746,0x0C,*\n32768,15427,,-\n49152,,,-')
vfat_size, vfat_offset, linux_size, linux_offset = (
- calculate_partition_size_and_offset(tempfile))
+ calculate_partition_size_and_offset(tmpfile))
# check that the linux partition offset starts at +16 MiB so that it's
# the partition immediately following the vfat one
self.assertEqual(linux_offset, 32768 * 512)
@@ -791,39 +870,39 @@
def test_get_boot_and_root_partitions_for_media_beagle(self):
self.useFixture(MockSomethingFixture(
partitions, '_get_device_file_for_partition_number',
- lambda dev, partition: '%s%d' % (tempfile, partition)))
- tempfile = self.createTempFileAsFixture()
- media = Media(tempfile)
+ lambda dev, partition: '%s%d' % (tmpfile, partition)))
+ tmpfile = self.createTempFileAsFixture()
+ media = Media(tmpfile)
media.is_block_device = True
self.assertEqual(
- ("%s%d" % (tempfile, 1), "%s%d" % (tempfile, 2)),
+ ("%s%d" % (tmpfile, 1), "%s%d" % (tmpfile, 2)),
get_boot_and_root_partitions_for_media(
media, board_configs['beagle']))
def test_get_boot_and_root_partitions_for_media_mx5(self):
self.useFixture(MockSomethingFixture(
partitions, '_get_device_file_for_partition_number',
- lambda dev, partition: '%s%d' % (tempfile, partition)))
- tempfile = self.createTempFileAsFixture()
- media = Media(tempfile)
+ lambda dev, partition: '%s%d' % (tmpfile, partition)))
+ tmpfile = self.createTempFileAsFixture()
+ media = Media(tmpfile)
media.is_block_device = True
self.assertEqual(
- ("%s%d" % (tempfile, 2), "%s%d" % (tempfile, 3)),
+ ("%s%d" % (tmpfile, 2), "%s%d" % (tmpfile, 3)),
get_boot_and_root_partitions_for_media(media, boards.Mx5Config))
def _create_qemu_img_with_partitions(self, sfdisk_commands):
- tempfile = self.createTempFileAsFixture()
+ tmpfile = self.createTempFileAsFixture()
proc = cmd_runner.run(
- ['qemu-img', 'create', '-f', 'raw', tempfile, '30M'],
+ ['qemu-img', 'create', '-f', 'raw', tmpfile, '30M'],
stdout=subprocess.PIPE)
proc.communicate()
stdout, stderr = run_sfdisk_commands(
- sfdisk_commands, 255, 63, '', tempfile, as_root=False,
+ sfdisk_commands, 255, 63, '', tmpfile, as_root=False,
# Throw away stderr as sfdisk complains a lot when operating on a
# qemu image.
stderr=subprocess.PIPE)
self.assertIn('Successfully wrote the new partition table', stdout)
- return tempfile
+ return tmpfile
def test_ensure_partition_is_not_mounted_for_mounted_partition(self):
self.useFixture(MockSomethingFixture(
@@ -841,18 +920,18 @@
self.assertEqual(None, popen_fixture.mock.calls)
def test_get_boot_and_root_loopback_devices(self):
- tempfile = self._create_tempfile()
+ tmpfile = self._create_tmpfile()
atexit_fixture = self.useFixture(MockSomethingFixture(
atexit, 'register', AtExitRegister()))
popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
# We can't test the return value of get_boot_and_root_loopback_devices
# because it'd require running losetup as root, so we just make sure
# it calls losetup correctly.
- get_boot_and_root_loopback_devices(tempfile)
+ get_boot_and_root_loopback_devices(tmpfile)
self.assertEqual(
- [['sudo', 'losetup', '-f', '--show', tempfile, '--offset',
+ [['sudo', 'losetup', '-f', '--show', tmpfile, '--offset',
'8388608', '--sizelimit', '8061952'],
- ['sudo', 'losetup', '-f', '--show', tempfile, '--offset',
+ ['sudo', 'losetup', '-f', '--show', tmpfile, '--offset',
'16777216', '--sizelimit', '14680064']],
popen_fixture.mock.calls)
@@ -873,7 +952,7 @@
# but here we mock Popen() and thanks to that the image is not setup
# (via qemu-img) inside setup_partitions. That's why we pass an
# already setup image file.
- tempfile = self._create_tempfile()
+ tmpfile = self._create_tmpfile()
popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
self.useFixture(MockSomethingFixture(
sys, 'stdout', open('/dev/null', 'w')))
@@ -890,14 +969,14 @@
partitions, 'get_boot_and_root_loopback_devices',
lambda image: ('/dev/loop99', '/dev/loop98')))
bootfs_dev, rootfs_dev = setup_partitions(
- board_configs['beagle'], Media(tempfile), '2G', 'boot',
+ board_configs['beagle'], Media(tmpfile), '2G', 'boot',
'root', 'ext3', True, True, True)
self.assertEqual(
# This is the call that would create a 2 GiB image file.
- [['qemu-img', 'create', '-f', 'raw', tempfile, '2147483648'],
+ [['qemu-img', 'create', '-f', 'raw', tmpfile, '2147483648'],
# This call would partition the image file.
['sudo', 'sfdisk', '--force', '-D', '-uS', '-H', '255', '-S',
- '63', '-C', '261', tempfile],
+ '63', '-C', '261', tmpfile],
# Make sure changes are written to disk.
['sync'],
['sudo', 'mkfs.vfat', '-F', '32', bootfs_dev, '-n', 'boot'],
@@ -910,21 +989,21 @@
# Pretend the partitions are mounted.
self.useFixture(MockSomethingFixture(
partitions, 'is_partition_mounted', lambda part: True))
- tempfile = self._create_tempfile()
+ tmpfile = self._create_tmpfile()
self.useFixture(MockSomethingFixture(
partitions, '_get_device_file_for_partition_number',
- lambda dev, partition: '%s%d' % (tempfile, partition)))
- media = Media(tempfile)
- # Pretend our tempfile is a block device.
+ lambda dev, partition: '%s%d' % (tmpfile, partition)))
+ media = Media(tmpfile)
+ # Pretend our tmpfile is a block device.
media.is_block_device = True
popen_fixture = self.useFixture(MockCmdRunnerPopenFixture())
bootfs_dev, rootfs_dev = setup_partitions(
board_configs['beagle'], media, '2G', 'boot', 'root', 'ext3',
True, True, True)
self.assertEqual(
- [['sudo', 'parted', '-s', tempfile, 'mklabel', 'msdos'],
+ [['sudo', 'parted', '-s', tmpfile, 'mklabel', 'msdos'],
['sudo', 'sfdisk', '--force', '-D', '-uS', '-H', '255', '-S',
- '63', tempfile],
+ '63', tmpfile],
['sync'],
# Since the partitions are mounted, setup_partitions will umount
# them before running mkfs.