system/core
リビジョン | 35a700179b56c2c110c4626e19536bcd3342589a (tree) |
---|---|
日時 | 2019-12-17 14:24:56 |
作者 | Michael Goffioul <michael.goffioul@linc...> |
コミッター | Chih-Wei Huang |
ueventd: auto load modules on uevents
@@ -18,6 +18,8 @@ | ||
18 | 18 | |
19 | 19 | #include <fnmatch.h> |
20 | 20 | #include <sys/syscall.h> |
21 | +#include <sys/utsname.h> | |
22 | +#include <unistd.h> | |
21 | 23 | |
22 | 24 | #include <algorithm> |
23 | 25 | #include <functional> |
@@ -33,6 +35,13 @@ | ||
33 | 35 | namespace android { |
34 | 36 | namespace init { |
35 | 37 | |
38 | +static const std::string base_paths[] = { | |
39 | + "/system/lib/modules/", | |
40 | + "/vendor/lib/modules/", | |
41 | + "/lib/modules/", | |
42 | + "/odm/lib/modules/", | |
43 | +}; | |
44 | + | |
36 | 45 | Result<Success> ModaliasHandler::ParseDepCallback(std::vector<std::string>&& args) { |
37 | 46 | std::vector<std::string> deps; |
38 | 47 |
@@ -83,26 +92,60 @@ Result<Success> ModaliasHandler::ParseAliasCallback(std::vector<std::string>&& a | ||
83 | 92 | ModaliasHandler::ModaliasHandler() { |
84 | 93 | using namespace std::placeholders; |
85 | 94 | |
86 | - static const std::string base_paths[] = { | |
87 | - "/vendor/lib/modules/", | |
88 | - "/lib/modules/", | |
89 | - "/odm/lib/modules/", | |
90 | - }; | |
95 | + struct utsname uts; | |
96 | + uname(&uts); | |
97 | + release_ = uts.release; | |
91 | 98 | |
92 | 99 | Parser alias_parser; |
93 | 100 | auto alias_callback = std::bind(&ModaliasHandler::ParseAliasCallback, this, _1); |
94 | 101 | alias_parser.AddSingleLineParser("alias", alias_callback); |
95 | - for (const auto& base_path : base_paths) alias_parser.ParseConfig(base_path + "modules.alias"); | |
102 | + for (const auto& base_path : base_paths) { | |
103 | + alias_parser.ParseConfig(base_path + release_ + "/modules.alias"); | |
104 | + alias_parser.ParseConfig(base_path + "modules.alias"); | |
105 | + } | |
96 | 106 | |
97 | 107 | Parser dep_parser; |
98 | 108 | auto dep_callback = std::bind(&ModaliasHandler::ParseDepCallback, this, _1); |
99 | 109 | dep_parser.AddSingleLineParser("", dep_callback); |
100 | - for (const auto& base_path : base_paths) dep_parser.ParseConfig(base_path + "modules.dep"); | |
110 | + for (const auto& base_path : base_paths) { | |
111 | + dep_parser.ParseConfig(base_path + release_ + "/modules.dep"); | |
112 | + dep_parser.ParseConfig(base_path + "modules.dep"); | |
113 | + } | |
114 | + | |
115 | + auto blacklist_callback = [] (auto args, std::set<std::string>* v_) -> Result<Success> { | |
116 | + if (args.size() < 2) { | |
117 | + return Error() << "blacklist/deferred lines must have 2 entries"; | |
118 | + } | |
119 | + | |
120 | + v_->emplace(args[1]); | |
121 | + return Success(); | |
122 | + }; | |
123 | + Parser blacklist_parser; | |
124 | + blacklist_parser.AddSingleLineParser("blacklist", std::bind(blacklist_callback, _1, &this->modules_to_blacklist_)); | |
125 | + blacklist_parser.AddSingleLineParser("deferred", std::bind(blacklist_callback, _1, &this->modules_to_defer_)); | |
126 | + blacklist_parser.ParseConfig("/system/etc/modules.blacklist"); | |
127 | +} | |
128 | + | |
129 | +std::string ModaliasHandler::GetModulePath(const std::string& path_name) { | |
130 | + if (path_name[0] != '/') { | |
131 | + std::string module_path_name; | |
132 | + for (const auto& base_path : base_paths) { | |
133 | + module_path_name = base_path + release_ + "/" + path_name; | |
134 | + if (access(module_path_name.c_str(), F_OK) == 0) { | |
135 | + return module_path_name; | |
136 | + } | |
137 | + module_path_name = base_path + path_name; | |
138 | + if (access(module_path_name.c_str(), F_OK) == 0) { | |
139 | + return module_path_name; | |
140 | + } | |
141 | + } | |
142 | + } | |
143 | + return path_name; | |
101 | 144 | } |
102 | 145 | |
103 | 146 | Result<Success> ModaliasHandler::Insmod(const std::string& path_name, const std::string& args) { |
104 | 147 | base::unique_fd fd( |
105 | - TEMP_FAILURE_RETRY(open(path_name.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC))); | |
148 | + TEMP_FAILURE_RETRY(open(GetModulePath(path_name).c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC))); | |
106 | 149 | if (fd == -1) return ErrnoError() << "Could not open module '" << path_name << "'"; |
107 | 150 | |
108 | 151 | int ret = syscall(__NR_finit_module, fd.get(), args.c_str(), 0); |
@@ -145,6 +188,17 @@ void ModaliasHandler::HandleUevent(const Uevent& uevent) { | ||
145 | 188 | for (const auto& [alias, module] : module_aliases_) { |
146 | 189 | if (fnmatch(alias.c_str(), uevent.modalias.c_str(), 0) != 0) continue; // Keep looking |
147 | 190 | |
191 | + if (modules_to_blacklist_.find(module) != modules_to_blacklist_.end()) { | |
192 | + // skip blacklisted module | |
193 | + continue; | |
194 | + } | |
195 | + | |
196 | + if (modules_to_defer_.find(module) != modules_to_defer_.end()) { | |
197 | + // defer module load until cold boot phase is done | |
198 | + deferred_modules_.emplace(module); | |
199 | + continue; | |
200 | + } | |
201 | + | |
148 | 202 | LOG(DEBUG) << "Loading kernel module '" << module << "' for alias '" << uevent.modalias |
149 | 203 | << "'"; |
150 | 204 |
@@ -155,9 +209,19 @@ void ModaliasHandler::HandleUevent(const Uevent& uevent) { | ||
155 | 209 | } |
156 | 210 | |
157 | 211 | // loading was successful |
158 | - return; | |
159 | 212 | } |
160 | 213 | } |
161 | 214 | |
215 | +void ModaliasHandler::ColdbootDone() { | |
216 | + for (const auto& module : deferred_modules_) { | |
217 | + LOG(INFO) << "Loading kernel module '" << module << "' [deferred]"; | |
218 | + if (auto result = InsmodWithDeps(module, ""); !result) { | |
219 | + LOG(ERROR) << "Cannot load module: " << result.error(); | |
220 | + } | |
221 | + } | |
222 | + modules_to_defer_.clear(); | |
223 | + deferred_modules_.clear(); | |
224 | +} | |
225 | + | |
162 | 226 | } // namespace init |
163 | 227 | } // namespace android |
@@ -16,6 +16,7 @@ | ||
16 | 16 | |
17 | 17 | #pragma once |
18 | 18 | |
19 | +#include <set> | |
19 | 20 | #include <string> |
20 | 21 | #include <unordered_map> |
21 | 22 | #include <vector> |
@@ -33,6 +34,7 @@ class ModaliasHandler : public UeventHandler { | ||
33 | 34 | virtual ~ModaliasHandler() = default; |
34 | 35 | |
35 | 36 | void HandleUevent(const Uevent& uevent) override; |
37 | + void ColdbootDone() override; | |
36 | 38 | |
37 | 39 | private: |
38 | 40 | Result<Success> InsmodWithDeps(const std::string& module_name, const std::string& args); |
@@ -41,8 +43,15 @@ class ModaliasHandler : public UeventHandler { | ||
41 | 43 | Result<Success> ParseDepCallback(std::vector<std::string>&& args); |
42 | 44 | Result<Success> ParseAliasCallback(std::vector<std::string>&& args); |
43 | 45 | |
46 | + std::string GetModulePath(const std::string& path_name); | |
47 | + | |
44 | 48 | std::vector<std::pair<std::string, std::string>> module_aliases_; |
45 | 49 | std::unordered_map<std::string, std::vector<std::string>> module_deps_; |
50 | + std::set<std::string> modules_to_defer_; | |
51 | + std::set<std::string> modules_to_blacklist_; | |
52 | + std::set<std::string> deferred_modules_; | |
53 | + | |
54 | + std::string release_; | |
46 | 55 | }; |
47 | 56 | |
48 | 57 | } // namespace init |
@@ -1,4 +1,5 @@ | ||
1 | 1 | firmware_directories /system/lib/firmware |
2 | +modalias_handling enabled | |
2 | 3 | uevent_socket_rcvbuf_size 16M |
3 | 4 | |
4 | 5 | subsystem graphics |