1 /*
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>
29 #include <ext4_utils/wipe.h>
30 #include <fs_mgr.h>
31 #include <fs_mgr/roots.h>
32 #include <libgsi/libgsi.h>
33 #include <liblp/builder.h>
34 #include <liblp/liblp.h>
35 #include <uuid/uuid.h>
36
37 #include "constants.h"
38 #include "fastboot_device.h"
39 #include "flashing.h"
40 #include "utility.h"
41
42 using ::android::hardware::hidl_string;
43 using ::android::hardware::boot::V1_0::BoolResult;
44 using ::android::hardware::boot::V1_0::CommandResult;
45 using ::android::hardware::boot::V1_0::Slot;
46 using ::android::hardware::fastboot::V1_0::Result;
47 using ::android::hardware::fastboot::V1_0::Status;
48
49 using namespace android::fs_mgr;
50
51 struct 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
GetAllVars(FastbootDevice * device,const std::string & name,const VariableHandlers & handlers)58 static 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
GetVarHandler(FastbootDevice * device,const std::vector<std::string> & args)81 bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args) {
82 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}},
88 {FB_VAR_VARIANT, {GetVariant, nullptr}},
89 {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}},
98 {FB_VAR_PARTITION_TYPE, {GetPartitionType, GetAllPartitionArgsWithSlot}},
99 {FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
100 {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
101 {FB_VAR_OFF_MODE_CHARGE_STATE, {GetOffModeChargeState, nullptr}},
102 {FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
103 {FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
104 {FB_VAR_HW_REVISION, {GetHardwareRevision, nullptr}},
105 {FB_VAR_SUPER_PARTITION_NAME, {GetSuperPartitionName, nullptr}}};
106
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 }
118
119 // args[0] is command name, args[1] is variable.
120 auto found_variable = kVariableMap.find(args[1]);
121 if (found_variable == kVariableMap.end()) {
122 return device->WriteFail("Unknown variable");
123 }
124
125 std::string message;
126 std::vector<std::string> getvar_args(args.begin() + 2, args.end());
127 if (!found_variable->second.get(device, getvar_args, &message)) {
128 return device->WriteFail(message);
129 }
130 return device->WriteOkay(message);
131 }
132
EraseHandler(FastbootDevice * device,const std::vector<std::string> & args)133 bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) {
134 if (args.size() < 2) {
135 return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
136 }
137
138 if (GetDeviceLockStatus()) {
139 return device->WriteStatus(FastbootResult::FAIL, "Erase is not allowed on locked devices");
140 }
141
142 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
OemCmdHandler(FastbootDevice * device,const std::vector<std::string> & args)152 bool 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
DownloadHandler(FastbootDevice * device,const std::vector<std::string> & args)170 bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
171 if (args.size() < 2) {
172 return device->WriteStatus(FastbootResult::FAIL, "size argument unspecified");
173 }
174
175 if (GetDeviceLockStatus()) {
176 return device->WriteStatus(FastbootResult::FAIL,
177 "Download is not allowed on locked devices");
178 }
179
180 // arg[0] is the command name, arg[1] contains size of data to be downloaded
181 unsigned int size;
182 if (!android::base::ParseUint("0x" + args[1], &size, kMaxDownloadSizeDefault)) {
183 return device->WriteStatus(FastbootResult::FAIL, "Invalid size");
184 }
185 device->download_data().resize(size);
186 if (!device->WriteStatus(FastbootResult::DATA, android::base::StringPrintf("%08x", size))) {
187 return false;
188 }
189
190 if (device->HandleData(true, &device->download_data())) {
191 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
FlashHandler(FastbootDevice * device,const std::vector<std::string> & args)198 bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) {
199 if (args.size() < 2) {
200 return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
201 }
202
203 if (GetDeviceLockStatus()) {
204 return device->WriteStatus(FastbootResult::FAIL,
205 "Flashing is not allowed on locked devices");
206 }
207
208 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
SetActiveHandler(FastbootDevice * device,const std::vector<std::string> & args)215 bool 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
220 if (GetDeviceLockStatus()) {
221 return device->WriteStatus(FastbootResult::FAIL,
222 "set_active command is not allowed on locked devices");
223 }
224
225 // 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);
243 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 }
250 return device->WriteStatus(FastbootResult::FAIL, "Unable to set slot");
251 }
252
ShutDownHandler(FastbootDevice * device,const std::vector<std::string> &)253 bool 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
RebootHandler(FastbootDevice * device,const std::vector<std::string> &)261 bool 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
RebootBootloaderHandler(FastbootDevice * device,const std::vector<std::string> &)269 bool 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
RebootFastbootHandler(FastbootDevice * device,const std::vector<std::string> &)277 bool 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
EnterRecovery()285 static 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
RebootRecoveryHandler(FastbootDevice * device,const std::vector<std::string> &)311 bool 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 }
322
323 // Helper class for opening a handle to a MetadataBuilder and writing the new
324 // partition table to the same place it was read.
325 class PartitionBuilder {
326 public:
327 explicit PartitionBuilder(FastbootDevice* device, const std::string& partition_name);
328
329 bool Write();
Valid() const330 bool Valid() const { return !!builder_; }
operator ->() const331 MetadataBuilder* operator->() const { return builder_.get(); }
332
333 private:
334 FastbootDevice* device_;
335 std::string super_device_;
336 uint32_t slot_number_;
337 std::unique_ptr<MetadataBuilder> builder_;
338 };
339
PartitionBuilder(FastbootDevice * device,const std::string & partition_name)340 PartitionBuilder::PartitionBuilder(FastbootDevice* device, const std::string& partition_name)
341 : device_(device) {
342 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_));
345 if (!super_device) {
346 return;
347 }
348 super_device_ = *super_device;
349 builder_ = MetadataBuilder::New(super_device_, slot_number_);
350 }
351
Write()352 bool PartitionBuilder::Write() {
353 std::unique_ptr<LpMetadata> metadata = builder_->Export();
354 if (!metadata) {
355 return false;
356 }
357 return UpdateAllPartitionMetadata(device_, super_device_, *metadata.get());
358 }
359
CreatePartitionHandler(FastbootDevice * device,const std::vector<std::string> & args)360 bool 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
365 if (GetDeviceLockStatus()) {
366 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
367 }
368
369 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
375 PartitionBuilder builder(device, partition_name);
376 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
384 Partition* partition = builder->AddPartition(partition_name, 0);
385 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
DeletePartitionHandler(FastbootDevice * device,const std::vector<std::string> & args)398 bool 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
403 if (GetDeviceLockStatus()) {
404 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
405 }
406
407 std::string partition_name = args[1];
408
409 PartitionBuilder builder(device, partition_name);
410 if (!builder.Valid()) {
411 return device->WriteFail("Could not open super partition");
412 }
413 builder->RemovePartition(partition_name);
414 if (!builder.Write()) {
415 return device->WriteFail("Failed to write partition table");
416 }
417 return device->WriteOkay("Partition deleted");
418 }
419
ResizePartitionHandler(FastbootDevice * device,const std::vector<std::string> & args)420 bool 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
425 if (GetDeviceLockStatus()) {
426 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
427 }
428
429 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
435 PartitionBuilder builder(device, partition_name);
436 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 }
452
UpdateSuperHandler(FastbootDevice * device,const std::vector<std::string> & args)453 bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args) {
454 if (args.size() < 2) {
455 return device->WriteFail("Invalid arguments");
456 }
457
458 if (GetDeviceLockStatus()) {
459 return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
460 }
461
462 bool wipe = (args.size() >= 3 && args[2] == "wipe");
463 return UpdateSuper(device, args[1], wipe);
464 }
465
466 class AutoMountMetadata {
467 public:
AutoMountMetadata()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;
488 }
~AutoMountMetadata()489 ~AutoMountMetadata() {
490 if (mounted_ && should_unmount_) {
491 EnsurePathUnmounted(&fstab_, "/metadata");
492 }
493 }
operator bool() const494 explicit operator bool() const { return mounted_; }
495
496 private:
497 Fstab fstab_;
498 bool mounted_ = false;
499 bool should_unmount_ = false;
500 };
501
GsiHandler(FastbootDevice * device,const std::vector<std::string> & args)502 bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) {
503 if (args.size() != 2) {
504 return device->WriteFail("Invalid arguments");
505 }
506
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
516 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 }
527