From patchwork Sun Apr 7 13:40:19 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Antonio Terceiro X-Patchwork-Id: 15957 Return-Path: X-Original-To: linaro@staging.patches.linaro.org Delivered-To: linaro@staging.patches.linaro.org Received: from mail-gg0-f198.google.com (mail-gg0-f198.google.com [209.85.161.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id DB9B727752 for ; Sun, 7 Apr 2013 13:40:34 +0000 (UTC) Received: by mail-gg0-f198.google.com with SMTP id a5sf6831917ggn.1 for ; Sun, 07 Apr 2013 06:40:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-beenthere:x-received:received-spf:x-received :x-forwarded-to:x-forwarded-for:delivered-to:x-received:received-spf :mime-version:x-launchpad-project:x-launchpad-branch :x-launchpad-message-rationale:x-launchpad-branch-revision-number :x-launchpad-notification-type:to:from:subject:message-id:date :reply-to:sender:errors-to:precedence:x-generated-by :x-launchpad-hash:x-gm-message-state:x-original-sender :x-original-authentication-results:mailing-list:list-id :x-google-group-id:list-post:list-help:list-archive:list-unsubscribe :content-type; bh=kUiUE6ExZz4NrbrQ0x8mSLi6u0FWeNQo8Iqv+fANnRg=; b=bHDPl4Y777MgW4NZnKfBrxZeiZhreKkB5LUkC7+vxyceBU6g+N2DqX+MML/zsv/yck 3d5GYfD3OjlcXcaOitClvkzjf9txUr4ROQFyWziq2xrxjT+jyF43Esm06Cb2lhPQ3tWx bUyW5ehphUTOpTfgjWeZBLC/Kuiuw7r3TIN7BzhWO91urN7mgBwrVyHYFssjZJHPDtsU DciI7k7kocIinDItX9comsbBaY6he8sjv4eysTKLP9th34fj7Yb1fusO0Ie785e6IwGr IzpNz+NRlUzEf57epXMGrp8sVMuZMlpjyrDB4iNRFuSMQKxUezF6nw3z2pfXViszSSZu UfgQ== X-Received: by 10.236.41.66 with SMTP id g42mr8249617yhb.14.1365342021947; Sun, 07 Apr 2013 06:40:21 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.0.76 with SMTP id 12ls2590404qec.40.gmail; Sun, 07 Apr 2013 06:40:21 -0700 (PDT) X-Received: by 10.52.98.225 with SMTP id el1mr7980331vdb.89.1365342021823; Sun, 07 Apr 2013 06:40:21 -0700 (PDT) Received: from mail-vc0-f171.google.com (mail-vc0-f171.google.com [209.85.220.171]) by mx.google.com with ESMTPS id ms9si15899083vcb.21.2013.04.07.06.40.21 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 07 Apr 2013 06:40:21 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.220.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.171; Received: by mail-vc0-f171.google.com with SMTP id ha11so4255861vcb.2 for ; Sun, 07 Apr 2013 06:40:21 -0700 (PDT) X-Received: by 10.52.93.20 with SMTP id cq20mr11267290vdb.38.1365342021365; Sun, 07 Apr 2013 06:40:21 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.58.85.136 with SMTP id h8csp13948vez; Sun, 7 Apr 2013 06:40:20 -0700 (PDT) X-Received: by 10.194.222.3 with SMTP id qi3mr26346149wjc.28.1365342019895; Sun, 07 Apr 2013 06:40:19 -0700 (PDT) Received: from indium.canonical.com (indium.canonical.com. [91.189.90.7]) by mx.google.com with ESMTPS id x1si3484098wiw.53.2013.04.07.06.40.19 (version=TLSv1 cipher=RC4-SHA bits=128/128); Sun, 07 Apr 2013 06:40:19 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bounces@canonical.com designates 91.189.90.7 as permitted sender) client-ip=91.189.90.7; Received: from ackee.canonical.com ([91.189.89.26]) by indium.canonical.com with esmtp (Exim 4.71 #1 (Debian)) id 1UOppT-0005od-Db for ; Sun, 07 Apr 2013 13:40:19 +0000 Received: from ackee.canonical.com (localhost [127.0.0.1]) by ackee.canonical.com (Postfix) with ESMTP id 55B2FE0028 for ; Sun, 7 Apr 2013 13:40:19 +0000 (UTC) MIME-Version: 1.0 X-Launchpad-Project: lava-dispatcher X-Launchpad-Branch: ~linaro-validation/lava-dispatcher/trunk X-Launchpad-Message-Rationale: Subscriber X-Launchpad-Branch-Revision-Number: 575 X-Launchpad-Notification-Type: branch-revision To: Linaro Patch Tracker From: noreply@launchpad.net Subject: [Branch ~linaro-validation/lava-dispatcher/trunk] Rev 575: Boot test system with UEFI image included in test image Message-Id: <20130407134019.29759.73325.launchpad@ackee.canonical.com> Date: Sun, 07 Apr 2013 13:40:19 -0000 Reply-To: noreply@launchpad.net Sender: bounces@canonical.com Errors-To: bounces@canonical.com Precedence: list X-Generated-By: Launchpad (canonical.com); Revision="16550"; Instance="launchpad-lazr.conf" X-Launchpad-Hash: 067955b51111e0b2173bc0373d172dd597f6f47e X-Gm-Message-State: ALoCoQlfcO85XXJ9/u5eICbpUW0f5nL9eC/C3S4Plv21hywemhJk3VtyjeNgTmnT6P82PyO98O2h X-Original-Sender: noreply@launchpad.net X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.171 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Merge authors: Antonio Terceiro (terceiro) Related merge proposals: https://code.launchpad.net/~terceiro/lava-dispatcher/vexpress-bootloader-test/+merge/150409 proposed by: Antonio Terceiro (terceiro) ------------------------------------------------------------ revno: 575 [merge] committer: Antonio Terceiro branch nick: trunk timestamp: Sun 2013-04-07 10:39:08 -0300 message: Boot test system with UEFI image included in test image added: lava_dispatcher/device/vexpress.py modified: lava_dispatcher/config.py lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf lava_dispatcher/device/master.py --- lp:lava-dispatcher https://code.launchpad.net/~linaro-validation/lava-dispatcher/trunk You are subscribed to branch lp:lava-dispatcher. To unsubscribe from this branch go to https://code.launchpad.net/~linaro-validation/lava-dispatcher/trunk/+edit-subscription === modified file 'lava_dispatcher/config.py' --- lava_dispatcher/config.py 2013-03-29 18:21:28 +0000 +++ lava_dispatcher/config.py 2013-04-05 17:19:57 +0000 @@ -97,6 +97,13 @@ fastboot_command = schema.StringOption() shared_working_directory = schema.StringOption(default=None) + uefi_image_filename = schema.StringOption(default=None) + vexpress_uefi_path = schema.StringOption(default=None) + vexpress_uefi_backup_path = schema.StringOption(default=None) + vexpress_stop_autoboot_prompt = schema.StringOption( + default='Press Enter to stop auto boot...') + vexpress_usb_mass_storage_device = schema.StringOption(default=None) + class OptionDescriptor(object): def __init__(self, name): self.name = name === modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf' --- lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf 2013-02-13 18:25:26 +0000 +++ lava_dispatcher/default-config/lava-dispatcher/device-types/vexpress-tc2.conf 2013-02-27 21:10:47 +0000 @@ -1,3 +1,5 @@ +client_type = vexpress + boot_cmds = 2 boot_cmds_android = 3 @@ -15,3 +17,11 @@ fstab.partitions init.rc fstab.arm-versatileexpress + +uefi_image_filename = uefi_v2p-ca15-tc2.bin + +vexpress_uefi_path = SOFTWARE/TC2/uefi.bin + +vexpress_uefi_backup_path = SOFTWARE/TC2/backup-uefi.bin + +vexpress_usb_mass_storage_device = /dev/disk/by-label/VEMSD === modified file 'lava_dispatcher/device/master.py' --- lava_dispatcher/device/master.py 2013-04-02 16:16:18 +0000 +++ lava_dispatcher/device/master.py 2013-04-07 13:37:43 +0000 @@ -112,6 +112,17 @@ system = download_image(system, self.context, sdir, decompress=False) data = download_image(userdata, self.context, sdir, decompress=False) + with self._as_master() as master: + self._format_testpartition(master, 'ext4') + self._deploy_android_tarballs(master, boot, system, data) + + if master.has_partition_with_label('userdata') and \ + master.has_partition_with_label('sdcard'): + _purge_linaro_android_sdcard(master) + + self.deployment_data = Target.android_deployment_data + + def _deploy_android_tarballs(self, master, boot, system, data): tmpdir = self.context.config.lava_image_tmpdir url = self.context.config.lava_image_url @@ -123,17 +134,9 @@ system_url = '/'.join(u.strip('/') for u in [url, system]) data_url = '/'.join(u.strip('/') for u in [url, data]) - with self._as_master() as master: - self._format_testpartition(master, 'ext4') - _deploy_linaro_android_boot(master, boot_url, self) - _deploy_linaro_android_system(master, system_url) - _deploy_linaro_android_data(master, data_url) - - if master.has_partition_with_label('userdata') and \ - master.has_partition_with_label('sdcard'): - _purge_linaro_android_sdcard(master) - - self.deployment_data = Target.android_deployment_data + _deploy_linaro_android_boot(master, boot_url, self) + _deploy_linaro_android_system(master, system_url) + _deploy_linaro_android_data(master, data_url) def deploy_linaro_prebuilt(self, image): self.boot_master_image() @@ -402,9 +405,9 @@ self.proc.sendline("hardreset") self.proc.empty_buffer() - def _enter_uboot(self): + def _enter_bootloader(self): if self.proc.expect(self.config.interrupt_boot_prompt) != 0: - raise Exception("Failed to enter uboot") + raise Exception("Failed to enter bootloader") self.proc.sendline(self.config.interrupt_boot_command) def _boot_linaro_image(self): @@ -421,11 +424,11 @@ def _boot(self, boot_cmds): try: self._soft_reboot() - self._enter_uboot() + self._enter_bootloader() except: - logging.exception("_enter_uboot failed") + logging.exception("_enter_bootloader failed") self._hard_reboot() - self._enter_uboot() + self._enter_bootloader() self.proc.sendline(boot_cmds[0]) for line in range(1, len(boot_cmds)): self.proc.expect(self.config.bootloader_prompt, timeout=300) === added file 'lava_dispatcher/device/vexpress.py' --- lava_dispatcher/device/vexpress.py 1970-01-01 00:00:00 +0000 +++ lava_dispatcher/device/vexpress.py 2013-04-05 21:58:28 +0000 @@ -0,0 +1,193 @@ +# Copyright (C) 2013 Linaro Limited +# +# Author: Antonio Terceiro +# +# This file is part of LAVA Dispatcher. +# +# LAVA Dispatcher is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# LAVA Dispatcher is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along +# with this program; if not, see . + +import pexpect +import os +import logging +from time import sleep +from contextlib import contextmanager + +from lava_dispatcher.device.master import MasterImageTarget +from lava_dispatcher.errors import CriticalError + +class VexpressTarget(MasterImageTarget): + + def __init__(self, context, config): + super(VexpressTarget, self).__init__(context, config) + + self.test_uefi = None + + if (self.config.uefi_image_filename is None or + self.config.vexpress_uefi_path is None or + self.config.vexpress_uefi_backup_path is None or + self.config.vexpress_usb_mass_storage_device is None): + + raise CriticalError( + "Versatile Express devices must specify all " + "of the following configuration variables: " + "uefi_image_filename, vexpress_uefi_path, " + "vexpress_uefi_backup_path, and " + "vexpress_usb_mass_storage_device") + + ################################################################## + # methods inherited from MasterImageTarget and overriden here + ################################################################## + + def _soft_reboot(self): + """ + The Vexpress board only displays the prompt to interrupt the MCC when + it is power-cycled, so we must always do a hard reset in practice. + + When a soft reboot is requested, though, at least we sync the disks + before sending the hard reset. + """ + # Try to C-c the running process, if any + self.proc.sendcontrol('c') + # Flush file system buffers + self.proc.sendline('sync') + + self._hard_reboot() + + def _enter_bootloader(self): + with self._mcc_setup() as mount_point: + self._install_test_uefi(mount_point) + + super(VexpressTarget, self)._enter_bootloader() + + def _wait_for_master_boot(self): + with self._mcc_setup() as mount_point: + self._restore_uefi_backup(mount_point) + + super(VexpressTarget, self)._wait_for_master_boot() + + def _deploy_android_tarballs(self, master, boot, system, data): + super(VexpressTarget, self)._deploy_android_tarballs(master, boot, + system, data) + # android images have boot files inside boot/ in the tarball + uefi_on_image = os.path.join('boot', self.config.uefi_image_filename) + self._extract_uefi_from_tarball(boot, uefi_on_image) + + def _deploy_tarballs(self, boot_tgz, root_tgz): + super(VexpressTarget, self)._deploy_tarballs(boot_tgz, root_tgz) + uefi_on_image = self.config.uefi_image_filename + self._extract_uefi_from_tarball(boot_tgz, uefi_on_image) + + ################################################################## + # implementation-specific methods + ################################################################## + + @contextmanager + def _mcc_setup(self): + """ + This method will manage the context for manipulating the USB mass + storage device, and pass the mount point where the USB MSD is mounted + to the inner block. + + Example: + + with self._mcc_setup() as mount_point: + do_stuff_with(mount_point) + + + This can be used for example to copy files from/to the USB MSD. + Mounting and unmounting is managed by this method, so the inner block + does not have to handle that. + """ + + mount_point = os.path.join(self.scratch_dir, 'vexpress-usb') + if not os.path.exists(mount_point): + os.makedirs(mount_point) + + self._enter_mcc() + self._mount_usbmsd(mount_point) + try: + yield mount_point + finally: + self._umount_usbmsd(mount_point) + self._leave_mcc() + + def _enter_mcc(self): + match_id = self.proc.expect([ + self.config.vexpress_stop_autoboot_prompt, + pexpect.EOF, pexpect.TIMEOUT]) + if match_id != 0: + msg = 'Unable to intercept MCC boot prompt' + logging.error(msg) + raise CriticalError(msg) + self.proc.sendline("") + self.proc.expect(['Cmd>']) + + def _mount_usbmsd(self, mount_point): + self.proc.sendline("USB_ON") + self.proc.expect(['Cmd>']) + + # wait a few seconds so that the kernel on the host detects the USB + # mass storage interface exposed by the Vexpress + sleep(5) + + usb_device = self.config.vexpress_usb_mass_storage_device + + self.context.run_command('mount %s %s' % (usb_device, mount_point)) + + def _umount_usbmsd(self, mount_point): + self.context.run_command('umount %s' % mount_point) + + def _leave_mcc(self): + self.proc.sendline("reboot") + + def _extract_uefi_from_tarball(self, tarball, uefi_on_image): + tmpdir = self.scratch_dir + + # Android boot tarballs have the UEFI binary at boot/*.bin, while + # Ubuntu ones have it at ./*.bin + # + # --no-anchored matches the name inside any directory in the tarball. + self.context.run_command('tar --no-anchored -xaf %s -C %s %s' % (tarball, tmpdir, + uefi_on_image)) + + uefi_on_image = os.path.join(tmpdir, uefi_on_image) + test_uefi = os.path.join(tmpdir, 'uefi.bin') + self.context.run_command('mv %s %s' % (uefi_on_image, test_uefi)) + + self.test_uefi = test_uefi + + def _restore_uefi_backup(self, mount_point): + uefi_path = self.config.vexpress_uefi_path + uefi = os.path.join(mount_point, uefi_path) + uefi_backup_path = self.config.vexpress_uefi_backup_path + uefi_backup = os.path.join(mount_point, uefi_backup_path) + + if os.path.exists(uefi_backup): + # restore the uefi backup + self.context.run_command('cp %s %s' % (uefi_backup, uefi)) + else: + # no existing backup yet means that this is the first time ever; + # the uefi in there is the good one, and we backup it up. + self.context.run_command('cp %s %s' % (uefi, uefi_backup)) + + def _install_test_uefi(self, mount_point): + uefi_path = self.config.vexpress_uefi_path + uefi = os.path.join(mount_point, uefi_path) + # FIXME what if self.test_uefi is not set, or points to an unexisting + # file? + self.context.run_command('cp %s %s' % (self.test_uefi, uefi)) + + +target_class = VexpressTarget