autotest: Support the flow to update RW firmware for BIOS and EC

This change completes the flow to update RW firmware, through
CrosHost.firmware_install(), Servo.program_bios()/Servo.program_ec(),
ProgrammerV3RwOnly.program_bios(), to FlashromProgrammer.program().

BUG=chromium:555709
TEST=Ran the following script:
import common
from autotest_lib.server import hosts
h = hosts.create_host(DUT_IP, servo_args={})
h.firmware_install(RO_VERSION)
h.firmware_install(RW_VERSION, rw_only=True)

Checked the DUT installed the proper RO and RW firmware (BIOS and EC).

Change-Id: I5dfca7b3d80c6cd23b0c1e3d2605fce008bd60b2
Reviewed-on: https://chromium-review.googlesource.com/320825
Commit-Ready: Wai-Hong Tam <waihong@chromium.org>
Tested-by: Wai-Hong Tam <waihong@chromium.org>
Reviewed-by: Dan Shi <dshi@google.com>
diff --git a/server/cros/servo/servo.py b/server/cros/servo/servo.py
index 602e152..6118f66 100644
--- a/server/cros/servo/servo.py
+++ b/server/cros/servo/servo.py
@@ -687,7 +687,12 @@
         return self._server.get_version()
 
 
-    def _initialize_programmer(self):
+    def _initialize_programmer(self, rw_only=False):
+        """Initialize the firmware programmer.
+
+        @param rw_only: True to initialize a programmer which only
+                        programs the RW portions.
+        """
         if self._programmer:
             return
         # Initialize firmware programmer
@@ -696,36 +701,45 @@
             self._programmer = firmware_programmer.ProgrammerV2(self)
         elif servo_version.startswith('servo_v3'):
             self._programmer = firmware_programmer.ProgrammerV3(self)
+            self._programmer_rw = firmware_programmer.ProgrammerV3RwOnly(self)
         else:
             raise error.TestError(
                     'No firmware programmer for servo version: %s' %
                          servo_version)
 
 
-    def program_bios(self, image):
+    def program_bios(self, image, rw_only=False):
         """Program bios on DUT with given image.
 
         @param image: a string, file name of the BIOS image to program
                       on the DUT.
+        @param rw_only: True to only program the RW portion of BIOS.
 
         """
         self._initialize_programmer()
         if not self.is_localhost():
             image = self._scp_image(image)
-        self._programmer.program_bios(image)
+        if rw_only:
+            self._programmer_rw.program_bios(image)
+        else:
+            self._programmer.program_bios(image)
 
 
-    def program_ec(self, image):
+    def program_ec(self, image, rw_only=False):
         """Program ec on DUT with given image.
 
         @param image: a string, file name of the EC image to program
                       on the DUT.
+        @param rw_only: True to only program the RW portion of EC.
 
         """
         self._initialize_programmer()
         if not self.is_localhost():
             image = self._scp_image(image)
-        self._programmer.program_ec(image)
+        if rw_only:
+           self._programmer_rw.program_ec(image)
+        else:
+           self._programmer.program_ec(image)
 
 
     def _switch_usbkey_power(self, power_state, detection_delay=False):