Merge changes from topic "mount-vendor-in-microdroid" into main
* changes: Support for conditionally mounting /vendor partition in Microdroid Small refactoring in first_stage_mount
This commit is contained in:
commit
230af76757
3 changed files with 115 additions and 95 deletions
|
|
@ -257,6 +257,16 @@ static BootMode GetBootMode(const std::string& cmdline, const std::string& bootc
|
|||
return BootMode::NORMAL_MODE;
|
||||
}
|
||||
|
||||
static std::unique_ptr<FirstStageMount> CreateFirstStageMount(const std::string& cmdline) {
|
||||
auto ret = FirstStageMount::Create(cmdline);
|
||||
if (ret.ok()) {
|
||||
return std::move(*ret);
|
||||
} else {
|
||||
LOG(ERROR) << "Failed to create FirstStageMount : " << ret.error();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int FirstStageMain(int argc, char** argv) {
|
||||
if (REBOOT_BOOTLOADER_ON_PANIC) {
|
||||
InstallRebootSignalHandlers();
|
||||
|
|
@ -381,12 +391,17 @@ int FirstStageMain(int argc, char** argv) {
|
|||
<< module_elapse_time.count() << " ms";
|
||||
}
|
||||
|
||||
std::unique_ptr<FirstStageMount> fsm;
|
||||
|
||||
bool created_devices = false;
|
||||
if (want_console == FirstStageConsoleParam::CONSOLE_ON_FAILURE) {
|
||||
if (!IsRecoveryMode()) {
|
||||
created_devices = DoCreateDevices();
|
||||
if (!created_devices) {
|
||||
LOG(ERROR) << "Failed to create device nodes early";
|
||||
fsm = CreateFirstStageMount(cmdline);
|
||||
if (fsm) {
|
||||
created_devices = fsm->DoCreateDevices();
|
||||
if (!created_devices) {
|
||||
LOG(ERROR) << "Failed to create device nodes early";
|
||||
}
|
||||
}
|
||||
}
|
||||
StartConsole(cmdline);
|
||||
|
|
@ -437,8 +452,23 @@ int FirstStageMain(int argc, char** argv) {
|
|||
SwitchRoot("/first_stage_ramdisk");
|
||||
}
|
||||
|
||||
if (!DoFirstStageMount(!created_devices)) {
|
||||
LOG(FATAL) << "Failed to mount required partitions early ...";
|
||||
if (IsRecoveryMode()) {
|
||||
LOG(INFO) << "First stage mount skipped (recovery mode)";
|
||||
} else {
|
||||
if (!fsm) {
|
||||
fsm = CreateFirstStageMount(cmdline);
|
||||
}
|
||||
if (!fsm) {
|
||||
LOG(FATAL) << "FirstStageMount not available";
|
||||
}
|
||||
|
||||
if (!created_devices && !fsm->DoCreateDevices()) {
|
||||
LOG(FATAL) << "Failed to create devices required for first stage mount";
|
||||
}
|
||||
|
||||
if (!fsm->DoFirstStageMount()) {
|
||||
LOG(FATAL) << "Failed to mount required partitions early ...";
|
||||
}
|
||||
}
|
||||
|
||||
struct stat new_root_info;
|
||||
|
|
|
|||
|
|
@ -76,21 +76,21 @@ namespace init {
|
|||
|
||||
// Class Declarations
|
||||
// ------------------
|
||||
class FirstStageMount {
|
||||
class FirstStageMountVBootV2 : public FirstStageMount {
|
||||
public:
|
||||
FirstStageMount(Fstab fstab);
|
||||
virtual ~FirstStageMount() = default;
|
||||
friend void SetInitAvbVersionInRecovery();
|
||||
|
||||
// The factory method to create a FirstStageMountVBootV2 instance.
|
||||
static Result<std::unique_ptr<FirstStageMount>> Create();
|
||||
bool DoCreateDevices(); // Creates devices and logical partitions from storage devices
|
||||
bool DoFirstStageMount(); // Mounts fstab entries read from device tree.
|
||||
FirstStageMountVBootV2(Fstab fstab);
|
||||
virtual ~FirstStageMountVBootV2() = default;
|
||||
|
||||
bool DoCreateDevices() override;
|
||||
bool DoFirstStageMount() override;
|
||||
|
||||
private:
|
||||
bool InitDevices();
|
||||
|
||||
protected:
|
||||
bool InitRequiredDevices(std::set<std::string> devices);
|
||||
bool CreateLogicalPartitions();
|
||||
bool CreateSnapshotPartitions(android::snapshot::SnapshotManager* sm);
|
||||
bool CreateSnapshotPartitions(SnapshotManager* sm);
|
||||
bool MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
|
||||
Fstab::iterator* end = nullptr);
|
||||
|
||||
|
|
@ -106,9 +106,10 @@ class FirstStageMount {
|
|||
// revocation check by DSU installation service.
|
||||
void CopyDsuAvbKeys();
|
||||
|
||||
// Pure virtual functions.
|
||||
virtual bool GetDmVerityDevices(std::set<std::string>* devices) = 0;
|
||||
virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
|
||||
bool GetDmVerityDevices(std::set<std::string>* devices);
|
||||
bool SetUpDmVerity(FstabEntry* fstab_entry);
|
||||
|
||||
bool InitAvbHandle();
|
||||
|
||||
bool need_dm_verity_;
|
||||
bool dsu_not_on_userdata_ = false;
|
||||
|
|
@ -122,19 +123,6 @@ class FirstStageMount {
|
|||
// Reads all AVB keys before chroot into /system, as they might be used
|
||||
// later when mounting other partitions, e.g., /vendor and /product.
|
||||
std::map<std::string, std::vector<std::string>> preload_avb_key_blobs_;
|
||||
};
|
||||
|
||||
class FirstStageMountVBootV2 : public FirstStageMount {
|
||||
public:
|
||||
friend void SetInitAvbVersionInRecovery();
|
||||
|
||||
FirstStageMountVBootV2(Fstab fstab);
|
||||
~FirstStageMountVBootV2() override = default;
|
||||
|
||||
protected:
|
||||
bool GetDmVerityDevices(std::set<std::string>* devices) override;
|
||||
bool SetUpDmVerity(FstabEntry* fstab_entry) override;
|
||||
bool InitAvbHandle();
|
||||
|
||||
std::vector<std::string> vbmeta_partitions_;
|
||||
AvbUniquePtr avb_handle_;
|
||||
|
|
@ -150,7 +138,7 @@ static inline bool IsDtVbmetaCompatible(const Fstab& fstab) {
|
|||
return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
|
||||
}
|
||||
|
||||
static Result<Fstab> ReadFirstStageFstab() {
|
||||
static Result<Fstab> ReadFirstStageFstabAndroid() {
|
||||
Fstab fstab;
|
||||
if (!ReadFstabFromDt(&fstab)) {
|
||||
if (ReadDefaultFstab(&fstab)) {
|
||||
|
|
@ -166,6 +154,24 @@ static Result<Fstab> ReadFirstStageFstab() {
|
|||
return fstab;
|
||||
}
|
||||
|
||||
// Note: this is a temporary solution to avoid blocking devs that depend on /vendor partition in
|
||||
// Microdroid. For the proper solution the /vendor fstab should probably be defined in the DT.
|
||||
// TODO(b/285855430): refactor this
|
||||
// TODO(b/285855436): verify key microdroid-vendor was signed with.
|
||||
// TODO(b/285855436): should be mounted on top of dm-verity device.
|
||||
static Result<Fstab> ReadFirstStageFstabMicrodroid(const std::string& cmdline) {
|
||||
Fstab fstab;
|
||||
if (!ReadDefaultFstab(&fstab)) {
|
||||
return Error() << "failed to read fstab";
|
||||
}
|
||||
if (cmdline.find("androidboot.microdroid.mount_vendor=1") == std::string::npos) {
|
||||
// We weren't asked to mount /vendor partition, filter it out from the fstab.
|
||||
auto predicate = [](const auto& entry) { return entry.mount_point == "/vendor"; };
|
||||
fstab.erase(std::remove_if(fstab.begin(), fstab.end(), predicate), fstab.end());
|
||||
}
|
||||
return fstab;
|
||||
}
|
||||
|
||||
static bool GetRootEntry(FstabEntry* root_entry) {
|
||||
Fstab proc_mounts;
|
||||
if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
|
||||
|
|
@ -218,14 +224,13 @@ static bool IsStandaloneImageRollback(const AvbHandle& builtin_vbmeta,
|
|||
return rollbacked;
|
||||
}
|
||||
|
||||
// Class Definitions
|
||||
// -----------------
|
||||
FirstStageMount::FirstStageMount(Fstab fstab) : need_dm_verity_(false), fstab_(std::move(fstab)) {
|
||||
super_partition_name_ = fs_mgr_get_super_partition_name();
|
||||
}
|
||||
|
||||
Result<std::unique_ptr<FirstStageMount>> FirstStageMount::Create() {
|
||||
auto fstab = ReadFirstStageFstab();
|
||||
Result<std::unique_ptr<FirstStageMount>> FirstStageMount::Create(const std::string& cmdline) {
|
||||
Result<Fstab> fstab;
|
||||
if (IsMicrodroid()) {
|
||||
fstab = ReadFirstStageFstabMicrodroid(cmdline);
|
||||
} else {
|
||||
fstab = ReadFirstStageFstabAndroid();
|
||||
}
|
||||
if (!fstab.ok()) {
|
||||
return fstab.error();
|
||||
}
|
||||
|
|
@ -233,7 +238,7 @@ Result<std::unique_ptr<FirstStageMount>> FirstStageMount::Create() {
|
|||
return std::make_unique<FirstStageMountVBootV2>(std::move(*fstab));
|
||||
}
|
||||
|
||||
bool FirstStageMount::DoCreateDevices() {
|
||||
bool FirstStageMountVBootV2::DoCreateDevices() {
|
||||
if (!InitDevices()) return false;
|
||||
|
||||
// Mount /metadata before creating logical partitions, since we need to
|
||||
|
|
@ -255,7 +260,7 @@ bool FirstStageMount::DoCreateDevices() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FirstStageMount::DoFirstStageMount() {
|
||||
bool FirstStageMountVBootV2::DoFirstStageMount() {
|
||||
if (!IsDmLinearEnabled() && fstab_.empty()) {
|
||||
// Nothing to mount.
|
||||
LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
|
||||
|
|
@ -267,7 +272,7 @@ bool FirstStageMount::DoFirstStageMount() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FirstStageMount::InitDevices() {
|
||||
bool FirstStageMountVBootV2::InitDevices() {
|
||||
std::set<std::string> devices;
|
||||
GetSuperDeviceName(&devices);
|
||||
|
||||
|
|
@ -288,14 +293,14 @@ bool FirstStageMount::InitDevices() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FirstStageMount::IsDmLinearEnabled() {
|
||||
bool FirstStageMountVBootV2::IsDmLinearEnabled() {
|
||||
for (const auto& entry : fstab_) {
|
||||
if (entry.fs_mgr_flags.logical) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void FirstStageMount::GetSuperDeviceName(std::set<std::string>* devices) {
|
||||
void FirstStageMountVBootV2::GetSuperDeviceName(std::set<std::string>* devices) {
|
||||
// Add any additional devices required for dm-linear mappings.
|
||||
if (!IsDmLinearEnabled()) {
|
||||
return;
|
||||
|
|
@ -307,7 +312,7 @@ void FirstStageMount::GetSuperDeviceName(std::set<std::string>* devices) {
|
|||
// Creates devices with uevent->partition_name matching ones in the given set.
|
||||
// Found partitions will then be removed from it for the subsequent member
|
||||
// function to check which devices are NOT created.
|
||||
bool FirstStageMount::InitRequiredDevices(std::set<std::string> devices) {
|
||||
bool FirstStageMountVBootV2::InitRequiredDevices(std::set<std::string> devices) {
|
||||
if (!block_dev_init_.InitDeviceMapper()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -317,7 +322,8 @@ bool FirstStageMount::InitRequiredDevices(std::set<std::string> devices) {
|
|||
return block_dev_init_.InitDevices(std::move(devices));
|
||||
}
|
||||
|
||||
bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
|
||||
bool FirstStageMountVBootV2::InitDmLinearBackingDevices(
|
||||
const android::fs_mgr::LpMetadata& metadata) {
|
||||
std::set<std::string> devices;
|
||||
|
||||
auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
|
||||
|
|
@ -334,7 +340,7 @@ bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetada
|
|||
return InitRequiredDevices(std::move(devices));
|
||||
}
|
||||
|
||||
bool FirstStageMount::CreateLogicalPartitions() {
|
||||
bool FirstStageMountVBootV2::CreateLogicalPartitions() {
|
||||
if (!IsDmLinearEnabled()) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -365,7 +371,7 @@ bool FirstStageMount::CreateLogicalPartitions() {
|
|||
return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path_);
|
||||
}
|
||||
|
||||
bool FirstStageMount::CreateSnapshotPartitions(SnapshotManager* sm) {
|
||||
bool FirstStageMountVBootV2::CreateSnapshotPartitions(SnapshotManager* sm) {
|
||||
// When COW images are present for snapshots, they are stored on
|
||||
// the data partition.
|
||||
if (!InitRequiredDevices({"userdata"})) {
|
||||
|
|
@ -400,8 +406,8 @@ bool FirstStageMount::CreateSnapshotPartitions(SnapshotManager* sm) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
|
||||
Fstab::iterator* end) {
|
||||
bool FirstStageMountVBootV2::MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
|
||||
Fstab::iterator* end) {
|
||||
// Sets end to begin + 1, so we can just return on failure below.
|
||||
if (end) {
|
||||
*end = begin + 1;
|
||||
|
|
@ -445,7 +451,7 @@ bool FirstStageMount::MountPartition(const Fstab::iterator& begin, bool erase_sa
|
|||
return mounted;
|
||||
}
|
||||
|
||||
void FirstStageMount::PreloadAvbKeys() {
|
||||
void FirstStageMountVBootV2::PreloadAvbKeys() {
|
||||
for (const auto& entry : fstab_) {
|
||||
// No need to cache the key content if it's empty, or is already cached.
|
||||
if (entry.avb_keys.empty() || preload_avb_key_blobs_.count(entry.avb_keys)) {
|
||||
|
|
@ -492,7 +498,7 @@ void FirstStageMount::PreloadAvbKeys() {
|
|||
// If system is in the fstab then we're not a system-as-root device, and in
|
||||
// this case, we mount system first then pivot to it. From that point on,
|
||||
// we are effectively identical to a system-as-root device.
|
||||
bool FirstStageMount::TrySwitchSystemAsRoot() {
|
||||
bool FirstStageMountVBootV2::TrySwitchSystemAsRoot() {
|
||||
UseDsuIfPresent();
|
||||
// Preloading all AVB keys from the ramdisk before switching root to /system.
|
||||
PreloadAvbKeys();
|
||||
|
|
@ -521,7 +527,7 @@ bool FirstStageMount::TrySwitchSystemAsRoot() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FirstStageMount::MountPartitions() {
|
||||
bool FirstStageMountVBootV2::MountPartitions() {
|
||||
if (!TrySwitchSystemAsRoot()) return false;
|
||||
|
||||
if (!SkipMountingPartitions(&fstab_, true /* verbose */)) return false;
|
||||
|
|
@ -604,7 +610,7 @@ bool FirstStageMount::MountPartitions() {
|
|||
// copy files to /metadata is NOT fatal, because it is auxiliary to perform
|
||||
// public key matching before booting into DSU images on next boot. The actual
|
||||
// public key matching will still be done on next boot to DSU.
|
||||
void FirstStageMount::CopyDsuAvbKeys() {
|
||||
void FirstStageMountVBootV2::CopyDsuAvbKeys() {
|
||||
std::error_code ec;
|
||||
// Removing existing keys in gsi::kDsuAvbKeyDir as they might be stale.
|
||||
std::filesystem::remove_all(gsi::kDsuAvbKeyDir, ec);
|
||||
|
|
@ -620,7 +626,7 @@ void FirstStageMount::CopyDsuAvbKeys() {
|
|||
}
|
||||
}
|
||||
|
||||
void FirstStageMount::UseDsuIfPresent() {
|
||||
void FirstStageMountVBootV2::UseDsuIfPresent() {
|
||||
std::string error;
|
||||
|
||||
if (!android::gsi::CanBootIntoGsi(&error)) {
|
||||
|
|
@ -657,10 +663,10 @@ void FirstStageMount::UseDsuIfPresent() {
|
|||
TransformFstabForDsu(&fstab_, active_dsu, dsu_partitions);
|
||||
}
|
||||
|
||||
// First retrieve any vbmeta partitions from device tree (legacy) then read through the fstab
|
||||
// for any further vbmeta partitions.
|
||||
FirstStageMountVBootV2::FirstStageMountVBootV2(Fstab fstab)
|
||||
: FirstStageMount(std::move(fstab)), avb_handle_(nullptr) {
|
||||
: need_dm_verity_(false), fstab_(std::move(fstab)), avb_handle_(nullptr) {
|
||||
super_partition_name_ = fs_mgr_get_super_partition_name();
|
||||
|
||||
std::string device_tree_vbmeta_parts;
|
||||
read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts);
|
||||
|
||||
|
|
@ -793,46 +799,13 @@ bool FirstStageMountVBootV2::InitAvbHandle() {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Public functions
|
||||
// ----------------
|
||||
// Creates devices and logical partitions from storage devices
|
||||
bool DoCreateDevices() {
|
||||
auto fsm = FirstStageMount::Create();
|
||||
if (!fsm.ok()) {
|
||||
LOG(ERROR) << "Failed to create FirstStageMount: " << fsm.error();
|
||||
return false;
|
||||
}
|
||||
return (*fsm)->DoCreateDevices();
|
||||
}
|
||||
|
||||
// Mounts partitions specified by fstab in device tree.
|
||||
bool DoFirstStageMount(bool create_devices) {
|
||||
// Skips first stage mount if we're in recovery mode.
|
||||
if (IsRecoveryMode()) {
|
||||
LOG(INFO) << "First stage mount skipped (recovery mode)";
|
||||
return true;
|
||||
}
|
||||
|
||||
auto fsm = FirstStageMount::Create();
|
||||
if (!fsm.ok()) {
|
||||
LOG(ERROR) << "Failed to create FirstStageMount " << fsm.error();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (create_devices) {
|
||||
if (!(*fsm)->DoCreateDevices()) return false;
|
||||
}
|
||||
|
||||
return (*fsm)->DoFirstStageMount();
|
||||
}
|
||||
|
||||
void SetInitAvbVersionInRecovery() {
|
||||
if (!IsRecoveryMode()) {
|
||||
LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)";
|
||||
return;
|
||||
}
|
||||
|
||||
auto fstab = ReadFirstStageFstab();
|
||||
auto fstab = ReadFirstStageFstabAndroid();
|
||||
if (!fstab.ok()) {
|
||||
LOG(ERROR) << fstab.error();
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -16,11 +16,28 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "result.h"
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
bool DoCreateDevices();
|
||||
bool DoFirstStageMount(bool create_devices);
|
||||
class FirstStageMount {
|
||||
public:
|
||||
virtual ~FirstStageMount() = default;
|
||||
|
||||
// The factory method to create a FirstStageMount instance.
|
||||
static Result<std::unique_ptr<FirstStageMount>> Create(const std::string& cmdline);
|
||||
// Creates devices and logical partitions from storage devices
|
||||
virtual bool DoCreateDevices() = 0;
|
||||
// Mounts fstab entries read from device tree.
|
||||
virtual bool DoFirstStageMount() = 0;
|
||||
|
||||
protected:
|
||||
FirstStageMount() = default;
|
||||
};
|
||||
|
||||
void SetInitAvbVersionInRecovery();
|
||||
|
||||
} // namespace init
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue