diff options
-rw-r--r-- | mdk-stage1/NEWS | 2 | ||||
-rw-r--r-- | mdk-stage1/modules.c | 100 |
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 |