diff options
Diffstat (limited to 'mdk-stage1/modules.c')
| -rw-r--r-- | mdk-stage1/modules.c | 206 | 
1 files changed, 83 insertions, 123 deletions
| diff --git a/mdk-stage1/modules.c b/mdk-stage1/modules.c index 745070052..76177302e 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" @@ -40,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) { @@ -124,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"); @@ -236,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");  	} @@ -309,52 +221,101 @@ int module_already_present(const char * name)  			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; @@ -380,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); @@ -398,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++; @@ -425,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;  	} | 
