1 //
2 // Copyright (C) 2015 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_android.h"
18 
19 #include <fcntl.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 
23 #include <algorithm>
24 
25 #include <bootloader.h>
26 
27 #include <base/files/file_util.h>
28 #include <base/strings/stringprintf.h>
29 #include <brillo/make_unique_ptr.h>
30 #include <cutils/properties.h>
31 
32 #include "update_engine/common/hardware.h"
33 #include "update_engine/common/platform_constants.h"
34 #include "update_engine/common/utils.h"
35 #include "update_engine/utils_android.h"
36 
37 using std::string;
38 
39 namespace chromeos_update_engine {
40 
41 namespace {
42 
43 // The powerwash arguments passed to recovery. Arguments are separated by \n.
44 const char kAndroidRecoveryPowerwashCommand[] =
45     "recovery\n"
46     "--wipe_data\n"
47     "--reason=wipe_data_from_ota\n";
48 
49 // Android properties that identify the hardware and potentially non-updatable
50 // parts of the bootloader (such as the bootloader version and the baseband
51 // version).
52 const char kPropBootBootloader[] = "ro.boot.bootloader";
53 const char kPropBootBaseband[] = "ro.boot.baseband";
54 const char kPropProductManufacturer[] = "ro.product.manufacturer";
55 const char kPropBootHardwareSKU[] = "ro.boot.hardware.sku";
56 const char kPropBootRevision[] = "ro.boot.revision";
57 
58 // Write a recovery command line |message| to the BCB. The arguments to recovery
59 // must be separated by '\n'. An empty string will erase the BCB.
WriteBootloaderRecoveryMessage(const string & message)60 bool WriteBootloaderRecoveryMessage(const string& message) {
61   base::FilePath misc_device;
62   if (!utils::DeviceForMountPoint("/misc", &misc_device))
63     return false;
64 
65   // Setup a bootloader_message with just the command and recovery fields set.
66   bootloader_message boot = {};
67   if (!message.empty()) {
68     strncpy(boot.command, "boot-recovery", sizeof(boot.command) - 1);
69     memcpy(boot.recovery,
70            message.data(),
71            std::min(message.size(), sizeof(boot.recovery) - 1));
72   }
73 
74   int fd =
75       HANDLE_EINTR(open(misc_device.value().c_str(), O_WRONLY | O_SYNC, 0600));
76   if (fd < 0) {
77     PLOG(ERROR) << "Opening misc";
78     return false;
79   }
80   ScopedFdCloser fd_closer(&fd);
81   // We only re-write the first part of the bootloader_message, up to and
82   // including the recovery message.
83   size_t boot_size =
84       offsetof(bootloader_message, recovery) + sizeof(boot.recovery);
85   if (!utils::WriteAll(fd, &boot, boot_size)) {
86     PLOG(ERROR) << "Writing recovery command to misc";
87     return false;
88   }
89   return true;
90 }
91 
92 }  // namespace
93 
94 namespace hardware {
95 
96 // Factory defined in hardware.h.
CreateHardware()97 std::unique_ptr<HardwareInterface> CreateHardware() {
98   return brillo::make_unique_ptr(new HardwareAndroid());
99 }
100 
101 }  // namespace hardware
102 
103 // In Android there are normally three kinds of builds: eng, userdebug and user.
104 // These builds target respectively a developer build, a debuggable version of
105 // the final product and the pristine final product the end user will run.
106 // Apart from the ro.build.type property name, they differ in the following
107 // properties that characterize the builds:
108 // * eng builds: ro.secure=0 and ro.debuggable=1
109 // * userdebug builds: ro.secure=1 and ro.debuggable=1
110 // * user builds: ro.secure=1 and ro.debuggable=0
111 //
112 // See IsOfficialBuild() and IsNormalMode() for the meaning of these options in
113 // Android.
114 
IsOfficialBuild() const115 bool HardwareAndroid::IsOfficialBuild() const {
116   // We run an official build iff ro.secure == 1, because we expect the build to
117   // behave like the end user product and check for updates. Note that while
118   // developers are able to build "official builds" by just running "make user",
119   // that will only result in a more restrictive environment. The important part
120   // is that we don't produce and push "non-official" builds to the end user.
121   //
122   // In case of a non-bool value, we take the most restrictive option and
123   // assume we are in an official-build.
124   return property_get_bool("ro.secure", 1) != 0;
125 }
126 
IsNormalBootMode() const127 bool HardwareAndroid::IsNormalBootMode() const {
128   // We are running in "dev-mode" iff ro.debuggable == 1. In dev-mode the
129   // update_engine will allow extra developers options, such as providing a
130   // different update URL. In case of error, we assume the build is in
131   // normal-mode.
132   return property_get_bool("ro.debuggable", 0) != 1;
133 }
134 
AreDevFeaturesEnabled() const135 bool HardwareAndroid::AreDevFeaturesEnabled() const {
136   return !IsNormalBootMode();
137 }
138 
IsOOBEEnabled() const139 bool HardwareAndroid::IsOOBEEnabled() const {
140   // No OOBE flow blocking updates for Android-based boards.
141   return false;
142 }
143 
IsOOBEComplete(base::Time * out_time_of_oobe) const144 bool HardwareAndroid::IsOOBEComplete(base::Time* out_time_of_oobe) const {
145   LOG(WARNING) << "OOBE is not enabled but IsOOBEComplete() called.";
146   if (out_time_of_oobe)
147     *out_time_of_oobe = base::Time();
148   return true;
149 }
150 
GetHardwareClass() const151 string HardwareAndroid::GetHardwareClass() const {
152   char manufacturer[PROPERTY_VALUE_MAX];
153   char sku[PROPERTY_VALUE_MAX];
154   char revision[PROPERTY_VALUE_MAX];
155   property_get(kPropBootHardwareSKU, sku, "");
156   property_get(kPropProductManufacturer, manufacturer, "");
157   property_get(kPropBootRevision, revision, "");
158 
159   return base::StringPrintf("%s:%s:%s", manufacturer, sku, revision);
160 }
161 
GetFirmwareVersion() const162 string HardwareAndroid::GetFirmwareVersion() const {
163   char bootloader[PROPERTY_VALUE_MAX];
164   property_get(kPropBootBootloader, bootloader, "");
165   return bootloader;
166 }
167 
GetECVersion() const168 string HardwareAndroid::GetECVersion() const {
169   char baseband[PROPERTY_VALUE_MAX];
170   property_get(kPropBootBaseband, baseband, "");
171   return baseband;
172 }
173 
GetPowerwashCount() const174 int HardwareAndroid::GetPowerwashCount() const {
175   LOG(WARNING) << "STUB: Assuming no factory reset was performed.";
176   return 0;
177 }
178 
SchedulePowerwash()179 bool HardwareAndroid::SchedulePowerwash() {
180   LOG(INFO) << "Scheduling a powerwash to BCB.";
181   return WriteBootloaderRecoveryMessage(kAndroidRecoveryPowerwashCommand);
182 }
183 
CancelPowerwash()184 bool HardwareAndroid::CancelPowerwash() {
185   return WriteBootloaderRecoveryMessage("");
186 }
187 
GetNonVolatileDirectory(base::FilePath * path) const188 bool HardwareAndroid::GetNonVolatileDirectory(base::FilePath* path) const {
189   base::FilePath local_path(constants::kNonVolatileDirectory);
190   if (!base::PathExists(local_path)) {
191     LOG(ERROR) << "Non-volatile directory not found: " << local_path.value();
192     return false;
193   }
194   *path = local_path;
195   return true;
196 }
197 
GetPowerwashSafeDirectory(base::FilePath * path) const198 bool HardwareAndroid::GetPowerwashSafeDirectory(base::FilePath* path) const {
199   // On Android, we don't have a directory persisted across powerwash.
200   return false;
201 }
202 
203 }  // namespace chromeos_update_engine
204