summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/modules.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/modules.c')
-rw-r--r--mdk-stage1/modules.c227
1 files changed, 105 insertions, 122 deletions
diff --git a/mdk-stage1/modules.c b/mdk-stage1/modules.c
index 53bc87d4c..76177302e 100644
--- a/mdk-stage1/modules.c
+++ b/mdk-stage1/modules.c
@@ -1,7 +1,7 @@
/*
- * Guillaume Cottenceau (gc@mandrakesoft.com)
+ * Guillaume Cottenceau (gc)
*
- * Copyright 2000 Mandrakesoft
+ * Copyright 2000 Mandriva
*
* This software may be freely redistributed under the terms of the GNU
* public license.
@@ -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 FIRMWARE_TIMEOUT_FILE "/sys/class/firmware/timeout"
-#define FIRMWARE_TIMEOUT_VALUE "1"
-
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,70 +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 = strdup(start);
- modules_deps[line].modname = filename2modname(start);
-
- start = ptr;
- i = 0;
- while (start && *start) {
- 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++;
- }
- 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");
@@ -229,25 +162,11 @@ static int load_modules_descriptions(void)
return 0;
}
-void init_firmware_timeout(void)
-{
- int fd = open(FIRMWARE_TIMEOUT_FILE, O_WRONLY|O_TRUNC, 0666);
- if (!fd) {
- log_message("warning, unable to set firmware timeout");
- return;
- }
- write(fd, FIRMWARE_TIMEOUT_VALUE, strlen(FIRMWARE_TIMEOUT_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, modules loading disabled");
+ log_message("warning, error initing modules stuff");
}
}
@@ -281,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"))) {
@@ -292,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;
@@ -363,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);
@@ -381,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++;
@@ -408,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;
}
@@ -420,6 +397,11 @@ static enum return_type insmod_with_options(char * mod, enum driver_type type)
return RETURN_OK;
}
+static int strsortfunc(const void *a, const void *b)
+{
+ return strcmp(* (char * const *) a, * (char * const *) b);
+}
+
enum return_type ask_insmod(enum driver_type type)
{
enum return_type results;
@@ -431,11 +413,12 @@ enum return_type ask_insmod(enum driver_type type)
char ** p_modules = modules;
char ** p_descrs = descrs;
+ qsort(dlist, string_array_length(dlist), sizeof(char *), strsortfunc);
+
unset_automatic(); /* we are in a fallback mode */
while (p_dlist && *p_dlist) {
struct module_descr_elem * descr;
-
if (!strstr(*p_dlist, kernel_module_extension())) {
p_dlist++;
continue;