devices.cpp revision 35403ebaf85aa229973275be9f5229d453799811
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007-2014 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <dirent.h> 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <errno.h> 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fnmatch.h> 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <libgen.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stddef.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdlib.h> 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <string.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/sendfile.h> 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/socket.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h> 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/time.h> 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/types.h> 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/un.h> 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/wait.h> 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <unistd.h> 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <linux/netlink.h> 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <memory> 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <thread> 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <selinux/selinux.h> 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <selinux/label.h> 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <selinux/android.h> 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <selinux/avc.h> 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <private/android_filesystem_config.h> 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android-base/file.h> 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android-base/stringprintf.h> 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android-base/unique_fd.h> 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/list.h> 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <cutils/uevent.h> 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "devices.h" 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "ueventd_parser.h" 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "util.h" 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "log.h" 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define SYSFS_PREFIX "/sys" 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char *firmware_dirs[] = { "/etc/firmware", 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "/vendor/firmware", 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "/firmware/image" }; 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectextern struct selabel_handle *sehandle; 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic android::base::unique_fd device_fd; 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct perms_ { 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char *name; 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char *attr; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mode_t perm; 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned int uid; 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned int gid; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned short prefix; 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned short wildcard; 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct perm_node { 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct perms_ dp; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct listnode plist; 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstruct platform_node { 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char *name; 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char *path; 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int path_len; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct listnode list; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic list_declare(sys_perms); 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic list_declare(dev_perms); 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic list_declare(platform_names); 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint add_dev_perms(const char *name, const char *attr, 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mode_t perm, unsigned int uid, unsigned int gid, 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned short prefix, 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned short wildcard) { 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct perm_node *node = (perm_node*) calloc(1, sizeof(*node)); 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!node) 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -ENOMEM; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project node->dp.name = strdup(name); 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!node->dp.name) { 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(node); 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -ENOMEM; 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (attr) { 108a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru node->dp.attr = strdup(attr); 109a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru if (!node->dp.attr) { 110a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru free(node->dp.name); 111a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru free(node); 112a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru return -ENOMEM; 113a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru } 114a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru } 115a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru 116a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru node->dp.perm = perm; 117a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru node->dp.uid = uid; 118a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru node->dp.gid = gid; 119a8675f67e33bc7337d148358783b0fd138b501ffJean-Baptiste Queru node->dp.prefix = prefix; 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project node->dp.wildcard = wildcard; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (attr) 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_add_tail(&sys_perms, &node->plist); 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_add_tail(&dev_perms, &node->plist); 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic bool perm_path_matches(const char *path, struct perms_ *dp) 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (dp->prefix) { 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strncmp(path, dp->name, strlen(dp->name)) == 0) 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (dp->wildcard) { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fnmatch(dp->name, path, FNM_PATHNAME) == 0) 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strcmp(path, dp->name) == 0) 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic bool match_subsystem(perms_* dp, const char* pattern, 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* path, const char* subsystem) { 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!pattern || !subsystem || strstr(dp->name, subsystem) == NULL) { 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string subsys_path = android::base::StringPrintf(pattern, subsystem, basename(path)); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return perm_path_matches(subsys_path.c_str(), dp); 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void fixup_sys_perms(const char* upath, const char* subsystem) { 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // upaths omit the "/sys" that paths in this list 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // contain, so we prepend it... 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string path = std::string(SYSFS_PREFIX) + upath; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project listnode* node; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_for_each(node, &sys_perms) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project perms_* dp = &(node_to_item(node, perm_node, plist))->dp; 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (match_subsystem(dp, SYSFS_PREFIX "/class/%s/%s", path.c_str(), subsystem)) { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ; // matched 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (match_subsystem(dp, SYSFS_PREFIX "/bus/%s/devices/%s", path.c_str(), subsystem)) { 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ; // matched 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!perm_path_matches(path.c_str(), dp)) { 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string attr_file = path + "/" + dp->attr; 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(INFO) << "fixup " << attr_file 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project << " " << dp->uid << " " << dp->gid << " " << std::oct << dp->perm; 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project chown(attr_file.c_str(), dp->uid, dp->gid); 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project chmod(attr_file.c_str(), dp->perm); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (access(path.c_str(), F_OK) == 0) { 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(VERBOSE) << "restorecon_recursive: " << path; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE); 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic mode_t get_device_perm(const char *path, const char **links, 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned *uid, unsigned *gid) 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct listnode *node; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct perm_node *perm_node; 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct perms_ *dp; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* search the perms list in reverse so that ueventd.$hardware can 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * override ueventd.rc 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_for_each_reverse(node, &dev_perms) { 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool match = false; 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project perm_node = node_to_item(node, struct perm_node, plist); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dp = &perm_node->dp; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (perm_path_matches(path, dp)) { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project match = true; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (links) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int i; 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (i = 0; links[i]; i++) { 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (perm_path_matches(links[i], dp)) { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project match = true; 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (match) { 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *uid = dp->uid; 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *gid = dp->gid; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return dp->perm; 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Default if nothing found. */ 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *uid = 0; 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *gid = 0; 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0600; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void make_device(const char *path, 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char */*upath*/, 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int block, int major, int minor, 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char **links) 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned uid; 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unsigned gid; 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mode_t mode; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dev_t dev; 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char *secontext = NULL; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mode = get_device_perm(path, links, &uid, &gid) | (block ? S_IFBLK : S_IFCHR); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sehandle) { 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selabel_lookup_best_match(sehandle, &secontext, path, links, mode)) { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "Device '" << path << "' not created; cannot find SELinux label"; 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setfscreatecon(secontext); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dev = makedev(major, minor); 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Temporarily change egid to avoid race condition setting the gid of the 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * device node. Unforunately changing the euid would prevent creation of 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * some device nodes, so the uid has to be set with chown() and is still 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * racy. Fixing the gid race at least fixed the issue with system_server 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * opening dynamic input devices under the AID_INPUT gid. */ 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setegid(gid); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* If the node already exists update its SELinux label to handle cases when 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it was created with the wrong context during coldboot procedure. */ 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mknod(path, mode, dev) && (errno == EEXIST) && secontext) { 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char* fcon = nullptr; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rc = lgetfilecon(path, &fcon); 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rc < 0) { 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "Cannot get SELinux label on '" << path << "' device"; 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto out; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bool different = strcmp(fcon, secontext) != 0; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project freecon(fcon); 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (different && lsetfilecon(path, secontext)) { 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "Cannot set '" << secontext << "' SELinux label on '" << path << "' device"; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectout: 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project chown(path, uid, -1); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setegid(AID_ROOT); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (secontext) { 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project freecon(secontext); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project setfscreatecon(NULL); 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void add_platform_device(const char *path) 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int path_len = strlen(path); 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct platform_node *bus; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *name = path; 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strncmp(path, "/devices/", 9)) { 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name += 9; 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strncmp(name, "platform/", 9)) 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name += 9; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(VERBOSE) << "adding platform device " << name << " (" << path << ")"; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bus = (platform_node*) calloc(1, sizeof(struct platform_node)); 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bus->path = strdup(path); 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bus->path_len = path_len; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bus->name = bus->path + (name - path); 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_add_tail(&platform_names, &bus->list); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * given a path that may start with a platform device, find the length of the 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * platform device prefix. If it doesn't start with a platform device, return 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 0. 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic struct platform_node *find_platform_device(const char *path) 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int path_len = strlen(path); 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct listnode *node; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct platform_node *bus; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_for_each_reverse(node, &platform_names) { 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bus = node_to_item(node, struct platform_node, list); 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((bus->path_len < path_len) && 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (path[bus->path_len] == '/') && 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project !strncmp(path, bus->path, bus->path_len)) 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return bus; 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void remove_platform_device(const char *path) 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct listnode *node; 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct platform_node *bus; 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_for_each_reverse(node, &platform_names) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bus = node_to_item(node, struct platform_node, list); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strcmp(path, bus->path)) { 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(INFO) << "removing platform device " << bus->name; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(bus->path); 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_remove(node); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(bus); 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void destroy_platform_devices() { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct listnode* node; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct listnode* n; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct platform_node* bus; 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_for_each_safe(node, n, &platform_names) { 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project list_remove(node); 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project bus = node_to_item(node, struct platform_node, list); 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(bus->path); 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(bus); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Given a path that may start with a PCI device, populate the supplied buffer 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * with the PCI domain/bus number and the peripheral ID and return 0. 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * If it doesn't start with a PCI device, or there is some error, return -1 */ 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int find_pci_device_prefix(const char *path, char *buf, ssize_t buf_sz) 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *start, *end; 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strncmp(path, "/devices/pci", 12)) 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Beginning of the prefix is the initial "pci" after "/devices/" */ 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project start = path + 9; 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* End of the prefix is two path '/' later, capturing the domain/bus number 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and the peripheral ID. Example: pci0000:00/0000:00:1f.2 */ 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end = strchr(start, '/'); 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!end) 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project end = strchr(end + 1, '/'); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!end) 3778aa393b03f6d1f25313c658334e9b86a86a6f61fSimon Schoar return -1; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Make sure we have enough room for the string plus null terminator */ 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (end - start + 1 > buf_sz) 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strncpy(buf, start, end - start); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project buf[end - start] = '\0'; 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return 0; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void parse_event(const char *msg, struct uevent *uevent) 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->action = ""; 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->path = ""; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->subsystem = ""; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->firmware = ""; 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->major = -1; 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->minor = -1; 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->partition_name = NULL; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->partition_num = -1; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->device_name = NULL; 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* currently ignoring SEQNUM */ 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while(*msg) { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(!strncmp(msg, "ACTION=", 7)) { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 7; 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->action = msg; 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(msg, "DEVPATH=", 8)) { 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 8; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->path = msg; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(msg, "SUBSYSTEM=", 10)) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 10; 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->subsystem = msg; 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(msg, "FIRMWARE=", 9)) { 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 9; 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->firmware = msg; 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(msg, "MAJOR=", 6)) { 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 6; 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->major = atoi(msg); 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(msg, "MINOR=", 6)) { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 6; 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->minor = atoi(msg); 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(msg, "PARTN=", 6)) { 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 6; 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->partition_num = atoi(msg); 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(msg, "PARTNAME=", 9)) { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 9; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->partition_name = msg; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(msg, "DEVNAME=", 8)) { 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg += 8; 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->device_name = msg; 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* advance to after the next \0 */ 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while(*msg++) 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ; 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (LOG_UEVENTS) { 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(INFO) << android::base::StringPrintf("event { '%s', '%s', '%s', '%s', %d, %d }", 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->action, uevent->path, uevent->subsystem, 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->firmware, uevent->major, uevent->minor); 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic char **get_character_device_symlinks(struct uevent *uevent) 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *parent; 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *slash; 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char **links; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int link_num = 0; 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int width; 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct platform_node *pdev; 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pdev = find_platform_device(uevent->path); 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!pdev) 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project links = (char**) malloc(sizeof(char *) * 2); 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!links) 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(links, 0, sizeof(char *) * 2); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* skip "/devices/platform/<driver>" */ 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parent = strchr(uevent->path + pdev->path_len, '/'); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!parent) 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto err; 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strncmp(parent, "/usb", 4)) { 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* skip root hub name and device. use device interface */ 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (*++parent && *parent != '/'); 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (*parent) 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (*++parent && *parent != '/'); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!*parent) 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto err; 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project slash = strchr(++parent, '/'); 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!slash) 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto err; 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project width = slash - parent; 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (width <= 0) 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto err; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (asprintf(&links[link_num], "/dev/usb/%s%.*s", uevent->subsystem, width, parent) > 0) 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project link_num++; 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project links[link_num] = NULL; 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mkdir("/dev/usb", 0755); 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto err; 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return links; 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecterr: 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(links); 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic char **get_block_device_symlinks(struct uevent *uevent) 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *device; 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct platform_node *pdev; 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *slash; 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *type; 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char buf[256]; 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char link_path[256]; 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int link_num = 0; 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char *p; 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pdev = find_platform_device(uevent->path); 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pdev) { 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project device = pdev->name; 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project type = "platform"; 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!find_pci_device_prefix(uevent->path, buf, sizeof(buf))) { 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project device = buf; 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project type = "pci"; 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char **links = (char**) malloc(sizeof(char *) * 4); 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!links) 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project memset(links, 0, sizeof(char *) * 4); 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(VERBOSE) << "found " << type << " device " << device; 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project snprintf(link_path, sizeof(link_path), "/dev/block/%s/%s", type, device); 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uevent->partition_name) { 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project p = strdup(uevent->partition_name); 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sanitize(p); 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strcmp(uevent->partition_name, p)) { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(VERBOSE) << "Linking partition '" << uevent->partition_name << "' as '" << p << "'"; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (asprintf(&links[link_num], "%s/by-name/%s", link_path, p) > 0) 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project link_num++; 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project links[link_num] = NULL; 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(p); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uevent->partition_num >= 0) { 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (asprintf(&links[link_num], "%s/by-num/p%d", link_path, uevent->partition_num) > 0) 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project link_num++; 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project links[link_num] = NULL; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project slash = strrchr(uevent->path, '/'); 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (asprintf(&links[link_num], "%s/%s", link_path, slash + 1) > 0) 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project link_num++; 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project links[link_num] = NULL; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return links; 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void make_link_init(const char* oldpath, const char* newpath) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* slash = strrchr(newpath, '/'); 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!slash) return; 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mkdir_recursive(dirname(newpath), 0755)) { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "Failed to create directory " << dirname(newpath); 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (symlink(oldpath, newpath) && errno != EEXIST) { 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "Failed to symlink " << oldpath << " to " << newpath; 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void remove_link(const char* oldpath, const char* newpath) { 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string path; 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (android::base::Readlink(newpath, &path) && path == oldpath) unlink(newpath); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void handle_device(const char *action, const char *devpath, 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *path, int block, int major, int minor, char **links) 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(!strcmp(action, "add")) { 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_device(devpath, path, block, major, minor, (const char **)links); 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (links) { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; links[i]; i++) { 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_link_init(devpath, links[i]); 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(!strcmp(action, "remove")) { 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (links) { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; links[i]; i++) { 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remove_link(devpath, links[i]); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project unlink(devpath); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (links) { 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; links[i]; i++) { 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(links[i]); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project free(links); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void handle_platform_device_event(struct uevent *uevent) 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *path = uevent->path; 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strcmp(uevent->action, "add")) 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project add_platform_device(path); 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (!strcmp(uevent->action, "remove")) 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project remove_platform_device(path); 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const char *parse_device_name(struct uevent *uevent, unsigned int len) 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *name; 6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* if it's not a /dev device, nothing else to do */ 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if((uevent->major < 0) || (uevent->minor < 0)) 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* do we have a name? */ 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name = strrchr(uevent->path, '/'); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(!name) 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name++; 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* too-long names would overrun our buffer */ 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(strlen(name) > len) { 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(ERROR) << "DEVPATH=" << name << " exceeds " << len << "-character limit on filename; ignoring event"; 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return NULL; 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return name; 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define DEVPATH_LEN 96 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define MAX_DEV_NAME 64 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void handle_block_device_event(struct uevent *uevent) 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *base = "/dev/block/"; 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *name; 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char devpath[DEVPATH_LEN]; 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char **links = NULL; 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name = parse_device_name(uevent, MAX_DEV_NAME); 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!name) 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project snprintf(devpath, sizeof(devpath), "%s%s", base, name); 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strncmp(uevent->path, "/devices/", 9)) 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project links = get_block_device_symlinks(uevent); 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle_device(uevent->action, devpath, uevent->path, 1, 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->major, uevent->minor, links); 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic bool assemble_devpath(char *devpath, const char *dirname, 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *devname) 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int s = snprintf(devpath, DEVPATH_LEN, "%s/%s", dirname, devname); 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (s < 0) { 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "failed to assemble device path; ignoring event"; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (s >= DEVPATH_LEN) { 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(ERROR) << dirname << "/" << devname 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project << " exceeds " << DEVPATH_LEN << "-character limit on path; ignoring event"; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void mkdir_recursive_for_devpath(const char *devpath) 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char dir[DEVPATH_LEN]; 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char *slash; 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project strcpy(dir, devpath); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project slash = strrchr(dir, '/'); 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *slash = '\0'; 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mkdir_recursive(dir, 0755); 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void handle_generic_device_event(struct uevent *uevent) 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *base; 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *name; 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char devpath[DEVPATH_LEN] = {0}; 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char **links = NULL; 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name = parse_device_name(uevent, MAX_DEV_NAME); 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!name) 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct ueventd_subsystem *subsystem = 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ueventd_subsystem_find_by_name(uevent->subsystem); 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (subsystem) { 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char *devname; 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (subsystem->devname_src) { 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case DEVNAME_UEVENT_DEVNAME: 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project devname = uevent->device_name; 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case DEVNAME_UEVENT_DEVPATH: 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project devname = name; 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project default: 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(ERROR) << uevent->subsystem << " subsystem's devpath option is not set; ignoring event"; 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!assemble_devpath(devpath, subsystem->dirname, devname)) 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mkdir_recursive_for_devpath(devpath); 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!strncmp(uevent->subsystem, "usb", 3)) { 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strcmp(uevent->subsystem, "usb")) { 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (uevent->device_name) { 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!assemble_devpath(devpath, "/dev", uevent->device_name)) 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mkdir_recursive_for_devpath(devpath); 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* This imitates the file system that would be created 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if we were using devfs instead. 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Minors are broken up into groups of 128, starting at "001" 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int bus_id = uevent->minor / 128 + 1; 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int device_id = uevent->minor % 128 + 1; 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* build directories */ 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir("/dev/bus", 0755); 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir("/dev/bus/usb", 0755); 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d", bus_id); 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(devpath, 0755); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project snprintf(devpath, sizeof(devpath), "/dev/bus/usb/%03d/%03d", bus_id, device_id); 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* ignore other USB events */ 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!strncmp(uevent->subsystem, "graphics", 8)) { 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/graphics/"; 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!strncmp(uevent->subsystem, "drm", 3)) { 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/dri/"; 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) { 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/oncrpc/"; 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!strncmp(uevent->subsystem, "adsp", 4)) { 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/adsp/"; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!strncmp(uevent->subsystem, "msm_camera", 10)) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/msm_camera/"; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(uevent->subsystem, "input", 5)) { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/input/"; 7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(uevent->subsystem, "mtd", 3)) { 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/mtd/"; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(uevent->subsystem, "sound", 5)) { 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/snd/"; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if(!strncmp(uevent->subsystem, "misc", 4) && !strncmp(name, "log_", 4)) { 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(INFO) << "kernel logger is deprecated"; 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/log/"; 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project make_dir(base, 0755); 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project name += 4; 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project base = "/dev/"; 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project links = get_character_device_symlinks(uevent); 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!devpath[0]) 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project snprintf(devpath, sizeof(devpath), "%s%s", base, name); 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle_device(uevent->action, devpath, uevent->path, 0, 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project uevent->major, uevent->minor, links); 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void handle_device_event(struct uevent *uevent) 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strcmp(uevent->action,"add") || !strcmp(uevent->action, "change") || !strcmp(uevent->action, "online")) 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fixup_sys_perms(uevent->path, uevent->subsystem); 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!strncmp(uevent->subsystem, "block", 5)) { 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle_block_device_event(uevent); 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (!strncmp(uevent->subsystem, "platform", 8)) { 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle_platform_device_event(uevent); 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle_generic_device_event(uevent); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void load_firmware(uevent* uevent, const std::string& root, 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int fw_fd, size_t fw_size, 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int loading_fd, int data_fd) { 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Start transfer. 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android::base::WriteFully(loading_fd, "1", 1); 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Copy the firmware. 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int rc = sendfile(data_fd, fw_fd, nullptr, fw_size); 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (rc == -1) { 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "firmware: sendfile failed { '" << root << "', '" << uevent->firmware << "' }"; 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Tell the firmware whether to abort or commit. 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project const char* response = (rc != -1) ? "0" : "-1"; 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android::base::WriteFully(loading_fd, response, strlen(response)); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic int is_booting() { 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return access("/dev/.booting", F_OK) == 0; 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void process_firmware_event(uevent* uevent) { 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int booting = is_booting(); 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(INFO) << "firmware: loading '" << uevent->firmware << "' for '" << uevent->path << "'"; 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string root = android::base::StringPrintf("/sys%s", uevent->path); 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string loading = root + "/loading"; 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string data = root + "/data"; 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android::base::unique_fd loading_fd(open(loading.c_str(), O_WRONLY|O_CLOEXEC)); 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (loading_fd == -1) { 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "couldn't open firmware loading fd for " << uevent->firmware; 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android::base::unique_fd data_fd(open(data.c_str(), O_WRONLY|O_CLOEXEC)); 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (data_fd == -1) { 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "couldn't open firmware data fd for " << uevent->firmware; 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projecttry_loading_again: 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (size_t i = 0; i < arraysize(firmware_dirs); i++) { 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::string file = android::base::StringPrintf("%s/%s", firmware_dirs[i], uevent->firmware); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android::base::unique_fd fw_fd(open(file.c_str(), O_RDONLY|O_CLOEXEC)); 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct stat sb; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fw_fd != -1 && fstat(fw_fd, &sb) != -1) { 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project load_firmware(uevent, root, fw_fd, sb.st_size, loading_fd, data_fd); 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (booting) { 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If we're not fully booted, we may be missing 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // filesystems needed for firmware, wait and retry. 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::this_thread::sleep_for(100ms); 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project booting = is_booting(); 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project goto try_loading_again; 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(ERROR) << "firmware: could not find firmware for " << uevent->firmware; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Write "-1" as our response to the kernel's firmware request, since we have nothing for it. 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project write(loading_fd, "-1", 2); 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic void handle_firmware_event(uevent* uevent) { 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strcmp(uevent->subsystem, "firmware")) return; 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (strcmp(uevent->action, "add")) return; 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Loading the firmware in a child means we can do that in parallel... 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // (We ignore SIGCHLD rather than wait for our children.) 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pid_t pid = fork(); 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pid == 0) { 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Timer t; 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project process_firmware_event(uevent); 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(INFO) << "loading " << uevent->path << " took " << t; 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project _exit(EXIT_SUCCESS); 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (pid == -1) { 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PLOG(ERROR) << "could not fork to process firmware event for " << uevent->firmware; 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic bool inline should_stop_coldboot(coldboot_action_t act) 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (act == COLDBOOT_STOP || act == COLDBOOT_FINISH); 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#define UEVENT_MSG_LEN 2048 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic inline coldboot_action_t handle_device_fd_with( 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::function<coldboot_action_t(uevent* uevent)> handle_uevent) 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project char msg[UEVENT_MSG_LEN+2]; 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int n; 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while ((n = uevent_kernel_multicast_recv(device_fd, msg, UEVENT_MSG_LEN)) > 0) { 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(n >= UEVENT_MSG_LEN) /* overflow -- discard */ 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg[n] = '\0'; 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project msg[n+1] = '\0'; 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct uevent uevent; 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project parse_event(msg, &uevent); 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project coldboot_action_t act = handle_uevent(&uevent); 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (should_stop_coldboot(act)) 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return act; 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return COLDBOOT_CONTINUE; 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectcoldboot_action_t handle_device_fd(coldboot_callback fn) 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project coldboot_action_t ret = handle_device_fd_with( 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project [&](uevent* uevent) -> coldboot_action_t { 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (selinux_status_updated() > 0) { 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct selabel_handle *sehandle2; 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sehandle2 = selinux_android_file_context_handle(); 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (sehandle2) { 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selabel_close(sehandle); 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sehandle = sehandle2; 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // default is to always create the devices 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project coldboot_action_t act = COLDBOOT_CREATE; 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fn) { 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project act = fn(uevent); 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (act == COLDBOOT_CREATE || act == COLDBOOT_STOP) { 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle_device_event(uevent); 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handle_firmware_event(uevent); 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return act; 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }); 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ret; 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* Coldboot walks parts of the /sys tree and pokes the uevent files 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** to cause the kernel to regenerate device add events that happened 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** before init's device manager was started 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** We drain any pending events from the netlink socket every time 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** we poke another uevent file to make sure we don't overrun the 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project** socket's buffer. 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project*/ 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic coldboot_action_t do_coldboot(DIR *d, coldboot_callback fn) 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct dirent *de; 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int dfd, fd; 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project coldboot_action_t act = COLDBOOT_CONTINUE; 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project dfd = dirfd(d); 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = openat(dfd, "uevent", O_WRONLY); 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fd >= 0) { 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project write(fd, "add\n", 4); 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(fd); 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project act = handle_device_fd(fn); 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (should_stop_coldboot(act)) 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return act; 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!should_stop_coldboot(act) && (de = readdir(d))) { 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project DIR *d2; 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(de->d_type != DT_DIR || de->d_name[0] == '.') 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY); 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(fd < 0) 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project d2 = fdopendir(fd); 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if(d2 == 0) 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(fd); 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else { 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project act = do_coldboot(d2, fn); 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project closedir(d2); 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // default is always to continue looking for uevents 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return act; 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic coldboot_action_t coldboot(const char *path, coldboot_callback fn) 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project std::unique_ptr<DIR, decltype(&closedir)> d(opendir(path), closedir); 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (d) { 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return do_coldboot(d.get(), fn); 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return COLDBOOT_CONTINUE; 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectvoid device_init(const char* path, coldboot_callback fn) { 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project sehandle = selinux_android_file_context_handle(); 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project selinux_status_open(true); 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* is 256K enough? udev uses 16MB! */ 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project device_fd.reset(uevent_open_socket(256*1024, true)); 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (device_fd == -1) { 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project fcntl(device_fd, F_SETFL, O_NONBLOCK); 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (access(COLDBOOT_DONE, F_OK) == 0) { 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(VERBOSE) << "Skipping coldboot, already done!"; 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Timer t; 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project coldboot_action_t act; 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!path) { 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project act = coldboot("/sys/class", fn); 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!should_stop_coldboot(act)) { 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project act = coldboot("/sys/block", fn); 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!should_stop_coldboot(act)) { 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project act = coldboot("/sys/devices", fn); 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project act = coldboot(path, fn); 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1031fc01794f33057862a361a0d0113630c58befc21bKenny Root // If we have a callback, then do as it says. If no, then the default is 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to always create COLDBOOT_DONE file. 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!fn || (act == COLDBOOT_FINISH)) { 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project close(open(COLDBOOT_DONE, O_WRONLY|O_CREAT|O_CLOEXEC, 0000)); 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG(INFO) << "Coldboot took " << t; 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1040fc01794f33057862a361a0d0113630c58befc21bKenny Rootvoid device_close() { 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project destroy_platform_devices(); 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project device_fd.reset(); 1043fc01794f33057862a361a0d0113630c58befc21bKenny Root} 1044fc01794f33057862a361a0d0113630c58befc21bKenny Root 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint get_device_fd() { 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return device_fd; 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project