diff options
Diffstat (limited to 'mdk-stage1/probing.c')
-rw-r--r-- | mdk-stage1/probing.c | 476 |
1 files changed, 161 insertions, 315 deletions
diff --git a/mdk-stage1/probing.c b/mdk-stage1/probing.c index 3052b2823..f956bb348 100644 --- a/mdk-stage1/probing.c +++ b/mdk-stage1/probing.c @@ -1,5 +1,5 @@ /* - * Guillaume Cottenceau (gc@mandriva.com) + * Guillaume Cottenceau (gc) * * Copyright 2000 Mandriva * @@ -40,23 +40,27 @@ #include <fnmatch.h> #include <sys/socket.h> #include <net/if.h> +#include <linux/sockios.h> +#include <linux/ethtool.h> #include <sys/ioctl.h> #include <sys/mount.h> #include <pci/pci.h> #include <libldetect.h> +#include <errno.h> +#include <glob.h> #include "stage1.h" #include "log.h" #include "utils.h" #include "frontend.h" #include "modules.h" -#include "pci-resource/pci-ids.h" +#include "pci-ids.h" #ifdef ENABLE_USB -#include "usb-resource/usb-ids.h" +#include "usb-ids.h" #endif #ifdef ENABLE_PCMCIA #include "sysfs/libsysfs.h" -#include "pcmcia-resource/pcmcia-ids.h" +#include "pcmcia-ids.h" #endif #include "probing.h" @@ -82,54 +86,31 @@ static void warning_insmod_failed(enum insmod_return r) } #ifndef DISABLE_NETWORK -struct net_description_elem -{ - char * intf_name; - char * intf_description; -}; -static struct net_description_elem net_descriptions[50]; -static int net_descr_number = 0; -static char * intf_descr_for_discover = NULL; -static char * net_intf_too_early_name[50]; /* for modules providing more than one net intf */ -static int net_intf_too_early_number = 0; -static int net_intf_too_early_ptr = 0; - const char * safe_descr(const char * text) { return text ? text : "unknown"; } -void prepare_intf_descr(const char * intf_descr) +char * get_net_intf_description(char * intf_name) { - intf_descr_for_discover = strdup(intf_descr); -} + struct ifreq ifr; + struct ethtool_drvinfo drvinfo; + int s = socket(AF_INET, SOCK_DGRAM, 0); + char *res; -void net_discovered_interface(char * intf_name) -{ - if (!intf_descr_for_discover) { - net_intf_too_early_name[net_intf_too_early_number++] = strdup(intf_name); - return; - } - if (!intf_name) { - if (net_intf_too_early_ptr >= net_intf_too_early_number) { - log_message("NET: was expecting another network interface (broken net module?)"); - return; - } - net_descriptions[net_descr_number].intf_name = net_intf_too_early_name[net_intf_too_early_ptr++]; - } - else - net_descriptions[net_descr_number].intf_name = strdup(intf_name); - net_descriptions[net_descr_number].intf_description = strdup(intf_descr_for_discover); - intf_descr_for_discover = NULL; - net_descr_number++; -} + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, intf_name, IFNAMSIZ); -char * get_net_intf_description(char * intf_name) -{ - int i; - for (i = 0; i < net_descr_number ; i++) - if (!strcmp(net_descriptions[i].intf_name, intf_name)) - return net_descriptions[i].intf_description; - return strdup("unknown"); + drvinfo.cmd = ETHTOOL_GDRVINFO; + ifr.ifr_data = (caddr_t) &drvinfo; + + if (ioctl(s, SIOCETHTOOL, &ifr) != -1) { + res = drvinfo.driver; + } else { + perror("SIOCETHTOOL"); + res = "unknown"; + } + close(s); + return strdup(res); } #endif @@ -272,10 +253,10 @@ void discovered_device(enum driver_type type, const char * description, const ch if (type == MEDIA_ADAPTERS) { const char * alternate = NULL; wait_message("Loading driver for media adapter:\n \n%s", description); - failed = my_insmod(driver, MEDIA_ADAPTERS, NULL, 1); + failed = my_modprobe(driver, MEDIA_ADAPTERS, NULL); alternate = get_alternate_module(driver); if (!IS_NOAUTO && alternate) { - failed = failed || my_insmod(alternate, MEDIA_ADAPTERS, NULL, 1); + failed = failed || my_modprobe(alternate, MEDIA_ADAPTERS, NULL); } remove_wait_message(); warning_insmod_failed(failed); @@ -283,19 +264,17 @@ void discovered_device(enum driver_type type, const char * description, const ch #endif #ifndef DISABLE_NETWORK if (type == NETWORK_DEVICES) { + log_message("NET: Loading driver for network device %s", description); wait_message("Loading driver for network device:\n \n%s", description); - prepare_intf_descr(description); - failed = my_insmod(driver, NETWORK_DEVICES, NULL, 1); + failed = my_modprobe(driver, NETWORK_DEVICES, NULL); warning_insmod_failed(failed); remove_wait_message(); - if (intf_descr_for_discover) /* for modules providing more than one net intf */ - net_discovered_interface(NULL); } #endif #ifdef ENABLE_USB if (type == USB_CONTROLLERS) /* we can't allow additional modules floppy since we need usbhid for keystrokes of usb keyboards */ - failed = my_insmod(driver, USB_CONTROLLERS, NULL, 0); + failed = my_modprobe(driver, USB_CONTROLLERS, NULL); #endif } @@ -337,7 +316,7 @@ void probe_virtio_modules(void) if (e->vendor == VIRTIO_PCI_VENDOR) { if (!loaded_pci) { log_message("loading virtio-pci"); - my_insmod("virtio_pci", ANY_DRIVER_TYPE, NULL, 0); + my_modprobe("virtio_pci", ANY_DRIVER_TYPE, NULL); loaded_pci = 1; } @@ -360,7 +339,7 @@ void probe_virtio_modules(void) } if (name) { log_message("virtio: loading %s", name); - my_insmod(name, ANY_DRIVER_TYPE, options, 0); + my_modprobe(name, ANY_DRIVER_TYPE, options); } } } @@ -429,14 +408,9 @@ void probe_that_type(enum driver_type type, enum media_bus bus __attribute__ ((u if (!already_mounted_usbdev) { already_mounted_usbdev = 1; - if (mount("none", "/proc/bus/usb", "usbfs", 0, NULL) && - mount("none", "/proc/bus/usb", "usbdevfs", 0, NULL)) { - log_message("USB: couldn't mount /proc/bus/usb"); - goto end_usb_probe; - } wait_message("Detecting USB devices."); sleep(4); /* sucking background work */ - my_insmod("usbhid", ANY_DRIVER_TYPE, NULL, 0); + my_modprobe("usbhid", ANY_DRIVER_TYPE, NULL); remove_wait_message(); } @@ -488,7 +462,7 @@ void probe_that_type(enum driver_type type, enum media_bus bus __attribute__ ((u for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { struct sysfs_attribute *modalias_attr; - char keyfile[256]; + char keyfile[300]; int i, id; if (dent->d_name[0] == '.') @@ -551,11 +525,13 @@ void probe_that_type(enum driver_type type, enum media_bus bus __attribute__ ((u already_probed_usb_controllers && !already_loaded_usb_scsi) { already_loaded_usb_scsi = 1; /* we can't allow additional modules floppy since we need usbkbd for keystrokes of usb keyboards */ - my_insmod("usb_storage", MEDIA_ADAPTERS, NULL, 0); + my_modprobe("usb_storage", MEDIA_ADAPTERS, NULL); if (module_already_present("ieee1394")) - my_insmod("sbp2", MEDIA_ADAPTERS, NULL, 0); + my_modprobe("sbp2", MEDIA_ADAPTERS, NULL); wait_message("Detecting USB mass-storage devices."); +#ifndef DEBUG sleep(10); /* sucking background work */ +#endif remove_wait_message(); } } @@ -563,13 +539,38 @@ void probe_that_type(enum driver_type type, enum media_bus bus __attribute__ ((u static struct media_info * medias = NULL; +// Read a short string from a file and strips it, intended for sysfs attributes +static ssize_t read_attribute(char *path, char *buf) { + ssize_t l = 0; + int fd = open(path, O_RDONLY); + buf[0] = '\0'; + if (fd == -1) { + log_message("Failed to open %s for reading", path); + } else { + ssize_t n = read(fd, buf, 32); + if (n == -1) { + log_message("Couldn't read file (%s)", path); + } else { + // Strip whitespaces and newline + for (int i = n-1; i >= 0; i--) { + if (buf[i] == '\n' || buf[i] == ' ') + continue; + l = i+1; + break; + } + buf[l] = '\0'; + } + close(fd); + } + log_message("Content of %s was %s", path, buf); + return l; +} + void find_media(enum media_bus bus) { - char b[50]; char buf[5000]; struct media_info tmp[50]; int count = 0; - int fd; if (medias) free(medias); /* that does not free the strings, by the way */ @@ -578,250 +579,6 @@ void find_media(enum media_bus bus) probe_that_type(MEDIA_ADAPTERS, bus); /* ----------------------------------------------- */ - if (bus != BUS_IDE && bus != BUS_ANY) - goto find_media_after_ide; - log_message("looking for ide media"); - - strcpy(b, "/proc/ide/hd"); - for (b[12] = 'a'; b[12] <= 't'; b[12]++) { - int i; - char ide_disk[] = "disk"; - char ide_cdrom[] = "cdrom"; - char ide_tape[] = "tape"; - char ide_floppy[] = "floppy"; - - /* first, test if file exists (will tell if attached medium exists) */ - b[13] = '\0'; - if (access(b, R_OK)) - continue; - - tmp[count].name = strdup("hda"); - tmp[count].name[2] = b[12]; - - /* media type */ - strcpy(b + 13, "/media"); - fd = open(b, O_RDONLY); - if (fd == -1) { - log_message("failed to open %s for reading", b); - continue; - } - - i = read(fd, buf, sizeof(buf)); - if (i == -1) { - log_message("failed to read %s", b); - continue; - } - buf[i] = '\0'; - close(fd); - - if (ptr_begins_static_str(buf, ide_disk)) - tmp[count].type = DISK; - else if (ptr_begins_static_str(buf, ide_cdrom)) - tmp[count].type = CDROM; - else if (ptr_begins_static_str(buf, ide_tape)) - tmp[count].type = TAPE; - else if (ptr_begins_static_str(buf, ide_floppy)) - tmp[count].type = FLOPPY; - else - tmp[count].type = UNKNOWN_MEDIA; - - /* media model */ - strcpy(b + 13, "/model"); - fd = open(b, O_RDONLY); - if (fd == -1) { - log_message("failed to open %s for reading", b); - continue; - } - - i = read(fd, buf, sizeof(buf)); - if (i <= 0) { - log_message("failed to read %s", b); - tmp[count].model = strdup("(none)"); - } - else { - buf[i-1] = '\0'; /* eat the \n */ - tmp[count].model = strdup(buf); - } - close(fd); - - log_message("IDE/%d: %s is a %s", tmp[count].type, tmp[count].name, tmp[count].model); - count++; - } - - find_media_after_ide: - /* ----------------------------------------------- */ - if (bus != BUS_SCSI && bus != BUS_USB && bus != BUS_PCMCIA && bus != BUS_ANY) - goto find_media_after_scsi; - log_message("looking for scsi media"); - - fd = open("/proc/scsi/scsi", O_RDONLY); - if (fd != -1) { - FILE * f; - - enum { SCSI_TOP, SCSI_HOST, SCSI_VENDOR, SCSI_TYPE } state = SCSI_TOP; - char * start, * chptr, * next, * end; - char scsi_disk_count = 'a'; - char scsi_cdrom_count = '0'; - char scsi_tape_count = '0'; - - char scsi_no_devices[] = "Attached devices: none"; - char scsi_some_devices[] = "Attached devices:"; - char scsi_host[] = "Host: "; - char scsi_vendor[] = " Vendor: "; - - int i = read(fd, &buf, sizeof(buf)-1); - if (i < 1) { - close(fd); - goto end_scsi; - } - close(fd); - buf[i] = '\0'; - - if (ptr_begins_static_str(buf, scsi_no_devices)) - goto end_scsi; - - start = buf; - while (*start) { - char tmp_model[50]; - char tmp_name[10]; - - chptr = start; - while (*chptr != '\n') chptr++; - *chptr = '\0'; - next = chptr + 1; - - switch (state) { - case SCSI_TOP: - if (!ptr_begins_static_str(start, scsi_some_devices)) - goto end_scsi; - state = SCSI_HOST; - break; - - case SCSI_HOST: - if (!ptr_begins_static_str(start, scsi_host)) - goto end_scsi; - state = SCSI_VENDOR; - break; - - case SCSI_VENDOR: - if (!ptr_begins_static_str(start, scsi_vendor)) - goto end_scsi; - - /* (1) Grab Vendor info */ - start += 10; - end = chptr = strstr(start, "Model:"); - if (!chptr) - goto end_scsi; - - chptr--; - while (*chptr == ' ') - chptr--; - if (*chptr == ':') { - chptr++; - *(chptr + 1) = '\0'; - strcpy(tmp_model,"(unknown)"); - } else { - *(chptr + 1) = '\0'; - strcpy(tmp_model, start); - } - - /* (2) Grab Model info */ - start = end; - start += 7; - - chptr = strstr(start, "Rev:"); - if (!chptr) - goto end_scsi; - - chptr--; - while (*chptr == ' ') chptr--; - *(chptr + 1) = '\0'; - - strcat(tmp_model, " "); - strcat(tmp_model, start); - - tmp[count].model = strdup(tmp_model); - - state = SCSI_TYPE; - - break; - - case SCSI_TYPE: - if (strncmp(" Type:", start, 7)) - goto end_scsi; - *tmp_name = '\0'; - - if (strstr(start, "Direct-Access")) { - sprintf(tmp_name, "sd%c", scsi_disk_count++); - tmp[count].type = DISK; - } else if (strstr(start, "Sequential-Access")) { - sprintf(tmp_name, "st%c", scsi_tape_count++); - tmp[count].type = TAPE; - } else if (strstr(start, "CD-ROM")) { - sprintf(tmp_name, "sr%c", scsi_cdrom_count++); - tmp[count].type = CDROM; - } - - if (!(f = fopen("/proc/partitions", "rb")) || !fgets(buf, sizeof(buf), f) || !fgets(buf, sizeof(buf), f)) { - log_message("Couldn't open /proc/partitions"); - } else { - while (fgets(buf, sizeof(buf), f)) { - char name[100]; - int major, minor, blocks; - memset(name, 0, sizeof(name)); - sscanf(buf, " %d %d %d %s", &major, &minor, &blocks, name); - if (streq(name, tmp_name) && tmp[count].type == DISK && ((blocks == 1048575) || (blocks == 1440))) - tmp[count].type = FLOPPY; - } - fclose(f); - } - - if (*tmp_name) { - tmp[count].name = strdup(tmp_name); - log_message("SCSI/%d: %s is a %s", tmp[count].type, tmp[count].name, tmp[count].model); - count++; - } - - state = SCSI_HOST; - } - - start = next; - } - - end_scsi:; - } - - /* ----------------------------------------------- */ - log_message("looking for Compaq Smart Array media"); - { - char * procfiles[] = { "/proc/driver/cpqarray/ida0", "/proc/driver/cciss/cciss0", // 2.4 style - "/proc/array/ida", "/proc/cciss/cciss", // 2.2 style - NULL }; - static char cpq_descr[] = "Compaq RAID logical disk"; - char ** procfile = procfiles; - FILE * f; - while (procfile && *procfile && (f = fopen(*procfile, "rb"))) { - while (fgets(buf, sizeof(buf), f)) { - if (ptr_begins_static_str(buf, "ida/") || ptr_begins_static_str(buf, "cciss/")) { - char * end = strchr(buf, ':'); - if (!end) - log_message("Inconsistency in %s, line:\n%s", *procfile, buf); - else { - *end = '\0'; - tmp[count].name = strdup(buf); - tmp[count].type = DISK; - tmp[count].model = cpq_descr; - log_message("CPQ: found %s", tmp[count].name); - count++; - } - } - } - fclose(f); - procfile++; - } - } - - /* ----------------------------------------------- */ log_message("looking for DAC960"); { FILE * f; @@ -851,13 +608,102 @@ void find_media(enum media_bus bus) fclose(f); } } - find_media_after_scsi: + /* ----------------------------------------------- */ + log_message("looking for other disks"); + { + glob_t globbuf; + // TODO: We should switch everything to here, and later switch to ignoring + // some types of disks (ram, loop, ...) rather than a list to accept. + glob("/sys/block/nvme*", 0, NULL, &globbuf); + glob("/sys/block/vd*", GLOB_APPEND, NULL, &globbuf); + glob("/sys/block/cciss*", GLOB_APPEND, NULL, &globbuf); + glob("/sys/block/fd*", GLOB_APPEND, NULL, &globbuf); + glob("/sys/block/sd*", GLOB_APPEND, NULL, &globbuf); + glob("/sys/block/st*", GLOB_APPEND, NULL, &globbuf); + glob("/sys/block/sr*", GLOB_APPEND, NULL, &globbuf); + + for (int i = 0; i < globbuf.gl_pathc; i++) { + char *name, *pathend; + char path[64]; + char model[64]; + int vendor_length = 0; + + strncpy(path, globbuf.gl_pathv[i], sizeof(path)); + name = strdup(path + 11); + + // Replace ! with /, for example for cciss!c0d0 devices + char * c = name; + while((c = strchr(c, '!')) != NULL) { + *c = '/'; + c++; + } + + pathend = path + strlen(path); + + // Check if this device had been handled by other code + int exists = 0; + for (int j = 0; j < count; j++) { + if (!strcmp(name, tmp[j].name)) { + exists = 1; + break; + } + } + if (exists) { + free(name); + continue; + } + + strcpy(model, "Unknown Disk"); + + strcpy(pathend, "/device/vendor"); + vendor_length = read_attribute(path, model); + + if (vendor_length) { + strcat(model, " "); + vendor_length++; + } + + strcpy(pathend, "/device/model"); + read_attribute(path, model+vendor_length); + + strcpy(pathend, "/capability"); + read_attribute(path, buf); + long caps = strtol(buf, NULL, 16); + + // GENHD_FL_UP (0x0010): indicated that the block device is “up” but the kernel has removed that info + if (caps && 0) { + log_message("Ignoring device %s (not up)", name); + free(name); + continue; + } + + if (caps & 0x0400) { + log_message("Ignoring device %s (hidden)", name); + free(name); + continue; + } + + tmp[count].type = DISK; + if (caps & 0x0008 || !strncmp(name, "sr", 2)) { + tmp[count].type = CDROM; + } else if (!strncmp(name, "fd", 2)) { + tmp[count].type = FLOPPY; + } else if (!strncmp(name, "st", 2)) { + tmp[count].type = TAPE; + } + + tmp[count].name = name; + tmp[count].model = strdup(model); + count++; + } + globfree(&globbuf); + } /* ----------------------------------------------- */ tmp[count].name = NULL; count++; - medias = memdup(tmp, sizeof(struct media_info) * count); + medias = _memdup(tmp, sizeof(struct media_info) * count); } @@ -884,8 +730,8 @@ void get_medias(enum media_type media, char *** names, char *** models, enum med tmp_names[count] = NULL; tmp_models[count++] = NULL; - *names = memdup(tmp_names, sizeof(char *) * count); - *models = memdup(tmp_models, sizeof(char *) * count); + *names = _memdup(tmp_names, sizeof(char *) * count); + *models = _memdup(tmp_models, sizeof(char *) * count); } @@ -913,7 +759,7 @@ char ** get_net_devices(void) int i = 0; if (!already_probed) { - already_probed = 1; /* cut off loop brought by: probe_that_type => my_insmod => get_net_devices */ + already_probed = 1; /* cut off loop brought by: probe_that_type => my_modprobe => get_net_devices */ probe_that_type(NETWORK_DEVICES, BUS_ANY); } @@ -951,7 +797,7 @@ char ** get_net_devices(void) tmp[i++] = NULL; - return memdup(tmp, sizeof(char *) * i); + return _memdup(tmp, sizeof(char *) * i); } #endif /* DISABLE_NETWORK */ |