diff options
Diffstat (limited to 'init/first_stage_mount.cpp')
-rw-r--r-- | init/first_stage_mount.cpp | 82 |
1 files changed, 58 insertions, 24 deletions
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp index 4b0f05d4a..d458924a7 100644 --- a/init/first_stage_mount.cpp +++ b/init/first_stage_mount.cpp @@ -78,6 +78,7 @@ class FirstStageMount { ListenerAction HandleBlockDevice(const std::string& name, const Uevent&); bool InitRequiredDevices(); bool InitMappedDevice(const std::string& verity_device); + bool InitDeviceMapper(); bool CreateLogicalPartitions(); bool MountPartition(const Fstab::iterator& begin, bool erase_used_fstab_entry, Fstab::iterator* end = nullptr); @@ -97,6 +98,7 @@ class FirstStageMount { virtual bool SetUpDmVerity(FstabEntry* fstab_entry) = 0; bool need_dm_verity_; + bool gsi_not_on_userdata_ = false; Fstab fstab_; std::string lp_metadata_partition_; @@ -267,8 +269,6 @@ 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; } @@ -281,25 +281,7 @@ bool FirstStageMount::InitRequiredDevices() { } if (IsDmLinearEnabled() || need_dm_verity_) { - 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"; + if (!InitDeviceMapper()) { return false; } } @@ -327,11 +309,36 @@ bool FirstStageMount::InitRequiredDevices() { 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) { auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata); for (const auto& partition_name : partition_names) { - const auto super_device = android::fs_mgr::GetMetadataSuperBlockDevice(metadata); - if (partition_name == android::fs_mgr::GetBlockDevicePartitionName(*super_device)) { + // The super partition was found in the earlier pass. + if (partition_name == super_partition_name_) { continue; } required_devices_partition_names_.emplace(partition_name); @@ -499,6 +506,10 @@ bool FirstStageMount::TrySwitchSystemAsRoot() { if (system_partition == fstab_.end()) return true; 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"); } else { PLOG(ERROR) << "Failed to mount /system"; @@ -612,7 +623,29 @@ void FirstStageMount::UseGsiIfPresent() { 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"; return; } @@ -630,6 +663,7 @@ void FirstStageMount::UseGsiIfPresent() { fstab_.erase(system_partition); } fstab_.emplace_back(BuildGsiSystemFstabEntry()); + gsi_not_on_userdata_ = (super_name != "userdata"); } bool FirstStageMountVBootV1::GetDmVerityDevices() { |