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

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

Merge "Added Flashing Plan"

parents e89ee18b 7df2ab9c
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 },
@@ -1604,8 +1585,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();

@@ -1625,25 +1605,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();
@@ -1651,10 +1618,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();
@@ -1691,13 +1658,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;
@@ -1714,7 +1681,7 @@ bool FlashAllTool::OptimizedFlashSuper() {
        return false;
    }

    SuperFlashHelper helper(source_);
    SuperFlashHelper helper(*fp_->source);
    if (!helper.Open(fd)) {
        return false;
    }
@@ -1754,43 +1721,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);
@@ -1803,7 +1770,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;
@@ -1817,7 +1784,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");
        }
@@ -1831,7 +1798,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;
    }
@@ -1846,7 +1813,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");
@@ -1868,7 +1835,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;
@@ -1897,15 +1864,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);
@@ -1930,9 +1898,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();
}

@@ -2167,12 +2136,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;
@@ -2225,7 +2190,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") {
@@ -2244,9 +2209,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") {
@@ -2267,7 +2232,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':
@@ -2287,7 +2252,7 @@ int FastBootTool::Main(int argc, char* argv[]) {
                    set_verbose();
                    break;
                case 'w':
                    wants_wipe = true;
                    fp->wants_wipe = true;
                    break;
                case '?':
                    return 1;
@@ -2300,7 +2265,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();
@@ -2342,7 +2307,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;
@@ -2350,7 +2315,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);
@@ -2442,7 +2407,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);
@@ -2461,9 +2426,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") {
@@ -2476,7 +2442,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);
@@ -2549,8 +2515,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"};
@@ -2564,10 +2530,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);