diff --git a/fastboot/Android.bp b/fastboot/Android.bp index 9995052e4ca7..3414d5352413 100644 --- a/fastboot/Android.bp +++ b/fastboot/Android.bp @@ -108,6 +108,7 @@ cc_binary { "libbase", "libbootloader_message", "libcutils", + "libext2_uuid", "libext4_utils", "libfs_mgr", "libhidlbase", diff --git a/fastboot/constants.h b/fastboot/constants.h index fa17070b1799..b780ba575865 100644 --- a/fastboot/constants.h +++ b/fastboot/constants.h @@ -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" diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp index 7eaefe6de6bf..053d6544788a 100644 --- a/fastboot/device/commands.cpp +++ b/fastboot/device/commands.cpp @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #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& args) { using VariableHandler = std::function&)>; @@ -54,7 +58,8 @@ bool GetVarHandler(FastbootDevice* device, const std::vector& 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() const { return builder_.get(); } + + private: + std::string super_device_; + uint32_t slot_number_; + std::unique_ptr 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 metadata = builder_->Export(); + if (!metadata) { + return false; + } + return UpdatePartitionTable(super_device_, *metadata.get(), slot_number_); +} + +bool CreatePartitionHandler(FastbootDevice* device, const std::vector& 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& 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& 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"); +} diff --git a/fastboot/device/commands.h b/fastboot/device/commands.h index 830eb554e366..f67df914053d 100644 --- a/fastboot/device/commands.h +++ b/fastboot/device/commands.h @@ -41,3 +41,6 @@ bool RebootRecoveryHandler(FastbootDevice* device, const std::vector& args); bool EraseHandler(FastbootDevice* device, const std::vector& args); bool FlashHandler(FastbootDevice* device, const std::vector& args); +bool CreatePartitionHandler(FastbootDevice* device, const std::vector& args); +bool DeletePartitionHandler(FastbootDevice* device, const std::vector& args); +bool ResizePartitionHandler(FastbootDevice* device, const std::vector& args); diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp index b94fbb0b1613..c306e675a138 100644 --- a/fastboot/device/fastboot_device.cpp +++ b/fastboot/device/fastboot_device.cpp @@ -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()), boot_control_hal_(IBootControl::getService()) {} diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp index b51b9853504a..70e4bcc4c5a7 100644 --- a/fastboot/device/variables.cpp +++ b/fastboot/device/variables.cpp @@ -148,3 +148,20 @@ bool GetPartitionSize(FastbootDevice* device, const std::vector& ar uint64_t size = get_block_device_size(handle.fd()); return device->WriteOkay(android::base::StringPrintf("%" PRIX64, size)); } + +bool GetPartitionIsLogical(FastbootDevice* device, const std::vector& args) { + if (args.size() < 1) { + return device->WriteFail("Missing argument"); + } + // Note: if a partition name is in both the GPT and the super partition, we + // 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())) { + return device->WriteOkay("yes"); + } + if (FindPhysicalPartition(partition_name)) { + return device->WriteOkay("no"); + } + return device->WriteFail("Partition not found"); +} diff --git a/fastboot/device/variables.h b/fastboot/device/variables.h index 88947e0cee54..0c706d7ab3dd 100644 --- a/fastboot/device/variables.h +++ b/fastboot/device/variables.h @@ -35,3 +35,4 @@ bool GetMaxDownloadSize(FastbootDevice* device, const std::vector& bool GetUnlocked(FastbootDevice* device, const std::vector& args); bool GetHasSlot(FastbootDevice* device, const std::vector& args); bool GetPartitionSize(FastbootDevice* device, const std::vector& args); +bool GetPartitionIsLogical(FastbootDevice* device, const std::vector& args); diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp index 63ee2af5b917..6890643396d5 100644 --- a/fastboot/engine.cpp +++ b/fastboot/engine.cpp @@ -155,6 +155,21 @@ void fb_queue_flash_sparse(const std::string& partition, struct sparse_file* s, total); } +void fb_queue_create_partition(const std::string& partition, const std::string& size) { + Action& a = queue_action(OP_COMMAND, FB_CMD_CREATE_PARTITION ":" + partition + ":" + size); + a.msg = "Creating '" + partition + "'"; +} + +void fb_queue_delete_partition(const std::string& partition) { + Action& a = queue_action(OP_COMMAND, FB_CMD_DELETE_PARTITION ":" + partition); + a.msg = "Deleting '" + partition + "'"; +} + +void fb_queue_resize_partition(const std::string& partition, const std::string& size) { + Action& a = queue_action(OP_COMMAND, FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size); + a.msg = "Resizing '" + partition + "'"; +} + static int match(const char* str, const char** value, unsigned count) { unsigned n; diff --git a/fastboot/engine.h b/fastboot/engine.h index 74aaa6a8b552..8aebdd76a410 100644 --- a/fastboot/engine.h +++ b/fastboot/engine.h @@ -69,6 +69,9 @@ void fb_queue_download_fd(const std::string& name, int fd, uint32_t sz); void fb_queue_upload(const std::string& outfile); void fb_queue_notice(const std::string& notice); void fb_queue_wait_for_disconnect(void); +void fb_queue_create_partition(const std::string& partition, const std::string& size); +void fb_queue_delete_partition(const std::string& partition); +void fb_queue_resize_partition(const std::string& partition, const std::string& size); int64_t fb_execute_queue(); void fb_set_active(const std::string& slot); diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index d652c0df9834..dc94952ba465 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -1691,6 +1691,17 @@ int FastBootTool::Main(int argc, char* argv[]) { } else { syntax_error("unknown 'flashing' command %s", args[0].c_str()); } + } else if (command == "create-logical-partition") { + std::string partition = next_arg(&args); + std::string size = next_arg(&args); + fb_queue_create_partition(partition, size); + } else if (command == "delete-logical-partition") { + std::string partition = next_arg(&args); + fb_queue_delete_partition(partition); + } else if (command == "resize-logical-partition") { + std::string partition = next_arg(&args); + std::string size = next_arg(&args); + fb_queue_resize_partition(partition, size); } else { syntax_error("unknown command %s", command.c_str()); }