Merge "ld-config: Add HIDL memory libs to VNDK-SP" into oc-dev
diff --git a/init/devices.cpp b/init/devices.cpp
index 6f86662..39571ac 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -19,7 +19,6 @@
#include <fcntl.h>
#include <fnmatch.h>
#include <libgen.h>
-#include <poll.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
@@ -47,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>
@@ -81,8 +79,16 @@
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,
@@ -280,37 +286,77 @@
}
}
-// 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;
- static const std::string kSysfsMountPoint = "/sys";
-
- // Uevents don't contain the mount point, so we need to add it here.
- path.insert(0, kSysfsMountPoint);
-
- std::string directory = android::base::Dirname(path);
-
- 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;
- }
-
- auto last_slash = path.rfind('/');
- if (last_slash == std::string::npos) return false;
-
- path.erase(last_slash);
- directory = android::base::Dirname(path);
+ if (!strncmp(path, "/devices/", 9)) {
+ name += 9;
+ if (!strncmp(name, "platform/", 9))
+ name += 9;
}
- return false;
+ LOG(VERBOSE) << "adding platform device " << name << " (" << path << ")";
+
+ 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);
+}
+
+/*
+ * 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;
+ }
+
+ 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;
+ }
+ }
+}
+
+static void destroy_platform_devices() {
+ struct listnode* node;
+ struct listnode* n;
+ struct platform_node* bus;
+
+ 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);
+ }
}
/* Given a path that may start with a PCI device, populate the supplied buffer
@@ -434,9 +480,11 @@
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)
@@ -444,7 +492,7 @@
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;
@@ -479,6 +527,8 @@
}
char** get_block_device_symlinks(struct uevent* uevent) {
+ const char *device;
+ struct platform_node *pdev;
const char *slash;
const char *type;
char buf[256];
@@ -486,18 +536,9 @@
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;
@@ -516,7 +557,7 @@
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);
@@ -594,6 +635,16 @@
}
}
+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;
@@ -773,6 +824,8 @@
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);
}
@@ -1025,41 +1078,11 @@
}
void device_close() {
+ destroy_platform_devices();
device_fd.reset();
selinux_status_close();
}
-void device_poll(const coldboot_callback& callback,
- const std::optional<std::chrono::milliseconds> relative_timeout) {
- using namespace std::chrono;
-
- pollfd ufd;
- ufd.events = POLLIN;
- ufd.fd = device_fd;
-
- auto start_time = steady_clock::now();
-
- while (true) {
- ufd.revents = 0;
-
- int timeout_ms = -1;
- if (relative_timeout) {
- auto now = steady_clock::now();
- auto time_elapsed = duration_cast<milliseconds>(now - start_time);
- if (time_elapsed > *relative_timeout) return;
-
- auto remaining_timeout = *relative_timeout - time_elapsed;
- timeout_ms = remaining_timeout.count();
- }
-
- int nr = poll(&ufd, 1, timeout_ms);
- if (nr == 0) return;
- if (nr < 0) {
- continue;
- }
- if (ufd.revents & POLLIN) {
- auto ret = handle_device_fd(callback);
- if (should_stop_coldboot(ret)) return;
- }
- }
+int get_device_fd() {
+ return device_fd;
}
diff --git a/init/devices.h b/init/devices.h
index 62aef2e..3f2cde4 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -17,11 +17,8 @@
#ifndef _INIT_DEVICES_H
#define _INIT_DEVICES_H
-#include <sys/stat.h>
-
-#include <chrono>
#include <functional>
-#include <optional>
+#include <sys/stat.h>
enum coldboot_action_t {
// coldboot continues without creating the device for the uevent
@@ -56,10 +53,8 @@
mode_t perm, unsigned int uid,
unsigned int gid, unsigned short prefix,
unsigned short wildcard);
+int get_device_fd();
char** get_block_device_symlinks(struct uevent* uevent);
-void device_poll(const coldboot_callback& callback = nullptr,
- const std::optional<std::chrono::milliseconds> relative_timeout = {});
-
#endif /* _INIT_DEVICES_H */
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index 9425027..bcc8d1b 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <unistd.h>
-#include <chrono>
#include <memory>
#include <set>
#include <string>
@@ -34,8 +33,6 @@
#include "fs_mgr_avb.h"
#include "util.h"
-using namespace std::chrono_literals;
-
// Class Declarations
// ------------------
class FirstStageMount {
@@ -50,8 +47,8 @@
bool InitDevices();
protected:
- bool InitRequiredDevices();
- bool InitVerityDevice(const std::string& verity_device);
+ void InitRequiredDevices();
+ void InitVerityDevice(const std::string& verity_device);
bool MountPartitions();
virtual coldboot_action_t ColdbootCallback(uevent* uevent);
@@ -142,56 +139,50 @@
return true;
}
-bool FirstStageMount::InitDevices() { return GetRequiredDevices() && InitRequiredDevices(); }
+bool FirstStageMount::InitDevices() {
+ if (!GetRequiredDevices()) return false;
+
+ InitRequiredDevices();
+
+ // InitRequiredDevices() will remove found partitions from required_devices_partition_names_.
+ // So if it isn't empty here, it means some partitions are not found.
+ if (!required_devices_partition_names_.empty()) {
+ LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
+ << android::base::Join(required_devices_partition_names_, ", ");
+ return false;
+ } else {
+ return true;
+ }
+}
// Creates devices with uevent->partition_name matching one in the member variable
// required_devices_partition_names_. Found partitions will then be removed from it
// for the subsequent member function to check which devices are NOT created.
-bool FirstStageMount::InitRequiredDevices() {
+void FirstStageMount::InitRequiredDevices() {
if (required_devices_partition_names_.empty()) {
- return true;
+ return;
}
if (need_dm_verity_) {
const std::string dm_path = "/devices/virtual/misc/device-mapper";
- bool found = false;
- auto dm_callback = [&dm_path, &found](uevent* uevent) -> coldboot_action_t {
- if (uevent->path && uevent->path == dm_path) {
- found = true;
- return COLDBOOT_STOP;
- }
+ device_init(("/sys" + dm_path).c_str(), [&dm_path](uevent* uevent) -> coldboot_action_t {
+ if (uevent->path && uevent->path == dm_path) return COLDBOOT_STOP;
return COLDBOOT_CONTINUE; // dm_path not found, continue to find it.
- };
- device_init(("/sys" + dm_path).c_str(), dm_callback);
- if (!found) {
- device_poll(dm_callback, 10s);
- }
- if (!found) {
- LOG(ERROR) << "device-mapper device not found";
- return false;
- }
+ });
}
- auto uevent_callback = [this](uevent* uevent) -> coldboot_action_t {
- return ColdbootCallback(uevent);
- };
-
- device_init(nullptr, uevent_callback);
- if (!required_devices_partition_names_.empty()) {
- device_poll(uevent_callback, 10s);
- }
-
- if (!required_devices_partition_names_.empty()) {
- LOG(ERROR) << __PRETTY_FUNCTION__ << ": partition(s) not found: "
- << android::base::Join(required_devices_partition_names_, ", ");
- return false;
- }
+ device_init(nullptr,
+ [this](uevent* uevent) -> coldboot_action_t { return ColdbootCallback(uevent); });
device_close();
- return true;
}
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;
@@ -217,30 +208,18 @@
}
// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
-bool FirstStageMount::InitVerityDevice(const std::string& verity_device) {
+void FirstStageMount::InitVerityDevice(const std::string& verity_device) {
const std::string device_name(basename(verity_device.c_str()));
const std::string syspath = "/sys/block/" + device_name;
- bool found = false;
- auto verity_callback = [&](uevent* uevent) -> coldboot_action_t {
+ device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
if (uevent->device_name && uevent->device_name == device_name) {
LOG(VERBOSE) << "Creating dm-verity device : " << verity_device;
- found = true;
return COLDBOOT_STOP;
}
return COLDBOOT_CONTINUE;
- };
-
- device_init(syspath.c_str(), verity_callback);
- if (!found) {
- device_poll(verity_callback, 10s);
- }
- if (!found) {
- LOG(ERROR) << "dm-verity device not found";
- return false;
- }
+ });
device_close();
- return true;
}
bool FirstStageMount::MountPartitions() {
@@ -306,7 +285,7 @@
} else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) {
// The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
// Needs to create it because ueventd isn't started in init first stage.
- return InitVerityDevice(fstab_rec->blk_device);
+ InitVerityDevice(fstab_rec->blk_device);
} else {
return false;
}
diff --git a/init/ueventd.cpp b/init/ueventd.cpp
index d0b7b8e..f27be64 100644
--- a/init/ueventd.cpp
+++ b/init/ueventd.cpp
@@ -17,6 +17,7 @@
#include <ctype.h>
#include <fcntl.h>
#include <grp.h>
+#include <poll.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
@@ -75,7 +76,20 @@
device_init();
- device_poll();
+ pollfd ufd;
+ ufd.events = POLLIN;
+ ufd.fd = get_device_fd();
+
+ while (true) {
+ ufd.revents = 0;
+ int nr = poll(&ufd, 1, -1);
+ if (nr <= 0) {
+ continue;
+ }
+ if (ufd.revents & POLLIN) {
+ handle_device_fd();
+ }
+ }
return 0;
}