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

Commit 0160700f authored by David Anderson's avatar David Anderson Committed by android-build-merger
Browse files

Merge "fastbootd: Support two super partitions for retrofit devices."

am: 66a6d887

Change-Id: I02835611f7662f3f7e3c13786d6db60ca1af4062
parents 1904e1ee 66a6d887
Loading
Loading
Loading
Loading
+14 −16
Original line number Diff line number Diff line
@@ -322,7 +322,7 @@ bool RebootRecoveryHandler(FastbootDevice* device, const std::vector<std::string
// partition table to the same place it was read.
class PartitionBuilder {
  public:
    explicit PartitionBuilder(FastbootDevice* device);
    explicit PartitionBuilder(FastbootDevice* device, const std::string& partition_name);

    bool Write();
    bool Valid() const { return !!builder_; }
@@ -330,19 +330,19 @@ class PartitionBuilder {

  private:
    std::string super_device_;
    uint32_t slot_number_;
    std::unique_ptr<MetadataBuilder> builder_;
};

PartitionBuilder::PartitionBuilder(FastbootDevice* device) {
    auto super_device = FindPhysicalPartition(fs_mgr_get_super_partition_name());
PartitionBuilder::PartitionBuilder(FastbootDevice* device, const std::string& partition_name) {
    std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
    slot_number_ = SlotNumberForSlotSuffix(slot_suffix);
    auto super_device = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number_));
    if (!super_device) {
        return;
    }
    super_device_ = *super_device;

    std::string slot = device->GetCurrentSlot();
    uint32_t slot_number = SlotNumberForSlotSuffix(slot);
    builder_ = MetadataBuilder::New(super_device_, slot_number);
    builder_ = MetadataBuilder::New(super_device_, slot_number_);
}

bool PartitionBuilder::Write() {
@@ -350,11 +350,7 @@ bool PartitionBuilder::Write() {
    if (!metadata) {
        return false;
    }
    bool ok = true;
    for (uint32_t i = 0; i < metadata->geometry.metadata_slot_count; i++) {
        ok &= UpdatePartitionTable(super_device_, *metadata.get(), i);
    }
    return ok;
    return UpdateAllPartitionMetadata(super_device_, *metadata.get());
}

bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
@@ -372,7 +368,7 @@ bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::strin
        return device->WriteFail("Invalid partition size");
    }

    PartitionBuilder builder(device);
    PartitionBuilder builder(device, partition_name);
    if (!builder.Valid()) {
        return device->WriteFail("Could not open super partition");
    }
@@ -404,11 +400,13 @@ bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::strin
        return device->WriteStatus(FastbootResult::FAIL, "Command not available on locked devices");
    }

    PartitionBuilder builder(device);
    std::string partition_name = args[1];

    PartitionBuilder builder(device, partition_name);
    if (!builder.Valid()) {
        return device->WriteFail("Could not open super partition");
    }
    builder->RemovePartition(args[1]);
    builder->RemovePartition(partition_name);
    if (!builder.Write()) {
        return device->WriteFail("Failed to write partition table");
    }
@@ -430,7 +428,7 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin
        return device->WriteFail("Invalid partition size");
    }

    PartitionBuilder builder(device);
    PartitionBuilder builder(device, partition_name);
    if (!builder.Valid()) {
        return device->WriteFail("Could not open super partition");
    }
