Merge "fastbootd: Add an update-super command to sync the super partition."

This commit is contained in:
Treehugger Robot 2018-08-23 00:54:26 +00:00 committed by Gerrit Code Review
commit e41cb2e767
7 changed files with 122 additions and 0 deletions

View File

@ -186,10 +186,45 @@ The various currently defined names are:
bootloader requiring a signature before
it will install or boot images.
is-userspace If the value is "yes", the device is running
fastbootd. Otherwise, it is running fastboot
in the bootloader.
Names starting with a lowercase character are reserved by this
specification. OEM-specific names should not start with lowercase
characters.
## Logical Partitions
There are a number of commands to interact with logical partitions:
update-super:%s:%s Write the previously downloaded image to a super
partition. Unlike the "flash" command, this has
special rules. The image must have been created by
the lpmake command, and must not be a sparse image.
If the last argument is "wipe", then all existing
logical partitions are deleted. If no final argument
is specified, the partition tables are merged. Any
partition in the new image that does not exist in the
old image is created with a zero size.
In all cases, this will cause the temporary "scratch"
partition to be deleted if it exists.
create-logical-partition:%s:%d
Create a logical partition with the given name and
size, in the super partition.
delete-logical-partition:%s
Delete a logical partition with the given name.
resize-logical-partition:%s:%d
Change the size of the named logical partition.
In addition, there is a variable to test whether a partition is logical:
is-logical:%s If the value is "yes", the partition is logical.
Otherwise the partition is physical.
## TCP Protocol v1

View File

@ -33,6 +33,7 @@
#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 FB_CMD_UPDATE_SUPER "update-super"
#define RESPONSE_OKAY "OKAY"
#define RESPONSE_FAIL "FAIL"

View File

@ -336,3 +336,11 @@ bool ResizePartitionHandler(FastbootDevice* device, const std::vector<std::strin
}
return device->WriteOkay("Partition resized");
}
bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args) {
if (args.size() < 2) {
return device->WriteFail("Invalid arguments");
}
bool wipe = (args.size() >= 3 && args[2] == "wipe");
return UpdateSuper(device, args[1], wipe);
}

View File

@ -44,3 +44,4 @@ 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);
bool UpdateSuperHandler(FastbootDevice* device, const std::vector<std::string>& args);

View File

@ -46,6 +46,7 @@ FastbootDevice::FastbootDevice()
{FB_CMD_CREATE_PARTITION, CreatePartitionHandler},
{FB_CMD_DELETE_PARTITION, DeletePartitionHandler},
{FB_CMD_RESIZE_PARTITION, ResizePartitionHandler},
{FB_CMD_UPDATE_SUPER, UpdateSuperHandler},
}),
transport_(std::make_unique<ClientUsbTransport>()),
boot_control_hal_(IBootControl::getService()) {}

View File

@ -25,6 +25,8 @@
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <ext4_utils/ext4_utils.h>
#include <liblp/builder.h>
#include <liblp/liblp.h>
#include <sparse/sparse.h>
#include "fastboot_device.h"
@ -36,6 +38,8 @@ constexpr uint32_t SPARSE_HEADER_MAGIC = 0xed26ff3a;
} // namespace
using namespace android::fs_mgr;
int FlashRawDataChunk(int fd, const char* data, size_t len) {
size_t ret = 0;
while (ret < len) {
@ -99,3 +103,74 @@ int Flash(FastbootDevice* device, const std::string& partition_name) {
}
return FlashBlockDevice(handle.fd(), data);
}
bool UpdateSuper(FastbootDevice* device, const std::string& partition_name, bool wipe) {
std::optional<std::string> super = FindPhysicalPartition(partition_name);
if (!super) {
return device->WriteFail("Could not find partition: " + partition_name);
}
std::vector<char> data = std::move(device->download_data());
if (data.empty()) {
return device->WriteFail("No data available");
}
std::unique_ptr<LpMetadata> new_metadata = ReadFromImageBlob(data.data(), data.size());
if (!new_metadata) {
return device->WriteFail("Data is not a valid logical partition metadata image");
}
// If we are unable to read the existing metadata, then the super partition
// is corrupt. In this case we reflash the whole thing using the provided
// image.
std::string slot_suffix = device->GetCurrentSlot();
uint32_t slot_number = SlotNumberForSlotSuffix(slot_suffix);
std::unique_ptr<LpMetadata> metadata = ReadMetadata(super->c_str(), slot_number);
if (!metadata || wipe) {
if (!FlashPartitionTable(super.value(), *new_metadata.get())) {
return device->WriteFail("Unable to flash new partition table");
}
return device->WriteOkay("Successfully flashed partition table");
}
// There's a working super partition, and we don't want to wipe it - it may
// may contain partitions created for the user. Instead, we create a zero-
// sized partition for each entry in the new partition table. It is then
// the host's responsibility to size it correctly via resize-logical-partition.
std::unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(*metadata.get());
if (!builder) {
return device->WriteFail("Unable to create a metadata builder");
}
for (const auto& partition : new_metadata->partitions) {
std::string name = GetPartitionName(partition);
if (builder->FindPartition(name)) {
continue;
}
std::string guid = GetPartitionGuid(partition);
if (!builder->AddPartition(name, guid, partition.attributes)) {
return device->WriteFail("Unable to add partition: " + name);
}
}
// The scratch partition may exist as temporary storage, created for
// use by adb remount for overlayfs. If we're performing a flashall
// operation then we want to start over with a clean slate, so we
// remove the scratch partition until it is requested again.
builder->RemovePartition("scratch");
new_metadata = builder->Export();
if (!new_metadata) {
return device->WriteFail("Unable to export new partition table");
}
// 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.value(), *new_metadata.get(), i);
}
if (!ok) {
return device->WriteFail("Unable to write new partition table");
}
return device->WriteOkay("Successfully updated partition table");
}

View File

@ -22,3 +22,4 @@
class FastbootDevice;
int Flash(FastbootDevice* device, const std::string& partition_name);
bool UpdateSuper(FastbootDevice* device, const std::string& partition_name, bool wipe);