init: Add wrapper library for crossystem

Adds C++ style wrapper library for crossystem that allows for testing
by swapping to a fake implementation. The library is based on a version
under login_manager but is not identical.

With this, we can have clobber_state.cc use dependency injection,
allowing for easier and more readable testing.

BUG=chromium:884520
TEST=code builds

Change-Id: I61b10fe367eb030ce525f2ac421e1b935a2b6f4f
Reviewed-on: https://chromium-review.googlesource.com/1387205
Commit-Ready: Fletcher Woodruff <fletcherw@chromium.org>
Tested-by: Fletcher Woodruff <fletcherw@chromium.org>
Reviewed-by: Fletcher Woodruff <fletcherw@chromium.org>
diff --git a/init/BUILD.gn b/init/BUILD.gn
index 7150930..7cb2425 100644
--- a/init/BUILD.gn
+++ b/init/BUILD.gn
@@ -19,6 +19,16 @@
   pkg_deps = [
     "libbrillo-${libbase_ver}",
     "libchrome-${libbase_ver}",
+    "vboot_host"
+  ]
+}
+
+static_library("libcrossystem") {
+  configs += [ ":target_defaults" ]
+  sources = [
+    "crossystem.cc",
+    "crossystem_fake.cc",
+    "crossystem_impl.cc",
   ]
 }
 
