blob: 75352489ee195d152f8ff86b2841e5562f9be0d0 [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>
27
28#include "fastboot_device.h"
David Anderson12211d12018-07-24 15:21:20 -070029#include "flashing.h"
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070030#include "utility.h"
31
32using ::android::hardware::boot::V1_0::BoolResult;
33using ::android::hardware::boot::V1_0::Slot;
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -070034using ::android::hardware::fastboot::V1_0::FileSystemType;
35using ::android::hardware::fastboot::V1_0::Result;
36using ::android::hardware::fastboot::V1_0::Status;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070037
38constexpr int kMaxDownloadSizeDefault = 0x20000000;
39constexpr char kFastbootProtocolVersion[] = "0.4";
40
David Anderson1fb3fd72018-08-31 14:40:22 -070041bool GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
42 std::string* message) {
43 *message = kFastbootProtocolVersion;
44 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070045}
46
David Anderson1fb3fd72018-08-31 14:40:22 -070047bool GetBootloaderVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
48 std::string* message) {
49 *message = android::base::GetProperty("ro.bootloader", "");
50 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070051}
52
David Anderson1fb3fd72018-08-31 14:40:22 -070053bool GetBasebandVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
54 std::string* message) {
55 *message = android::base::GetProperty("ro.build.expect.baseband", "");
56 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070057}
58
David Anderson1fb3fd72018-08-31 14:40:22 -070059bool GetProduct(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
60 std::string* message) {
61 *message = android::base::GetProperty("ro.product.device", "");
62 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070063}
64
David Anderson1fb3fd72018-08-31 14:40:22 -070065bool GetSerial(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
66 std::string* message) {
67 *message = android::base::GetProperty("ro.serialno", "");
68 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070069}
70
David Anderson1fb3fd72018-08-31 14:40:22 -070071bool GetSecure(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
72 std::string* message) {
73 *message = android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no";
74 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070075}
76
David Anderson1fb3fd72018-08-31 14:40:22 -070077bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */,
78 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070079 std::string suffix = device->GetCurrentSlot();
David Anderson1fb3fd72018-08-31 14:40:22 -070080 *message = suffix.size() == 2 ? suffix.substr(1) : suffix;
81 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070082}
83
David Anderson1fb3fd72018-08-31 14:40:22 -070084bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */,
85 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070086 auto boot_control_hal = device->boot_control_hal();
87 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -070088 *message = "0";
89 } else {
90 *message = std::to_string(boot_control_hal->getNumberSlots());
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070091 }
David Anderson1fb3fd72018-08-31 14:40:22 -070092 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070093}
94
David Anderson1fb3fd72018-08-31 14:40:22 -070095bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
96 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070097 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -070098 *message = "Missing argument";
99 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700100 }
101 Slot slot;
102 if (!GetSlotNumber(args[0], &slot)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700103 *message = "Invalid slot";
104 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700105 }
106 auto boot_control_hal = device->boot_control_hal();
107 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700108 *message = "Device has no slots";
109 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700110 }
David Anderson856b7ec2018-08-08 17:58:56 -0700111 if (boot_control_hal->isSlotMarkedSuccessful(slot) != BoolResult::TRUE) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700112 *message = "no";
113 } else {
114 *message = "yes";
David Anderson856b7ec2018-08-08 17:58:56 -0700115 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700116 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700117}
118
David Anderson1fb3fd72018-08-31 14:40:22 -0700119bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
120 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700121 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700122 *message = "Missing argument";
123 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700124 }
125 Slot slot;
126 if (!GetSlotNumber(args[0], &slot)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700127 *message = "Invalid slot";
128 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700129 }
130 auto boot_control_hal = device->boot_control_hal();
131 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700132 *message = "Device has no slots";
133 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700134 }
David Anderson856b7ec2018-08-08 17:58:56 -0700135 if (boot_control_hal->isSlotBootable(slot) != BoolResult::TRUE) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700136 *message = "yes";
137 } else {
138 *message = "no";
David Anderson856b7ec2018-08-08 17:58:56 -0700139 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700140 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700141}
142
David Anderson1fb3fd72018-08-31 14:40:22 -0700143bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
144 std::string* message) {
David Anderson28b81cd2018-09-04 16:51:29 -0700145 *message = android::base::StringPrintf("0x%X", kMaxDownloadSizeDefault);
David Anderson1fb3fd72018-08-31 14:40:22 -0700146 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700147}
148
David Anderson1fb3fd72018-08-31 14:40:22 -0700149bool GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
150 std::string* message) {
151 *message = "yes";
152 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700153}
154
David Anderson1fb3fd72018-08-31 14:40:22 -0700155bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args,
156 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700157 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700158 *message = "Missing argument";
159 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700160 }
161 std::string slot_suffix = device->GetCurrentSlot();
162 if (slot_suffix.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700163 *message = "no";
164 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700165 }
David Anderson79ab0e32018-08-14 16:21:50 -0700166 std::string partition_name = args[0] + slot_suffix;
167 if (FindPhysicalPartition(partition_name) ||
168 LogicalPartitionExists(partition_name, slot_suffix)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700169 *message = "yes";
170 } else {
171 *message = "no";
David Anderson79ab0e32018-08-14 16:21:50 -0700172 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700173 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700174}
David Anderson12211d12018-07-24 15:21:20 -0700175
David Anderson1fb3fd72018-08-31 14:40:22 -0700176bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
177 std::string* message) {
David Anderson12211d12018-07-24 15:21:20 -0700178 if (args.size() < 1) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700179 *message = "Missing argument";
180 return false;
David Anderson12211d12018-07-24 15:21:20 -0700181 }
David Anderson88ef0b12018-08-09 10:40:00 -0700182 // Zero-length partitions cannot be created through device-mapper, so we
183 // special case them here.
184 bool is_zero_length;
185 if (LogicalPartitionExists(args[0], device->GetCurrentSlot(), &is_zero_length) &&
186 is_zero_length) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700187 *message = "0";
188 return true;
David Anderson88ef0b12018-08-09 10:40:00 -0700189 }
190 // Otherwise, open the partition as normal.
David Anderson12211d12018-07-24 15:21:20 -0700191 PartitionHandle handle;
192 if (!OpenPartition(device, args[0], &handle)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700193 *message = "Could not open partition";
194 return false;
David Anderson12211d12018-07-24 15:21:20 -0700195 }
196 uint64_t size = get_block_device_size(handle.fd());
David Anderson47589672018-09-04 16:22:41 -0700197 *message = android::base::StringPrintf("0x%" PRIX64, size);
David Anderson1fb3fd72018-08-31 14:40:22 -0700198 return true;
David Anderson12211d12018-07-24 15:21:20 -0700199}
David Anderson0d4277d2018-07-31 13:27:37 -0700200
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -0700201bool GetPartitionType(FastbootDevice* device, const std::vector<std::string>& args,
202 std::string* message) {
203 if (args.size() < 1) {
204 *message = "Missing argument";
205 return false;
206 }
207 std::string partition_name = args[0];
208 auto fastboot_hal = device->fastboot_hal();
209 if (!fastboot_hal) {
210 *message = "Fastboot HAL not found";
211 return false;
212 }
213
214 FileSystemType type;
215 Result ret;
216 auto ret_val =
217 fastboot_hal->getPartitionType(args[0], [&](FileSystemType fs_type, Result result) {
218 type = fs_type;
219 ret = result;
220 });
221 if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
222 *message = "Unable to retrieve partition type";
223 } else {
224 switch (type) {
225 case FileSystemType::RAW:
226 *message = "raw";
227 return true;
228 case FileSystemType::EXT4:
229 *message = "ext4";
230 return true;
231 case FileSystemType::F2FS:
232 *message = "f2fs";
233 return true;
234 default:
235 *message = "Unknown file system type";
236 }
237 }
238
239 return false;
240}
241
David Anderson1fb3fd72018-08-31 14:40:22 -0700242bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
243 std::string* message) {
David Anderson0d4277d2018-07-31 13:27:37 -0700244 if (args.size() < 1) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700245 *message = "Missing argument";
246 return false;
David Anderson0d4277d2018-07-31 13:27:37 -0700247 }
248 // Note: if a partition name is in both the GPT and the super partition, we
249 // return "true", to be consistent with prefering to flash logical partitions
250 // over physical ones.
251 std::string partition_name = args[0];
252 if (LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700253 *message = "yes";
254 return true;
David Anderson0d4277d2018-07-31 13:27:37 -0700255 }
256 if (FindPhysicalPartition(partition_name)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700257 *message = "no";
258 return true;
David Anderson0d4277d2018-07-31 13:27:37 -0700259 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700260 *message = "Partition not found";
261 return false;
David Anderson0d4277d2018-07-31 13:27:37 -0700262}
David Andersond9ba0612018-08-02 11:05:00 -0700263
David Anderson1fb3fd72018-08-31 14:40:22 -0700264bool GetIsUserspace(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
265 std::string* message) {
266 *message = "yes";
267 return true;
David Andersond9ba0612018-08-02 11:05:00 -0700268}
David Anderson0f626632018-08-31 16:44:25 -0700269
270std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
271 std::vector<std::vector<std::string>> args;
272 auto partitions = ListPartitions(device);
273 for (const auto& partition : partitions) {
274 args.emplace_back(std::initializer_list<std::string>{partition});
275 }
276 return args;
277}
278
279std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device) {
280 auto partitions = ListPartitions(device);
281
282 std::string slot_suffix = device->GetCurrentSlot();
283 if (!slot_suffix.empty()) {
284 auto names = std::move(partitions);
285 for (const auto& name : names) {
286 std::string slotless_name = name;
287 if (android::base::EndsWith(name, "_a") || android::base::EndsWith(name, "_b")) {
288 slotless_name = name.substr(0, name.rfind("_"));
289 }
290 if (std::find(partitions.begin(), partitions.end(), slotless_name) ==
291 partitions.end()) {
292 partitions.emplace_back(slotless_name);
293 }
294 }
295 }
296
297 std::vector<std::vector<std::string>> args;
298 for (const auto& partition : partitions) {
299 args.emplace_back(std::initializer_list<std::string>{partition});
300 }
301 return args;
302}
David Andersonc091c172018-09-04 18:11:03 -0700303
304bool GetHardwareRevision(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
305 std::string* message) {
306 *message = android::base::GetProperty("ro.revision", "");
307 return true;
308}