Merge "Add recovery flag to reformat /data" into main am: c7fad9a77c
am: 7390406dd1
am: a5c8b4e739
Original change: https://android-review.googlesource.com/c/platform/bootable/recovery/+/2898791 Change-Id: Idf6561986a243fdd7ca4b89d824bb26b837a4ecc Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
0aaa5af8aa
6 changed files with 36 additions and 45 deletions
|
@ -24,7 +24,8 @@
|
||||||
struct selabel_handle;
|
struct selabel_handle;
|
||||||
|
|
||||||
// Returns true on success.
|
// 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.
|
// 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 = "");
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
|
|
||||||
#include "bootloader_message/bootloader_message.h"
|
#include "bootloader_message/bootloader_message.h"
|
||||||
#include "install/snapshot_utils.h"
|
#include "install/snapshot_utils.h"
|
||||||
#include "otautil/dirutil.h"
|
|
||||||
#include "recovery_ui/ui.h"
|
#include "recovery_ui/ui.h"
|
||||||
#include "recovery_utils/logging.h"
|
#include "recovery_utils/logging.h"
|
||||||
#include "recovery_utils/roots.h"
|
#include "recovery_utils/roots.h"
|
||||||
|
@ -36,7 +35,8 @@ constexpr const char* CACHE_ROOT = "/cache";
|
||||||
constexpr const char* DATA_ROOT = "/data";
|
constexpr const char* DATA_ROOT = "/data";
|
||||||
constexpr const char* METADATA_ROOT = "/metadata";
|
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);
|
bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
|
||||||
|
|
||||||
std::vector<saved_log_file> log_files;
|
std::vector<saved_log_file> log_files;
|
||||||
|
@ -50,7 +50,7 @@ static bool EraseVolume(const char* volume, RecoveryUI* ui) {
|
||||||
|
|
||||||
ensure_path_unmounted(volume);
|
ensure_path_unmounted(volume);
|
||||||
|
|
||||||
int result = format_volume(volume);
|
int result = format_volume(volume, "", new_fstype);
|
||||||
|
|
||||||
if (is_cache) {
|
if (is_cache) {
|
||||||
RestoreLogFilesAfterFormat(log_files);
|
RestoreLogFilesAfterFormat(log_files);
|
||||||
|
@ -59,7 +59,8 @@ static bool EraseVolume(const char* volume, RecoveryUI* ui) {
|
||||||
return (result == 0);
|
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;
|
bool has_cache = volume_for_mount_point("/cache") != nullptr;
|
||||||
if (!has_cache) {
|
if (!has_cache) {
|
||||||
ui->Print("No /cache partition found.\n");
|
ui->Print("No /cache partition found.\n");
|
||||||
|
@ -74,14 +75,14 @@ bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm_func) {
|
||||||
ui->SetBackground(RecoveryUI::ERASING);
|
ui->SetBackground(RecoveryUI::ERASING);
|
||||||
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
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");
|
ui->Print("Cache wipe %s.\n", success ? "complete" : "failed");
|
||||||
return success;
|
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();
|
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->SetBackground(RecoveryUI::ERASING);
|
||||||
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
ui->SetProgressType(RecoveryUI::INDETERMINATE);
|
||||||
|
|
||||||
|
@ -92,13 +93,13 @@ bool WipeData(Device* device, bool keep_memtag_mode) {
|
||||||
|
|
||||||
bool success = device->PreWipeData();
|
bool success = device->PreWipeData();
|
||||||
if (success) {
|
if (success) {
|
||||||
success &= EraseVolume(DATA_ROOT, ui);
|
success &= EraseVolume(DATA_ROOT, ui, data_fstype);
|
||||||
bool has_cache = volume_for_mount_point("/cache") != nullptr;
|
bool has_cache = volume_for_mount_point("/cache") != nullptr;
|
||||||
if (has_cache) {
|
if (has_cache) {
|
||||||
success &= EraseVolume(CACHE_ROOT, ui);
|
success &= EraseVolume(CACHE_ROOT, ui, data_fstype);
|
||||||
}
|
}
|
||||||
if (volume_for_mount_point(METADATA_ROOT) != nullptr) {
|
if (volume_for_mount_point(METADATA_ROOT) != nullptr) {
|
||||||
success &= EraseVolume(METADATA_ROOT, ui);
|
success &= EraseVolume(METADATA_ROOT, ui, data_fstype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (keep_memtag_mode) {
|
if (keep_memtag_mode) {
|
||||||
|
|
22
recovery.cpp
22
recovery.cpp
|
@ -16,11 +16,8 @@
|
||||||
|
|
||||||
#include "recovery.h"
|
#include "recovery.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -51,7 +48,6 @@
|
||||||
#include "install/snapshot_utils.h"
|
#include "install/snapshot_utils.h"
|
||||||
#include "install/wipe_data.h"
|
#include "install/wipe_data.h"
|
||||||
#include "install/wipe_device.h"
|
#include "install/wipe_device.h"
|
||||||
#include "otautil/boot_state.h"
|
|
||||||
#include "otautil/error_code.h"
|
#include "otautil/error_code.h"
|
||||||
#include "otautil/package.h"
|
#include "otautil/package.h"
|
||||||
#include "otautil/paths.h"
|
#include "otautil/paths.h"
|
||||||
|
@ -463,7 +459,7 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status)
|
||||||
WriteUpdateInProgress();
|
WriteUpdateInProgress();
|
||||||
|
|
||||||
bool adb = true;
|
bool adb = true;
|
||||||
Device::BuiltinAction reboot_action;
|
Device::BuiltinAction reboot_action{};
|
||||||
if (chosen_action == Device::ENTER_RESCUE) {
|
if (chosen_action == Device::ENTER_RESCUE) {
|
||||||
// Switch to graphics screen.
|
// Switch to graphics screen.
|
||||||
ui->ShowText(false);
|
ui->ShowText(false);
|
||||||
|
@ -610,6 +606,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
||||||
{ "wipe_data", no_argument, nullptr, 0 },
|
{ "wipe_data", no_argument, nullptr, 0 },
|
||||||
{ "keep_memtag_mode", no_argument, nullptr, 0 },
|
{ "keep_memtag_mode", no_argument, nullptr, 0 },
|
||||||
{ "wipe_package_size", required_argument, nullptr, 0 },
|
{ "wipe_package_size", required_argument, nullptr, 0 },
|
||||||
|
{ "reformat_data", required_argument, nullptr, 0 },
|
||||||
{ nullptr, 0, nullptr, 0 },
|
{ nullptr, 0, nullptr, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -632,8 +629,9 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
||||||
|
|
||||||
auto args_to_parse = StringVectorToNullTerminatedArray(args);
|
auto args_to_parse = StringVectorToNullTerminatedArray(args);
|
||||||
|
|
||||||
int arg;
|
int arg = 0;
|
||||||
int option_index;
|
int option_index = 0;
|
||||||
|
std::string data_fstype;
|
||||||
// Parse everything before the last element (which must be a nullptr). getopt_long(3) expects a
|
// 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
|
// null-terminated char* array, but without counting null as an arg (i.e. argv[argc] should be
|
||||||
// nullptr).
|
// nullptr).
|
||||||
|
@ -677,6 +675,8 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
||||||
should_wipe_data = true;
|
should_wipe_data = true;
|
||||||
} else if (option == "wipe_package_size") {
|
} else if (option == "wipe_package_size") {
|
||||||
android::base::ParseUint(optarg, &wipe_package_size);
|
android::base::ParseUint(optarg, &wipe_package_size);
|
||||||
|
} else if (option == "reformat_data") {
|
||||||
|
data_fstype = optarg;
|
||||||
} else if (option == "keep_memtag_mode") {
|
} else if (option == "keep_memtag_mode") {
|
||||||
should_keep_memtag_mode = true;
|
should_keep_memtag_mode = true;
|
||||||
}
|
}
|
||||||
|
@ -698,7 +698,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
||||||
// otherwise set it to "installing system update".
|
// otherwise set it to "installing system update".
|
||||||
ui->SetSystemUpdateText(security_update);
|
ui->SetSystemUpdateText(security_update);
|
||||||
|
|
||||||
int st_cur, st_max;
|
int st_cur = 0, st_max = 0;
|
||||||
if (!device->GetStage().has_value() &&
|
if (!device->GetStage().has_value() &&
|
||||||
sscanf(device->GetStage().value().c_str(), "%d/%d", &st_cur, &st_max) == 2) {
|
sscanf(device->GetStage().value().c_str(), "%d/%d", &st_cur, &st_max) == 2) {
|
||||||
ui->SetStage(st_cur, st_max);
|
ui->SetStage(st_cur, st_max);
|
||||||
|
@ -731,7 +731,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
||||||
// to log the update attempt since update_package is non-NULL.
|
// to log the update attempt since update_package is non-NULL.
|
||||||
save_current_log = true;
|
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",
|
ui->Print("battery capacity is not enough for installing package: %d%% needed\n",
|
||||||
required_battery_level);
|
required_battery_level);
|
||||||
// Log the error code to last_install when installation skips due to low battery.
|
// Log the error code to last_install when installation skips due to low battery.
|
||||||
|
@ -797,7 +797,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
||||||
} else if (should_wipe_data) {
|
} else if (should_wipe_data) {
|
||||||
save_current_log = true;
|
save_current_log = true;
|
||||||
CHECK(device->GetReason().has_value());
|
CHECK(device->GetReason().has_value());
|
||||||
if (!WipeData(device, should_keep_memtag_mode)) {
|
if (!WipeData(device, should_keep_memtag_mode, data_fstype)) {
|
||||||
status = INSTALL_ERROR;
|
status = INSTALL_ERROR;
|
||||||
}
|
}
|
||||||
} else if (should_prompt_and_wipe_data) {
|
} else if (should_prompt_and_wipe_data) {
|
||||||
|
@ -812,7 +812,7 @@ Device::BuiltinAction start_recovery(Device* device, const std::vector<std::stri
|
||||||
}
|
}
|
||||||
} else if (should_wipe_cache) {
|
} else if (should_wipe_cache) {
|
||||||
save_current_log = true;
|
save_current_log = true;
|
||||||
if (!WipeCache(ui, nullptr)) {
|
if (!WipeCache(ui, nullptr, data_fstype)) {
|
||||||
status = INSTALL_ERROR;
|
status = INSTALL_ERROR;
|
||||||
}
|
}
|
||||||
} else if (should_wipe_ab) {
|
} else if (should_wipe_ab) {
|
||||||
|
|
|
@ -130,7 +130,7 @@ static std::vector<std::string> get_args(const int argc, char** const argv, std:
|
||||||
// Skip empty and '\0'-filled tokens.
|
// Skip empty and '\0'-filled tokens.
|
||||||
if (!it->empty() && (*it)[0] != '\0') args.push_back(std::move(*it));
|
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) {
|
} else if (boot.recovery[0] != 0) {
|
||||||
LOG(ERROR) << "Bad boot message: \"" << boot_recovery << "\"";
|
LOG(ERROR) << "Bad boot message: \"" << boot_recovery << "\"";
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,8 @@ int format_volume(const std::string& volume);
|
||||||
// "/cache"), no paths permitted. Attempts to unmount the volume if
|
// "/cache"), no paths permitted. Attempts to unmount the volume if
|
||||||
// it is mounted.
|
// it is mounted.
|
||||||
// Copies 'directory' to root of the newly formatted volume
|
// 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
|
// Ensure that all and only the volumes that packages expect to find
|
||||||
// mounted (/tmp and /cache) are mounted. Returns 0 on success.
|
// mounted (/tmp and /cache) are mounted. Returns 0 on success.
|
||||||
|
|
|
@ -130,7 +130,8 @@ static int64_t get_file_size(int fd, uint64_t reserve_len) {
|
||||||
return computed_size;
|
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);
|
const FstabEntry* v = android::fs_mgr::GetEntryForPath(&fstab, volume);
|
||||||
if (v == nullptr) {
|
if (v == nullptr) {
|
||||||
LOG(ERROR) << "unknown volume \"" << volume << "\"";
|
LOG(ERROR) << "unknown volume \"" << volume << "\"";
|
||||||
|
@ -176,25 +177,11 @@ 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,
|
// 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
|
// next boot will first mount this partition as read only, and then unmount,
|
||||||
// to get any failure in the process. In order to avoid it, let's simply wipe
|
// call encrypt_inplace.
|
||||||
// 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) {
|
|
||||||
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;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int64_t device_size = get_file_size(fd.get(), 0);
|
|
||||||
if (device_size > 0 && !wipe_block_device(fd.get(), device_size)) {
|
|
||||||
LOG(INFO) << "format_volume: wipe metadata encrypted " << v->blk_device << " with size "
|
|
||||||
<< device_size;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
static constexpr int kBlockSize = 4096;
|
||||||
std::vector<std::string> mke2fs_args = {
|
std::vector<std::string> mke2fs_args = {
|
||||||
"/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize),
|
"/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize),
|
||||||
|
@ -246,6 +233,7 @@ int format_volume(const std::string& volume, const std::string& directory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has to be f2fs because we checked earlier.
|
// Has to be f2fs because we checked earlier.
|
||||||
|
LOG(INFO) << "Formatting " << v->blk_device << " as f2fs";
|
||||||
static constexpr int kSectorSize = 4096;
|
static constexpr int kSectorSize = 4096;
|
||||||
std::vector<std::string> make_f2fs_cmd = {
|
std::vector<std::string> make_f2fs_cmd = {
|
||||||
"/system/bin/make_f2fs",
|
"/system/bin/make_f2fs",
|
||||||
|
@ -290,7 +278,7 @@ int format_volume(const std::string& volume, const std::string& directory) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int format_volume(const std::string& volume) {
|
int format_volume(const std::string& volume) {
|
||||||
return format_volume(volume, "");
|
return format_volume(volume, "", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
int setup_install_mounts() {
|
int setup_install_mounts() {
|
||||||
|
|
Loading…
Reference in a new issue