diff options
| author | Julian Veit <Claymore1298@gmail.com> | 2024-07-08 07:46:54 +0200 |
|---|---|---|
| committer | Julian Veit <Claymore1298@gmail.com> | 2024-07-08 07:46:54 +0200 |
| commit | 0aac54a0e9fd9d80d43d7154370810ac86e92f1b (patch) | |
| tree | d63c54a4973f5958ab5d6def478563d27a72b6eb | |
| parent | af9a42f1d13ffeca2eabf368580ad6790e2763ba (diff) | |
| parent | 8bbe7bae399b428cfaa021a511d749c78e5a8e73 (diff) | |
Merge https://github.com/LineageOS/android_bootable_recovery into HEADu14.0
Change-Id: I05e44ba7ba265c80b0f6bf48f2c084e2598c69e4
| -rw-r--r-- | Android.mk | 5 | ||||
| -rw-r--r-- | bootloader_message/Android.bp | 11 | ||||
| -rw-r--r-- | bootloader_message/bootloader_message.cpp | 38 | ||||
| -rw-r--r-- | bootloader_message/include/bootloader_message/bootloader_message.h | 46 | ||||
| -rw-r--r-- | bootloader_message/misctrl.rc | 4 | ||||
| -rw-r--r-- | bootloader_message/misctrl_main.cpp | 91 | ||||
| -rw-r--r-- | edify/include/edify/updater_runtime_interface.h | 3 | ||||
| -rw-r--r-- | install/include/install/wipe_data.h | 8 | ||||
| -rw-r--r-- | install/wipe_data.cpp | 26 | ||||
| -rw-r--r-- | recovery.cpp | 22 | ||||
| -rw-r--r-- | recovery_main.cpp | 2 | ||||
| -rw-r--r-- | recovery_utils/include/recovery_utils/roots.h | 3 | ||||
| -rw-r--r-- | recovery_utils/roots.cpp | 21 | ||||
| -rw-r--r-- | updater/Android.bp | 2 | ||||
| -rw-r--r-- | updater/Android.mk | 2 | ||||
| -rw-r--r-- | updater/dynamic_partitions.cpp | 17 | ||||
| -rw-r--r-- | updater/include/updater/simulator_runtime.h | 3 | ||||
| -rw-r--r-- | updater/include/updater/updater_runtime.h | 4 | ||||
| -rw-r--r-- | updater/simulator_runtime.cpp | 3 | ||||
| -rw-r--r-- | updater/updater_runtime_dynamic_partitions.cpp | 40 |
20 files changed, 299 insertions, 52 deletions
@@ -73,6 +73,11 @@ LOCAL_REQUIRED_MODULES += \ dump.erofs.recovery \ fsck.erofs.recovery +LOCAL_REQUIRED_MODULES += \ + e2fsck.recovery \ + resize2fs.recovery \ + tune2fs.recovery + # On A/B devices recovery-persist reads the recovery related file from the persist storage and # copies them into /data/misc/recovery. Then, for both A/B and non-A/B devices, recovery-persist # parses the last_install file and reports the embedded update metrics. Also, the last_install file diff --git a/bootloader_message/Android.bp b/bootloader_message/Android.bp index 92c4428e..24b562f4 100644 --- a/bootloader_message/Android.bp +++ b/bootloader_message/Android.bp @@ -40,6 +40,17 @@ cc_defaults { export_include_dirs: ["include"], } +cc_binary { + name: "misctrl", + shared_libs: [ + "libbase", + "libbootloader_message", + "liblog", + ], + init_rc: ["misctrl.rc"], + srcs: ["misctrl_main.cpp"], +} + cc_library { name: "libbootloader_message", defaults: [ diff --git a/bootloader_message/bootloader_message.cpp b/bootloader_message/bootloader_message.cpp index 18ff886d..d80d9d1d 100644 --- a/bootloader_message/bootloader_message.cpp +++ b/bootloader_message/bootloader_message.cpp @@ -26,6 +26,7 @@ #include <vector> #include <android-base/file.h> +#include <android-base/hex.h> #include <android-base/properties.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> @@ -319,6 +320,43 @@ bool WriteMiscMemtagMessage(const misc_memtag_message& message, std::string* err offsetof(misc_system_space_layout, memtag_message), err); } +bool ReadMiscKcmdlineMessage(misc_kcmdline_message* message, std::string* err) { + return ReadMiscPartitionSystemSpace(message, sizeof(*message), + offsetof(misc_system_space_layout, kcmdline_message), err); +} + +bool WriteMiscKcmdlineMessage(const misc_kcmdline_message& message, std::string* err) { + return WriteMiscPartitionSystemSpace(&message, sizeof(message), + offsetof(misc_system_space_layout, kcmdline_message), err); +} + +bool ReadMiscControlMessage(misc_control_message* message, std::string* err) { + return ReadMiscPartitionSystemSpace(message, sizeof(*message), + offsetof(misc_system_space_layout, control_message), err); +} + +bool WriteMiscControlMessage(const misc_control_message& message, std::string* err) { + return WriteMiscPartitionSystemSpace(&message, sizeof(message), + offsetof(misc_system_space_layout, control_message), err); +} + +bool CheckReservedSystemSpaceEmpty(bool* empty, std::string* err) { + constexpr size_t kReservedSize = SYSTEM_SPACE_SIZE_IN_MISC - sizeof(misc_system_space_layout); + + uint8_t space[kReservedSize]; + if (!ReadMiscPartitionSystemSpace(&space, kReservedSize, sizeof(misc_system_space_layout), err)) { + return false; + } + + *empty = space[0] == 0 && 0 == memcmp(space, space + 1, kReservedSize - 1); + + if (!*empty) { + *err = android::base::HexString(space, kReservedSize); + } + + return true; +} + extern "C" bool write_reboot_bootloader(void) { std::string err; return write_reboot_bootloader(&err); diff --git a/bootloader_message/include/bootloader_message/bootloader_message.h b/bootloader_message/include/bootloader_message/bootloader_message.h index c8a84372..4b2b8a13 100644 --- a/bootloader_message/include/bootloader_message/bootloader_message.h +++ b/bootloader_message/include/bootloader_message/bootloader_message.h @@ -100,6 +100,21 @@ struct misc_memtag_message { uint8_t reserved[55]; } __attribute__((packed)); +struct misc_kcmdline_message { + uint8_t version; + uint32_t magic; + uint64_t kcmdline_flags; + uint8_t reserved[51]; +} __attribute__((packed)); + +// holds generic platform info, managed by misctrl +struct misc_control_message { + uint8_t version; + uint32_t magic; + uint64_t misctrl_flags; + uint8_t reserved[51]; +} __attribute__((packed)); + #define MISC_VIRTUAL_AB_MESSAGE_VERSION 2 #define MISC_VIRTUAL_AB_MAGIC_HEADER 0x56740AB0 @@ -116,11 +131,23 @@ struct misc_memtag_message { // See system/extras/mtectrl in AOSP for more information. #define MISC_MEMTAG_MODE_FORCED 0x20 +#define MISC_KCMDLINE_MESSAGE_VERSION 1 +#define MISC_KCMDLINE_MAGIC_HEADER 0x6ab5110c +#define MISC_KCMDLINE_BINDER_RUST 0x1 + +#define MISC_CONTROL_MESSAGE_VERSION 1 +#define MISC_CONTROL_MAGIC_HEADER 0x736d6f72 +#define MISC_CONTROL_16KB_BEFORE 0x1 + #if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) static_assert(sizeof(struct misc_virtual_ab_message) == 64, "struct misc_virtual_ab_message has wrong size"); static_assert(sizeof(struct misc_memtag_message) == 64, "struct misc_memtag_message has wrong size"); +static_assert(sizeof(struct misc_kcmdline_message) == 64, + "struct misc_kcmdline_message has wrong size"); +static_assert(sizeof(struct misc_control_message) == 64, + "struct misc_control_message has wrong size"); #endif // This struct is not meant to be used directly, rather, it is to make @@ -128,8 +155,15 @@ static_assert(sizeof(struct misc_memtag_message) == 64, struct misc_system_space_layout { misc_virtual_ab_message virtual_ab_message; misc_memtag_message memtag_message; + misc_kcmdline_message kcmdline_message; + misc_control_message control_message; } __attribute__((packed)); +#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus) +static_assert(sizeof(struct misc_system_space_layout) % 64 == 0, + "prefer to extend by 64 byte chunks, for consistency"); +#endif + #ifdef __cplusplus #include <string> @@ -198,6 +232,18 @@ bool WriteMiscVirtualAbMessage(const misc_virtual_ab_message& message, std::stri // Read or write the memtag message from system space in /misc. bool ReadMiscMemtagMessage(misc_memtag_message* message, std::string* err); bool WriteMiscMemtagMessage(const misc_memtag_message& message, std::string* err); + +// Read or write the kcmdline message from system space in /misc. +bool ReadMiscKcmdlineMessage(misc_kcmdline_message* message, std::string* err); +bool WriteMiscKcmdlineMessage(const misc_kcmdline_message& message, std::string* err); + +// Read or write the kcmdline message from system space in /misc. +bool ReadMiscControlMessage(misc_control_message* message, std::string* err); +bool WriteMiscControlMessage(const misc_control_message& message, std::string* err); + +// Check reserved system space. +bool CheckReservedSystemSpaceEmpty(bool* empty, std::string* err); + #else #include <stdbool.h> diff --git a/bootloader_message/misctrl.rc b/bootloader_message/misctrl.rc new file mode 100644 index 00000000..5293bf2d --- /dev/null +++ b/bootloader_message/misctrl.rc @@ -0,0 +1,4 @@ +service misctrl /system/bin/misctrl + user root # for misc partition access + class core + oneshot diff --git a/bootloader_message/misctrl_main.cpp b/bootloader_message/misctrl_main.cpp new file mode 100644 index 00000000..653b62de --- /dev/null +++ b/bootloader_message/misctrl_main.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <android-base/logging.h> +#include <android-base/properties.h> +#include <bootloader_message/bootloader_message.h> +#include <log/log.h> + +#include <string> + +#include <cstdio> + +static int check_control_message() { + misc_control_message m; + std::string err; + if (!ReadMiscControlMessage(&m, &err)) { + LOG(ERROR) << "Could not read misctrl message: " << err.c_str(); + return 1; + } + + if (m.magic != MISC_CONTROL_MAGIC_HEADER || m.version != MISC_CONTROL_MESSAGE_VERSION) { + LOG(WARNING) << "misctrl message invalid, resetting it"; + m = { .version = MISC_CONTROL_MESSAGE_VERSION, + .magic = MISC_CONTROL_MAGIC_HEADER, + .misctrl_flags = 0 }; + } + + int res = 0; + + const size_t ps = getpagesize(); + + if (ps != 4096 && ps != 16384) { + LOG(ERROR) << "Unrecognized page size: " << ps; + res = 1; + } + + if (ps == 16384) { + m.misctrl_flags |= MISC_CONTROL_16KB_BEFORE; + } + + bool before_16kb = m.misctrl_flags & MISC_CONTROL_16KB_BEFORE; + res |= android::base::SetProperty("ro.misctrl.16kb_before", before_16kb ? "1" : "0"); + + if (!WriteMiscControlMessage(m, &err)) { + LOG(ERROR) << "Could not write misctrl message: " << err.c_str(); + res |= 1; + } + + return res; +} + +static int check_reserved_space() { + bool empty; + std::string err; + bool success = CheckReservedSystemSpaceEmpty(&empty, &err); + if (!success) { + LOG(ERROR) << "Could not read reserved space: " << err.c_str(); + return 1; + } + LOG(INFO) << "System reserved space empty? " << empty; + + if (!err.empty()) { + LOG(ERROR) << "Reserved misc space being used: " << err; + } + + return empty ? 0 : 1; +} + +int main(int argc, char** argv) { + { + using namespace android::base; + (void)argc; + InitLogging(argv, TeeLogger(LogdLogger(), &StderrLogger)); + } + int err = 0; + err |= check_control_message(); + err |= check_reserved_space(); + return err; +} diff --git a/edify/include/edify/updater_runtime_interface.h b/edify/include/edify/updater_runtime_interface.h index 054b85de..c5a18250 100644 --- a/edify/include/edify/updater_runtime_interface.h +++ b/edify/include/edify/updater_runtime_interface.h @@ -72,7 +72,8 @@ class UpdaterRuntimeInterface { // Dynamic partition related functions. virtual bool MapPartitionOnDeviceMapper(const std::string& partition_name, std::string* path) = 0; virtual bool UnmapPartitionOnDeviceMapper(const std::string& partition_name) = 0; - virtual bool UpdateDynamicPartitions(const std::string_view op_list_value) = 0; + virtual bool UpdateDynamicPartitions(const std::string_view op_list_value, + const std::string_view super_empty_value) = 0; // On devices supports A/B, add current slot suffix to arg. Otherwise, return |arg| as is. virtual std::string AddSlotSuffix(const std::string_view arg) const = 0; diff --git a/install/include/install/wipe_data.h b/install/include/install/wipe_data.h index 75b8d365..0890a4b0 100644 --- a/install/include/install/wipe_data.h +++ b/install/include/install/wipe_data.h @@ -24,10 +24,12 @@ struct selabel_handle; // Returns true on success. -bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm); +bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm, + std::string_view new_fstype = ""); // Returns true on success. -bool WipeData(Device* device, bool keep_memtag_mode = false); +bool WipeData(Device* device, bool keep_memtag_mode = false, std::string_view new_fstype = ""); // Returns true on success. -bool WipeSystem(RecoveryUI* ui, const std::function<bool()>& confirm); +bool WipeSystem(RecoveryUI* ui, const std::function<bool()>& confirm, + std::string_view new_fstype = ""); diff --git a/install/wipe_data.cpp b/install/wipe_data.cpp index 5d00e582..6cce36c6 100644 --- a/install/wipe_data.cpp +++ b/install/wipe_data.cpp @@ -32,7 +32,6 @@ #include "bootloader_message/bootloader_message.h" #include "install/snapshot_utils.h" -#include "otautil/dirutil.h" #include "recovery_ui/ui.h" #include "recovery_utils/logging.h" #include "recovery_utils/roots.h" @@ -41,7 +40,8 @@ constexpr const char* CACHE_ROOT = "/cache"; constexpr const char* DATA_ROOT = "/data"; constexpr const char* METADATA_ROOT = "/metadata"; -static bool EraseVolume(const char* volume, RecoveryUI* ui) { +static bool EraseVolume(const char* volume, RecoveryUI* ui, std::string_view new_fstype) { + LOG(INFO) << "Erasing volume " << volume << " with new filesystem type " << new_fstype; bool is_cache = (strcmp(volume, CACHE_ROOT) == 0); std::vector<saved_log_file> log_files; @@ -100,7 +100,7 @@ static bool EraseVolume(const char* volume, RecoveryUI* ui) { return false; } - int result = format_volume(volume); + int result = format_volume(volume, "", new_fstype); if (is_cache) { RestoreLogFilesAfterFormat(log_files); @@ -109,7 +109,8 @@ static bool EraseVolume(const char* volume, RecoveryUI* ui) { return (result == 0); } -bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm_func) { +bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm_func, + std::string_view new_fstype) { bool has_cache = volume_for_mount_point("/cache") != nullptr; if (!has_cache) { ui->Print("No /cache partition found.\n"); @@ -124,14 +125,14 @@ bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm_func) { ui->SetBackground(RecoveryUI::ERASING); ui->SetProgressType(RecoveryUI::INDETERMINATE); - bool success = EraseVolume("/cache", ui); + bool success = EraseVolume("/cache", ui, new_fstype); ui->Print("Cache wipe %s.\n", success ? "complete" : "failed"); return success; } -bool WipeData(Device* device, bool keep_memtag_mode) { +bool WipeData(Device* device, bool keep_memtag_mode, std::string_view data_fstype) { RecoveryUI* ui = device->GetUI(); - ui->Print("\n-- Wiping data...\n"); + ui->Print("\n-- Wiping data %.*s...\n", static_cast<int>(data_fstype.size()), data_fstype.data()); ui->SetBackground(RecoveryUI::ERASING); ui->SetProgressType(RecoveryUI::INDETERMINATE); @@ -142,13 +143,13 @@ bool WipeData(Device* device, bool keep_memtag_mode) { bool success = device->PreWipeData(); if (success) { - success &= EraseVolume(DATA_ROOT, ui); + success &= EraseVolume(DATA_ROOT, ui, data_fstype); bool has_cache = volume_for_mount_point("/cache") != nullptr; if (has_cache) { - success &= EraseVolume(CACHE_ROOT, ui); + success &= EraseVolume(CACHE_ROOT, ui, data_fstype); } if (volume_for_mount_point(METADATA_ROOT) != nullptr) { - success &= EraseVolume(METADATA_ROOT, ui); + success &= EraseVolume(METADATA_ROOT, ui, data_fstype); } } if (keep_memtag_mode) { @@ -168,13 +169,14 @@ bool WipeData(Device* device, bool keep_memtag_mode) { return success; } -bool WipeSystem(RecoveryUI* ui, const std::function<bool()>& confirm_func) { +bool WipeSystem(RecoveryUI* ui, const std::function<bool()>& confirm_func, + std::string_view new_fstype) { if (confirm_func && !confirm_func()) { return false; } ui->Print("\n-- Wiping system...\n"); - bool success = EraseVolume(android::fs_mgr::GetSystemRoot().c_str(), ui); + bool success = EraseVolume(android::fs_mgr::GetSystemRoot().c_str(), ui, new_fstype); ui->Print("System wipe %s.\n", success ? "complete" : "failed"); return success; } diff --git a/recovery.cpp b/recovery.cpp index 15720371..8f8600c4 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -16,11 +16,8 @@ #include "recovery.h" -#include <ctype.h> #include <errno.h> #include <getopt.h> -#include <inttypes.h> -#include <limits.h> #include <linux/input.h> #include <stdio.h> #include <stdlib.h> @@ -53,7 +50,6 @@ #include "install/snapshot_utils.h" #include "install/wipe_data.h" #include "install/wipe_device.h" -#include "otautil/boot_state.h" #include "otautil/error_code.h" #include "otautil/package.h" #include "otautil/paths.h" @@ -560,7 +556,7 @@ change_menu: update_in_progress = true; WriteUpdateInProgress(); - Device::BuiltinAction reboot_action; + Device::BuiltinAction reboot_action{}; if (chosen_action == Device::ENTER_RESCUE) { // Switch to graphics screen. ui->ShowText(false); @@ -725,6 +721,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri { "wipe_data", no_argument, nullptr, 0 }, { "keep_memtag_mode", no_argument, nullptr, 0 }, { "wipe_package_size", required_argument, nullptr, 0 }, + { "reformat_data", required_argument, nullptr, 0 }, { nullptr, 0, nullptr, 0 }, }; @@ -747,8 +744,9 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri auto args_to_parse = StringVectorToNullTerminatedArray(args); - int arg; - int option_index; + int arg = 0; + int option_index = 0; + std::string data_fstype; // Parse everything before the last element (which must be a nullptr). getopt_long(3) expects a // null-terminated char* array, but without counting null as an arg (i.e. argv[argc] should be // nullptr). @@ -792,6 +790,8 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri should_wipe_data = true; } else if (option == "wipe_package_size") { android::base::ParseUint(optarg, &wipe_package_size); + } else if (option == "reformat_data") { + data_fstype = optarg; } else if (option == "keep_memtag_mode") { should_keep_memtag_mode = true; } @@ -819,7 +819,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri // otherwise set it to "installing system update". ui->SetSystemUpdateText(security_update); - int st_cur, st_max; + int st_cur = 0, st_max = 0; if (!device->GetStage().has_value() && sscanf(device->GetStage().value().c_str(), "%d/%d", &st_cur, &st_max) == 2) { ui->SetStage(st_cur, st_max); @@ -863,7 +863,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri // to log the update attempt since update_package is non-NULL. save_current_log = true; - if (int required_battery_level; retry_count == 0 && !IsBatteryOk(&required_battery_level)) { + if (int required_battery_level = 0; retry_count == 0 && !IsBatteryOk(&required_battery_level)) { ui->Print("battery capacity is not enough for installing package: %d%% needed\n", required_battery_level); // Log the error code to last_install when installation skips due to low battery. @@ -929,7 +929,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri } else if (should_wipe_data) { save_current_log = true; CHECK(device->GetReason().has_value()); - if (!WipeData(device, should_keep_memtag_mode)) { + if (!WipeData(device, should_keep_memtag_mode, data_fstype)) { status = INSTALL_ERROR; } } else if (should_prompt_and_wipe_data) { @@ -944,7 +944,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri } } else if (should_wipe_cache) { save_current_log = true; - if (!WipeCache(ui, nullptr)) { + if (!WipeCache(ui, nullptr, data_fstype)) { status = INSTALL_ERROR; } } else if (should_wipe_ab) { diff --git a/recovery_main.cpp b/recovery_main.cpp index 6e7675f7..75ba2d1f 100644 --- a/recovery_main.cpp +++ b/recovery_main.cpp @@ -141,7 +141,7 @@ static std::vector<std::string> get_args(const int argc, char** const argv, std: // Skip empty and '\0'-filled tokens. if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it)); } - LOG(INFO) << "Got " << args.size() << " arguments from boot message"; + LOG(INFO) << "Got " << args.size() << " arguments from boot message " << android::base::Join(args, ", "); } else if (boot.recovery[0] != 0) { LOG(ERROR) << "Bad boot message: \"" << boot_recovery << "\""; } diff --git a/recovery_utils/include/recovery_utils/roots.h b/recovery_utils/include/recovery_utils/roots.h index cbc8b07a..aa7b0eeb 100644 --- a/recovery_utils/include/recovery_utils/roots.h +++ b/recovery_utils/include/recovery_utils/roots.h @@ -52,7 +52,8 @@ int format_volume(const std::string& volume); // "/cache"), no paths permitted. Attempts to unmount the volume if // it is mounted. // Copies 'directory' to root of the newly formatted volume -int format_volume(const std::string& volume, const std::string& directory); +int format_volume(const std::string& volume, const std::string& directory, + std::string_view new_fstype); // Ensure that all and only the volumes that packages expect to find // mounted (/tmp and /cache) are mounted. Returns 0 on success. diff --git a/recovery_utils/roots.cpp b/recovery_utils/roots.cpp index b6a2ce4b..5a542fd2 100644 --- a/recovery_utils/roots.cpp +++ b/recovery_utils/roots.cpp @@ -206,7 +206,8 @@ static int64_t get_file_size(int fd, uint64_t reserve_len) { return computed_size; } -int format_volume(const std::string& volume, const std::string& directory) { +int format_volume(const std::string& volume, const std::string& directory, + std::string_view new_fstype) { const FstabEntry* v = android::fs_mgr::GetEntryForPath(&fstab, volume); if (v == nullptr) { LOG(ERROR) << "unknown volume \"" << volume << "\""; @@ -252,11 +253,13 @@ int format_volume(const std::string& volume, const std::string& directory) { } // If the raw disk will be used as a metadata encrypted device mapper target, - // next boot will do encrypt_in_place the raw disk which gives a subtle duration - // to get any failure in the process. In order to avoid it, let's simply wipe - // the raw disk if we don't reserve any space, which behaves exactly same as booting - // after "fastboot -w". - if (!v->metadata_key_dir.empty() && length == 0) { + // next boot will do encrypt_in_place the raw disk. While fs_mgr mounts /data + // as RO to avoid write file operations before encrypt_inplace, this code path + // is not well tested so we would like to avoid it if possible. For safety, + // let vold do the formatting on boot for metadata encrypted devices, except + // when user specified a new fstype. Because init formats /data according + // to fstab, it's difficult to override the fstab in init. + if (!v->metadata_key_dir.empty() && length == 0 && new_fstype.empty()) { android::base::unique_fd fd(open(v->blk_device.c_str(), O_RDWR)); if (fd == -1) { PLOG(ERROR) << "format_volume: failed to open " << v->blk_device; @@ -270,7 +273,8 @@ int format_volume(const std::string& volume, const std::string& directory) { } } - if (v->fs_type == "ext4") { + if ((v->fs_type == "ext4" && new_fstype.empty()) || new_fstype == "ext4") { + LOG(INFO) << "Formatting " << v->blk_device << " as ext4"; static constexpr int kBlockSize = 4096; std::vector<std::string> mke2fs_args = { "/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize), @@ -322,6 +326,7 @@ int format_volume(const std::string& volume, const std::string& directory) { } // Has to be f2fs because we checked earlier. + LOG(INFO) << "Formatting " << v->blk_device << " as f2fs"; static constexpr int kSectorSize = 4096; std::vector<std::string> make_f2fs_cmd = { "/system/bin/make_f2fs", @@ -366,7 +371,7 @@ int format_volume(const std::string& volume, const std::string& directory) { } int format_volume(const std::string& volume) { - return format_volume(volume, ""); + return format_volume(volume, "", ""); } int setup_install_mounts() { diff --git a/updater/Android.bp b/updater/Android.bp index 35debaaf..4fc3c494 100644 --- a/updater/Android.bp +++ b/updater/Android.bp @@ -44,7 +44,7 @@ cc_defaults { "libbrotli", "libbz", "libziparchive", - "libz", + "libz_stable", "libbase", "libcrypto_utils", "libcutils", diff --git a/updater/Android.mk b/updater/Android.mk index bb1c07d4..2fd56397 100644 --- a/updater/Android.mk +++ b/updater/Android.mk @@ -42,7 +42,7 @@ updater_common_static_libraries := \ libbrotli \ libbz \ libziparchive \ - libz \ + libz_stable \ libbase \ libcrypto_static \ libcrypto_utils \ diff --git a/updater/dynamic_partitions.cpp b/updater/dynamic_partitions.cpp index a340116f..b94bd0e5 100644 --- a/updater/dynamic_partitions.cpp +++ b/updater/dynamic_partitions.cpp @@ -88,8 +88,10 @@ static constexpr char kMetadataUpdatedMarker[] = "/dynamic_partition_metadata.UP Value* UpdateDynamicPartitionsFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) { - if (argv.size() != 1) { - ErrorAbort(state, kArgsParsingFailure, "%s expects 1 arguments, got %zu", name, argv.size()); + const std::string_view empty_string_view{}; + if (argv.size() != 1 && argv.size() != 2) { + ErrorAbort(state, kArgsParsingFailure, "%s expects 1 or 2 arguments, got %zu", name, + argv.size()); return StringValue(""); } std::vector<std::unique_ptr<Value>> args; @@ -102,6 +104,14 @@ Value* UpdateDynamicPartitionsFn(const char* name, State* state, return StringValue(""); } + const std::unique_ptr<Value>& super_empty_value = args[1]; + if (argv.size() > 1) { + if (super_empty_value->type != Value::Type::BLOB) { + ErrorAbort(state, kArgsParsingFailure, "super_empty argument to %s must be blob", name); + return StringValue(""); + } + } + std::string updated_marker = Paths::Get().stash_directory_base() + kMetadataUpdatedMarker; if (state->is_retry) { struct stat sb; @@ -121,7 +131,8 @@ Value* UpdateDynamicPartitionsFn(const char* name, State* state, } auto updater_runtime = state->updater->GetRuntime(); - if (!updater_runtime->UpdateDynamicPartitions(op_list_value->data)) { + if (!updater_runtime->UpdateDynamicPartitions( + op_list_value->data, argv.size() > 1 ? super_empty_value->data : empty_string_view)) { return StringValue(""); } diff --git a/updater/include/updater/simulator_runtime.h b/updater/include/updater/simulator_runtime.h index fa878db3..419f01eb 100644 --- a/updater/include/updater/simulator_runtime.h +++ b/updater/include/updater/simulator_runtime.h @@ -52,7 +52,8 @@ class SimulatorRuntime : public UpdaterRuntimeInterface { bool MapPartitionOnDeviceMapper(const std::string& partition_name, std::string* path) override; bool UnmapPartitionOnDeviceMapper(const std::string& partition_name) override; - bool UpdateDynamicPartitions(const std::string_view op_list_value) override; + bool UpdateDynamicPartitions(const std::string_view op_list_value, + const std::string_view super_empty_value) override; std::string AddSlotSuffix(const std::string_view arg) const override; private: diff --git a/updater/include/updater/updater_runtime.h b/updater/include/updater/updater_runtime.h index fc537d24..2f1d825a 100644 --- a/updater/include/updater/updater_runtime.h +++ b/updater/include/updater/updater_runtime.h @@ -22,6 +22,7 @@ #include <utility> #include <vector> +#include "edify/expr.h" #include "edify/updater_runtime_interface.h" class UpdaterRuntime : public UpdaterRuntimeInterface { @@ -53,7 +54,8 @@ class UpdaterRuntime : public UpdaterRuntimeInterface { bool MapPartitionOnDeviceMapper(const std::string& partition_name, std::string* path) override; bool UnmapPartitionOnDeviceMapper(const std::string& partition_name) override; - bool UpdateDynamicPartitions(const std::string_view op_list_value) override; + bool UpdateDynamicPartitions(const std::string_view op_list_value, + const std::string_view super_empty_value) override; std::string AddSlotSuffix(const std::string_view arg) const override; struct selabel_handle* sehandle() const override { diff --git a/updater/simulator_runtime.cpp b/updater/simulator_runtime.cpp index 57dfb32d..e670a3f7 100644 --- a/updater/simulator_runtime.cpp +++ b/updater/simulator_runtime.cpp @@ -113,7 +113,8 @@ bool SimulatorRuntime::UnmapPartitionOnDeviceMapper(const std::string& partition return true; } -bool SimulatorRuntime::UpdateDynamicPartitions(const std::string_view op_list_value) { +bool SimulatorRuntime::UpdateDynamicPartitions(const std::string_view op_list_value, + const std::string_view /* super_empty_value */) { const std::unordered_set<std::string> commands{ "resize", "remove", "add", "move", "add_group", "resize_group", "remove_group", "remove_all_groups", diff --git a/updater/updater_runtime_dynamic_partitions.cpp b/updater/updater_runtime_dynamic_partitions.cpp index 6570cfff..e671a30b 100644 --- a/updater/updater_runtime_dynamic_partitions.cpp +++ b/updater/updater_runtime_dynamic_partitions.cpp @@ -41,6 +41,7 @@ using android::fs_mgr::LpMetadata; using android::fs_mgr::MetadataBuilder; using android::fs_mgr::Partition; using android::fs_mgr::PartitionOpener; +using android::fs_mgr::ReadFromImageBlob; using android::fs_mgr::SlotNumberForSlotSuffix; static constexpr std::chrono::milliseconds kMapTimeout{ 1000 }; @@ -298,12 +299,30 @@ bool PerformOpRemoveAllGroups(const OpParameters& params) { } // namespace -bool UpdaterRuntime::UpdateDynamicPartitions(const std::string_view op_list_value) { +bool UpdaterRuntime::UpdateDynamicPartitions(const std::string_view op_list_value, + const std::string_view super_empty_value) { + bool flash_metadata = false; + const auto partition_opener = PartitionOpener(); auto super_device = GetSuperDevice(); - auto builder = MetadataBuilder::New(PartitionOpener(), super_device, 0); + auto builder = MetadataBuilder::New(partition_opener, super_device, 0); if (builder == nullptr) { - LOG(ERROR) << "Failed to load dynamic partition metadata."; - return false; + LOG(ERROR) << "Failed to load dynamic partition metadata from device."; + if (super_empty_value.size()) { + LOG(INFO) << "Trying to load dynamic partition metadata from OTA."; + const auto metadata = ReadFromImageBlob(super_empty_value.data(), super_empty_value.size()); + if (metadata == nullptr) { + LOG(ERROR) << "Failed to parse dynamic partition metadata from OTA."; + return false; + } + builder = MetadataBuilder::New(*metadata, &partition_opener); + if (builder == nullptr) { + LOG(ERROR) << "Failed to initialize dynamic partition metadata from OTA."; + return false; + } + flash_metadata = true; + } else { + return false; + } } static const OpMap op_map{ @@ -347,9 +366,16 @@ bool UpdaterRuntime::UpdateDynamicPartitions(const std::string_view op_list_valu return false; } - if (!UpdatePartitionTable(super_device, *metadata, 0)) { - LOG(ERROR) << "Failed to write metadata."; - return false; + if (flash_metadata) { + if (!FlashPartitionTable(super_device, *metadata)) { + LOG(ERROR) << "Failed to flash metadata."; + return false; + } + } else { + if (!UpdatePartitionTable(super_device, *metadata, 0)) { + LOG(ERROR) << "Failed to write metadata."; + return false; + } } return true; |
