blob: 409ef70c21fca6383e7030ffcdfc7af4d98dad82 [file] [log] [blame]
Hridya Valsarajudea91b42018-07-17 11:14:01 -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 "commands.h"
18
19#include <sys/socket.h>
20#include <sys/un.h>
21
22#include <android-base/logging.h>
23#include <android-base/parseint.h>
24#include <android-base/properties.h>
25#include <android-base/stringprintf.h>
26#include <android-base/strings.h>
27#include <android-base/unique_fd.h>
28#include <cutils/android_reboot.h>
David Anderson12211d12018-07-24 15:21:20 -070029#include <ext4_utils/wipe.h>
David Anderson5cbd2e42018-09-27 10:53:04 -070030#include <fs_mgr.h>
David Anderson3d782d52019-01-29 13:09:49 -080031#include <fs_mgr/roots.h>
David Anderson1d504e32019-01-15 14:38:20 -080032#include <libgsi/libgsi.h>
David Anderson0d4277d2018-07-31 13:27:37 -070033#include <liblp/builder.h>
34#include <liblp/liblp.h>
35#include <uuid/uuid.h>
Hridya Valsarajudea91b42018-07-17 11:14:01 -070036
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070037#include "constants.h"
Hridya Valsarajudea91b42018-07-17 11:14:01 -070038#include "fastboot_device.h"
David Anderson12211d12018-07-24 15:21:20 -070039#include "flashing.h"
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070040#include "utility.h"
41
David Anderson27475322019-06-11 14:00:08 -070042using android::fs_mgr::MetadataBuilder;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070043using ::android::hardware::hidl_string;
44using ::android::hardware::boot::V1_0::BoolResult;
45using ::android::hardware::boot::V1_0::CommandResult;
46using ::android::hardware::boot::V1_0::Slot;
Hridya Valsarajua15fe312018-09-14 13:58:21 -070047using ::android::hardware::fastboot::V1_0::Result;
48using ::android::hardware::fastboot::V1_0::Status;
49
David Anderson0f626632018-08-31 16:44:25 -070050struct VariableHandlers {
51 // Callback to retrieve the value of a single variable.
52 std::function<bool(FastbootDevice*, const std::vector<std::string>&, std::string*)> get;
53 // Callback to retrieve all possible argument combinations, for getvar all.
54 std::function<std::vector<std::vector<std::string>>(FastbootDevice*)> get_all_args;
55};
56
57static void GetAllVars(FastbootDevice* device, const std::string& name,
58 const VariableHandlers& handlers) {
59 if (!handlers.get_all_args) {
60 std::string message;
61 if (!handlers.get(device, std::vector<std::string>(), &message)) {
62 return;
63 }
64 device->WriteInfo(android::base::StringPrintf("%s:%s", name.c_str(), message.c_str()));
65 return;
66 }
67
68 auto all_args = handlers.get_all_args(device);
69 for (const auto& args : all_args) {
70 std::string message;
71 if (!handlers.get(device, args, &message)) {
72 continue;
73 }
74 std::string arg_string = android::base::Join(args, ":");
75 device->WriteInfo(android::base::StringPrintf("%s:%s:%s", name.c_str(), arg_string.c_str(),
76 message.c_str()));
77 }
78}
79
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070080bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args) {
David Anderson0f626632018-08-31 16:44:25 -070081 const std::unordered_map<std::string, VariableHandlers> kVariableMap = {
82 {FB_VAR_VERSION, {GetVersion, nullptr}},
83 {FB_VAR_VERSION_BOOTLOADER, {GetBootloaderVersion, nullptr}},
84 {FB_VAR_VERSION_BASEBAND, {GetBasebandVersion, nullptr}},
85 {FB_VAR_PRODUCT, {GetProduct, nullptr}},
86 {FB_VAR_SERIALNO, {GetSerial, nullptr}},
Hridya Valsaraju4af80902018-09-26 13:08:16 -070087 {FB_VAR_VARIANT, {GetVariant, nullptr}},
David Anderson0f626632018-08-31 16:44:25 -070088 {FB_VAR_SECURE, {GetSecure, nullptr}},
89 {FB_VAR_UNLOCKED, {GetUnlocked, nullptr}},
90 {FB_VAR_MAX_DOWNLOAD_SIZE, {GetMaxDownloadSize, nullptr}},
91 {FB_VAR_CURRENT_SLOT, {::GetCurrentSlot, nullptr}},
92 {FB_VAR_SLOT_COUNT, {GetSlotCount, nullptr}},
93 {FB_VAR_HAS_SLOT, {GetHasSlot, GetAllPartitionArgsNoSlot}},
94 {FB_VAR_SLOT_SUCCESSFUL, {GetSlotSuccessful, nullptr}},
95 {FB_VAR_SLOT_UNBOOTABLE, {GetSlotUnbootable, nullptr}},
David Anderson27475322019-06-11 14:00:08 -070096 {FB_VAR_PARTITION_SIZE, {GetPartitionSize, GetAllPartitionArgsWithSlot}},
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -070097 {FB_VAR_PARTITION_TYPE, {GetPartitionType, GetAllPartitionArgsWithSlot}},
David Anderson0f626632018-08-31 16:44:25 -070098 {FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
David Andersonc091c172018-09-04 18:11:03 -070099 {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
Hridya Valsaraju7c9bbe92018-09-27 10:41:01 -0700100 {FB_VAR_OFF_MODE_CHARGE_STATE, {GetOffModeChargeState, nullptr}},
Hridya Valsaraju47658ca2018-09-28 11:41:22 -0700101 {FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
Hridya Valsarajua534a5a2018-10-03 15:53:22 -0700102 {FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
David Anderson90fe0a42018-11-05 18:01:32 -0800103 {FB_VAR_HW_REVISION, {GetHardwareRevision, nullptr}},
104 {FB_VAR_SUPER_PARTITION_NAME, {GetSuperPartitionName, nullptr}}};
David Anderson0f626632018-08-31 16:44:25 -0700105
106 if (args.size() < 2) {
107 return device->WriteFail("Missing argument");
108 }
109
110 // Special case: return all variables that we can.
111 if (args[1] == "all") {
112 for (const auto& [name, handlers] : kVariableMap) {
113 GetAllVars(device, name, handlers);
114 }
115 return device->WriteOkay("");
116 }
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700117
118 // args[0] is command name, args[1] is variable.
119 auto found_variable = kVariableMap.find(args[1]);
120 if (found_variable == kVariableMap.end()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700121 return device->WriteFail("Unknown variable");
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700122 }
123
David Anderson1fb3fd72018-08-31 14:40:22 -0700124 std::string message;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700125 std::vector<std::string> getvar_args(args.begin() + 2, args.end());
David Anderson0f626632018-08-31 16:44:25 -0700126 if (!found_variable->second.get(device, getvar_args, &message)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700127 return device->WriteFail(message);
128 }
129 return device->WriteOkay(message);
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700130}
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700131
David Anderson12211d12018-07-24 15:21:20 -0700132bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) {
133 if (args.size() < 2) {
134 return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
135 }
Hridya Valsarajud1e62312018-10-08 09:13:17 -0700136
137 if (GetDeviceLockStatus()) {
138 return device->WriteStatus(FastbootResult::FAIL, "Erase is not allowed on locked devices");
139 }
140
David Anderson12211d12018-07-24 15:21:20 -0700141 PartitionHandle handle;
142 if (!OpenPartition(device, args[1], &handle)) {
143 return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist");
144 }
145 if (wipe_block_device(handle.fd(), get_block_device_size(handle.fd())) == 0) {
146 return device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
147 }
148 return device->WriteStatus(FastbootResult::FAIL, "Erasing failed");
149}
150
Hridya Valsarajua15fe312018-09-14 13:58:21 -0700151bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args) {
152 auto fastboot_hal = device->fastboot_hal();
153 if (!fastboot_hal) {
154 return device->WriteStatus(FastbootResult::FAIL, "Unable to open fastboot HAL");
155 }
156
157 Result ret;
158 auto ret_val = fastboot_hal->doOemCommand(args[0], [&](Result result) { ret = result; });
159 if (!ret_val.isOk()) {
160 return device->WriteStatus(FastbootResult::FAIL, "Unable to do OEM command");
161 }
162 if (ret.status != Status::SUCCESS) {
163 return device->WriteStatus(FastbootResult::FAIL, ret.message);
164 }
165
166 return device->WriteStatus(FastbootResult::OKAY, ret.message);
167}
168
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700169bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
170 if (args.size() < 2) {
171 return device->WriteStatus(FastbootResult::FAIL, "size argument unspecified");
172 }
Hridya Valsarajud1e62312018-10-08 09:13:17 -0700173
174 if (GetDeviceLockStatus()) {
175 return device->WriteStatus(FastbootResult::FAIL,
176 "Download is not allowed on locked devices");
177 }
178
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700179 // arg[0] is the command name, arg[1] contains size of data to be downloaded
180 unsigned int size;
Hridya Valsarajuaae84e82018-10-08 13:10:25 -0700181 if (!android::base::ParseUint("0x" + args[1], &size, kMaxDownloadSizeDefault)) {
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700182 return device->WriteStatus(FastbootResult::FAIL, "Invalid size");
183 }
David Anderson12211d12018-07-24 15:21:20 -0700184 device->download_data().resize(size);
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700185 if (!device->WriteStatus(FastbootResult::DATA, android::base::StringPrintf("%08x", size))) {
186 return false;
187 }
188
David Anderson12211d12018-07-24 15:21:20 -0700189 if (device->HandleData(true, &device->download_data())) {
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700190 return device->WriteStatus(FastbootResult::OKAY, "");
191 }
192
193 PLOG(ERROR) << "Couldn't download data";
194 return device->WriteStatus(FastbootResult::FAIL, "Couldn't download data");
195}
196
David Anderson12211d12018-07-24 15:21:20 -0700197bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) {
198 if (args.size() < 2) {
199 return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
200 }
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700201
202 if (GetDeviceLockStatus()) {
203 return device->WriteStatus(FastbootResult::FAIL,
204 "Flashing is not allowed on locked devices");
205 }
206
David Anderson12211d12018-07-24 15:21:20 -0700207 int ret = Flash(device, args[1]);
208 if (ret < 0) {
209 return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
210 }
211 return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
212}
213
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700214bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& args) {
215 if (args.size() < 2) {
216 return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
217 }
218
Hridya Valsarajud1e62312018-10-08 09:13:17 -0700219 if (GetDeviceLockStatus()) {
220 return device->WriteStatus(FastbootResult::FAIL,
221 "set_active command is not allowed on locked devices");
222 }
223
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700224 // Slot suffix needs to be between 'a' and 'z'.
225 Slot slot;
226 if (!GetSlotNumber(args[1], &slot)) {
227 return device->WriteStatus(FastbootResult::FAIL, "Bad slot suffix");
228 }
229
230 // Non-A/B devices will not have a boot control HAL.
231 auto boot_control_hal = device->boot_control_hal();
232 if (!boot_control_hal) {
233 return device->WriteStatus(FastbootResult::FAIL,
234 "Cannot set slot: boot control HAL absent");
235 }
236 if (slot >= boot_control_hal->getNumberSlots()) {
237 return device->WriteStatus(FastbootResult::FAIL, "Slot out of range");
238 }
239 CommandResult ret;
240 auto cb = [&ret](CommandResult result) { ret = result; };
241 auto result = boot_control_hal->setActiveBootSlot(slot, cb);
Hridya Valsaraju20bdf892018-10-10 11:02:19 -0700242 if (result.isOk() && ret.success) {
243 // Save as slot suffix to match the suffix format as returned from
244 // the boot control HAL.
245 auto current_slot = "_" + args[1];
246 device->set_active_slot(current_slot);
247 return device->WriteStatus(FastbootResult::OKAY, "");
248 }
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700249 return device->WriteStatus(FastbootResult::FAIL, "Unable to set slot");
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700250}
251
252bool ShutDownHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
253 auto result = device->WriteStatus(FastbootResult::OKAY, "Shutting down");
254 android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,fastboot");
255 device->CloseDevice();
256 TEMP_FAILURE_RETRY(pause());
257 return result;
258}
259
260bool RebootHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
261 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting");
262 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,from_fastboot");
263 device->CloseDevice();
264 TEMP_FAILURE_RETRY(pause());
265 return result;
266}
267
268bool RebootBootloaderHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
269 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting bootloader");
270 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
271 device->CloseDevice();
272 TEMP_FAILURE_RETRY(pause());
273 return result;
274}
275
276bool RebootFastbootHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
277 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting fastboot");
278 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
279 device->CloseDevice();
280 TEMP_FAILURE_RETRY(pause());
281 return result;
282}
283
284static bool EnterRecovery() {
285 const char msg_switch_to_recovery = 'r';
286
287 android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0));
288 if (sock < 0) {
289 PLOG(ERROR) << "Couldn't create sock";
290 return false;
291 }
292
293 struct sockaddr_un addr = {.sun_family = AF_UNIX};
294 strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1);
295 if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
296 PLOG(ERROR) << "Couldn't connect to recovery";
297 return false;
298 }
299 // Switch to recovery will not update the boot reason since it does not
300 // require a reboot.
301 auto ret = write(sock, &msg_switch_to_recovery, sizeof(msg_switch_to_recovery));
302 if (ret != sizeof(msg_switch_to_recovery)) {
303 PLOG(ERROR) << "Couldn't write message to switch to recovery";
304 return false;
305 }
306
307 return true;
308}
309
310bool RebootRecoveryHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
311 auto status = true;
312 if (EnterRecovery()) {
313 status = device->WriteStatus(FastbootResult::OKAY, "Rebooting to recovery");
314 } else {
315 status = device->WriteStatus(FastbootResult::FAIL, "Unable to reboot to recovery");
316 }
317 device->CloseDevice();
318 TEMP_FAILURE_RETRY(pause());
319 return status;
320}
David Anderson0d4277d2018-07-31 13:27:37 -0700321
322// Helper class for opening a handle to a MetadataBuilder and writing the new
323// partition table to the same place it was read.
324class PartitionBuilder {
325 public:
David Andersond25f1c32018-11-09 20:41:33 -0800326 explicit PartitionBuilder(FastbootDevice* device, const std::string& partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700327
328 bool Write();
329 bool Valid() const { return !!builder_; }
330 MetadataBuilder* operator->() const { return builder_.get(); }
331
332 private:
David Anderson4d307b02018-12-17 17:07:34 -0800333 FastbootDevice* device_;
David Anderson0d4277d2018-07-31 13:27:37 -0700334 std::string super_device_;
David Andersond25f1c32018-11-09 20:41:33 -0800335 uint32_t slot_number_;
David Anderson0d4277d2018-07-31 13:27:37 -0700336 std::unique_ptr<MetadataBuilder> builder_;
337};
338
David Anderson4d307b02018-12-17 17:07:34 -0800339PartitionBuilder::PartitionBuilder(FastbootDevice* device, const std::string& partition_name)
340 : device_(device) {
David Andersond25f1c32018-11-09 20:41:33 -0800341 std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
David Anderson27475322019-06-11 14:00:08 -0700342 slot_number_ = android::fs_mgr::SlotNumberForSlotSuffix(slot_suffix);
David Andersond25f1c32018-11-09 20:41:33 -0800343 auto super_device = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number_));
David Anderson0d4277d2018-07-31 13:27:37 -0700344 if (!super_device) {
345 return;
346 }
347 super_device_ = *super_device;
David Andersond25f1c32018-11-09 20:41:33 -0800348 builder_ = MetadataBuilder::New(super_device_, slot_number_);
David Anderson0d4277d2018-07-31 13:27:37 -0700349}
350
351bool PartitionBuilder::Write() {
David Anderson27475322019-06-11 14:00:08 -0700352 auto metadata = builder_->Export();
David Anderson0d4277d2018-07-31 13:27:37 -0700353 if (!metadata) {
354 return false;
355 }
David Anderson4d307b02018-12-17 17:07:34 -0800356 return UpdateAllPartitionMetadata(device_, super_device_, *metadata.get());
David Anderson0d4277d2018-07-31 13:27:37 -0700357}
358
359bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
360 if (args.size() < 3) {
361 return device->WriteFail("Invalid partition name and size");
362 }
363
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700364 if (GetDeviceLockStatus()) {
365 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
366 }
367
David Anderson0d4277d2018-07-31 13:27:37 -0700368 uint64_t partition_size;
369 std::string partition_name = args[1];
370 if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
371 return device->WriteFail("Invalid partition size");
372 }
373
David Andersond25f1c32018-11-09 20:41:33 -0800374 PartitionBuilder builder(device, partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700375 if (!builder.Valid()) {
376 return device->WriteFail("Could not open super partition");
377 }
378 // TODO(112433293) Disallow if the name is in the physical table as well.
379 if (builder->FindPartition(partition_name)) {
380 return device->WriteFail("Partition already exists");
381 }
382
David Anderson27475322019-06-11 14:00:08 -0700383 auto partition = builder->AddPartition(partition_name, 0);
David Anderson0d4277d2018-07-31 13:27:37 -0700384 if (!partition) {
385 return device->WriteFail("Failed to add partition");
386 }
387 if (!builder->ResizePartition(partition, partition_size)) {
388 builder->RemovePartition(partition_name);
389 return device->WriteFail("Not enough space for partition");
390 }
391 if (!builder.Write()) {
392 return device->WriteFail("Failed to write partition table");
393 }
394 return device->WriteOkay("Partition created");
395}
396
397bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
398 if (args.size() < 2) {
399 return device->WriteFail("Invalid partition name and size");
400 }
401
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700402 if (GetDeviceLockStatus()) {
403 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
404 }
405
David Andersond25f1c32018-11-09 20:41:33 -0800406 std::string partition_name = args[1];
407
408 PartitionBuilder builder(device, partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700409 if (!builder.Valid()) {
410 return device->WriteFail("Could not open super partition");
411 }
David Andersond25f1c32018-11-09 20:41:33 -0800412 builder->RemovePartition(partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700413 if (!builder.Write()) {
414 return device->WriteFail("Failed to write partition table");
415 }
416 return device->WriteOkay("Partition deleted");
417}
418
419bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
420 if (args.size() < 3) {
421 return device->WriteFail("Invalid partition name and size");
422 }
423
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700424 if (GetDeviceLockStatus()) {
425 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
426 }
427
David Anderson0d4277d2018-07-31 13:27:37 -0700428 uint64_t partition_size;
429 std::string partition_name = args[1];
430 if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
431 return device->WriteFail("Invalid partition size");
432 }
433
David Andersond25f1c32018-11-09 20:41:33 -0800434 PartitionBuilder builder(device, partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700435 if (!builder.Valid()) {
436 return device->WriteFail("Could not open super partition");
437 }
438
David Anderson27475322019-06-11 14:00:08 -0700439 auto partition = builder->FindPartition(partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700440 if (!partition) {
441 return device->WriteFail("Partition does not exist");
442 }
443 if (!builder->ResizePartition(partition, partition_size)) {
444 return device->WriteFail("Not enough space to resize partition");
445 }
446 if (!builder.Write()) {
447 return device->WriteFail("Failed to write partition table");
448 }
449 return device->WriteOkay("Partition resized");
450}
David Anderson38b3c7a2018-08-15 16:27:42 -0700451
452bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args) {
453 if (args.size() < 2) {
454 return device->WriteFail("Invalid arguments");
455 }
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700456
457 if (GetDeviceLockStatus()) {
458 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
459 }
460
David Anderson38b3c7a2018-08-15 16:27:42 -0700461 bool wipe = (args.size() >= 3 && args[2] == "wipe");
462 return UpdateSuper(device, args[1], wipe);
463}
David Anderson1d504e32019-01-15 14:38:20 -0800464
David Anderson3d782d52019-01-29 13:09:49 -0800465class AutoMountMetadata {
466 public:
467 AutoMountMetadata() {
David Anderson27475322019-06-11 14:00:08 -0700468 android::fs_mgr::Fstab proc_mounts;
David Anderson3d782d52019-01-29 13:09:49 -0800469 if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
470 LOG(ERROR) << "Could not read /proc/mounts";
471 return;
472 }
473
474 auto iter = std::find_if(proc_mounts.begin(), proc_mounts.end(),
475 [](const auto& entry) { return entry.mount_point == "/metadata"; });
476 if (iter != proc_mounts.end()) {
477 mounted_ = true;
478 return;
479 }
480
481 if (!ReadDefaultFstab(&fstab_)) {
482 LOG(ERROR) << "Could not read default fstab";
483 return;
484 }
485 mounted_ = EnsurePathMounted(&fstab_, "/metadata");
486 should_unmount_ = true;
David Anderson1d504e32019-01-15 14:38:20 -0800487 }
David Anderson3d782d52019-01-29 13:09:49 -0800488 ~AutoMountMetadata() {
489 if (mounted_ && should_unmount_) {
490 EnsurePathUnmounted(&fstab_, "/metadata");
491 }
492 }
493 explicit operator bool() const { return mounted_; }
494
495 private:
David Anderson27475322019-06-11 14:00:08 -0700496 android::fs_mgr::Fstab fstab_;
David Anderson3d782d52019-01-29 13:09:49 -0800497 bool mounted_ = false;
498 bool should_unmount_ = false;
499};
500
501bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) {
David Anderson1d504e32019-01-15 14:38:20 -0800502 if (args.size() != 2) {
503 return device->WriteFail("Invalid arguments");
504 }
David Anderson3d782d52019-01-29 13:09:49 -0800505
506 AutoMountMetadata mount_metadata;
507 if (!mount_metadata) {
508 return device->WriteFail("Could not find GSI install");
509 }
510
511 if (!android::gsi::IsGsiInstalled()) {
512 return device->WriteStatus(FastbootResult::FAIL, "No GSI is installed");
513 }
514
David Anderson1d504e32019-01-15 14:38:20 -0800515 if (args[1] == "wipe") {
516 if (!android::gsi::UninstallGsi()) {
517 return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
518 }
519 } else if (args[1] == "disable") {
520 if (!android::gsi::DisableGsi()) {
521 return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
522 }
523 }
524 return device->WriteStatus(FastbootResult::OKAY, "Success");
525}