autotest: refactor firmware installation for cros_host
The actual work of installing firmware is done by servo, so move related
code to servo.py from cros_host.py
BUG=chromium:877180
TEST=Ran below python code in chroot
# cd autotest/files/site_utiles/deployment
import common
from prepare import dut
d = dut.create_host('my-dut-hostname', 'coral', 'santa',
'localhost', 9999)
d.firmware_install('coral-firmware/R64-10068.71.0')
Change-Id: I744b0cb24e8b97b2cb75eea3549998d37c0c78d6
Reviewed-on: https://chromium-review.googlesource.com/1469224
Commit-Ready: Congbin Guo <guocb@chromium.org>
Tested-by: Congbin Guo <guocb@chromium.org>
Reviewed-by: Wai-Hong Tam <waihong@google.com>
diff --git a/server/cros/servo/servo.py b/server/cros/servo/servo.py
index fe564bc..da9f484 100644
--- a/server/cros/servo/servo.py
+++ b/server/cros/servo/servo.py
@@ -13,6 +13,7 @@
import xmlrpclib
from autotest_lib.client.common_lib import error
+from autotest_lib.server import utils as server_utils
from autotest_lib.server.cros.servo import firmware_programmer
# Time to wait when probing for a usb device, it takes on avg 17 seconds
@@ -20,6 +21,25 @@
_USB_PROBE_TIMEOUT = 40
+def _extract_image_from_tarball(tarball, dest_dir, image_candidates):
+ """Try extracting the image_candidates from the tarball.
+
+ @param tarball: The path of the tarball.
+ @param dest_path: The path of the destination.
+ @param image_candidates: A tuple of the paths of image candidates.
+
+ @return: The first path from the image candidates, which succeeds, or None
+ if all the image candidates fail.
+ """
+ for image in image_candidates:
+ status = server_utils.system(
+ ('tar xf %s -C %s %s' % (tarball, dest_dir, image)),
+ timeout=60, ignore_status=True)
+ if status == 0:
+ return image
+ return None
+
+
class _PowerStateController(object):
"""Class to provide board-specific power operations.
@@ -786,7 +806,7 @@
else:
raise error.TestError(
'No firmware programmer for servo version: %s' %
- servo_version)
+ servo_version)
def program_bios(self, image, rw_only=False):
@@ -818,9 +838,59 @@
if not self.is_localhost():
image = self._scp_image(image)
if rw_only:
- self._programmer_rw.program_ec(image)
+ self._programmer_rw.program_ec(image)
else:
- self._programmer.program_ec(image)
+ self._programmer.program_ec(image)
+
+
+ def _reprogram(self, tarball_path, firmware_name, image_candidates,
+ rw_only):
+ """Helper function to reprogram firmware for EC or BIOS.
+
+ @param tarball_path: The path of the downloaded build tarball.
+ @param: firmware_name: either 'EC' or 'BIOS'.
+ @param image_candidates: A tuple of the paths of image candidates.
+ @param rw_only: True to only install firmware to its RW portions. Keep
+ the RO portions unchanged.
+
+ @raise: TestError if cannot extract firmware from the tarball.
+ """
+ dest_dir = os.path.dirname(tarball_path)
+ image = _extract_image_from_tarball(tarball_path, dest_dir,
+ image_candidates)
+ if not image:
+ if firmware_name == 'EC':
+ logging.info('Not a Chrome EC, ignore re-programming it')
+ return
+ else:
+ raise error.TestError('Failed to extract the %s image from '
+ 'tarball' % firmware_name)
+
+ logging.info('Will re-program %s %snow', firmware_name,
+ 'RW ' if rw_only else '')
+
+ if firmware_name == 'EC':
+ self.program_ec(os.path.join(dest_dir, image), rw_only)
+ else:
+ self.program_bios(os.path.join(dest_dir, image), rw_only)
+
+
+ def program_firmware(self, model, tarball_path, rw_only=False):
+ """Program firmware (EC, if applied, and BIOS) of the DUT.
+
+ @param model: The DUT model name.
+ @param tarball_path: The path of the downloaded build tarball.
+ @param rw_only: True to only install firmware to its RW portions. Keep
+ the RO portions unchanged.
+ """
+ ap_image_candidates = ('image.bin', 'image-%s.bin' % model)
+ ec_image_candidates = ('ec.bin', '%s/ec.bin' % model)
+
+ self._reprogram(tarball_path, 'EC', ec_image_candidates, rw_only)
+ self._reprogram(tarball_path, 'BIOS', ap_image_candidates, rw_only)
+
+ self.get_power_state_controller().reset()
+ time.sleep(Servo.BOOT_DELAY)
def _switch_usbkey_power(self, power_state, detection_delay=False):