libmodprobe: parse kernel command line for module options
Bug: 145808811
Test: atest libmodprobe_tests, verify on flame
Change-Id: I0b41b1610fe13ae526d38f029da888f6f0d8a02d
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index 6b9107f..f22bbf1 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -238,6 +238,80 @@
return;
}
+void Modprobe::AddOption(const std::string& module_name, const std::string& option_name,
+ const std::string& value) {
+ auto canonical_name = MakeCanonical(module_name);
+ auto options_iter = module_options_.find(canonical_name);
+ auto option_str = option_name + "=" + value;
+ if (options_iter != module_options_.end()) {
+ options_iter->second = options_iter->second + " " + option_str;
+ } else {
+ module_options_.emplace(canonical_name, option_str);
+ }
+}
+
+void Modprobe::ParseKernelCmdlineOptions(void) {
+ std::string cmdline = GetKernelCmdline();
+ std::string module_name = "";
+ std::string option_name = "";
+ std::string value = "";
+ bool in_module = true;
+ bool in_option = false;
+ bool in_value = false;
+ bool in_quotes = false;
+ int start = 0;
+
+ for (int i = 0; i < cmdline.size(); i++) {
+ if (cmdline[i] == '"') {
+ in_quotes = !in_quotes;
+ }
+
+ if (in_quotes) continue;
+
+ if (cmdline[i] == ' ') {
+ if (in_value) {
+ value = cmdline.substr(start, i - start);
+ if (!module_name.empty() && !option_name.empty()) {
+ AddOption(module_name, option_name, value);
+ }
+ }
+ module_name = "";
+ option_name = "";
+ value = "";
+ in_value = false;
+ start = i + 1;
+ in_module = true;
+ continue;
+ }
+
+ if (cmdline[i] == '.') {
+ if (in_module) {
+ module_name = cmdline.substr(start, i - start);
+ start = i + 1;
+ in_module = false;
+ }
+ in_option = true;
+ continue;
+ }
+
+ if (cmdline[i] == '=') {
+ if (in_option) {
+ option_name = cmdline.substr(start, i - start);
+ start = i + 1;
+ in_option = false;
+ }
+ in_value = true;
+ continue;
+ }
+ }
+ if (in_value && !in_quotes) {
+ value = cmdline.substr(start, cmdline.size() - start);
+ if (!module_name.empty() && !option_name.empty()) {
+ AddOption(module_name, option_name, value);
+ }
+ }
+}
+
Modprobe::Modprobe(const std::vector<std::string>& base_paths) {
using namespace std::placeholders;
@@ -261,6 +335,7 @@
ParseCfg(base_path + "/modules.blacklist", blacklist_callback);
}
+ ParseKernelCmdlineOptions();
android::base::SetMinimumLogSeverity(android::base::INFO);
}