Home | History | Annotate | Download | only in update_engine
      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