+1 −6
Original line number Diff line number Diff line
@@ -183,12 +183,7 @@ bool UpdateSuper(FastbootDevice* device, const std::string& super_name, bool wip
    }

    // Write the new table to every metadata slot.
    bool ok = true;
    for (size_t i = 0; i < new_metadata->geometry.metadata_slot_count; i++) {
        ok &= UpdatePartitionTable(super_name, *new_metadata.get(), i);
    }

    if (!ok) {
    if (!UpdateAllPartitionMetadata(super_name, *new_metadata.get())) {
        return device->WriteFail("Unable to write new partition table");
    }
    return device->WriteOkay("Successfully updated partition table");
+71 −20
Original line number Diff line number Diff line
@@ -23,9 +23,11 @@

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>

#include "fastboot_device.h"
@@ -35,7 +37,9 @@ using namespace std::chrono_literals;
using android::base::unique_fd;
using android::hardware::boot::V1_0::Slot;

static bool OpenPhysicalPartition(const std::string& name, PartitionHandle* handle) {
namespace {

bool OpenPhysicalPartition(const std::string& name, PartitionHandle* handle) {
    std::optional<std::string> path = FindPhysicalPartition(name);
    if (!path) {
        return false;
@@ -44,28 +48,31 @@ static bool OpenPhysicalPartition(const std::string& name, PartitionHandle* hand
    return true;
}

static bool OpenLogicalPartition(const std::string& name, const std::string& slot,
bool OpenLogicalPartition(FastbootDevice* device, const std::string& partition_name,
                          PartitionHandle* handle) {
    std::optional<std::string> path = FindPhysicalPartition(fs_mgr_get_super_partition_name());
    std::string slot_suffix = GetSuperSlotSuffix(device, partition_name);
    uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
    auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number));
    if (!path) {
        return false;
    }
    uint32_t slot_number = SlotNumberForSlotSuffix(slot);
    std::string dm_path;
    if (!CreateLogicalPartition(path->c_str(), slot_number, name, true, 5s, &dm_path)) {
        LOG(ERROR) << "Could not map partition: " << name;
    if (!CreateLogicalPartition(path->c_str(), slot_number, partition_name, true, 5s, &dm_path)) {
        LOG(ERROR) << "Could not map partition: " << partition_name;
        return false;
    }
    auto closer = [name]() -> void { DestroyLogicalPartition(name, 5s); };
    auto closer = [partition_name]() -> void { DestroyLogicalPartition(partition_name, 5s); };
    *handle = PartitionHandle(dm_path, std::move(closer));
    return true;
}

}  // namespace

bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle) {
    // We prioritize logical partitions over physical ones, and do this
    // consistently for other partition operations (like getvar:partition-size).
    if (LogicalPartitionExists(name, device->GetCurrentSlot())) {
        if (!OpenLogicalPartition(name, device->GetCurrentSlot(), handle)) {
    if (LogicalPartitionExists(device, name)) {
        if (!OpenLogicalPartition(device, name, handle)) {
            return false;
        }
    } else if (!OpenPhysicalPartition(name, handle)) {
@@ -104,14 +111,14 @@ static const LpMetadataPartition* FindLogicalPartition(const LpMetadata& metadat
    return nullptr;
}

bool LogicalPartitionExists(const std::string& name, const std::string& slot_suffix,
                            bool* is_zero_length) {
    auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name());
bool LogicalPartitionExists(FastbootDevice* device, const std::string& name, bool* is_zero_length) {
    std::string slot_suffix = GetSuperSlotSuffix(device, name);
    uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
    auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name(slot_number));
    if (!path) {
        return false;
    }

    uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
    std::unique_ptr<LpMetadata> metadata = ReadMetadata(path->c_str(), slot_number);
    if (!metadata) {
        return false;
@@ -154,12 +161,29 @@ std::vector<std::string> ListPartitions(FastbootDevice* device) {
        }
    }

    // Next get logical partitions.
    if (auto path = FindPhysicalPartition(fs_mgr_get_super_partition_name())) {
        uint32_t slot_number = SlotNumberForSlotSuffix(device->GetCurrentSlot());
        if (auto metadata = ReadMetadata(path->c_str(), slot_number)) {
    // Find metadata in each super partition (on retrofit devices, there will
    // be two).
    std::vector<std::unique_ptr<LpMetadata>> metadata_list;

    uint32_t current_slot = SlotNumberForSlotSuffix(device->GetCurrentSlot());
    std::string super_name = fs_mgr_get_super_partition_name(current_slot);
    if (auto metadata = ReadMetadata(super_name, current_slot)) {
        metadata_list.emplace_back(std::move(metadata));
    }

    uint32_t other_slot = (current_slot == 0) ? 1 : 0;
    std::string other_super = fs_mgr_get_super_partition_name(other_slot);
    if (super_name != other_super) {
        if (auto metadata = ReadMetadata(other_super, other_slot)) {
            metadata_list.emplace_back(std::move(metadata));
        }
    }

    for (const auto& metadata : metadata_list) {
        for (const auto& partition : metadata->partitions) {
            std::string partition_name = GetPartitionName(partition);
            if (std::find(partitions.begin(), partitions.end(), partition_name) ==
                partitions.end()) {
                partitions.emplace_back(partition_name);
            }
        }
@@ -175,3 +199,30 @@ bool GetDeviceLockStatus() {
    }
    return cmdline.find("androidboot.verifiedbootstate=orange") == std::string::npos;
}

bool UpdateAllPartitionMetadata(const std::string& super_name,
                                const android::fs_mgr::LpMetadata& metadata) {
    bool ok = true;
    for (size_t i = 0; i < metadata.geometry.metadata_slot_count; i++) {
        ok &= UpdatePartitionTable(super_name, metadata, i);
    }
    return ok;
}

std::string GetSuperSlotSuffix(FastbootDevice* device, const std::string& partition_name) {
    // If the super partition does not have a slot suffix, this is not a
    // retrofit device, and we should take the current slot.
    std::string current_slot_suffix = device->GetCurrentSlot();
    uint32_t current_slot_number = SlotNumberForSlotSuffix(current_slot_suffix);
    std::string super_partition = fs_mgr_get_super_partition_name(current_slot_number);
    if (GetPartitionSlotSuffix(super_partition).empty()) {
        return current_slot_suffix;
    }

    // Otherwise, infer the slot from the partition name.
    std::string slot_suffix = GetPartitionSlotSuffix(partition_name);
    if (!slot_suffix.empty()) {
        return slot_suffix;
    }
    return current_slot_suffix;
}
+12 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@

#include <android-base/unique_fd.h>
#include <android/hardware/boot/1.0/IBootControl.h>
#include <liblp/liblp.h>

// Logical partitions are only mapped to a block device as needed, and
// immediately unmapped when no longer needed. In order to enforce this we
@@ -52,10 +53,20 @@ class PartitionHandle {

class FastbootDevice;

// On normal devices, the super partition is always named "super". On retrofit
// devices, the name must be derived from the partition name or current slot.
// This helper assists in choosing the correct super for a given partition
// name.
std::string GetSuperSlotSuffix(FastbootDevice* device, const std::string& partition_name);

std::optional<std::string> FindPhysicalPartition(const std::string& name);
bool LogicalPartitionExists(const std::string& name, const std::string& slot_suffix,
bool LogicalPartitionExists(FastbootDevice* device, const std::string& name,
                            bool* is_zero_length = nullptr);
bool OpenPartition(FastbootDevice* device, const std::string& name, PartitionHandle* handle);
bool GetSlotNumber(const std::string& slot, android::hardware::boot::V1_0::Slot* number);
std::vector<std::string> ListPartitions(FastbootDevice* device);
bool GetDeviceLockStatus();

// Update all copies of metadata.
bool UpdateAllPartitionMetadata(const std::string& super_name,
                                const android::fs_mgr::LpMetadata& metadata);
+4 −7
Original line number Diff line number Diff line
@@ -271,8 +271,7 @@ bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args,
        return true;
    }
    std::string partition_name = args[0] + slot_suffix;
    if (FindPhysicalPartition(partition_name) ||
        LogicalPartitionExists(partition_name, slot_suffix)) {
    if (FindPhysicalPartition(partition_name) || LogicalPartitionExists(device, partition_name)) {
        *message = "yes";
    } else {
        *message = "no";
@@ -289,8 +288,7 @@ bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& ar
    // Zero-length partitions cannot be created through device-mapper, so we
    // special case them here.
    bool is_zero_length;
    if (LogicalPartitionExists(args[0], device->GetCurrentSlot(), &is_zero_length) &&
        is_zero_length) {
    if (LogicalPartitionExists(device, args[0], &is_zero_length) && is_zero_length) {
        *message = "0x0";
        return true;
    }
@@ -313,8 +311,7 @@ bool GetPartitionType(FastbootDevice* device, const std::vector<std::string>& ar
    }

    std::string partition_name = args[0];
    if (!FindPhysicalPartition(partition_name) &&
        !LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
    if (!FindPhysicalPartition(partition_name) && !LogicalPartitionExists(device, partition_name)) {
        *message = "Invalid partition";
        return false;
    }
@@ -363,7 +360,7 @@ bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string
    // return "true", to be consistent with prefering to flash logical partitions
    // over physical ones.
    std::string partition_name = args[0];
    if (LogicalPartitionExists(partition_name, device->GetCurrentSlot())) {
    if (LogicalPartitionExists(device, partition_name)) {
        *message = "yes";
        return true;
    }
Loading