summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
Diffstat (limited to 'init')
-rw-r--r--init/Android.bp1
-rw-r--r--init/init.cpp3
-rw-r--r--init/modalias_handler.cpp163
-rw-r--r--init/modalias_handler.h48
-rw-r--r--init/property_service.cpp1
-rw-r--r--init/uevent.h1
-rw-r--r--init/uevent_listener.cpp4
-rw-r--r--init/ueventd.cpp13
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
33namespace android {
34namespace init {
35
36Result<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
64Result<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
83ModaliasHandler::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
103Result<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
121Result<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
142void 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
26namespace android {
27namespace init {
28
29class 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
107class ColdBoot { 108class 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 });