Loading fastboot/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -137,12 +137,14 @@ cc_binary { "libhidlbase", "liblog", "liblp", "libprotobuf-cpp-lite", "libsparse", "libutils", ], static_libs: [ "libhealthhalutils", "libsnapshot_nobinder", ], header_libs: [ Loading fastboot/device/commands.cpp +87 −15 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <sys/socket.h> #include <sys/un.h> #include <unordered_set> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/properties.h> Loading @@ -33,6 +35,7 @@ #include <libgsi/libgsi.h> #include <liblp/builder.h> #include <liblp/liblp.h> #include <libsnapshot/snapshot.h> #include <uuid/uuid.h> #include "constants.h" Loading @@ -48,6 +51,7 @@ using ::android::hardware::boot::V1_0::Slot; using ::android::hardware::boot::V1_1::MergeStatus; using ::android::hardware::fastboot::V1_0::Result; using ::android::hardware::fastboot::V1_0::Status; using android::snapshot::SnapshotManager; using IBootControl1_1 = ::android::hardware::boot::V1_1::IBootControl; struct VariableHandlers { Loading @@ -57,6 +61,24 @@ struct VariableHandlers { std::function<std::vector<std::vector<std::string>>(FastbootDevice*)> get_all_args; }; static bool IsSnapshotUpdateInProgress(FastbootDevice* device) { auto hal = device->boot1_1(); if (!hal) { return false; } auto merge_status = hal->getSnapshotMergeStatus(); return merge_status == MergeStatus::SNAPSHOTTED || merge_status == MergeStatus::MERGING; } static bool IsProtectedPartitionDuringMerge(FastbootDevice* device, const std::string& name) { static const std::unordered_set<std::string> ProtectedPartitionsDuringMerge = { "userdata", "metadata", "misc"}; if (ProtectedPartitionsDuringMerge.count(name) == 0) { return false; } return IsSnapshotUpdateInProgress(device); } static void GetAllVars(FastbootDevice* device, const std::string& name, const VariableHandlers& handlers) { if (!handlers.get_all_args) { Loading Loading @@ -143,8 +165,14 @@ bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) return device->WriteStatus(FastbootResult::FAIL, "Erase is not allowed on locked devices"); } const auto& partition_name = args[1]; if (IsProtectedPartitionDuringMerge(device, partition_name)) { auto message = "Cannot erase " + partition_name + " while a snapshot update is in progress"; return device->WriteFail(message); } PartitionHandle handle; if (!OpenPartition(device, args[1], &handle)) { if (!OpenPartition(device, partition_name, &handle)) { return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist"); } if (wipe_block_device(handle.fd(), get_block_device_size(handle.fd())) == 0) { Loading Loading @@ -209,9 +237,9 @@ bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& ar "set_active command is not allowed on locked devices"); } // Slot suffix needs to be between 'a' and 'z'. Slot slot; if (!GetSlotNumber(args[1], &slot)) { // Slot suffix needs to be between 'a' and 'z'. return device->WriteStatus(FastbootResult::FAIL, "Bad slot suffix"); } Loading @@ -224,6 +252,32 @@ bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& ar if (slot >= boot_control_hal->getNumberSlots()) { return device->WriteStatus(FastbootResult::FAIL, "Slot out of range"); } // If the slot is not changing, do nothing. if (slot == boot_control_hal->getCurrentSlot()) { return device->WriteOkay(""); } // Check how to handle the current snapshot state. if (auto hal11 = device->boot1_1()) { auto merge_status = hal11->getSnapshotMergeStatus(); if (merge_status == MergeStatus::MERGING) { return device->WriteFail("Cannot change slots while a snapshot update is in progress"); } // Note: we allow the slot change if the state is SNAPSHOTTED. First- // stage init does not have access to the HAL, and uses the slot number // and /metadata OTA state to determine whether a slot change occurred. // Booting into the old slot would erase the OTA, and switching A->B->A // would simply resume it if no boots occur in between. Re-flashing // partitions implicitly cancels the OTA, so leaving the state as-is is // safe. if (merge_status == MergeStatus::SNAPSHOTTED) { device->WriteInfo( "Changing the active slot with a snapshot applied may cancel the" " update."); } } CommandResult ret; auto cb = [&ret](CommandResult result) { ret = result; }; auto result = boot_control_hal->setActiveBootSlot(slot, cb); Loading Loading @@ -467,6 +521,11 @@ bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) } const auto& partition_name = args[1]; if (IsProtectedPartitionDuringMerge(device, partition_name)) { auto message = "Cannot flash " + partition_name + " while a snapshot update is in progress"; return device->WriteFail(message); } if (LogicalPartitionExists(device, partition_name)) { CancelPartitionSnapshot(device, partition_name); } Loading Loading @@ -556,12 +615,9 @@ bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) { bool SnapshotUpdateHandler(FastbootDevice* device, const std::vector<std::string>& args) { // Note that we use the HAL rather than mounting /metadata, since we want // our results to match the bootloader. auto hal = device->boot_control_hal(); auto hal = device->boot1_1(); if (!hal) return device->WriteFail("Not supported"); android::sp<IBootControl1_1> hal11 = IBootControl1_1::castFrom(hal); if (!hal11) return device->WriteFail("Not supported"); // If no arguments, return the same thing as a getvar. Note that we get the // HAL first so we can return "not supported" before we return the less // specific error message below. Loading @@ -574,18 +630,34 @@ bool SnapshotUpdateHandler(FastbootDevice* device, const std::vector<std::string return device->WriteOkay(""); } if (args.size() != 2 || args[1] != "cancel") { MergeStatus status = hal->getSnapshotMergeStatus(); if (args.size() != 2) { return device->WriteFail("Invalid arguments"); } MergeStatus status = hal11->getSnapshotMergeStatus(); if (args[1] == "cancel") { switch (status) { case MergeStatus::SNAPSHOTTED: case MergeStatus::MERGING: hal11->setSnapshotMergeStatus(MergeStatus::CANCELLED); hal->setSnapshotMergeStatus(MergeStatus::CANCELLED); break; default: break; } } else if (args[1] == "merge") { if (status != MergeStatus::MERGING) { return device->WriteFail("No snapshot merge is in progress"); } auto sm = SnapshotManager::NewForFirstStageMount(); if (!sm) { return device->WriteFail("Unable to create SnapshotManager"); } if (!sm->HandleImminentDataWipe()) { return device->WriteFail("Unable to finish snapshot merge"); } } else { return device->WriteFail("Invalid parameter to snapshot-update"); } return device->WriteStatus(FastbootResult::OKAY, "Success"); } fastboot/device/fastboot_device.cpp +5 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,11 @@ FastbootDevice::FastbootDevice() boot_control_hal_(IBootControl::getService()), health_hal_(get_health_service()), fastboot_hal_(IFastboot::getService()), active_slot_("") {} active_slot_("") { if (boot_control_hal_) { boot1_1_ = android::hardware::boot::V1_1::IBootControl::castFrom(boot_control_hal_); } } FastbootDevice::~FastbootDevice() { CloseDevice(); Loading fastboot/device/fastboot_device.h +3 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <vector> #include <android/hardware/boot/1.0/IBootControl.h> #include <android/hardware/boot/1.1/IBootControl.h> #include <android/hardware/fastboot/1.0/IFastboot.h> #include <android/hardware/health/2.0/IHealth.h> Loading Loading @@ -51,6 +52,7 @@ class FastbootDevice { android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal() { return boot_control_hal_; } android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1() { return boot1_1_; } android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal() { return fastboot_hal_; } Loading @@ -63,6 +65,7 @@ class FastbootDevice { std::unique_ptr<Transport> transport_; android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal_; android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1_; android::sp<android::hardware::health::V2_0::IHealth> health_hal_; android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal_; std::vector<char> download_data_; Loading fastboot/device/variables.cpp +2 −8 Original line number Diff line number Diff line Loading @@ -432,19 +432,13 @@ bool GetSnapshotUpdateStatus(FastbootDevice* device, const std::vector<std::stri std::string* message) { // Note that we use the HAL rather than mounting /metadata, since we want // our results to match the bootloader. auto hal = device->boot_control_hal(); auto hal = device->boot1_1(); if (!hal) { *message = "not supported"; return false; } android::sp<IBootControl1_1> hal11 = IBootControl1_1::castFrom(hal); if (!hal11) { *message = "not supported"; return false; } MergeStatus status = hal11->getSnapshotMergeStatus(); MergeStatus status = hal->getSnapshotMergeStatus(); switch (status) { case MergeStatus::SNAPSHOTTED: *message = "snapshotted"; Loading Loading
fastboot/Android.bp +2 −0 Original line number Diff line number Diff line Loading @@ -137,12 +137,14 @@ cc_binary { "libhidlbase", "liblog", "liblp", "libprotobuf-cpp-lite", "libsparse", "libutils", ], static_libs: [ "libhealthhalutils", "libsnapshot_nobinder", ], header_libs: [ Loading
fastboot/device/commands.cpp +87 −15 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #include <sys/socket.h> #include <sys/un.h> #include <unordered_set> #include <android-base/logging.h> #include <android-base/parseint.h> #include <android-base/properties.h> Loading @@ -33,6 +35,7 @@ #include <libgsi/libgsi.h> #include <liblp/builder.h> #include <liblp/liblp.h> #include <libsnapshot/snapshot.h> #include <uuid/uuid.h> #include "constants.h" Loading @@ -48,6 +51,7 @@ using ::android::hardware::boot::V1_0::Slot; using ::android::hardware::boot::V1_1::MergeStatus; using ::android::hardware::fastboot::V1_0::Result; using ::android::hardware::fastboot::V1_0::Status; using android::snapshot::SnapshotManager; using IBootControl1_1 = ::android::hardware::boot::V1_1::IBootControl; struct VariableHandlers { Loading @@ -57,6 +61,24 @@ struct VariableHandlers { std::function<std::vector<std::vector<std::string>>(FastbootDevice*)> get_all_args; }; static bool IsSnapshotUpdateInProgress(FastbootDevice* device) { auto hal = device->boot1_1(); if (!hal) { return false; } auto merge_status = hal->getSnapshotMergeStatus(); return merge_status == MergeStatus::SNAPSHOTTED || merge_status == MergeStatus::MERGING; } static bool IsProtectedPartitionDuringMerge(FastbootDevice* device, const std::string& name) { static const std::unordered_set<std::string> ProtectedPartitionsDuringMerge = { "userdata", "metadata", "misc"}; if (ProtectedPartitionsDuringMerge.count(name) == 0) { return false; } return IsSnapshotUpdateInProgress(device); } static void GetAllVars(FastbootDevice* device, const std::string& name, const VariableHandlers& handlers) { if (!handlers.get_all_args) { Loading Loading @@ -143,8 +165,14 @@ bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) return device->WriteStatus(FastbootResult::FAIL, "Erase is not allowed on locked devices"); } const auto& partition_name = args[1]; if (IsProtectedPartitionDuringMerge(device, partition_name)) { auto message = "Cannot erase " + partition_name + " while a snapshot update is in progress"; return device->WriteFail(message); } PartitionHandle handle; if (!OpenPartition(device, args[1], &handle)) { if (!OpenPartition(device, partition_name, &handle)) { return device->WriteStatus(FastbootResult::FAIL, "Partition doesn't exist"); } if (wipe_block_device(handle.fd(), get_block_device_size(handle.fd())) == 0) { Loading Loading @@ -209,9 +237,9 @@ bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& ar "set_active command is not allowed on locked devices"); } // Slot suffix needs to be between 'a' and 'z'. Slot slot; if (!GetSlotNumber(args[1], &slot)) { // Slot suffix needs to be between 'a' and 'z'. return device->WriteStatus(FastbootResult::FAIL, "Bad slot suffix"); } Loading @@ -224,6 +252,32 @@ bool SetActiveHandler(FastbootDevice* device, const std::vector<std::string>& ar if (slot >= boot_control_hal->getNumberSlots()) { return device->WriteStatus(FastbootResult::FAIL, "Slot out of range"); } // If the slot is not changing, do nothing. if (slot == boot_control_hal->getCurrentSlot()) { return device->WriteOkay(""); } // Check how to handle the current snapshot state. if (auto hal11 = device->boot1_1()) { auto merge_status = hal11->getSnapshotMergeStatus(); if (merge_status == MergeStatus::MERGING) { return device->WriteFail("Cannot change slots while a snapshot update is in progress"); } // Note: we allow the slot change if the state is SNAPSHOTTED. First- // stage init does not have access to the HAL, and uses the slot number // and /metadata OTA state to determine whether a slot change occurred. // Booting into the old slot would erase the OTA, and switching A->B->A // would simply resume it if no boots occur in between. Re-flashing // partitions implicitly cancels the OTA, so leaving the state as-is is // safe. if (merge_status == MergeStatus::SNAPSHOTTED) { device->WriteInfo( "Changing the active slot with a snapshot applied may cancel the" " update."); } } CommandResult ret; auto cb = [&ret](CommandResult result) { ret = result; }; auto result = boot_control_hal->setActiveBootSlot(slot, cb); Loading Loading @@ -467,6 +521,11 @@ bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args) } const auto& partition_name = args[1]; if (IsProtectedPartitionDuringMerge(device, partition_name)) { auto message = "Cannot flash " + partition_name + " while a snapshot update is in progress"; return device->WriteFail(message); } if (LogicalPartitionExists(device, partition_name)) { CancelPartitionSnapshot(device, partition_name); } Loading Loading @@ -556,12 +615,9 @@ bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) { bool SnapshotUpdateHandler(FastbootDevice* device, const std::vector<std::string>& args) { // Note that we use the HAL rather than mounting /metadata, since we want // our results to match the bootloader. auto hal = device->boot_control_hal(); auto hal = device->boot1_1(); if (!hal) return device->WriteFail("Not supported"); android::sp<IBootControl1_1> hal11 = IBootControl1_1::castFrom(hal); if (!hal11) return device->WriteFail("Not supported"); // If no arguments, return the same thing as a getvar. Note that we get the // HAL first so we can return "not supported" before we return the less // specific error message below. Loading @@ -574,18 +630,34 @@ bool SnapshotUpdateHandler(FastbootDevice* device, const std::vector<std::string return device->WriteOkay(""); } if (args.size() != 2 || args[1] != "cancel") { MergeStatus status = hal->getSnapshotMergeStatus(); if (args.size() != 2) { return device->WriteFail("Invalid arguments"); } MergeStatus status = hal11->getSnapshotMergeStatus(); if (args[1] == "cancel") { switch (status) { case MergeStatus::SNAPSHOTTED: case MergeStatus::MERGING: hal11->setSnapshotMergeStatus(MergeStatus::CANCELLED); hal->setSnapshotMergeStatus(MergeStatus::CANCELLED); break; default: break; } } else if (args[1] == "merge") { if (status != MergeStatus::MERGING) { return device->WriteFail("No snapshot merge is in progress"); } auto sm = SnapshotManager::NewForFirstStageMount(); if (!sm) { return device->WriteFail("Unable to create SnapshotManager"); } if (!sm->HandleImminentDataWipe()) { return device->WriteFail("Unable to finish snapshot merge"); } } else { return device->WriteFail("Invalid parameter to snapshot-update"); } return device->WriteStatus(FastbootResult::OKAY, "Success"); }
fastboot/device/fastboot_device.cpp +5 −1 Original line number Diff line number Diff line Loading @@ -60,7 +60,11 @@ FastbootDevice::FastbootDevice() boot_control_hal_(IBootControl::getService()), health_hal_(get_health_service()), fastboot_hal_(IFastboot::getService()), active_slot_("") {} active_slot_("") { if (boot_control_hal_) { boot1_1_ = android::hardware::boot::V1_1::IBootControl::castFrom(boot_control_hal_); } } FastbootDevice::~FastbootDevice() { CloseDevice(); Loading
fastboot/device/fastboot_device.h +3 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <vector> #include <android/hardware/boot/1.0/IBootControl.h> #include <android/hardware/boot/1.1/IBootControl.h> #include <android/hardware/fastboot/1.0/IFastboot.h> #include <android/hardware/health/2.0/IHealth.h> Loading Loading @@ -51,6 +52,7 @@ class FastbootDevice { android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal() { return boot_control_hal_; } android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1() { return boot1_1_; } android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal() { return fastboot_hal_; } Loading @@ -63,6 +65,7 @@ class FastbootDevice { std::unique_ptr<Transport> transport_; android::sp<android::hardware::boot::V1_0::IBootControl> boot_control_hal_; android::sp<android::hardware::boot::V1_1::IBootControl> boot1_1_; android::sp<android::hardware::health::V2_0::IHealth> health_hal_; android::sp<android::hardware::fastboot::V1_0::IFastboot> fastboot_hal_; std::vector<char> download_data_; Loading
fastboot/device/variables.cpp +2 −8 Original line number Diff line number Diff line Loading @@ -432,19 +432,13 @@ bool GetSnapshotUpdateStatus(FastbootDevice* device, const std::vector<std::stri std::string* message) { // Note that we use the HAL rather than mounting /metadata, since we want // our results to match the bootloader. auto hal = device->boot_control_hal(); auto hal = device->boot1_1(); if (!hal) { *message = "not supported"; return false; } android::sp<IBootControl1_1> hal11 = IBootControl1_1::castFrom(hal); if (!hal11) { *message = "not supported"; return false; } MergeStatus status = hal11->getSnapshotMergeStatus(); MergeStatus status = hal->getSnapshotMergeStatus(); switch (status) { case MergeStatus::SNAPSHOTTED: *message = "snapshotted"; Loading