Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab8f4661 authored by David Anderson's avatar David Anderson
Browse files

fastboot: Implement helper commands for Virtual A/B.

This introduces two new commands to the fastboot protocol:

  - getvar snapshot-update-status - Return "none", "snapshotted", or
    "merging" depending on the current status set by the boot control
    HAL.
  - snapshot-update [cancel] - Cancel any pending snapshot-based updates
    via the boot control HAL. After this, the HAL should return
    MergeStatus::CANCELLED and "update-merge-status" should be "none".
    If no argument is specified, the snapshot-update-status is returned
    via an INFO response.

Bootloaders are expected to implement this in a manner consistent with
the boot control HAL.

Fastboot-based tooling should expect wipes of userdata to fail when
update-merge-status returns "merging". Thus, the force flag now cancel
any pending snapshots.

Bug: 139154945
Test: fastboot getvar snapshot-update-status
      fastboot snapshot-update cancel
      fastboot snapshot-update

Change-Id: Idc423fe7656b212e929e64eb0e6b85b453e0e8dc
parent 32e7325c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ cc_binary {

    shared_libs: [
        "android.hardware.boot@1.0",
        "android.hardware.boot@1.1",
        "android.hardware.fastboot@1.0",
        "android.hardware.health@2.0",
        "libadbd",
+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@
#define FB_CMD_UPDATE_SUPER "update-super"
#define FB_CMD_OEM "oem"
#define FB_CMD_GSI "gsi"
#define FB_CMD_SNAPSHOT_UPDATE "snapshot-update"

#define RESPONSE_OKAY "OKAY"
#define RESPONSE_FAIL "FAIL"
@@ -66,3 +67,4 @@
#define FB_VAR_BATTERY_VOLTAGE "battery-voltage"
#define FB_VAR_BATTERY_SOC_OK "battery-soc-ok"
#define FB_VAR_SUPER_PARTITION_NAME "super-partition-name"
#define FB_VAR_SNAPSHOT_UPDATE_STATUS "snapshot-update-status"
+42 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <android/hardware/boot/1.1/IBootControl.h>
#include <cutils/android_reboot.h>
#include <ext4_utils/wipe.h>
#include <fs_mgr.h>
@@ -44,8 +45,10 @@ using ::android::hardware::hidl_string;
using ::android::hardware::boot::V1_0::BoolResult;
using ::android::hardware::boot::V1_0::CommandResult;
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 IBootControl1_1 = ::android::hardware::boot::V1_1::IBootControl;

struct VariableHandlers {
    // Callback to retrieve the value of a single variable.
@@ -101,7 +104,8 @@ bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args)
            {FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
            {FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
            {FB_VAR_HW_REVISION, {GetHardwareRevision, nullptr}},
            {FB_VAR_SUPER_PARTITION_NAME, {GetSuperPartitionName, nullptr}}};
            {FB_VAR_SUPER_PARTITION_NAME, {GetSuperPartitionName, nullptr}},
            {FB_VAR_SNAPSHOT_UPDATE_STATUS, {GetSnapshotUpdateStatus, nullptr}}};

    if (args.size() < 2) {
        return device->WriteFail("Missing argument");
@@ -547,3 +551,40 @@ bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    }
    return device->WriteStatus(FastbootResult::OKAY, "Success");
}

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();
    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.
    if (args.size() < 2 || args[1].empty()) {
        std::string message;
        if (!GetSnapshotUpdateStatus(device, {}, &message)) {
            return device->WriteFail("Could not determine update status");
        }
        device->WriteInfo(message);
        return device->WriteOkay("");
    }

    if (args.size() != 2 || args[1] != "cancel") {
        return device->WriteFail("Invalid arguments");
    }

    MergeStatus status = hal11->getSnapshotMergeStatus();
    switch (status) {
        case MergeStatus::SNAPSHOTTED:
        case MergeStatus::MERGING:
            hal11->setSnapshotMergeStatus(MergeStatus::CANCELLED);
            break;
        default:
            break;
    }
    return device->WriteStatus(FastbootResult::OKAY, "Success");
}
+1 −0
Original line number Diff line number Diff line
@@ -49,3 +49,4 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin
bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool OemCmdHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool GsiHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool SnapshotUpdateHandler(FastbootDevice* device, const std::vector<std::string>& args);
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ FastbootDevice::FastbootDevice()
              {FB_CMD_UPDATE_SUPER, UpdateSuperHandler},
              {FB_CMD_OEM, OemCmdHandler},
              {FB_CMD_GSI, GsiHandler},
              {FB_CMD_SNAPSHOT_UPDATE, SnapshotUpdateHandler},
      }),
      transport_(std::make_unique<ClientUsbTransport>()),
      boot_control_hal_(IBootControl::getService()),
Loading