diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp index 9c2a7bb14..05e00edfd 100644 --- a/init/block_dev_initializer.cpp +++ b/init/block_dev_initializer.cpp @@ -87,7 +87,13 @@ ListenerAction BlockDevInitializer::HandleUevent(const Uevent& uevent, auto iter = devices->find(name); if (iter == devices->end()) { - return ListenerAction::kContinue; + auto partition_name = DeviceHandler::GetPartitionNameForDevice(uevent.device_name); + if (!partition_name.empty()) { + iter = devices->find(partition_name); + } + if (iter == devices->end()) { + return ListenerAction::kContinue; + } } LOG(VERBOSE) << __PRETTY_FUNCTION__ << ": found partition: " << name; diff --git a/init/devices.cpp b/init/devices.cpp index 56c66239e..d4a3cb9d3 100644 --- a/init/devices.cpp +++ b/init/devices.cpp @@ -46,6 +46,7 @@ using android::base::Dirname; using android::base::ReadFileToString; using android::base::Readlink; using android::base::Realpath; +using android::base::Split; using android::base::StartsWith; using android::base::StringPrintf; using android::base::Trim; @@ -187,6 +188,36 @@ void SysfsPermissions::SetPermissions(const std::string& path) const { } } +std::string DeviceHandler::GetPartitionNameForDevice(const std::string& query_device) { + static const auto partition_map = [] { + std::vector> partition_map; + auto parser = [&partition_map](const std::string& key, const std::string& value) { + if (key != "androidboot.partition_map") { + return; + } + for (const auto& map : Split(value, ";")) { + auto map_pieces = Split(map, ","); + if (map_pieces.size() != 2) { + LOG(ERROR) << "Expected a comma separated device,partition mapping, but found '" + << map << "'"; + continue; + } + partition_map.emplace_back(map_pieces[0], map_pieces[1]); + } + }; + ImportKernelCmdline(parser); + ImportBootconfig(parser); + return partition_map; + }(); + + for (const auto& [device, partition] : partition_map) { + if (query_device == device) { + return partition; + } + } + 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 @@ -389,6 +420,10 @@ std::vector DeviceHandler::GetBlockDeviceSymlinks(const Uevent& uev // 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/ for symmetry. links.emplace_back("/dev/block/by-name/" + uevent.device_name); + auto partition_name = GetPartitionNameForDevice(uevent.device_name); + if (!partition_name.empty()) { + links.emplace_back("/dev/block/by-name/" + partition_name); + } } auto last_slash = uevent.path.rfind('/'); diff --git a/init/devices.h b/init/devices.h index d70d746e8..f9f4d7989 100644 --- a/init/devices.h +++ b/init/devices.h @@ -122,6 +122,12 @@ class DeviceHandler : public UeventHandler { std::vector GetBlockDeviceSymlinks(const Uevent& uevent) const; + // `androidboot.partition_map` allows associating a partition name for a raw block device + // through a comma separated and semicolon deliminated list. For example, + // `androidboot.partition_map=vdb,metadata;vdc,userdata` maps `vdb` to `metadata` and `vdc` to + // `userdata`. + static std::string GetPartitionNameForDevice(const std::string& device); + private: bool FindPlatformDevice(std::string path, std::string* platform_device_path) const; std::tuple GetDevicePermissions(