diff options
Diffstat (limited to 'mdk-stage1/modules.c')
-rw-r--r-- | mdk-stage1/modules.c | 221 |
1 files changed, 96 insertions, 125 deletions
diff --git a/mdk-stage1/modules.c b/mdk-stage1/modules.c index 5f02d2a6d..76177302e 100644 --- a/mdk-stage1/modules.c +++ b/mdk-stage1/modules.c @@ -1,5 +1,5 @@ /* - * Guillaume Cottenceau (gc@mandriva.com) + * Guillaume Cottenceau (gc) * * Copyright 2000 Mandriva * @@ -30,7 +30,9 @@ #include <string.h> #include <stdio.h> #include <errno.h> +#include <time.h> #include <sys/utsname.h> +#include <libkmod.h> #include "log.h" #include "utils.h" #include "frontend.h" @@ -39,16 +41,11 @@ #include "modules.h" -#define UEVENT_HELPER_FILE "/sys/kernel/uevent_helper" -#define UEVENT_HELPER_VALUE "/sbin/hotplug" - static char modules_directory[100]; -static struct module_deps_elem * modules_deps = NULL; static struct module_descr_elem * modules_descr = NULL; extern long init_module(void *, unsigned long, const char *); - static const char *moderror(int err) { switch (err) { @@ -89,7 +86,7 @@ int insmod_local_file(char * path, char * options) static char *kernel_module_extension(void) { - return ".ko.gz"; + return ".ko.xz"; } @@ -123,76 +120,6 @@ static void find_modules_directory(void) sprintf(modules_directory , "%s/%s", prefix, release); } -static int load_modules_dependencies(void) -{ - char * deps_file = asprintf_("%s/%s", modules_directory, "modules.dep"); - char * buf, * ptr, * start, * end; - struct stat s; - int line, i; - - log_message("loading modules dependencies"); - buf = cat_file(deps_file, &s); - if (!buf) - return -1; - line = line_counts(buf); - modules_deps = malloc(sizeof(*modules_deps) * (line+1)); - - start = buf; - line = 0; - while (start < (buf+s.st_size) && *start) { - char * tmp_deps[50]; - - end = strchr(start, '\n'); - *end = '\0'; - - ptr = strchr(start, ':'); - if (!ptr) { - start = end + 1; - continue; - } - *ptr = '\0'; - ptr++; - - while (*ptr && (*ptr == ' ')) ptr++; - - /* sort of a good line */ - modules_deps[line].filename = start[0] == '/' ? strdup(start) : asprintf_("%s/%s", modules_directory, start); - modules_deps[line].modname = filename2modname(start); - - start = ptr; - i = 0; - while (start && *start && i < sizeof(tmp_deps)/sizeof(char *)) { - ptr = strchr(start, ' '); - if (ptr) *ptr = '\0'; - tmp_deps[i++] = filename2modname(start); - if (ptr) - start = ptr + 1; - else - start = NULL; - while (start && *start && *start == ' ') - start++; - } - if(i >= sizeof(tmp_deps)/sizeof(char *)-1) { - log_message("warning, more than %zu dependencies for module %s", - sizeof(tmp_deps)/sizeof(char *)-1, - modules_deps[line].modname); - i = sizeof(tmp_deps)/sizeof(char *)-1; - } - tmp_deps[i++] = NULL; - - modules_deps[line].deps = memdup(tmp_deps, sizeof(char *) * i); - - line++; - start = end + 1; - } - modules_deps[line].modname = NULL; - - free(buf); - - return 0; -} - - static int load_modules_descriptions(void) { char * descr_file = asprintf_("%s/%s", modules_directory, "modules.description"); @@ -235,23 +162,9 @@ static int load_modules_descriptions(void) return 0; } -void init_firmware_loader(void) -{ - int fd = open(UEVENT_HELPER_FILE, O_WRONLY|O_TRUNC, 0666); - if (!fd) { - log_message("warning, unable to set firmware loader"); - return; - } - write(fd, UEVENT_HELPER_VALUE, strlen(UEVENT_HELPER_VALUE)); - close(fd); -} - void init_modules_insmoding(void) { find_modules_directory(); - if (load_modules_dependencies()) { - fatal_error("warning, error initing modules stuff, modules loading disabled"); - } if (load_modules_descriptions()) { log_message("warning, error initing modules stuff"); } @@ -287,6 +200,8 @@ static void add_modules_conf(char * str) int module_already_present(const char * name) { FILE * f; + struct stat sb; + char *path; int answ = 0; if ((f = fopen("/proc/modules", "rb"))) { @@ -298,52 +213,109 @@ int module_already_present(const char * name) } fclose(f); } + + /* built-in module case. try to find them through sysfs */ + if (!answ) { + asprintf(&path, "/sys/module/%s", name); + if (!stat(path, &sb)) + answ = 1; + free(path); + } + if (!answ) { + asprintf(&path, "/sys/fs/%s", name); + if (!stat(path, &sb)) + answ = 1; + free(path); + } return answ; } #ifndef ENABLE_NETWORK_STANDALONE -static enum insmod_return insmod_with_deps(const char * mod_name, char * options, int allow_modules_floppy) -{ - 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, allow_modules_floppy); - 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 #ifndef DISABLE_NETWORK -enum insmod_return my_insmod(const char * mod_name, enum driver_type type, char * options, int allow_modules_floppy) +enum insmod_return my_modprobe(const char * mod_name, enum driver_type type, char * options) #else -enum insmod_return my_insmod(const char * mod_name, enum driver_type type __attribute__ ((unused)), char * options, int allow_modules_floppy) +enum insmod_return my_modprobe(const char * mod_name, enum driver_type type __attribute__ ((unused)), char * options) #endif { int i; @@ -369,7 +341,7 @@ enum insmod_return my_insmod(const char * mod_name, enum driver_type type __attr i = system(cmd); } #else - i = insmod_with_deps(mod_name, options, allow_modules_floppy); + i = insmod_with_deps(mod_name, options); #endif if (i == 0) { log_message("\tsucceeded %s", mod_name); @@ -387,7 +359,6 @@ enum insmod_return my_insmod(const char * mod_name, enum driver_type type __attr sprintf(alias, "alias %s %s", *new_net_devices, mod_name); add_modules_conf(alias); log_message("NET: %s", alias); - net_discovered_interface(*new_net_devices); already_present: new_net_devices++; @@ -414,9 +385,9 @@ static enum return_type insmod_with_options(char * mod, enum driver_type type) strcat(options, mod); strcat(options, " "); - strcat(options, answers[0]); // because my_insmod will eventually modify the string + strcat(options, answers[0]); // because my_modprobe will eventually modify the string - if (my_insmod(mod, type, answers[0], 1) != INSMOD_OK) { + if (my_modprobe(mod, type, answers[0]) != INSMOD_OK) { stg1_error_message("Insmod failed."); return RETURN_ERROR; } |