firmware_Cr50Update: move the update code to cr50_utils

More tests will need to run usb_update to new images. This change moves
the usb_update to cr50_utils.

BUG=none
BRANCH=none
TEST=test_that $DUT_IP -b reef --args="release_ver=0.0.19
old_release_ver=0.0.18" firmware_Cr50Update

Change-Id: I6353ad7273e61348369002fbf37318950337831e
Signed-off-by: Mary Ruthven <mruthven@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/522881
diff --git a/client/common_lib/cros/cr50_utils.py b/client/common_lib/cros/cr50_utils.py
index fb98c52..b61e37e 100644
--- a/client/common_lib/cros/cr50_utils.py
+++ b/client/common_lib/cros/cr50_utils.py
@@ -32,6 +32,8 @@
     "--binvers" : 'RO_A:(?P<ro_a>\S+).*RW_A:(?P<rw_a>\S+).*' \
            'RO_B:(?P<ro_b>\S+).*RW_B:(?P<rw_b>\S+)',
 }
+UPDATE_TIMEOUT = 60
+UPDATE_OK = 1
 
 
 def AssertVersionsAreEqual(name_a, ver_a, name_b, ver_b):
@@ -113,6 +115,67 @@
     return FindVersion(result, "--fwver")
 
 
+def CheckArg(arg, shortopt, longopt):
+    """Return True if arg equals longopt or shortopt"""
+    return arg == shortopt or arg == longopt
+
+
+def ParseArgs(args):
+    """Parse the args and determine what the intent of the usb_update command is
+
+    Check each arg and determine if the command will cause a reboot, uses
+    /dev/tpm0, or is getting the running version or the version of a .bin.
+
+    Returns a tuple of bools expect_reboot, systemdev, get_ver
+    """
+    systemdev = False
+    post_reset = False
+    get_ver = False
+    for arg in args:
+        arg = arg.strip()
+        systemdev |= CheckArg(arg, '-s', '--systemdev')
+        get_ver |= CheckArg(arg, '-b', '--binvers')
+        get_ver |= CheckArg(arg, '-f', '--fwver')
+        post_reset |= CheckArg(arg, '-p', '--post_reset')
+        post_reset |= CheckArg(arg, '-u', '--upstart')
+
+    # immediate reboots are only honored if the command is sent using /dev/tpm0
+    expect_reboot = systemdev and not post_reset and not get_ver
+    return expect_reboot, systemdev, get_ver
+
+
+def UsbUpdate(client, args):
+    """Run usb_update with the given args.
+
+    Args:
+        a list of strings that contiain the usb_update args
+
+    Returns:
+        the result of usb_update
+    """
+    expect_reboot, systemdev, get_ver = ParseArgs(args)
+
+    result = client.run("status trunksd")
+    if systemdev and 'running' in result.stdout:
+        client.run("stop trunksd")
+
+    # If we are updating the cr50 image, usb_update will return a non-zero exit
+    # status so we should ignore it.
+    ignore_status = not get_ver
+
+    result = client.run("usb_updater %s" % ' '.join(args),
+                        ignore_status=ignore_status,
+                        ignore_timeout=expect_reboot,
+                        timeout=UPDATE_TIMEOUT)
+
+    # After a posted reboot, the usb_update exit code should equal 1.
+    if result.exit_status and result.exit_status != UPDATE_OK:
+        logging.debug(result)
+        raise error.TestError("Unexpected usb_update exit code after %s %d" %
+                              ' '.join(args), result.exit_status)
+    return result
+
+
 def GetVersionFromUpdater(client, args):
     """Return the version from usb_updater"""
     result = client.run("usb_updater %s" % ' '.join(args)).stdout.strip()
diff --git a/server/site_tests/firmware_Cr50Update/firmware_Cr50Update.py b/server/site_tests/firmware_Cr50Update/firmware_Cr50Update.py
index 1a5bfcc..8905aa9 100644
--- a/server/site_tests/firmware_Cr50Update/firmware_Cr50Update.py
+++ b/server/site_tests/firmware_Cr50Update/firmware_Cr50Update.py
@@ -151,63 +151,26 @@
         super(firmware_Cr50Update, self).cleanup()
 
 
-    def run_usb_update(self, dest, is_newer):
+    def run_usb_update(self, dest):
         """Run usb_update with the given image.
 
-        If the new image version is newer than the one Cr50 is running, then
-        the upstart option will be used. This will reboot the AP after
-        usb_updater runs, so Cr50 will finish the update and jump to the new
-        image.
-
         If the new image version is older than the one Cr50 is running, then the
         best usb_updater can do is flash the image into the inactive partition.
-        To finish th update, the 'rw' command will need to be used to force a
+        To finish the update, the 'rw' command will need to be used to force a
         rollback.
 
         @param dest: the image location.
-        @param is_newer: True if the rw version of the update image is newer
-                         than the one Cr50 is running.
         """
 
-        result = self.host.run("status trunksd")
-        if 'running' in result.stdout:
-            self.host.run("stop trunksd")
-
         # Enable CCD, so we can detect the Cr50 reboot.
         self.cr50.ccd_enable()
-        if is_newer:
-            # Using -u usb_updater will post a reboot request but not reboot
-            # immediately.
-            result = self.host.run("usb_updater -s -u %s" % dest,
-                                   ignore_status=True)
-            exit_status = result.exit_status
-        else:
-            logging.info("Flashing image into inactive partition")
-            # The image at 'dest' is older than the one Cr50 is running, so
-            # upstart cannot be used. Without -u Cr50 will flash the image into
-            # the inactive partition and reboot immediately.
-            result = self.host.run("usb_updater -s %s" % dest,
-                                   ignore_status=True,
-                                   ignore_timeout=True,
-                                   timeout=self.UPDATE_TIMEOUT)
-            # If the command timed out result will be None. That is expected if
-            # Cr50 reboots
-            exit_status = result.exit_status if result else self.UPDATE_OK
 
-        # After a posted reboot, the usb_update exit code should equal 1.
-        if exit_status and exit_status != self.UPDATE_OK:
-            logging.debug(result)
-            raise error.TestError("Got unexpected usb_update exit code %d" %
-                                  result.exit_status)
-
-        # Reset the AP to finish the Cr50 update.
-        if is_newer:
-            self.cr50.send_command("sysrst pulse")
+        cr50_utils.UsbUpdate(self.host, ['-s', dest])
 
         # After usb_updater finishes running, Cr50 will reboot. Wait until Cr50
         # reboots before continuing. Cr50 reboot can be detected by detecting
         # when CCD stops working.
-        self.cr50.wait_for_ccd_disable(raise_error=is_newer)
+        self.cr50.wait_for_ccd_disable()
 
 
     def finish_rollback(self, image_rw):
@@ -286,7 +249,7 @@
         # If a rollback is needed, flash the image into the inactive partition,
         # on or use usb_update to update to the new image if it is requested.
         if use_usb_update or rollback:
-            self.run_usb_update(dest, not rollback)
+            self.run_usb_update(dest)
         # Use cr50 console commands to rollback to the old image.
         if rollback:
             self.finish_rollback(image_rw)