diff options
Diffstat (limited to 'init/modalias_handler.cpp')
| -rw-r--r-- | init/modalias_handler.cpp | 135 | 
1 files changed, 4 insertions, 131 deletions
diff --git a/init/modalias_handler.cpp b/init/modalias_handler.cpp index a511156280..07b05d8b42 100644 --- a/init/modalias_handler.cpp +++ b/init/modalias_handler.cpp @@ -16,147 +16,20 @@  #include "modalias_handler.h" -#include <fnmatch.h> -#include <sys/syscall.h> - -#include <algorithm> -#include <functional>  #include <string>  #include <vector> -#include <android-base/chrono_utils.h> -#include <android-base/logging.h> -#include <android-base/unique_fd.h> - -#include "parser.h" +#include <modprobe/modprobe.h>  namespace android {  namespace init { -Result<void> ModaliasHandler::ParseDepCallback(std::vector<std::string>&& args) { -    std::vector<std::string> deps; - -    // Set first item as our modules path -    std::string::size_type pos = args[0].find(':'); -    if (pos != std::string::npos) { -        deps.emplace_back(args[0].substr(0, pos)); -    } else { -        return Error() << "dependency lines must start with name followed by ':'"; -    } - -    // Remaining items are dependencies of our module -    for (auto arg = args.begin() + 1; arg != args.end(); ++arg) { -        deps.push_back(*arg); -    } - -    // Key is striped module name to match names in alias file -    std::size_t start = args[0].find_last_of('/'); -    std::size_t end = args[0].find(".ko:"); -    if ((end - start) <= 1) return Error() << "malformed dependency line"; -    auto mod_name = args[0].substr(start + 1, (end - start) - 1); -    // module names can have '-', but their file names will have '_' -    std::replace(mod_name.begin(), mod_name.end(), '-', '_'); -    this->module_deps_[mod_name] = deps; - -    return {}; -} - -Result<void> ModaliasHandler::ParseAliasCallback(std::vector<std::string>&& args) { -    auto it = args.begin(); -    const std::string& type = *it++; - -    if (type != "alias") { -        return Error() << "we only handle alias lines, got: " << type; -    } - -    if (args.size() != 3) { -        return Error() << "alias lines must have 3 entries"; -    } - -    std::string& alias = *it++; -    std::string& module_name = *it++; -    this->module_aliases_.emplace_back(alias, module_name); - -    return {}; -} - -ModaliasHandler::ModaliasHandler() { -    using namespace std::placeholders; - -    static const std::string base_paths[] = { -            "/vendor/lib/modules/", -            "/lib/modules/", -            "/odm/lib/modules/", -    }; - -    Parser alias_parser; -    auto alias_callback = std::bind(&ModaliasHandler::ParseAliasCallback, this, _1); -    alias_parser.AddSingleLineParser("alias", alias_callback); -    for (const auto& base_path : base_paths) alias_parser.ParseConfig(base_path + "modules.alias"); - -    Parser dep_parser; -    auto dep_callback = std::bind(&ModaliasHandler::ParseDepCallback, this, _1); -    dep_parser.AddSingleLineParser("", dep_callback); -    for (const auto& base_path : base_paths) dep_parser.ParseConfig(base_path + "modules.dep"); -} - -Result<void> ModaliasHandler::Insmod(const std::string& path_name, const std::string& args) { -    base::unique_fd fd( -            TEMP_FAILURE_RETRY(open(path_name.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC))); -    if (fd == -1) return ErrnoError() << "Could not open module '" << path_name << "'"; - -    int ret = syscall(__NR_finit_module, fd.get(), args.c_str(), 0); -    if (ret != 0) { -        if (errno == EEXIST) { -            // Module already loaded -            return {}; -        } -        return ErrnoError() << "Failed to insmod '" << path_name << "' with args '" << args << "'"; -    } - -    LOG(INFO) << "Loaded kernel module " << path_name; -    return {}; -} - -Result<void> ModaliasHandler::InsmodWithDeps(const std::string& module_name, -                                             const std::string& args) { -    if (module_name.empty()) { -        return Error() << "Need valid module name"; -    } - -    auto it = module_deps_.find(module_name); -    if (it == module_deps_.end()) { -        return Error() << "Module '" << module_name << "' not in dependency file"; -    } -    auto& dependencies = it->second; - -    // load module dependencies in reverse order -    for (auto dep = dependencies.rbegin(); dep != dependencies.rend() - 1; ++dep) { -        if (auto result = Insmod(*dep, ""); !result) return result; -    } - -    // load target module itself with args -    return Insmod(dependencies[0], args); -} +ModaliasHandler::ModaliasHandler(const std::vector<std::string>& base_paths) +    : modprobe_(base_paths) {}  void ModaliasHandler::HandleUevent(const Uevent& uevent) {      if (uevent.modalias.empty()) return; - -    for (const auto& [alias, module] : module_aliases_) { -        if (fnmatch(alias.c_str(), uevent.modalias.c_str(), 0) != 0) continue;  // Keep looking - -        LOG(DEBUG) << "Loading kernel module '" << module << "' for alias '" << uevent.modalias -                   << "'"; - -        if (auto result = InsmodWithDeps(module, ""); !result) { -            LOG(ERROR) << "Cannot load module: " << result.error(); -            // try another one since there may be another match -            continue; -        } - -        // loading was successful -        return; -    } +    modprobe_.LoadWithAliases(uevent.modalias, true);  }  }  // namespace init  | 
