summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mdk-stage1/NEWS2
-rw-r--r--mdk-stage1/modules.c100
2 files changed, 74 insertions, 28 deletions
diff --git a/mdk-stage1/NEWS b/mdk-stage1/NEWS
index 261171bcd..c94a2c728 100644
--- a/mdk-stage1/NEWS
+++ b/mdk-stage1/NEWS
@@ -1,3 +1,5 @@
+- use kmod for module loading (mga#9242, based on Pok works @mdv)
+
1.76
- revert patch introduced in r7542
diff --git a/mdk-stage1/modules.c b/mdk-stage1/modules.c
index d3d92ea81..92109f515 100644
--- a/mdk-stage1/modules.c
+++ b/mdk-stage1/modules.c
@@ -32,6 +32,7 @@
#include <errno.h>
#include <time.h>
#include <sys/utsname.h>
+#include <libkmod.h>
#include "log.h"
#include "utils.h"
#include "frontend.h"
@@ -300,38 +301,81 @@ int module_already_present(const char * name)
#ifndef ENABLE_NETWORK_STANDALONE
-static enum insmod_return insmod_with_deps(const char * mod_name, char * options)
-{
- struct module_deps_elem * dep;
- const char * filename;
-
- dep = modules_deps;
- while (dep && dep->modname && strcmp(dep->modname, mod_name)) dep++;
-
- if (dep && dep->modname && dep->deps) {
- char ** one_dep;
- one_dep = dep->deps;
- while (*one_dep) {
- /* here, we can fail but we don't care, if the error is
- * important, the desired module will fail also */
- insmod_with_deps(*one_dep, NULL);
- one_dep++;
- }
+static enum insmod_return insmod_with_deps(const char * alias, char * options) {
+ struct kmod_ctx *ctx;
+ struct kmod_list *l, *list = NULL;
+ int err = 0, flags = 0;
+
+ if (!*modules_directory)
+ find_modules_directory();
+
+ ctx = kmod_new(modules_directory, NULL);
+ if (!ctx) {
+ fputs("Error: kmod_new() failed!\n", stderr);
+ goto exit;
}
-
- if (dep && dep->filename) {
- filename = dep->filename;
- } else {
- log_message("warning: unable to get module filename for %s", mod_name);
- filename = mod_name;
+ kmod_load_resources(ctx);
+
+ err = kmod_module_new_from_lookup(ctx, alias, &list);
+ if (err < 0)
+ goto exit;
+
+ // No module found...
+ if (list == NULL)
+ goto exit;
+
+ // filter through blacklist
+ struct kmod_list *filtered = NULL;
+ err = kmod_module_apply_filter(ctx, KMOD_FILTER_BLACKLIST, list, &filtered);
+ kmod_module_unref_list(list);
+ if (err < 0)
+ goto exit;
+ list = filtered;
+
+ kmod_list_foreach(l, list) {
+ struct kmod_module *mod = kmod_module_get_module(l);
+ err = kmod_module_probe_insert_module(mod, flags,
+ options, NULL, NULL, NULL);
+
+ if (err >= 0)
+ /* ignore flag return values such as a mod being blacklisted */
+ err = 0;
+ else {
+ switch (err) {
+ case -EEXIST:
+ fprintf(stderr, "could not insert '%s': Module already in kernel\n",
+ kmod_module_get_name(mod));
+ break;
+ case -ENOENT:
+ fprintf(stderr, "could not insert '%s': Unknown symbol in module, "
+ "or unknown parameter (see dmesg)\n",
+ kmod_module_get_name(mod));
+ break;
+ default:
+ fprintf(stderr, "could not insert '%s': %s\n",
+ kmod_module_get_name(mod),
+ strerror(-err));
+ break;
+ }
+ }
+
+ kmod_module_unref(mod);
+ if (err < 0)
+ break;
}
- if (module_already_present(mod_name))
- return INSMOD_OK;
+ kmod_module_unref_list(list);
- log_message("needs %s", filename);
- {
- return insmod_local_file((char *) filename, options);
+exit:
+ kmod_unref(ctx);
+
+ switch (err){
+ case 0:
+ return INSMOD_OK;
+ case -ENOENT:
+ return INSMOD_FAILED_FILE_NOT_FOUND;
+ default:
+ return INSMOD_FAILED;
}
}
#endif