aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Veit <Claymore1298@gmail.com>2024-07-08 07:46:54 +0200
committerJulian Veit <Claymore1298@gmail.com>2024-07-08 07:46:54 +0200
commit0aac54a0e9fd9d80d43d7154370810ac86e92f1b (patch)
treed63c54a4973f5958ab5d6def478563d27a72b6eb
parentaf9a42f1d13ffeca2eabf368580ad6790e2763ba (diff)
parent8bbe7bae399b428cfaa021a511d749c78e5a8e73 (diff)
Merge https://github.com/LineageOS/android_bootable_recovery into HEADu14.0
Change-Id: I05e44ba7ba265c80b0f6bf48f2c084e2598c69e4
-rw-r--r--Android.mk5
-rw-r--r--bootloader_message/Android.bp11
-rw-r--r--bootloader_message/bootloader_message.cpp38
-rw-r--r--bootloader_message/include/bootloader_message/bootloader_message.h46
-rw-r--r--bootloader_message/misctrl.rc4
-rw-r--r--bootloader_message/misctrl_main.cpp91
-rw-r--r--edify/include/edify/updater_runtime_interface.h3
-rw-r--r--install/include/install/wipe_data.h8
-rw-r--r--install/wipe_data.cpp26
-rw-r--r--recovery.cpp22
-rw-r--r--recovery_main.cpp2
-rw-r--r--recovery_utils/include/recovery_utils/roots.h3
-rw-r--r--recovery_utils/roots.cpp21
-rw-r--r--updater/Android.bp2
-rw-r--r--updater/Android.mk2
-rw-r--r--updater/dynamic_partitions.cpp17
-rw-r--r--updater/include/updater/simulator_runtime.h3
-rw-r--r--updater/include/updater/updater_runtime.h4
-rw-r--r--updater/simulator_runtime.cpp3
-rw-r--r--updater/updater_runtime_dynamic_partitions.cpp40
20 files changed, 299 insertions, 52 deletions
diff --git a/Android.mk b/Android.mk
index 273be14a..ee7f7813 100644
--- a/Android.mk
+++ b/Android.mk
@@ -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;