1 //
2 // Copyright (C) 2013 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "update_engine/hardware_chromeos.h"
18
19 #include <base/files/file_util.h>
20 #include <base/logging.h>
21 #include <base/strings/string_number_conversions.h>
22 #include <base/strings/string_util.h>
23 #include <brillo/make_unique_ptr.h>
24 #include <vboot/crossystem.h>
25
26 extern "C" {
27 #include "vboot/vboot_host.h"
28 }
29
30 #include "update_engine/common/hardware.h"
31 #include "update_engine/common/hwid_override.h"
32 #include "update_engine/common/platform_constants.h"
33 #include "update_engine/common/subprocess.h"
34 #include "update_engine/common/utils.h"
35
36 using std::string;
37 using std::vector;
38
39 namespace {
40
41 const char kOOBECompletedMarker[] = "/home/chronos/.oobe_completed";
42
43 // The stateful directory used by update_engine to store powerwash-safe files.
44 // The files stored here must be whitelisted in the powerwash scripts.
45 const char kPowerwashSafeDirectory[] =
46 "/mnt/stateful_partition/unencrypted/preserve";
47
48 // The powerwash_count marker file contains the number of times the device was
49 // powerwashed. This value is incremented by the clobber-state script when
50 // a powerwash is performed.
51 const char kPowerwashCountMarker[] = "powerwash_count";
52
53 } // namespace
54
55 namespace chromeos_update_engine {
56
57 namespace hardware {
58
59 // Factory defined in hardware.h.
CreateHardware()60 std::unique_ptr<HardwareInterface> CreateHardware() {
61 return brillo::make_unique_ptr(new HardwareChromeOS());
62 }
63
64 } // namespace hardware
65
IsOfficialBuild() const66 bool HardwareChromeOS::IsOfficialBuild() const {
67 return VbGetSystemPropertyInt("debug_build") == 0;
68 }
69
IsNormalBootMode() const70 bool HardwareChromeOS::IsNormalBootMode() const {
71 bool dev_mode = VbGetSystemPropertyInt("devsw_boot") != 0;
72 return !dev_mode;
73 }
74
IsOOBEComplete(base::Time * out_time_of_oobe) const75 bool HardwareChromeOS::IsOOBEComplete(base::Time* out_time_of_oobe) const {
76 struct stat statbuf;
77 if (stat(kOOBECompletedMarker, &statbuf) != 0) {
78 if (errno != ENOENT) {
79 PLOG(ERROR) << "Error getting information about "
80 << kOOBECompletedMarker;
81 }
82 return false;
83 }
84
85 if (out_time_of_oobe != nullptr)
86 *out_time_of_oobe = base::Time::FromTimeT(statbuf.st_mtime);
87 return true;
88 }
89
ReadValueFromCrosSystem(const string & key)90 static string ReadValueFromCrosSystem(const string& key) {
91 char value_buffer[VB_MAX_STRING_PROPERTY];
92
93 const char* rv = VbGetSystemPropertyString(key.c_str(), value_buffer,
94 sizeof(value_buffer));
95 if (rv != nullptr) {
96 string return_value(value_buffer);
97 base::TrimWhitespaceASCII(return_value, base::TRIM_ALL, &return_value);
98 return return_value;
99 }
100
101 LOG(ERROR) << "Unable to read crossystem key " << key;
102 return "";
103 }
104
GetHardwareClass() const105 string HardwareChromeOS::GetHardwareClass() const {
106 if (USE_HWID_OVERRIDE) {
107 return HwidOverride::Read(base::FilePath("/"));
108 }
109 return ReadValueFromCrosSystem("hwid");
110 }
111
GetFirmwareVersion() const112 string HardwareChromeOS::GetFirmwareVersion() const {
113 return ReadValueFromCrosSystem("fwid");
114 }
115
GetECVersion() const116 string HardwareChromeOS::GetECVersion() const {
117 string input_line;
118 int exit_code = 0;
119 vector<string> cmd = {"/usr/sbin/mosys", "-k", "ec", "info"};
120
121 bool success = Subprocess::SynchronousExec(cmd, &exit_code, &input_line);
122 if (!success || exit_code) {
123 LOG(ERROR) << "Unable to read ec info from mosys (" << exit_code << ")";
124 return "";
125 }
126
127 return utils::ParseECVersion(input_line);
128 }
129
GetPowerwashCount() const130 int HardwareChromeOS::GetPowerwashCount() const {
131 int powerwash_count;
132 base::FilePath marker_path = base::FilePath(kPowerwashSafeDirectory).Append(
133 kPowerwashCountMarker);
134 string contents;
135 if (!utils::ReadFile(marker_path.value(), &contents))
136 return -1;
137 base::TrimWhitespaceASCII(contents, base::TRIM_TRAILING, &contents);
138 if (!base::StringToInt(contents, &powerwash_count))
139 return -1;
140 return powerwash_count;
141 }
142
GetNonVolatileDirectory(base::FilePath * path) const143 bool HardwareChromeOS::GetNonVolatileDirectory(base::FilePath* path) const {
144 *path = base::FilePath(constants::kNonVolatileDirectory);
145 return true;
146 }
147
GetPowerwashSafeDirectory(base::FilePath * path) const148 bool HardwareChromeOS::GetPowerwashSafeDirectory(base::FilePath* path) const {
149 *path = base::FilePath(kPowerwashSafeDirectory);
150 return true;
151 }
152
153 } // namespace chromeos_update_engine
154