From 9027af0d406a7ee4f285f55ed58ba227df268243 Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Mon, 24 Sep 2018 15:48:09 -0700 Subject: [PATCH] fastboot: remove engine.cpp/engine.h Replace the remnants of engine.cpp with better functionality in FastBootDriver. Particularly, add prolog() and epilog() callbacks to FastBootDriver for printing actions and their result to the console. Then clean up the rest of fastboot.cpp to directly use FastBootDriver. Test: fastboot works Change-Id: I0ff01d6a10f75e9dc1c82b46c6e9bb3bc4c68638 --- fastboot/Android.bp | 1 - fastboot/engine.cpp | 197 -------------------------- fastboot/fastboot.cpp | 200 ++++++++++++++++----------- fastboot/{engine.h => fastboot.h} | 44 +----- fastboot/fastboot_driver.cpp | 141 +++++++++++++------ fastboot/fastboot_driver.h | 59 ++++---- fastboot/fastboot_test.cpp | 2 +- fastboot/fuzzy_fastboot/fixtures.cpp | 6 +- fastboot/main.cpp | 2 +- fastboot/util.cpp | 5 - fastboot/util.h | 2 - 11 files changed, 260 insertions(+), 399 deletions(-) delete mode 100644 fastboot/engine.cpp rename fastboot/{engine.h => fastboot.h} (50%) diff --git a/fastboot/Android.bp b/fastboot/Android.bp index 6b175af7d..8c08c8603 100644 --- a/fastboot/Android.bp +++ b/fastboot/Android.bp @@ -202,7 +202,6 @@ cc_library_host_static { cpp_std: "c++17", srcs: [ "bootimg_utils.cpp", - "engine.cpp", "fastboot.cpp", "fs.cpp", "socket.cpp", diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp deleted file mode 100644 index a43e7a6bb..000000000 --- a/fastboot/engine.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#include "engine.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "constants.h" -#include "transport.h" - -using android::base::StringPrintf; - -static fastboot::FastBootDriver* fb = nullptr; - -void fb_init(fastboot::FastBootDriver& fbi) { - fb = &fbi; - auto cb = [](std::string& info) { fprintf(stderr, "(bootloader) %s\n", info.c_str()); }; - fb->SetInfoCallback(cb); -} - -void fb_reinit(Transport* transport) { - if (Transport* old_transport = fb->set_transport(transport)) { - delete old_transport; - } -} - -const std::string fb_get_error() { - return fb->Error(); -} - -bool fb_getvar(const std::string& key, std::string* value) { - return !fb->GetVar(key, value); -} - -static void HandleResult(double start, int status) { - if (status) { - fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str()); - die("Command failed"); - } else { - double split = now(); - fprintf(stderr, "OKAY [%7.3fs]\n", (split - start)); - } -} - -#define RUN_COMMAND(command) \ - { \ - double start = now(); \ - auto status = (command); \ - HandleResult(start, status); \ - } - -void fb_set_active(const std::string& slot) { - Status("Setting current slot to '" + slot + "'"); - RUN_COMMAND(fb->SetActive(slot)); -} - -void fb_erase(const std::string& partition) { - Status("Erasing '" + partition + "'"); - RUN_COMMAND(fb->Erase(partition)); -} - -void fb_flash_fd(const std::string& partition, int fd, uint32_t sz) { - Status(StringPrintf("Sending '%s' (%u KB)", partition.c_str(), sz / 1024)); - RUN_COMMAND(fb->Download(fd, sz)); - - Status("Writing '" + partition + "'"); - RUN_COMMAND(fb->Flash(partition)); -} - -void fb_flash(const std::string& partition, const std::vector& data) { - Status(StringPrintf("Sending '%s' (%zu KB)", partition.c_str(), data.size() / 1024)); - RUN_COMMAND(fb->Download(data)); - - Status("Writing '" + partition + "'"); - RUN_COMMAND(fb->Flash(partition)); -} - -void fb_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz, - size_t current, size_t total) { - Status(StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(), current, total, - sz / 1024)); - RUN_COMMAND(fb->Download(s)); - - Status(StringPrintf("Writing sparse '%s' %zu/%zu", partition.c_str(), current, total)); - RUN_COMMAND(fb->Flash(partition)); -} - -void fb_create_partition(const std::string& partition, const std::string& size) { - Status("Creating '" + partition + "'"); - RUN_COMMAND(fb->RawCommand(FB_CMD_CREATE_PARTITION ":" + partition + ":" + size)); -} - -void fb_delete_partition(const std::string& partition) { - Status("Deleting '" + partition + "'"); - RUN_COMMAND(fb->RawCommand(FB_CMD_DELETE_PARTITION ":" + partition)); -} - -void fb_resize_partition(const std::string& partition, const std::string& size) { - Status("Resizing '" + partition + "'"); - RUN_COMMAND(fb->RawCommand(FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size)); -} - -void fb_display(const std::string& label, const std::string& var) { - std::string value; - auto status = fb->GetVar(var, &value); - - if (status) { - fprintf(stderr, "getvar:%s FAILED (%s)\n", var.c_str(), fb->Error().c_str()); - return; - } - fprintf(stderr, "%s: %s\n", label.c_str(), value.c_str()); -} - -void fb_reboot() { - fprintf(stderr, "Rebooting"); - fb->Reboot(); - fprintf(stderr, "\n"); -} - -void fb_command(const std::string& cmd, const std::string& msg) { - Status(msg); - RUN_COMMAND(fb->RawCommand(cmd)); -} - -void fb_download(const std::string& name, const std::vector& data) { - Status("Downloading '" + name + "'"); - RUN_COMMAND(fb->Download(data)); -} - -void fb_download_fd(const std::string& name, int fd, uint32_t sz) { - Status(StringPrintf("Sending '%s' (%u KB)", name.c_str(), sz / 1024)); - RUN_COMMAND(fb->Download(fd, sz)); -} - -void fb_upload(const std::string& outfile) { - Status("Uploading '" + outfile + "'"); - RUN_COMMAND(fb->Upload(outfile)); -} - -void fb_notice(const std::string& notice) { - Status(notice); - fprintf(stderr, "\n"); -} - -void fb_wait_for_disconnect() { - fb->WaitForDisconnect(); -} - -bool fb_reboot_to_userspace() { - Status("Rebooting to userspace fastboot"); - verbose("\n"); - - if (fb->RebootTo("fastboot") != fastboot::RetCode::SUCCESS) { - fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str()); - return false; - } - fprintf(stderr, "OKAY\n"); - - fb_reinit(nullptr); - return true; -} diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index 5173babeb..59626507d 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -26,6 +26,8 @@ * SUCH DAMAGE. */ +#include "fastboot.h" + #include #include #include @@ -63,12 +65,13 @@ #include "bootimg_utils.h" #include "diagnose_usb.h" -#include "engine.h" +#include "fastboot_driver.h" #include "fs.h" #include "tcp.h" #include "transport.h" #include "udp.h" #include "usb.h" +#include "util.h" using android::base::ReadFully; using android::base::Split; @@ -98,6 +101,8 @@ static bool g_disable_verification = false; static const std::string convert_fbe_marker_filename("convert_fbe"); +fastboot::FastBootDriver* fb = nullptr; + enum fb_buffer_type { FB_BUFFER_FD, FB_BUFFER_SPARSE, @@ -179,6 +184,28 @@ static std::string find_item(const std::string& item) { return ""; } +double last_start_time; + +static void Status(const std::string& message) { + static constexpr char kStatusFormat[] = "%-50s "; + fprintf(stderr, kStatusFormat, message.c_str()); + last_start_time = now(); +} + +static void Epilog(int status) { + if (status) { + fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str()); + die("Command failed"); + } else { + double split = now(); + fprintf(stderr, "OKAY [%7.3fs]\n", (split - last_start_time)); + } +} + +static void InfoMessage(const std::string& info) { + fprintf(stderr, "(bootloader) %s\n", info.c_str()); +} + static int64_t get_file_size(int fd) { struct stat sb; if (fstat(fd, &sb) == -1) { @@ -606,9 +633,10 @@ static void CheckRequirement(const std::string& cur_product, const std::string& } std::string var_value; - if (!fb_getvar(var, &var_value)) { + if (fb->GetVar(var, &var_value) != fastboot::SUCCESS) { fprintf(stderr, "FAILED\n\n"); - fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(), fb_get_error().c_str()); + fprintf(stderr, "Could not getvar for '%s' (%s)\n\n", var.c_str(), + fb->Error().c_str()); die("requirements not met!"); } @@ -686,7 +714,7 @@ bool ParseRequirementLine(const std::string& line, std::string* name, std::strin static void HandlePartitionExists(const std::vector& options) { const std::string& partition_name = options[0]; std::string has_slot; - if (!fb_getvar("has-slot:" + partition_name, &has_slot) || + if (fb->GetVar("has-slot:" + partition_name, &has_slot) != fastboot::SUCCESS || (has_slot != "yes" && has_slot != "no")) { die("device doesn't have required partition %s!", partition_name.c_str()); } @@ -705,8 +733,8 @@ static void HandlePartitionExists(const std::vector& options) { static void CheckRequirements(const std::string& data) { std::string cur_product; - if (!fb_getvar("product", &cur_product)) { - fprintf(stderr, "getvar:product FAILED (%s)\n", fb_get_error().c_str()); + if (fb->GetVar("product", &cur_product) != fastboot::SUCCESS) { + fprintf(stderr, "getvar:product FAILED (%s)\n", fb->Error().c_str()); } auto lines = Split(data, "\n"); @@ -732,12 +760,24 @@ static void CheckRequirements(const std::string& data) { } } -static void dump_info() { - fb_notice("--------------------------------------------"); - fb_display("Bootloader Version...", "version-bootloader"); - fb_display("Baseband Version.....", "version-baseband"); - fb_display("Serial Number........", "serialno"); - fb_notice("--------------------------------------------"); +static void DisplayVarOrError(const std::string& label, const std::string& var) { + std::string value; + + if (fb->GetVar(var, &value) != fastboot::SUCCESS) { + Status("getvar:" + var); + fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str()); + return; + } + fprintf(stderr, "%s: %s\n", label.c_str(), value.c_str()); +} + +static void DumpInfo() { + fprintf(stderr, "--------------------------------------------\n"); + DisplayVarOrError("Bootloader Version...", "version-bootloader"); + DisplayVarOrError("Baseband Version.....", "version-baseband"); + DisplayVarOrError("Serial Number........", "serialno"); + fprintf(stderr, "--------------------------------------------\n"); + } static struct sparse_file** load_sparse_files(int fd, int64_t max_size) { @@ -762,7 +802,7 @@ static struct sparse_file** load_sparse_files(int fd, int64_t max_size) { static int64_t get_target_sparse_limit() { std::string max_download_size; - if (!fb_getvar("max-download-size", &max_download_size) || + if (fb->GetVar("max-download-size", &max_download_size) != fastboot::SUCCESS || max_download_size.empty()) { verbose("target didn't report max-download-size"); return 0; @@ -910,12 +950,12 @@ static void flash_buf(const std::string& partition, struct fastboot_buffer *buf) for (size_t i = 0; i < sparse_files.size(); ++i) { const auto& pair = sparse_files[i]; - fb_flash_sparse(partition, pair.first, pair.second, i + 1, sparse_files.size()); + fb->FlashPartition(partition, pair.first, pair.second, i + 1, sparse_files.size()); } break; } case FB_BUFFER_FD: - fb_flash_fd(partition, buf->fd, buf->sz); + fb->FlashPartition(partition, buf->fd, buf->sz); break; default: die("unknown buffer type: %d", buf->type); @@ -924,14 +964,15 @@ static void flash_buf(const std::string& partition, struct fastboot_buffer *buf) static std::string get_current_slot() { std::string current_slot; - if (!fb_getvar("current-slot", ¤t_slot)) return ""; + if (fb->GetVar("current-slot", ¤t_slot) != fastboot::SUCCESS) return ""; return current_slot; } static int get_slot_count() { std::string var; int count = 0; - if (!fb_getvar("slot-count", &var) || !android::base::ParseInt(var, &count)) { + if (fb->GetVar("slot-count", &var) != fastboot::SUCCESS || + !android::base::ParseInt(var, &count)) { return 0; } return count; @@ -1006,7 +1047,7 @@ static void do_for_partition(const std::string& part, const std::string& slot, std::string has_slot; std::string current_slot; - if (!fb_getvar("has-slot:" + part, &has_slot)) { + if (fb->GetVar("has-slot:" + part, &has_slot) != fastboot::SUCCESS) { /* If has-slot is not supported, the answer is no. */ has_slot = "no"; } @@ -1039,7 +1080,7 @@ static void do_for_partitions(const std::string& part, const std::string& slot, std::string has_slot; if (slot == "all") { - if (!fb_getvar("has-slot:" + part, &has_slot)) { + if (fb->GetVar("has-slot:" + part, &has_slot) != fastboot::SUCCESS) { die("Could not check if partition %s has slot %s", part.c_str(), slot.c_str()); } if (has_slot == "yes") { @@ -1069,25 +1110,25 @@ static void set_active(const std::string& slot_override) { if (!supports_AB()) return; if (slot_override != "") { - fb_set_active(slot_override); + fb->SetActive(slot_override); } else { std::string current_slot = get_current_slot(); if (current_slot != "") { - fb_set_active(current_slot); + fb->SetActive(current_slot); } } } static bool is_userspace_fastboot() { std::string value; - return fb_getvar("is-userspace", &value) && value == "yes"; + return fb->GetVar("is-userspace", &value) == fastboot::SUCCESS && value == "yes"; } static bool if_partition_exists(const std::string& partition, const std::string& slot) { std::string has_slot; std::string partition_name = partition; - if (fb_getvar("has-slot:" + partition, &has_slot) && has_slot == "yes") { + if (fb->GetVar("has-slot:" + partition, &has_slot) == fastboot::SUCCESS && has_slot == "yes") { if (slot == "") { std::string current_slot = get_current_slot(); if (current_slot == "") { @@ -1099,23 +1140,24 @@ static bool if_partition_exists(const std::string& partition, const std::string& } } std::string partition_size; - return fb_getvar("partition-size:" + partition_name, &partition_size); + return fb->GetVar("partition-size:" + partition_name, &partition_size) == fastboot::SUCCESS; } static bool is_logical(const std::string& partition) { std::string value; - return fb_getvar("is-logical:" + partition, &value) && value == "yes"; + return fb->GetVar("is-logical:" + partition, &value) == fastboot::SUCCESS && value == "yes"; } static void reboot_to_userspace_fastboot() { - if (!fb_reboot_to_userspace()) { - die("Must reboot to userspace fastboot to flash logical partitions"); - } + fb->RebootTo("fastboot"); + + auto* old_transport = fb->set_transport(nullptr); + delete old_transport; // Give the current connection time to close. std::this_thread::sleep_for(std::chrono::milliseconds(1000)); - fb_reinit(open_device()); + fb->set_transport(open_device()); } class ImageSource { @@ -1156,6 +1198,7 @@ FlashAllTool::FlashAllTool(const ImageSource& source, const std::string& slot_ov } void FlashAllTool::Flash() { + DumpInfo(); CheckRequirements(); DetermineSecondarySlot(); CollectImages(); @@ -1172,7 +1215,7 @@ void FlashAllTool::Flash() { for (const auto& [image, slot] : os_images_) { auto resize_partition = [](const std::string& partition) -> void { if (is_logical(partition)) { - fb_resize_partition(partition, "0"); + fb->ResizePartition(partition, "0"); } }; do_for_partitions(image->part_name, slot, resize_partition, false); @@ -1248,12 +1291,12 @@ void FlashAllTool::FlashImage(const Image& image, const std::string& slot, fastb auto flash = [&, this](const std::string& partition_name) { std::vector signature_data; if (source_.ReadFile(image.sig_name, &signature_data)) { - fb_download("signature", signature_data); - fb_command("signature", "installing signature"); + fb->Download("signature", signature_data); + fb->RawCommand("signature", "installing signature"); } if (is_logical(partition_name)) { - fb_resize_partition(partition_name, std::to_string(buf->image_size)); + fb->ResizePartition(partition_name, std::to_string(buf->image_size)); } flash_buf(partition_name.c_str(), buf); }; @@ -1272,13 +1315,13 @@ void FlashAllTool::UpdateSuperPartition() { if (!is_userspace_fastboot()) { reboot_to_userspace_fastboot(); } - fb_download_fd("super", fd, get_file_size(fd)); + fb->Download("super", fd, get_file_size(fd)); std::string command = "update-super:super"; if (wipe_) { command += ":wipe"; } - fb_command(command, "Updating super partition"); + fb->RawCommand(command, "Updating super partition"); } class ZipImageSource final : public ImageSource { @@ -1300,8 +1343,6 @@ int ZipImageSource::OpenFile(const std::string& name) const { } static void do_update(const char* filename, const std::string& slot_override, bool skip_secondary) { - dump_info(); - ZipArchiveHandle zip; int error = OpenArchive(filename, &zip); if (error != 0) { @@ -1334,9 +1375,6 @@ int LocalImageSource::OpenFile(const std::string& name) const { } static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe) { - std::string fname; - dump_info(); - FlashAllTool tool(LocalImageSource(), slot_override, skip_secondary, wipe); tool.Flash(); } @@ -1355,7 +1393,7 @@ static void do_oem_command(const std::string& cmd, std::vector* arg while (!args->empty()) { command += " " + next_arg(args); } - fb_command(command, ""); + fb->RawCommand(command, ""); } static std::string fb_fix_numeric_var(std::string var) { @@ -1369,7 +1407,7 @@ static std::string fb_fix_numeric_var(std::string var) { static unsigned fb_get_flash_block_size(std::string name) { std::string sizeString; - if (!fb_getvar(name, &sizeString) || sizeString.empty()) { + if (fb->GetVar(name, &sizeString) != fastboot::SUCCESS || sizeString.empty()) { // This device does not report flash block sizes, so return 0. return 0; } @@ -1407,7 +1445,7 @@ static void fb_perform_format( limit = sparse_limit; } - if (!fb_getvar("partition-type:" + partition, &partition_type)) { + if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) { errMsg = "Can't determine partition type.\n"; goto failed; } @@ -1419,7 +1457,7 @@ static void fb_perform_format( partition_type = type_override; } - if (!fb_getvar("partition-size:" + partition, &partition_size)) { + if (fb->GetVar("partition-size:" + partition, &partition_size) != fastboot::SUCCESS) { errMsg = "Unable to get partition size\n"; goto failed; } @@ -1477,7 +1515,7 @@ failed: fprintf(stderr, "Erase successful, but not automatically formatting.\n"); if (errMsg) fprintf(stderr, "%s", errMsg); } - fprintf(stderr, "FAILED (%s)\n", fb_get_error().c_str()); + fprintf(stderr, "FAILED (%s)\n", fb->Error().c_str()); } int FastBootTool::Main(int argc, char* argv[]) { @@ -1627,8 +1665,13 @@ int FastBootTool::Main(int argc, char* argv[]) { if (transport == nullptr) { return 1; } - fastboot::FastBootDriver fb(transport); - fb_init(fb); + fastboot::DriverCallbacks driver_callbacks = { + .prolog = Status, + .epilog = Epilog, + .info = InfoMessage, + }; + fastboot::FastBootDriver fastboot_driver(transport, driver_callbacks, false); + fb = &fastboot_driver; const double start = now(); @@ -1639,7 +1682,7 @@ int FastBootTool::Main(int argc, char* argv[]) { if (next_active == "") { if (slot_override == "") { std::string current_slot; - if (fb_getvar("current-slot", ¤t_slot)) { + if (fb->GetVar("current-slot", ¤t_slot) == fastboot::SUCCESS) { next_active = verify_slot(current_slot, false); } else { wants_set_active = false; @@ -1656,19 +1699,18 @@ int FastBootTool::Main(int argc, char* argv[]) { if (command == "getvar") { std::string variable = next_arg(&args); - fb_display(variable, variable); + DisplayVarOrError(variable, variable); } else if (command == "erase") { std::string partition = next_arg(&args); auto erase = [&](const std::string& partition) { std::string partition_type; - if (fb_getvar(std::string("partition-type:") + partition, - &partition_type) && + if (fb->GetVar("partition-type:" + partition, &partition_type) == fastboot::SUCCESS && fs_get_generator(partition_type) != nullptr) { fprintf(stderr, "******** Did you mean to fastboot format this %s partition?\n", partition_type.c_str()); } - fb_erase(partition); + fb->Erase(partition); }; do_for_partitions(partition, slot_override, erase, true); } else if (android::base::StartsWith(command, "format")) { @@ -1698,8 +1740,8 @@ int FastBootTool::Main(int argc, char* argv[]) { die("could not load '%s': %s", filename.c_str(), strerror(errno)); } if (data.size() != 256) die("signature must be 256 bytes (got %zu)", data.size()); - fb_download("signature", data); - fb_command("signature", "installing signature"); + fb->Download("signature", data); + fb->RawCommand("signature", "installing signature"); } else if (command == "reboot") { wants_reboot = true; @@ -1727,7 +1769,7 @@ int FastBootTool::Main(int argc, char* argv[]) { } else if (command == "reboot-fastboot") { wants_reboot_fastboot = true; } else if (command == "continue") { - fb_command("continue", "resuming boot"); + fb->Continue(); } else if (command == "boot") { std::string kernel = next_arg(&args); std::string ramdisk; @@ -1736,8 +1778,8 @@ int FastBootTool::Main(int argc, char* argv[]) { if (!args.empty()) second_stage = next_arg(&args); auto data = LoadBootableImage(kernel, ramdisk, second_stage); - fb_download("boot.img", data); - fb_command("boot", "booting"); + fb->Download("boot.img", data); + fb->Boot(); } else if (command == "flash") { std::string pname = next_arg(&args); @@ -1763,7 +1805,7 @@ int FastBootTool::Main(int argc, char* argv[]) { auto data = LoadBootableImage(kernel, ramdisk, second_stage); auto flashraw = [&data](const std::string& partition) { - fb_flash(partition, data); + fb->FlashPartition(partition, data); }; do_for_partitions(partition, slot_override, flashraw, true); } else if (command == "flashall") { @@ -1787,7 +1829,7 @@ int FastBootTool::Main(int argc, char* argv[]) { wants_reboot = true; } else if (command == "set_active") { std::string slot = verify_slot(next_arg(&args), false); - fb_set_active(slot); + fb->SetActive(slot); } else if (command == "stage") { std::string filename = next_arg(&args); @@ -1795,10 +1837,10 @@ int FastBootTool::Main(int argc, char* argv[]) { if (!load_buf(filename.c_str(), &buf) || buf.type != FB_BUFFER_FD) { die("cannot load '%s'", filename.c_str()); } - fb_download_fd(filename, buf.fd, buf.sz); + fb->Download(filename, buf.fd, buf.sz); } else if (command == "get_staged") { std::string filename = next_arg(&args); - fb_upload(filename); + fb->Upload(filename); } else if (command == "oem") { do_oem_command("oem", &args); } else if (command == "flashing") { @@ -1815,14 +1857,14 @@ int FastBootTool::Main(int argc, char* argv[]) { } else if (command == "create-logical-partition") { std::string partition = next_arg(&args); std::string size = next_arg(&args); - fb_create_partition(partition, size); + fb->CreatePartition(partition, size); } else if (command == "delete-logical-partition") { std::string partition = next_arg(&args); - fb_delete_partition(partition); + fb->DeletePartition(partition); } else if (command == "resize-logical-partition") { std::string partition = next_arg(&args); std::string size = next_arg(&args); - fb_resize_partition(partition, size); + fb->ResizePartition(partition, size); } else { syntax_error("unknown command %s", command.c_str()); } @@ -1832,9 +1874,11 @@ int FastBootTool::Main(int argc, char* argv[]) { std::vector partitions = { "userdata", "cache", "metadata" }; for (const auto& partition : partitions) { std::string partition_type; - if (!fb_getvar(std::string{"partition-type:"} + partition, &partition_type)) continue; + if (fb->GetVar("partition-type:" + partition, &partition_type) != fastboot::SUCCESS) { + continue; + } if (partition_type.empty()) continue; - fb_erase(partition); + fb->Erase(partition); if (partition == "userdata" && set_fbe_marker) { fprintf(stderr, "setting FBE marker on initial userdata...\n"); std::string initial_userdata_dir = create_fbemarker_tmpdir(); @@ -1846,27 +1890,27 @@ int FastBootTool::Main(int argc, char* argv[]) { } } if (wants_set_active) { - fb_set_active(next_active); + fb->SetActive(next_active); } if (wants_reboot && !skip_reboot) { - fb_reboot(); - fb_wait_for_disconnect(); + fb->Reboot(); + fb->WaitForDisconnect(); } else if (wants_reboot_bootloader) { - fb_command("reboot-bootloader", "rebooting into bootloader"); - fb_wait_for_disconnect(); + fb->RebootTo("bootloader"); + fb->WaitForDisconnect(); } else if (wants_reboot_recovery) { - fb_command("reboot-recovery", "rebooting into recovery"); - fb_wait_for_disconnect(); + fb->RebootTo("recovery"); + fb->WaitForDisconnect(); } else if (wants_reboot_fastboot) { - fb_command("reboot-fastboot", "rebooting into fastboot"); - fb_wait_for_disconnect(); + fb->RebootTo("fastboot"); + fb->WaitForDisconnect(); } fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start)); - if (Transport* old_transport = fb.set_transport(nullptr)) { - delete old_transport; - } + auto* old_transport = fb->set_transport(nullptr); + delete old_transport; + return 0; } diff --git a/fastboot/engine.h b/fastboot/fastboot.h similarity index 50% rename from fastboot/engine.h rename to fastboot/fastboot.h index b681f5ab3..9f1825366 100644 --- a/fastboot/engine.h +++ b/fastboot/fastboot.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 The Android Open Source Project + * Copyright (C) 2018 The Android Open Source Project * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,49 +26,7 @@ * SUCH DAMAGE. */ -#pragma once - -#include -#include - -#include - #include -#include "fastboot_driver.h" -#include "util.h" - -#include "constants.h" - -class Transport; -struct sparse_file; - -const std::string fb_get_error(); - -void fb_init(fastboot::FastBootDriver& fbi); -void fb_reinit(Transport* transport); - -bool fb_getvar(const std::string& key, std::string* value); -void fb_flash(const std::string& partition, const std::vector& data); -void fb_flash_fd(const std::string& partition, int fd, uint32_t sz); -void fb_flash_sparse(const std::string& partition, struct sparse_file* s, uint32_t sz, - size_t current, size_t total); -void fb_erase(const std::string& partition); -void fb_display(const std::string& label, const std::string& var); -void fb_reboot(); -void fb_command(const std::string& cmd, const std::string& msg); -void fb_download(const std::string& name, const std::vector& data); -void fb_download_fd(const std::string& name, int fd, uint32_t sz); -void fb_upload(const std::string& outfile); -void fb_notice(const std::string& notice); -void fb_wait_for_disconnect(void); -void fb_create_partition(const std::string& partition, const std::string& size); -void fb_delete_partition(const std::string& partition); -void fb_resize_partition(const std::string& partition, const std::string& size); -void fb_set_active(const std::string& slot); -bool fb_reboot_to_userspace(); - -/* Current product */ -extern char cur_product[FB_RESPONSE_SZ + 1]; class FastBootTool { public: diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp index 72ba6194b..b1f3bc91b 100644 --- a/fastboot/fastboot_driver.cpp +++ b/fastboot/fastboot_driver.cpp @@ -25,6 +25,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ + #include "fastboot_driver.h" #include @@ -44,43 +45,56 @@ #include #include #include -#include "fastboot_driver.h" + +#include "constants.h" #include "transport.h" +using android::base::StringPrintf; + namespace fastboot { /*************************** PUBLIC *******************************/ -FastBootDriver::FastBootDriver(Transport* transport, std::function info, +FastBootDriver::FastBootDriver(Transport* transport, DriverCallbacks driver_callbacks, bool no_checks) - : transport_(transport) { - info_cb_ = info; - disable_checks_ = no_checks; -} + : transport_(transport), + prolog_(std::move(driver_callbacks.prolog)), + epilog_(std::move(driver_callbacks.epilog)), + info_(std::move(driver_callbacks.info)), + disable_checks_(no_checks) {} FastBootDriver::~FastBootDriver() { } RetCode FastBootDriver::Boot(std::string* response, std::vector* info) { - return RawCommand(Commands::BOOT, response, info); + return RawCommand(FB_CMD_BOOT, "Booting", response, info); } RetCode FastBootDriver::Continue(std::string* response, std::vector* info) { - return RawCommand(Commands::CONTINUE, response, info); + return RawCommand(FB_CMD_CONTINUE, "Resuming boot", response, info); } -RetCode FastBootDriver::Erase(const std::string& part, std::string* response, - std::vector* info) { - return RawCommand(Commands::ERASE + part, response, info); +RetCode FastBootDriver::CreatePartition(const std::string& partition, const std::string& size) { + return RawCommand(FB_CMD_CREATE_PARTITION ":" + partition + ":" + size, + "Creating '" + partition + "'"); } -RetCode FastBootDriver::Flash(const std::string& part, std::string* response, +RetCode FastBootDriver::DeletePartition(const std::string& partition) { + return RawCommand(FB_CMD_DELETE_PARTITION ":" + partition, "Deleting '" + partition + "'"); +} + +RetCode FastBootDriver::Erase(const std::string& partition, std::string* response, std::vector* info) { - return RawCommand(Commands::FLASH + part, response, info); + return RawCommand(FB_CMD_ERASE ":" + partition, "Erasing '" + partition + "'", response, info); +} + +RetCode FastBootDriver::Flash(const std::string& partition, std::string* response, + std::vector* info) { + return RawCommand(FB_CMD_FLASH ":" + partition, "Writing '" + partition + "'", response, info); } RetCode FastBootDriver::GetVar(const std::string& key, std::string* val, std::vector* info) { - return RawCommand(Commands::GET_VAR + key, val, info); + return RawCommand(FB_CMD_GETVAR ":" + key, val, info); } RetCode FastBootDriver::GetVarAll(std::vector* response) { @@ -89,44 +103,52 @@ RetCode FastBootDriver::GetVarAll(std::vector* response) { } RetCode FastBootDriver::Reboot(std::string* response, std::vector* info) { - return RawCommand(Commands::REBOOT, response, info); + return RawCommand(FB_CMD_REBOOT, "Rebooting", response, info); } RetCode FastBootDriver::RebootTo(std::string target, std::string* response, std::vector* info) { - return RawCommand("reboot-" + target, response, info); + return RawCommand("reboot-" + target, "Rebooting into " + target, response, info); +} + +RetCode FastBootDriver::ResizePartition(const std::string& partition, const std::string& size) { + return RawCommand(FB_CMD_RESIZE_PARTITION ":" + partition + ":" + size, + "Resizing '" + partition + "'"); } RetCode FastBootDriver::SetActive(const std::string& slot, std::string* response, std::vector* info) { - return RawCommand(Commands::SET_ACTIVE + slot, response, info); + return RawCommand(FB_CMD_SET_ACTIVE ":" + slot, "Setting current slot to '" + slot + "'", + response, info); } -RetCode FastBootDriver::FlashPartition(const std::string& part, const std::vector& data) { +RetCode FastBootDriver::FlashPartition(const std::string& partition, + const std::vector& data) { RetCode ret; - if ((ret = Download(data))) { + if ((ret = Download(partition, data))) { return ret; } - return RawCommand(Commands::FLASH + part); + return Flash(partition); } -RetCode FastBootDriver::FlashPartition(const std::string& part, int fd, uint32_t sz) { +RetCode FastBootDriver::FlashPartition(const std::string& partition, int fd, uint32_t size) { RetCode ret; - if ((ret = Download(fd, sz))) { + if ((ret = Download(partition, fd, size))) { return ret; } - return RawCommand(Commands::FLASH + part); + return Flash(partition); } -RetCode FastBootDriver::FlashPartition(const std::string& part, sparse_file* s) { +RetCode FastBootDriver::FlashPartition(const std::string& partition, sparse_file* s, uint32_t size, + size_t current, size_t total) { RetCode ret; - if ((ret = Download(s))) { + if ((ret = Download(partition, s, size, current, total, false))) { return ret; } - return RawCommand(Commands::FLASH + part); + return Flash(partition); } -RetCode FastBootDriver::Partitions(std::vector>* parts) { +RetCode FastBootDriver::Partitions(std::vector>* partitions) { std::vector all; RetCode ret; if ((ret = GetVarAll(&all))) { @@ -141,12 +163,20 @@ RetCode FastBootDriver::Partitions(std::vector std::string m1(sm[1]); std::string m2(sm[2]); uint64_t tmp = strtoll(m2.c_str(), 0, 16); - parts->push_back(std::make_tuple(m1, tmp)); + partitions->push_back(std::make_tuple(m1, tmp)); } } return SUCCESS; } +RetCode FastBootDriver::Download(const std::string& name, int fd, size_t size, + std::string* response, std::vector* info) { + prolog_(StringPrintf("Sending '%s' (%zu KB)", name.c_str(), size / 1024)); + auto result = Download(fd, size, response, info); + epilog_(result); + return result; +} + RetCode FastBootDriver::Download(int fd, size_t size, std::string* response, std::vector* info) { RetCode ret; @@ -170,6 +200,14 @@ RetCode FastBootDriver::Download(int fd, size_t size, std::string* response, return HandleResponse(response, info); } +RetCode FastBootDriver::Download(const std::string& name, const std::vector& buf, + std::string* response, std::vector* info) { + prolog_(StringPrintf("Sending '%s' (%zu KB)", name.c_str(), buf.size() / 1024)); + auto result = Download(buf, response, info); + epilog_(result); + return result; +} + RetCode FastBootDriver::Download(const std::vector& buf, std::string* response, std::vector* info) { RetCode ret; @@ -192,6 +230,16 @@ RetCode FastBootDriver::Download(const std::vector& buf, std::string* resp return HandleResponse(response, info); } +RetCode FastBootDriver::Download(const std::string& partition, struct sparse_file* s, uint32_t size, + size_t current, size_t total, bool use_crc, std::string* response, + std::vector* info) { + prolog_(StringPrintf("Sending sparse '%s' %zu/%zu (%u KB)", partition.c_str(), current, total, + size / 1024)); + auto result = Download(s, use_crc, response, info); + epilog_(result); + return result; +} + RetCode FastBootDriver::Download(sparse_file* s, bool use_crc, std::string* response, std::vector* info) { error_ = ""; @@ -234,9 +282,17 @@ RetCode FastBootDriver::Download(sparse_file* s, bool use_crc, std::string* resp RetCode FastBootDriver::Upload(const std::string& outfile, std::string* response, std::vector* info) { + prolog_("Uploading '" + outfile + "'"); + auto result = UploadInner(outfile, response, info); + epilog_(result); + return result; +} + +RetCode FastBootDriver::UploadInner(const std::string& outfile, std::string* response, + std::vector* info) { RetCode ret; int dsize; - if ((ret = RawCommand(Commands::UPLOAD, response, info, &dsize))) { + if ((ret = RawCommand(FB_CMD_UPLOAD, response, info, &dsize))) { error_ = "Upload request failed: " + error_; return ret; } @@ -270,8 +326,8 @@ RetCode FastBootDriver::Upload(const std::string& outfile, std::string* response } // Helpers -void FastBootDriver::SetInfoCallback(std::function info) { - info_cb_ = info; +void FastBootDriver::SetInfoCallback(std::function info) { + info_ = info; } const std::string FastBootDriver::RCString(RetCode rc) { @@ -308,6 +364,15 @@ RetCode FastBootDriver::WaitForDisconnect() { } /****************************** PROTECTED *************************************/ +RetCode FastBootDriver::RawCommand(const std::string& cmd, const std::string& message, + std::string* response, std::vector* info, + int* dsize) { + prolog_(message); + auto result = RawCommand(cmd, response, info, dsize); + epilog_(result); + return result; +} + RetCode FastBootDriver::RawCommand(const std::string& cmd, std::string* response, std::vector* info, int* dsize) { error_ = ""; // Clear any pending error @@ -327,7 +392,7 @@ RetCode FastBootDriver::RawCommand(const std::string& cmd, std::string* response RetCode FastBootDriver::DownloadCommand(uint32_t size, std::string* response, std::vector* info) { - std::string cmd(android::base::StringPrintf("%s%08" PRIx32, Commands::DOWNLOAD.c_str(), size)); + std::string cmd(android::base::StringPrintf("%s:%08" PRIx32, FB_CMD_DOWNLOAD, size)); RetCode ret; if ((ret = RawCommand(cmd, response, info))) { return ret; @@ -360,7 +425,7 @@ RetCode FastBootDriver::HandleResponse(std::string* response, std::vector prolog = [](const std::string&) {}; + std::function epilog = [](int) {}; + std::function info = [](const std::string&) {}; +}; + class FastBootDriver { friend class FastBootTest; @@ -63,22 +69,30 @@ class FastBootDriver { static constexpr uint32_t MAX_DOWNLOAD_SIZE = std::numeric_limits::max(); static constexpr size_t TRANSPORT_CHUNK_SIZE = 1024; - FastBootDriver(Transport* transport, - std::function info = [](std::string&) {}, + FastBootDriver(Transport* transport, DriverCallbacks driver_callbacks = {}, bool no_checks = false); ~FastBootDriver(); RetCode Boot(std::string* response = nullptr, std::vector* info = nullptr); RetCode Continue(std::string* response = nullptr, std::vector* info = nullptr); + RetCode CreatePartition(const std::string& partition, const std::string& size); + RetCode DeletePartition(const std::string& partition); + RetCode Download(const std::string& name, int fd, size_t size, std::string* response = nullptr, + std::vector* info = nullptr); RetCode Download(int fd, size_t size, std::string* response = nullptr, std::vector* info = nullptr); + RetCode Download(const std::string& name, const std::vector& buf, + std::string* response = nullptr, std::vector* info = nullptr); RetCode Download(const std::vector& buf, std::string* response = nullptr, std::vector* info = nullptr); + RetCode Download(const std::string& partition, struct sparse_file* s, uint32_t sz, + size_t current, size_t total, bool use_crc, std::string* response = nullptr, + std::vector* info = nullptr); RetCode Download(sparse_file* s, bool use_crc = false, std::string* response = nullptr, std::vector* info = nullptr); - RetCode Erase(const std::string& part, std::string* response = nullptr, + RetCode Erase(const std::string& partition, std::string* response = nullptr, std::vector* info = nullptr); - RetCode Flash(const std::string& part, std::string* response = nullptr, + RetCode Flash(const std::string& partition, std::string* response = nullptr, std::vector* info = nullptr); RetCode GetVar(const std::string& key, std::string* val, std::vector* info = nullptr); @@ -86,22 +100,24 @@ class FastBootDriver { RetCode Reboot(std::string* response = nullptr, std::vector* info = nullptr); RetCode RebootTo(std::string target, std::string* response = nullptr, std::vector* info = nullptr); + RetCode ResizePartition(const std::string& partition, const std::string& size); RetCode SetActive(const std::string& slot, std::string* response = nullptr, std::vector* info = nullptr); RetCode Upload(const std::string& outfile, std::string* response = nullptr, std::vector* info = nullptr); /* HIGHER LEVEL COMMANDS -- Composed of the commands above */ - RetCode FlashPartition(const std::string& part, const std::vector& data); - RetCode FlashPartition(const std::string& part, int fd, uint32_t sz); - RetCode FlashPartition(const std::string& part, sparse_file* s); + RetCode FlashPartition(const std::string& partition, const std::vector& data); + RetCode FlashPartition(const std::string& partition, int fd, uint32_t sz); + RetCode FlashPartition(const std::string& partition, sparse_file* s, uint32_t sz, + size_t current, size_t total); - RetCode Partitions(std::vector>* parts); + RetCode Partitions(std::vector>* partitions); RetCode Require(const std::string& var, const std::vector& allowed, bool* reqmet, bool invert = false); /* HELPERS */ - void SetInfoCallback(std::function info); + void SetInfoCallback(std::function info); static const std::string RCString(RetCode rc); std::string Error(); RetCode WaitForDisconnect(); @@ -110,7 +126,10 @@ class FastBootDriver { Transport* set_transport(Transport* transport); Transport* transport() const { return transport_; } - // This is temporarily public for engine.cpp + RetCode RawCommand(const std::string& cmd, const std::string& message, + std::string* response = nullptr, std::vector* info = nullptr, + int* dsize = nullptr); + RetCode RawCommand(const std::string& cmd, std::string* response = nullptr, std::vector* info = nullptr, int* dsize = nullptr); @@ -122,19 +141,6 @@ class FastBootDriver { std::string ErrnoStr(const std::string& msg); - // More like a namespace... - struct Commands { - static const std::string BOOT; - static const std::string CONTINUE; - static const std::string DOWNLOAD; - static const std::string ERASE; - static const std::string FLASH; - static const std::string GET_VAR; - static const std::string REBOOT; - static const std::string SET_ACTIVE; - static const std::string UPLOAD; - }; - Transport* transport_; private: @@ -145,10 +151,15 @@ class FastBootDriver { RetCode ReadBuffer(std::vector& buf); RetCode ReadBuffer(void* buf, size_t size); + RetCode UploadInner(const std::string& outfile, std::string* response = nullptr, + std::vector* info = nullptr); + int SparseWriteCallback(std::vector& tpbuf, const char* data, size_t len); std::string error_; - std::function info_cb_; + std::function prolog_; + std::function epilog_; + std::function info_; bool disable_checks_; }; diff --git a/fastboot/fastboot_test.cpp b/fastboot/fastboot_test.cpp index e0bbd561f..9c3ab6e66 100644 --- a/fastboot/fastboot_test.cpp +++ b/fastboot/fastboot_test.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "engine.h" +#include "fastboot.h" #include diff --git a/fastboot/fuzzy_fastboot/fixtures.cpp b/fastboot/fuzzy_fastboot/fixtures.cpp index 4da71ca58..c18af1d8d 100644 --- a/fastboot/fuzzy_fastboot/fixtures.cpp +++ b/fastboot/fuzzy_fastboot/fixtures.cpp @@ -121,8 +121,7 @@ void FastBootTest::SetUp() { } else { ASSERT_EQ(device_path, cb_scratch); // The path can not change } - fb = std::unique_ptr( - new FastBootDriver(transport.get(), [](std::string&) {}, true)); + fb = std::unique_ptr(new FastBootDriver(transport.get(), {}, true)); } void FastBootTest::TearDown() { @@ -204,8 +203,7 @@ void FastBootTest::SetLockState(bool unlock, bool assert_change) { putchar('.'); } device_path = cb_scratch; - fb = std::unique_ptr( - new FastBootDriver(transport.get(), [](std::string&) {}, true)); + fb = std::unique_ptr(new FastBootDriver(transport.get(), {}, true)); if (assert_change) { ASSERT_EQ(fb->GetVar("unlocked", &resp), SUCCESS) << "getvar:unlocked failed"; ASSERT_EQ(resp, unlock ? "yes" : "no") diff --git a/fastboot/main.cpp b/fastboot/main.cpp index c3683f737..35f421894 100644 --- a/fastboot/main.cpp +++ b/fastboot/main.cpp @@ -26,7 +26,7 @@ * SUCH DAMAGE. */ -#include "engine.h" +#include "fastboot.h" int main(int argc, char* argv[]) { FastBootTool fb; diff --git a/fastboot/util.cpp b/fastboot/util.cpp index 7d15047ff..d02b37fee 100644 --- a/fastboot/util.cpp +++ b/fastboot/util.cpp @@ -69,8 +69,3 @@ void verbose(const char* fmt, ...) { } fprintf(stderr, "\n"); } - -void Status(const std::string& message) { - static constexpr char kStatusFormat[] = "%-50s "; - fprintf(stderr, kStatusFormat, message.c_str()); -} diff --git a/fastboot/util.h b/fastboot/util.h index 533d2c708..2535414f5 100644 --- a/fastboot/util.h +++ b/fastboot/util.h @@ -11,8 +11,6 @@ double now(); void set_verbose(); -void Status(const std::string& message); - // These printf-like functions are implemented in terms of vsnprintf, so they // use the same attribute for compile-time format string checking. void die(const char* fmt, ...) __attribute__((__noreturn__))