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(); +} |
