Loading init/devices.cpp +95 −40 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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, Loading Loading @@ -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; static const std::string kSysfsMountPoint = "/sys"; if (!strncmp(path, "/devices/", 9)) { name += 9; if (!strncmp(name, "platform/", 9)) name += 9; } // Uevents don't contain the mount point, so we need to add it here. path.insert(0, kSysfsMountPoint); LOG(VERBOSE) << "adding platform device " << name << " (" << path << ")"; std::string directory = android::base::Dirname(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); } 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; /* * 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; } auto last_slash = path.rfind('/'); if (last_slash == std::string::npos) return false; return NULL; } path.erase(last_slash); directory = android::base::Dirname(path); 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; } } } return false; 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 Loading Loading @@ -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) Loading @@ -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; Loading Loading @@ -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]; Loading @@ -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; Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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(); } Loading init/init_first_stage.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
init/devices.cpp +95 −40 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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, Loading Loading @@ -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; static const std::string kSysfsMountPoint = "/sys"; if (!strncmp(path, "/devices/", 9)) { name += 9; if (!strncmp(name, "platform/", 9)) name += 9; } // Uevents don't contain the mount point, so we need to add it here. path.insert(0, kSysfsMountPoint); LOG(VERBOSE) << "adding platform device " << name << " (" << path << ")"; std::string directory = android::base::Dirname(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); } 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; /* * 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; } auto last_slash = path.rfind('/'); if (last_slash == std::string::npos) return false; return NULL; } path.erase(last_slash); directory = android::base::Dirname(path); 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; } } } return false; 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 Loading Loading @@ -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) Loading @@ -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; Loading Loading @@ -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]; Loading @@ -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; Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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); } Loading Loading @@ -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(); } Loading
init/init_first_stage.cpp +5 −0 Original line number Diff line number Diff line Loading @@ -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; Loading