diff options
Diffstat (limited to 'init')
-rw-r--r-- | init/Android.bp | 1 | ||||
-rw-r--r-- | init/init.cpp | 3 | ||||
-rw-r--r-- | init/modalias_handler.cpp | 163 | ||||
-rw-r--r-- | init/modalias_handler.h | 48 | ||||
-rw-r--r-- | init/property_service.cpp | 1 | ||||
-rw-r--r-- | init/uevent.h | 1 | ||||
-rw-r--r-- | init/uevent_listener.cpp | 4 | ||||
-rw-r--r-- | init/ueventd.cpp | 13 |
8 files changed, 231 insertions, 3 deletions
diff --git a/init/Android.bp b/init/Android.bp index c02b8d187..660d58676 100644 --- a/init/Android.bp +++ b/init/Android.bp | |||
@@ -108,6 +108,7 @@ cc_library_static { | |||
108 | "import_parser.cpp", | 108 | "import_parser.cpp", |
109 | "init.cpp", | 109 | "init.cpp", |
110 | "keychords.cpp", | 110 | "keychords.cpp", |
111 | "modalias_handler.cpp", | ||
111 | "parser.cpp", | 112 | "parser.cpp", |
112 | "persistent_properties.cpp", | 113 | "persistent_properties.cpp", |
113 | "persistent_properties.proto", | 114 | "persistent_properties.proto", |
diff --git a/init/init.cpp b/init/init.cpp index 6569871b8..73194bdd9 100644 --- a/init/init.cpp +++ b/init/init.cpp | |||
@@ -119,6 +119,9 @@ static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_ | |||
119 | if (!parser.ParseConfig("/product/etc/init")) { | 119 | if (!parser.ParseConfig("/product/etc/init")) { |
120 | late_import_paths.emplace_back("/product/etc/init"); | 120 | late_import_paths.emplace_back("/product/etc/init"); |
121 | } | 121 | } |
122 | if (!parser.ParseConfig("/product-services/etc/init")) { | ||
123 | late_import_paths.emplace_back("/product-services/etc/init"); | ||
124 | } | ||
122 | if (!parser.ParseConfig("/odm/etc/init")) { | 125 | if (!parser.ParseConfig("/odm/etc/init")) { |
123 | late_import_paths.emplace_back("/odm/etc/init"); | 126 | late_import_paths.emplace_back("/odm/etc/init"); |
124 | } | 127 | } |
diff --git a/init/modalias_handler.cpp b/init/modalias_handler.cpp new file mode 100644 index 000000000..1734a7e0f --- /dev/null +++ b/init/modalias_handler.cpp | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include "modalias_handler.h" | ||
18 | |||
19 | #include <fnmatch.h> | ||
20 | #include <sys/syscall.h> | ||
21 | |||
22 | #include <algorithm> | ||
23 | #include <functional> | ||
24 | #include <string> | ||
25 | #include <vector> | ||
26 | |||
27 | #include <android-base/chrono_utils.h> | ||
28 | #include <android-base/logging.h> | ||
29 | #include <android-base/unique_fd.h> | ||
30 | |||
31 | #include "parser.h" | ||
32 | |||
33 | namespace android { | ||
34 | namespace init { | ||
35 | |||
36 | Result<Success> ModaliasHandler::ParseDepCallback(std::vector<std::string>&& args) { | ||
37 | std::vector<std::string> deps; | ||
38 | |||
39 | // Set first item as our modules path | ||
40 | std::string::size_type pos = args[0].find(':'); | ||
41 | if (pos != std::string::npos) { | ||
42 | deps.emplace_back(args[0].substr(0, pos)); | ||
43 | } else { | ||
44 | return Error() << "dependency lines must start with name followed by ':'"; | ||
45 | } | ||
46 | |||
47 | // Remaining items are dependencies of our module | ||
48 | for (auto arg = args.begin() + 1; arg != args.end(); ++arg) { | ||
49 | deps.push_back(*arg); | ||
50 | } | ||
51 | |||
52 | // Key is striped module name to match names in alias file | ||
53 | std::size_t start = args[0].find_last_of("/"); | ||
54 | std::size_t end = args[0].find(".ko:"); | ||
55 | if ((end - start) <= 1) return Error() << "malformed dependency line"; | ||
56 | auto mod_name = args[0].substr(start + 1, (end - start) - 1); | ||
57 | // module names can have '-', but their file names will have '_' | ||
58 | std::replace(mod_name.begin(), mod_name.end(), '-', '_'); | ||
59 | this->module_deps_[mod_name] = deps; | ||
60 | |||
61 | return Success(); | ||
62 | } | ||
63 | |||
64 | Result<Success> ModaliasHandler::ParseAliasCallback(std::vector<std::string>&& args) { | ||
65 | auto it = args.begin(); | ||
66 | const std::string& type = *it++; | ||
67 | |||
68 | if (type != "alias") { | ||
69 | return Error() << "we only handle alias lines, got: " << type; | ||
70 | } | ||
71 | |||
72 | if (args.size() != 3) { | ||
73 | return Error() << "alias lines must have 3 entries"; | ||
74 | } | ||
75 | |||
76 | std::string& alias = *it++; | ||
77 | std::string& module_name = *it++; | ||
78 | this->module_aliases_.emplace_back(alias, module_name); | ||
79 | |||
80 | return Success(); | ||
81 | } | ||
82 | |||
83 | ModaliasHandler::ModaliasHandler() { | ||
84 | using namespace std::placeholders; | ||
85 | |||
86 | static const std::string base_paths[] = { | ||
87 | "/vendor/lib/modules/", | ||
88 | "/lib/modules/", | ||
89 | "/odm/lib/modules/", | ||
90 | }; | ||
91 | |||
92 | Parser alias_parser; | ||
93 | auto alias_callback = std::bind(&ModaliasHandler::ParseAliasCallback, this, _1); | ||
94 | alias_parser.AddSingleLineParser("alias", alias_callback); | ||
95 | for (const auto& base_path : base_paths) alias_parser.ParseConfig(base_path + "modules.alias"); | ||
96 | |||
97 | Parser dep_parser; | ||
98 | auto dep_callback = std::bind(&ModaliasHandler::ParseDepCallback, this, _1); | ||
99 | dep_parser.AddSingleLineParser("", dep_callback); | ||
100 | for (const auto& base_path : base_paths) dep_parser.ParseConfig(base_path + "modules.dep"); | ||
101 | } | ||
102 | |||
103 | Result<Success> ModaliasHandler::Insmod(const std::string& path_name, const std::string& args) { | ||
104 | base::unique_fd fd( | ||
105 | TEMP_FAILURE_RETRY(open(path_name.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC))); | ||
106 | if (fd == -1) return ErrnoError() << "Could not open module '" << path_name << "'"; | ||
107 | |||
108 | int ret = syscall(__NR_finit_module, fd.get(), args.c_str(), 0); | ||
109 | if (ret != 0) { | ||
110 | if (errno == EEXIST) { | ||
111 | // Module already loaded | ||
112 | return Success(); | ||
113 | } | ||
114 | return ErrnoError() << "Failed to insmod '" << path_name << "' with args '" << args << "'"; | ||
115 | } | ||
116 | |||
117 | LOG(INFO) << "Loaded kernel module " << path_name; | ||
118 | return Success(); | ||
119 | } | ||
120 | |||
121 | Result<Success> ModaliasHandler::InsmodWithDeps(const std::string& module_name, | ||
122 | const std::string& args) { | ||
123 | if (module_name.empty()) { | ||
124 | return Error() << "Need valid module name"; | ||
125 | } | ||
126 | |||
127 | auto it = module_deps_.find(module_name); | ||
128 | if (it == module_deps_.end()) { | ||
129 | return Error() << "Module '" << module_name << "' not in dependency file"; | ||
130 | } | ||
131 | auto& dependencies = it->second; | ||
132 | |||
133 | // load module dependencies in reverse order | ||
134 | for (auto dep = dependencies.rbegin(); dep != dependencies.rend() - 1; ++dep) { | ||
135 | if (auto result = Insmod(*dep, ""); !result) return result; | ||
136 | } | ||
137 | |||
138 | // load target module itself with args | ||
139 | return Insmod(dependencies[0], args); | ||
140 | } | ||
141 | |||
142 | void ModaliasHandler::HandleModaliasEvent(const Uevent& uevent) { | ||
143 | if (uevent.modalias.empty()) return; | ||
144 | |||
145 | for (const auto& [alias, module] : module_aliases_) { | ||
146 | if (fnmatch(alias.c_str(), uevent.modalias.c_str(), 0) != 0) continue; // Keep looking | ||
147 | |||
148 | LOG(DEBUG) << "Loading kernel module '" << module << "' for alias '" << uevent.modalias | ||
149 | << "'"; | ||
150 | |||
151 | if (auto result = InsmodWithDeps(module, ""); !result) { | ||
152 | LOG(ERROR) << "Cannot load module: " << result.error(); | ||
153 | // try another one since there may be another match | ||
154 | continue; | ||
155 | } | ||
156 | |||
157 | // loading was successful | ||
158 | return; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | } // namespace init | ||
163 | } // namespace android | ||
diff --git a/init/modalias_handler.h b/init/modalias_handler.h new file mode 100644 index 000000000..e79da3275 --- /dev/null +++ b/init/modalias_handler.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #pragma once | ||
18 | |||
19 | #include "result.h" | ||
20 | #include "uevent.h" | ||
21 | |||
22 | #include <string> | ||
23 | #include <unordered_map> | ||
24 | #include <vector> | ||
25 | |||
26 | namespace android { | ||
27 | namespace init { | ||
28 | |||
29 | class ModaliasHandler { | ||
30 | public: | ||
31 | ModaliasHandler(); | ||
32 | ~ModaliasHandler(){}; | ||
33 | |||
34 | void HandleModaliasEvent(const Uevent& uevent); | ||
35 | |||
36 | private: | ||
37 | Result<Success> InsmodWithDeps(const std::string& module_name, const std::string& args); | ||
38 | Result<Success> Insmod(const std::string& path_name, const std::string& args); | ||
39 | |||
40 | Result<Success> ParseDepCallback(std::vector<std::string>&& args); | ||
41 | Result<Success> ParseAliasCallback(std::vector<std::string>&& args); | ||
42 | |||
43 | std::vector<std::pair<std::string, std::string>> module_aliases_; | ||
44 | std::unordered_map<std::string, std::vector<std::string>> module_deps_; | ||
45 | }; | ||
46 | |||
47 | } // namespace init | ||
48 | } // namespace android | ||
diff --git a/init/property_service.cpp b/init/property_service.cpp index d1c427dba..c0d811fc6 100644 --- a/init/property_service.cpp +++ b/init/property_service.cpp | |||
@@ -691,6 +691,7 @@ void property_load_boot_defaults() { | |||
691 | } | 691 | } |
692 | } | 692 | } |
693 | load_properties_from_file("/product/build.prop", NULL); | 693 | load_properties_from_file("/product/build.prop", NULL); |
694 | load_properties_from_file("/product-services/build.prop", NULL); | ||
694 | load_properties_from_file("/odm/default.prop", NULL); | 695 | load_properties_from_file("/odm/default.prop", NULL); |
695 | load_properties_from_file("/vendor/default.prop", NULL); | 696 | load_properties_from_file("/vendor/default.prop", NULL); |
696 | 697 | ||
diff --git a/init/uevent.h b/init/uevent.h index c4fd9454c..dc35fd968 100644 --- a/init/uevent.h +++ b/init/uevent.h | |||
@@ -29,6 +29,7 @@ struct Uevent { | |||
29 | std::string firmware; | 29 | std::string firmware; |
30 | std::string partition_name; | 30 | std::string partition_name; |
31 | std::string device_name; | 31 | std::string device_name; |
32 | std::string modalias; | ||
32 | int partition_num; | 33 | int partition_num; |
33 | int major; | 34 | int major; |
34 | int minor; | 35 | int minor; |
diff --git a/init/uevent_listener.cpp b/init/uevent_listener.cpp index 24b14c44d..8cf212867 100644 --- a/init/uevent_listener.cpp +++ b/init/uevent_listener.cpp | |||
@@ -39,6 +39,7 @@ static void ParseEvent(const char* msg, Uevent* uevent) { | |||
39 | uevent->firmware.clear(); | 39 | uevent->firmware.clear(); |
40 | uevent->partition_name.clear(); | 40 | uevent->partition_name.clear(); |
41 | uevent->device_name.clear(); | 41 | uevent->device_name.clear(); |
42 | uevent->modalias.clear(); | ||
42 | // currently ignoring SEQNUM | 43 | // currently ignoring SEQNUM |
43 | while (*msg) { | 44 | while (*msg) { |
44 | if (!strncmp(msg, "ACTION=", 7)) { | 45 | if (!strncmp(msg, "ACTION=", 7)) { |
@@ -68,6 +69,9 @@ static void ParseEvent(const char* msg, Uevent* uevent) { | |||
68 | } else if (!strncmp(msg, "DEVNAME=", 8)) { | 69 | } else if (!strncmp(msg, "DEVNAME=", 8)) { |
69 | msg += 8; | 70 | msg += 8; |
70 | uevent->device_name = msg; | 71 | uevent->device_name = msg; |
72 | } else if (!strncmp(msg, "MODALIAS=", 9)) { | ||
73 | msg += 9; | ||
74 | uevent->modalias = msg; | ||
71 | } | 75 | } |
72 | 76 | ||
73 | // advance to after the next \0 | 77 | // advance to after the next \0 |
diff --git a/init/ueventd.cpp b/init/ueventd.cpp index cd45a3fb7..e9d829b51 100644 --- a/init/ueventd.cpp +++ b/init/ueventd.cpp | |||
@@ -36,6 +36,7 @@ | |||
36 | 36 | ||
37 | #include "devices.h" | 37 | #include "devices.h" |
38 | #include "firmware_handler.h" | 38 | #include "firmware_handler.h" |
39 | #include "modalias_handler.h" | ||
39 | #include "selinux.h" | 40 | #include "selinux.h" |
40 | #include "uevent_listener.h" | 41 | #include "uevent_listener.h" |
41 | #include "ueventd_parser.h" | 42 | #include "ueventd_parser.h" |
@@ -106,9 +107,11 @@ namespace init { | |||
106 | 107 | ||
107 | class ColdBoot { | 108 | class ColdBoot { |
108 | public: | 109 | public: |
109 | ColdBoot(UeventListener& uevent_listener, DeviceHandler& device_handler) | 110 | ColdBoot(UeventListener& uevent_listener, DeviceHandler& device_handler, |
111 | ModaliasHandler& modalias_handler) | ||
110 | : uevent_listener_(uevent_listener), | 112 | : uevent_listener_(uevent_listener), |
111 | device_handler_(device_handler), | 113 | device_handler_(device_handler), |
114 | modalias_handler_(modalias_handler), | ||
112 | num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4) {} | 115 | num_handler_subprocesses_(std::thread::hardware_concurrency() ?: 4) {} |
113 | 116 | ||
114 | void Run(); | 117 | void Run(); |
@@ -122,6 +125,7 @@ class ColdBoot { | |||
122 | 125 | ||
123 | UeventListener& uevent_listener_; | 126 | UeventListener& uevent_listener_; |
124 | DeviceHandler& device_handler_; | 127 | DeviceHandler& device_handler_; |
128 | ModaliasHandler& modalias_handler_; | ||
125 | 129 | ||
126 | unsigned int num_handler_subprocesses_; | 130 | unsigned int num_handler_subprocesses_; |
127 | std::vector<Uevent> uevent_queue_; | 131 | std::vector<Uevent> uevent_queue_; |
@@ -133,6 +137,7 @@ void ColdBoot::UeventHandlerMain(unsigned int process_num, unsigned int total_pr | |||
133 | for (unsigned int i = process_num; i < uevent_queue_.size(); i += total_processes) { | 137 | for (unsigned int i = process_num; i < uevent_queue_.size(); i += total_processes) { |
134 | auto& uevent = uevent_queue_[i]; | 138 | auto& uevent = uevent_queue_[i]; |
135 | device_handler_.HandleDeviceEvent(uevent); | 139 | device_handler_.HandleDeviceEvent(uevent); |
140 | modalias_handler_.HandleModaliasEvent(uevent); | ||
136 | } | 141 | } |
137 | _exit(EXIT_SUCCESS); | 142 | _exit(EXIT_SUCCESS); |
138 | } | 143 | } |
@@ -230,6 +235,7 @@ int ueventd_main(int argc, char** argv) { | |||
230 | SelabelInitialize(); | 235 | SelabelInitialize(); |
231 | 236 | ||
232 | DeviceHandler device_handler; | 237 | DeviceHandler device_handler; |
238 | ModaliasHandler modalias_handler; | ||
233 | UeventListener uevent_listener; | 239 | UeventListener uevent_listener; |
234 | 240 | ||
235 | { | 241 | { |
@@ -251,7 +257,7 @@ int ueventd_main(int argc, char** argv) { | |||
251 | } | 257 | } |
252 | 258 | ||
253 | if (access(COLDBOOT_DONE, F_OK) != 0) { | 259 | if (access(COLDBOOT_DONE, F_OK) != 0) { |
254 | ColdBoot cold_boot(uevent_listener, device_handler); | 260 | ColdBoot cold_boot(uevent_listener, device_handler, modalias_handler); |
255 | cold_boot.Run(); | 261 | cold_boot.Run(); |
256 | } | 262 | } |
257 | 263 | ||
@@ -262,8 +268,9 @@ int ueventd_main(int argc, char** argv) { | |||
262 | while (waitpid(-1, nullptr, WNOHANG) > 0) { | 268 | while (waitpid(-1, nullptr, WNOHANG) > 0) { |
263 | } | 269 | } |
264 | 270 | ||
265 | uevent_listener.Poll([&device_handler](const Uevent& uevent) { | 271 | uevent_listener.Poll([&device_handler, &modalias_handler](const Uevent& uevent) { |
266 | HandleFirmwareEvent(uevent); | 272 | HandleFirmwareEvent(uevent); |
273 | modalias_handler.HandleModaliasEvent(uevent); | ||
267 | device_handler.HandleDeviceEvent(uevent); | 274 | device_handler.HandleDeviceEvent(uevent); |
268 | return ListenerAction::kContinue; | 275 | return ListenerAction::kContinue; |
269 | }); | 276 | }); |