summaryrefslogtreecommitdiffstats
path: root/mdk-stage1/thirdparty.c
diff options
context:
space:
mode:
Diffstat (limited to 'mdk-stage1/thirdparty.c')
-rw-r--r--mdk-stage1/thirdparty.c87
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();
+}