system/core
Revisão | f520e44c4cd240330243ebcc046138f9e9b77fb4 (tree) |
---|---|
Hora | 2017-06-22 03:10:53 |
Autor | Tom Cherry <tomcherry@goog...> |
Commiter | Tom Cherry |
Revert "ueventd: remove PlatformDeviceList"
Bug: 62864413
This reverts commit d43b615216fb1656fb5234e8202aa3ed7b37fda7.
Change-Id: If3d9060e723d6040d3f32f253b492131a56edb9f
@@ -46,7 +46,6 @@ | ||
46 | 46 | |
47 | 47 | #include <android-base/file.h> |
48 | 48 | #include <android-base/stringprintf.h> |
49 | -#include <android-base/strings.h> | |
50 | 49 | #include <android-base/unique_fd.h> |
51 | 50 | #include <cutils/list.h> |
52 | 51 | #include <cutils/uevent.h> |
@@ -80,8 +79,16 @@ struct perm_node { | ||
80 | 79 | struct listnode plist; |
81 | 80 | }; |
82 | 81 | |
82 | +struct platform_node { | |
83 | + char *name; | |
84 | + char *path; | |
85 | + int path_len; | |
86 | + struct listnode list; | |
87 | +}; | |
88 | + | |
83 | 89 | static list_declare(sys_perms); |
84 | 90 | static list_declare(dev_perms); |
91 | +static list_declare(platform_names); | |
85 | 92 | |
86 | 93 | int add_dev_perms(const char *name, const char *attr, |
87 | 94 | mode_t perm, unsigned int uid, unsigned int gid, |
@@ -279,37 +286,77 @@ out: | ||
279 | 286 | } |
280 | 287 | } |
281 | 288 | |
282 | -// Given a path that may start with a platform device, find the parent platform device by finding a | |
283 | -// parent directory with a 'subsystem' symlink that points to the platform bus. | |
284 | -// If it doesn't start with a platform device, return false | |
285 | -bool FindPlatformDevice(std::string path, std::string* platform_device_path) { | |
286 | - platform_device_path->clear(); | |
289 | +static void add_platform_device(const char *path) | |
290 | +{ | |
291 | + int path_len = strlen(path); | |
292 | + struct platform_node *bus; | |
293 | + const char *name = path; | |
294 | + | |
295 | + if (!strncmp(path, "/devices/", 9)) { | |
296 | + name += 9; | |
297 | + if (!strncmp(name, "platform/", 9)) | |
298 | + name += 9; | |
299 | + } | |
287 | 300 | |
288 | - static const std::string kSysfsMountPoint = "/sys"; | |
301 | + LOG(VERBOSE) << "adding platform device " << name << " (" << path << ")"; | |
289 | 302 | |
290 | - // Uevents don't contain the mount point, so we need to add it here. | |
291 | - path.insert(0, kSysfsMountPoint); | |
303 | + bus = (platform_node*) calloc(1, sizeof(struct platform_node)); | |
304 | + bus->path = strdup(path); | |
305 | + bus->path_len = path_len; | |
306 | + bus->name = bus->path + (name - path); | |
307 | + list_add_tail(&platform_names, &bus->list); | |
308 | +} | |
292 | 309 | |
293 | - std::string directory = android::base::Dirname(path); | |
310 | +/* | |
311 | + * given a path that may start with a platform device, find the length of the | |
312 | + * platform device prefix. If it doesn't start with a platform device, return | |
313 | + * 0. | |
314 | + */ | |
315 | +static struct platform_node *find_platform_device(const char *path) | |
316 | +{ | |
317 | + int path_len = strlen(path); | |
318 | + struct listnode *node; | |
319 | + struct platform_node *bus; | |
320 | + | |
321 | + list_for_each_reverse(node, &platform_names) { | |
322 | + bus = node_to_item(node, struct platform_node, list); | |
323 | + if ((bus->path_len < path_len) && | |
324 | + (path[bus->path_len] == '/') && | |
325 | + !strncmp(path, bus->path, bus->path_len)) | |
326 | + return bus; | |
327 | + } | |
294 | 328 | |
295 | - while (directory != "/" && directory != ".") { | |
296 | - std::string subsystem_link_path; | |
297 | - if (android::base::Realpath(directory + "/subsystem", &subsystem_link_path) && | |
298 | - subsystem_link_path == kSysfsMountPoint + "/bus/platform") { | |
299 | - // We need to remove the mount point that we added above before returning. | |
300 | - directory.erase(0, kSysfsMountPoint.size()); | |
301 | - *platform_device_path = directory; | |
302 | - return true; | |
329 | + return NULL; | |
330 | +} | |
331 | + | |
332 | +static void remove_platform_device(const char *path) | |
333 | +{ | |
334 | + struct listnode *node; | |
335 | + struct platform_node *bus; | |
336 | + | |
337 | + list_for_each_reverse(node, &platform_names) { | |
338 | + bus = node_to_item(node, struct platform_node, list); | |
339 | + if (!strcmp(path, bus->path)) { | |
340 | + LOG(INFO) << "removing platform device " << bus->name; | |
341 | + free(bus->path); | |
342 | + list_remove(node); | |
343 | + free(bus); | |
344 | + return; | |
303 | 345 | } |
346 | + } | |
347 | +} | |
304 | 348 | |
305 | - auto last_slash = path.rfind('/'); | |
306 | - if (last_slash == std::string::npos) return false; | |
349 | +static void destroy_platform_devices() { | |
350 | + struct listnode* node; | |
351 | + struct listnode* n; | |
352 | + struct platform_node* bus; | |
307 | 353 | |
308 | - path.erase(last_slash); | |
309 | - directory = android::base::Dirname(path); | |
354 | + list_for_each_safe(node, n, &platform_names) { | |
355 | + list_remove(node); | |
356 | + bus = node_to_item(node, struct platform_node, list); | |
357 | + free(bus->path); | |
358 | + free(bus); | |
310 | 359 | } |
311 | - | |
312 | - return false; | |
313 | 360 | } |
314 | 361 | |
315 | 362 | /* 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) | ||
433 | 480 | char **links; |
434 | 481 | int link_num = 0; |
435 | 482 | int width; |
483 | + struct platform_node *pdev; | |
436 | 484 | |
437 | - std::string platform_device; | |
438 | - if (!FindPlatformDevice(uevent->path, &platform_device)) return nullptr; | |
485 | + pdev = find_platform_device(uevent->path); | |
486 | + if (!pdev) | |
487 | + return NULL; | |
439 | 488 | |
440 | 489 | links = (char**) malloc(sizeof(char *) * 2); |
441 | 490 | if (!links) |
@@ -443,7 +492,7 @@ static char **get_character_device_symlinks(struct uevent *uevent) | ||
443 | 492 | memset(links, 0, sizeof(char *) * 2); |
444 | 493 | |
445 | 494 | /* skip "/devices/platform/<driver>" */ |
446 | - parent = strchr(uevent->path + platform_device.size(), '/'); | |
495 | + parent = strchr(uevent->path + pdev->path_len, '/'); | |
447 | 496 | if (!parent) |
448 | 497 | goto err; |
449 | 498 |
@@ -478,6 +527,8 @@ err: | ||
478 | 527 | } |
479 | 528 | |
480 | 529 | char** get_block_device_symlinks(struct uevent* uevent) { |
530 | + const char *device; | |
531 | + struct platform_node *pdev; | |
481 | 532 | const char *slash; |
482 | 533 | const char *type; |
483 | 534 | char buf[256]; |
@@ -485,18 +536,9 @@ char** get_block_device_symlinks(struct uevent* uevent) { | ||
485 | 536 | int link_num = 0; |
486 | 537 | char *p; |
487 | 538 | |
488 | - std::string device; | |
489 | - if (FindPlatformDevice(uevent->path, &device)) { | |
490 | - // Skip /devices/platform or /devices/ if present | |
491 | - static const std::string devices_platform_prefix = "/devices/platform/"; | |
492 | - static const std::string devices_prefix = "/devices/"; | |
493 | - | |
494 | - if (android::base::StartsWith(device, devices_platform_prefix.c_str())) { | |
495 | - device = device.substr(devices_platform_prefix.length()); | |
496 | - } else if (android::base::StartsWith(device, devices_prefix.c_str())) { | |
497 | - device = device.substr(devices_prefix.length()); | |
498 | - } | |
499 | - | |
539 | + pdev = find_platform_device(uevent->path); | |
540 | + if (pdev) { | |
541 | + device = pdev->name; | |
500 | 542 | type = "platform"; |
501 | 543 | } else if (!find_pci_device_prefix(uevent->path, buf, sizeof(buf))) { |
502 | 544 | device = buf; |
@@ -515,7 +557,7 @@ char** get_block_device_symlinks(struct uevent* uevent) { | ||
515 | 557 | |
516 | 558 | LOG(VERBOSE) << "found " << type << " device " << device; |
517 | 559 | |
518 | - snprintf(link_path, sizeof(link_path), "/dev/block/%s/%s", type, device.c_str()); | |
560 | + snprintf(link_path, sizeof(link_path), "/dev/block/%s/%s", type, device); | |
519 | 561 | |
520 | 562 | if (uevent->partition_name) { |
521 | 563 | p = strdup(uevent->partition_name); |
@@ -593,6 +635,16 @@ static void handle_device(const char *action, const char *devpath, | ||
593 | 635 | } |
594 | 636 | } |
595 | 637 | |
638 | +static void handle_platform_device_event(struct uevent *uevent) | |
639 | +{ | |
640 | + const char *path = uevent->path; | |
641 | + | |
642 | + if (!strcmp(uevent->action, "add")) | |
643 | + add_platform_device(path); | |
644 | + else if (!strcmp(uevent->action, "remove")) | |
645 | + remove_platform_device(path); | |
646 | +} | |
647 | + | |
596 | 648 | static const char *parse_device_name(struct uevent *uevent, unsigned int len) |
597 | 649 | { |
598 | 650 | const char *name; |
@@ -772,6 +824,8 @@ static void handle_device_event(struct uevent *uevent) | ||
772 | 824 | |
773 | 825 | if (!strncmp(uevent->subsystem, "block", 5)) { |
774 | 826 | handle_block_device_event(uevent); |
827 | + } else if (!strncmp(uevent->subsystem, "platform", 8)) { | |
828 | + handle_platform_device_event(uevent); | |
775 | 829 | } else { |
776 | 830 | handle_generic_device_event(uevent); |
777 | 831 | } |
@@ -1024,6 +1078,7 @@ void device_init(const char* path, coldboot_callback fn) { | ||
1024 | 1078 | } |
1025 | 1079 | |
1026 | 1080 | void device_close() { |
1081 | + destroy_platform_devices(); | |
1027 | 1082 | device_fd.reset(); |
1028 | 1083 | selinux_status_close(); |
1029 | 1084 | } |
@@ -178,6 +178,11 @@ void FirstStageMount::InitRequiredDevices() { | ||
178 | 178 | } |
179 | 179 | |
180 | 180 | coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) { |
181 | + // We need platform devices to create symlinks. | |
182 | + if (!strncmp(uevent->subsystem, "platform", 8)) { | |
183 | + return COLDBOOT_CREATE; | |
184 | + } | |
185 | + | |
181 | 186 | // Ignores everything that is not a block device. |
182 | 187 | if (strncmp(uevent->subsystem, "block", 5)) { |
183 | 188 | return COLDBOOT_CONTINUE; |