From abec25d226f2afcc7dcd1fb05d8a55f92b1290c7 Mon Sep 17 00:00:00 2001 From: Pierre-Hugues Husson Date: Sat, 20 Mar 2021 19:57:52 +0100 Subject: [PATCH] Pump up lptools - Add `free` command to know how big a partition can be created - `create` command now properly return errors - Add lptools_static, suitable for use from recovery - Add clear-cow and unlimited-group to help expand current group's beyond original expectations --- cmds/Android.bp | 32 +++++++++++++++++ cmds/lptools.cc | 95 ++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 122 insertions(+), 5 deletions(-) diff --git a/cmds/Android.bp b/cmds/Android.bp index 464ad29..5896563 100644 --- a/cmds/Android.bp +++ b/cmds/Android.bp @@ -198,6 +198,8 @@ cc_binary { "libfs_mgr", "libutils", "libcutils", + "android.hardware.boot@1.1", + "libhidlbase", ], static_libs: [ "libdm", @@ -210,6 +212,36 @@ cc_binary { ], } +cc_binary { + name: "lptools_static", + cflags: [ + "-Werror", + "-Wextra", + "-DLPTOOLS_STATIC", + ], + device_supported: true, +shared_libs: [ + "libcrypto", +], + static_libs: [ + "libbase", + "liblog", + "liblp", + "libsparse", + "libfs_mgr", + "libutils", + "libcutils", + "libdm", + "libext4_utils", + ], + srcs: [ + "lptools.cc", + ], + cppflags: [ + "-D_FILE_OFFSET_BITS=64", + ], +} + cc_binary { name: "sec-camera-list", srcs: [ diff --git a/cmds/lptools.cc b/cmds/lptools.cc index c132005..b5d8e87 100644 --- a/cmds/lptools.cc +++ b/cmds/lptools.cc @@ -40,6 +40,11 @@ #include #include +#ifndef LPTOOLS_STATIC +#include +#include +#endif + using namespace android; using namespace android::fs_mgr; @@ -77,8 +82,25 @@ void saveToDisk(std::unique_ptr builder) { } } +inline bool ends_with(std::string const & value, std::string const & ending) +{ + if (ending.size() > value.size()) return false; + return std::equal(ending.rbegin(), ending.rend(), value.rbegin()); +} + std::string findGroup(std::unique_ptr& builder) { auto groups = builder->ListGroups(); + + auto partitionName = "system" + ::android::base::GetProperty("ro.boot.slot_suffix", ""); + for(auto groupName: groups) { + auto partitions = builder->ListPartitionsInGroup(groupName); + for (const auto& partition : partitions) { + if(partition->name() == partitionName) { + return groupName; + } + } + } + std::string maxGroup = ""; uint64_t maxGroupSize = 0; for(auto groupName: groups) { @@ -116,7 +138,9 @@ int main(int argc, char **argv) { exit(1); } partition = builder->AddPartition(partName, group, 0); - std::cout << "Growing partition " << builder->ResizePartition(partition, size) << std::endl; + auto result = builder->ResizePartition(partition, size); + std::cout << "Growing partition " << result << std::endl; + if(!result) return 1; saveToDisk(std::move(builder)); std::string dmPath; @@ -163,13 +187,19 @@ int main(int argc, char **argv) { auto src = argv[2]; auto dst = argv[3]; auto srcPartition = builder->FindPartition(src); + if(srcPartition == nullptr) { + srcPartition = builder->FindPartition(src + ::android::base::GetProperty("ro.boot.slot_suffix", "")); + } + auto dstPartition = builder->FindPartition(dst); + if(dstPartition == nullptr) { + dstPartition = builder->FindPartition(dst + ::android::base::GetProperty("ro.boot.slot_suffix", "")); + } std::vector> originalExtents; const auto& extents = srcPartition->extents(); for(unsigned i=0; iAsLinearExtent(); - std::cerr << (linear != nullptr) << std::endl; if(linear != nullptr) { auto copyLinear = std::make_unique(linear->num_sectors(), linear->device_index(), linear->physical_sector()); originalExtents.push_back(std::move(copyLinear)); @@ -178,9 +208,9 @@ int main(int argc, char **argv) { originalExtents.push_back(std::move(copyZero)); } } - builder->RemovePartition(src); - builder->RemovePartition(dst); - auto newDstPartition = builder->AddPartition(dst, group, 0); + builder->RemovePartition(srcPartition->name()); + builder->RemovePartition(dstPartition->name()); + auto newDstPartition = builder->AddPartition(dstPartition->name(), group, 0); for(auto&& extent: originalExtents) { newDstPartition->AddExtent(std::move(extent)); } @@ -214,6 +244,61 @@ int main(int argc, char **argv) { android::fs_mgr::DestroyLogicalPartition(partName); } exit(0); + } else if(strcmp(argv[1], "free") == 0) { + if(argc != 2) { + std::cerr << "Usage: " << argv[0] << " free" << std::endl; + exit(1); + } + auto groupO = builder->FindGroup(group); + uint64_t maxSize = groupO->maximum_size(); + + uint64_t total = 0; + auto partitions = builder->ListPartitionsInGroup(group); + for (const auto& partition : partitions) { + total += partition->BytesOnDisk(); + } + + uint64_t groupAllocatable = maxSize - total; + uint64_t superFreeSpace = builder->AllocatableSpace() - builder->UsedSpace(); + if(groupAllocatable > superFreeSpace || maxSize == 0) + groupAllocatable = superFreeSpace; + + printf("Free space: %" PRIu64 "\n", groupAllocatable); + + exit(0); + } else if(strcmp(argv[1], "unlimited-group") == 0) { + builder->ChangeGroupSize(group, 0); + saveToDisk(std::move(builder)); + return 0; + } else if(strcmp(argv[1], "clear-cow") == 0) { +#ifndef LPTOOLS_STATIC + // Ensure this is a V AB device, and that no merging is taking place (merging? in gsi? uh) + auto svc1_1 = ::android::hardware::boot::V1_1::IBootControl::tryGetService(); + if(svc1_1 == nullptr) { + std::cerr << "Couldn't get a bootcontrol HAL. You can clear cow only on V AB devices" << std::endl; + return 1; + } + auto mergeStatus = svc1_1->getSnapshotMergeStatus(); + if(mergeStatus != ::android::hardware::boot::V1_1::MergeStatus::NONE) { + std::cerr << "Merge status is NOT none, meaning a merge is pending. Clearing COW isn't safe" << std::endl; + return 1; + } +#endif + + uint64_t superFreeSpace = builder->AllocatableSpace() - builder->UsedSpace(); + std::cerr << "Super allocatable " << superFreeSpace << std::endl; + + uint64_t total = 0; + auto partitions = builder->ListPartitionsInGroup("cow"); + for (const auto& partition : partitions) { + std::cout << "Deleting partition? " << partition->name() << std::endl; + if(ends_with(partition->name(), "-cow")) { + std::cout << "Deleting partition " << partition->name() << std::endl; + builder->RemovePartition(partition->name()); + } + } + saveToDisk(std::move(builder)); + return 0; } return 0;