1 /*
2 * Copyright (C) 2018 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 "variables.h"
18
19 #include <inttypes.h>
20
21 #include <android-base/file.h>
22 #include <android-base/logging.h>
23 #include <android-base/properties.h>
24 #include <android-base/stringprintf.h>
25 #include <android-base/strings.h>
26 #include <ext4_utils/ext4_utils.h>
27 #include <fs_mgr.h>
28 #include <healthhalutils/HealthHalUtils.h>
29 #include <liblp/liblp.h>
30
31 #include "fastboot_device.h"
32 #include "flashing.h"
33 #include "utility.h"
34
35 using ::android::hardware::boot::V1_0::BoolResult;
36 using ::android::hardware::boot::V1_0::Slot;
37 using ::android::hardware::fastboot::V1_0::FileSystemType;
38 using ::android::hardware::fastboot::V1_0::Result;
39 using ::android::hardware::fastboot::V1_0::Status;
40 using namespace android::fs_mgr;
41
42 constexpr char kFastbootProtocolVersion[] = "0.4";
43
GetVersion(FastbootDevice *,const std::vector<std::string> &,std::string * message)44 bool GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
45 std::string* message) {
46 *message = kFastbootProtocolVersion;
47 return true;
48 }
49
GetBootloaderVersion(FastbootDevice *,const std::vector<std::string> &,std::string * message)50 bool GetBootloaderVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
51 std::string* message) {
52 *message = android::base::GetProperty("ro.bootloader", "");
53 return true;
54 }
55
GetBasebandVersion(FastbootDevice *,const std::vector<std::string> &,std::string * message)56 bool GetBasebandVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
57 std::string* message) {
58 *message = android::base::GetProperty("ro.build.expect.baseband", "");
59 return true;
60 }
61
GetProduct(FastbootDevice *,const std::vector<std::string> &,std::string * message)62 bool GetProduct(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
63 std::string* message) {
64 *message = android::base::GetProperty("ro.product.device", "");
65 return true;
66 }
67
GetSerial(FastbootDevice *,const std::vector<std::string> &,std::string * message)68 bool GetSerial(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
69 std::string* message) {
70 *message = android::base::GetProperty("ro.serialno", "");
71 return true;
72 }
73
GetSecure(FastbootDevice *,const std::vector<std::string> &,std::string * message)74 bool GetSecure(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
75 std::string* message) {
76 *message = android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no";
77 return true;
78 }
79
GetVariant(FastbootDevice * device,const std::vector<std::string> &,std::string * message)80 bool GetVariant(FastbootDevice* device, const std::vector<std::string>& /* args */,
81 std::string* message) {
82 auto fastboot_hal = device->fastboot_hal();
83 if (!fastboot_hal) {
84 *message = "Fastboot HAL not found";
85 return false;
86 }
87
88 Result ret;
89 auto ret_val = fastboot_hal->getVariant([&](std::string device_variant, Result result) {
90 *message = device_variant;
91 ret = result;
92 });
93 if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
94 *message = "Unable to get device variant";
95 return false;
96 }
97
98 return true;
99 }
100
GetBatteryVoltageHelper(FastbootDevice * device,int32_t * battery_voltage)101 bool GetBatteryVoltageHelper(FastbootDevice* device, int32_t* battery_voltage) {
102 using android::hardware::health::V2_0::HealthInfo;
103 using android::hardware::health::V2_0::Result;
104
105 auto health_hal = device->health_hal();
106 if (!health_hal) {
107 return false;
108 }
109
110 Result ret;
111 auto ret_val = health_hal->getHealthInfo([&](Result result, HealthInfo info) {
112 *battery_voltage = info.legacy.batteryVoltage;
113 ret = result;
114 });
115 if (!ret_val.isOk() || (ret != Result::SUCCESS)) {
116 return false;
117 }
118
119 return true;
120 }
121
GetBatterySoCOk(FastbootDevice * device,const std::vector<std::string> &,std::string * message)122 bool GetBatterySoCOk(FastbootDevice* device, const std::vector<std::string>& /* args */,
123 std::string* message) {
124 int32_t battery_voltage = 0;
125 if (!GetBatteryVoltageHelper(device, &battery_voltage)) {
126 *message = "Unable to read battery voltage";
127 return false;
128 }
129
130 auto fastboot_hal = device->fastboot_hal();
131 if (!fastboot_hal) {
132 *message = "Fastboot HAL not found";
133 return false;
134 }
135
136 Result ret;
137 auto ret_val = fastboot_hal->getBatteryVoltageFlashingThreshold(
138 [&](int32_t voltage_threshold, Result result) {
139 *message = battery_voltage >= voltage_threshold ? "yes" : "no";
140 ret = result;
141 });
142
143 if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
144 *message = "Unable to get battery voltage flashing threshold";
145 return false;
146 }
147
148 return true;
149 }
150
GetOffModeChargeState(FastbootDevice * device,const std::vector<std::string> &,std::string * message)151 bool GetOffModeChargeState(FastbootDevice* device, const std::vector<std::string>& /* args */,
152 std::string* message) {
153 auto fastboot_hal = device->fastboot_hal();
154 if (!fastboot_hal) {
155 *message = "Fastboot HAL not found";
156 return false;
157 }
158
159 Result ret;
160 auto ret_val =
161 fastboot_hal->getOffModeChargeState([&](bool off_mode_charging_state, Result result) {
162 *message = off_mode_charging_state ? "1" : "0";
163 ret = result;
164 });
165 if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
166 *message = "Unable to get off mode charge state";
167 return false;
168 }
169
170 return true;
171 }
172
GetBatteryVoltage(FastbootDevice * device,const std::vector<std::string> &,std::string * message)173 bool GetBatteryVoltage(FastbootDevice* device, const std::vector<std::string>& /* args */,
174 std::string* message) {
175 int32_t battery_voltage = 0;
176 if (GetBatteryVoltageHelper(device, &battery_voltage)) {
177 *message = std::to_string(battery_voltage);
178 return true;
179 }
180 *message = "Unable to get battery voltage";
181 return false;
182 }
183
GetCurrentSlot(FastbootDevice * device,const std::vector<std::string> &,std::string * message)184 bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */,
185 std::string* message) {
186 std::string suffix = device->GetCurrentSlot();
187 *message = suffix.size() == 2 ? suffix.substr(1) : suffix;
188 return true;
189 }
190
GetSlotCount(FastbootDevice * device,const std::vector<std::string> &,std::string * message)191 bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */,
192 std::string* message) {
193 auto boot_control_hal = device->boot_control_hal();
194 if (!boot_control_hal) {
195 *message = "0";
196 } else {
197 *message = std::to_string(boot_control_hal->getNumberSlots());
198 }
199 return true;
200 }
201
GetSlotSuccessful(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)202 bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
203 std::string* message) {
204 if (args.empty()) {
205 *message = "Missing argument";
206 return false;
207 }
208 Slot slot;
209 if (!GetSlotNumber(args[0], &slot)) {
210 *message = "Invalid slot";
211 return false;
212 }
213 auto boot_control_hal = device->boot_control_hal();
214 if (!boot_control_hal) {
215 *message = "Device has no slots";
216 return false;
217 }
218 if (boot_control_hal->isSlotMarkedSuccessful(slot) != BoolResult::TRUE) {
219 *message = "no";
220 } else {
221 *message = "yes";
222 }
223 return true;
224 }
225
GetSlotUnbootable(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)226 bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
227 std::string* message) {
228 if (args.empty()) {
229 *message = "Missing argument";
230 return false;
231 }
232 Slot slot;
233 if (!GetSlotNumber(args[0], &slot)) {
234 *message = "Invalid slot";
235 return false;
236 }
237 auto boot_control_hal = device->boot_control_hal();
238 if (!boot_control_hal) {
239 *message = "Device has no slots";
240 return false;
241 }
242 if (boot_control_hal->isSlotBootable(slot) != BoolResult::TRUE) {
243 *message = "yes";
244 } else {
245 *message = "no";
246 }
247 return true;
248 }
249
GetMaxDownloadSize(FastbootDevice *,const std::vector<std::string> &,std::string * message)250 bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
251 std::string* message) {
252 *message = android::base::StringPrintf("0x%X", kMaxDownloadSizeDefault);
253 return true;
254 }
255
GetUnlocked(FastbootDevice *,const std::vector<std::string> &,std::string * message)256 bool GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
257 std::string* message) {
258 *message = GetDeviceLockStatus() ? "no" : "yes";
259 return true;
260 }
261
GetHasSlot(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)262 bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args,
263 std::string* message) {
264 if (args.empty()) {
265 *message = "Missing argument";
266 return false;
267 }
268 std::string slot_suffix = device->GetCurrentSlot();
269 if (slot_suffix.empty()) {
270 *message = "no";
271 return true;
272 }
273 std::string partition_name = args[0] + slot_suffix;
274 if (FindPhysicalPartition(partition_name) || LogicalPartitionExists(device, partition_name)) {
275 *message = "yes";
276 } else {
277 *message = "no";
278 }
279 return true;
280 }
281
GetPartitionSize(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)282 bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
283 std::string* message) {
284 if (args.size() < 1) {
285 *message = "Missing argument";
286 return false;
287 }
288 // Zero-length partitions cannot be created through device-mapper, so we
289 // special case them here.
290 bool is_zero_length;
291 if (LogicalPartitionExists(device, args[0], &is_zero_length) && is_zero_length) {
292 *message = "0x0";
293 return true;
294 }
295 // Otherwise, open the partition as normal.
296 PartitionHandle handle;
297 if (!OpenPartition(device, args[0], &handle)) {
298 *message = "Could not open partition";
299 return false;
300 }
301 uint64_t size = get_block_device_size(handle.fd());
302 *message = android::base::StringPrintf("0x%" PRIX64, size);
303 return true;
304 }
305
GetPartitionType(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)306 bool GetPartitionType(FastbootDevice* device, const std::vector<std::string>& args,
307 std::string* message) {
308 if (args.size() < 1) {
309 *message = "Missing argument";
310 return false;
311 }
312
313 std::string partition_name = args[0];
314 if (!FindPhysicalPartition(partition_name) && !LogicalPartitionExists(device, partition_name)) {
315 *message = "Invalid partition";
316 return false;
317 }
318
319 auto fastboot_hal = device->fastboot_hal();
320 if (!fastboot_hal) {
321 *message = "Fastboot HAL not found";
322 return false;
323 }
324
325 FileSystemType type;
326 Result ret;
327 auto ret_val =
328 fastboot_hal->getPartitionType(args[0], [&](FileSystemType fs_type, Result result) {
329 type = fs_type;
330 ret = result;
331 });
332 if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
333 *message = "Unable to retrieve partition type";
334 } else {
335 switch (type) {
336 case FileSystemType::RAW:
337 *message = "raw";
338 return true;
339 case FileSystemType::EXT4:
340 *message = "ext4";
341 return true;
342 case FileSystemType::F2FS:
343 *message = "f2fs";
344 return true;
345 default:
346 *message = "Unknown file system type";
347 }
348 }
349
350 return false;
351 }
352
GetPartitionIsLogical(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)353 bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
354 std::string* message) {
355 if (args.size() < 1) {
356 *message = "Missing argument";
357 return false;
358 }
359 // Note: if a partition name is in both the GPT and the super partition, we
360 // return "true", to be consistent with prefering to flash logical partitions
361 // over physical ones.
362 std::string partition_name = args[0];
363 if (LogicalPartitionExists(device, partition_name)) {
364 *message = "yes";
365 return true;
366 }
367 if (FindPhysicalPartition(partition_name)) {
368 *message = "no";
369 return true;
370 }
371 *message = "Partition not found";
372 return false;
373 }
374
GetIsUserspace(FastbootDevice *,const std::vector<std::string> &,std::string * message)375 bool GetIsUserspace(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
376 std::string* message) {
377 *message = "yes";
378 return true;
379 }
380
GetAllPartitionArgsWithSlot(FastbootDevice * device)381 std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
382 std::vector<std::vector<std::string>> args;
383 auto partitions = ListPartitions(device);
384 for (const auto& partition : partitions) {
385 args.emplace_back(std::initializer_list<std::string>{partition});
386 }
387 return args;
388 }
389
GetAllPartitionArgsNoSlot(FastbootDevice * device)390 std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device) {
391 auto partitions = ListPartitions(device);
392
393 std::string slot_suffix = device->GetCurrentSlot();
394 if (!slot_suffix.empty()) {
395 auto names = std::move(partitions);
396 for (const auto& name : names) {
397 std::string slotless_name = name;
398 if (android::base::EndsWith(name, "_a") || android::base::EndsWith(name, "_b")) {
399 slotless_name = name.substr(0, name.rfind("_"));
400 }
401 if (std::find(partitions.begin(), partitions.end(), slotless_name) ==
402 partitions.end()) {
403 partitions.emplace_back(slotless_name);
404 }
405 }
406 }
407
408 std::vector<std::vector<std::string>> args;
409 for (const auto& partition : partitions) {
410 args.emplace_back(std::initializer_list<std::string>{partition});
411 }
412 return args;
413 }
414
GetHardwareRevision(FastbootDevice *,const std::vector<std::string> &,std::string * message)415 bool GetHardwareRevision(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
416 std::string* message) {
417 *message = android::base::GetProperty("ro.revision", "");
418 return true;
419 }
420
GetSuperPartitionName(FastbootDevice * device,const std::vector<std::string> &,std::string * message)421 bool GetSuperPartitionName(FastbootDevice* device, const std::vector<std::string>& /* args */,
422 std::string* message) {
423 uint32_t slot_number = SlotNumberForSlotSuffix(device->GetCurrentSlot());
424 *message = fs_mgr_get_super_partition_name(slot_number);
425 return true;
426 }
427