blob: 1b09f79f62b620d3d43bc74357297fd171483da5 [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
42using ::android::hardware::hidl_string;
43using ::android::hardware::boot::V1_0::BoolResult;
44using ::android::hardware::boot::V1_0::CommandResult;
45using ::android::hardware::boot::V1_0::Slot;
Hridya Valsarajua15fe312018-09-14 13:58:21 -070046using ::android::hardware::fastboot::V1_0::Result;
47using ::android::hardware::fastboot::V1_0::Status;
48
David Anderson0d4277d2018-07-31 13:27:37 -070049using namespace android::fs_mgr;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070050
David Anderson0f626632018-08-31 16:44:25 -070051struct VariableHandlers {
52 // Callback to retrieve the value of a single variable.
53 std::function<bool(FastbootDevice*, const std::vector<std::string>&, std::string*)> get;
54 // Callback to retrieve all possible argument combinations, for getvar all.
55 std::function<std::vector<std::vector<std::string>>(FastbootDevice*)> get_all_args;
56};
57
58static void GetAllVars(FastbootDevice* device, const std::string& name,
59 const VariableHandlers& handlers) {
60 if (!handlers.get_all_args) {
61 std::string message;
62 if (!handlers.get(device, std::vector<std::string>(), &message)) {
63 return;
64 }
65 device->WriteInfo(android::base::StringPrintf("%s:%s", name.c_str(), message.c_str()));
66 return;
67 }
68
69 auto all_args = handlers.get_all_args(device);
70 for (const auto& args : all_args) {
71 std::string message;
72 if (!handlers.get(device, args, &message)) {
73 continue;
74 }
75 std::string arg_string = android::base::Join(args, ":");
76 device->WriteInfo(android::base::StringPrintf("%s:%s:%s", name.c_str(), arg_string.c_str(),
77 message.c_str()));
78 }
79}
80
Hridya Valsaraju31d2c262018-07-20 13:35:50 -070081bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args) {
David Anderson0f626632018-08-31 16:44:25 -070082 const std::unordered_map<std::string, VariableHandlers> kVariableMap = {
83 {FB_VAR_VERSION, {GetVersion, nullptr}},
84 {FB_VAR_VERSION_BOOTLOADER, {GetBootloaderVersion, nullptr}},
85 {FB_VAR_VERSION_BASEBAND, {GetBasebandVersion, nullptr}},
86 {FB_VAR_PRODUCT, {GetProduct, nullptr}},
87 {FB_VAR_SERIALNO, {GetSerial, nullptr}},
Hridya Valsaraju4af80902018-09-26 13:08:16 -070088 {FB_VAR_VARIANT, {GetVariant, nullptr}},
David Anderson0f626632018-08-31 16:44:25 -070089 {FB_VAR_SECURE, {GetSecure, nullptr}},
90 {FB_VAR_UNLOCKED, {GetUnlocked, nullptr}},
91 {FB_VAR_MAX_DOWNLOAD_SIZE, {GetMaxDownloadSize, nullptr}},
92 {FB_VAR_CURRENT_SLOT, {::GetCurrentSlot, nullptr}},
93 {FB_VAR_SLOT_COUNT, {GetSlotCount, nullptr}},
94 {FB_VAR_HAS_SLOT, {GetHasSlot, GetAllPartitionArgsNoSlot}},
95 {FB_VAR_SLOT_SUCCESSFUL, {GetSlotSuccessful, nullptr}},
96 {FB_VAR_SLOT_UNBOOTABLE, {GetSlotUnbootable, nullptr}},
97 {FB_VAR_PARTITION_SIZE, {GetPartitionSize, GetAllPartitionArgsWithSlot}},
Hridya Valsarajubf9f8d12018-09-05 16:57:24 -070098 {FB_VAR_PARTITION_TYPE, {GetPartitionType, GetAllPartitionArgsWithSlot}},
David Anderson0f626632018-08-31 16:44:25 -070099 {FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
David Andersonc091c172018-09-04 18:11:03 -0700100 {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
Hridya Valsaraju7c9bbe92018-09-27 10:41:01 -0700101 {FB_VAR_OFF_MODE_CHARGE_STATE, {GetOffModeChargeState, nullptr}},
Hridya Valsaraju47658ca2018-09-28 11:41:22 -0700102 {FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
Hridya Valsarajua534a5a2018-10-03 15:53:22 -0700103 {FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
David Anderson90fe0a42018-11-05 18:01:32 -0800104 {FB_VAR_HW_REVISION, {GetHardwareRevision, nullptr}},
105 {FB_VAR_SUPER_PARTITION_NAME, {GetSuperPartitionName, nullptr}}};
David Anderson0f626632018-08-31 16:44:25 -0700106
107 if (args.size() < 2) {
108 return device->WriteFail("Missing argument");
109 }
110
111 // Special case: return all variables that we can.
112 if (args[1] == "all") {
113 for (const auto& [name, handlers] : kVariableMap) {
114 GetAllVars(device, name, handlers);
115 }
116 return device->WriteOkay("");
117 }
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700118
119 // args[0] is command name, args[1] is variable.
120 auto found_variable = kVariableMap.find(args[1]);
121 if (found_variable == kVariableMap.end()) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700122 return device->WriteFail("Unknown variable");
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700123 }
124
David Anderson1fb3fd72018-08-31 14:40:22 -0700125 std::string message;
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700126 std::vector<std::string> getvar_args(args.begin() + 2, args.end());
David Anderson0f626632018-08-31 16:44:25 -0700127 if (!found_variable->second.get(device, getvar_args, &message)) {
David Anderson1fb3fd72018-08-31 14:40:22 -0700128 return device->WriteFail(message);
129 }
130 return device->WriteOkay(message);
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700131}
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700132
David Anderson12211d12018-07-24 15:21:20 -0700133bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) {
134 if (args.size() < 2) {
135 return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
136 }
Hridya Valsarajud1e62312018-10-08 09:13:17 -0700137
138 if (GetDeviceLockStatus()) {
139 return device->WriteStatus(FastbootResult::FAIL, "Erase is not allowed on locked devices");
140 }
141
David Anderson12211d12018-07-24 15:21:20 -0700142 PartitionHandle handle;
143 if (!OpenPartition(device, args[1], &handle)) {
144 return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist");
145 }
146 if (wipe_block_device(handle.fd(), get_block_device_size(handle.fd())) == 0) {
147 return device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
148 }
149 return device->WriteStatus(FastbootResult::FAIL, "Erasing failed");
150}
151
Hridya Valsarajua15fe312018-09-14 13:58:21 -0700152bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args) {
153 auto fastboot_hal = device->fastboot_hal();
154 if (!fastboot_hal) {
155 return device->WriteStatus(FastbootResult::FAIL, "Unable to open fastboot HAL");
156 }
157
158 Result ret;
159 auto ret_val = fastboot_hal->doOemCommand(args[0], [&](Result result) { ret = result; });
160 if (!ret_val.isOk()) {
161 return device->WriteStatus(FastbootResult::FAIL, "Unable to do OEM command");
162 }
163 if (ret.status != Status::SUCCESS) {
164 return device->WriteStatus(FastbootResult::FAIL, ret.message);
165 }
166
167 return device->WriteStatus(FastbootResult::OKAY, ret.message);
168}
169
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700170bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
171 if (args.size() < 2) {
172 return device->WriteStatus(FastbootResult::FAIL, "size argument unspecified");
173 }
Hridya Valsarajud1e62312018-10-08 09:13:17 -0700174
175 if (GetDeviceLockStatus()) {
176 return device->WriteStatus(FastbootResult::FAIL,
177 "Download is not allowed on locked devices");
178 }
179
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700180 // arg[0] is the command name, arg[1] contains size of data to be downloaded
181 unsigned int size;
Hridya Valsarajuaae84e82018-10-08 13:10:25 -0700182 if (!android::base::ParseUint("0x" + args[1], &size, kMaxDownloadSizeDefault)) {
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700183 return device->WriteStatus(FastbootResult::FAIL, "Invalid size");
184 }
David Anderson12211d12018-07-24 15:21:20 -0700185 device->download_data().resize(size);
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700186 if (!device->WriteStatus(FastbootResult::DATA, android::base::StringPrintf("%08x", size))) {
187 return false;
188 }
189
David Anderson12211d12018-07-24 15:21:20 -0700190 if (device->HandleData(true, &device->download_data())) {
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700191 return device->WriteStatus(FastbootResult::OKAY, "");
192 }
193
194 PLOG(ERROR) << "Couldn't download data";
195 return device->WriteStatus(FastbootResult::FAIL, "Couldn't download data");
196}
197
David Anderson12211d12018-07-24 15:21:20 -0700198bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) {
199 if (args.size() < 2) {
200 return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
201 }
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700202
203 if (GetDeviceLockStatus()) {
204 return device->WriteStatus(FastbootResult::FAIL,
205 "Flashing is not allowed on locked devices");
206 }
207
David Anderson12211d12018-07-24 15:21:20 -0700208 int ret = Flash(device, args[1]);
209 if (ret < 0) {
210 return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
211 }
212 return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
213}
214
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700215bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& args) {
216 if (args.size() < 2) {
217 return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
218 }
219
Hridya Valsarajud1e62312018-10-08 09:13:17 -0700220 if (GetDeviceLockStatus()) {
221 return device->WriteStatus(FastbootResult::FAIL,
222 "set_active command is not allowed on locked devices");
223 }
224
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700225 // Slot suffix needs to be between 'a' and 'z'.
226 Slot slot;
227 if (!GetSlotNumber(args[1], &slot)) {
228 return device->WriteStatus(FastbootResult::FAIL, "Bad slot suffix");
229 }
230
231 // Non-A/B devices will not have a boot control HAL.
232 auto boot_control_hal = device->boot_control_hal();
233 if (!boot_control_hal) {
234 return device->WriteStatus(FastbootResult::FAIL,
235 "Cannot set slot: boot control HAL absent");
236 }
237 if (slot >= boot_control_hal->getNumberSlots()) {
238 return device->WriteStatus(FastbootResult::FAIL, "Slot out of range");
239 }
240 CommandResult ret;
241 auto cb = [&ret](CommandResult result) { ret = result; };
242 auto result = boot_control_hal->setActiveBootSlot(slot, cb);
Hridya Valsaraju20bdf892018-10-10 11:02:19 -0700243 if (result.isOk() && ret.success) {
244 // Save as slot suffix to match the suffix format as returned from
245 // the boot control HAL.
246 auto current_slot = "_" + args[1];
247 device->set_active_slot(current_slot);
248 return device->WriteStatus(FastbootResult::OKAY, "");
249 }
Hridya Valsaraju31d2c262018-07-20 13:35:50 -0700250 return device->WriteStatus(FastbootResult::FAIL, "Unable to set slot");
Hridya Valsarajudea91b42018-07-17 11:14:01 -0700251}
252
253bool ShutDownHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
254 auto result = device->WriteStatus(FastbootResult::OKAY, "Shutting down");
255 android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,fastboot");
256 device->CloseDevice();
257 TEMP_FAILURE_RETRY(pause());
258 return result;
259}
260
261bool RebootHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
262 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting");
263 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,from_fastboot");
264 device->CloseDevice();
265 TEMP_FAILURE_RETRY(pause());
266 return result;
267}
268
269bool RebootBootloaderHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
270 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting bootloader");
271 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
272 device->CloseDevice();
273 TEMP_FAILURE_RETRY(pause());
274 return result;
275}
276
277bool RebootFastbootHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
278 auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting fastboot");
279 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
280 device->CloseDevice();
281 TEMP_FAILURE_RETRY(pause());
282 return result;
283}
284
285static bool EnterRecovery() {
286 const char msg_switch_to_recovery = 'r';
287
288 android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0));
289 if (sock < 0) {
290 PLOG(ERROR) << "Couldn't create sock";
291 return false;
292 }
293
294 struct sockaddr_un addr = {.sun_family = AF_UNIX};
295 strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1);
296 if (connect(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
297 PLOG(ERROR) << "Couldn't connect to recovery";
298 return false;
299 }
300 // Switch to recovery will not update the boot reason since it does not
301 // require a reboot.
302 auto ret = write(sock, &msg_switch_to_recovery, sizeof(msg_switch_to_recovery));
303 if (ret != sizeof(msg_switch_to_recovery)) {
304 PLOG(ERROR) << "Couldn't write message to switch to recovery";
305 return false;
306 }
307
308 return true;
309}
310
311bool RebootRecoveryHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
312 auto status = true;
313 if (EnterRecovery()) {
314 status = device->WriteStatus(FastbootResult::OKAY, "Rebooting to recovery");
315 } else {
316 status = device->WriteStatus(FastbootResult::FAIL, "Unable to reboot to recovery");
317 }
318 device->CloseDevice();
319 TEMP_FAILURE_RETRY(pause());
320 return status;
321}
David Anderson0d4277d2018-07-31 13:27:37 -0700322
323// Helper class for opening a handle to a MetadataBuilder and writing the new
324// partition table to the same place it was read.
325class PartitionBuilder {
326 public:
David Andersond25f1c32018-11-09 20:41:33 -0800327 explicit PartitionBuilder(FastbootDevice* device, const std::string& partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700328
329 bool Write();
330 bool Valid() const { return !!builder_; }
331 MetadataBuilder* operator->() const { return builder_.get(); }
332
333 private:
David Anderson4d307b02018-12-17 17:07:34 -0800334 FastbootDevice* device_;
David Anderson0d4277d2018-07-31 13:27:37 -0700335 std::string super_device_;
David Andersond25f1c32018-11-09 20:41:33 -0800336 uint32_t slot_number_;
David Anderson0d4277d2018-07-31 13:27:37 -0700337 std::unique_ptr<MetadataBuilder> builder_;
338};
339
David Anderson4d307b02018-12-17 17:07:34 -0800340PartitionBuilder::PartitionBuilder(FastbootDevice* device, const std::string& partition_name)
341 : device_(device) {
David Andersond25f1c32018-11-09 20:41:33 -0800342 std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
343 slot_number_ = SlotNumberForSlotSuffix(slot_suffix);
344 auto super_device = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number_));
David Anderson0d4277d2018-07-31 13:27:37 -0700345 if (!super_device) {
346 return;
347 }
348 super_device_ = *super_device;
David Andersond25f1c32018-11-09 20:41:33 -0800349 builder_ = MetadataBuilder::New(super_device_, slot_number_);
David Anderson0d4277d2018-07-31 13:27:37 -0700350}
351
352bool PartitionBuilder::Write() {
353 std::unique_ptr<LpMetadata> metadata = builder_->Export();
354 if (!metadata) {
355 return false;
356 }
David Anderson4d307b02018-12-17 17:07:34 -0800357 return UpdateAllPartitionMetadata(device_, super_device_, *metadata.get());
David Anderson0d4277d2018-07-31 13:27:37 -0700358}
359
360bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
361 if (args.size() < 3) {
362 return device->WriteFail("Invalid partition name and size");
363 }
364
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700365 if (GetDeviceLockStatus()) {
366 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
367 }
368
David Anderson0d4277d2018-07-31 13:27:37 -0700369 uint64_t partition_size;
370 std::string partition_name = args[1];
371 if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
372 return device->WriteFail("Invalid partition size");
373 }
374
David Andersond25f1c32018-11-09 20:41:33 -0800375 PartitionBuilder builder(device, partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700376 if (!builder.Valid()) {
377 return device->WriteFail("Could not open super partition");
378 }
379 // TODO(112433293) Disallow if the name is in the physical table as well.
380 if (builder->FindPartition(partition_name)) {
381 return device->WriteFail("Partition already exists");
382 }
383
David Andersone5f2f062018-10-03 13:49:23 -0700384 Partition* partition = builder->AddPartition(partition_name, 0);
David Anderson0d4277d2018-07-31 13:27:37 -0700385 if (!partition) {
386 return device->WriteFail("Failed to add partition");
387 }
388 if (!builder->ResizePartition(partition, partition_size)) {
389 builder->RemovePartition(partition_name);
390 return device->WriteFail("Not enough space for partition");
391 }
392 if (!builder.Write()) {
393 return device->WriteFail("Failed to write partition table");
394 }
395 return device->WriteOkay("Partition created");
396}
397
398bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
399 if (args.size() < 2) {
400 return device->WriteFail("Invalid partition name and size");
401 }
402
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700403 if (GetDeviceLockStatus()) {
404 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
405 }
406
David Andersond25f1c32018-11-09 20:41:33 -0800407 std::string partition_name = args[1];
408
409 PartitionBuilder builder(device, partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700410 if (!builder.Valid()) {
411 return device->WriteFail("Could not open super partition");
412 }
David Andersond25f1c32018-11-09 20:41:33 -0800413 builder->RemovePartition(partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700414 if (!builder.Write()) {
415 return device->WriteFail("Failed to write partition table");
416 }
417 return device->WriteOkay("Partition deleted");
418}
419
420bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
421 if (args.size() < 3) {
422 return device->WriteFail("Invalid partition name and size");
423 }
424
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700425 if (GetDeviceLockStatus()) {
426 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
427 }
428
David Anderson0d4277d2018-07-31 13:27:37 -0700429 uint64_t partition_size;
430 std::string partition_name = args[1];
431 if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
432 return device->WriteFail("Invalid partition size");
433 }
434
David Andersond25f1c32018-11-09 20:41:33 -0800435 PartitionBuilder builder(device, partition_name);
David Anderson0d4277d2018-07-31 13:27:37 -0700436 if (!builder.Valid()) {
437 return device->WriteFail("Could not open super partition");
438 }
439
440 Partition* partition = builder->FindPartition(partition_name);
441 if (!partition) {
442 return device->WriteFail("Partition does not exist");
443 }
444 if (!builder->ResizePartition(partition, partition_size)) {
445 return device->WriteFail("Not enough space to resize partition");
446 }
447 if (!builder.Write()) {
448 return device->WriteFail("Failed to write partition table");
449 }
450 return device->WriteOkay("Partition resized");
451}
David Anderson38b3c7a2018-08-15 16:27:42 -0700452
453bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args) {
454 if (args.size() < 2) {
455 return device->WriteFail("Invalid arguments");
456 }
Hridya Valsarajudca328d2018-09-24 16:01:35 -0700457
458 if (GetDeviceLockStatus()) {
459 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
460 }
461
David Anderson38b3c7a2018-08-15 16:27:42 -0700462 bool wipe = (args.size() >= 3 && args[2] == "wipe");
463 return UpdateSuper(device, args[1], wipe);
464}
David Anderson1d504e32019-01-15 14:38:20 -0800465
David Anderson3d782d52019-01-29 13:09:49 -0800466class AutoMountMetadata {
467 public:
468 AutoMountMetadata() {
469 Fstab proc_mounts;
470 if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
471 LOG(ERROR) << "Could not read /proc/mounts";
472 return;
473 }
474
475 auto iter = std::find_if(proc_mounts.begin(), proc_mounts.end(),
476 [](const auto& entry) { return entry.mount_point == "/metadata"; });
477 if (iter != proc_mounts.end()) {
478 mounted_ = true;
479 return;
480 }
481
482 if (!ReadDefaultFstab(&fstab_)) {
483 LOG(ERROR) << "Could not read default fstab";
484 return;
485 }
486 mounted_ = EnsurePathMounted(&fstab_, "/metadata");
487 should_unmount_ = true;
David Anderson1d504e32019-01-15 14:38:20 -0800488 }
David Anderson3d782d52019-01-29 13:09:49 -0800489 ~AutoMountMetadata() {
490 if (mounted_ && should_unmount_) {
491 EnsurePathUnmounted(&fstab_, "/metadata");
492 }
493 }
494 explicit operator bool() const { return mounted_; }
495
496 private:
497 Fstab fstab_;
498 bool mounted_ = false;
499 bool should_unmount_ = false;
500};
501
502bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) {
David Anderson1d504e32019-01-15 14:38:20 -0800503 if (args.size() != 2) {
504 return device->WriteFail("Invalid arguments");
505 }
David Anderson3d782d52019-01-29 13:09:49 -0800506
507 AutoMountMetadata mount_metadata;
508 if (!mount_metadata) {
509 return device->WriteFail("Could not find GSI install");
510 }
511
512 if (!android::gsi::IsGsiInstalled()) {
513 return device->WriteStatus(FastbootResult::FAIL, "No GSI is installed");
514 }
515
David Anderson1d504e32019-01-15 14:38:20 -0800516 if (args[1] == "wipe") {
517 if (!android::gsi::UninstallGsi()) {
518 return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
519 }
520 } else if (args[1] == "disable") {
521 if (!android::gsi::DisableGsi()) {
522 return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
523 }
524 }
525 return device->WriteStatus(FastbootResult::OKAY, "Success");
526}