diff options
Diffstat (limited to 'mdk-stage1/thirdparty.c')
| -rw-r--r-- | mdk-stage1/thirdparty.c | 87 | 
1 files changed, 70 insertions, 17 deletions
| diff --git a/mdk-stage1/thirdparty.c b/mdk-stage1/thirdparty.c index 176a24f1c..78bbf485a 100644 --- a/mdk-stage1/thirdparty.c +++ b/mdk-stage1/thirdparty.c @@ -1,8 +1,8 @@  /* - * Guillaume Cottenceau (gc@mandrakesoft.com) - * Olivier Blin (oblin@mandrakesoft.com) + * Guillaume Cottenceau (gc) + * Olivier Blin (oblin)   * - * Copyright 2005 Mandrakesoft + * Copyright 2005 Mandriva   *   * This software may be freely redistributed under the terms of the GNU   * public license. @@ -17,10 +17,12 @@  #include <stdio.h>  #include <string.h>  #include <sys/mount.h> +#include <sys/utsname.h>  #include "stage1.h" +#include "tools.h" +#include "utils.h"  #include "log.h" -#include "insmod.h"  #include "modules.h"  #include "mount.h"  #include "frontend.h" @@ -32,7 +34,8 @@  #define THIRDPARTY_MOUNT_LOCATION "/tmp/thirdparty" -static struct pcitable_entry pcitable[100]; +#define N_PCITABLE_ENTRIES 100 +static struct pcitable_entry pcitable[N_PCITABLE_ENTRIES];  static int pcitable_len = 0;  static enum return_type thirdparty_choose_device(char ** device, int probe_only) @@ -65,7 +68,7 @@ static enum return_type thirdparty_choose_device(char ** device, int probe_only)  #endif  	floppy_dev = floppy_device(); -	if (strstr(floppy_dev, "/dev/") == floppy_dev) { +	if (floppy_dev && strstr(floppy_dev, "/dev/") == floppy_dev) {  		floppy_dev = floppy_dev + 5;  	}  	if (floppy_dev) @@ -129,7 +132,7 @@ static enum return_type thirdparty_choose_device(char ** device, int probe_only)  			return results;  	} -	if (streq(*device, floppy_dev)) { +	if (floppy_dev && streq(*device, floppy_dev)) {  		/* a floppy is selected, don't try to list partitions */  		return RETURN_OK;  	} @@ -217,24 +220,50 @@ static enum return_type thirdparty_prompt_modules(const char *modules_location,  } +static int pcitable_orderer(const void *a, const void *b) +{ +	int ret; +	struct pcitable_entry *ap = (struct pcitable_entry *)a; +	struct pcitable_entry *bp = (struct pcitable_entry *)b; + +	if ((ret = ap->vendor - bp->vendor) != 0) +		return ret; +	if ((ret = ap->device - bp->device) != 0) +		return ret; +	if ((ret = ap->subvendor - bp->subvendor) != 0) +		return ret; +	if ((ret = ap->subdevice - bp->subdevice) != 0) +		return ret; + +	return 0; +} + +  static void thirdparty_load_pcitable(const char *modules_location)  {  	char pcitable_filename[100];  	FILE * f = NULL; -	sprintf(pcitable_filename, "%s/pcitable", modules_location); +	snprintf(pcitable_filename, sizeof(pcitable_filename), "%s/pcitable", modules_location);  	if (!(f = fopen(pcitable_filename, "rb"))) {  		log_message("third_party: no external pcitable found");  		return;  	} -	while (1) { +	pcitable_len = 0; +	while (pcitable_len < N_PCITABLE_ENTRIES) {  		char buf[200];  		struct pcitable_entry *e;  		if (!fgets(buf, sizeof(buf), f)) break;  		e = &pcitable[pcitable_len++]; -		sscanf(buf, "%hx\t%hx\t\"%[^ \"]\"\t\"%[^ \"]\"", &e->vendor, &e->device, e->module, e->description); +		if (sscanf(buf, "%hx\t%hx\t\"%[^ \"]\"\t\"%[^\"]\"", &e->vendor, &e->device, e->module, e->description) == 4) +			e->subvendor = e->subdevice = PCITABLE_MATCH_ALL; +		else +			sscanf(buf, "%hx\t%hx\t%x\t%x\t\"%[^ \"]\"\t\"%[^\"]\"", &e->vendor, &e->device, &e->subvendor, &e->subdevice, e->module, e->description);  	}  	fclose(f); + +	/* sort pcitable by most specialised entries first */ +	qsort(pcitable, pcitable_len, sizeof(pcitable[0]), pcitable_orderer);  } @@ -247,8 +276,13 @@ static int thirdparty_is_detected(char *driver) {  			if (pcitable[j].vendor == detected_devices[i].vendor &&  			    pcitable[j].device == detected_devices[i].device &&  			    !strcmp(pcitable[j].module, driver)) { -				log_message("probing: found device for module %s", driver); -				return 1; +				const int subvendor = pcitable[j].subvendor; +				const int subdevice = pcitable[j].subdevice; +				if ((subvendor == PCITABLE_MATCH_ALL && subdevice == PCITABLE_MATCH_ALL) || +					(subvendor == detected_devices[i].subvendor && subdevice == detected_devices[i].subdevice)) { +					log_message("probing: found device for module %s", driver); +					return 1; +				}  			}  		}  		/* if not found, compare with the detected driver */ @@ -299,7 +333,7 @@ static enum return_type thirdparty_autoload_modules(const char *modules_location  			entry++;  		}  		if (!entry || !*entry) { -			enum insmod_return ret = my_insmod(module, ANY_DRIVER_TYPE, options, 0); +			enum insmod_return ret = my_modprobe(module, ANY_DRIVER_TYPE, options);  			if (ret != INSMOD_OK) {  				log_message("\t%s (marfile): failed", module);  				stg1_error_message("Insmod %s (marfile) failed.", module); @@ -312,13 +346,14 @@ static enum return_type thirdparty_autoload_modules(const char *modules_location  static enum return_type thirdparty_try_directory(char * root_directory, int interactive) {  	char modules_location[100]; -	char list_filename[50]; +	char modules_location_release[100]; +	char *list_filename;  	FILE *f_load, *f_detect; -	char **modules_list; +	char **modules_list, **modules_list_release; +	struct utsname kernel_uname;  	/* look first in the specific third-party directory */ -	strcpy(modules_location, root_directory); -	strcat(modules_location, THIRDPARTY_DIRECTORY); +	snprintf(modules_location, sizeof(modules_location), "%s" THIRDPARTY_DIRECTORY, root_directory);  	modules_list = list_directory(modules_location);  	/* if it's empty, look in the root of selected device */ @@ -332,6 +367,17 @@ static enum return_type thirdparty_try_directory(char * root_directory, int inte  			add_to_env("THIRDPARTY_DIR", THIRDPARTY_DIRECTORY);          } +	if (uname(&kernel_uname)) { +		log_perror("uname failed"); +		return RETURN_ERROR; +	} +	snprintf(modules_location_release, sizeof(modules_location_release), "%s/%s", modules_location, kernel_uname.release); +	modules_list_release = list_directory(modules_location_release); +	if (modules_list_release && modules_list_release[0]) { +		strcpy(modules_location, modules_location_release); +		modules_list = modules_list_release; +	} +  	log_message("third party: using modules location %s", modules_location);  	if (!modules_list || !*modules_list) { @@ -341,6 +387,8 @@ static enum return_type thirdparty_try_directory(char * root_directory, int inte  		return RETURN_ERROR;          } +	list_filename = alloca(strlen(modules_location) + 10 /* max: "/to_detect" */ + 1); +  	sprintf(list_filename, "%s/to_load", modules_location);  	f_load = fopen(list_filename, "rb");  	if (f_load) { @@ -405,3 +453,8 @@ void thirdparty_load_modules(void)  	if (results != RETURN_OK)  		return thirdparty_load_modules();  } + +void thirdparty_destroy(void) +{ +	probing_destroy(); +} | 