diff --git a/init/crossystem.cc b/init/crossystem.cc
new file mode 100644
index 0000000..7a07b17
--- /dev/null
+++ b/init/crossystem.cc
@@ -0,0 +1,9 @@
+// Copyright 2018 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.
+
+#include "init/crossystem.h"
+
+constexpr char CrosSystem::kDevSwitchBoot[];
+constexpr char CrosSystem::kMainFirmwareActive[];
+constexpr char CrosSystem::kClearTpmOwnerRequest[];
diff --git a/init/crossystem.h b/init/crossystem.h
new file mode 100644
index 0000000..ed9dda6
--- /dev/null
+++ b/init/crossystem.h
@@ -0,0 +1,48 @@
+// Copyright 2018 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.
+
+#ifndef INIT_CROSSYSTEM_H_
+#define INIT_CROSSYSTEM_H_
+
+#include <string>
+
+// Light-weight interface to crossystem with std::string semantics.
+class CrosSystem {
+ public:
+  virtual ~CrosSystem() {}
+
+  // Name of property containing the position of the Developer Switch when the
+  // device booted.
+  static constexpr char kDevSwitchBoot[] = "devsw_boot";
+
+  // Name of property containing the active main firmware.
+  static constexpr char kMainFirmwareActive[] = "mainfw_act";
+
+  // Name of property that signals a request to clear TPM owner on next reboot.
+  static constexpr char kClearTpmOwnerRequest[] = "clear_tpm_owner_request";
+
+  // Reads a system property integer into |value_out|.
+  //
+  // Returns true on sucess
+  virtual bool GetInt(const std::string& name, int* value_out) = 0;
+
+  // Sets the system property integer |name| to |value|.
+  //
+  // Returns true on success.
+  virtual bool SetInt(const std::string& name, int value) = 0;
+
+  // Reads a system property string and stores it in |value_out|.
+  //
+  // Returns true on success.
+  virtual bool GetString(const std::string& name, std::string* value_out) = 0;
+
+  // Sets a system property string.
+  //
+  // The maximum length of the value accepted depends on the specific property.
+  //
+  // Returns true on success.
+  virtual bool SetString(const std::string& name, const std::string& value) = 0;
+};
+
+#endif  // INIT_CROSSYSTEM_H_
diff --git a/init/crossystem_fake.cc b/init/crossystem_fake.cc
new file mode 100644
index 0000000..74f5272
--- /dev/null
+++ b/init/crossystem_fake.cc
@@ -0,0 +1,33 @@
+// Copyright 2018 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.
+
+#include "init/crossystem_fake.h"
+
+bool CrosSystemFake::GetInt(const std::string& name, int* value_out) {
+  if (int_map_.count(name) == 0)
+    return false;
+
+  *value_out = int_map_[name];
+  return true;
+}
+
+bool CrosSystemFake::SetInt(const std::string& name, int value) {
+  int_map_[name] = value;
+  return true;
+}
+
+bool CrosSystemFake::GetString(const std::string& name,
+                               std::string* value_out) {
+  if (string_map_.count(name) == 0)
+    return false;
+
+  *value_out = string_map_[name];
+  return true;
+}
+
+bool CrosSystemFake::SetString(const std::string& name,
+                               const std::string& value) {
+  string_map_[name] = value;
+  return true;
+}
diff --git a/init/crossystem_fake.h b/init/crossystem_fake.h
new file mode 100644
index 0000000..1aa67cd
--- /dev/null
+++ b/init/crossystem_fake.h
@@ -0,0 +1,25 @@
+// Copyright 2018 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.
+
+#ifndef INIT_CROSSYSTEM_FAKE_H_
+#define INIT_CROSSYSTEM_FAKE_H_
+
+#include <string>
+#include <unordered_map>
+
+#include "init/crossystem.h"
+
+class CrosSystemFake : public CrosSystem {
+ public:
+  bool GetInt(const std::string& name, int* value_out);
+  bool SetInt(const std::string& name, int value);
+  bool GetString(const std::string& name, std::string* value_out);
+  bool SetString(const std::string& name, const std::string& value);
+
+ private:
+  std::unordered_map<std::string, int> int_map_;
+  std::unordered_map<std::string, std::string> string_map_;
+};
+
+#endif  // INIT_CROSSYSTEM_FAKE_H_
diff --git a/init/crossystem_impl.cc b/init/crossystem_impl.cc
new file mode 100644
index 0000000..ff560ba
--- /dev/null
+++ b/init/crossystem_impl.cc
@@ -0,0 +1,35 @@
+// Copyright 2018 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.
+
+#include "init/crossystem_impl.h"
+
+#include <string>
+
+#include <vboot/crossystem.h>
+
+bool CrosSystemImpl::GetInt(const std::string& name, int* value_out) {
+  int value = ::VbGetSystemPropertyInt(name.c_str());
+  if (value == -1)
+    return false;
+  *value_out = value;
+  return true;
+}
+
+bool CrosSystemImpl::SetInt(const std::string& name, int value) {
+  return 0 == ::VbSetSystemPropertyInt(name.c_str(), value);
+}
+
+bool CrosSystemImpl::GetString(const std::string& name,
+                               std::string* value_out) {
+  char buf[VB_MAX_STRING_PROPERTY];
+  if (0 != ::VbGetSystemPropertyString(name.c_str(), buf, sizeof(buf)))
+    return false;
+  *value_out = std::string(buf);
+  return true;
+}
+
+bool CrosSystemImpl::SetString(const std::string& name,
+                               const std::string& value) {
+  return 0 == ::VbSetSystemPropertyString(name.c_str(), value.c_str());
+}
diff --git a/init/crossystem_impl.h b/init/crossystem_impl.h
new file mode 100644
index 0000000..c8d8322
--- /dev/null
+++ b/init/crossystem_impl.h
@@ -0,0 +1,20 @@
+// Copyright 2018 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.
+
+#ifndef INIT_CROSSYSTEM_IMPL_H_
+#define INIT_CROSSYSTEM_IMPL_H_
+
+#include "init/crossystem.h"
+
+#include <string>
+
+class CrosSystemImpl : public CrosSystem {
+ public:
+  bool GetInt(const std::string& name, int* value_out);
+  bool SetInt(const std::string& name, int value);
+  bool GetString(const std::string& name, std::string* value_out);
+  bool SetString(const std::string& name, const std::string& value);
+};
+
+#endif  // INIT_CROSSYSTEM_IMPL_H_