From patchwork Wed Mar 9 15:58:27 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: James Westby X-Patchwork-Id: 473 Return-Path: Delivered-To: unknown Received: from imap.gmail.com (74.125.159.109) by localhost6.localdomain6 with IMAP4-SSL; 08 Jun 2011 14:42:58 -0000 Delivered-To: patches@linaro.org Received: by 10.224.60.68 with SMTP id o4cs63785qah; Wed, 9 Mar 2011 07:58:29 -0800 (PST) Received: by 10.227.196.67 with SMTP id ef3mr5867248wbb.185.1299686308271; Wed, 09 Mar 2011 07:58:28 -0800 (PST) Received: from adelie.canonical.com (adelie.canonical.com [91.189.90.139]) by mx.google.com with ESMTP id k6si3552625wbc.38.2011.03.09.07.58.27; Wed, 09 Mar 2011 07:58:28 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) client-ip=91.189.90.139; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.139 as permitted sender) smtp.mail=bounces@canonical.com Received: from loganberry.canonical.com ([91.189.90.37]) by adelie.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1PxLmN-0003MK-JC for ; Wed, 09 Mar 2011 15:58:27 +0000 Received: from loganberry.canonical.com (localhost [127.0.0.1]) by loganberry.canonical.com (Postfix) with ESMTP id 8F4862E80F1 for ; Wed, 9 Mar 2011 15:58:27 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: linaro-image-tools X-Launchpad-Branch: ~linaro-maintainers/linaro-image-tools/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 295 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~linaro-maintainers/linaro-image-tools/trunk] Rev 295: Add support for the smdkv310. Thanks Angus. Message-Id: <20110309155827.30223.82525.launchpad@loganberry.canonical.com> Date: Wed, 09 Mar 2011 15:58:27 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: bulk X-Generated-By: Launchpad (canonical.com); Revision="12532"; Instance="initZopeless config overlay" X-Launchpad-Hash: eb04777e04f99319498e242f41a71c8fd3eb3b0f Merge authors: Angus Ainslie (angus-akkea) Loïc Minier (lool) Related merge proposals: https://code.launchpad.net/~angus-akkea/linaro-image-tools/Samsung-SMDKV310/+merge/51904 proposed by: Angus Ainslie (angus-akkea) review: Approve - Guilherme Salgado (salgado) review: Approve - Loïc Minier (lool) ------------------------------------------------------------ revno: 295 [merge] committer: James Westby branch nick: trunk timestamp: Wed 2011-03-09 10:55:56 -0500 message: Add support for the smdkv310. Thanks Angus. modified: linaro_media_create/boards.py linaro_media_create/tests/test_media_create.py --- lp:linaro-image-tools https://code.launchpad.net/~linaro-maintainers/linaro-image-tools/trunk You are subscribed to branch lp:linaro-image-tools. To unsubscribe from this branch go to https://code.launchpad.net/~linaro-maintainers/linaro-image-tools/trunk/+edit-subscription === modified file 'linaro_media_create/boards.py' --- linaro_media_create/boards.py 2011-03-08 15:15:39 +0000 +++ linaro_media_create/boards.py 2011-03-09 15:55:56 +0000 @@ -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('