Add EC and Firmware Versions to the Omaha Response.

This CL adds 2 additional utils methods to get the version for both the
fw and ec versions. I've added a unittest to verify these work and piped
in the values into the omaha response.

BUG=chromium:219871
TEST=Unittests + on device

Change-Id: Iadf70fff858988f52797d94bcdb062bb2482bbf3
Reviewed-on: https://gerrit.chromium.org/gerrit/49713
Commit-Queue: Chris Sosa <sosa@chromium.org>
Reviewed-by: Chris Sosa <sosa@chromium.org>
Tested-by: Chris Sosa <sosa@chromium.org>
diff --git a/utils.cc b/utils.cc
index a6d8d91..d24a61f 100644
--- a/utils.cc
+++ b/utils.cc
@@ -18,6 +18,7 @@
 #include <unistd.h>
 
 #include <algorithm>
+#include <vector>
 
 #include <base/file_path.h>
 #include <base/file_util.h>
@@ -25,6 +26,7 @@
 #include <base/posix/eintr_wrapper.h>
 #include <base/rand_util.h>
 #include <base/string_number_conversions.h>
+#include <base/string_split.h>
 #include <base/string_util.h>
 #include <base/stringprintf.h>
 #include <glib.h>
@@ -41,6 +43,7 @@
 using base::Time;
 using base::TimeDelta;
 using std::min;
+using std::pair;
 using std::string;
 using std::vector;
 
@@ -82,23 +85,70 @@
   return !dev_mode;
 }
 
-string GetHardwareClass() {
-  // TODO(petkov): Convert to a library call once a crossystem library is
-  // available (crosbug.com/13291).
+string ReadValueFromCrosSystem(const string& key){
   int exit_code = 0;
   vector<string> cmd(1, "/usr/bin/crossystem");
-  cmd.push_back("hwid");
+  cmd.push_back(key);
 
-  string hwid;
-  bool success = Subprocess::SynchronousExec(cmd, &exit_code, &hwid);
+  string return_value;
+  bool success = Subprocess::SynchronousExec(cmd, &exit_code, &return_value);
   if (success && !exit_code) {
-    TrimWhitespaceASCII(hwid, TRIM_ALL, &hwid);
-    return hwid;
+    TrimWhitespaceASCII(return_value, TRIM_ALL, &return_value);
+    return return_value;
   }
-  LOG(ERROR) << "Unable to read HWID (" << exit_code << ") " << hwid;
+  LOG(ERROR) << "Unable to read " << key << " (" << exit_code << ") "
+             << return_value;
   return "";
 }
 
+string GetHardwareClass() {
+  return ReadValueFromCrosSystem("hwid");
+}
+
+string GetFirmwareVersion() {
+  return ReadValueFromCrosSystem("fwid");
+}
+
+string GetECVersion(const char* input_line) {
+  string line;
+  if(input_line == NULL) {
+    int exit_code = 0;
+    vector<string> cmd(1, "/usr/sbin/mosys");
+    cmd.push_back("-k");
+    cmd.push_back("ec");
+    cmd.push_back("info");
+
+    bool success = Subprocess::SynchronousExec(cmd, &exit_code, &line);
+    if (!success || exit_code) {
+      LOG(ERROR) << "Unable to read ec info from mosys (" << exit_code << ")";
+      return "";
+    }
+  } else {
+    line = input_line;
+  }
+
+  TrimWhitespaceASCII(line, TRIM_ALL, &line);
+
+  // At this point we want to conver the format key=value pair from mosys to
+  // a vector of key value pairs.
+  vector<pair<string, string> > kv_pairs;
+  if (base::SplitStringIntoKeyValuePairs(line, '=', ' ', &kv_pairs)) {
+    for (vector<pair<string, string> >::iterator it = kv_pairs.begin();
+         it != kv_pairs.end(); ++it) {
+      // Finally match against the fw_verion which may have quotes.
+      if (it->first == "fw_version") {
+        string output;
+        // Trim any quotes.
+        TrimString(it->second, "\"", &output);
+        return output;
+      }
+    }
+  }
+  LOG(ERROR) << "Unable to parse fwid from ec info.";
+  return "";
+}
+
+
 bool WriteFile(const char* path, const char* data, int data_len) {
   DirectFileWriter writer;
   TEST_AND_RETURN_FALSE_ERRNO(0 == writer.Open(path,