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