blob: a7966ee8510ab93987fb0db083b56cfa69bdea5b [file] [log] [blame]
# Copyright (c) 2012 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.
"""Runs chromeos-firmwareupdate to force update EC/firmware."""
import logging
import os
import subprocess
import threading
import unittest
import factory_common # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.test.env import paths
from cros.factory.test import event
from cros.factory.test.i18n import test_ui as i18n_test_ui
from cros.factory.test import shopfloor
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 process_utils
_TEST_TITLE = i18n_test_ui.MakeI18nLabel('Update Firmware')
_CSS = '#state {text-align:left;}'
class UpdateFirmwareTest(unittest.TestCase):
ARGS = [
Arg('firmware_updater', str, 'Full path of chromeos-firmwareupdate.',
default='/usr/local/factory/board/chromeos-firmwareupdate'),
Arg('rw_only', bool, 'Update only RW firmware', default=False),
Arg('update_ec', bool, 'Update EC firmware.', default=True),
Arg('update_pd', bool, 'Update PD firmware.', default=True),
Arg('umpire', bool, 'Update firmware updater from Umpire server',
default=False),
Arg('update_main', bool, 'Update main firmware.', default=True),
Arg('apply_customization_id', bool,
'Update root key based on the customization_id stored in VPD.',
default=False, optional=True),
]
def setUp(self):
self.dut = device_utils.CreateDUTInterface()
self.just_pass = False
if self.args.umpire:
if shopfloor.get_firmware_updater():
self.args.firmware_updater = paths.FIRMWARE_UPDATER_PATH
else:
self.just_pass = True
else:
self.assertTrue(os.path.isfile(self.args.firmware_updater),
msg='%s is missing.' % self.args.firmware_updater)
self._ui = test_ui.UI()
self._template = ui_templates.OneScrollableSection(self._ui)
self._template.SetTitle(_TEST_TITLE)
self._ui.AppendCSS(_CSS)
def UpdateFirmware(self):
"""Runs firmware updater.
While running updater, it shows updater activity on factory UI.
"""
# Remove /tmp/chromeos-firmwareupdate-running if the process
# doesn't seem to be alive anymore. (http://crosbug.com/p/15642)
LOCK_FILE = '/tmp/chromeos-firmwareupdate-running'
if os.path.exists(LOCK_FILE):
process = process_utils.Spawn(['pgrep', '-f', 'chromeos-firmwareupdate'],
call=True, log=True, read_stdout=True)
if process.returncode == 0:
# Found a chromeos-firmwareupdate alive.
self._ui.Fail('Lock file %s is present and firmware update already '
'running (PID %s)' % (
LOCK_FILE, ', '.join(process.stdout_data.split())))
return
logging.warn('Removing %s', LOCK_FILE)
os.unlink(LOCK_FILE)
command = [self.args.firmware_updater, '--force',
'--update_main' if self.args.update_main else '--noupdate_main',
'--update_ec' if self.args.update_ec else '--noupdate_ec',
'--update_pd' if self.args.update_pd else '--noupdate_pd']
if self.args.rw_only:
command += ['--mode=recovery', '--wp=1']
else:
command += ['--mode=factory']
if self.args.apply_customization_id:
customization_id = self.dut.vpd.ro.get('customization_id')
if customization_id is None:
self._ui.Fail('Customization_id not found in VPD.')
return
if not self.args.update_main:
self._ui.Fail(
'Main firmware must be updated when apply customization_id.')
return
command += ['--customization_id', customization_id]
p = process_utils.Spawn(
command, 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)
# Updates system info so EC and Firmware version in system info box
# are correct.
self._ui.event_client.post_event(
event.Event(event.Event.Type.UPDATE_SYSTEM_INFO))
if p.poll() != 0:
self._ui.Fail('Firmware update failed: %d.' % p.returncode)
else:
self._ui.Pass()
def runTest(self):
if self.just_pass:
return
threading.Thread(target=self.UpdateFirmware).start()
self._ui.Run()