| # Copyright 2017 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Update Cr50 firmware. |
| |
| Description |
| ----------- |
| This test calls `trunks_send` on DUT to update Cr50 firmware. The Cr50 firmware |
| image to update is either from a given path in station or from the release |
| partition on DUT. |
| |
| `trunks_send` is a program with ability to update Cr50 firmware. Notice that |
| some older factory branches might have only `usb_updater` but no `trunks_send`. |
| |
| To prepare Cr50 firmware image on station, download the release image with |
| desired Cr50 firmware image and find the image in FIRMWARE_RELATIVE_PATH below. |
| |
| Test Procedure |
| -------------- |
| This is an automatic test that doesn't need any user interaction. |
| |
| 1. Firstly, this test will create a DUT link. |
| 2. If Cr50 firmware image source is from station, the image would be sent to |
| DUT. Else, the release partition on DUT will be mounted. |
| 3. DUT runs `trunks_send` to update Cr50 firmware. |
| |
| Dependency |
| ---------- |
| - DUT link must be ready before running this test. |
| - `trunks_send` on DUT. |
| - Cr50 firmware image must be prepared. |
| |
| Examples |
| -------- |
| To update Cr50 firmware with the Cr50 firmware image in DUT release partition:: |
| |
| OperatorTest(pytest_name='update_cr50_firmware') |
| |
| To update Cr50 firmware with the Cr50 firmware image in station:: |
| |
| OperatorTest(pytest_name='update_cr50_firmware', |
| dargs=dict(from_release=False, |
| firmware_file='/path/on/station/to/cr50.bin.prod')) |
| """ |
| |
| import logging |
| import os |
| import subprocess |
| import unittest |
| |
| import factory_common # pylint: disable=unused-import |
| from cros.factory.device import device_utils |
| from cros.factory.test import test_ui |
| from cros.factory.test import ui_templates |
| from cros.factory.utils.arg_utils import Arg |
| from cros.factory.utils import sys_utils |
| |
| _CSS = '#state { text-align: left; }' |
| |
| TRUNKS_SEND = '/usr/sbin/trunks_send' |
| FIRMWARE_RELATIVE_PATH = 'opt/google/cr50/firmware/cr50.bin.prod' |
| |
| |
| class UpdateCr50FirmwareTest(unittest.TestCase): |
| ARGS = [ |
| Arg('firmware_file', str, 'The full path of the firmware.', |
| optional=True), |
| Arg('from_release', bool, 'Find the firmware from release rootfs.', |
| optional=True, default=True) |
| ] |
| |
| def setUp(self): |
| self.dut = device_utils.CreateDUTInterface() |
| self._ui = test_ui.UI() |
| self._template = ui_templates.OneScrollableSection(self._ui) |
| self._ui.AppendCSS(_CSS) |
| |
| def UpdateCr50Firmware(self): |
| """Update Cr50 firmware.""" |
| self.assertEqual( |
| 1, len(filter(None, [self.args.firmware_file, self.args.from_release])), |
| 'Must specify exactly one of "firmware_file" or "from_release".') |
| if self.args.firmware_file: |
| if self.dut.link.IsLocal(): |
| self._UpdateCr50Firmware(self.args.firmware_file) |
| else: |
| with self.dut.temp.TempFile() as dut_temp_file: |
| self.dut.SendFile(self.args.firmware_file, dut_temp_file) |
| self._UpdateCr50Firmware(dut_temp_file) |
| elif self.args.from_release: |
| with sys_utils.MountPartition( |
| self.dut.partitions.RELEASE_ROOTFS.path, dut=self.dut) as root: |
| firmware_path = os.path.join(root, FIRMWARE_RELATIVE_PATH) |
| self._UpdateCr50Firmware(firmware_path) |
| |
| def _UpdateCr50Firmware(self, firmware_file): |
| p = self.dut.Popen( |
| [TRUNKS_SEND, '--update', firmware_file], |
| stdout=subprocess.PIPE, stderr=subprocess.STDOUT, log=True) |
| |
| for line in iter(p.stdout.readline, ''): |
| logging.info(line.strip()) |
| self._template.SetState(test_ui.Escape(line), append=True) |
| |
| if p.poll() != 0: |
| self._ui.Fail('Cr50 firmware update failed: %d.' % p.returncode) |
| else: |
| self._ui.Pass() |
| |
| def runTest(self): |
| self._ui.RunInBackground(self.UpdateCr50Firmware) |
| self._ui.Run() |