summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Cherry <tomcherry@google.com>2017-06-21 18:10:53 +0000
committerTom Cherry <tomcherry@google.com>2017-06-21 18:10:53 +0000
commitf520e44c4cd240330243ebcc046138f9e9b77fb4 (patch)
tree72c38cef222fc302b6a5881ff5b403c27360a718
parentd43b615216fb1656fb5234e8202aa3ed7b37fda7 (diff)
downloadcore-f520e44c4cd240330243ebcc046138f9e9b77fb4.tar.gz
Revert "ueventd: remove PlatformDeviceList"
Bug: 62864413 This reverts commit d43b615216fb1656fb5234e8202aa3ed7b37fda7. Change-Id: If3d9060e723d6040d3f32f253b492131a56edb9f
-rw-r--r--init/devices.cpp135
-rw-r--r--init/init_first_stage.cpp5
2 files changed, 100 insertions, 40 deletions
diff --git a/init/devices.cpp b/init/devices.cpp
index 27a20a435..39571ac65 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -46,7 +46,6 @@
#include <android-base/file.h>
#include <android-base/stringprintf.h>
-#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/list.h>
#include <cutils/uevent.h>
@@ -80,8 +79,16 @@ struct perm_node {
struct listnode plist;
};
+struct platform_node {
+ char *name;
+ char *path;
+ int path_len;
+ struct listnode list;
+};
+
static list_declare(sys_perms);
static list_declare(dev_perms);
+static list_declare(platform_names);
int add_dev_perms(const char *name, const char *attr,
mode_t perm, unsigned int uid, unsigned int gid,
@@ -279,37 +286,77 @@ out:
}
}
-// 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 FindPlatformDevice(std::string path, std::string* platform_device_path) {
- platform_device_path->clear();
+static void add_platform_device(const char *path)
+{
+ int path_len = strlen(path);
+ struct platform_node *bus;
+ const char *name = path;
+
+ if (!strncmp(path, "/devices/", 9)) {
+ name += 9;
+ if (!strncmp(name, "platform/", 9))
+ name += 9;
+ }
- static const std::string kSysfsMountPoint = "/sys";
+ LOG(VERBOSE) << "adding platform device " << name << " (" << path << ")";
- // Uevents don't contain the mount point, so we need to add it here.
- path.insert(0, kSysfsMountPoint);
+ bus = (platform_node*) calloc(1, sizeof(struct platform_node));
+ bus->path = strdup(path);
+ bus->path_len = path_len;
+ bus->name = bus->path + (name - path);
+ list_add_tail(&platform_names, &bus->list);
+}
- std::string directory = android::base::Dirname(path);
+/*
+ * given a path that may start with a platform device, find the length of the
+ * platform device prefix. If it doesn't start with a platform device, return
+ * 0.
+ */
+static struct platform_node *find_platform_device(const char *path)
+{
+ int path_len = strlen(path);
+ struct listnode *node;
+ struct platform_node *bus;
+
+ list_for_each_reverse(node, &platform_names) {
+ bus = node_to_item(node, struct platform_node, list);
+ if ((bus->path_len < path_len) &&
+ (path[bus->path_len] == '/') &&
+ !strncmp(path, bus->path, bus->path_len))
+ return bus;
+ }
- while (directory != "/" && directory != ".") {
- std::string subsystem_link_path;
- if (android::base::Realpath(directory + "/subsystem", &subsystem_link_path) &&
- subsystem_link_path == kSysfsMountPoint + "/bus/platform") {
- // We need to remove the mount point that we added above before returning.
- directory.erase(0, kSysfsMountPoint.size());
- *platform_device_path = directory;
- return true;
+ return NULL;
+}
+
+static void remove_platform_device(const char *path)
+{
+ struct listnode *node;
+ struct platform_node *bus;
+
+ list_for_each_reverse(node, &platform_names) {
+ bus = node_to_item(node, struct platform_node, list);
+ if (!strcmp(path, bus->path)) {
+ LOG(INFO) << "removing platform device " << bus->name;
+ free(bus->path);
+ list_remove(node);
+ free(bus);
+ return;
}
+ }
+}
- auto last_slash = path.rfind('/');
- if (last_slash == std::string::npos) return false;
+static void destroy_platform_devices() {
+ struct listnode* node;
+ struct listnode* n;
+ struct platform_node* bus;
- path.erase(last_slash);
- directory = android::base::Dirname(path);
+ list_for_each_safe(node, n, &platform_names) {
+ list_remove(node);
+ bus = node_to_item(node, struct platform_node, list);
+ free(bus->path);
+ free(bus);
}
-
- return false;
}
/* Given a path that may start with a PCI device, populate the supplied buffer
@@ -433,9 +480,11 @@ static char **get_character_device_symlinks(struct uevent *uevent)
char **links;
int link_num = 0;
int width;
+ struct platform_node *pdev;
- std::string platform_device;
- if (!FindPlatformDevice(uevent->path, &platform_device)) return nullptr;
+ pdev = find_platform_device(uevent->path);
+ if (!pdev)
+ return NULL;
links = (char**) malloc(sizeof(char *) * 2);
if (!links)
@@ -443,7 +492,7 @@ static char **get_character_device_symlinks(struct uevent *uevent)
memset(links, 0, sizeof(char *) * 2);
/* skip "/devices/platform/<driver>" */
- parent = strchr(uevent->path + platform_device.size(), '/');
+ parent = strchr(uevent->path + pdev->path_len, '/');
if (!parent)
goto err;
@@ -478,6 +527,8 @@ err:
}
char** get_block_device_symlinks(struct uevent* uevent) {
+ const char *device;
+ struct platform_node *pdev;
const char *slash;
const char *type;
char buf[256];
@@ -485,18 +536,9 @@ char** get_block_device_symlinks(struct uevent* uevent) {
int link_num = 0;
char *p;
- std::string device;
- if (FindPlatformDevice(uevent->path, &device)) {
- // Skip /devices/platform or /devices/ if present
- static const std::string devices_platform_prefix = "/devices/platform/";
- static const std::string devices_prefix = "/devices/";
-
- if (android::base::StartsWith(device, devices_platform_prefix.c_str())) {
- device = device.substr(devices_platform_prefix.length());
- } else if (android::base::StartsWith(device, devices_prefix.c_str())) {
- device = device.substr(devices_prefix.length());
- }
-
+ pdev = find_platform_device(uevent->path);
+ if (pdev) {
+ device = pdev->name;
type = "platform";
} else if (!find_pci_device_prefix(uevent->path, buf, sizeof(buf))) {
device = buf;
@@ -515,7 +557,7 @@ char** get_block_device_symlinks(struct uevent* uevent) {
LOG(VERBOSE) << "found " << type << " device " << device;
- snprintf(link_path, sizeof(link_path), "/dev/block/%s/%s", type, device.c_str());
+ snprintf(link_path, sizeof(link_path), "/dev/block/%s/%s", type, device);
if (uevent->partition_name) {
p = strdup(uevent->partition_name);
@@ -593,6 +635,16 @@ static void handle_device(const char *action, const char *devpath,
}
}
+static void handle_platform_device_event(struct uevent *uevent)
+{
+ const char *path = uevent->path;
+
+ if (!strcmp(uevent->action, "add"))
+ add_platform_device(path);
+ else if (!strcmp(uevent->action, "remove"))
+ remove_platform_device(path);
+}
+
static const char *parse_device_name(struct uevent *uevent, unsigned int len)
{
const char *name;
@@ -772,6 +824,8 @@ static void handle_device_event(struct uevent *uevent)
if (!strncmp(uevent->subsystem, "block", 5)) {
handle_block_device_event(uevent);
+ } else if (!strncmp(uevent->subsystem, "platform", 8)) {
+ handle_platform_device_event(uevent);
} else {
handle_generic_device_event(uevent);
}
@@ -1024,6 +1078,7 @@ void device_init(const char* path, coldboot_callback fn) {
}
void device_close() {
+ destroy_platform_devices();
device_fd.reset();
selinux_status_close();
}
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index 60ce6e9c0..bcc8d1b1a 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -178,6 +178,11 @@ void FirstStageMount::InitRequiredDevices() {
}
coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) {
+ // We need platform devices to create symlinks.
+ if (!strncmp(uevent->subsystem, "platform", 8)) {
+ return COLDBOOT_CREATE;
+ }
+
// Ignores everything that is not a block device.
if (strncmp(uevent->subsystem, "block", 5)) {
return COLDBOOT_CONTINUE;