1# Copyright (c) 2021 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 5import logging 6import time 7 8from autotest_lib.server import test 9from autotest_lib.server.hosts import cros_firmware 10from autotest_lib.client.common_lib import error 11 12 13class fleet_FirmwareUpdate(test.test): 14 """Test to update OS bundled firmware and validate DUT is in good state.""" 15 version = 1 16 17 UPDATE_CMD = "/usr/sbin/chromeos-firmwareupdate --wp=1 --mode=autoupdate" 18 19 def update_os_bundled_firmware(self, host): 20 """Update OS bundled firmware, RW only. 21 22 Args: 23 host: Target host machine to update firmware. 24 25 raises: 26 error.TestFail if update firmware cmd return with non-zero code. 27 """ 28 logging.info("Starting update firmware on %s.", host.hostname) 29 try: 30 res = host.run(self.UPDATE_CMD) 31 except: 32 raise error.TestFail("Failed to update firmware.") 33 34 def pre_update_validation(self, host): 35 """Validate DUT is in good state before firmware update. 36 37 Args: 38 host: Target host machine to do the validation. 39 40 raises: 41 error.TestNAError if DUT is not sshable, or not come back after 42 reboot. 43 """ 44 # Ensure the DUT is sshable before firmware update. 45 if not host.is_up(): 46 raise error.TestNAError("DUT is down before firmware update.") 47 48 # Ensure the DUT can reboot normally before firmware update. 49 logging.info("Rebooting %s prior firmware update", host.hostname) 50 try: 51 host.reboot(timeout=host.BOOT_TIMEOUT, wait=True) 52 except Exception as e: 53 logging.error(e) 54 raise error.TestNAError("DUT failed to reboot before firmware" 55 " update.") 56 57 def is_firmware_updated(self, host): 58 """Check whether the DUT is updated to OS bundled firmware. 59 60 Args: 61 host: Target host machine to check. 62 """ 63 model = host.get_platform() 64 expected = cros_firmware._get_available_firmware(host, model) 65 if not expected: 66 logging.info("Couldn't get expected version based on model" 67 " info, skip firmware version check.") 68 actual = host.run("crossystem fwid").stdout 69 logging.debug("Expected firmware: %s, actual firmware on DUT: %s.", 70 expected, actual) 71 return expected == actual 72 73 def post_update_validation(self, host): 74 """Validate DUT is good after firmware update. 75 76 Args: 77 host: Target host machine to do the validation. 78 79 raises: 80 error.TestFail if the DUT failed to pass validation. 81 """ 82 try: 83 host.reboot(timeout=host.BOOT_TIMEOUT, wait=True) 84 except Exception as e: 85 logging.error(e) 86 raise error.TestFail("DUT didn't come back from reboot after" 87 " firmware update.") 88 if not self.is_firmware_updated(host): 89 raise error.TestFail("Firmware on DUT mismatch with OS bundled" 90 " firmware after update.") 91 92 def run_once(self, host): 93 """Main control of test steps: 94 95 1. Pre-update validation, ensure the DUT is in good state before actual 96 test to reduce flakiness. 97 2. Firmware update, update os bundled firmware in RW portion. 98 3. Post-update validation, test if the DUT is still in good state after 99 receive firmware update. 100 """ 101 self.pre_update_validation(host) 102 # Need to wait for machine fully ready for firmware update to reduce 103 # flakiness. 104 time.sleep(60) 105 if self.is_firmware_updated(host): 106 raise error.TestNAError("Firmware version on the DUT is already" 107 " up-to-date.") 108 self.update_os_bundled_firmware(host) 109 self.post_update_validation(host) 110