Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73549948 authored by Kelvin Zhang's avatar Kelvin Zhang
Browse files

Add recovery flag to reformat /data

For 16K dev options, we might need to reformat /data partition as ext4
before enabling the feature. Add necessary support to recovery.

Test: Trigger reboot with --wipe_data --reformat_data=ext4, make sure
/data is reformatted with ext4 on next boot
Bug: 293313353

Change-Id: I3cb67a62635a2df578472cd48cf6d2f5e04b5f82
parent c117b7e4
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -24,7 +24,8 @@
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 = "");
+11 −10
Original line number Diff line number Diff line
@@ -27,7 +27,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"
@@ -36,7 +35,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;
@@ -50,7 +50,7 @@ static bool EraseVolume(const char* volume, RecoveryUI* ui) {

  ensure_path_unmounted(volume);

  int result = format_volume(volume);
  int result = format_volume(volume, "", new_fstype);

  if (is_cache) {
    RestoreLogFilesAfterFormat(log_files);
@@ -59,7 +59,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");
@@ -74,14 +75,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);

@@ -92,13 +93,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) {
+11 −11
Original line number Diff line number Diff line
@@ -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>
@@ -51,7 +48,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"
@@ -463,7 +459,7 @@ static Device::BuiltinAction PromptAndWait(Device* device, InstallResult status)
        WriteUpdateInProgress();

        bool adb = true;
        Device::BuiltinAction reboot_action;
        Device::BuiltinAction reboot_action{};
        if (chosen_action == Device::ENTER_RESCUE) {
          // Switch to graphics screen.
          ui->ShowText(false);
@@ -610,6 +606,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 },
  };

@@ -632,8 +629,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).
@@ -677,6 +675,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;
        }
@@ -698,7 +698,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);
@@ -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.
    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.
@@ -797,7 +797,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) {
@@ -812,7 +812,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) {
+1 −1
Original line number Diff line number Diff line
@@ -130,7 +130,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 << "\"";
    }
+2 −1
Original line number Diff line number Diff line
@@ -48,7 +48,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.
Loading