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 // UpdateManager config path. 54 const char* kConfigFilePath = "/etc/update_manager.conf"; 55 56 // UpdateManager config options: 57 const char* kConfigOptsIsOOBEEnabled = "is_oobe_enabled"; 58 59 } // namespace 60 61 namespace chromeos_update_engine { 62 63 namespace hardware { 64 65 // Factory defined in hardware.h. 66 std::unique_ptr<HardwareInterface> CreateHardware() { 67 return brillo::make_unique_ptr(new HardwareChromeOS()); 68 } 69 70 } // namespace hardware 71 72 bool HardwareChromeOS::IsOfficialBuild() const { 73 return VbGetSystemPropertyInt("debug_build") == 0; 74 } 75 76 bool HardwareChromeOS::IsNormalBootMode() const { 77 bool dev_mode = VbGetSystemPropertyInt("devsw_boot") != 0; 78 return !dev_mode; 79 } 80 81 bool HardwareChromeOS::IsOOBEComplete(base::Time* out_time_of_oobe) const { 82 struct stat statbuf; 83 if (stat(kOOBECompletedMarker, &statbuf) != 0) { 84 if (errno != ENOENT) { 85 PLOG(ERROR) << "Error getting information about " 86 << kOOBECompletedMarker; 87 } 88 return false; 89 } 90 91 if (out_time_of_oobe != nullptr) 92 *out_time_of_oobe = base::Time::FromTimeT(statbuf.st_mtime); 93 return true; 94 } 95 96 static string ReadValueFromCrosSystem(const string& key) { 97 char value_buffer[VB_MAX_STRING_PROPERTY]; 98 99 const char* rv = VbGetSystemPropertyString(key.c_str(), value_buffer, 100 sizeof(value_buffer)); 101 if (rv != nullptr) { 102 string return_value(value_buffer); 103 base::TrimWhitespaceASCII(return_value, base::TRIM_ALL, &return_value); 104 return return_value; 105 } 106 107 LOG(ERROR) << "Unable to read crossystem key " << key; 108 return ""; 109 } 110 111 string HardwareChromeOS::GetHardwareClass() const { 112 if (USE_HWID_OVERRIDE) { 113 return HwidOverride::Read(base::FilePath("/")); 114 } 115 return ReadValueFromCrosSystem("hwid"); 116 } 117 118 string HardwareChromeOS::GetFirmwareVersion() const { 119 return ReadValueFromCrosSystem("fwid"); 120 } 121 122 string HardwareChromeOS::GetECVersion() const { 123 string input_line; 124 int exit_code = 0; 125 vector<string> cmd = {"/usr/sbin/mosys", "-k", "ec", "info"}; 126 127 bool success = Subprocess::SynchronousExec(cmd, &exit_code, &input_line); 128 if (!success || exit_code) { 129 LOG(ERROR) << "Unable to read ec info from mosys (" << exit_code << ")"; 130 return ""; 131 } 132 133 return utils::ParseECVersion(input_line); 134 } 135 136 int HardwareChromeOS::GetPowerwashCount() const { 137 int powerwash_count; 138 base::FilePath marker_path = base::FilePath(kPowerwashSafeDirectory).Append( 139 kPowerwashCountMarker); 140 string contents; 141 if (!utils::ReadFile(marker_path.value(), &contents)) 142 return -1; 143 base::TrimWhitespaceASCII(contents, base::TRIM_TRAILING, &contents); 144 if (!base::StringToInt(contents, &powerwash_count)) 145 return -1; 146 return powerwash_count; 147 } 148 149 bool HardwareChromeOS::SchedulePowerwash() { 150 bool result = utils::WriteFile( 151 kPowerwashMarkerFile, kPowerwashCommand, strlen(kPowerwashCommand)); 152 if (result) { 153 LOG(INFO) << "Created " << marker_file << " to powerwash on next reboot"; 154 } else { 155 PLOG(ERROR) << "Error in creating powerwash marker file: " << marker_file; 156 } 157 158 return result; 159 } 160 161 bool HardwareChromeOS::CancelPowerwash() { 162 bool result = base::DeleteFile(base::FilePath(kPowerwashMarkerFile), false); 163 164 if (result) { 165 LOG(INFO) << "Successfully deleted the powerwash marker file : " 166 << marker_file; 167 } else { 168 PLOG(ERROR) << "Could not delete the powerwash marker file : " 169 << marker_file; 170 } 171 172 return result; 173 } 174 175 bool HardwareChromeOS::GetNonVolatileDirectory(base::FilePath* path) const { 176 *path = base::FilePath(constants::kNonVolatileDirectory); 177 return true; 178 } 179 180 bool HardwareChromeOS::GetPowerwashSafeDirectory(base::FilePath* path) const { 181 *path = base::FilePath(kPowerwashSafeDirectory); 182 return true; 183 } 184 185 } // namespace chromeos_update_engine 186