Add methods to backup firmware RW

Here adds two method in faftsequence.py: backup_firmware() and
restore_firmware(). Also add associated method to retrieve firmware sha and
modify firmware rw. These two methods only backup vblock and body of firmware
rw section A and B.

BUG=chromium-os:33641
CQ-DEPEND=32503
TEST=Use backup_firmware() and restore_firmware() in tests.

Change-Id: I97b289f24765bf5bccd19fa61fe7e50594240d86
Reviewed-on: https://gerrit.chromium.org/gerrit/32504
Reviewed-by: Tom Wai-Hong Tam <waihong@chromium.org>
Commit-Ready: Tom Wai-Hong Tam <waihong@chromium.org>
Tested-by: Tom Wai-Hong Tam <waihong@chromium.org>
diff --git a/client/cros/saft/flashrom_handler.py b/client/cros/saft/flashrom_handler.py
index 2870192..36c81a6 100644
--- a/client/cros/saft/flashrom_handler.py
+++ b/client/cros/saft/flashrom_handler.py
@@ -1,3 +1,4 @@
+#!/usr/bin/python
 # Copyright (c) 2010 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.
@@ -27,6 +28,7 @@
         self._version = -1  # Is not set on construction.
         self._flags = 0  # Is not set on construction.
         self._sha = None  # Is not set on construction.
+        self._sig_sha = None # Is not set on construction.
         self._datakey_version = -1 # Is not set on construction.
         self._kernel_subkey_version = -1 # Is not set on construction.
 
@@ -48,6 +50,9 @@
     def get_sha(self):
         return self._sha
 
+    def get_sig_sha(self):
+        return self._sig_sha
+
     def get_datakey_version(self):
         return self._datakey_version
 
@@ -63,6 +68,9 @@
     def set_sha(self, sha):
         self._sha = sha
 
+    def set_sig_sha(self, sha):
+        self._sig_sha = sha
+
     def set_datakey_version(self, version):
         self._datakey_version = version
 
@@ -168,6 +176,10 @@
             section.set_kernel_subkey_version(
                 self.chros_if.retrieve_kernel_subkey_version(vb_section))
 
+            s = hashlib.sha1()
+            s.update(self.fum.get_section(self.image, section.get_sig_name()))
+            section.set_sig_sha(s.hexdigest())
+
         if not self.pub_key_file:
             self._retrieve_pub_key()
 
@@ -382,6 +394,10 @@
             raise FlashromHandlerError(e)
         return gbb_flags
 
+    def get_section_sig_sha(self, section):
+        """Retrieve SHA1 hash of a firmware vblock section"""
+        return self.fv_sections[section].get_sig_sha()
+
     def get_section_sha(self, section):
         """Retrieve SHA1 hash of a firmware body section"""
         return self.fv_sections[section].get_sha()
@@ -408,6 +424,12 @@
         blob = self.fum.get_section(self.image, subsection_name)
         return blob
 
+    def get_section_sig(self, section):
+        """Retrieve vblock of a firmware section"""
+        subsection_name = self.fv_sections[section].get_sig_name()
+        blob = self.fum.get_section(self.image, subsection_name)
+        return blob
+
     def _find_ecbin_offset(self, blob):
         """Return the offset of EC binary from the given firmware blob"""
         # The RW firmware is concatenated from u-boot, dtb, and ecbin.
@@ -438,11 +460,26 @@
         ecbin = blob[ecbin_offset :].rstrip(pad)
         return ecbin
 
-    def set_section_body(self, section, blob):
+    def set_section_body(self, section, blob, write_through=False):
         """Put the supplied blob to the body of the firmware section"""
         subsection_name = self.fv_sections[section].get_body_name()
         self.image = self.fum.put_section(self.image, subsection_name, blob)
 
+        if write_through:
+            self.dump_partial(subsection_name,
+                              self.chros_if.state_dir_file(subsection_name))
+            self.fum.write_partial(self.image, (subsection_name, ))
+
+    def set_section_sig(self, section, blob, write_through=False):
+        """Put the supplied blob to the vblock of the firmware section"""
+        subsection_name = self.fv_sections[section].get_sig_name()
+        self.image = self.fum.put_section(self.image, subsection_name, blob)
+
+        if write_through:
+            self.dump_partial(subsection_name,
+                              self.chros_if.state_dir_file(subsection_name))
+            self.fum.write_partial(self.image, (subsection_name, ))
+
     def set_section_ecbin(self, section, ecbin, write_through=False):
         """Put the supplied EC binary to the firwmare section.