1 //
2 // Copyright (C) 2012 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/cros/real_system_state.h"
18 
19 #include <memory>
20 #include <string>
21 #include <utility>
22 
23 #include <base/bind.h>
24 #include <base/files/file_util.h>
25 #include <base/location.h>
26 #include <base/time/time.h>
27 #include <brillo/message_loops/message_loop.h>
28 #include <chromeos/dbus/service_constants.h>
29 
30 #include "update_engine/common/boot_control.h"
31 #include "update_engine/common/boot_control_stub.h"
32 #include "update_engine/common/constants.h"
33 #include "update_engine/common/dlcservice_interface.h"
34 #include "update_engine/common/hardware.h"
35 #include "update_engine/common/utils.h"
36 #include "update_engine/cros/metrics_reporter_omaha.h"
37 #if USE_DBUS
38 #include "update_engine/cros/dbus_connection.h"
39 #endif  // USE_DBUS
40 #include "update_engine/update_manager/state_factory.h"
41 
42 namespace chromeos_update_engine {
43 
Initialize()44 bool RealSystemState::Initialize() {
45   boot_control_ = boot_control::CreateBootControl();
46   if (!boot_control_) {
47     LOG(WARNING) << "Unable to create BootControl instance, using stub "
48                  << "instead. All update attempts will fail.";
49     boot_control_ = std::make_unique<BootControlStub>();
50   }
51 
52   hardware_ = hardware::CreateHardware();
53   if (!hardware_) {
54     LOG(ERROR) << "Error initializing the HardwareInterface.";
55     return false;
56   }
57 
58   kiosk_app_proxy_.reset(new org::chromium::KioskAppServiceInterfaceProxy(
59       DBusConnection::Get()->GetDBus(), chromeos::kKioskAppServiceName));
60 
61   LOG_IF(INFO, !hardware_->IsNormalBootMode()) << "Booted in dev mode.";
62   LOG_IF(INFO, !hardware_->IsOfficialBuild()) << "Booted non-official build.";
63 
64   connection_manager_ = connection_manager::CreateConnectionManager();
65   if (!connection_manager_) {
66     LOG(ERROR) << "Error initializing the ConnectionManagerInterface.";
67     return false;
68   }
69 
70   power_manager_ = power_manager::CreatePowerManager();
71   if (!power_manager_) {
72     LOG(ERROR) << "Error initializing the PowerManagerInterface.";
73     return false;
74   }
75 
76   dlcservice_ = CreateDlcService();
77   if (!dlcservice_) {
78     LOG(ERROR) << "Error initializing the DlcServiceInterface.";
79     return false;
80   }
81 
82   // Initialize standard and powerwash-safe prefs.
83   base::FilePath non_volatile_path;
84   // TODO(deymo): Fall back to in-memory prefs if there's no physical directory
85   // available.
86   if (!hardware_->GetNonVolatileDirectory(&non_volatile_path)) {
87     LOG(ERROR) << "Failed to get a non-volatile directory.";
88     return false;
89   }
90   Prefs* prefs;
91   prefs_.reset(prefs = new Prefs());
92   if (!prefs->Init(non_volatile_path.Append(kPrefsSubDirectory))) {
93     LOG(ERROR) << "Failed to initialize preferences.";
94     return false;
95   }
96 
97   base::FilePath powerwash_safe_path;
98   if (!hardware_->GetPowerwashSafeDirectory(&powerwash_safe_path)) {
99     // TODO(deymo): Fall-back to in-memory prefs if there's no powerwash-safe
100     // directory, or disable powerwash feature.
101     powerwash_safe_path = non_volatile_path.Append("powerwash-safe");
102     LOG(WARNING) << "No powerwash-safe directory, using non-volatile one.";
103   }
104   powerwash_safe_prefs_.reset(prefs = new Prefs());
105   if (!prefs->Init(
106           powerwash_safe_path.Append(kPowerwashSafePrefsSubDirectory))) {
107     LOG(ERROR) << "Failed to initialize powerwash preferences.";
108     return false;
109   }
110 
111   // Check the system rebooted marker file.
112   std::string boot_id;
113   if (utils::GetBootId(&boot_id)) {
114     std::string prev_boot_id;
115     system_rebooted_ = (!prefs_->GetString(kPrefsBootId, &prev_boot_id) ||
116                         prev_boot_id != boot_id);
117     prefs_->SetString(kPrefsBootId, boot_id);
118   } else {
119     LOG(WARNING) << "Couldn't detect the bootid, assuming system was rebooted.";
120     system_rebooted_ = true;
121   }
122 
123   // Initialize the OmahaRequestParams with the default settings. These settings
124   // will be re-initialized before every request using the actual request
125   // options. This initialization here pre-loads current channel and version, so
126   // the DBus service can access it.
127   if (!request_params_.Init("", "", {})) {
128     LOG(WARNING) << "Ignoring OmahaRequestParams initialization error. Some "
129                     "features might not work properly.";
130   }
131 
132   certificate_checker_.reset(
133       new CertificateChecker(prefs_.get(), &openssl_wrapper_));
134   certificate_checker_->Init();
135 
136   update_attempter_.reset(new UpdateAttempter(certificate_checker_.get()));
137 
138   // Initialize the UpdateAttempter before the UpdateManager.
139   update_attempter_->Init();
140 
141   // Initialize the Update Manager using the default state factory.
142   chromeos_update_manager::State* um_state =
143       chromeos_update_manager::DefaultStateFactory(&policy_provider_,
144                                                    kiosk_app_proxy_.get());
145 
146   if (!um_state) {
147     LOG(ERROR) << "Failed to initialize the Update Manager.";
148     return false;
149   }
150   update_manager_.reset(new chromeos_update_manager::UpdateManager(
151       base::TimeDelta::FromSeconds(5),
152       base::TimeDelta::FromHours(12),
153       um_state));
154 
155   // The P2P Manager depends on the Update Manager for its initialization.
156   p2p_manager_.reset(
157       P2PManager::Construct(nullptr,
158                             update_manager_.get(),
159                             "cros_au",
160                             kMaxP2PFilesToKeep,
161                             base::TimeDelta::FromDays(kMaxP2PFileAgeDays)));
162 
163   if (!payload_state_.Initialize()) {
164     LOG(ERROR) << "Failed to initialize the payload state object.";
165     return false;
166   }
167 
168   // For images that are build for debugging purposes like test images
169   // initialize max kernel key version to 0xfffffffe, which is logical infinity.
170   if (!hardware_->IsOfficialBuild()) {
171     if (!hardware()->SetMaxKernelKeyRollforward(
172             chromeos_update_manager::kRollforwardInfinity)) {
173       LOG(ERROR) << "Failed to set kernel_max_rollforward to infinity for"
174                  << " device with test/dev image.";
175     }
176   }
177 
178   // All is well. Initialization successful.
179   return true;
180 }
181 
182 }  // namespace chromeos_update_engine
183