=== modified file 'lava_dispatcher/actions/boot_control.py'
@@ -77,9 +77,7 @@
'default': False, 'optional': True
}
- def run(self, options=None, interactive_boot_cmds=False):
- if not options:
- options = []
+ def run(self, options=[], interactive_boot_cmds=False):
client = self.client
if interactive_boot_cmds:
client.config.boot_cmds = options
=== modified file 'lava_dispatcher/actions/deploy.py'
@@ -91,6 +91,33 @@
def run(self, boot, system, data, rootfstype='ext4'):
self.client.deploy_linaro_android(boot, system, data, rootfstype)
+class cmd_deploy_linaro_kernel(BaseAction):
+
+ parameters_schema = {
+ 'type': 'object',
+ 'properties': {
+ 'kernel': {'type': 'string', 'optional': False},
+ 'ramdisk': {'type': 'string', 'optional': True},
+ 'dtb': {'type': 'string', 'optional': True},
+ 'rootfs': {'type': 'string', 'optional': True},
+ 'rootfstype': {'type': 'string', 'optional': True},
+ 'bootloader': {'type': 'string', 'optional': True, 'default': 'u_boot'},
+ },
+ 'additionalProperties': False,
+ }
+
+ @classmethod
+ def validate_parameters(cls, parameters):
+ super(cmd_deploy_linaro_kernel, cls).validate_parameters(parameters)
+ if 'kernel' not in parameters:
+ raise ValueError('must specify a kernel')
+
+ def run(self, kernel=None, ramdisk=None, dtb=None, rootfs=None, rootfstype='ext4',
+ bootloader='u_boot'):
+ self.client.deploy_linaro_kernel(
+ kernel=kernel, ramdisk=ramdisk, dtb=dtb, rootfs=rootfs,
+ rootfstype=rootfstype, bootloader=bootloader)
+
class cmd_dummy_deploy(BaseAction):
=== modified file 'lava_dispatcher/client/targetdevice.py'
@@ -64,6 +64,11 @@
else:
self.target_device.deploy_linaro_prebuilt(image)
+ def deploy_linaro_kernel(self, kernel, ramdisk=None, dtb=None, rootfs=None,
+ rootfstype='ext4', bootloader='u_boot'):
+ self.target_device.deploy_linaro_kernel(kernel, ramdisk, dtb, rootfs,
+ bootloader)
+
def _boot_linaro_image(self):
if self.proc:
logging.warning('device already powered on, powering off first')
=== modified file 'lava_dispatcher/config.py'
@@ -32,6 +32,7 @@
boot_cmds = schema.StringOption(fatal=True) # Can do better here
boot_cmds_android = schema.StringOption(fatal=True) # And here
boot_cmds_oe = schema.StringOption(fatal=True) # And here?
+ boot_cmds_tftp = schema.StringOption()
read_boot_cmds_from_image = schema.BoolOption(default=True)
boot_options = schema.ListOption()
boot_linaro_timeout = schema.IntOption(default=300)
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/arndale.conf'
@@ -1,5 +1,8 @@
+client_type = bootloader
boot_part = 2
root_part = 3
+testboot_offset = 3
+
boot_cmds = mmc rescan,
mmc part 1,
setenv bootcmd "'fatload mmc 0:5 0x40007000 uImage; fatload mmc 0:5 0x42000000 uInitrd; fatload mmc 0:5 0x41f00000 board.dtb; bootm 0x40007000 0x42000000 0x41f00000'",
@@ -18,11 +21,27 @@
sdcard_part_android = 7
data_part_android = 7
+image_boot_msg = Starting kernel
+
boot_cmds_android = mmc init,
mmc part 0,
setenv bootcmd "'fatload mmc 0:5 0x40007000 uImage; fatload mmc 0:5 0x41000000 uInitrd; fatload mmc 0:5 0x41f00000 board.dtb; bootm 0x40007000 0x41000000 0x41f00000'",
setenv bootargs "'console=tty0 console=ttySAC2,115200n8 androidboot.hardware=exynos5250-arndale rootwait ro rootdelay=3 init=/init androidboot.console=ttySAC2 console=ttySAC2'",
boot
-bootloader_prompt = #
+boot_cmds_tftp =
+ setenv autoload no,
+ setenv usbethaddr 00:40:5c:26:0a:5b,
+ setenv pxefile_addr_r "'0x50000000'",
+ setenv kernel_addr_r "'0x40007000'",
+ setenv initrd_addr_r "'0x42000000'",
+ setenv fdt_addr_r "'0x41f00000'",
+ setenv loadkernel "'tftp ${kernel_addr_r} ${lava_kernel}'",
+ setenv loadinitrd "'tftp ${initrd_addr_r} ${lava_ramdisk}; setenv initrd_size ${filesize}'",
+ setenv loadfdt "'tftp ${fdt_addr_r} ${lava_dtb}'",
+ setenv bootargs "'root=/dev/ram0 console=ttySAC2,115200n8 init --no-log ip=:::::eth0:dhcp'",
+ setenv bootcmd "'usb start; dhcp; setenv serverip ${lava_server_ip}; run loadkernel; run loadinitrd; run loadfdt; bootm ${kernel_addr_r} ${initrd_addr_r} ${fdt_addr_r}'",
+ boot
+
+bootloader_prompt = ARNDALE5250
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/beagle-xm.conf'
@@ -1,3 +1,4 @@
+client_type = bootloader
boot_cmds = mmc init,
mmc part 0,
setenv bootcmd "'fatload mmc 0:3 0x80000000 uImage;
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone-black.conf'
@@ -1,3 +1,21 @@
+client_type = bootloader
+
+boot_cmds_tftp =
+ setenv autoload no,
+ setenv usbethaddr 00:40:5c:26:0a:6c,
+ setenv pxefile_addr_r "'0x50000000'",
+ setenv kernel_addr_r "'0x80200000'",
+ setenv initrd_addr_r "'0x81000000'",
+ setenv fdt_addr_r "'0x815f0000'",
+ setenv initrd_high "'0xffffffff'",
+ setenv fdt_high "'0xffffffff'",
+ setenv loadkernel "'tftp ${kernel_addr_r} ${lava_kernel}'",
+ setenv loadinitrd "'tftp ${initrd_addr_r} ${lava_ramdisk}; setenv initrd_size ${filesize}'",
+ setenv loadfdt "'tftp ${fdt_addr_r} ${lava_dtb}'",
+ setenv bootargs "'console=ttyO0,115200n8 root=/dev/ram0 earlyprintk ip=:::::eth0:dhcp'",
+ setenv bootcmd "'dhcp; setenv serverip ${lava_server_ip}; run loadkernel; run loadinitrd; run loadfdt; bootz ${kernel_addr_r} ${initrd_addr_r} ${fdt_addr_r}'",
+ boot
+
boot_cmds_oe =
setenv initrd_high "'0xffffffff'",
setenv fdt_high "'0xffffffff'",
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone.conf'
@@ -1,3 +1,4 @@
+client_type = bootloader
boot_cmds_oe =
setenv initrd_high "'0xffffffff'",
setenv fdt_high "'0xffffffff'",
@@ -12,6 +13,22 @@
setenv bootargs "'console=ttyO0,115200n8 root=LABEL=testrootfs rootwait ro'",
boot
+boot_cmds_tftp =
+ setenv autoload no,
+ setenv usbethaddr 00:40:5c:26:0a:6c,
+ setenv pxefile_addr_r "'0x50000000'",
+ setenv kernel_addr_r "'0x80200000'",
+ setenv initrd_addr_r "'0x81000000'",
+ setenv fdt_addr_r "'0x815f0000'",
+ setenv initrd_high "'0xffffffff'",
+ setenv fdt_high "'0xffffffff'",
+ setenv loadkernel "'tftp ${kernel_addr_r} ${lava_kernel}'",
+ setenv loadinitrd "'tftp ${initrd_addr_r} ${lava_ramdisk}; setenv initrd_size ${filesize}'",
+ setenv loadfdt "'tftp ${fdt_addr_r} ${lava_dtb}'",
+ setenv bootargs "'console=ttyO0,115200n8 root=/dev/ram0 earlyprintk ip=:::::eth0:dhcp'",
+ setenv bootcmd "'dhcp; setenv serverip ${lava_server_ip}; run loadkernel; run loadinitrd; run loadfdt; bootz ${kernel_addr_r} ${initrd_addr_r} ${fdt_addr_r}'",
+ boot,
+
lmc_dev_arg = beaglebone
boot_options =
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/mx51evk.conf'
@@ -1,3 +1,4 @@
+client_type = bootloader
boot_part = 2
root_part = 3
boot_cmds = mmc init,
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/mx53loco.conf'
@@ -1,3 +1,4 @@
+client_type = bootloader
boot_part = 2
root_part = 3
boot_cmds = mmc init,
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/origen.conf'
@@ -1,3 +1,4 @@
+client_type = bootloader
boot_part = 2
root_part = 3
boot_cmds = mmc init,
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/panda.conf'
@@ -1,3 +1,4 @@
+client_type = bootloader
boot_cmds = mmc init,
mmc part 0,
setenv bootcmd "'fatload mmc 0:3 0x80200000 uImage; fatload mmc
@@ -27,6 +28,28 @@
vram=48M omapfb.vram=0:24M'",
boot
+boot_cmds_fdt = mmc init,
+ mmc part 0,
+ setenv bootcmd "'fatload mmc 0:3 0x80200000 uImage; fatload mmc 0:3 0x81600000 uInitrd; fatload mmc 0:3 0x815f0000 board.dtb; bootm 0x80200000 0x81600000 0x815f0000'",
+ setenv bootargs "'console=tty0 console=ttyO2,115200n8 root=LABEL=testrootfs rootwait ro earlyprintk fixrtc nocompcache vram=48M omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000'",
+ boot
+
+boot_cmds_tftp =
+ setenv autoload no,
+ setenv usbethaddr 00:40:5c:26:0a:5c,
+ setenv pxefile_addr_r "'0x50000000'",
+ setenv kernel_addr_r "'0x80200000'",
+ setenv initrd_addr_r "'0x81600000'",
+ setenv fdt_addr_r "'0x815f0000'",
+ setenv initrd_high "'0xffffffff'",
+ setenv fdt_high "'0xffffffff'",
+ setenv loadkernel "'tftp ${kernel_addr_r} ${lava_kernel}'",
+ setenv loadinitrd "'tftp ${initrd_addr_r} ${lava_ramdisk}; setenv initrd_size ${filesize}'",
+ setenv loadfdt "'tftp ${fdt_addr_r} ${lava_dtb}'",
+ setenv bootargs "'console=ttyO2,115200n8 root=/dev/ram0 fixrtc nocompcache vram=48M omapfb.vram=0:24M mem=456M@0x80000000 mem=512M@0xA0000000 ip=:::::eth0:dhcp init=init'",
+ setenv bootcmd "'usb start; dhcp; setenv serverip ${lava_server_ip}; run loadkernel; run loadinitrd; run loadfdt; bootm ${kernel_addr_r} ${initrd_addr_r} ${fdt_addr_r}'",
+ boot
+
android_binary_drivers = http://192.168.1.21/LAVA_HTTP/android-binaries/panda-drivers.tgz
possible_partitions_files =
init.partitions.rc
=== modified file 'lava_dispatcher/default-config/lava-dispatcher/device-types/snowball.conf'
@@ -1,3 +1,4 @@
+client_type = bootloader
boot_cmds = mmc rescan 0,
setenv bootcmd "'fatload mmc 0:3 0x00100000 /uImage;
bootm 0x00100000'",
=== added file 'lava_dispatcher/device/bootloader.py'
@@ -0,0 +1,130 @@
+# Copyright (C) 2013 Linaro Limited
+#
+# Author: Tyler Baker <tyler.baker@linaro.org>
+#
+# 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 <http://www.gnu.org/licenses>.
+
+import logging
+import contextlib
+import time
+import os
+import pexpect
+
+from lava_dispatcher.device.master import (
+ MasterImageTarget
+)
+from lava_dispatcher.utils import (
+ string_to_list
+)
+from lava_dispatcher.errors import (
+ CriticalError
+)
+from lava_dispatcher.downloader import (
+ download_image
+)
+
+class BootloaderTarget(MasterImageTarget):
+
+ def __init__(self, context, config):
+ super(BootloaderTarget, self).__init__(context, config)
+ self._booted = False
+ self._boot_cmds = None
+ self._lava_cmds = None
+ self._uboot_boot = False
+ # This is the offset into the path, used to reference bootfiles
+ self._offset = self.scratch_dir.index('images')
+
+ def power_off(self, proc):
+ if self._uboot_boot:
+ if self.config.power_off_cmd:
+ self.context.run_command(self.config.power_off_cmd)
+ else:
+ super(BootloaderTarget, self).power_off(proc)
+
+ def deploy_linaro_kernel(self, kernel, ramdisk, dtb, rootfs, bootloader):
+ if bootloader == "u_boot":
+ # We assume we will be controlling u-boot
+ if kernel is not None:
+ # We have been passed kernel image, setup TFTP boot
+ self._uboot_boot = True
+ # Set the TFTP server IP (Dispatcher)
+ self._lava_cmds = "lava_server_ip=" + self.context.config.lava_server_ip + ","
+ kernel = download_image(kernel, self.context, self.scratch_dir, decompress=False)
+ # Set the TFTP bootfile path for the kernel
+ self._lava_cmds += "lava_kernel=" + kernel[self._offset::] + ","
+ if ramdisk is not None:
+ # We have been passed a ramdisk
+ ramdisk = download_image(ramdisk, self.context, self.scratch_dir, decompress=False)
+ # Set the TFTP bootfile path for the ramdisk
+ self._lava_cmds += "lava_ramdisk=" + ramdisk[self._offset::] + ","
+ if dtb is not None:
+ # We have been passed a device tree blob
+ dtb = download_image(dtb, self.context, self.scratch_dir, decompress=False)
+ # Set the bootfile path for the ramdisk
+ self._lava_cmds += "lava_dtb=" + dtb[self._offset::] + ","
+ if rootfs is not None:
+ # We have been passed a rootfs
+ rootfs = download_image(rootfs, self.context, self.scratch_dir, decompress=True)
+ self._lava_cmds += "lava_rootfs=" + dtb[self._offset::] + ","
+ else:
+ # TODO: Faking the deployment data - Ubuntu
+ self.deployment_data = self.target_map['ubuntu']
+ else:
+ # This *should* never happen
+ raise CriticalError("No kernel images to boot")
+ else:
+ # Define other "types" of bootloaders here. UEFI? Grub?
+ raise CriticalError("U-Boot is the only supported bootloader at this time")
+
+ def deploy_linaro(self, hwpack, rfs, bootloader):
+ self._uboot_boot = False
+ super(BootloaderTarget, self).deploy_linaro(hwpack, rfs, bootloader)
+
+ def deploy_linaro_prebuilt(self, image):
+ self._uboot_boot = False
+ super(BootloaderTarget, self).deploy_linaro_prebuilt(image)
+
+ def _inject_boot_cmds(self):
+ if isinstance(self.config.boot_cmds, basestring):
+ if self.config.boot_cmds_tftp is None:
+ raise CriticalError("No TFTP boot commands defined")
+ else:
+ self._boot_cmds = self._lava_cmds + self.config.boot_cmds_tftp
+ self._boot_cmds = string_to_list(self._boot_cmds.encode('ascii'))
+ else:
+ self._boot_cmds = string_to_list(self._lava_cmds.encode('ascii')) + self.config.boot_cmds
+
+ def _run_boot(self):
+ self._enter_bootloader(self.proc)
+ self._inject_boot_cmds()
+ self._customize_bootloader(self.proc, self._boot_cmds)
+ self._wait_for_prompt(self.proc, ['\(initramfs\)', self.config.master_str],
+ self.config.boot_linaro_timeout)
+
+ def _boot_linaro_image(self):
+ if self._uboot_boot:
+ if self.config.hard_reset_command:
+ self._hard_reboot()
+ else:
+ raise CriticalError("No hard reset command defined")
+ self._run_boot()
+ self.proc.sendline('export PS1="%s"' % self.deployment_data['TESTER_PS1'])
+ self._booted = True
+ else:
+ super(BootloaderTarget, self)._boot_linaro_image()
+
+target_class = BootloaderTarget
=== modified file 'lava_dispatcher/device/capri.py'
@@ -44,11 +44,11 @@
return
try:
self._soft_reboot()
- self._enter_bootloader()
+ self._enter_bootloader(self.proc)
except:
logging.exception("_enter_bootloader failed")
self._hard_reboot()
- self._enter_bootloader()
+ self._enter_bootloader(self.proc)
self.proc.sendline("fastboot")
def deploy_android(self, boot, system, userdata):
=== modified file 'lava_dispatcher/device/fastmodel.py'
@@ -47,6 +47,7 @@
extract_targz,
DrainConsoleOutput,
finalize_process,
+ string_to_list,
)
@@ -238,11 +239,6 @@
if self._uefi:
os.chown(self._uefi, st.st_uid, st.st_gid)
- def _enter_bootloader(self):
- if self.proc.expect(self.config.interrupt_boot_prompt) != 0:
- raise Exception("Failed to enter bootloader")
- self.proc.sendline(self.config.interrupt_boot_command)
-
def power_off(self, proc):
super(FastModelTarget, self).power_off(proc)
finalize_process(self._sim_proc)
@@ -304,8 +300,12 @@
self.proc.logfile_read)
if self._uefi:
- self._enter_bootloader()
- self._customize_bootloader()
+ self._enter_bootloader(self.proc)
+ if isinstance(self.config.boot_cmds, basestring):
+ boot_cmds = string_to_list(self.config.boot_cmds.encode('ascii'))
+ else:
+ boot_cmds = self.config.boot_cmds
+ self._customize_bootloader(self.proc, boot_cmds)
return self.proc
=== modified file 'lava_dispatcher/device/master.py'
@@ -99,12 +99,14 @@
return self.device_version
def power_on(self):
+ if self.config.power_on_cmd:
+ self.context.run_command(self.config.power_on_cmd)
self._boot_linaro_image()
return self.proc
def power_off(self, proc):
- # we always leave master image devices powered on
- pass
+ if self.config.power_off_cmd:
+ self.context.run_command(self.config.power_off_cmd)
def deploy_linaro(self, hwpack, rfs, bootloader):
self.boot_master_image()
@@ -482,47 +484,51 @@
self.proc.sendline("hardreset")
self.proc.empty_buffer()
- def _enter_bootloader(self):
- if self.proc.expect(self.config.interrupt_boot_prompt) != 0:
- raise Exception("Failed to enter bootloader")
- self.proc.sendline(self.config.interrupt_boot_command)
-
def _boot_linaro_image(self):
boot_cmds = self.deployment_data['boot_cmds']
- boot_cmds_override = False
-
options = boot_options.as_dict(self, defaults={'boot_cmds': boot_cmds})
- if 'boot_cmds' in options:
+
+ # Interactive boot_cmds from the job file are a list.
+ # We check for them first, if they are present, we use
+ # them and ignore the other cases.
+ if not isinstance(self.config.boot_cmds, basestring):
+ logging.info('Overriding boot_cmds from job file')
boot_cmds_override = True
+ boot_cmds = self.config.boot_cmds
+ # If there were no interactive boot_cmds, next we check
+ # for boot_option overrides. If one exists, we use them
+ # and ignore all other cases.
+ elif options['boot_cmds'].value != 'boot_cmds':
+ logging.info('Overriding boot_cmds from boot_options')
boot_cmds = options['boot_cmds'].value
-
- logging.info('boot_cmds attribute: %s', boot_cmds)
-
- # Check if we have already got some values from image's boot file.
- if self.deployment_data.get('boot_cmds_dynamic') \
- and not boot_cmds_override:
+ boot_cmds = self.config.cp.get('__main__', boot_cmds)
+ boot_cmds = string_to_list(boot_cmds.encode('ascii'))
+ # No interactive or boot_option overrides are present,
+ # we prefer to get the boot_cmds for the image if they are
+ # present.
+ elif self.deployment_data.get('boot_cmds_dynamic'):
logging.info('Loading boot_cmds from image')
boot_cmds = self.deployment_data['boot_cmds_dynamic']
- else:
+ # This is the catch all case. Where we get the default boot_cmds
+ # from the deployment data.
+ else:
logging.info('Loading boot_cmds from device configuration')
boot_cmds = self.config.cp.get('__main__', boot_cmds)
boot_cmds = string_to_list(boot_cmds.encode('ascii'))
+ logging.info('boot_cmds: %s', boot_cmds)
+
self._boot(boot_cmds)
def _boot(self, boot_cmds):
try:
self._soft_reboot()
- self._enter_bootloader()
+ self._enter_bootloader(self.proc)
except:
logging.exception("_enter_bootloader failed")
self._hard_reboot()
- 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)
- self.proc.sendline(boot_cmds[line])
-
+ self._enter_bootloader(self.proc)
+ self._customize_bootloader(self.proc, boot_cmds)
target_class = MasterImageTarget
=== modified file 'lava_dispatcher/device/target.py'
@@ -23,8 +23,12 @@
import shutil
import re
+from lava_dispatcher.client.base import (
+ wait_for_prompt
+)
from lava_dispatcher.client.lmc_utils import (
- image_partition_mounted)
+ image_partition_mounted
+)
import lava_dispatcher.utils as utils
@@ -171,13 +175,15 @@
return dest
return dest
- def _customize_bootloader(self):
- # FIXME: proc is unresolved - is this the same as the proc from runner?
- self.proc.expect(self.config.bootloader_prompt, timeout=300)
- if isinstance(self.config.boot_cmds, basestring):
- boot_cmds = utils.string_to_list(self.config.boot_cmds.encode('ascii'))
- else:
- boot_cmds = self.config.boot_cmds
+ def _wait_for_prompt(self, connection, prompt_pattern, timeout):
+ wait_for_prompt(connection, prompt_pattern, timeout)
+
+ def _enter_bootloader(self, connection):
+ if connection.expect(self.config.interrupt_boot_prompt) != 0:
+ raise Exception("Failed to enter bootloader")
+ connection.sendline(self.config.interrupt_boot_command)
+
+ def _customize_bootloader(self, connection, boot_cmds):
for line in boot_cmds:
parts = re.match('^(?P<action>sendline|expect)\s*(?P<command>.*)', line)
if parts:
@@ -187,13 +193,14 @@
except AttributeError as e:
raise Exception("Badly formatted command in boot_cmds %s" % e)
if action == "sendline":
- self.proc.send(command)
- self.proc.sendline('')
+ connection.send(command)
+ connection.sendline('')
elif action == "expect":
command = re.escape(command)
- self.proc.expect(command, timeout=300)
+ connection.expect(command, timeout=300)
else:
- self.proc.sendline(line)
+ self._wait_for_prompt(connection, self.config.bootloader_prompt, timeout=300)
+ connection.sendline(line)
def _customize_ubuntu(self, rootdir):
self.deployment_data = Target.ubuntu_deployment_data
=== modified file 'lava_dispatcher/device/vexpress.py'
@@ -66,11 +66,11 @@
self._hard_reboot()
- def _enter_bootloader(self):
+ def _enter_bootloader(self, connection):
with self._mcc_setup() as mount_point:
self._install_test_uefi(mount_point)
- super(VexpressTarget, self)._enter_bootloader()
+ super(VexpressTarget, self)._enter_bootloader(connection)
def _wait_for_master_boot(self):
with self._mcc_setup() as mount_point: