1# Copyright 2019 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5 6""" The autotest performing Cr50 update to the TOT image.""" 7 8 9import logging 10import os 11 12from autotest_lib.client.common_lib.cros import cr50_utils 13from autotest_lib.client.common_lib import error 14from autotest_lib.server import utils 15from autotest_lib.server.cros import gsutil_wrapper 16from autotest_lib.server.cros.faft.firmware_test import FirmwareTest 17 18 19# TOT cr50 images are built as part of the reef image builder. 20BUILDER = 'reef' 21GS_URL = 'gs://chromeos-releases/dev-channel/' + BUILDER 22# Firmware artifacts are stored in files like this. 23# ChromeOS-firmware-R79-12519.0.0-reef.tar.bz2 24FIRMWARE_NAME = 'ChromeOS-firmware-%s-%s.tar.bz2' 25REMOTE_TMPDIR = '/tmp/cr50_tot_update' 26CR50_IMAGE_PATH = 'cr50/ec.bin' 27# Wait 10 seconds for the update to take effect. 28class provision_Cr50TOT(FirmwareTest): 29 """Update cr50 to TOT. 30 31 The reef builder builds cr50. Fetch the image from the latest reef build 32 and update cr50 to that image. This expects that the DUT is running node 33 locked RO. 34 """ 35 version = 1 36 37 def get_latest_builds(self, board='reef-release', 38 bucket='chromeos-image-archive', 39 num_builds=5): 40 """Gets the latest build for the given board. 41 42 Args: 43 board: The board for which the latest build needs to be fetched. 44 bucket: The GS bucket name. 45 num_builds: Number of builds to return. 46 47 Raises: 48 error.TestFail() if the List() method is unable to retrieve the 49 contents of the path gs://<bucket>/<board> for any reason. 50 """ 51 path = 'gs://%s/%s' % (bucket, board) 52 cmd = 'gsutil ls -- %s' % path 53 try: 54 contents = utils.system_output(cmd).splitlines() 55 latest_contents = contents[(num_builds * -1):] 56 latest_builds = [] 57 for content in latest_contents: 58 latest_builds.append(content.strip(path).strip('/')) 59 latest_builds.reverse() 60 logging.info('Checking latest builds %s', latest_builds) 61 return latest_builds 62 except Exception as e: 63 raise error.TestFail('Could not determine the latest build due ' 64 'to exception: %s' % e) 65 66 def get_cr50_build(self, latest_ver, remote_dir): 67 """Download the TOT cr50 image from the reef artifacts.""" 68 bucket = os.path.join(GS_URL, latest_ver.split('-')[-1]) 69 filename = FIRMWARE_NAME % (latest_ver, BUILDER) 70 logging.info('Using cr50 image from %s', latest_ver) 71 72 # Download the firmware artifacts from google storage. 73 gsutil_wrapper.copy_private_bucket(host=self.host, 74 bucket=bucket, 75 filename=filename, 76 destination=remote_dir) 77 78 # Extract the cr50 image. 79 dut_path = os.path.join(remote_dir, filename) 80 result = self.host.run('tar xfv %s -C %s' % (dut_path, remote_dir)) 81 return os.path.join(remote_dir, CR50_IMAGE_PATH) 82 83 84 def get_latest_cr50_build(self): 85 self.host.run('mkdir -p %s' % (REMOTE_TMPDIR)) 86 latest_builds = self.get_latest_builds() 87 for latest_build in latest_builds: 88 try: 89 return self.get_cr50_build(latest_build, REMOTE_TMPDIR) 90 except Exception as e: 91 logging.warning('Unable to find %s cr50 image %s', 92 latest_build, e) 93 raise error.TestFail('Unable to find latest cr50 image in %s' % 94 latest_builds) 95 96 97 def run_once(self, host, force=False): 98 """Update cr50 to the TOT image from the reef builder.""" 99 # TODO(mruthven): remove once the test is successfully scheduled. 100 logging.info('SUCCESSFULLY SCHEDULED PROVISION CR50 TOT UPDATE') 101 if not force: 102 logging.info('skipping update') 103 return 104 logging.info('cr50 version %s', host.servo.get('cr50_version')) 105 self.host = host 106 cr50_path = self.get_latest_cr50_build() 107 logging.info('cr50 image is at %s', cr50_path) 108 local_path = os.path.join(self.resultsdir, 'cr50.bin.tot') 109 self.host.get_file(cr50_path, local_path) 110 111 cr50_utils.GSCTool(self.host, ['-a', cr50_path]) 112 113 self.cr50.wait_for_reboot( 114 timeout=self.faft_config.gsc_update_wait_for_reboot) 115 cr50_version = self.cr50.get_active_version_info()[3].split('/')[-1] 116 logging.info('Cr50 running %s after update', cr50_version) 117 self.make_rootfs_writable() 118 cr50_utils.InstallImage(self.host, local_path, cr50_utils.CR50_PREPVT) 119