Loading fastboot/fastboot.cpp +25 −94 Original line number Diff line number Diff line Loading @@ -982,7 +982,7 @@ static void DumpInfo() { fprintf(stderr, "--------------------------------------------\n"); } static std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size) { std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size) { if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) { die("invalid max size %" PRId64, max_size); } Loading Loading @@ -1027,7 +1027,7 @@ static uint64_t get_uint_var(const char* var_name) { return value; } static int64_t get_sparse_limit(int64_t size) { int64_t get_sparse_limit(int64_t size) { int64_t limit = sparse_limit; if (limit == 0) { // Unlimited, so see what the target device's limit is. Loading Loading @@ -1161,7 +1161,7 @@ static bool has_vbmeta_partition() { // Note: this only works in userspace fastboot. In the bootloader, use // should_flash_in_userspace(). static bool is_logical(const std::string& partition) { bool is_logical(const std::string& partition) { std::string value; return fb->GetVar("is-logical:" + partition, &value) == fastboot::SUCCESS && value == "yes"; } Loading Loading @@ -1243,8 +1243,7 @@ static void copy_avb_footer(const std::string& partition, struct fastboot_buffer lseek(buf->fd.get(), 0, SEEK_SET); } static void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files) { void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files) { for (size_t i = 0; i < files.size(); i++) { sparse_file* s = files[i].get(); int64_t sz = sparse_file_len(s, true, false); Loading Loading @@ -1303,7 +1302,7 @@ static int get_slot_count() { return count; } static bool supports_AB() { bool supports_AB() { return get_slot_count() >= 2; } Loading Loading @@ -1426,7 +1425,7 @@ void do_for_partitions(const std::string& part, const std::string& slot, } } static bool is_retrofit_device() { bool is_retrofit_device() { std::string value; if (fb->GetVar("super-partition-name", &value) != fastboot::SUCCESS) { return false; Loading Loading @@ -1562,6 +1561,20 @@ static void CancelSnapshotIfNeeded() { } } std::string GetPartitionName(const ImageEntry& entry, std::string& current_slot) { auto slot = entry.second; if (slot.empty()) { slot = current_slot; } if (slot.empty()) { return entry.first->part_name; } if (slot == "all") { LOG(FATAL) << "Cannot retrieve a singular name when using all slots"; } return entry.first->part_name + "_" + slot; } class FlashAllTool { public: FlashAllTool(FlashingPlan* fp); Loading @@ -1575,15 +1588,12 @@ class FlashAllTool { void FlashImages(const std::vector<std::pair<const Image*, std::string>>& images); void FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf); void UpdateSuperPartition(); bool OptimizedFlashSuper(); // 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. using ImageEntry = std::pair<const Image*, std::string>; std::string GetPartitionName(const ImageEntry& entry); std::vector<ImageEntry> boot_images_; std::vector<ImageEntry> os_images_; FlashingPlan* fp_; Loading Loading @@ -1612,10 +1622,13 @@ void FlashAllTool::Flash() { // or in bootloader fastboot. FlashImages(boot_images_); if (!OptimizedFlashSuper()) { auto flash_super_task = FlashSuperLayoutTask::Initialize(fp_, os_images_); if (flash_super_task) { flash_super_task->Run(); } else { // Sync the super partition. This will reboot to userspace fastboot if needed. UpdateSuperPartition(); // Resize any logical partition to 0, so each partition is reset to 0 // extents, and will achieve more optimal allocation. for (const auto& [image, slot] : os_images_) { Loading @@ -1627,77 +1640,9 @@ void FlashAllTool::Flash() { do_for_partitions(image->part_name, slot, resize_partition, false); } } // Flash OS images, resizing logical partitions as needed. FlashImages(os_images_); } bool FlashAllTool::OptimizedFlashSuper() { if (!supports_AB()) { LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device"; return false; } 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 = fp_->source->OpenFile("super_empty.img"); if (fd < 0) { LOG(VERBOSE) << "could not open super_empty.img"; return false; } // Try to find whether there is a super partition. std::string super_name; if (fb->GetVar("super-partition-name", &super_name) != fastboot::SUCCESS) { super_name = "super"; } std::string partition_size_str; if (fb->GetVar("partition-size:" + super_name, &partition_size_str) != fastboot::SUCCESS) { LOG(VERBOSE) << "Cannot optimize super flashing: could not determine super partition"; return false; } SuperFlashHelper helper(*fp_->source); if (!helper.Open(fd)) { return false; } for (const auto& entry : os_images_) { auto partition = GetPartitionName(entry); auto image = entry.first; if (!helper.AddPartition(partition, image->img_name, image->optional_if_no_image)) { return false; } } auto s = helper.GetSparseLayout(); if (!s) { return false; } std::vector<SparsePtr> files; if (int limit = get_sparse_limit(sparse_file_len(s.get(), false, false))) { files = resparse_file(s.get(), limit); } else { files.emplace_back(std::move(s)); } // Send the data to the device. flash_partition_files(super_name, files); // Remove images that we already flashed, just in case we have non-dynamic OS images. auto remove_if_callback = [&, this](const ImageEntry& entry) -> bool { return helper.WillFlash(GetPartitionName(entry)); }; os_images_.erase(std::remove_if(os_images_.begin(), os_images_.end(), remove_if_callback), os_images_.end()); return true; } void FlashAllTool::CheckRequirements() { std::vector<char> contents; if (!fp_->source->ReadFile("android-info.txt", &contents)) { Loading Loading @@ -1811,20 +1756,6 @@ void FlashAllTool::UpdateSuperPartition() { } } std::string FlashAllTool::GetPartitionName(const ImageEntry& entry) { auto slot = entry.second; if (slot.empty()) { slot = fp_->current_slot; } if (slot.empty()) { return entry.first->part_name; } if (slot == "all") { LOG(FATAL) << "Cannot retrieve a singular name when using all slots"; } return entry.first->part_name + "_" + slot; } class ZipImageSource final : public ImageSource { public: explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {} Loading fastboot/fastboot.h +10 −2 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <string> #include "fastboot_driver.h" #include "super_flash_helper.h" #include "util.h" #include <bootimg.h> Loading Loading @@ -82,7 +83,6 @@ struct FlashingPlan { std::string current_slot; std::string secondary_slot; fastboot::FastBootDriver* fb; }; bool should_flash_in_userspace(const std::string& partition_name); Loading @@ -101,3 +101,11 @@ struct NetworkSerial { }; Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial); bool supports_AB(); std::string GetPartitionName(const ImageEntry& entry, std::string& current_slot_); void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files); int64_t get_sparse_limit(int64_t size); std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size); bool is_retrofit_device(); bool is_logical(const std::string& partition); fastboot/task.cpp +79 −3 Original line number Diff line number Diff line Loading @@ -14,11 +14,12 @@ // limitations under the License. // #include "task.h" #include <iostream> #include "fastboot.h" #include "util.h" #include "filesystem.h" #include "super_flash_helper.h" #include "fastboot.h" #include "util.h" using namespace std::string_literals; FlashTask::FlashTask(const std::string& _slot, const std::string& _pname) : pname_(_pname), fname_(find_item(_pname)), slot_(_slot) { Loading Loading @@ -66,3 +67,78 @@ void RebootTask::Run() { syntax_error("unknown reboot target %s", reboot_target_.c_str()); } } FlashSuperLayoutTask::FlashSuperLayoutTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper, SparsePtr sparse_layout) : super_name_(super_name), helper_(std::move(helper)), sparse_layout_(std::move(sparse_layout)) {} void FlashSuperLayoutTask::Run() { std::vector<SparsePtr> files; if (int limit = get_sparse_limit(sparse_file_len(sparse_layout_.get(), false, false))) { files = resparse_file(sparse_layout_.get(), limit); } else { files.emplace_back(std::move(sparse_layout_)); } // Send the data to the device. flash_partition_files(super_name_, files); } std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::Initialize( FlashingPlan* fp, std::vector<ImageEntry>& os_images) { if (!supports_AB()) { LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device"; return nullptr; } if (fp->slot == "all") { LOG(VERBOSE) << "Cannot optimize flashing super for all slots"; return nullptr; } // Does this device use dynamic partitions at all? unique_fd fd = fp->source->OpenFile("super_empty.img"); if (fd < 0) { LOG(VERBOSE) << "could not open super_empty.img"; return nullptr; } std::string super_name; // Try to find whether there is a super partition. if (fp->fb->GetVar("super-partition-name", &super_name) != fastboot::SUCCESS) { super_name = "super"; } std::string partition_size_str; if (fp->fb->GetVar("partition-size:" + super_name, &partition_size_str) != fastboot::SUCCESS) { LOG(VERBOSE) << "Cannot optimize super flashing: could not determine super partition"; return nullptr; } std::unique_ptr<SuperFlashHelper> helper = std::make_unique<SuperFlashHelper>(*fp->source); if (!helper->Open(fd)) { return nullptr; } for (const auto& entry : os_images) { auto partition = GetPartitionName(entry, fp->current_slot); auto image = entry.first; if (!helper->AddPartition(partition, image->img_name, image->optional_if_no_image)) { return nullptr; } } auto s = helper->GetSparseLayout(); if (!s) return nullptr; // Remove images that we already flashed, just in case we have non-dynamic OS images. auto remove_if_callback = [&](const ImageEntry& entry) -> bool { return helper->WillFlash(GetPartitionName(entry, fp->current_slot)); }; os_images.erase(std::remove_if(os_images.begin(), os_images.end(), remove_if_callback), os_images.end()); return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s)); } fastboot/task.h +18 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include "fastboot.h" #include "fastboot_driver.h" #include "super_flash_helper.h" #include "util.h" class Task { public: Loading Loading @@ -53,3 +55,18 @@ class RebootTask : public Task { const std::string reboot_target_ = ""; FlashingPlan* fp_; }; class FlashSuperLayoutTask : public Task { public: FlashSuperLayoutTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper, SparsePtr sparse_layout); static std::unique_ptr<FlashSuperLayoutTask> Initialize(FlashingPlan* fp, std::vector<ImageEntry>& os_images); using ImageEntry = std::pair<const Image*, std::string>; void Run() override; private: const std::string super_name_; std::unique_ptr<SuperFlashHelper> helper_; SparsePtr sparse_layout_; }; Loading
fastboot/fastboot.cpp +25 −94 Original line number Diff line number Diff line Loading @@ -982,7 +982,7 @@ static void DumpInfo() { fprintf(stderr, "--------------------------------------------\n"); } static std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size) { std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size) { if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) { die("invalid max size %" PRId64, max_size); } Loading Loading @@ -1027,7 +1027,7 @@ static uint64_t get_uint_var(const char* var_name) { return value; } static int64_t get_sparse_limit(int64_t size) { int64_t get_sparse_limit(int64_t size) { int64_t limit = sparse_limit; if (limit == 0) { // Unlimited, so see what the target device's limit is. Loading Loading @@ -1161,7 +1161,7 @@ static bool has_vbmeta_partition() { // Note: this only works in userspace fastboot. In the bootloader, use // should_flash_in_userspace(). static bool is_logical(const std::string& partition) { bool is_logical(const std::string& partition) { std::string value; return fb->GetVar("is-logical:" + partition, &value) == fastboot::SUCCESS && value == "yes"; } Loading Loading @@ -1243,8 +1243,7 @@ static void copy_avb_footer(const std::string& partition, struct fastboot_buffer lseek(buf->fd.get(), 0, SEEK_SET); } static void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files) { void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files) { for (size_t i = 0; i < files.size(); i++) { sparse_file* s = files[i].get(); int64_t sz = sparse_file_len(s, true, false); Loading Loading @@ -1303,7 +1302,7 @@ static int get_slot_count() { return count; } static bool supports_AB() { bool supports_AB() { return get_slot_count() >= 2; } Loading Loading @@ -1426,7 +1425,7 @@ void do_for_partitions(const std::string& part, const std::string& slot, } } static bool is_retrofit_device() { bool is_retrofit_device() { std::string value; if (fb->GetVar("super-partition-name", &value) != fastboot::SUCCESS) { return false; Loading Loading @@ -1562,6 +1561,20 @@ static void CancelSnapshotIfNeeded() { } } std::string GetPartitionName(const ImageEntry& entry, std::string& current_slot) { auto slot = entry.second; if (slot.empty()) { slot = current_slot; } if (slot.empty()) { return entry.first->part_name; } if (slot == "all") { LOG(FATAL) << "Cannot retrieve a singular name when using all slots"; } return entry.first->part_name + "_" + slot; } class FlashAllTool { public: FlashAllTool(FlashingPlan* fp); Loading @@ -1575,15 +1588,12 @@ class FlashAllTool { void FlashImages(const std::vector<std::pair<const Image*, std::string>>& images); void FlashImage(const Image& image, const std::string& slot, fastboot_buffer* buf); void UpdateSuperPartition(); bool OptimizedFlashSuper(); // 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. using ImageEntry = std::pair<const Image*, std::string>; std::string GetPartitionName(const ImageEntry& entry); std::vector<ImageEntry> boot_images_; std::vector<ImageEntry> os_images_; FlashingPlan* fp_; Loading Loading @@ -1612,10 +1622,13 @@ void FlashAllTool::Flash() { // or in bootloader fastboot. FlashImages(boot_images_); if (!OptimizedFlashSuper()) { auto flash_super_task = FlashSuperLayoutTask::Initialize(fp_, os_images_); if (flash_super_task) { flash_super_task->Run(); } else { // Sync the super partition. This will reboot to userspace fastboot if needed. UpdateSuperPartition(); // Resize any logical partition to 0, so each partition is reset to 0 // extents, and will achieve more optimal allocation. for (const auto& [image, slot] : os_images_) { Loading @@ -1627,77 +1640,9 @@ void FlashAllTool::Flash() { do_for_partitions(image->part_name, slot, resize_partition, false); } } // Flash OS images, resizing logical partitions as needed. FlashImages(os_images_); } bool FlashAllTool::OptimizedFlashSuper() { if (!supports_AB()) { LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device"; return false; } 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 = fp_->source->OpenFile("super_empty.img"); if (fd < 0) { LOG(VERBOSE) << "could not open super_empty.img"; return false; } // Try to find whether there is a super partition. std::string super_name; if (fb->GetVar("super-partition-name", &super_name) != fastboot::SUCCESS) { super_name = "super"; } std::string partition_size_str; if (fb->GetVar("partition-size:" + super_name, &partition_size_str) != fastboot::SUCCESS) { LOG(VERBOSE) << "Cannot optimize super flashing: could not determine super partition"; return false; } SuperFlashHelper helper(*fp_->source); if (!helper.Open(fd)) { return false; } for (const auto& entry : os_images_) { auto partition = GetPartitionName(entry); auto image = entry.first; if (!helper.AddPartition(partition, image->img_name, image->optional_if_no_image)) { return false; } } auto s = helper.GetSparseLayout(); if (!s) { return false; } std::vector<SparsePtr> files; if (int limit = get_sparse_limit(sparse_file_len(s.get(), false, false))) { files = resparse_file(s.get(), limit); } else { files.emplace_back(std::move(s)); } // Send the data to the device. flash_partition_files(super_name, files); // Remove images that we already flashed, just in case we have non-dynamic OS images. auto remove_if_callback = [&, this](const ImageEntry& entry) -> bool { return helper.WillFlash(GetPartitionName(entry)); }; os_images_.erase(std::remove_if(os_images_.begin(), os_images_.end(), remove_if_callback), os_images_.end()); return true; } void FlashAllTool::CheckRequirements() { std::vector<char> contents; if (!fp_->source->ReadFile("android-info.txt", &contents)) { Loading Loading @@ -1811,20 +1756,6 @@ void FlashAllTool::UpdateSuperPartition() { } } std::string FlashAllTool::GetPartitionName(const ImageEntry& entry) { auto slot = entry.second; if (slot.empty()) { slot = fp_->current_slot; } if (slot.empty()) { return entry.first->part_name; } if (slot == "all") { LOG(FATAL) << "Cannot retrieve a singular name when using all slots"; } return entry.first->part_name + "_" + slot; } class ZipImageSource final : public ImageSource { public: explicit ZipImageSource(ZipArchiveHandle zip) : zip_(zip) {} Loading
fastboot/fastboot.h +10 −2 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ #include <string> #include "fastboot_driver.h" #include "super_flash_helper.h" #include "util.h" #include <bootimg.h> Loading Loading @@ -82,7 +83,6 @@ struct FlashingPlan { std::string current_slot; std::string secondary_slot; fastboot::FastBootDriver* fb; }; bool should_flash_in_userspace(const std::string& partition_name); Loading @@ -101,3 +101,11 @@ struct NetworkSerial { }; Result<NetworkSerial, FastbootError> ParseNetworkSerial(const std::string& serial); bool supports_AB(); std::string GetPartitionName(const ImageEntry& entry, std::string& current_slot_); void flash_partition_files(const std::string& partition, const std::vector<SparsePtr>& files); int64_t get_sparse_limit(int64_t size); std::vector<SparsePtr> resparse_file(sparse_file* s, int64_t max_size); bool is_retrofit_device(); bool is_logical(const std::string& partition);
fastboot/task.cpp +79 −3 Original line number Diff line number Diff line Loading @@ -14,11 +14,12 @@ // limitations under the License. // #include "task.h" #include <iostream> #include "fastboot.h" #include "util.h" #include "filesystem.h" #include "super_flash_helper.h" #include "fastboot.h" #include "util.h" using namespace std::string_literals; FlashTask::FlashTask(const std::string& _slot, const std::string& _pname) : pname_(_pname), fname_(find_item(_pname)), slot_(_slot) { Loading Loading @@ -66,3 +67,78 @@ void RebootTask::Run() { syntax_error("unknown reboot target %s", reboot_target_.c_str()); } } FlashSuperLayoutTask::FlashSuperLayoutTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper, SparsePtr sparse_layout) : super_name_(super_name), helper_(std::move(helper)), sparse_layout_(std::move(sparse_layout)) {} void FlashSuperLayoutTask::Run() { std::vector<SparsePtr> files; if (int limit = get_sparse_limit(sparse_file_len(sparse_layout_.get(), false, false))) { files = resparse_file(sparse_layout_.get(), limit); } else { files.emplace_back(std::move(sparse_layout_)); } // Send the data to the device. flash_partition_files(super_name_, files); } std::unique_ptr<FlashSuperLayoutTask> FlashSuperLayoutTask::Initialize( FlashingPlan* fp, std::vector<ImageEntry>& os_images) { if (!supports_AB()) { LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device"; return nullptr; } if (fp->slot == "all") { LOG(VERBOSE) << "Cannot optimize flashing super for all slots"; return nullptr; } // Does this device use dynamic partitions at all? unique_fd fd = fp->source->OpenFile("super_empty.img"); if (fd < 0) { LOG(VERBOSE) << "could not open super_empty.img"; return nullptr; } std::string super_name; // Try to find whether there is a super partition. if (fp->fb->GetVar("super-partition-name", &super_name) != fastboot::SUCCESS) { super_name = "super"; } std::string partition_size_str; if (fp->fb->GetVar("partition-size:" + super_name, &partition_size_str) != fastboot::SUCCESS) { LOG(VERBOSE) << "Cannot optimize super flashing: could not determine super partition"; return nullptr; } std::unique_ptr<SuperFlashHelper> helper = std::make_unique<SuperFlashHelper>(*fp->source); if (!helper->Open(fd)) { return nullptr; } for (const auto& entry : os_images) { auto partition = GetPartitionName(entry, fp->current_slot); auto image = entry.first; if (!helper->AddPartition(partition, image->img_name, image->optional_if_no_image)) { return nullptr; } } auto s = helper->GetSparseLayout(); if (!s) return nullptr; // Remove images that we already flashed, just in case we have non-dynamic OS images. auto remove_if_callback = [&](const ImageEntry& entry) -> bool { return helper->WillFlash(GetPartitionName(entry, fp->current_slot)); }; os_images.erase(std::remove_if(os_images.begin(), os_images.end(), remove_if_callback), os_images.end()); return std::make_unique<FlashSuperLayoutTask>(super_name, std::move(helper), std::move(s)); }
fastboot/task.h +18 −1 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ #include "fastboot.h" #include "fastboot_driver.h" #include "super_flash_helper.h" #include "util.h" class Task { public: Loading Loading @@ -53,3 +55,18 @@ class RebootTask : public Task { const std::string reboot_target_ = ""; FlashingPlan* fp_; }; class FlashSuperLayoutTask : public Task { public: FlashSuperLayoutTask(const std::string& super_name, std::unique_ptr<SuperFlashHelper> helper, SparsePtr sparse_layout); static std::unique_ptr<FlashSuperLayoutTask> Initialize(FlashingPlan* fp, std::vector<ImageEntry>& os_images); using ImageEntry = std::pair<const Image*, std::string>; void Run() override; private: const std::string super_name_; std::unique_ptr<SuperFlashHelper> helper_; SparsePtr sparse_layout_; };