blob: 68efa08c35e13f9a5c4ac35ad3afdce8522804a8 [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;
34
35constexpr int kMaxDownloadSizeDefault = 0x20000000;
36constexpr char kFastbootProtocolVersion[] = "0.4";
37
David Anderson1fb3fd72018-08-31 14:40:22 -070038bool GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
39 std::string* message) {
40 *message = kFastbootProtocolVersion;
41 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070042}
43
David Anderson1fb3fd72018-08-31 14:40:22 -070044bool GetBootloaderVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
45 std::string* message) {
46 *message = android::base::GetProperty("ro.bootloader", "");
47 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070048}
49
David Anderson1fb3fd72018-08-31 14:40:22 -070050bool GetBasebandVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
51 std::string* message) {
52 *message = android::base::GetProperty("ro.build.expect.baseband", "");
53 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070054}
55
David Anderson1fb3fd72018-08-31 14:40:22 -070056bool GetProduct(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
57 std::string* message) {
58 *message = android::base::GetProperty("ro.product.device", "");
59 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070060}
61
David Anderson1fb3fd72018-08-31 14:40:22 -070062bool GetSerial(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
63 std::string* message) {
64 *message = android::base::GetProperty("ro.serialno", "");
65 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070066}
67
David Anderson1fb3fd72018-08-31 14:40:22 -070068bool GetSecure(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
69 std::string* message) {
70 *message = android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no";
71 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070072}
73
David Anderson1fb3fd72018-08-31 14:40:22 -070074bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */,
75 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070076 std::string suffix = device->GetCurrentSlot();
David Anderson1fb3fd72018-08-31 14:40:22 -070077 *message = suffix.size() == 2 ? suffix.substr(1) : suffix;
78 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070079}
80
David Anderson1fb3fd72018-08-31 14:40:22 -070081bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */,
82 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070083 auto boot_control_hal = device->boot_control_hal();
84 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -070085 *message = "0";
86 } else {
87 *message = std::to_string(boot_control_hal->getNumberSlots());
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070088 }
David Anderson1fb3fd72018-08-31 14:40:22 -070089 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070090}
91
David Anderson1fb3fd72018-08-31 14:40:22 -070092bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
93 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070094 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -070095 *message = "Missing argument";
96 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070097 }
98 Slot slot;
99 if (!GetSlotNumber(args[0], &slot)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700100 *message = "Invalid slot";
101 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700102 }
103 auto boot_control_hal = device->boot_control_hal();
104 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700105 *message = "Device has no slots";
106 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700107 }
David Anderson856b7ec2018-08-08 17:58:56 -0700108 if (boot_control_hal->isSlotMarkedSuccessful(slot) != BoolResult::TRUE) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700109 *message = "no";
110 } else {
111 *message = "yes";
David Anderson856b7ec2018-08-08 17:58:56 -0700112 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700113 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700114}
115
David Anderson1fb3fd72018-08-31 14:40:22 -0700116bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
117 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700118 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700119 *message = "Missing argument";
120 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700121 }
122 Slot slot;
123 if (!GetSlotNumber(args[0], &slot)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700124 *message = "Invalid slot";
125 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700126 }
127 auto boot_control_hal = device->boot_control_hal();
128 if (!boot_control_hal) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700129 *message = "Device has no slots";
130 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700131 }
David Anderson856b7ec2018-08-08 17:58:56 -0700132 if (boot_control_hal->isSlotBootable(slot) != BoolResult::TRUE) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700133 *message = "yes";
134 } else {
135 *message = "no";
David Anderson856b7ec2018-08-08 17:58:56 -0700136 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700137 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700138}
139
David Anderson1fb3fd72018-08-31 14:40:22 -0700140bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
141 std::string* message) {
David Anderson28b81cd2018-09-04 16:51:29 -0700142 *message = android::base::StringPrintf("0x%X", kMaxDownloadSizeDefault);
David Anderson1fb3fd72018-08-31 14:40:22 -0700143 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700144}
145
David Anderson1fb3fd72018-08-31 14:40:22 -0700146bool GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
147 std::string* message) {
148 *message = "yes";
149 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700150}
151
David Anderson1fb3fd72018-08-31 14:40:22 -0700152bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args,
153 std::string* message) {
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700154 if (args.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700155 *message = "Missing argument";
156 return false;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700157 }
158 std::string slot_suffix = device->GetCurrentSlot();
159 if (slot_suffix.empty()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700160 *message = "no";
161 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700162 }
David Anderson79ab0e32018-08-14 16:21:50 -0700163 std::string partition_name = args[0] + slot_suffix;
164 if (FindPhysicalPartition(partition_name) ||
165 LogicalPartitionExists(partition_name, slot_suffix)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700166 *message = "yes";
167 } else {
168 *message = "no";
David Anderson79ab0e32018-08-14 16:21:50 -0700169 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700170 return true;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700171}
David Anderson12211d12018-07-24 15:21:20 -0700172
David Anderson1fb3fd72018-08-31 14:40:22 -0700173bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
174 std::string* message) {
David Anderson12211d12018-07-24 15:21:20 -0700175 if (args.size() < 1) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700176 *message = "Missing argument";
177 return false;
David Anderson12211d12018-07-24 15:21:20 -0700178 }
David Anderson88ef0b12018-08-09 10:40:00 -0700179 // Zero-length partitions cannot be created through device-mapper, so we
180 // special case them here.
181 bool is_zero_length;
182 if (LogicalPartitionExists(args[0], device->GetCurrentSlot(), &is_zero_length) &&
183 is_zero_length) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700184 *message = "0";
185 return true;
David Anderson88ef0b12018-08-09 10:40:00 -0700186 }
187 // Otherwise, open the partition as normal.
David Anderson12211d12018-07-24 15:21:20 -0700188 PartitionHandle handle;
189 if (!OpenPartition(device, args[0], &handle)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700190 *message = "Could not open partition";
191 return false;
David Anderson12211d12018-07-24 15:21:20 -0700192 }
193 uint64_t size = get_block_device_size(handle.fd());
David Anderson47589672018-09-04 16:22:41 -0700194 *message = android::base::StringPrintf("0x%" PRIX64, size);
David Anderson1fb3fd72018-08-31 14:40:22 -0700195 return true;
David Anderson12211d12018-07-24 15:21:20 -0700196}
David Anderson0d4277d2018-07-31 13:27:37 -0700197
David Anderson1fb3fd72018-08-31 14:40:22 -0700198bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
199 std::string* message) {
David Anderson0d4277d2018-07-31 13:27:37 -0700200 if (args.size() < 1) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700201 *message = "Missing argument";
202 return false;
David Anderson0d4277d2018-07-31 13:27:37 -0700203 }
204 // Note: if a partition name is in both the GPT and the super partition, we
205 // return "true", to be consistent with prefering to flash logical partitions
206 // over physical ones.
207 std::string partition_name = args[0];
208 if (LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700209 *message = "yes";
210 return true;
David Anderson0d4277d2018-07-31 13:27:37 -0700211 }
212 if (FindPhysicalPartition(partition_name)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700213 *message = "no";
214 return true;
David Anderson0d4277d2018-07-31 13:27:37 -0700215 }
David Anderson1fb3fd72018-08-31 14:40:22 -0700216 *message = "Partition not found";
217 return false;
David Anderson0d4277d2018-07-31 13:27:37 -0700218}
David Andersond9ba0612018-08-02 11:05:00 -0700219
David Anderson1fb3fd72018-08-31 14:40:22 -0700220bool GetIsUserspace(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
221 std::string* message) {
222 *message = "yes";
223 return true;
David Andersond9ba0612018-08-02 11:05:00 -0700224}
David Anderson0f626632018-08-31 16:44:25 -0700225
226std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
227 std::vector<std::vector<std::string>> args;
228 auto partitions = ListPartitions(device);
229 for (const auto& partition : partitions) {
230 args.emplace_back(std::initializer_list<std::string>{partition});
231 }
232 return args;
233}
234
235std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device) {
236 auto partitions = ListPartitions(device);
237
238 std::string slot_suffix = device->GetCurrentSlot();
239 if (!slot_suffix.empty()) {
240 auto names = std::move(partitions);
241 for (const auto& name : names) {
242 std::string slotless_name = name;
243 if (android::base::EndsWith(name, "_a") || android::base::EndsWith(name, "_b")) {
244 slotless_name = name.substr(0, name.rfind("_"));
245 }
246 if (std::find(partitions.begin(), partitions.end(), slotless_name) ==
247 partitions.end()) {
248 partitions.emplace_back(slotless_name);
249 }
250 }
251 }
252
253 std::vector<std::vector<std::string>> args;
254 for (const auto& partition : partitions) {
255 args.emplace_back(std::initializer_list<std::string>{partition});
256 }
257 return args;
258}