fw_wp_state: Introduce abstraction of firmware write-protection
Modifying the firmware protection is different on CCD-capable devices.
It is done by the 'wp' command on CCD console instead of the servo
pins:
fw_wp_vref:some_voltage
fw_wp_en:on
fw_wp:on/off
This CL unifies these 2 approaches by introducing a new servo
control, fw_wp_state (similar to power_state). Different boards have
different implementations (via servo overlay and driver).
BUG=chrome-os-partner:58041
TEST=Tested on servo v3 with micro-servo and CCD.
servo> dut-control fw_wp_state:force_on fw_wp_state
fw_wp_state:force_on
dut> crossystem wpsw_cur # Firmware WP hardware switch current position
1
servo> dut-control fw_wp_state:force_off fw_wp_state
fw_wp_state:force_off
dut> crossystem wpsw_cur
0
servo> dut-control fw_wp_state:reset fw_wp_state # micro-servo only
fw_wp_state:off
dut> crossystem wpsw_cur
0
Change-Id: If8dd7c0b07ccd820b4d956cef6cc48ba2685b320
Reviewed-on: https://chromium-review.googlesource.com/397839
Commit-Ready: Wai-Hong Tam <waihong@google.com>
Tested-by: Wai-Hong Tam <waihong@google.com>
Reviewed-by: Wai-Hong Tam <waihong@google.com>
diff --git a/servo/data/ccd_cr50.xml b/servo/data/ccd_cr50.xml
index 84a3726..2130746 100644
--- a/servo/data/ccd_cr50.xml
+++ b/servo/data/ccd_cr50.xml
@@ -75,4 +75,9 @@
<params subtype="ccd_ec_uart_en" interface="8" drv="cr50" map="onoff"
clobber_ok="" init="on"></params>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params interface="8" drv="fw_wp_ccd" input_type="str"/>
+ </control>
</root>
diff --git a/servo/data/servo_auron_overlay.xml b/servo/data/servo_auron_overlay.xml
index 901cfee..d8d261c 100644
--- a/servo/data/servo_auron_overlay.xml
+++ b/servo/data/servo_auron_overlay.xml
@@ -10,4 +10,9 @@
<doc>Used to turn the DUT off and on</doc>
<params clobber_ok="" reset_recovery="5.0"/>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/data/servo_beltino_overlay.xml b/servo/data/servo_beltino_overlay.xml
index 3815445..76a4443 100644
--- a/servo/data/servo_beltino_overlay.xml
+++ b/servo/data/servo_beltino_overlay.xml
@@ -11,4 +11,9 @@
<params clobber_ok="" cmd="set" interface="servo" drv="beltino_power"
input_type="str" reset_hold="0.1" reset_recovery="0.0"/>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/data/servo_cyan_overlay.xml b/servo/data/servo_cyan_overlay.xml
index e3e0026..dd50e13 100644
--- a/servo/data/servo_cyan_overlay.xml
+++ b/servo/data/servo_cyan_overlay.xml
@@ -12,6 +12,11 @@
shutdown_delay="11.0" />
</control>
<control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp1800"/>
+ </control>
+ <control>
<name>ec_chip</name>
<doc>EC chip name (read-only)</doc>
<params clobber_ok="" cmd="get" subtype="chip" interface="servo"
diff --git a/servo/data/servo_glados_overlay.xml b/servo/data/servo_glados_overlay.xml
index 616e590..4013789 100644
--- a/servo/data/servo_glados_overlay.xml
+++ b/servo/data/servo_glados_overlay.xml
@@ -14,6 +14,11 @@
shutdown_delay="11.0" boot_to_rec_screen_delay="5.0" />
</control>
<control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
+ <control>
<name>dev_mode</name>
<alias>usbpd_boot_mode</alias>
<params clobber_ok="" od="PU" map="onoff_i"></params>
diff --git a/servo/data/servo_gnawty_overlay.xml b/servo/data/servo_gnawty_overlay.xml
index 9073c39..7973463 100644
--- a/servo/data/servo_gnawty_overlay.xml
+++ b/servo/data/servo_gnawty_overlay.xml
@@ -11,4 +11,9 @@
<params drv="cros_ec_softrec_power" clobber_ok="" reset_recovery="0.6"
shutdown_delay="11.0" />
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/data/servo_jecht_overlay.xml b/servo/data/servo_jecht_overlay.xml
index 3815445..76a4443 100644
--- a/servo/data/servo_jecht_overlay.xml
+++ b/servo/data/servo_jecht_overlay.xml
@@ -11,4 +11,9 @@
<params clobber_ok="" cmd="set" interface="servo" drv="beltino_power"
input_type="str" reset_hold="0.1" reset_recovery="0.0"/>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/data/servo_kunimitsu_overlay.xml b/servo/data/servo_kunimitsu_overlay.xml
index ae8faa9..5d1283e 100644
--- a/servo/data/servo_kunimitsu_overlay.xml
+++ b/servo/data/servo_kunimitsu_overlay.xml
@@ -7,4 +7,9 @@
<alias>usbpd_boot_mode</alias>
<params clobber_ok="" od="PP" map="onoff"></params>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/data/servo_link_overlay.xml b/servo/data/servo_link_overlay.xml
index f3ee378..5a6fbc8 100644
--- a/servo/data/servo_link_overlay.xml
+++ b/servo/data/servo_link_overlay.xml
@@ -16,4 +16,9 @@
<params clobber_ok="" cmd="set" drv="link_power"
shutdown_ec_command="x86shutdown"/>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/data/servo_micro.xml b/servo/data/servo_micro.xml
index a44f9ee..a134204 100644
--- a/servo/data/servo_micro.xml
+++ b/servo/data/servo_micro.xml
@@ -239,8 +239,12 @@
<params interface="4" drv="tca6416" slv="0x20" od="PU" port="1"
offset="7" map="onoff" init="off"></params>
</control>
-
-
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params interface="servo" drv="fw_wp_servoflex" input_type="str"
+ fw_wp_vref="pp1800"/>
+ </control>
<!-- UART and CONSOLE settings -->
<control>
diff --git a/servo/data/servo_ninja_overlay.xml b/servo/data/servo_ninja_overlay.xml
index 36390b7..c8a2ad8 100644
--- a/servo/data/servo_ninja_overlay.xml
+++ b/servo/data/servo_ninja_overlay.xml
@@ -14,4 +14,9 @@
<params drv="cros_ec_softrec_power" clobber_ok="" reset_recovery="0.6"
shutdown_delay="11.0" />
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/data/servo_nyan_overlay.xml b/servo/data/servo_nyan_overlay.xml
index bbc1ecc..4ab929e 100644
--- a/servo/data/servo_nyan_overlay.xml
+++ b/servo/data/servo_nyan_overlay.xml
@@ -11,4 +11,9 @@
<params clobber_ok="" shutdown_delay="3.0" reset_recovery="5.0"
drv="cros_ec_softrec_power" />
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="off"/>
+ </control>
</root>
diff --git a/servo/data/servo_quawks_overlay.xml b/servo/data/servo_quawks_overlay.xml
index 134e5ad..2a707d3 100644
--- a/servo/data/servo_quawks_overlay.xml
+++ b/servo/data/servo_quawks_overlay.xml
@@ -2,4 +2,9 @@
<include>
<name>servo_rambi_overlay.xml</name>
</include>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="off"/>
+ </control>
</root>
diff --git a/servo/data/servo_rambi_overlay.xml b/servo/data/servo_rambi_overlay.xml
index 2c95cd0..5cce66c 100644
--- a/servo/data/servo_rambi_overlay.xml
+++ b/servo/data/servo_rambi_overlay.xml
@@ -11,4 +11,9 @@
<params drv="cros_ec_softrec_power" clobber_ok=""
shutdown_delay="11.0" />
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp1800"/>
+ </control>
</root>
diff --git a/servo/data/servo_reef_overlay.xml b/servo/data/servo_reef_overlay.xml
index 68f77c8..bc35a22 100644
--- a/servo/data/servo_reef_overlay.xml
+++ b/servo/data/servo_reef_overlay.xml
@@ -14,6 +14,11 @@
shutdown_delay="11.0" />
</control>
<control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp1800"/>
+ </control>
+ <control>
<name>ec_chip</name>
<doc>EC chip name (read-only)</doc>
<params clobber_ok="" cmd="get" subtype="chip" interface="servo"
diff --git a/servo/data/servo_samus_overlay.xml b/servo/data/servo_samus_overlay.xml
index 999f380..7c3862e 100644
--- a/servo/data/servo_samus_overlay.xml
+++ b/servo/data/servo_samus_overlay.xml
@@ -15,6 +15,11 @@
shutdown_delay="11.0" boot_to_rec_screen_delay="10.0" />
</control>
<control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
+ <control>
<name>usbpd_chip</name>
<doc>USB PD chip name (read-only)</doc>
<params clobber_ok="" cmd="get" subtype="chip" interface="servo"
diff --git a/servo/data/servo_slippy_overlay.xml b/servo/data/servo_slippy_overlay.xml
index 901cfee..d8d261c 100644
--- a/servo/data/servo_slippy_overlay.xml
+++ b/servo/data/servo_slippy_overlay.xml
@@ -10,4 +10,9 @@
<doc>Used to turn the DUT off and on</doc>
<params clobber_ok="" reset_recovery="5.0"/>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/data/servo_strago_overlay.xml b/servo/data/servo_strago_overlay.xml
index 1119745..1622849 100644
--- a/servo/data/servo_strago_overlay.xml
+++ b/servo/data/servo_strago_overlay.xml
@@ -12,6 +12,11 @@
shutdown_delay="11.0" />
</control>
<control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp1800"/>
+ </control>
+ <control>
<name>ec_chip</name>
<doc>EC chip name (read-only)</doc>
<params clobber_ok="" cmd="get" subtype="chip" interface="servo"
diff --git a/servo/data/servo_v2_r0.xml b/servo/data/servo_v2_r0.xml
index 700cb19..c0cddf1 100644
--- a/servo/data/servo_v2_r0.xml
+++ b/servo/data/servo_v2_r0.xml
@@ -728,4 +728,10 @@
<params interface="10" drv="ec3po_driver" map="onoff" init="on"
subtype="interp_connect"></params>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params interface="servo" drv="fw_wp_servoflex" input_type="str"
+ fw_wp_vref="pp1800"/>
+ </control>
</root>
diff --git a/servo/data/servo_v3_r0.xml b/servo/data/servo_v3_r0.xml
index 65e8c1b..0ebe4a0 100644
--- a/servo/data/servo_v3_r0.xml
+++ b/servo/data/servo_v3_r0.xml
@@ -671,4 +671,10 @@
<params interface="10" drv="ec3po_driver" map="onoff" init="on"
subtype="interp_connect"></params>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params interface="servo" drv="fw_wp_servoflex" input_type="str"
+ fw_wp_vref="pp1800"/>
+ </control>
</root>
diff --git a/servo/data/servo_veyron_overlay.xml b/servo/data/servo_veyron_overlay.xml
index c68d0ff..db26b6b 100644
--- a/servo/data/servo_veyron_overlay.xml
+++ b/servo/data/servo_veyron_overlay.xml
@@ -12,4 +12,9 @@
<params clobber_ok="" cmd="set" shutdown_ec_command="power off"
drv="veyron_power" reset_recovery="0.5"/>
</control>
+ <control>
+ <name>fw_wp_state</name>
+ <doc>Used to turn fw wp off and on</doc>
+ <params clobber_ok="" fw_wp_vref="pp3300"/>
+ </control>
</root>
diff --git a/servo/drv/__init__.py b/servo/drv/__init__.py
index b87b26a..96273fd 100644
--- a/servo/drv/__init__.py
+++ b/servo/drv/__init__.py
@@ -23,6 +23,9 @@
import ec3po_gpio
import ec3po_driver
import ec3po_servo_micro
+import fw_wp_ccd
+import fw_wp_servoflex
+import fw_wp_state
import gpio
import hw_driver
import i2c_reg
diff --git a/servo/drv/fw_wp_ccd.py b/servo/drv/fw_wp_ccd.py
new file mode 100644
index 0000000..ca7e7d4
--- /dev/null
+++ b/servo/drv/fw_wp_ccd.py
@@ -0,0 +1,49 @@
+# Copyright 2016 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.
+
+import fw_wp_state
+import pty_driver
+
+
+class fwWpCcdError(Exception):
+ """Exception class for fwWpCcd."""
+
+
+class fwWpCcd(fw_wp_state.FwWpStateDriver, pty_driver.ptyDriver):
+ """Driver for fw_wp_state for boards with CCD."""
+
+ def __init__(self, interface, params):
+ """Constructor.
+
+ Args:
+ interface: driver interface object
+ params: dictionary of params
+ """
+ super(fwWpCcd, self).__init__(interface, params)
+
+ def _force_on(self):
+ """Force the firmware to write-protected."""
+ self._issue_cmd("wp on")
+
+ def _force_off(self):
+ """Force the firmware to not write-protected."""
+ self._issue_cmd("wp off")
+
+ def _reset(self):
+ """Reset the firmware write-protection state to the system value."""
+ # The WP is totally controlled by CCD chip. Do nothing to reset.
+ pass
+
+ def _get_state(self):
+ """Get the firmware write-protection state."""
+ # The output string is defined in ec/board/cr50/wp.c
+ result = self._issue_cmd_get_results(
+ "wp", ["Flash WP is (enabled|disabled)"])[0]
+ if result is None:
+ raise fwWpCcdError("Cannot retrieve wp result on CCD console.")
+
+ if result[1] == "enabled":
+ return self._STATE_FORCE_ON
+ else:
+ return self._STATE_FORCE_OFF
diff --git a/servo/drv/fw_wp_servoflex.py b/servo/drv/fw_wp_servoflex.py
new file mode 100644
index 0000000..91d2568
--- /dev/null
+++ b/servo/drv/fw_wp_servoflex.py
@@ -0,0 +1,44 @@
+# Copyright 2016 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.
+
+import fw_wp_state
+
+
+class fwWpServoflex(fw_wp_state.FwWpStateDriver):
+ """Driver for fw_wp_state for boards connecting servoflex's."""
+
+ def __init__(self, interface, params):
+ """Constructor.
+
+ Args:
+ interface: driver interface object
+ params: dictionary of params
+ """
+ super(fwWpServoflex, self).__init__(interface, params)
+ self._fw_wp_vref = self._params.get('fw_wp_vref', 'pp1800')
+
+ def _force_on(self):
+ """Force the firmware to write-protected."""
+ self._interface.set('fw_wp_vref', self._fw_wp_vref)
+ self._interface.set('fw_wp_en', 'on')
+ self._interface.set('fw_wp', 'on')
+
+ def _force_off(self):
+ """Force the firmware to not write-protected."""
+ self._interface.set('fw_wp_vref', self._fw_wp_vref)
+ self._interface.set('fw_wp_en', 'on')
+ self._interface.set('fw_wp', 'off')
+
+ def _reset(self):
+ """Reset the firmware write-protection state to the system value."""
+ self._interface.set('fw_wp_en', 'off')
+
+ def _get_state(self):
+ """Get the firmware write-protection state."""
+ fw_wp_en = (self._interface.get('fw_wp_en') == 'on')
+ fw_wp = (self._interface.get('fw_wp') == 'on')
+ if fw_wp_en:
+ return self._STATE_FORCE_ON if fw_wp else self._STATE_FORCE_OFF
+ else:
+ return self._STATE_ON if fw_wp else self._STATE_OFF
diff --git a/servo/drv/fw_wp_state.py b/servo/drv/fw_wp_state.py
new file mode 100644
index 0000000..172a3aa
--- /dev/null
+++ b/servo/drv/fw_wp_state.py
@@ -0,0 +1,70 @@
+# Copyright 2016 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.
+
+import hw_driver
+
+
+class FwWpStateDriver(hw_driver.HwDriver):
+ """Abstract superclass to provide board-specific WP operations.
+
+ This driver handles a single control with these settings:
+ * 'force_on' - Force to turn on firmware write-protection.
+ * 'force_off' - Force to turn off firmware write-protection.
+ * 'reset' - For setter, reset the value to the system one.
+ * 'on' - For getter, the system value is write-protected.
+ * 'off' - For getter, the system value is not write-protected.
+
+ Actual implementation of the required behaviors is delegated to
+ the methods `_force_on()`, `_force_off()`, `_reset()`, and
+ `_get_state()`, which must be implemented in a subclass.
+
+ """
+
+ _STATE_FORCE_ON = 'force_on'
+ _STATE_FORCE_OFF = 'force_off'
+ _STATE_RESET = 'reset'
+ _STATE_ON = 'on'
+ _STATE_OFF = 'off'
+
+ def __init__(self, interface, params):
+ """Constructor.
+
+ Args:
+ interface: driver interface object
+ params: dictionary of params
+ """
+ super(FwWpStateDriver, self).__init__(interface, params)
+
+ def _force_on(self):
+ """Force the firmware to write-protected."""
+ raise NotImplementedError()
+
+ def _force_off(self):
+ """Force the firmware to not write-protected."""
+ raise NotImplementedError()
+
+ def _reset(self):
+ """Reset the firmware write-protection state to the system value."""
+ raise NotImplementedError()
+
+ def _get_state(self):
+ """Get the firmware write-protection state."""
+ raise NotImplementedError()
+
+ def set(self, statename):
+ """Set firmware write-protection state according to `statename`."""
+ if statename == self._STATE_FORCE_ON:
+ self._force_on()
+ elif statename == self._STATE_FORCE_OFF:
+ self._force_off()
+ elif statename == self._STATE_RESET:
+ self._reset()
+ else:
+ raise ValueError("Invalid fw_wp_state setting: '%s'. Try one of "
+ "'%s', '%s', or '%s'." % (statename,
+ self._FORCE_ON, self._FORCE_OFF, self._RESET))
+
+ def get(self):
+ """Get firmware write-protection state."""
+ return self._get_state()