Commit 3ea9c48c authored by Guillaume Tucker's avatar Guillaume Tucker
Browse files

add servoflash.py to flash any Chromebook using a Servo board



Add servoflash.py as a better tool than device-specific scripts such
as flash-kevin.sh.  This will use the google-servo.conf file to look
up a device's serial number, so the user only has to provide the
device name.

It will not downnload any firmware file automatically, that still has
to be done by the user.

Signed-off-by: Guillaume Tucker's avatarGuillaume Tucker <guillaume.tucker@collabora.com>
parent 4c9d77b7
#!/usr/bin/env python
import argparse
import logging
import os
import servo
import servo.servo_parsing
import subprocess
import sys
import time
class Device(object):
def __init__(self, device, device_name, config_path):
self._device = device
self._device_name = device_name
self._config_path = config_path
@property
def name(self):
return self._device_name
@property
def sn(self):
return self._device['sn']
def _run(self, cmd):
print("* {}".format(cmd))
if subprocess.call(cmd, shell=True):
raise Exception("Command failed")
def _dut_control(self, cmd, sleep=1):
run = 'dut-control --rcfile={} -n {} {}'.format(
self._config_path, self.name, cmd)
self._run(run)
if sleep:
time.sleep(sleep)
def _flag(self, name, status):
cmd = "{}:{}".format(name, "on" if status else "off")
self._dut_control(cmd)
def _reset(self, status):
self._flag("cold_reset", status)
def _spi2_vref(self, status, voltage="pp1800"):
cmd = "spi2_vref:{} spi2_buf_en:{}".format(
voltage, "on" if status else "off")
self._dut_control(cmd)
def _flashrom(self, cmd):
run = "flashrom --programmer raiden_debug_spi:serial={} {}".format(
self.sn, cmd)
self._run(run)
def _read(self, path):
self._flashrom("-r {}".format(path))
def _erase(self):
self._flashrom("-E")
def _write(self, path):
self._flashrom("-w {}".format(path))
def flash(self, fw_path=None, backup_path=None):
raise NotImplementedError("No run() method implemented")
class ServoMicro(Device):
def flash(self, fw_path=None, backup_path=None):
self._reset(False)
self._reset(True)
self._spi2_vref(True)
if backup_path:
self._read(backup_path)
if fw_path:
self._flag("fw_wp_en", True)
self._flag("fw_wp", False)
self._flag("fw_up", True)
time.sleep(1)
self._erase()
time.sleep(1)
self._write(fw_path)
time.sleep(1)
self._spi2_vref(False)
self._flag("cpu_uart_en", True)
self._flag("dev_mode", True)
self._reset(False)
class SuzyQ(Device):
def _flashrom(self, cmd):
run = "\
flashrom --programmer raiden_debug_spi:target=AP,serial={} {}".format(
self.sn, cmd)
self._run(run)
def flash(self, fw_path=None, backup_path=None):
if backup_path:
self._read(backup_path)
if fw_path:
self._write(fw_path)
DEVICE_CLS = {
'grunt': SuzyQ,
'hana': ServoMicro,
'kevin': ServoMicro,
}
def get_device(config, device_name, config_path):
device = config.get(device_name)
if device is None:
return None
cls = DEVICE_CLS[device['board']]
return cls(device, device_name, config_path)
def set_local_env():
cwd = os.getcwd()
bin_path, lib_path = (os.path.join(cwd, x) for x in ['bin', 'lib'])
os.environ.update({
env: ':'.join([path, os.environ.get(env, '')])
for env, path in [('PATH', bin_path), ('LD_LIBRARY_PATH', lib_path)]
})
def get_config(config_path, logger=None):
if logger is None:
logger = logging.getLogger()
return servo.servo_parsing.parse_rc(logger, config_path)
def main(argv):
parser = argparse.ArgumentParser("Servo flashing tool for Chromebooks")
parser.add_argument("--config", default="/etc/google-servo.conf",
help="Path to the servod file")
parser.add_argument("--device",
help="Name of the device to flash")
parser.add_argument("--firmware",
help="Path to the firmware file to flash")
parser.add_argument("--backup",
help="Path to a backup firmware file")
args = parser.parse_args(argv[1:])
set_local_env()
config = get_config(args.config)
if not args.device:
print("Please choose one device:")
for name in config.iterkeys():
print(" {}".format(name))
else:
device = get_device(config, args.device, args.config)
if device is None:
print("Device not found: {}".format(args.device))
sys.exit(1)
print("Device: {}".format(device.name))
print("Serial: {}".format(device.sn))
device.flash(args.firmware, args.backup)
if __name__ == '__main__':
main(sys.argv)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment