=== modified file 'lava_dispatcher/actions/boot_control.py'
--- lava_dispatcher/actions/boot_control.py	2013-07-16 15:59:32 +0000
+++ lava_dispatcher/actions/boot_control.py	2013-08-09 19:44:35 +0000
@@ -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'
--- lava_dispatcher/actions/deploy.py	2013-07-16 16:01:18 +0000
+++ lava_dispatcher/actions/deploy.py	2013-08-12 20:36:43 +0000
@@ -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'
--- lava_dispatcher/client/targetdevice.py	2013-07-24 16:56:18 +0000
+++ lava_dispatcher/client/targetdevice.py	2013-08-08 00:15:59 +0000
@@ -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'
--- lava_dispatcher/config.py	2013-07-22 21:18:32 +0000
+++ lava_dispatcher/config.py	2013-08-12 02:30:38 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/arndale.conf	2013-07-02 18:04:30 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/arndale.conf	2013-08-14 20:57:02 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/beagle-xm.conf	2012-03-27 19:31:12 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/beagle-xm.conf	2013-08-12 20:44:14 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone-black.conf	2013-06-05 00:39:23 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone-black.conf	2013-08-14 19:54:58 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone.conf	2013-06-05 00:39:23 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/beaglebone.conf	2013-08-14 19:54:58 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/mx51evk.conf	2011-10-20 04:09:15 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/mx51evk.conf	2013-08-12 20:44:14 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/mx53loco.conf	2012-06-29 08:42:13 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/mx53loco.conf	2013-08-12 20:44:14 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/origen.conf	2012-12-13 22:04:36 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/origen.conf	2013-08-12 20:44:14 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/panda.conf	2013-01-08 03:31:23 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/panda.conf	2013-08-14 20:57:02 +0000
@@ -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'
--- lava_dispatcher/default-config/lava-dispatcher/device-types/snowball.conf	2013-04-18 14:11:37 +0000
+++ lava_dispatcher/default-config/lava-dispatcher/device-types/snowball.conf	2013-08-12 20:44:14 +0000
@@ -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'
--- lava_dispatcher/device/bootloader.py	1970-01-01 00:00:00 +0000
+++ lava_dispatcher/device/bootloader.py	2013-08-12 02:44:22 +0000
@@ -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'
--- lava_dispatcher/device/capri.py	2013-07-16 16:04:57 +0000
+++ lava_dispatcher/device/capri.py	2013-08-12 14:56:36 +0000
@@ -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'
--- lava_dispatcher/device/fastmodel.py	2013-07-24 14:04:25 +0000
+++ lava_dispatcher/device/fastmodel.py	2013-08-12 02:44:22 +0000
@@ -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'
--- lava_dispatcher/device/master.py	2013-07-17 09:16:46 +0000
+++ lava_dispatcher/device/master.py	2013-08-12 02:44:22 +0000
@@ -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'
--- lava_dispatcher/device/target.py	2013-07-17 09:16:46 +0000
+++ lava_dispatcher/device/target.py	2013-08-12 02:44:22 +0000
@@ -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'
--- lava_dispatcher/device/vexpress.py	2013-07-17 09:16:46 +0000
+++ lava_dispatcher/device/vexpress.py	2013-08-12 14:56:36 +0000
@@ -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:

