diff options
Diffstat (limited to 'mdk-stage1/probing.c')
| -rw-r--r-- | mdk-stage1/probing.c | 492 | 
1 files changed, 143 insertions, 349 deletions
| diff --git a/mdk-stage1/probing.c b/mdk-stage1/probing.c index d841941b3..f956bb348 100644 --- a/mdk-stage1/probing.c +++ b/mdk-stage1/probing.c @@ -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,9 +525,9 @@ 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 */ @@ -565,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 */ @@ -580,265 +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; -                                                struct stat statbuf; -                                                char *ptr; -                                                memset(name, 0, sizeof(name)); -                                                strcpy(name, "/dev/"); -                                                sscanf(buf, " %d %d %d %s", &major, &minor, &blocks, &name[5]); -                                                if (streq(&name[5], tmp_name) && tmp[count].type == DISK && ((blocks == 1048575) || (blocks == 1440))) -                                                        tmp[count].type = FLOPPY; -                                                /* Try to create all devices while we have major/minor */ -                                                if ((ptr = strchr(&name[5], '/'))) { -                                                        *ptr = '\0'; -                                                        if (stat(name, &statbuf)) -                                                                mkdir(name, 0755); -                                                        *ptr = '/'; -                                                }							 -                                                if (stat(name, &statbuf) && mknod(name, S_IFBLK | 0600, makedev(major, minor))) { -                                                        log_perror(name); -                                                } -                                        } -                                        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; -		FILE * f; - -		for (procfile = procfiles; procfile && *procfile; procfile++) { -			if((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); -			} -		} -	} - -	/* ----------------------------------------------- */  	log_message("looking for DAC960");  	{  		FILE * f; @@ -869,41 +609,95 @@ void find_media(enum media_bus bus)  		}  	}  	/* ----------------------------------------------- */ -	log_message("looking for VirtIO"); +	log_message("looking for other disks");  	{ -		int fd, i; -		char b[50]; -		char *name = b+11; -		strcpy(b, "/sys/block/vd"); -		for (b[13] = 'a'; b[13] <= 'c'; b[13]++) { -			/* first, test if file exists (will tell if attached medium exists) */ -			b[14] = '\0'; -			if (access(b, R_OK)) +		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"); -			tmp[count].name = strdup(name); -			tmp[count].type = DISK; //UNKNOWN_MEDIA; -			tmp[count].model = strdup("VirtIO disk"); +			strcpy(pathend, "/device/vendor"); +			vendor_length = read_attribute(path, model); -			/* media type */ -			strcpy(b + 14, "/capability"); -			fd = open(b, O_RDONLY); -			if (fd == -1) { -				log_message("failed to open %s for reading", b); -				//continue; +			if (vendor_length) { +				strcat(model, " "); +				vendor_length++;  			} -			i = read(fd, buf, sizeof(buf)); -			if (i == -1) { -				log_message("Couldn't read capabilities file (%s)", b); -			} else { -				if (!strcmp(buf, "10")) -					tmp[count].type = DISK; + +			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);  	} - find_media_after_scsi:  	/* ----------------------------------------------- */  	tmp[count].name = NULL; @@ -965,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);  	} | 
