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

Commit 770395de authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "fastbootd: Add commands for logical partitions."

parents 18eae78c 0d4277d7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ cc_binary {
        "libbase",
        "libbootloader_message",
        "libcutils",
        "libext2_uuid",
        "libext4_utils",
        "libfs_mgr",
        "libhidlbase",
+4 −0
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@
#define FB_CMD_REBOOT_RECOVERY "reboot-recovery"
#define FB_CMD_REBOOT_FASTBOOT "reboot-fastboot"
#define FB_CMD_POWERDOWN "powerdown"
#define FB_CMD_CREATE_PARTITION "create-logical-partition"
#define FB_CMD_DELETE_PARTITION "delete-logical-partition"
#define FB_CMD_RESIZE_PARTITION "resize-logical-partition"

#define RESPONSE_OKAY "OKAY"
#define RESPONSE_FAIL "FAIL"
@@ -53,3 +56,4 @@
#define FB_VAR_PARTITION_SIZE "partition-size"
#define FB_VAR_SLOT_SUCCESSFUL "slot-successful"
#define FB_VAR_SLOT_UNBOOTABLE "slot-unbootable"
#define FB_VAR_IS_LOGICAL "is-logical"
+127 −1
Original line number Diff line number Diff line
@@ -27,6 +27,9 @@
#include <android-base/unique_fd.h>
#include <cutils/android_reboot.h>
#include <ext4_utils/wipe.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
#include <uuid/uuid.h>

#include "constants.h"
#include "fastboot_device.h"
@@ -37,6 +40,7 @@ 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 namespace android::fs_mgr;

bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    using VariableHandler = std::function<bool(FastbootDevice*, const std::vector<std::string>&)>;
@@ -54,7 +58,8 @@ bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args)
            {FB_VAR_HAS_SLOT, GetHasSlot},
            {FB_VAR_SLOT_SUCCESSFUL, GetSlotSuccessful},
            {FB_VAR_SLOT_UNBOOTABLE, GetSlotUnbootable},
            {FB_VAR_PARTITION_SIZE, GetPartitionSize}};
            {FB_VAR_PARTITION_SIZE, GetPartitionSize},
            {FB_VAR_IS_LOGICAL, GetPartitionIsLogical}};

    // args[0] is command name, args[1] is variable.
    auto found_variable = kVariableMap.find(args[1]);
@@ -209,3 +214,124 @@ bool RebootRecoveryHandler(FastbootDevice* device, const std::vector<std::string
    TEMP_FAILURE_RETRY(pause());
    return status;
}

// Helper class for opening a handle to a MetadataBuilder and writing the new
// partition table to the same place it was read.
class PartitionBuilder {
  public:
    explicit PartitionBuilder(FastbootDevice* device);

    bool Write();
    bool Valid() const { return !!builder_; }
    MetadataBuilder* operator->() const { return builder_.get(); }

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

PartitionBuilder::PartitionBuilder(FastbootDevice* device) {
    auto super_device = FindPhysicalPartition(LP_METADATA_PARTITION_NAME);
    if (!super_device) {
        return;
    }
    super_device_ = *super_device;

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

bool PartitionBuilder::Write() {
    std::unique_ptr<LpMetadata> metadata = builder_->Export();
    if (!metadata) {
        return false;
    }
    return UpdatePartitionTable(super_device_, *metadata.get(), slot_number_);
}

bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    if (args.size() < 3) {
        return device->WriteFail("Invalid partition name and size");
    }

    uint64_t partition_size;
    std::string partition_name = args[1];
    if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
        return device->WriteFail("Invalid partition size");
    }

    PartitionBuilder builder(device);
    if (!builder.Valid()) {
        return device->WriteFail("Could not open super partition");
    }
    // TODO(112433293) Disallow if the name is in the physical table as well.
    if (builder->FindPartition(partition_name)) {
        return device->WriteFail("Partition already exists");
    }

    // Make a random UUID, since they're not currently used.
    uuid_t uuid;
    char uuid_str[37];
    uuid_generate_random(uuid);
    uuid_unparse(uuid, uuid_str);

    Partition* partition = builder->AddPartition(partition_name, uuid_str, 0);
    if (!partition) {
        return device->WriteFail("Failed to add partition");
    }
    if (!builder->ResizePartition(partition, partition_size)) {
        builder->RemovePartition(partition_name);
        return device->WriteFail("Not enough space for partition");
    }
    if (!builder.Write()) {
        return device->WriteFail("Failed to write partition table");
    }
    return device->WriteOkay("Partition created");
}

bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    if (args.size() < 2) {
        return device->WriteFail("Invalid partition name and size");
    }

    PartitionBuilder builder(device);
    if (!builder.Valid()) {
        return device->WriteFail("Could not open super partition");
    }
    builder->RemovePartition(args[1]);
    if (!builder.Write()) {
        return device->WriteFail("Failed to write partition table");
    }
    return device->WriteOkay("Partition deleted");
}

bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args) {
    if (args.size() < 3) {
        return device->WriteFail("Invalid partition name and size");
    }

    uint64_t partition_size;
    std::string partition_name = args[1];
    if (!android::base::ParseUint(args[2].c_str(), &partition_size)) {
        return device->WriteFail("Invalid partition size");
    }

    PartitionBuilder builder(device);
    if (!builder.Valid()) {
        return device->WriteFail("Could not open super partition");
    }

    Partition* partition = builder->FindPartition(partition_name);
    if (!partition) {
        return device->WriteFail("Partition does not exist");
    }
    if (!builder->ResizePartition(partition, partition_size)) {
        return device->WriteFail("Not enough space to resize partition");
    }
    if (!builder.Write()) {
        return device->WriteFail("Failed to write partition table");
    }
    return device->WriteOkay("Partition resized");
}
+3 −0
Original line number Diff line number Diff line
@@ -41,3 +41,6 @@ bool RebootRecoveryHandler(FastbootDevice* device, const std::vector<std::string
bool GetVarHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool FlashHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool CreatePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool DeletePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args);
bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::string>& args);
+3 −0
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@ FastbootDevice::FastbootDevice()
              {FB_CMD_REBOOT_RECOVERY, RebootRecoveryHandler},
              {FB_CMD_ERASE, EraseHandler},
              {FB_CMD_FLASH, FlashHandler},
              {FB_CMD_CREATE_PARTITION, CreatePartitionHandler},
              {FB_CMD_DELETE_PARTITION, DeletePartitionHandler},
              {FB_CMD_RESIZE_PARTITION, ResizePartitionHandler},
      }),
      transport_(std::make_unique<ClientUsbTransport>()),
      boot_control_hal_(IBootControl::getService()) {}
Loading