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

Commit 769ea81c authored by Daniel Zheng's avatar Daniel Zheng Committed by Gerrit Code Review
Browse files

Merge "Added support for FlashSuperLayoutTask"

parents 79faee90 47d70a55
Loading
Loading
Loading
Loading
+25 −94
Original line number Diff line number Diff line
@@ -982,7 +982,7 @@ static void DumpInfo() {
    fprintf(stderr, "--------------------------------------------\n");
}

static std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size) {
std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size) {
    if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) {
        die("invalid max size %" PRId64, max_size);
    }
@@ -1027,7 +1027,7 @@ static uint64_t get_uint_var(const char* var_name) {
    return value;
}

static int64_t get_sparse_limit(int64_t size) {
int64_t get_sparse_limit(int64_t size) {
    int64_t limit = sparse_limit;
    if (limit == 0) {
        // Unlimited, so see what the target device's limit is.
@@ -1161,7 +1161,7 @@ static bool has_vbmeta_partition() {

// Note: this only works in userspace fastboot. In the bootloader, use
// should_flash_in_userspace().
static bool is_logical(const std::string& partition) {
bool is_logical(const std::string& partition) {
    std::string value;
    return fb->GetVar("is-logical:" + partition, &value) == fastboot::SUCCESS && value == "yes";
}
@@ -1243,8 +1243,7 @@ static void copy_avb_footer(const std::string& partition, struct fastboot_buffer
    lseek(buf->fd.get(), 0, SEEK_SET);
}

static void flash_partition_files(const std::string& partition,
                                  const std::vector<SparsePtr>& files) {
void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files) {
    for (size_t i = 0; i < files.size(); i++) {
        sparse_file* s = files[i].get();
        int64_t sz = sparse_file_len(s, true, false);
@@ -1303,7 +1302,7 @@ static int get_slot_count() {
    return count;
}

static bool supports_AB() {
bool supports_AB() {
    return get_slot_count() >= 2;
}

@@ -1426,7 +1425,7 @@ void do_for_partitions(const std::string& part, const std::string& slot,
    }
}

static bool is_retrofit_device() {
bool is_retrofit_device() {
    std::string value;
    if (fb->GetVar("super-partition-name", &value) != fastboot::SUCCESS) {
        return false;
@@ -1562,6 +1561,20 @@ static void CancelSnapshotIfNeeded() {
    }
}

std::string GetPartitionName(const ImageEntry& entry, std::string& current_slot) {
    auto slot = entry.second;
    if (slot.empty()) {
        slot = current_slot;
    }
    if (slot.empty()) {
        return entry.first->part_name;
    }
    if (slot == "all") {
        LOG(FATAL) << "Cannot retrieve a singular name when using all slots";
    }
    return entry.first->part_name + "_" + slot;
}

class FlashAllTool {
  public:
    FlashAllTool(FlashingPlan* fp);
@@ -1575,15 +1588,12 @@ class FlashAllTool {
    void FlashImages(const std::vector<std::pair<const Image*, std::string>>& images);
    void FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf);
    void UpdateSuperPartition();
    bool OptimizedFlashSuper();

    // If the image uses the default slot, or the user specified "all", then
    // the paired string will be empty. If the image requests a specific slot
    // (for example, system_other) it is specified instead.
    using ImageEntry = std::pair<const Image*, std::string>;

    std::string GetPartitionName(const ImageEntry& entry);

    std::vector<ImageEntry> boot_images_;
    std::vector<ImageEntry> os_images_;
    FlashingPlan* fp_;
@@ -1612,10 +1622,13 @@ void FlashAllTool::Flash() {
    // or in bootloader fastboot.
    FlashImages(boot_images_);

    if (!OptimizedFlashSuper()) {
    auto flash_super_task = FlashSuperLayoutTask::Initialize(fp_, os_images_);

    if (flash_super_task) {
        flash_super_task->Run();
    } else {
        // Sync the super partition. This will reboot to userspace fastboot if needed.
        UpdateSuperPartition();

        // Resize any logical partition to 0, so each partition is reset to 0
        // extents, and will achieve more optimal allocation.
        for (const auto& [image, slot] : os_images_) {
@@ -1627,77 +1640,9 @@ void FlashAllTool::Flash() {
            do_for_partitions(image->part_name, slot, resize_partition, false);
        }
    }

    // Flash OS images, resizing logical partitions as needed.
    FlashImages(os_images_);
}

bool FlashAllTool::OptimizedFlashSuper() {
    if (!supports_AB()) {
        LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
        return false;
    }
    if (fp_->slot == "all") {
        LOG(VERBOSE) << "Cannot optimize flashing super for all slots";
        return false;
    }

    // Does this device use dynamic partitions at all?
    unique_fd fd = fp_->source->OpenFile("super_empty.img");
    if (fd < 0) {
        LOG(VERBOSE) << "could not open super_empty.img";
        return false;
    }

    // Try to find whether there is a super partition.
    std::string super_name;
    if (fb->GetVar("super-partition-name", &super_name) != fastboot::SUCCESS) {
        super_name = "super";
    }
    std::string partition_size_str;
    if (fb->GetVar("partition-size:" + super_name, &partition_size_str) != fastboot::SUCCESS) {
        LOG(VERBOSE) << "Cannot optimize super flashing: could not determine super partition";
        return false;
    }

    SuperFlashHelper helper(*fp_->source);
    if (!helper.Open(fd)) {
        return false;
    }

    for (const auto& entry : os_images_) {
        auto partition = GetPartitionName(entry);
        auto image = entry.first;

        if (!helper.AddPartition(partition, image->img_name, image->optional_if_no_image)) {
            return false;
        }
    }

    auto s = helper.GetSparseLayout();
    if (!s) {
        return false;
    }

    std::vector<SparsePtr> files;
    if (int limit = get_sparse_limit(sparse_file_len(s.get(), false, false))) {
        files = resparse_file(s.get(), limit);
    } else {
        files.emplace_back(std::move(s));
    }

    // Send the data to the device.
    flash_partition_files(super_name, files);

    // Remove images that we already flashed, just in case we have non-dynamic OS images.
    auto remove_if_callback = [&, this](const ImageEntry& entry) -> bool {
        return helper.WillFlash(GetPartitionName(entry));
    };
    os_images_.erase(std::remove_if(os_images_.begin(), os_images_.end(), remove_if_callback),
                     os_images_.end());
    return true;
}

void FlashAllTool::CheckRequirements() {
    std::vector<char> contents;
    if (!fp_->source->ReadFile("android-info.txt", &contents)) {
@@ -1811,20 +1756,6 @@ void FlashAllTool::UpdateSuperPartition() {
    }
}

std::string FlashAllTool::GetPartitionName(const ImageEntry& entry) {
    auto slot = entry.second;
    if (slot.empty()) {
        slot = fp_->current_slot;
    }
    if (slot.empty()) {
        return entry.first->part_name;
    }
    if (slot == "all") {
        LOG(FATAL) << "Cannot retrieve a singular name when using all slots";
    }
    return entry.first->part_name + "_" + slot;
}

class ZipImageSource final : public ImageSource {
  public:
    explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {}
+10 −2
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@

#include <string>
#include "fastboot_driver.h"
#include "super_flash_helper.h"
#include "util.h"

#include <bootimg.h>
@@ -82,7 +83,6 @@ struct FlashingPlan {
    std::string current_slot;
    std::string secondary_slot;
    fastboot::FastBootDriver* fb;

};

bool should_flash_in_userspace(const std::string& partition_name);
@@ -101,3 +101,11 @@ struct NetworkSerial {
};

Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial);
bool supports_AB();
std::string GetPartitionName(const ImageEntry& entry, std::string& current_slot_);
void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files);
int64_t get_sparse_limit(int64_t size);
std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size);

bool is_retrofit_device();
bool is_logical(const std::string& partition);
+79 −3
Original line number Diff line number Diff line
@@ -14,11 +14,12 @@
// limitations under the License.
//
#include "task.h"
#include <iostream>
#include "fastboot.h"
#include "util.h"
#include "filesystem.h"
#include "super_flash_helper.h"

#include "fastboot.h"
#include "util.h"
using namespace std::string_literals;

FlashTask::FlashTask(const std::string& _slot, const std::string& _pname)
    : pname_(_pname), fname_(find_item(_pname)), slot_(_slot) {
@@ -66,3 +67,78 @@ void RebootTask::Run() {
        syntax_error("unknown reboot target %s", reboot_target_.c_str());
    }
}

FlashSuperLayoutTask::FlashSuperLayoutTask(const std::string& super_name,
                                           std::unique_ptr<SuperFlashHelper> helper,
                                           SparsePtr sparse_layout)
    : super_name_(super_name),
      helper_(std::move(helper)),
      sparse_layout_(std::move(sparse_layout)) {}

void FlashSuperLayoutTask::Run() {
    std::vector<SparsePtr> files;
    if (int limit = get_sparse_limit(sparse_file_len(sparse_layout_.get(), false, false))) {
        files = resparse_file(sparse_layout_.get(), limit);
    } else {
        files.emplace_back(std::move(sparse_layout_));
    }

    // Send the data to the device.
    flash_partition_files(super_name_, files);
}

std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::Initialize(
        FlashingPlan* fp, std::vector<ImageEntry>& os_images) {
    if (!supports_AB()) {
        LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
        return nullptr;
    }
    if (fp->slot == "all") {
        LOG(VERBOSE) << "Cannot optimize flashing super for all slots";
        return nullptr;
    }

    // Does this device use dynamic partitions at all?
    unique_fd fd = fp->source->OpenFile("super_empty.img");

    if (fd < 0) {
        LOG(VERBOSE) << "could not open super_empty.img";
        return nullptr;
    }

    std::string super_name;
    // Try to find whether there is a super partition.
    if (fp->fb->GetVar("super-partition-name", &super_name) != fastboot::SUCCESS) {
        super_name = "super";
    }
    std::string partition_size_str;

    if (fp->fb->GetVar("partition-size:" + super_name, &partition_size_str) != fastboot::SUCCESS) {
        LOG(VERBOSE) << "Cannot optimize super flashing: could not determine super partition";
        return nullptr;
    }
    std::unique_ptr<SuperFlashHelper> helper = std::make_unique<SuperFlashHelper>(*fp->source);
    if (!helper->Open(fd)) {
        return nullptr;
    }

    for (const auto& entry : os_images) {
        auto partition = GetPartitionName(entry, fp->current_slot);
        auto image = entry.first;

        if (!helper->AddPartition(partition, image->img_name, image->optional_if_no_image)) {
            return nullptr;
        }
    }

    auto s = helper->GetSparseLayout();
    if (!s) return nullptr;

    // Remove images that we already flashed, just in case we have non-dynamic OS images.
    auto remove_if_callback = [&](const ImageEntry& entry) -> bool {
        return helper->WillFlash(GetPartitionName(entry, fp->current_slot));
    };
    os_images.erase(std::remove_if(os_images.begin(), os_images.end(), remove_if_callback),
                    os_images.end());
    return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s));
}
+18 −1
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@

#include "fastboot.h"
#include "fastboot_driver.h"
#include "super_flash_helper.h"
#include "util.h"

class Task {
  public:
@@ -53,3 +55,18 @@ class RebootTask : public Task {
    const std::string reboot_target_ = "";
    FlashingPlan* fp_;
};

class FlashSuperLayoutTask : public Task {
  public:
    FlashSuperLayoutTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper,
                         SparsePtr sparse_layout);
    static std::unique_ptr<FlashSuperLayoutTask> Initialize(FlashingPlan* fp,
                                                            std::vector<ImageEntry>& os_images);
    using ImageEntry = std::pair<const Image*, std::string>;
    void Run() override;

  private:
    const std::string super_name_;
    std::unique_ptr<SuperFlashHelper> helper_;
    SparsePtr sparse_layout_;
};