Merge "init: Support booting off GSIs installed to non-userdata block devices."
This commit is contained in:
commit
5aa37dc3dc
4 changed files with 93 additions and 33 deletions
|
|
@ -1602,6 +1602,14 @@ bool fs_mgr_load_verity_state(int* mode) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string fs_mgr_get_verity_device_name(const FstabEntry& entry) {
|
||||||
|
if (entry.mount_point == "/") {
|
||||||
|
// In AVB, the dm device name is vroot instead of system.
|
||||||
|
return entry.fs_mgr_flags.avb ? "vroot" : "system";
|
||||||
|
}
|
||||||
|
return Basename(entry.mount_point);
|
||||||
|
}
|
||||||
|
|
||||||
bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
|
bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
|
||||||
if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
|
if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -1609,14 +1617,7 @@ bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
|
||||||
|
|
||||||
DeviceMapper& dm = DeviceMapper::Instance();
|
DeviceMapper& dm = DeviceMapper::Instance();
|
||||||
|
|
||||||
std::string mount_point;
|
std::string mount_point = fs_mgr_get_verity_device_name(entry);
|
||||||
if (entry.mount_point == "/") {
|
|
||||||
// In AVB, the dm device name is vroot instead of system.
|
|
||||||
mount_point = entry.fs_mgr_flags.avb ? "vroot" : "system";
|
|
||||||
} else {
|
|
||||||
mount_point = Basename(entry.mount_point);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
|
if (dm.GetState(mount_point) == DmDeviceState::INVALID) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -1639,6 +1640,27 @@ bool fs_mgr_is_verity_enabled(const FstabEntry& entry) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry) {
|
||||||
|
if (!entry.fs_mgr_flags.verify && !entry.fs_mgr_flags.avb) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceMapper& dm = DeviceMapper::Instance();
|
||||||
|
std::string device = fs_mgr_get_verity_device_name(entry);
|
||||||
|
|
||||||
|
std::vector<DeviceMapper::TargetInfo> table;
|
||||||
|
if (dm.GetState(device) == DmDeviceState::INVALID || !dm.GetTableInfo(device, &table)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const auto& target : table) {
|
||||||
|
if (strcmp(target.spec.target_type, "verity") == 0 &&
|
||||||
|
target.data.find("check_at_most_once") != std::string::npos) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::string fs_mgr_get_super_partition_name(int slot) {
|
std::string fs_mgr_get_super_partition_name(int slot) {
|
||||||
// Devices upgrading to dynamic partitions are allowed to specify a super
|
// Devices upgrading to dynamic partitions are allowed to specify a super
|
||||||
// partition name, assumed to be A/B (non-A/B retrofit is not supported).
|
// partition name, assumed to be A/B (non-A/B retrofit is not supported).
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,10 @@ bool fs_mgr_is_verity_enabled(const android::fs_mgr::FstabEntry& entry);
|
||||||
bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab);
|
bool fs_mgr_swapon_all(const android::fs_mgr::Fstab& fstab);
|
||||||
bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry);
|
bool fs_mgr_update_logical_partition(android::fs_mgr::FstabEntry* entry);
|
||||||
|
|
||||||
|
// Returns true if the given fstab entry has verity enabled, *and* the verity
|
||||||
|
// device is in "check_at_most_once" mode.
|
||||||
|
bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry);
|
||||||
|
|
||||||
int fs_mgr_do_format(const android::fs_mgr::FstabEntry& entry, bool reserve_footer);
|
int fs_mgr_do_format(const android::fs_mgr::FstabEntry& entry, bool reserve_footer);
|
||||||
|
|
||||||
#define FS_MGR_SETUP_VERITY_SKIPPED (-3)
|
#define FS_MGR_SETUP_VERITY_SKIPPED (-3)
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@ static int TableCmdHandler(int argc, char** argv) {
|
||||||
|
|
||||||
DeviceMapper& dm = DeviceMapper::Instance();
|
DeviceMapper& dm = DeviceMapper::Instance();
|
||||||
std::vector<DeviceMapper::TargetInfo> table;
|
std::vector<DeviceMapper::TargetInfo> table;
|
||||||
if (!dm.GetTableStatus(argv[0], &table)) {
|
if (!dm.GetTableInfo(argv[0], &table)) {
|
||||||
std::cerr << "Could not query table status of device \"" << argv[0] << "\"." << std::endl;
|
std::cerr << "Could not query table status of device \"" << argv[0] << "\"." << std::endl;
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,7 @@ class FirstStageMount {
|
||||||
ListenerAction HandleBlockDevice(const std::string& name, const Uevent&);
|
ListenerAction HandleBlockDevice(const std::string& name, const Uevent&);
|
||||||
bool InitRequiredDevices();
|
bool InitRequiredDevices();
|
||||||
bool InitMappedDevice(const std::string& verity_device);
|
bool InitMappedDevice(const std::string& verity_device);
|
||||||
|
bool InitDeviceMapper();
|
||||||
bool CreateLogicalPartitions();
|
bool CreateLogicalPartitions();
|
||||||
bool MountPartition(const Fstab::iterator& begin, bool erase_used_fstab_entry,
|
bool MountPartition(const Fstab::iterator& begin, bool erase_used_fstab_entry,
|
||||||
Fstab::iterator* end = nullptr);
|
Fstab::iterator* end = nullptr);
|
||||||
|
|
@ -97,6 +98,7 @@ class FirstStageMount {
|
||||||
virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
|
virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0;
|
||||||
|
|
||||||
bool need_dm_verity_;
|
bool need_dm_verity_;
|
||||||
|
bool gsi_not_on_userdata_ = false;
|
||||||
|
|
||||||
Fstab fstab_;
|
Fstab fstab_;
|
||||||
std::string lp_metadata_partition_;
|
std::string lp_metadata_partition_;
|
||||||
|
|
@ -267,8 +269,6 @@ bool FirstStageMount::GetDmLinearMetadataDevice() {
|
||||||
}
|
}
|
||||||
|
|
||||||
required_devices_partition_names_.emplace(super_partition_name_);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -281,25 +281,7 @@ bool FirstStageMount::InitRequiredDevices() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsDmLinearEnabled() || need_dm_verity_) {
|
if (IsDmLinearEnabled() || need_dm_verity_) {
|
||||||
const std::string dm_path = "/devices/virtual/misc/device-mapper";
|
if (!InitDeviceMapper()) {
|
||||||
bool found = false;
|
|
||||||
auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
|
|
||||||
if (uevent.path == dm_path) {
|
|
||||||
device_handler_->HandleUevent(uevent);
|
|
||||||
found = true;
|
|
||||||
return ListenerAction::kStop;
|
|
||||||
}
|
|
||||||
return ListenerAction::kContinue;
|
|
||||||
};
|
|
||||||
uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
|
|
||||||
if (!found) {
|
|
||||||
LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
|
|
||||||
Timer t;
|
|
||||||
uevent_listener_.Poll(dm_callback, 10s);
|
|
||||||
LOG(INFO) << "Wait for device-mapper returned after " << t;
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
LOG(ERROR) << "device-mapper device not found after polling timeout";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -327,11 +309,36 @@ bool FirstStageMount::InitRequiredDevices() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FirstStageMount::InitDeviceMapper() {
|
||||||
|
const std::string dm_path = "/devices/virtual/misc/device-mapper";
|
||||||
|
bool found = false;
|
||||||
|
auto dm_callback = [this, &dm_path, &found](const Uevent& uevent) {
|
||||||
|
if (uevent.path == dm_path) {
|
||||||
|
device_handler_->HandleUevent(uevent);
|
||||||
|
found = true;
|
||||||
|
return ListenerAction::kStop;
|
||||||
|
}
|
||||||
|
return ListenerAction::kContinue;
|
||||||
|
};
|
||||||
|
uevent_listener_.RegenerateUeventsForPath("/sys" + dm_path, dm_callback);
|
||||||
|
if (!found) {
|
||||||
|
LOG(INFO) << "device-mapper device not found in /sys, waiting for its uevent";
|
||||||
|
Timer t;
|
||||||
|
uevent_listener_.Poll(dm_callback, 10s);
|
||||||
|
LOG(INFO) << "Wait for device-mapper returned after " << t;
|
||||||
|
}
|
||||||
|
if (!found) {
|
||||||
|
LOG(ERROR) << "device-mapper device not found after polling timeout";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
|
bool FirstStageMount::InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata) {
|
||||||
auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
|
auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
|
||||||
for (const auto& partition_name : partition_names) {
|
for (const auto& partition_name : partition_names) {
|
||||||
const auto super_device = android::fs_mgr::GetMetadataSuperBlockDevice(metadata);
|
// The super partition was found in the earlier pass.
|
||||||
if (partition_name == android::fs_mgr::GetBlockDevicePartitionName(*super_device)) {
|
if (partition_name == super_partition_name_) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
required_devices_partition_names_.emplace(partition_name);
|
required_devices_partition_names_.emplace(partition_name);
|
||||||
|
|
@ -499,6 +506,10 @@ bool FirstStageMount::TrySwitchSystemAsRoot() {
|
||||||
if (system_partition == fstab_.end()) return true;
|
if (system_partition == fstab_.end()) return true;
|
||||||
|
|
||||||
if (MountPartition(system_partition, false)) {
|
if (MountPartition(system_partition, false)) {
|
||||||
|
if (gsi_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
|
||||||
|
LOG(ERROR) << "check_most_at_once forbidden on external media";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
SwitchRoot("/system");
|
SwitchRoot("/system");
|
||||||
} else {
|
} else {
|
||||||
PLOG(ERROR) << "Failed to mount /system";
|
PLOG(ERROR) << "Failed to mount /system";
|
||||||
|
|
@ -612,7 +623,29 @@ void FirstStageMount::UseGsiIfPresent() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), "/dev/block/by-name/userdata")) {
|
if (!InitDmLinearBackingDevices(*metadata.get())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Device-mapper might not be ready if the device doesn't use DAP or verity
|
||||||
|
// (for example, hikey).
|
||||||
|
if (access("/dev/device-mapper", F_OK) && !InitDeviceMapper()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the name of the super partition for the GSI. It will either be
|
||||||
|
// "userdata", or a block device such as an sdcard. There are no by-name
|
||||||
|
// partitions other than userdata that we support installing GSIs to.
|
||||||
|
auto super = GetMetadataSuperBlockDevice(*metadata.get());
|
||||||
|
std::string super_name = android::fs_mgr::GetBlockDevicePartitionName(*super);
|
||||||
|
std::string super_path;
|
||||||
|
if (super_name == "userdata") {
|
||||||
|
super_path = "/dev/block/by-name/" + super_name;
|
||||||
|
} else {
|
||||||
|
super_path = "/dev/block/" + super_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path)) {
|
||||||
LOG(ERROR) << "GSI partition layout could not be instantiated";
|
LOG(ERROR) << "GSI partition layout could not be instantiated";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -630,6 +663,7 @@ void FirstStageMount::UseGsiIfPresent() {
|
||||||
fstab_.erase(system_partition);
|
fstab_.erase(system_partition);
|
||||||
}
|
}
|
||||||
fstab_.emplace_back(BuildGsiSystemFstabEntry());
|
fstab_.emplace_back(BuildGsiSystemFstabEntry());
|
||||||
|
gsi_not_on_userdata_ = (super_name != "userdata");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FirstStageMountVBootV1::GetDmVerityDevices() {
|
bool FirstStageMountVBootV1::GetDmVerityDevices() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue