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

Commit 7df2ab9c authored by Daniel Zheng's avatar Daniel Zheng
Browse files

Added Flashing Plan

Fastboot has a lot of flags that are used by many different functions
including the Flashall Class and newly added FlashSuperTask. Passing all
of these flags as paramaters is cumbersome, so adding a Flashing Plan
that contains these flags simplifies the code.

Test: tested Flashall and update img.zip on raven
Change-Id: I9c842f25389a20b852d55f684e1b86040af1d86a
Bug: 194686221
parent 71b3b434
Loading
Loading
Loading
Loading
+54 −88
Original line number Diff line number Diff line
@@ -128,25 +128,6 @@ struct fastboot_buffer {
    int64_t image_size;
};

enum class ImageType {
    // Must be flashed for device to boot into the kernel.
    BootCritical,
    // Normal partition to be flashed during "flashall".
    Normal,
    // Partition that is never flashed during "flashall".
    Extra
};

struct Image {
    std::string nickname;
    std::string img_name;
    std::string sig_name;
    std::string part_name;
    bool optional_if_no_image;
    ImageType type;
    bool IsSecondary() const { return nickname.empty(); }
};

static std::vector<Image> images = {
        // clang-format off
    { "boot",     "boot.img",         "boot.sig",     "boot",     false, ImageType::BootCritical },
@@ -1580,8 +1561,7 @@ static void CancelSnapshotIfNeeded() {

class FlashAllTool {
  public:
    FlashAllTool(const ImageSource& source, const std::string& slot_override, bool skip_secondary,
                 bool wipe, bool force_flash);
    FlashAllTool(FlashingPlan* fp);

    void Flash();

@@ -1601,25 +1581,12 @@ class FlashAllTool {

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

    const ImageSource& source_;
    std::string slot_override_;
    bool skip_secondary_;
    bool wipe_;
    bool force_flash_;
    std::string current_slot_;
    std::string secondary_slot_;

    std::vector<ImageEntry> boot_images_;
    std::vector<ImageEntry> os_images_;
    FlashingPlan* fp_;
};

FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_override,
                           bool skip_secondary, bool wipe, bool force_flash)
    : source_(source),
      slot_override_(slot_override),
      skip_secondary_(skip_secondary),
      wipe_(wipe),
      force_flash_(force_flash) {}
FlashAllTool::FlashAllTool(FlashingPlan* fp) : fp_(fp) {}

void FlashAllTool::Flash() {
    DumpInfo();
@@ -1627,10 +1594,10 @@ void FlashAllTool::Flash() {

    // Change the slot first, so we boot into the correct recovery image when
    // using fastbootd.
    if (slot_override_ == "all") {
    if (fp_->slot == "all") {
        set_active("a");
    } else {
        set_active(slot_override_);
        set_active(fp_->slot);
    }

    DetermineSlot();
@@ -1667,13 +1634,13 @@ bool FlashAllTool::OptimizedFlashSuper() {
        LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
        return false;
    }
    if (slot_override_ == "all") {
    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 = source_.OpenFile("super_empty.img");
    unique_fd fd = fp_->source->OpenFile("super_empty.img");
    if (fd < 0) {
        LOG(VERBOSE) << "could not open super_empty.img";
        return false;
@@ -1690,7 +1657,7 @@ bool FlashAllTool::OptimizedFlashSuper() {
        return false;
    }

    SuperFlashHelper helper(source_);
    SuperFlashHelper helper(*fp_->source);
    if (!helper.Open(fd)) {
        return false;
    }
@@ -1730,43 +1697,43 @@ bool FlashAllTool::OptimizedFlashSuper() {

void FlashAllTool::CheckRequirements() {
    std::vector<char> contents;
    if (!source_.ReadFile("android-info.txt", &contents)) {
    if (!fp_->source->ReadFile("android-info.txt", &contents)) {
        die("could not read android-info.txt");
    }
    ::CheckRequirements({contents.data(), contents.size()}, force_flash_);
    ::CheckRequirements({contents.data(), contents.size()}, fp_->force_flash);
}

void FlashAllTool::DetermineSlot() {
    if (slot_override_.empty()) {
        current_slot_ = get_current_slot();
    if (fp_->slot.empty()) {
        fp_->current_slot = get_current_slot();
    } else {
        current_slot_ = slot_override_;
        fp_->current_slot = fp_->slot;
    }

    if (skip_secondary_) {
    if (fp_->skip_secondary) {
        return;
    }
    if (slot_override_ != "" && slot_override_ != "all") {
        secondary_slot_ = get_other_slot(slot_override_);
    if (fp_->slot != "" && fp_->slot != "all") {
        fp_->secondary_slot = get_other_slot(fp_->slot);
    } else {
        secondary_slot_ = get_other_slot();
        fp_->secondary_slot = get_other_slot();
    }
    if (secondary_slot_ == "") {
    if (fp_->secondary_slot == "") {
        if (supports_AB()) {
            fprintf(stderr, "Warning: Could not determine slot for secondary images. Ignoring.\n");
        }
        skip_secondary_ = true;
        fp_->skip_secondary = true;
    }
}

void FlashAllTool::CollectImages() {
    for (size_t i = 0; i < images.size(); ++i) {
        std::string slot = slot_override_;
        std::string slot = fp_->slot;
        if (images[i].IsSecondary()) {
            if (skip_secondary_) {
            if (fp_->skip_secondary) {
                continue;
            }
            slot = secondary_slot_;
            slot = fp_->secondary_slot;
        }
        if (images[i].type == ImageType::BootCritical) {
            boot_images_.emplace_back(&images[i], slot);
@@ -1779,7 +1746,7 @@ void FlashAllTool::CollectImages() {
void FlashAllTool::FlashImages(const std::vector<std::pair<const Image*, std::string>>& images) {
    for (const auto& [image, slot] : images) {
        fastboot_buffer buf;
        unique_fd fd = source_.OpenFile(image->img_name);
        unique_fd fd = fp_->source->OpenFile(image->img_name);
        if (fd < 0 || !load_buf_fd(std::move(fd), &buf)) {
            if (image->optional_if_no_image) {
                continue;
@@ -1793,7 +1760,7 @@ void FlashAllTool::FlashImages(const std::vector<std::pair<const Image*, std::st
void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf) {
    auto flash = [&, this](const std::string& partition_name) {
        std::vector<char> signature_data;
        if (source_.ReadFile(image.sig_name, &signature_data)) {
        if (fp_->source->ReadFile(image.sig_name, &signature_data)) {
            fb->Download("signature", signature_data);
            fb->RawCommand("signature", "installing signature");
        }
@@ -1807,7 +1774,7 @@ void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastb
}

void FlashAllTool::UpdateSuperPartition() {
    unique_fd fd = source_.OpenFile("super_empty.img");
    unique_fd fd = fp_->source->OpenFile("super_empty.img");
    if (fd < 0) {
        return;
    }
@@ -1822,7 +1789,7 @@ void FlashAllTool::UpdateSuperPartition() {
    fb->Download(super_name, fd, get_file_size(fd));

    std::string command = "update-super:" + super_name;
    if (wipe_) {
    if (fp_->wants_wipe) {
        command += ":wipe";
    }
    fb->RawCommand(command, "Updating super partition");
@@ -1844,7 +1811,7 @@ void FlashAllTool::UpdateSuperPartition() {
std::string FlashAllTool::GetPartitionName(const ImageEntry& entry) {
    auto slot = entry.second;
    if (slot.empty()) {
        slot = current_slot_;
        slot = fp_->current_slot;
    }
    if (slot.empty()) {
        return entry.first->part_name;
@@ -1873,15 +1840,16 @@ unique_fd ZipImageSource::OpenFile(const std::string& name) const {
    return unzip_to_file(zip_, name.c_str());
}

static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary,
                      bool force_flash) {
static void do_update(const char* filename, FlashingPlan* fp) {
    ZipArchiveHandle zip;
    int error = OpenArchive(filename, &zip);
    if (error != 0) {
        die("failed to open zip file '%s': %s", filename, ErrorCodeString(error));
    }

    FlashAllTool tool(ZipImageSource(zip), slot_override, skip_secondary, false, force_flash);
    ZipImageSource zp = ZipImageSource(zip);
    fp->source = &zp;
    fp->wants_wipe = false;
    FlashAllTool tool(fp);
    tool.Flash();

    CloseArchive(zip);
@@ -1906,9 +1874,10 @@ unique_fd LocalImageSource::OpenFile(const std::string& name) const {
    return unique_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_BINARY)));
}

static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe,
                        bool force_flash) {
    FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe, force_flash);
static void do_flashall(FlashingPlan* fp) {
    LocalImageSource s = LocalImageSource();
    fp->source = &s;
    FlashAllTool tool(fp);
    tool.Flash();
}

@@ -2143,12 +2112,8 @@ static void FastbootAborter(const char* message) {

int FastBootTool::Main(int argc, char* argv[]) {
    android::base::InitLogging(argv, FastbootLogger, FastbootAborter);
    std::unique_ptr<FlashingPlan> fp = std::make_unique<FlashingPlan>();

    bool wants_wipe = false;
    bool skip_reboot = false;
    bool wants_set_active = false;
    bool skip_secondary = false;
    bool force_flash = false;
    unsigned fs_options = 0;
    int longindex;
    std::string slot_override;
@@ -2201,7 +2166,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
            } else if (name == "disable-verity") {
                g_disable_verity = true;
            } else if (name == "force") {
                force_flash = true;
                fp->force_flash = true;
            } else if (name == "fs-options") {
                fs_options = ParseFsOption(optarg);
            } else if (name == "header-version") {
@@ -2220,9 +2185,9 @@ int FastBootTool::Main(int argc, char* argv[]) {
            } else if (name == "ramdisk-offset") {
                g_boot_img_hdr.ramdisk_addr = strtoul(optarg, 0, 16);
            } else if (name == "skip-reboot") {
                skip_reboot = true;
                fp->skip_reboot = true;
            } else if (name == "skip-secondary") {
                skip_secondary = true;
                fp->skip_secondary = true;
            } else if (name == "slot") {
                slot_override = optarg;
            } else if (name == "dtb-offset") {
@@ -2243,7 +2208,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
        } else {
            switch (c) {
                case 'a':
                    wants_set_active = true;
                    fp->wants_set_active = true;
                    if (optarg) next_active = optarg;
                    break;
                case 'h':
@@ -2263,7 +2228,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
                    set_verbose();
                    break;
                case 'w':
                    wants_wipe = true;
                    fp->wants_wipe = true;
                    break;
                case '?':
                    return 1;
@@ -2276,7 +2241,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
    argc -= optind;
    argv += optind;

    if (argc == 0 && !wants_wipe && !wants_set_active) syntax_error("no command");
    if (argc == 0 && !fp->wants_wipe && !fp->wants_set_active) syntax_error("no command");

    if (argc > 0 && !strcmp(*argv, "devices")) {
        list_devices();
@@ -2318,7 +2283,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
    if (slot_override != "") slot_override = verify_slot(slot_override);
    if (next_active != "") next_active = verify_slot(next_active, false);

    if (wants_set_active) {
    if (fp->wants_set_active) {
        if (next_active == "") {
            if (slot_override == "") {
                std::string current_slot;
@@ -2326,7 +2291,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
                    if (current_slot[0] == '_') current_slot.erase(0, 1);
                    next_active = verify_slot(current_slot, false);
                } else {
                    wants_set_active = false;
                    fp->wants_set_active = false;
                }
            } else {
                next_active = verify_slot(slot_override, false);
@@ -2418,7 +2383,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
                fname = find_item(pname);
            }
            if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
            FlashTask task(slot_override, force_flash, pname, fname);
            FlashTask task(slot_override, fp->force_flash, pname, fname);
            task.Run();
        } else if (command == "flash:raw") {
            std::string partition = next_arg(&args);
@@ -2437,9 +2402,10 @@ int FastBootTool::Main(int argc, char* argv[]) {
            if (slot_override == "all") {
                fprintf(stderr,
                        "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
                do_flashall(slot_override, true, wants_wipe, force_flash);
                fp->skip_secondary = true;
                do_flashall(fp.get());
            } else {
                do_flashall(slot_override, skip_secondary, wants_wipe, force_flash);
                do_flashall(fp.get());
            }
            reboot_task = std::make_unique<RebootTask>(fb);
        } else if (command == "update") {
@@ -2452,7 +2418,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
            if (!args.empty()) {
                filename = next_arg(&args);
            }
            do_update(filename.c_str(), slot_override, skip_secondary || slot_all, force_flash);
            do_update(filename.c_str(), fp.get());
            reboot_task = std::make_unique<RebootTask>(fb);
        } else if (command == FB_CMD_SET_ACTIVE) {
            std::string slot = verify_slot(next_arg(&args), false);
@@ -2525,8 +2491,8 @@ int FastBootTool::Main(int argc, char* argv[]) {
            syntax_error("unknown command %s", command.c_str());
        }
    }
    if (wants_wipe) {
        if (force_flash) {
    if (fp->wants_wipe) {
        if (fp->force_flash) {
            CancelSnapshotIfNeeded();
        }
        std::vector<std::string> partitions = {"userdata", "cache", "metadata"};
@@ -2540,10 +2506,10 @@ int FastBootTool::Main(int argc, char* argv[]) {
            fb_perform_format(partition, 1, partition_type, "", fs_options);
        }
    }
    if (wants_set_active) {
    if (fp->wants_set_active) {
        fb->SetActive(next_active);
    }
    if (reboot_task && !skip_reboot) {
    if (reboot_task && !fp->skip_reboot) {
        reboot_task->Run();
    }
    fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
+41 −0
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
#pragma once

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

#include <bootimg.h>

@@ -40,6 +42,45 @@ class FastBootTool {
    unsigned ParseFsOption(const char*);
};

enum class ImageType {
    // Must be flashed for device to boot into the kernel.
    BootCritical,
    // Normal partition to be flashed during "flashall".
    Normal,
    // Partition that is never flashed during "flashall".
    Extra
};

struct Image {
    std::string nickname;
    std::string img_name;
    std::string sig_name;
    std::string part_name;
    bool optional_if_no_image;
    ImageType type;
    bool IsSecondary() const { return nickname.empty(); }
};

using ImageEntry = std::pair<const Image*, std::string>;

struct FlashingPlan {
    // 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.
    ImageSource* source;
    bool wants_wipe = false;
    bool skip_reboot = false;
    bool wants_set_active = false;
    bool skip_secondary = false;
    bool force_flash = false;

    std::string slot;
    std::string current_slot;
    std::string secondary_slot;
    fastboot::FastBootDriver* fb;

};

bool should_flash_in_userspace(const std::string& partition_name);
bool is_userspace_fastboot();
void do_flash(const char* pname, const char* fname);