diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 517253078..e2e734efc 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -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 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 boot_images_; std::vector 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 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>& 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 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 fp = std::make_unique(); - 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(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(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 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)); diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h index b5fb8c0bf..c4366a960 100644 --- a/fastboot/fastboot.h +++ b/fastboot/fastboot.h @@ -28,6 +28,8 @@ #pragma once #include +#include "fastboot_driver.h" +#include "util.h" #include @@ -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; + +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);