From c3ade7f48a479ff29d2265a6ba754d9ed56e9120 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 23 Aug 2018 10:42:02 -0700 Subject: [PATCH 1/2] fastboot: Use _WIN32 instead of WIN32. Bug: N/A Test: fastboot.exe builds Change-Id: I316611f581c80ec813b953a7e6074293399ab7d7 --- fastboot/fs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp index b0ac2ef4f..fc6a16bb2 100644 --- a/fastboot/fs.cpp +++ b/fastboot/fs.cpp @@ -8,7 +8,7 @@ #include #include #include -#ifndef WIN32 +#ifndef _WIN32 #include #else #include @@ -27,7 +27,7 @@ using android::base::GetExecutableDirectory; using android::base::StringPrintf; using android::base::unique_fd; -#ifdef WIN32 +#ifdef _WIN32 static int exec_cmd(const char* path, const char** argv, const char** envp) { std::string cmd; int i = 0; From 32e376f8480b267d72dfe9730fe978611bdbfa89 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Thu, 16 Aug 2018 13:43:11 -0700 Subject: [PATCH 2/2] fastbootd: Support flashall with logical partitions. Currently, fastboot flashall will try to flash every partition in the image list. For devices with logical partitions, this will cause those partitions to be flashed twice (once via super.img, and again for each individual image). Additionally, super.img is needed to synchronize the logical partition list, but it is only generated with "make dist", making it inconvenient for most workflows. This patch removes automatic flashing of super.img. Instead, devices with a super partition must now generate a "super_empty.img" describing the super geometry and logical partition layout. Before flashing any other partitions, this image is used to ensure the device has created all necessary logical partitions. Additionally, before flashing (but after updating super), all logical partitions that will be flashed are resized to 0. This ensures that logical partitions will receive more optimal space allocation. Finally, during flashing of individual images, logical partitions are resized to the image size, since they do not have hardcoded sizes in the build. Bug: 78793464 Test: fastboot flashall can flash vendor, product, product_services without a make dist/super.img. Change-Id: I18c2291e0d0cb10de729c5646b75ac84dde8c871 --- fastboot/Android.mk | 2 +- fastboot/fastboot.cpp | 94 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 83 insertions(+), 13 deletions(-) diff --git a/fastboot/Android.mk b/fastboot/Android.mk index a679143ca..7da0a9fbb 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -64,6 +64,7 @@ LOCAL_SRC_FILES_windows := usb_windows.cpp LOCAL_C_INCLUDES_windows := development/host/windows/usb/api LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) +LOCAL_CPP_STD := c++17 LOCAL_CXX_STL := $(fastboot_stl) LOCAL_HEADER_LIBRARIES := bootimg_headers LOCAL_LDLIBS_darwin := $(fastboot_ldlibs_darwin) @@ -82,7 +83,6 @@ LOCAL_MODULE_HOST_OS := darwin linux windows LOCAL_CFLAGS := $(fastboot_cflags) LOCAL_CFLAGS_darwin := $(fastboot_cflags_darwin) -LOCAL_CPP_STD := c++17 LOCAL_CXX_STL := $(fastboot_stl) LOCAL_HEADER_LIBRARIES := bootimg_headers LOCAL_LDLIBS_darwin := $(fastboot_ldlibs_darwin) diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp index dc94952ba..862366687 100644 --- a/fastboot/fastboot.cpp +++ b/fastboot/fastboot.cpp @@ -104,9 +104,10 @@ struct fastboot_buffer { void* data; int64_t sz; int fd; + int64_t image_size; }; -static struct { +struct Image { const char* nickname; const char* img_name; const char* sig_name; @@ -114,7 +115,9 @@ static struct { bool optional_if_no_image; bool optional_if_no_partition; bool IsSecondary() const { return nickname == nullptr; } -} images[] = { +}; + +static Image images[] = { // clang-format off { "boot", "boot.img", "boot.sig", "boot", false, false }, { nullptr, "boot_other.img", "boot.sig", "boot", true, false }, @@ -128,7 +131,6 @@ static struct { "product_services", true, true }, { "recovery", "recovery.img", "recovery.sig", "recovery", true, false }, - { "super", "super.img", "super.sig", "super", true, true }, { "system", "system.img", "system.sig", "system", false, true }, { nullptr, "system_other.img", "system.sig", "system", true, false }, { "vbmeta", "vbmeta.img", "vbmeta.sig", "vbmeta", true, false }, @@ -773,6 +775,13 @@ static bool load_buf_fd(int fd, struct fastboot_buffer* buf) { return false; } + if (sparse_file* s = sparse_file_import_auto(fd, false, false)) { + buf->image_size = sparse_file_len(s, false, false); + sparse_file_destroy(s); + } else { + buf->image_size = sz; + } + lseek64(fd, 0, SEEK_SET); int64_t limit = get_sparse_limit(sz); if (limit) { @@ -1044,6 +1053,11 @@ static void set_active(const std::string& slot_override) { } } +static bool is_userspace_fastboot() { + std::string value; + return fb_getvar("is-userspace", &value) && value == "yes"; +} + static bool if_partition_exists(const std::string& partition, const std::string& slot) { std::string has_slot; std::string partition_name = partition; @@ -1158,7 +1172,42 @@ static void do_send_signature(const std::string& fn) { fb_queue_command("signature", "installing signature"); } -static void do_flashall(const std::string& slot_override, bool skip_secondary) { +static bool is_logical(const std::string& partition) { + std::string value; + return fb_getvar("is-logical:" + partition, &value) && value == "yes"; +} + +static void update_super_partition(bool force_wipe) { + if (!if_partition_exists("super", "")) { + return; + } + std::string image = find_item_given_name("super_empty.img"); + if (access(image.c_str(), R_OK) < 0) { + return; + } + + if (!is_userspace_fastboot()) { + die("Must have userspace fastboot to flash logical partitions"); + } + + int fd = open(image.c_str(), O_RDONLY); + if (fd < 0) { + die("could not open '%s': %s", image.c_str(), strerror(errno)); + } + fb_queue_download_fd("super", fd, get_file_size(fd)); + + std::string command = "update-super:super"; + if (force_wipe) { + command += ":wipe"; + } + fb_queue_command(command, "Updating super partition"); + + // We need these commands to have finished before proceeding, since + // otherwise "getvar is-logical" may not return a correct answer below. + fb_execute_queue(); +} + +static void do_flashall(const std::string& slot_override, bool skip_secondary, bool wipe) { std::string fname; queue_info_dump(); @@ -1188,6 +1237,10 @@ static void do_flashall(const std::string& slot_override, bool skip_secondary) { } } + update_super_partition(wipe); + + // List of partitions to flash and their slots. + std::vector> entries; for (size_t i = 0; i < arraysize(images); i++) { const char* slot = NULL; if (images[i].IsSecondary()) { @@ -1196,21 +1249,38 @@ static void do_flashall(const std::string& slot_override, bool skip_secondary) { slot = slot_override.c_str(); } if (!slot) continue; - fname = find_item_given_name(images[i].img_name); + entries.emplace_back(&images[i], slot); + + // Resize any logical partition to 0, so each partition is reset to 0 + // extents, and will achieve more optimal allocation. + auto resize_partition = [](const std::string& partition) -> void { + if (is_logical(partition)) { + fb_queue_resize_partition(partition, "0"); + } + }; + do_for_partitions(images[i].part_name, slot, resize_partition, false); + } + + // Flash each partition in the list if it has a corresponding image. + for (const auto& [image, slot] : entries) { + fname = find_item_given_name(image->img_name); fastboot_buffer buf; if (!load_buf(fname.c_str(), &buf)) { - if (images[i].optional_if_no_image) continue; - die("could not load '%s': %s", images[i].img_name, strerror(errno)); + if (image->optional_if_no_image) continue; + die("could not load '%s': %s", image->img_name, strerror(errno)); } - if (images[i].optional_if_no_partition && - !if_partition_exists(images[i].part_name, slot)) { + if (image->optional_if_no_partition && + !if_partition_exists(image->part_name, slot)) { continue; } auto flashall = [&](const std::string &partition) { do_send_signature(fname.c_str()); + if (is_logical(partition)) { + fb_queue_resize_partition(partition, std::to_string(buf.image_size)); + } flash_buf(partition.c_str(), &buf); }; - do_for_partitions(images[i].part_name, slot, flashall, false); + do_for_partitions(image->part_name, slot, flashall, false); } if (slot_override == "all") { @@ -1648,9 +1718,9 @@ int FastBootTool::Main(int argc, char* argv[]) { } else if (command == "flashall") { if (slot_override == "all") { fprintf(stderr, "Warning: slot set to 'all'. Secondary slots will not be flashed.\n"); - do_flashall(slot_override, true); + do_flashall(slot_override, true, wants_wipe); } else { - do_flashall(slot_override, skip_secondary); + do_flashall(slot_override, skip_secondary, wants_wipe); } wants_reboot = true; } else if (command == "update") {