blob: 25042c9d6c331867d7715d21b2102aaaf03870f4 [file] [log] [blame]
Hridya Valsaraju31d2c262018-07-20 13:35:50 -07001/*
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
David Anderson12211d12018-07-24 15:21:20 -070019#include <inttypes.h>
20
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070021#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>
Hridya Valsaraju47658ca2018-09-28 11:41:22 -070027#include <healthhalutils/HealthHalUtils.h>
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070028
29#include "fastboot_device.h"
David Anderson12211d12018-07-24 15:21:20 -070030#include "flashing.h"
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070031#include "utility.h"
32
33using ::android::hardware::boot::V1_0::BoolResult;
34using ::android::hardware::boot::V1_0::Slot;
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -070035using ::android::hardware::fastboot::V1_0::FileSystemType;
36using ::android::hardware::fastboot::V1_0::Result;
37using ::android::hardware::fastboot::V1_0::Status;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070038
39constexpr int kMaxDownloadSizeDefault = 0x20000000;
40constexpr char kFastbootProtocolVersion[] = "0.4";
41
David Anderson1fb3fd72018-08-31 14:40:22 -070042bool GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
43 std::string* message) {
44 *message = kFastbootProtocolVersion;
45 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070046}
47
David Anderson1fb3fd72018-08-31 14:40:22 -070048bool GetBootloaderVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
49 std::string* message) {
50 *message = android::base::GetProperty("ro.bootloader", "");
51 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070052}
53
David Anderson1fb3fd72018-08-31 14:40:22 -070054bool GetBasebandVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
55 std::string* message) {
56 *message = android::base::GetProperty("ro.build.expect.baseband", "");
57 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070058}
59
David Anderson1fb3fd72018-08-31 14:40:22 -070060bool GetProduct(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
61 std::string* message) {
62 *message = android::base::GetProperty("ro.product.device", "");
63 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070064}
65
David Anderson1fb3fd72018-08-31 14:40:22 -070066bool GetSerial(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
67 std::string* message) {
68 *message = android::base::GetProperty("ro.serialno", "");
69 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070070}
71
David Anderson1fb3fd72018-08-31 14:40:22 -070072bool GetSecure(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
73 std::string* message) {
74 *message = android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no";
75 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070076}
77
Hridya Valsaraju4af80902018-09-26 13:08:16 -070078bool GetVariant(FastbootDevice* device, const std::vector<std::string>& /* args */,
79 std::string* message) {
80 auto fastboot_hal = device->fastboot_hal();
81 if (!fastboot_hal) {
82 *message = "Fastboot HAL not found";
83 return false;
84 }
85
86 Result ret;
87 auto ret_val = fastboot_hal->getVariant([&](std::string device_variant, Result result) {
88 *message = device_variant;
89 ret = result;
90 });
91 if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
92 *message = "Unable to get device variant";
93 return false;
94 }
95
96 return true;
97}
98
Hridya Valsarajua534a5a2018-10-03 15:53:22 -070099bool GetBatteryVoltageHelper(FastbootDevice* device, int32_t* battery_voltage) {
100 using android::hardware::health::V2_0::HealthInfo;
101 using android::hardware::health::V2_0::Result;
102
103 auto health_hal = device->health_hal();
104 if (!health_hal) {
105 return false;
106 }
107
108 Result ret;
109 auto ret_val = health_hal->getHealthInfo([&](Result result, HealthInfo info) {
110 *battery_voltage = info.legacy.batteryVoltage;
111 ret = result;
112 });
113 if (!ret_val.isOk() || (ret != Result::SUCCESS)) {
114 return false;
115 }
116
117 return true;
118}
119
120bool GetBatterySoCOk(FastbootDevice* device, const std::vector<std::string>& /* args */,
121 std::string* message) {
122 int32_t battery_voltage = 0;
123 if (!GetBatteryVoltageHelper(device, &battery_voltage)) {
124 *message = "Unable to read battery voltage";
125 return false;
126 }
127
128 auto fastboot_hal = device->fastboot_hal();
129 if (!fastboot_hal) {
130 *message = "Fastboot HAL not found";
131 return false;
132 }
133
134 Result ret;
135 auto ret_val = fastboot_hal->getBatteryVoltageFlashingThreshold(
136 [&](int32_t voltage_threshold, Result result) {
137 *message = battery_voltage >= voltage_threshold ? "yes" : "no";
138 ret = result;
139 });
140
141 if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
142 *message = "Unable to get battery voltage flashing threshold";
143 return false;
144 }
145
146 return true;
147}
148
Hridya Valsaraju7c9bbe92018-09-27 10:41:01 -0700149bool GetOffModeChargeState(FastbootDevice* device, const std::vector<std::string>& /* args */,
150 std::string* message) {
151 auto fastboot_hal = device->fastboot_hal();
152 if (!fastboot_hal) {
153 *message = "Fastboot HAL not found";
154 return false;
155 }
156
157 Result ret;
158 auto ret_val =
159 fastboot_hal->getOffModeChargeState([&](bool off_mode_charging_state, Result result) {
160 *message = off_mode_charging_state ? "1" : "0";
161 ret = result;
162 });
163 if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
164 *message = "Unable to get off mode charge state";
165 return false;
166 }
167
168 return true;
169}
170
Hridya Valsaraju47658ca2018-09-28 11:41:22 -0700171bool GetBatteryVoltage(FastbootDevice* device, const std::vector<std::string>& /* args */,
172 std::string* message) {
Hridya Valsarajua534a5a2018-10-03 15:53:22 -0700173 int32_t battery_voltage = 0;
174 if (GetBatteryVoltageHelper(device, &battery_voltage)) {
175 *message = std::to_string(battery_voltage);
176 return true;
Hridya Valsaraju47658ca2018-09-28 11:41:22 -0700177 }
Hridya Valsarajua534a5a2018-10-03 15:53:22 -0700178 *message = "Unable to get battery voltage";
179 return false;
Hridya Valsaraju47658ca2018-09-28 11:41:22 -0700180}
181
David Anderson1fb3fd72018-08-31 14:40:22 -0700182bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */,
183 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700184 std::string suffix = device->GetCurrentSlot();
David Anderson1fb3fd72018-08-31 14:40:22 -0700185 *message = suffix.size() == 2 ? suffix.substr(1) : suffix;
186 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700187}
188
David Anderson1fb3fd72018-08-31 14:40:22 -0700189bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */,
190 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700191 auto boot_control_hal = device->boot_control_hal();
192 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700193 *message = "0";
194 } else {
195 *message = std::to_string(boot_control_hal->getNumberSlots());
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700196 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700197 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700198}
199
David Anderson1fb3fd72018-08-31 14:40:22 -0700200bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
201 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700202 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700203 *message = "Missing argument";
204 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700205 }
206 Slot slot;
207 if (!GetSlotNumber(args[0], &slot)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700208 *message = "Invalid slot";
209 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700210 }
211 auto boot_control_hal = device->boot_control_hal();
212 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700213 *message = "Device has no slots";
214 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700215 }
David Anderson856b7ec2018-08-08 17:58:56 -0700216 if (boot_control_hal->isSlotMarkedSuccessful(slot) != BoolResult::TRUE) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700217 *message = "no";
218 } else {
219 *message = "yes";
David Anderson856b7ec2018-08-08 17:58:56 -0700220 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700221 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700222}
223
David Anderson1fb3fd72018-08-31 14:40:22 -0700224bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
225 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700226 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700227 *message = "Missing argument";
228 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700229 }
230 Slot slot;
231 if (!GetSlotNumber(args[0], &slot)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700232 *message = "Invalid slot";
233 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700234 }
235 auto boot_control_hal = device->boot_control_hal();
236 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700237 *message = "Device has no slots";
238 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700239 }
David Anderson856b7ec2018-08-08 17:58:56 -0700240 if (boot_control_hal->isSlotBootable(slot) != BoolResult::TRUE) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700241 *message = "yes";
242 } else {
243 *message = "no";
David Anderson856b7ec2018-08-08 17:58:56 -0700244 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700245 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700246}
247
David Anderson1fb3fd72018-08-31 14:40:22 -0700248bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
249 std::string* message) {
David Anderson28b81cd2018-09-04 16:51:29 -0700250 *message = android::base::StringPrintf("0x%X", kMaxDownloadSizeDefault);
David Anderson1fb3fd72018-08-31 14:40:22 -0700251 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700252}
253
David Anderson1fb3fd72018-08-31 14:40:22 -0700254bool GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
255 std::string* message) {
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700256 *message = GetDeviceLockStatus() ? "no" : "yes";
David Anderson1fb3fd72018-08-31 14:40:22 -0700257 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700258}
259
David Anderson1fb3fd72018-08-31 14:40:22 -0700260bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args,
261 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700262 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700263 *message = "Missing argument";
264 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700265 }
266 std::string slot_suffix = device->GetCurrentSlot();
267 if (slot_suffix.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700268 *message = "no";
269 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700270 }
David Anderson79ab0e32018-08-14 16:21:50 -0700271 std::string partition_name = args[0] + slot_suffix;
272 if (FindPhysicalPartition(partition_name) ||
273 LogicalPartitionExists(partition_name, slot_suffix)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700274 *message = "yes";
275 } else {
276 *message = "no";
David Anderson79ab0e32018-08-14 16:21:50 -0700277 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700278 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700279}
David Anderson12211d12018-07-24 15:21:20 -0700280
David Anderson1fb3fd72018-08-31 14:40:22 -0700281bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
282 std::string* message) {
David Anderson12211d12018-07-24 15:21:20 -0700283 if (args.size() < 1) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700284 *message = "Missing argument";
285 return false;
David Anderson12211d12018-07-24 15:21:20 -0700286 }
David Anderson88ef0b12018-08-09 10:40:00 -0700287 // Zero-length partitions cannot be created through device-mapper, so we
288 // special case them here.
289 bool is_zero_length;
290 if (LogicalPartitionExists(args[0], device->GetCurrentSlot(), &is_zero_length) &&
291 is_zero_length) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700292 *message = "0";
293 return true;
David Anderson88ef0b12018-08-09 10:40:00 -0700294 }
295 // Otherwise, open the partition as normal.
David Anderson12211d12018-07-24 15:21:20 -0700296 PartitionHandle handle;
297 if (!OpenPartition(device, args[0], &handle)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700298 *message = "Could not open partition";
299 return false;
David Anderson12211d12018-07-24 15:21:20 -0700300 }
301 uint64_t size = get_block_device_size(handle.fd());
David Anderson47589672018-09-04 16:22:41 -0700302 *message = android::base::StringPrintf("0x%" PRIX64, size);
David Anderson1fb3fd72018-08-31 14:40:22 -0700303 return true;
David Anderson12211d12018-07-24 15:21:20 -0700304}
David Anderson0d4277d2018-07-31 13:27:37 -0700305
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -0700306bool 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 }
Hridya Valsaraju4165e002018-10-09 10:40:35 -0700312
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -0700313 std::string partition_name = args[0];
Hridya Valsaraju4165e002018-10-09 10:40:35 -0700314 if (!FindPhysicalPartition(partition_name) &&
315 !LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
316 *message = "Invalid partition";
317 return false;
318 }
319
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -0700320 auto fastboot_hal = device->fastboot_hal();
321 if (!fastboot_hal) {
322 *message = "Fastboot HAL not found";
323 return false;
324 }
325
326 FileSystemType type;
327 Result ret;
328 auto ret_val =
329 fastboot_hal->getPartitionType(args[0], [&](FileSystemType fs_type, Result result) {
330 type = fs_type;
331 ret = result;
332 });
333 if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
334 *message = "Unable to retrieve partition type";
335 } else {
336 switch (type) {
337 case FileSystemType::RAW:
338 *message = "raw";
339 return true;
340 case FileSystemType::EXT4:
341 *message = "ext4";
342 return true;
343 case FileSystemType::F2FS:
344 *message = "f2fs";
345 return true;
346 default:
347 *message = "Unknown file system type";
348 }
349 }
350
351 return false;
352}
353
David Anderson1fb3fd72018-08-31 14:40:22 -0700354bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
355 std::string* message) {
David Anderson0d4277d2018-07-31 13:27:37 -0700356 if (args.size() < 1) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700357 *message = "Missing argument";
358 return false;
David Anderson0d4277d2018-07-31 13:27:37 -0700359 }
360 // Note: if a partition name is in both the GPT and the super partition, we
361 // return "true", to be consistent with prefering to flash logical partitions
362 // over physical ones.
363 std::string partition_name = args[0];
364 if (LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700365 *message = "yes";
366 return true;
David Anderson0d4277d2018-07-31 13:27:37 -0700367 }
368 if (FindPhysicalPartition(partition_name)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700369 *message = "no";
370 return true;
David Anderson0d4277d2018-07-31 13:27:37 -0700371 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700372 *message = "Partition not found";
373 return false;
David Anderson0d4277d2018-07-31 13:27:37 -0700374}
David Andersond9ba0612018-08-02 11:05:00 -0700375
David Anderson1fb3fd72018-08-31 14:40:22 -0700376bool GetIsUserspace(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
377 std::string* message) {
378 *message = "yes";
379 return true;
David Andersond9ba0612018-08-02 11:05:00 -0700380}
David Anderson0f626632018-08-31 16:44:25 -0700381
382std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
383 std::vector<std::vector<std::string>> args;
384 auto partitions = ListPartitions(device);
385 for (const auto& partition : partitions) {
386 args.emplace_back(std::initializer_list<std::string>{partition});
387 }
388 return args;
389}
390
391std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device) {
392 auto partitions = ListPartitions(device);
393
394 std::string slot_suffix = device->GetCurrentSlot();
395 if (!slot_suffix.empty()) {
396 auto names = std::move(partitions);
397 for (const auto& name : names) {
398 std::string slotless_name = name;
399 if (android::base::EndsWith(name, "_a") || android::base::EndsWith(name, "_b")) {
400 slotless_name = name.substr(0, name.rfind("_"));
401 }
402 if (std::find(partitions.begin(), partitions.end(), slotless_name) ==
403 partitions.end()) {
404 partitions.emplace_back(slotless_name);
405 }
406 }
407 }
408
409 std::vector<std::vector<std::string>> args;
410 for (const auto& partition : partitions) {
411 args.emplace_back(std::initializer_list<std::string>{partition});
412 }
413 return args;
414}
David Andersonc091c172018-09-04 18:11:03 -0700415
416bool GetHardwareRevision(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
417 std::string* message) {
418 *message = android::base::GetProperty("ro.revision", "");
419 return true;
420}