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 <inttypes.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 
23 #include <unordered_set>
24 
25 #include <android-base/logging.h>
26 #include <android-base/parseint.h>
27 #include <android-base/properties.h>
28 #include <android-base/stringprintf.h>
29 #include <android-base/strings.h>
30 #include <android-base/unique_fd.h>
31 #include <android/hardware/boot/1.1/IBootControl.h>
32 #include <cutils/android_reboot.h>
33 #include <ext4_utils/wipe.h>
34 #include <fs_mgr.h>
35 #include <fs_mgr/roots.h>
36 #include <libgsi/libgsi.h>
37 #include <liblp/builder.h>
38 #include <liblp/liblp.h>
39 #include <libsnapshot/snapshot.h>
40 #include <storage_literals/storage_literals.h>
41 #include <uuid/uuid.h>
42 
43 #include <bootloader_message/bootloader_message.h>
44 
45 #include "BootControlClient.h"
46 #include "constants.h"
47 #include "fastboot_device.h"
48 #include "flashing.h"
49 #include "utility.h"
50 
51 #ifdef FB_ENABLE_FETCH
52 static constexpr bool kEnableFetch = true;
53 #else
54 static constexpr bool kEnableFetch = false;
55 #endif
56 
57 using android::fs_mgr::MetadataBuilder;
58 using android::hal::CommandResult;
59 using ::android::hardware::hidl_string;
60 using android::snapshot::SnapshotManager;
61 using MergeStatus = android::hal::BootControlClient::MergeStatus;
62 
63 using namespace android::storage_literals;
64 
65 struct VariableHandlers {
66     // Callback to retrieve the value of a single variable.
67     std::function<bool(FastbootDevice*, const std::vector<std::string>&, std::string*)> get;
68     // Callback to retrieve all possible argument combinations, for getvar all.
69     std::function<std::vector<std::vector<std::string>>(FastbootDevice*)> get_all_args;
70 };
71 
IsSnapshotUpdateInProgress(FastbootDevice * device)72 static bool IsSnapshotUpdateInProgress(FastbootDevice* device) {
73     auto hal = device->boot1_1();
74     if (!hal) {
75         return false;
76     }
77     auto merge_status = hal->getSnapshotMergeStatus();
78     return merge_status == MergeStatus::SNAPSHOTTED || merge_status == MergeStatus::MERGING;
79 }
80 
IsProtectedPartitionDuringMerge(FastbootDevice * device,const std::string & name)81 static bool IsProtectedPartitionDuringMerge(FastbootDevice* device, const std::string& name) {
82     static const std::unordered_set<std::string> ProtectedPartitionsDuringMerge = {
83             "userdata", "metadata", "misc"};
84     if (ProtectedPartitionsDuringMerge.count(name) == 0) {
85         return false;
86     }
87     return IsSnapshotUpdateInProgress(device);
88 }
89 
GetAllVars(FastbootDevice * device,const std::string & name,const VariableHandlers & handlers)90 static void GetAllVars(FastbootDevice* device, const std::string& name,
91                        const VariableHandlers& handlers) {
92     if (!handlers.get_all_args) {
93         std::string message;
94         if (!handlers.get(device, std::vector<std::string>(), &message)) {
95             return;
96         }
97         device->WriteInfo(android::base::StringPrintf("%s:%s", name.c_str(), message.c_str()));
98         return;
99     }
100 
101     auto all_args = handlers.get_all_args(device);
102     for (const auto& args : all_args) {
103         std::string message;
104         if (!handlers.get(device, args, &message)) {
105             continue;
106         }
107         std::string arg_string = android::base::Join(args, ":");
108         device->WriteInfo(android::base::StringPrintf("%s:%s:%s", name.c_str(), arg_string.c_str(),
109                                                       message.c_str()));
110     }
111 }
112 
113 const std::unordered_map<std::string, VariableHandlers> kVariableMap = {
114         {FB_VAR_VERSION, {GetVersion, nullptr}},
115         {FB_VAR_VERSION_BOOTLOADER, {GetBootloaderVersion, nullptr}},
116         {FB_VAR_VERSION_BASEBAND, {GetBasebandVersion, nullptr}},
117         {FB_VAR_VERSION_OS, {GetOsVersion, nullptr}},
118         {FB_VAR_VERSION_VNDK, {GetVndkVersion, nullptr}},
119         {FB_VAR_PRODUCT, {GetProduct, nullptr}},
120         {FB_VAR_SERIALNO, {GetSerial, nullptr}},
121         {FB_VAR_VARIANT, {GetVariant, nullptr}},
122         {FB_VAR_SECURE, {GetSecure, nullptr}},
123         {FB_VAR_UNLOCKED, {GetUnlocked, nullptr}},
124         {FB_VAR_MAX_DOWNLOAD_SIZE, {GetMaxDownloadSize, nullptr}},
125         {FB_VAR_CURRENT_SLOT, {::GetCurrentSlot, nullptr}},
126         {FB_VAR_SLOT_COUNT, {GetSlotCount, nullptr}},
127         {FB_VAR_HAS_SLOT, {GetHasSlot, GetAllPartitionArgsNoSlot}},
128         {FB_VAR_SLOT_SUCCESSFUL, {GetSlotSuccessful, nullptr}},
129         {FB_VAR_SLOT_UNBOOTABLE, {GetSlotUnbootable, nullptr}},
130         {FB_VAR_PARTITION_SIZE, {GetPartitionSize, GetAllPartitionArgsWithSlot}},
131         {FB_VAR_PARTITION_TYPE, {GetPartitionType, GetAllPartitionArgsWithSlot}},
132         {FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
133         {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
134         {FB_VAR_IS_FORCE_DEBUGGABLE, {GetIsForceDebuggable, nullptr}},
135         {FB_VAR_OFF_MODE_CHARGE_STATE, {GetOffModeChargeState, nullptr}},
136         {FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
137         {FB_VAR_BATTERY_SOC, {GetBatterySoC, nullptr}},
138         {FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
139         {FB_VAR_HW_REVISION, {GetHardwareRevision, nullptr}},
140         {FB_VAR_SUPER_PARTITION_NAME, {GetSuperPartitionName, nullptr}},
141         {FB_VAR_SNAPSHOT_UPDATE_STATUS, {GetSnapshotUpdateStatus, nullptr}},
142         {FB_VAR_CPU_ABI, {GetCpuAbi, nullptr}},
143         {FB_VAR_SYSTEM_FINGERPRINT, {GetSystemFingerprint, nullptr}},
144         {FB_VAR_VENDOR_FINGERPRINT, {GetVendorFingerprint, nullptr}},
145         {FB_VAR_DYNAMIC_PARTITION, {GetDynamicPartition, nullptr}},
146         {FB_VAR_FIRST_API_LEVEL, {GetFirstApiLevel, nullptr}},
147         {FB_VAR_SECURITY_PATCH_LEVEL, {GetSecurityPatchLevel, nullptr}},
148         {FB_VAR_TREBLE_ENABLED, {GetTrebleEnabled, nullptr}},
149         {FB_VAR_MAX_FETCH_SIZE, {GetMaxFetchSize, nullptr}},
150         {FB_VAR_BATTERY_SERIAL_NUMBER, {GetBatterySerialNumber, nullptr}},
151         {FB_VAR_BATTERY_PART_STATUS, {GetBatteryPartStatus, nullptr}},
152 };
153 
GetVarAll(FastbootDevice * device)154 static bool GetVarAll(FastbootDevice* device) {
155     for (const auto& [name, handlers] : kVariableMap) {
156         GetAllVars(device, name, handlers);
157     }
158     return true;
159 }
160 
PostWipeData()161 static void PostWipeData() {
162     std::string err;
163     // Reset mte state of device.
164     if (!WriteMiscMemtagMessage({}, &err)) {
165         LOG(ERROR) << "Failed to reset MTE state: " << err;
166     }
167 }
168 
169 const std::unordered_map<std::string, std::function<bool(FastbootDevice*)>> kSpecialVars = {
170         {"all", GetVarAll},
171         {"dmesg", GetDmesg},
172 };
173 
GetVarHandler(FastbootDevice * device,const std::vector<std::string> & args)174 bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args) {
175     if (args.size() < 2) {
176         return device->WriteFail("Missing argument");
177     }
178 
179     // "all" and "dmesg" are multiline and handled specially.
180     auto found_special = kSpecialVars.find(args[1]);
181     if (found_special != kSpecialVars.end()) {
182         if (!found_special->second(device)) {
183             return false;
184         }
185         return device->WriteOkay("");
186     }
187 
188     // args[0] is command name, args[1] is variable.
189     auto found_variable = kVariableMap.find(args[1]);
190     if (found_variable == kVariableMap.end()) {
191         return device->WriteFail("Unknown variable");
192     }
193 
194     std::string message;
195     std::vector<std::string> getvar_args(args.begin() + 2, args.end());
196     if (!found_variable->second.get(device, getvar_args, &message)) {
197         return device->WriteFail(message);
198     }
199     return device->WriteOkay(message);
200 }
201 
OemPostWipeData(FastbootDevice * device)202 bool OemPostWipeData(FastbootDevice* device) {
203     auto fastboot_hal = device->fastboot_hal();
204     if (!fastboot_hal) {
205         return false;
206     }
207 
208     auto status = fastboot_hal->doOemSpecificErase();
209     if (status.isOk()) {
210         device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
211         return true;
212     }
213     switch (status.getExceptionCode()) {
214         case EX_UNSUPPORTED_OPERATION:
215             return false;
216         case EX_SERVICE_SPECIFIC:
217             device->WriteStatus(FastbootResult::FAIL, status.getDescription());
218             return false;
219         default:
220             LOG(ERROR) << "Erase operation failed" << status.getDescription();
221             return false;
222     }
223 }
224 
EraseHandler(FastbootDevice * device,const std::vector<std::string> & args)225 bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) {
226     if (args.size() < 2) {
227         return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
228     }
229 
230     if (GetDeviceLockStatus()) {
231         return device->WriteStatus(FastbootResult::FAIL, "Erase is not allowed on locked devices");
232     }
233 
234     const auto& partition_name = args[1];
235     if (IsProtectedPartitionDuringMerge(device, partition_name)) {
236         auto message = "Cannot erase " + partition_name + " while a snapshot update is in progress";
237         return device->WriteFail(message);
238     }
239 
240     PartitionHandle handle;
241     if (!OpenPartition(device, partition_name, &handle)) {
242         return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist");
243     }
244     if (wipe_block_device(handle.fd(), get_block_device_size(handle.fd())) == 0) {
245         //Perform oem PostWipeData if Android userdata partition has been erased
246         bool support_oem_postwipedata = false;
247         if (partition_name == "userdata") {
248             PostWipeData();
249             support_oem_postwipedata = OemPostWipeData(device);
250         }
251 
252         if (!support_oem_postwipedata) {
253             return device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
254         } else {
255             //Write device status in OemPostWipeData(), so just return true
256             return true;
257         }
258     }
259     return device->WriteStatus(FastbootResult::FAIL, "Erasing failed");
260 }
261 
OemCmdHandler(FastbootDevice * device,const std::vector<std::string> & args)262 bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args) {
263     auto fastboot_hal = device->fastboot_hal();
264     if (!fastboot_hal) {
265         return device->WriteStatus(FastbootResult::FAIL, "Unable to open fastboot HAL");
266     }
267 
268     //Disable "oem postwipedata userdata" to prevent user wipe oem userdata only.
269     if (args[0] == "oem postwipedata userdata") {
270         return device->WriteStatus(FastbootResult::FAIL, "Unable to do oem postwipedata userdata");
271     }
272     std::string message;
273     auto status = fastboot_hal->doOemCommand(args[0], &message);
274     if (!status.isOk()) {
275         LOG(ERROR) << "Unable to do OEM command " << args[0].c_str() << status.getDescription();
276         return device->WriteStatus(FastbootResult::FAIL,
277                                    "Unable to do OEM command " + status.getDescription());
278     }
279 
280     device->WriteInfo(message);
281     return device->WriteStatus(FastbootResult::OKAY, message);
282 }
283 
DownloadHandler(FastbootDevice * device,const std::vector<std::string> & args)284 bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
285     if (args.size() < 2) {
286         return device->WriteStatus(FastbootResult::FAIL, "size argument unspecified");
287     }
288 
289     if (GetDeviceLockStatus()) {
290         return device->WriteStatus(FastbootResult::FAIL,
291                                    "Download is not allowed on locked devices");
292     }
293 
294     // arg[0] is the command name, arg[1] contains size of data to be downloaded
295     // which should always be 8 bytes
296     if (args[1].length() != 8) {
297         return device->WriteStatus(FastbootResult::FAIL,
298                                    "Invalid size (length of size != 8)");
299     }
300     unsigned int size;
301     if (!android::base::ParseUint("0x" + args[1], &size, kMaxDownloadSizeDefault)) {
302         return device->WriteStatus(FastbootResult::FAIL, "Invalid size");
303     }
304     if (size == 0) {
305         return device->WriteStatus(FastbootResult::FAIL, "Invalid size (0)");
306     }
307     device->download_data().resize(size);
308     if (!device->WriteStatus(FastbootResult::DATA, android::base::StringPrintf("%08x", size))) {
309         return false;
310     }
311 
312     if (device->HandleData(true, &device->download_data())) {
313         return device->WriteStatus(FastbootResult::OKAY, "");
314     }
315 
316     PLOG(ERROR) << "Couldn't download data";
317     return device->WriteStatus(FastbootResult::FAIL, "Couldn't download data");
318 }
319 
SetActiveHandler(FastbootDevice * device,const std::vector<std::string> & args)320 bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& args) {
321     if (args.size() < 2) {
322         return device->WriteStatus(FastbootResult::FAIL, "Missing slot argument");
323     }
324 
325     if (GetDeviceLockStatus()) {
326         return device->WriteStatus(FastbootResult::FAIL,
327                                    "set_active command is not allowed on locked devices");
328     }
329 
330     int32_t slot = 0;
331     if (!GetSlotNumber(args[1], &slot)) {
332         // Slot suffix needs to be between 'a' and 'z'.
333         return device->WriteStatus(FastbootResult::FAIL, "Bad slot suffix");
334     }
335 
336     // Non-A/B devices will not have a boot control HAL.
337     auto boot_control_hal = device->boot_control_hal();
338     if (!boot_control_hal) {
339         return device->WriteStatus(FastbootResult::FAIL,
340                                    "Cannot set slot: boot control HAL absent");
341     }
342     if (slot >= boot_control_hal->GetNumSlots()) {
343         return device->WriteStatus(FastbootResult::FAIL, "Slot out of range");
344     }
345 
346     // If the slot is not changing, do nothing.
347     if (args[1] == device->GetCurrentSlot()) {
348         return device->WriteOkay("");
349     }
350 
351     // Check how to handle the current snapshot state.
352     if (auto hal11 = device->boot1_1()) {
353         auto merge_status = hal11->getSnapshotMergeStatus();
354         if (merge_status == MergeStatus::MERGING) {
355             return device->WriteFail("Cannot change slots while a snapshot update is in progress");
356         }
357         // Note: we allow the slot change if the state is SNAPSHOTTED. First-
358         // stage init does not have access to the HAL, and uses the slot number
359         // and /metadata OTA state to determine whether a slot change occurred.
360         // Booting into the old slot would erase the OTA, and switching A->B->A
361         // would simply resume it if no boots occur in between. Re-flashing
362         // partitions implicitly cancels the OTA, so leaving the state as-is is
363         // safe.
364         if (merge_status == MergeStatus::SNAPSHOTTED) {
365             device->WriteInfo(
366                     "Changing the active slot with a snapshot applied may cancel the"
367                     " update.");
368         }
369     }
370 
371     CommandResult ret = boot_control_hal->SetActiveBootSlot(slot);
372     if (ret.success) {
373         // Save as slot suffix to match the suffix format as returned from
374         // the boot control HAL.
375         auto current_slot = "_" + args[1];
376         device->set_active_slot(current_slot);
377         return device->WriteStatus(FastbootResult::OKAY, "");
378     }
379     return device->WriteStatus(FastbootResult::FAIL, "Unable to set slot");
380 }
381 
ShutDownHandler(FastbootDevice * device,const std::vector<std::string> &)382 bool ShutDownHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
383     auto result = device->WriteStatus(FastbootResult::OKAY, "Shutting down");
384     android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,fastboot");
385     device->CloseDevice();
386     TEMP_FAILURE_RETRY(pause());
387     return result;
388 }
389 
RebootHandler(FastbootDevice * device,const std::vector<std::string> &)390 bool RebootHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
391     auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting");
392     android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,from_fastboot");
393     device->CloseDevice();
394     TEMP_FAILURE_RETRY(pause());
395     return result;
396 }
397 
RebootBootloaderHandler(FastbootDevice * device,const std::vector<std::string> &)398 bool RebootBootloaderHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
399     auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting bootloader");
400     android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
401     device->CloseDevice();
402     TEMP_FAILURE_RETRY(pause());
403     return result;
404 }
405 
RebootFastbootHandler(FastbootDevice * device,const std::vector<std::string> &)406 bool RebootFastbootHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
407     auto result = device->WriteStatus(FastbootResult::OKAY, "Rebooting fastboot");
408     android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
409     device->CloseDevice();
410     TEMP_FAILURE_RETRY(pause());
411     return result;
412 }
413 
EnterRecovery()414 static bool EnterRecovery() {
415     const char msg_switch_to_recovery = 'r';
416 
417     android::base::unique_fd sock(socket(AF_UNIX, SOCK_STREAM, 0));
418     if (sock < 0) {
419         PLOG(ERROR) << "Couldn't create sock";
420         return false;
421     }
422 
423     struct sockaddr_un addr = {.sun_family = AF_UNIX};
424     strncpy(addr.sun_path, "/dev/socket/recovery", sizeof(addr.sun_path) - 1);
425     if (connect(sock.get(), (struct sockaddr*)&addr, sizeof(addr)) < 0) {
426         PLOG(ERROR) << "Couldn't connect to recovery";
427         return false;
428     }
429     // Switch to recovery will not update the boot reason since it does not
430     // require a reboot.
431     auto ret = write(sock.get(), &msg_switch_to_recovery, sizeof(msg_switch_to_recovery));
432     if (ret != sizeof(msg_switch_to_recovery)) {
433         PLOG(ERROR) << "Couldn't write message to switch to recovery";
434         return false;
435     }
436 
437     return true;
438 }
439 
RebootRecoveryHandler(FastbootDevice * device,const std::vector<std::string> &)440 bool RebootRecoveryHandler(FastbootDevice* device, const std::vector<std::string>& /* args */) {
441     auto status = true;
442     if (EnterRecovery()) {
443         status = device->WriteStatus(FastbootResult::OKAY, "Rebooting to recovery");
444     } else {
445         status = device->WriteStatus(FastbootResult::FAIL, "Unable to reboot to recovery");
446     }
447     device->CloseDevice();
448     TEMP_FAILURE_RETRY(pause());
449     return status;
450 }
451 
452 // Helper class for opening a handle to a MetadataBuilder and writing the new
453 // partition table to the same place it was read.
454 class PartitionBuilder {
455   public:
456     explicit PartitionBuilder(FastbootDevice* device, const std::string& partition_name);
457 
458     bool Write();
Valid() const459     bool Valid() const { return !!builder_; }
operator ->() const460     MetadataBuilder* operator->() const { return builder_.get(); }
461 
462   private:
463     FastbootDevice* device_;
464     std::string super_device_;
465     uint32_t slot_number_;
466     std::unique_ptr<MetadataBuilder> builder_;
467 };
468 
PartitionBuilder(FastbootDevice * device,const std::string & partition_name)469 PartitionBuilder::PartitionBuilder(FastbootDevice* device, const std::string& partition_name)
470     : device_(device) {
471     std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
472     slot_number_ = android::fs_mgr::SlotNumberForSlotSuffix(slot_suffix);
473     auto super_device = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number_));
474     if (!super_device) {
475         return;
476     }
477     super_device_ = *super_device;
478     builder_ = MetadataBuilder::New(super_device_, slot_number_);
479 }
480 
Write()481 bool PartitionBuilder::Write() {
482     auto metadata = builder_->Export();
483     if (!metadata) {
484         return false;
485     }
486     return UpdateAllPartitionMetadata(device_, super_device_, *metadata.get());
487 }
488 
CreatePartitionHandler(FastbootDevice * device,const std::vector<std::string> & args)489 bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
490     if (args.size() < 3) {
491         return device->WriteFail("Invalid partition name and size");
492     }
493 
494     if (GetDeviceLockStatus()) {
495         return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
496     }
497 
498     uint64_t partition_size;
499     std::string partition_name = args[1];
500     if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
501         return device->WriteFail("Invalid partition size");
502     }
503 
504     PartitionBuilder builder(device, partition_name);
505     if (!builder.Valid()) {
506         return device->WriteFail("Could not open super partition");
507     }
508     // TODO(112433293) Disallow if the name is in the physical table as well.
509     if (builder->FindPartition(partition_name)) {
510         return device->WriteFail("Partition already exists");
511     }
512 
513     auto partition = builder->AddPartition(partition_name, 0);
514     if (!partition) {
515         return device->WriteFail("Failed to add partition");
516     }
517     if (!builder->ResizePartition(partition, partition_size)) {
518         builder->RemovePartition(partition_name);
519         return device->WriteFail("Not enough space for partition");
520     }
521     if (!builder.Write()) {
522         return device->WriteFail("Failed to write partition table");
523     }
524     return device->WriteOkay("Partition created");
525 }
526 
DeletePartitionHandler(FastbootDevice * device,const std::vector<std::string> & args)527 bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
528     if (args.size() < 2) {
529         return device->WriteFail("Invalid partition name and size");
530     }
531 
532     if (GetDeviceLockStatus()) {
533         return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
534     }
535 
536     std::string partition_name = args[1];
537 
538     PartitionBuilder builder(device, partition_name);
539     if (!builder.Valid()) {
540         return device->WriteFail("Could not open super partition");
541     }
542     builder->RemovePartition(partition_name);
543     if (!builder.Write()) {
544         return device->WriteFail("Failed to write partition table");
545     }
546     return device->WriteOkay("Partition deleted");
547 }
548 
ResizePartitionHandler(FastbootDevice * device,const std::vector<std::string> & args)549 bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
550     if (args.size() < 3) {
551         return device->WriteFail("Invalid partition name and size");
552     }
553 
554     if (GetDeviceLockStatus()) {
555         return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
556     }
557 
558     uint64_t partition_size;
559     std::string partition_name = args[1];
560     if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
561         return device->WriteFail("Invalid partition size");
562     }
563 
564     PartitionBuilder builder(device, partition_name);
565     if (!builder.Valid()) {
566         return device->WriteFail("Could not open super partition");
567     }
568 
569     auto partition = builder->FindPartition(partition_name);
570     if (!partition) {
571         return device->WriteFail("Partition does not exist");
572     }
573 
574     // Remove the updated flag to cancel any snapshots.
575     uint32_t attrs = partition->attributes();
576     partition->set_attributes(attrs & ~LP_PARTITION_ATTR_UPDATED);
577 
578     if (!builder->ResizePartition(partition, partition_size)) {
579         return device->WriteFail("Not enough space to resize partition");
580     }
581     if (!builder.Write()) {
582         return device->WriteFail("Failed to write partition table");
583     }
584     return device->WriteOkay("Partition resized");
585 }
586 
CancelPartitionSnapshot(FastbootDevice * device,const std::string & partition_name)587 void CancelPartitionSnapshot(FastbootDevice* device, const std::string& partition_name) {
588     PartitionBuilder builder(device, partition_name);
589     if (!builder.Valid()) return;
590 
591     auto partition = builder->FindPartition(partition_name);
592     if (!partition) return;
593 
594     // Remove the updated flag to cancel any snapshots.
595     uint32_t attrs = partition->attributes();
596     partition->set_attributes(attrs & ~LP_PARTITION_ATTR_UPDATED);
597 
598     builder.Write();
599 }
600 
FlashHandler(FastbootDevice * device,const std::vector<std::string> & args)601 bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) {
602     if (args.size() < 2) {
603         return device->WriteStatus(FastbootResult::FAIL, "Invalid arguments");
604     }
605 
606     if (GetDeviceLockStatus()) {
607         return device->WriteStatus(FastbootResult::FAIL,
608                                    "Flashing is not allowed on locked devices");
609     }
610 
611     const auto& partition_name = args[1];
612     if (IsProtectedPartitionDuringMerge(device, partition_name)) {
613         auto message = "Cannot flash " + partition_name + " while a snapshot update is in progress";
614         return device->WriteFail(message);
615     }
616 
617     if (LogicalPartitionExists(device, partition_name)) {
618         CancelPartitionSnapshot(device, partition_name);
619     }
620 
621     int ret = Flash(device, partition_name);
622     if (ret < 0) {
623         return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
624     }
625     if (partition_name == "userdata") {
626         PostWipeData();
627     }
628 
629     return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
630 }
631 
UpdateSuperHandler(FastbootDevice * device,const std::vector<std::string> & args)632 bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args) {
633     if (args.size() < 2) {
634         return device->WriteFail("Invalid arguments");
635     }
636 
637     if (GetDeviceLockStatus()) {
638         return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
639     }
640 
641     bool wipe = (args.size() >= 3 && args[2] == "wipe");
642     return UpdateSuper(device, args[1], wipe);
643 }
644 
IsLockedDsu()645 static bool IsLockedDsu() {
646     std::string active_dsu;
647     android::gsi::GetActiveDsu(&active_dsu);
648     return android::base::EndsWith(active_dsu, ".lock");
649 }
650 
GsiHandler(FastbootDevice * device,const std::vector<std::string> & args)651 bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) {
652     if (args.size() != 2) {
653         return device->WriteFail("Invalid arguments");
654     }
655 
656     AutoMountMetadata mount_metadata;
657     if (!mount_metadata) {
658         return device->WriteFail("Could not find GSI install");
659     }
660 
661     if (!android::gsi::IsGsiInstalled()) {
662         return device->WriteStatus(FastbootResult::FAIL, "No GSI is installed");
663     }
664 
665     if ((args[1] == "wipe" || args[1] == "disable") && GetDeviceLockStatus() && IsLockedDsu()) {
666         // Block commands that modify the states of locked DSU
667         return device->WriteFail("Command not available on locked DSU/devices");
668     }
669 
670     if (args[1] == "wipe") {
671         if (!android::gsi::UninstallGsi()) {
672             return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
673         }
674     } else if (args[1] == "disable") {
675         if (!android::gsi::DisableGsi()) {
676             return device->WriteStatus(FastbootResult::FAIL, strerror(errno));
677         }
678     } else if (args[1] == "status") {
679         std::string active_dsu;
680         if (!android::gsi::IsGsiRunning()) {
681             device->WriteInfo("Not running");
682         } else if (!android::gsi::GetActiveDsu(&active_dsu)) {
683             return device->WriteFail(strerror(errno));
684         } else {
685             device->WriteInfo("Running active DSU: " + active_dsu);
686         }
687     } else {
688         return device->WriteFail("Invalid arguments");
689     }
690     return device->WriteStatus(FastbootResult::OKAY, "Success");
691 }
692 
SnapshotUpdateHandler(FastbootDevice * device,const std::vector<std::string> & args)693 bool SnapshotUpdateHandler(FastbootDevice* device, const std::vector<std::string>& args) {
694     // Note that we use the HAL rather than mounting /metadata, since we want
695     // our results to match the bootloader.
696     auto hal = device->boot1_1();
697     if (!hal) return device->WriteFail("Not supported");
698 
699     // If no arguments, return the same thing as a getvar. Note that we get the
700     // HAL first so we can return "not supported" before we return the less
701     // specific error message below.
702     if (args.size() < 2 || args[1].empty()) {
703         std::string message;
704         if (!GetSnapshotUpdateStatus(device, {}, &message)) {
705             return device->WriteFail("Could not determine update status");
706         }
707         device->WriteInfo(message);
708         return device->WriteOkay("");
709     }
710 
711     MergeStatus status = hal->getSnapshotMergeStatus();
712 
713     if (args.size() != 2) {
714         return device->WriteFail("Invalid arguments");
715     }
716     if (args[1] == "cancel") {
717         switch (status) {
718             case MergeStatus::SNAPSHOTTED:
719             case MergeStatus::MERGING: {
720                 const auto ret = hal->SetSnapshotMergeStatus(MergeStatus::CANCELLED);
721                 if (!ret.success) {
722                     device->WriteFail("Failed to SetSnapshotMergeStatus(MergeStatus::CANCELLED) " +
723                                       ret.errMsg);
724                 }
725                 break;
726             }
727             default:
728                 break;
729         }
730     } else if (args[1] == "merge") {
731         if (status != MergeStatus::MERGING) {
732             return device->WriteFail("No snapshot merge is in progress");
733         }
734 
735         auto sm = SnapshotManager::New();
736         if (!sm) {
737             return device->WriteFail("Unable to create SnapshotManager");
738         }
739         if (!sm->FinishMergeInRecovery()) {
740             return device->WriteFail("Unable to finish snapshot merge");
741         }
742     } else {
743         return device->WriteFail("Invalid parameter to snapshot-update");
744     }
745     return device->WriteStatus(FastbootResult::OKAY, "Success");
746 }
747 
748 namespace {
749 // Helper of FetchHandler.
750 class PartitionFetcher {
751   public:
Fetch(FastbootDevice * device,const std::vector<std::string> & args)752     static bool Fetch(FastbootDevice* device, const std::vector<std::string>& args) {
753         if constexpr (!kEnableFetch) {
754             return device->WriteFail("Fetch is not allowed on user build");
755         }
756 
757         if (GetDeviceLockStatus()) {
758             return device->WriteFail("Fetch is not allowed on locked devices");
759         }
760 
761         PartitionFetcher fetcher(device, args);
762         if (fetcher.Open()) {
763             fetcher.Fetch();
764         }
765         CHECK(fetcher.ret_.has_value());
766         return *fetcher.ret_;
767     }
768 
769   private:
PartitionFetcher(FastbootDevice * device,const std::vector<std::string> & args)770     PartitionFetcher(FastbootDevice* device, const std::vector<std::string>& args)
771         : device_(device), args_(&args) {}
772     // Return whether the partition is successfully opened.
773     // If successfully opened, ret_ is left untouched. Otherwise, ret_ is set to the value
774     // that FetchHandler should return.
Open()775     bool Open() {
776         if (args_->size() < 2) {
777             ret_ = device_->WriteFail("Missing partition arg");
778             return false;
779         }
780 
781         partition_name_ = args_->at(1);
782         if (std::find(kAllowedPartitions.begin(), kAllowedPartitions.end(), partition_name_) ==
783             kAllowedPartitions.end()) {
784             ret_ = device_->WriteFail("Fetch is only allowed on [" +
785                                       android::base::Join(kAllowedPartitions, ", ") + "]");
786             return false;
787         }
788 
789         if (!OpenPartition(device_, partition_name_, &handle_, O_RDONLY)) {
790             ret_ = device_->WriteFail(
791                     android::base::StringPrintf("Cannot open %s", partition_name_.c_str()));
792             return false;
793         }
794 
795         partition_size_ = get_block_device_size(handle_.fd());
796         if (partition_size_ == 0) {
797             ret_ = device_->WriteOkay(android::base::StringPrintf("Partition %s has size 0",
798                                                                   partition_name_.c_str()));
799             return false;
800         }
801 
802         start_offset_ = 0;
803         if (args_->size() >= 3) {
804             if (!android::base::ParseUint(args_->at(2), &start_offset_)) {
805                 ret_ = device_->WriteFail("Invalid offset, must be integer");
806                 return false;
807             }
808             if (start_offset_ > std::numeric_limits<off64_t>::max()) {
809                 ret_ = device_->WriteFail(
810                         android::base::StringPrintf("Offset overflows: %" PRIx64, start_offset_));
811                 return false;
812             }
813         }
814         if (start_offset_ > partition_size_) {
815             ret_ = device_->WriteFail(android::base::StringPrintf(
816                     "Invalid offset 0x%" PRIx64 ", partition %s has size 0x%" PRIx64, start_offset_,
817                     partition_name_.c_str(), partition_size_));
818             return false;
819         }
820         uint64_t maximum_total_size_to_read = partition_size_ - start_offset_;
821         total_size_to_read_ = maximum_total_size_to_read;
822         if (args_->size() >= 4) {
823             if (!android::base::ParseUint(args_->at(3), &total_size_to_read_)) {
824                 ret_ = device_->WriteStatus(FastbootResult::FAIL, "Invalid size, must be integer");
825                 return false;
826             }
827         }
828         if (total_size_to_read_ == 0) {
829             ret_ = device_->WriteOkay("Read 0 bytes");
830             return false;
831         }
832         if (total_size_to_read_ > maximum_total_size_to_read) {
833             ret_ = device_->WriteFail(android::base::StringPrintf(
834                     "Invalid size to read 0x%" PRIx64 ", partition %s has size 0x%" PRIx64
835                     " and fetching from offset 0x%" PRIx64,
836                     total_size_to_read_, partition_name_.c_str(), partition_size_, start_offset_));
837             return false;
838         }
839 
840         if (total_size_to_read_ > kMaxFetchSizeDefault) {
841             ret_ = device_->WriteFail(android::base::StringPrintf(
842                     "Cannot fetch 0x%" PRIx64
843                     " bytes because it exceeds maximum transport size 0x%x",
844                     partition_size_, kMaxDownloadSizeDefault));
845             return false;
846         }
847 
848         return true;
849     }
850 
851     // Assume Open() returns true.
852     // After execution, ret_ is set to the value that FetchHandler should return.
Fetch()853     void Fetch() {
854         CHECK(start_offset_ <= std::numeric_limits<off64_t>::max());
855         if (lseek64(handle_.fd(), start_offset_, SEEK_SET) != static_cast<off64_t>(start_offset_)) {
856             ret_ = device_->WriteFail(android::base::StringPrintf(
857                     "On partition %s, unable to lseek(0x%" PRIx64 ": %s", partition_name_.c_str(),
858                     start_offset_, strerror(errno)));
859             return;
860         }
861 
862         if (!device_->WriteStatus(FastbootResult::DATA,
863                                   android::base::StringPrintf(
864                                           "%08x", static_cast<uint32_t>(total_size_to_read_)))) {
865             ret_ = false;
866             return;
867         }
868         uint64_t end_offset = start_offset_ + total_size_to_read_;
869         std::vector<char> buf(1_MiB);
870         uint64_t current_offset = start_offset_;
871         while (current_offset < end_offset) {
872             // On any error, exit. We can't return a status message to the driver because
873             // we are in the middle of writing data, so just let the driver guess what's wrong
874             // by ending the data stream prematurely.
875             uint64_t remaining = end_offset - current_offset;
876             uint64_t chunk_size = std::min<uint64_t>(buf.size(), remaining);
877             if (!android::base::ReadFully(handle_.fd(), buf.data(), chunk_size)) {
878                 PLOG(ERROR) << std::hex << "Unable to read 0x" << chunk_size << " bytes from "
879                             << partition_name_ << " @ offset 0x" << current_offset;
880                 ret_ = false;
881                 return;
882             }
883             if (!device_->HandleData(false /* is read */, buf.data(), chunk_size)) {
884                 PLOG(ERROR) << std::hex << "Unable to send 0x" << chunk_size << " bytes of "
885                             << partition_name_ << " @ offset 0x" << current_offset;
886                 ret_ = false;
887                 return;
888             }
889             current_offset += chunk_size;
890         }
891 
892         ret_ = device_->WriteOkay(android::base::StringPrintf(
893                 "Fetched %s (offset=0x%" PRIx64 ", size=0x%" PRIx64, partition_name_.c_str(),
894                 start_offset_, total_size_to_read_));
895     }
896 
897     static constexpr std::array<const char*, 3> kAllowedPartitions{
898             "vendor_boot",
899             "vendor_boot_a",
900             "vendor_boot_b",
901     };
902 
903     FastbootDevice* device_;
904     const std::vector<std::string>* args_ = nullptr;
905     std::string partition_name_;
906     PartitionHandle handle_;
907     uint64_t partition_size_ = 0;
908     uint64_t start_offset_ = 0;
909     uint64_t total_size_to_read_ = 0;
910 
911     // What FetchHandler should return.
912     std::optional<bool> ret_ = std::nullopt;
913 };
914 }  // namespace
915 
FetchHandler(FastbootDevice * device,const std::vector<std::string> & args)916 bool FetchHandler(FastbootDevice* device, const std::vector<std::string>& args) {
917     return PartitionFetcher::Fetch(device, args);
918 }
919