init: Add support for GSI installations in first-stage mount.
Bug: 121209697 Test: gsi boots Change-Id: I69db0f8e999da366e46728b1008602f543cd79f6
This commit is contained in:
parent
a0ca0191d6
commit
0e330f12bc
8 changed files with 117 additions and 4 deletions
|
@ -59,6 +59,7 @@ cc_library {
|
|||
"libfs_avb",
|
||||
"libfstab",
|
||||
"libdm",
|
||||
"libgsi",
|
||||
],
|
||||
export_static_lib_headers: [
|
||||
"libfs_avb",
|
||||
|
@ -105,5 +106,8 @@ cc_library_static {
|
|||
},
|
||||
},
|
||||
export_include_dirs: ["include_fstab"],
|
||||
header_libs: ["libbase_headers"],
|
||||
header_libs: [
|
||||
"libbase_headers",
|
||||
"libgsi_headers",
|
||||
],
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <android-base/file.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/strings.h>
|
||||
#include <libgsi/libgsi.h>
|
||||
|
||||
#include "fs_mgr_priv.h"
|
||||
|
||||
|
@ -638,6 +639,35 @@ static std::set<std::string> extract_boot_devices(const Fstab& fstab) {
|
|||
return boot_devices;
|
||||
}
|
||||
|
||||
static void EraseFstabEntry(Fstab* fstab, const std::string& mount_point) {
|
||||
auto iter = std::remove_if(fstab->begin(), fstab->end(),
|
||||
[&](const auto& entry) { return entry.mount_point == mount_point; });
|
||||
fstab->erase(iter, fstab->end());
|
||||
}
|
||||
|
||||
static void TransformFstabForGsi(Fstab* fstab) {
|
||||
EraseFstabEntry(fstab, "/system");
|
||||
EraseFstabEntry(fstab, "/data");
|
||||
|
||||
fstab->emplace_back(BuildGsiSystemFstabEntry());
|
||||
|
||||
constexpr uint32_t kFlags = MS_NOATIME | MS_NOSUID | MS_NODEV;
|
||||
|
||||
FstabEntry userdata = {
|
||||
.blk_device = "userdata_gsi",
|
||||
.mount_point = "/data",
|
||||
.fs_type = "ext4",
|
||||
.flags = kFlags,
|
||||
.reserved_size = 128 * 1024 * 1024,
|
||||
};
|
||||
userdata.fs_mgr_flags.wait = true;
|
||||
userdata.fs_mgr_flags.check = true;
|
||||
userdata.fs_mgr_flags.logical = true;
|
||||
userdata.fs_mgr_flags.quota = true;
|
||||
userdata.fs_mgr_flags.late_mount = true;
|
||||
fstab->emplace_back(userdata);
|
||||
}
|
||||
|
||||
bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
|
||||
auto fstab_file = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
|
||||
if (!fstab_file) {
|
||||
|
@ -645,10 +675,15 @@ bool ReadFstabFromFile(const std::string& path, Fstab* fstab) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!fs_mgr_read_fstab_file(fstab_file.get(), path == "/proc/mounts", fstab)) {
|
||||
bool is_proc_mounts = path == "/proc/mounts";
|
||||
|
||||
if (!fs_mgr_read_fstab_file(fstab_file.get(), is_proc_mounts, fstab)) {
|
||||
LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << path << "'";
|
||||
return false;
|
||||
}
|
||||
if (!is_proc_mounts && !access(android::gsi::kGsiBootedIndicatorFile, F_OK)) {
|
||||
TransformFstabForGsi(fstab);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1023,3 +1058,17 @@ int fs_mgr_is_checkpoint_fs(const struct fstab_rec* fstab) {
|
|||
int fs_mgr_is_checkpoint_blk(const struct fstab_rec* fstab) {
|
||||
return fstab->fs_mgr_flags & MF_CHECKPOINT_BLK;
|
||||
}
|
||||
|
||||
FstabEntry BuildGsiSystemFstabEntry() {
|
||||
FstabEntry system = {
|
||||
.blk_device = "system_gsi",
|
||||
.mount_point = "/system",
|
||||
.fs_type = "ext4",
|
||||
.flags = MS_RDONLY,
|
||||
.fs_options = "barrier=1",
|
||||
};
|
||||
system.fs_mgr_flags.wait = true;
|
||||
system.fs_mgr_flags.logical = true;
|
||||
system.fs_mgr_flags.first_stage_mount = true;
|
||||
return system;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <fs_mgr_overlayfs.h>
|
||||
#include <fstab/fstab.h>
|
||||
#include <libdm/dm.h>
|
||||
#include <libgsi/libgsi.h>
|
||||
#include <liblp/builder.h>
|
||||
#include <liblp/liblp.h>
|
||||
|
||||
|
@ -802,8 +803,9 @@ bool fs_mgr_overlayfs_scratch_can_be_mounted(const std::string& scratch_device)
|
|||
bool fs_mgr_overlayfs_invalid() {
|
||||
if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) return true;
|
||||
|
||||
// in recovery or fastbootd mode, not allowed!
|
||||
// in recovery, fastbootd, or gsi mode, not allowed!
|
||||
if (fs_mgr_access("/system/bin/recovery")) return true;
|
||||
if (android::gsi::IsGsiRunning()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -187,3 +187,6 @@ bool ReadDefaultFstab(Fstab* fstab);
|
|||
FstabEntry FstabRecToFstabEntry(const fstab_rec* fstab_rec);
|
||||
Fstab LegacyFstabToFstab(const struct fstab* legacy_fstab);
|
||||
fstab* FstabToLegacyFstab(const Fstab& fstab);
|
||||
|
||||
// Helper method to build a GSI fstab entry for mounting /system.
|
||||
FstabEntry BuildGsiSystemFstabEntry();
|
||||
|
|
|
@ -77,6 +77,7 @@ cc_defaults {
|
|||
"libext4_utils",
|
||||
"libfs_mgr",
|
||||
"libfscrypt",
|
||||
"libgsi",
|
||||
"libhidl-gen-utils",
|
||||
"libkeyutils",
|
||||
"liblog",
|
||||
|
|
|
@ -91,6 +91,7 @@ LOCAL_STATIC_LIBRARIES := \
|
|||
libz \
|
||||
libselinux \
|
||||
libcap \
|
||||
libgsi \
|
||||
|
||||
LOCAL_SANITIZE := signed-integer-overflow
|
||||
# First stage init is weird: it may start without stdout/stderr, and no /proc.
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#include <fs_mgr.h>
|
||||
#include <fscrypt/fscrypt.h>
|
||||
#include <fscrypt/fscrypt_init_extensions.h>
|
||||
#include <libgsi/libgsi.h>
|
||||
#include <selinux/android.h>
|
||||
#include <selinux/label.h>
|
||||
#include <selinux/selinux.h>
|
||||
|
@ -520,6 +521,9 @@ static Result<Success> queue_fs_event(int code) {
|
|||
return Success();
|
||||
} else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
|
||||
/* Setup a wipe via recovery, and reboot into recovery */
|
||||
if (android::gsi::IsGsiRunning()) {
|
||||
return Error() << "cannot wipe within GSI";
|
||||
}
|
||||
PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery.";
|
||||
const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" };
|
||||
return reboot_into_recovery(options);
|
||||
|
@ -1022,7 +1026,8 @@ static Result<Success> ExecWithRebootOnFailure(const std::string& reboot_reason,
|
|||
}
|
||||
service->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
|
||||
if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
|
||||
if (fscrypt_is_native()) {
|
||||
// TODO (b/122850122): support this in gsi
|
||||
if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
|
||||
LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
|
||||
if (auto result = reboot_into_recovery(
|
||||
{"--prompt_and_wipe_data", "--reason="s + reboot_reason});
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <fs_mgr.h>
|
||||
#include <fs_mgr_dm_linear.h>
|
||||
#include <fs_mgr_overlayfs.h>
|
||||
#include <libgsi/libgsi.h>
|
||||
#include <liblp/liblp.h>
|
||||
|
||||
#include "devices.h"
|
||||
|
@ -79,6 +80,7 @@ class FirstStageMount {
|
|||
bool IsDmLinearEnabled();
|
||||
bool GetDmLinearMetadataDevice();
|
||||
bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata);
|
||||
void UseGsiIfPresent();
|
||||
|
||||
ListenerAction UeventCallback(const Uevent& uevent);
|
||||
|
||||
|
@ -207,6 +209,8 @@ bool FirstStageMount::GetDmLinearMetadataDevice() {
|
|||
}
|
||||
|
||||
required_devices_partition_names_.emplace(super_partition_name_);
|
||||
// When booting from live GSI images, userdata is the super device.
|
||||
required_devices_partition_names_.emplace("userdata");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -410,6 +414,16 @@ bool FirstStageMount::MountPartition(FstabEntry* fstab_entry) {
|
|||
// 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() {
|
||||
auto metadata_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
|
||||
return entry.mount_point == "/metadata";
|
||||
});
|
||||
if (metadata_partition != fstab_.end()) {
|
||||
if (MountPartition(&(*metadata_partition))) {
|
||||
fstab_.erase(metadata_partition);
|
||||
UseGsiIfPresent();
|
||||
}
|
||||
}
|
||||
|
||||
auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
|
||||
return entry.mount_point == "/system";
|
||||
});
|
||||
|
@ -513,6 +527,40 @@ bool FirstStageMount::MountPartitions() {
|
|||
return true;
|
||||
}
|
||||
|
||||
void FirstStageMount::UseGsiIfPresent() {
|
||||
std::string metadata_file, error;
|
||||
|
||||
if (!android::gsi::CanBootIntoGsi(&metadata_file, &error)) {
|
||||
LOG(INFO) << "GSI " << error << ", proceeding with normal boot";
|
||||
return;
|
||||
}
|
||||
|
||||
auto metadata = android::fs_mgr::ReadFromImageFile(metadata_file.c_str());
|
||||
if (!metadata) {
|
||||
LOG(ERROR) << "GSI partition layout could not be read";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), "/dev/block/by-name/userdata")) {
|
||||
LOG(ERROR) << "GSI partition layout could not be instantiated";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!android::gsi::MarkSystemAsGsi()) {
|
||||
PLOG(ERROR) << "GSI indicator file could not be written";
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace the existing system fstab entry.
|
||||
auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
|
||||
return entry.mount_point == "/system";
|
||||
});
|
||||
if (system_partition != fstab_.end()) {
|
||||
fstab_.erase(system_partition);
|
||||
}
|
||||
fstab_.emplace_back(BuildGsiSystemFstabEntry());
|
||||
}
|
||||
|
||||
bool FirstStageMountVBootV1::GetDmVerityDevices() {
|
||||
std::string verity_loc_device;
|
||||
need_dm_verity_ = false;
|
||||
|
|
Loading…
Reference in a new issue