Merge "Revert^2 "Deprecating libvendorsupport_llndk_headers"" into main
diff --git a/fs_mgr/libfstab/fstab.cpp b/fs_mgr/libfstab/fstab.cpp
index 6e4cae1..ca35990 100644
--- a/fs_mgr/libfstab/fstab.cpp
+++ b/fs_mgr/libfstab/fstab.cpp
@@ -262,7 +262,7 @@
if (!arg.empty() && arg.back() == '%') {
arg.pop_back();
int val;
- if (ParseInt(arg, &val, 0, 100)) {
+ if (ParseInt(arg, &val, 0, 200)) {
entry->zram_size = CalculateZramSize(val);
} else {
LWARNING << "Warning: zramsize= flag malformed: " << arg;
@@ -950,6 +950,22 @@
return ExtraBootDevices(fstab);
}
+std::string GetBootPartUuid() {
+ std::string boot_part_uuid;
+
+ if (GetBootconfig("androidboot.boot_part_uuid", &boot_part_uuid)) {
+ return boot_part_uuid;
+ }
+
+ ImportKernelCmdline([&](std::string key, std::string value) {
+ if (key == "androidboot.boot_part_uuid") {
+ boot_part_uuid = value;
+ }
+ });
+
+ return boot_part_uuid;
+}
+
std::string GetVerityDeviceName(const FstabEntry& entry) {
std::string base_device;
if (entry.mount_point == "/") {
diff --git a/fs_mgr/libfstab/include/fstab/fstab.h b/fs_mgr/libfstab/include/fstab/fstab.h
index 070dd91..0ff3188 100644
--- a/fs_mgr/libfstab/include/fstab/fstab.h
+++ b/fs_mgr/libfstab/include/fstab/fstab.h
@@ -126,6 +126,16 @@
std::set<std::string> GetBootDevices();
+// Get the Partition UUID the kernel loaded from if the bootloader passed it.
+//
+// If the kernel's Partition UUID is provided then we can use this to help
+// identify which block device contains the filesystems we care about.
+//
+// NOTE: Nothing secures a UUID other than the convention that two disks
+// aren't supposed to both have the same UUID. We still need other mechanisms
+// to ensure we've got the right disk.
+std::string GetBootPartUuid();
+
// Return the name of the dm-verity device for the given fstab entry. This does
// not check whether the device is valid or exists; it merely returns the
// expected name.
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 06c27e7..97cfe76 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -169,7 +169,7 @@
recovery_available: true,
}
-// This target will install to /system/bin/snapuserd_ramdisk
+// This target will install to /system/bin/snapuserd_ramdisk
// It will also create a symblink on /system/bin/snapuserd that point to
// /system/bin/snapuserd_ramdisk .
// This way, init can check if generic ramdisk copy exists.
@@ -265,6 +265,10 @@
name: "force-no-test-error",
value: "false",
},
+ {
+ name: "native-test-timeout",
+ value: "15m",
+ },
],
},
}
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
index e2c5874..486548c 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
@@ -55,7 +55,7 @@
break;
}
- *source_offset = cow_op->new_block * BLOCK_SZ;
+ *source_offset = static_cast<uint64_t>(cow_op->new_block) * BLOCK_SZ;
if (!checkOrderedOp) {
replace_zero_vec->push_back(cow_op);
if (cow_op->type() == kCowReplaceOp) {
@@ -74,7 +74,7 @@
break;
}
- uint64_t next_offset = op->new_block * BLOCK_SZ;
+ uint64_t next_offset = static_cast<uint64_t>(op->new_block) * BLOCK_SZ;
if (next_offset != (*source_offset + nr_consecutive * BLOCK_SZ)) {
break;
}
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 6522c02..6e050cf 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -710,6 +710,7 @@
source none3 swap defaults zramsize=5%
source none4 swap defaults zramsize=105%
source none5 swap defaults zramsize=%
+source none6 swap defaults zramsize=210%
)fs";
ASSERT_TRUE(android::base::WriteStringToFile(fstab_contents, tf.path));
@@ -742,12 +743,17 @@
EXPECT_EQ("none4", entry->mount_point);
EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
- EXPECT_EQ(0, entry->zram_size);
+ EXPECT_NE(0, entry->zram_size);
entry++;
EXPECT_EQ("none5", entry->mount_point);
EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
EXPECT_EQ(0, entry->zram_size);
+ entry++;
+
+ EXPECT_EQ("none6", entry->mount_point);
+ EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
+ EXPECT_EQ(0, entry->zram_size);
}
TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_FileEncryption) {
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
index 7d00195..aac4acb 100644
--- a/init/README.ueventd.md
+++ b/init/README.ueventd.md
@@ -39,6 +39,33 @@
`device_id` is `uevent MINOR % 128 + 1`.
3. All other devices are created as `/dev/<basename uevent DEVPATH>`
+Whether a device is considered a "boot device" is a bit complicated.
+
+ - The recommended way to specify the boot device is to provide the "partition UUID" containing the
+ kernel (or, really, any parition on the boot device) and then boot device is the block device
+ containing that partition. This is passed via `androidboot.boot_part_uuid` which can be provided
+ either via the kernel bootconfig or via the kernel commandline. As an example, you could set
+ `androidboot.boot_part_uuid=12345678-abcd-ef01-0234-6789abcdef01`.
+ - Though using `boot_part_uuid` is preferred, you can also specify the boot device via
+ `androidboot.boot_device` or `androidboot.boot_devices`. These can be passed via the kernel
+ bootconfig or the kernel command line. It is also possible to pass this via device tree by
+ creating a `boot_devices` property in the Android firmware node. In most cases the `boot_device`
+ is the sysfs path (without the `/sys/devices` or `/sys/devices/platform` prefix) to the closest
+ parent of the block device that's on the "platform" bus. As an example, if the block device is
+ `/sys/devices/platform/soc@0/7c4000.mmc/mmc_host/mmc1/mmc1:0001/block/mmcblk1` then the
+ `boot_device` is `soc@0/7c4000.mmc` since we strip off the `/sys/devices/platform` and nothing
+ past the `7c4000.mmc` directory represents a device on the "platform" bus. In the case that none
+ of the parents are on the "platform" bus there are special rules for block devices under PCI
+ and VBD (Virtual Block Device). NOTE: sysfs paths for block devices are not guaranteed to be
+ stable between kernel versions, which is one of the reasons why it is suggested to use
+ `boot_part_uuid` instead of `boot_devices`. ALSO NOTE: If more than one device matches (either
+ because multiple `boot_devices` were listed or because there was more than one block device
+ under the found sysfs directory) and these multiple matching devices provide some of the same
+ named partitions then the behavior is unspecified.
+ - There is a further fallback to determine "boot devices" via the vstab, but providing at least
+ `boot_devices` has been required since Android 12 so this further fallback will not be described
+ here.
+
The permissions can be modified using a ueventd.rc script and a line that beings with `/dev`. These
lines take the format of
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
index 8f52158..7f83037 100644
--- a/init/block_dev_initializer.cpp
+++ b/init/block_dev_initializer.cpp
@@ -33,7 +33,49 @@
auto boot_devices = android::fs_mgr::GetBootDevices();
device_handler_ = std::make_unique<DeviceHandler>(
std::vector<Permissions>{}, std::vector<SysfsPermissions>{}, std::vector<Subsystem>{},
- std::move(boot_devices), false);
+ std::move(boot_devices), android::fs_mgr::GetBootPartUuid(), false);
+}
+
+// If boot_part_uuid is specified, use it to set boot_devices
+//
+// When `androidboot.boot_part_uuid` is specified then that's the partition UUID
+// of the kernel. Look for that partition and then set `boot_devices` to be
+// exactly one item: the block device containing that partition.
+//
+// NOTE that `boot_part_uuid` is only specified on newer devices. Older devices
+// specified `boot_devices` directly.
+bool BlockDevInitializer::InitBootDevicesFromPartUuid() {
+ bool uuid_check_done = false;
+
+ auto boot_part_callback = [&, this](const Uevent& uevent) -> ListenerAction {
+ uuid_check_done = device_handler_->CheckUeventForBootPartUuid(uevent);
+ return uuid_check_done ? ListenerAction::kStop : ListenerAction::kContinue;
+ };
+
+ // Re-run already arrived uevents looking for the boot partition UUID.
+ //
+ // NOTE: If we're not using the boot partition UUID to find the boot
+ // device then the first uevent we analyze will cause us to stop looking
+ // and set `uuid_check_done`. This will shortcut all of the UUID logic.
+ // Replaying one uevent is not expected to be slow.
+ uevent_listener_.RegenerateUevents(boot_part_callback);
+
+ // If we're not done looking, poll for uevents for longer
+ if (!uuid_check_done) {
+ Timer t;
+ uevent_listener_.Poll(boot_part_callback, 10s);
+ LOG(INFO) << "Wait for boot partition returned after " << t;
+ }
+
+ // Give a nicer error message if we were expecting to find the kernel boot
+ // partition but didn't. Later code would fail too but the message there
+ // is a bit further from the root cause of the problem.
+ if (!uuid_check_done) {
+ LOG(ERROR) << __PRETTY_FUNCTION__ << ": boot partition not found after polling timeout.";
+ return false;
+ }
+
+ return true;
}
bool BlockDevInitializer::InitDeviceMapper() {
@@ -98,11 +140,43 @@
LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << name;
- devices->erase(iter);
+ // Remove the partition from the list of partitions we're waiting for.
+ //
+ // Partitions that we're waiting for here are expected to be on the boot
+ // device, so only remove from the list if they're on the boot device.
+ // This prevents us from being confused if there are multiple disks (some
+ // perhaps connected via USB) that have matching partition names.
+ //
+ // ...but...
+ //
+ // Some products (especialy emulators) don't seem to set up boot_devices
+ // or possibly not all the partitions that we need to wait for are on the
+ // specified boot device. Thus, only require partitions to be on the boot
+ // device in "strict" mode, which should be used on newer systems.
+ if (device_handler_->IsBootDevice(uevent) || !device_handler_->IsBootDeviceStrict()) {
+ devices->erase(iter);
+ }
+
device_handler_->HandleUevent(uevent);
return devices->empty() ? ListenerAction::kStop : ListenerAction::kContinue;
}
+// Wait for partitions that are expected to be on the "boot device" to initialize.
+//
+// Wait (for up to 10 seconds) for partitions passed in `devices` to show up.
+// All block devices found while waiting will be initialized, which includes
+// creating symlinks for them in /dev/block. Once all `devices` are found we'll
+// return success (true). If any devices aren't found we'll return failure
+// (false). As devices are found they will be removed from `devices`.
+//
+// The contents of `devices` is the names of the partitions. This can be:
+// - The `partition_name` reported by a uevent, or the final component in the
+// `path` reported by a uevent if the `partition_name` is blank.
+// - The result of DeviceHandler::GetPartitionNameForDevice() on the
+// `device_name` reported by a uevent.
+//
+// NOTE: on newer systems partitions _must_ be on the "boot device". See
+// comments inside HandleUevent().
bool BlockDevInitializer::InitDevices(std::set<std::string> devices) {
auto uevent_callback = [&, this](const Uevent& uevent) -> ListenerAction {
return HandleUevent(uevent, &devices);
diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h
index cb1d365..25107c9 100644
--- a/init/block_dev_initializer.h
+++ b/init/block_dev_initializer.h
@@ -29,6 +29,7 @@
public:
BlockDevInitializer();
+ bool InitBootDevicesFromPartUuid();
bool InitDeviceMapper();
bool InitDmUser(const std::string& name);
bool InitDevices(std::set<std::string> devices);
diff --git a/init/devices.cpp b/init/devices.cpp
index f2bb9d2..2cdecec 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -45,6 +45,7 @@
using namespace std::chrono_literals;
using android::base::Basename;
+using android::base::ConsumePrefix;
using android::base::Dirname;
using android::base::ReadFileToString;
using android::base::Readlink;
@@ -188,6 +189,52 @@
}
}
+BlockDeviceInfo DeviceHandler::GetBlockDeviceInfo(const std::string& uevent_path) const {
+ BlockDeviceInfo info;
+
+ if (!boot_part_uuid_.empty()) {
+ // Only use the more specific "MMC" or "SCSI" match if a partition UUID
+ // was passed. Old bootloaders that aren't passing the partition UUID
+ // instead pass the path to the closest "platform" device. It would
+ // break them if we chose this deeper (more specific) path.
+ //
+ // When we have a UUID we _want_ the more specific path since it can
+ // handle, for instance, differentiating two USB disks that are on
+ // the same USB controller. Using the closest platform device would
+ // classify them both the same by using the path to the USB controller.
+ if (FindMmcDevice(uevent_path, &info.str)) {
+ info.type = "mmc";
+ } else if (FindScsiDevice(uevent_path, &info.str)) {
+ info.type = "scsi";
+ }
+ } else if (FindPlatformDevice(uevent_path, &info.str)) {
+ info.type = "platform";
+ } else if (FindPciDevicePrefix(uevent_path, &info.str)) {
+ info.type = "pci";
+ } else if (FindVbdDevicePrefix(uevent_path, &info.str)) {
+ info.type = "vbd";
+ } else {
+ // Re-clear device to be extra certain in case one of the FindXXX()
+ // functions returned false but still modified it.
+ info.str = "";
+ }
+
+ info.is_boot_device = boot_devices_.find(info.str) != boot_devices_.end();
+
+ return info;
+}
+
+bool DeviceHandler::IsBootDeviceStrict() const {
+ // When using the newer "boot_part_uuid" to specify the boot device then
+ // we require all core system partitions to be on the boot device.
+ return !boot_part_uuid_.empty();
+}
+
+bool DeviceHandler::IsBootDevice(const Uevent& uevent) const {
+ auto device = GetBlockDeviceInfo(uevent.path);
+ return device.is_boot_device;
+}
+
std::string DeviceHandler::GetPartitionNameForDevice(const std::string& query_device) {
static const auto partition_map = [] {
std::vector<std::pair<std::string, std::string>> partition_map;
@@ -218,11 +265,12 @@
return {};
}
-// Given a path that may start with a platform device, find the parent platform device by finding a
-// parent directory with a 'subsystem' symlink that points to the platform bus.
-// If it doesn't start with a platform device, return false
-bool DeviceHandler::FindPlatformDevice(std::string path, std::string* platform_device_path) const {
- platform_device_path->clear();
+// Given a path to a device that may have a parent in the passed set of
+// subsystems, find the parent device that's in the passed set of subsystems.
+// If we don't find a parent in the passed set of subsystems, return false.
+bool DeviceHandler::FindSubsystemDevice(std::string path, std::string* device_path,
+ const std::set<std::string>& subsystem_paths) const {
+ device_path->clear();
// Uevents don't contain the mount point, so we need to add it here.
path.insert(0, sysfs_mount_point_);
@@ -232,11 +280,20 @@
while (directory != "/" && directory != ".") {
std::string subsystem_link_path;
if (Realpath(directory + "/subsystem", &subsystem_link_path) &&
- (subsystem_link_path == sysfs_mount_point_ + "/bus/platform" ||
- subsystem_link_path == sysfs_mount_point_ + "/bus/amba")) {
+ subsystem_paths.find(subsystem_link_path) != subsystem_paths.end()) {
// We need to remove the mount point that we added above before returning.
directory.erase(0, sysfs_mount_point_.size());
- *platform_device_path = directory;
+
+ // Skip /devices/platform or /devices/ if present
+ static constexpr std::string_view devices_platform_prefix = "/devices/platform/";
+ static constexpr std::string_view devices_prefix = "/devices/";
+ std::string_view sv = directory;
+
+ if (!ConsumePrefix(&sv, devices_platform_prefix)) {
+ ConsumePrefix(&sv, devices_prefix);
+ }
+ *device_path = sv;
+
return true;
}
@@ -250,6 +307,32 @@
return false;
}
+bool DeviceHandler::FindPlatformDevice(const std::string& path,
+ std::string* platform_device_path) const {
+ const std::set<std::string> subsystem_paths = {
+ sysfs_mount_point_ + "/bus/platform",
+ sysfs_mount_point_ + "/bus/amba",
+ };
+
+ return FindSubsystemDevice(path, platform_device_path, subsystem_paths);
+}
+
+bool DeviceHandler::FindMmcDevice(const std::string& path, std::string* mmc_device_path) const {
+ const std::set<std::string> subsystem_paths = {
+ sysfs_mount_point_ + "/bus/mmc",
+ };
+
+ return FindSubsystemDevice(path, mmc_device_path, subsystem_paths);
+}
+
+bool DeviceHandler::FindScsiDevice(const std::string& path, std::string* scsi_device_path) const {
+ const std::set<std::string> subsystem_paths = {
+ sysfs_mount_point_ + "/bus/scsi",
+ };
+
+ return FindSubsystemDevice(path, scsi_device_path, subsystem_paths);
+}
+
void DeviceHandler::FixupSysPermissions(const std::string& upath,
const std::string& subsystem) const {
// upaths omit the "/sys" that paths in this list
@@ -371,44 +454,30 @@
}
std::vector<std::string> DeviceHandler::GetBlockDeviceSymlinks(const Uevent& uevent) const {
- std::string device;
- std::string type;
+ BlockDeviceInfo info;
std::string partition;
std::string uuid;
- if (FindPlatformDevice(uevent.path, &device)) {
- // Skip /devices/platform or /devices/ if present
- static constexpr std::string_view devices_platform_prefix = "/devices/platform/";
- static constexpr std::string_view devices_prefix = "/devices/";
-
- if (StartsWith(device, devices_platform_prefix)) {
- device = device.substr(devices_platform_prefix.length());
- } else if (StartsWith(device, devices_prefix)) {
- device = device.substr(devices_prefix.length());
- }
-
- type = "platform";
- } else if (FindPciDevicePrefix(uevent.path, &device)) {
- type = "pci";
- } else if (FindVbdDevicePrefix(uevent.path, &device)) {
- type = "vbd";
- } else if (FindDmDevice(uevent, &partition, &uuid)) {
+ if (FindDmDevice(uevent, &partition, &uuid)) {
std::vector<std::string> symlinks = {"/dev/block/mapper/" + partition};
if (!uuid.empty()) {
symlinks.emplace_back("/dev/block/mapper/by-uuid/" + uuid);
}
return symlinks;
- } else {
+ }
+
+ info = GetBlockDeviceInfo(uevent.path);
+
+ if (info.type.empty()) {
return {};
}
std::vector<std::string> links;
- LOG(VERBOSE) << "found " << type << " device " << device;
+ LOG(VERBOSE) << "found " << info.type << " device " << info.str;
- auto link_path = "/dev/block/" + type + "/" + device;
+ auto link_path = "/dev/block/" + info.type + "/" + info.str;
- bool is_boot_device = boot_devices_.find(device) != boot_devices_.end();
if (!uevent.partition_name.empty()) {
std::string partition_name_sanitized(uevent.partition_name);
SanitizePartitionName(&partition_name_sanitized);
@@ -418,10 +487,10 @@
}
links.emplace_back(link_path + "/by-name/" + partition_name_sanitized);
// Adds symlink: /dev/block/by-name/<partition_name>.
- if (is_boot_device) {
+ if (info.is_boot_device) {
links.emplace_back("/dev/block/by-name/" + partition_name_sanitized);
}
- } else if (is_boot_device) {
+ } else if (info.is_boot_device) {
// If we don't have a partition name but we are a partition on a boot device, create a
// symlink of /dev/block/by-name/<device_name> for symmetry.
links.emplace_back("/dev/block/by-name/" + uevent.device_name);
@@ -541,6 +610,48 @@
}
}
+// Check Uevents looking for the kernel's boot partition UUID
+//
+// When we can stop checking uevents (either because we're done or because
+// we weren't looking for the kernel's boot partition UUID) then return
+// true. Return false if we're not done yet.
+bool DeviceHandler::CheckUeventForBootPartUuid(const Uevent& uevent) {
+ // If we aren't using boot_part_uuid then we're done.
+ if (boot_part_uuid_.empty()) {
+ return true;
+ }
+
+ // Finding the boot partition is a one-time thing that we do at init
+ // time, not steady state. This is because the boot partition isn't
+ // allowed to go away or change. Once we found the boot partition we don't
+ // expect to run again.
+ if (found_boot_part_uuid_) {
+ LOG(WARNING) << __PRETTY_FUNCTION__
+ << " shouldn't run after kernel boot partition is found";
+ return true;
+ }
+
+ // We only need to look at newly-added block devices. Note that if someone
+ // is replaying events all existing devices will get "add"ed.
+ if (uevent.subsystem != "block" || uevent.action != "add") {
+ return false;
+ }
+
+ // If it's not the partition we care about then move on.
+ if (uevent.partition_uuid != boot_part_uuid_) {
+ return false;
+ }
+
+ auto device = GetBlockDeviceInfo(uevent.path);
+
+ LOG(INFO) << "Boot device " << device.str << " found via partition UUID";
+ found_boot_part_uuid_ = true;
+ boot_devices_.clear();
+ boot_devices_.insert(device.str);
+
+ return true;
+}
+
void DeviceHandler::HandleUevent(const Uevent& uevent) {
if (uevent.action == "add" || uevent.action == "change" || uevent.action == "bind" ||
uevent.action == "online") {
@@ -603,17 +714,25 @@
DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
std::vector<SysfsPermissions> sysfs_permissions,
std::vector<Subsystem> subsystems, std::set<std::string> boot_devices,
- bool skip_restorecon)
+ std::string boot_part_uuid, bool skip_restorecon)
: dev_permissions_(std::move(dev_permissions)),
sysfs_permissions_(std::move(sysfs_permissions)),
subsystems_(std::move(subsystems)),
boot_devices_(std::move(boot_devices)),
+ boot_part_uuid_(boot_part_uuid),
skip_restorecon_(skip_restorecon),
- sysfs_mount_point_("/sys") {}
+ sysfs_mount_point_("/sys") {
+ // If both a boot partition UUID and a list of boot devices are
+ // specified then we ignore the boot_devices in favor of boot_part_uuid.
+ if (boot_devices_.size() && !boot_part_uuid.empty()) {
+ LOG(WARNING) << "Both boot_devices and boot_part_uuid provided; ignoring bootdevices";
+ boot_devices_.clear();
+ }
+}
DeviceHandler::DeviceHandler()
: DeviceHandler(std::vector<Permissions>{}, std::vector<SysfsPermissions>{},
- std::vector<Subsystem>{}, std::set<std::string>{}, false) {}
+ std::vector<Subsystem>{}, std::set<std::string>{}, "", false) {}
} // namespace init
} // namespace android
diff --git a/init/devices.h b/init/devices.h
index 6da1232..67a3d00 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -116,16 +116,24 @@
std::string dir_name_ = "/dev";
};
+struct BlockDeviceInfo {
+ std::string str;
+ std::string type;
+ bool is_boot_device;
+};
+
class DeviceHandler : public UeventHandler {
public:
friend class DeviceHandlerTester;
DeviceHandler();
DeviceHandler(std::vector<Permissions> dev_permissions,
- std::vector<SysfsPermissions> sysfs_permissions, std::vector<Subsystem> subsystems,
- std::set<std::string> boot_devices, bool skip_restorecon);
+ std::vector<SysfsPermissions> sysfs_permissions,
+ std::vector<Subsystem> subsystems, std::set<std::string> boot_devices,
+ std::string boot_part_uuid, bool skip_restorecon);
virtual ~DeviceHandler() = default;
+ bool CheckUeventForBootPartUuid(const Uevent& uevent);
void HandleUevent(const Uevent& uevent) override;
// `androidboot.partition_map` allows associating a partition name for a raw block device
@@ -133,10 +141,17 @@
// `androidboot.partition_map=vdb,metadata;vdc,userdata` maps `vdb` to `metadata` and `vdc` to
// `userdata`.
static std::string GetPartitionNameForDevice(const std::string& device);
+ bool IsBootDeviceStrict() const;
+ bool IsBootDevice(const Uevent& uevent) const;
private:
void ColdbootDone() override;
- bool FindPlatformDevice(std::string path, std::string* platform_device_path) const;
+ BlockDeviceInfo GetBlockDeviceInfo(const std::string& uevent_path) const;
+ bool FindSubsystemDevice(std::string path, std::string* device_path,
+ const std::set<std::string>& subsystem_paths) const;
+ bool FindPlatformDevice(const std::string& path, std::string* platform_device_path) const;
+ bool FindMmcDevice(const std::string& path, std::string* mmc_device_path) const;
+ bool FindScsiDevice(const std::string& path, std::string* scsi_device_path) const;
std::tuple<mode_t, uid_t, gid_t> GetDevicePermissions(
const std::string& path, const std::vector<std::string>& links) const;
void MakeDevice(const std::string& path, bool block, int major, int minor,
@@ -151,6 +166,8 @@
std::vector<SysfsPermissions> sysfs_permissions_;
std::vector<Subsystem> subsystems_;
std::set<std::string> boot_devices_;
+ std::string boot_part_uuid_;
+ bool found_boot_part_uuid_;
bool skip_restorecon_;
std::string sysfs_mount_point_;
};
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 4f1af30..aa6b551 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -288,6 +288,10 @@
}
bool FirstStageMountVBootV2::InitDevices() {
+ if (!block_dev_init_.InitBootDevicesFromPartUuid()) {
+ return false;
+ }
+
std::set<std::string> devices;
GetSuperDeviceName(&devices);
diff --git a/init/uevent.h b/init/uevent.h
index dc35fd9..c8ca52a 100644
--- a/init/uevent.h
+++ b/init/uevent.h
@@ -28,6 +28,7 @@
std::string subsystem;
std::string firmware;
std::string partition_name;
+ std::string partition_uuid;
std::string device_name;
std::string modalias;
int partition_num;
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp
index 5da6777..97f3de6 100644
--- a/init/uevent_listener.cpp
+++ b/init/uevent_listener.cpp
@@ -66,6 +66,9 @@
} else if (!strncmp(msg, "PARTNAME=", 9)) {
msg += 9;
uevent->partition_name = msg;
+ } else if (!strncmp(msg, "PARTUUID=", 9)) {
+ msg += 9;
+ uevent->partition_uuid = msg;
} else if (!strncmp(msg, "DEVNAME=", 8)) {
msg += 8;
uevent->device_name = msg;
@@ -82,7 +85,7 @@
if (LOG_UEVENTS) {
LOG(INFO) << "event { '" << uevent->action << "', '" << uevent->path << "', '"
<< uevent->subsystem << "', '" << uevent->firmware << "', " << uevent->major
- << ", " << uevent->minor << " }";
+ << ", " << uevent->minor << ", " << uevent->partition_uuid << " }";
}
}
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index 3f0d0e9..286e472 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -353,10 +353,25 @@
auto ueventd_configuration = GetConfiguration();
- uevent_handlers.emplace_back(std::make_unique<DeviceHandler>(
+ UeventListener uevent_listener(ueventd_configuration.uevent_socket_rcvbuf_size);
+
+ // Right after making DeviceHandler, replay all events looking for which
+ // block device has the boot partition. This lets us make symlinks
+ // for all of the other partitions on the same disk. Note that by the time
+ // we get here we know that the boot partition has already shown up (if
+ // we're looking for it) so just regenerating events is enough to know
+ // we'll see it.
+ std::unique_ptr<DeviceHandler> device_handler = std::make_unique<DeviceHandler>(
std::move(ueventd_configuration.dev_permissions),
std::move(ueventd_configuration.sysfs_permissions),
- std::move(ueventd_configuration.subsystems), android::fs_mgr::GetBootDevices(), true));
+ std::move(ueventd_configuration.subsystems), android::fs_mgr::GetBootDevices(),
+ android::fs_mgr::GetBootPartUuid(), true);
+ uevent_listener.RegenerateUevents([&](const Uevent& uevent) -> ListenerAction {
+ bool uuid_check_done = device_handler->CheckUeventForBootPartUuid(uevent);
+ return uuid_check_done ? ListenerAction::kStop : ListenerAction::kContinue;
+ });
+
+ uevent_handlers.emplace_back(std::move(device_handler));
uevent_handlers.emplace_back(std::make_unique<FirmwareHandler>(
std::move(ueventd_configuration.firmware_directories),
std::move(ueventd_configuration.external_firmware_handlers)));
@@ -365,8 +380,6 @@
std::vector<std::string> base_paths = {"/odm/lib/modules", "/vendor/lib/modules"};
uevent_handlers.emplace_back(std::make_unique<ModaliasHandler>(base_paths));
}
- UeventListener uevent_listener(ueventd_configuration.uevent_socket_rcvbuf_size);
-
if (!android::base::GetBoolProperty(kColdBootDoneProp, false)) {
ColdBoot cold_boot(uevent_listener, uevent_handlers,
ueventd_configuration.enable_parallel_restorecon,
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 5bb64cc..617e60a 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -614,6 +614,9 @@
mkdir /metadata/aconfig/boot 0775 root system
mkdir /metadata/aconfig_test_missions 0775 root system
+
+ # See flag enable_system_aconfigd_rust, which toggles these processes.
+ exec_start system_aconfigd_platform_init
exec_start aconfigd-platform-init
on late-fs
@@ -1002,7 +1005,16 @@
# Wait for apexd to finish activating APEXes before starting more processes.
wait_for_prop apexd.status activated
perform_apex_config
+
+ # See flag enable_system_aconfigd_rust, which toggles these processes.
exec_start aconfigd-mainline-init
+ exec_start system_aconfigd_mainline_init
+
+ # system_aconfigd_socket_service is replacing aconfigd:
+ # - A flag (enable_system_aconfigd_rust) toggles which socket executes.
+ # - When enabled, aconfigd is a no-op, system_aconfigd_socket_service executes.
+ # - Conversely, when disabled, aconfigd executes, and system_aconfigd_socket_service is a no-op.
+ start system_aconfigd_socket_service
start aconfigd
# Create directories for boot animation.