⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
	ENTER1("unloading driver: %s (%p)", driver->name, driver);	TRACE1("freeing %d images", driver->num_pe_images);	drv_obj = driver->drv_obj;	for (i = 0; i < driver->num_pe_images; i++)		if (driver->pe_images[i].image) {			TRACE1("freeing image at %p",			       driver->pe_images[i].image);			vfree(driver->pe_images[i].image);		}	TRACE1("freeing %d bin files", driver->num_bin_files);	for (i = 0; i < driver->num_bin_files; i++) {		TRACE1("freeing image at %p", driver->bin_files[i].data);		if (driver->bin_files[i].data)			vfree(driver->bin_files[i].data);	}	if (driver->bin_files)		kfree(driver->bin_files);	RtlFreeUnicodeString(&drv_obj->name);	RemoveEntryList(&driver->list);	nt_list_for_each_safe(cur, next, &driver->settings) {		struct wrap_device_setting *setting;		struct ndis_configuration_parameter *param;		setting = container_of(cur, struct wrap_device_setting, list);		TRACE2("%p", setting);		param = setting->encoded;		if (param) {			TRACE2("%p", param);			if (param->type == NdisParameterString)				RtlFreeUnicodeString(&param->data.string);			ExFreePool(param);		}		kfree(setting);	}	/* this frees driver */	free_custom_extensions(drv_obj->drv_ext);	kfree(drv_obj->drv_ext);	TRACE1("drv_obj: %p", drv_obj);	EXIT1(return);}/* call the entry point of the driver */static int start_wrap_driver(struct wrap_driver *driver){	int i;	NTSTATUS ret, res;	struct driver_object *drv_obj;	typeof(driver->pe_images[0].entry) entry;	ENTER1("%s", driver->name);	drv_obj = driver->drv_obj;	for (ret = res = 0, i = 0; i < driver->num_pe_images; i++)		/* dlls are already started by loader */		if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) {			entry = driver->pe_images[i].entry;			drv_obj->start = driver->pe_images[i].entry;			drv_obj->driver_size = driver->pe_images[i].size;			TRACE1("entry: %p, %p, drv_obj: %p",			       entry, *entry, drv_obj);			res = LIN2WIN2(entry, drv_obj, &drv_obj->name);			ret |= res;			TRACE1("entry returns %08X", res);			break;		}	if (ret) {		ERROR("driver initialization failed: %08X", ret);		RtlFreeUnicodeString(&drv_obj->name);		/* this frees ndis_driver */		free_custom_extensions(drv_obj->drv_ext);		kfree(drv_obj->drv_ext);		TRACE1("drv_obj: %p", drv_obj);		ObDereferenceObject(drv_obj);		EXIT1(return -EINVAL);	}	EXIT1(return 0);}/* * add driver to list of loaded driver but make sure this driver is * not loaded before. called with loader_mutex down */static int add_wrap_driver(struct wrap_driver *driver){	struct wrap_driver *tmp;	ENTER1("name: %s", driver->name);	nt_list_for_each_entry(tmp, &wrap_drivers, list) {		if (stricmp(tmp->name, driver->name) == 0) {			ERROR("cannot add duplicate driver");			EXIT1(return -EBUSY);		}	}	InsertHeadList(&wrap_drivers, &driver->list);	EXIT1(return 0);}/* load a driver from userspace and initialize it. called with * loader_mutex down */static int load_user_space_driver(struct load_driver *load_driver){	struct driver_object *drv_obj;	struct ansi_string ansi_reg;	struct wrap_driver *wrap_driver = NULL;	ENTER1("%p", load_driver);	drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL);	if (!drv_obj) {		ERROR("couldn't allocate memory");		EXIT1(return -ENOMEM);	}	TRACE1("drv_obj: %p", drv_obj);	drv_obj->drv_ext = kmalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL);	if (!drv_obj->drv_ext) {		ERROR("couldn't allocate memory");		ObDereferenceObject(drv_obj);		EXIT1(return -ENOMEM);	}	memset(drv_obj->drv_ext, 0, sizeof(*(drv_obj->drv_ext)));	InitializeListHead(&drv_obj->drv_ext->custom_ext);	if (IoAllocateDriverObjectExtension(drv_obj,					    (void *)WRAP_DRIVER_CLIENT_ID,					    sizeof(*wrap_driver),					    (void **)&wrap_driver) !=	    STATUS_SUCCESS)		EXIT1(return -ENOMEM);	TRACE1("driver: %p", wrap_driver);	memset(wrap_driver, 0, sizeof(*wrap_driver));	InitializeListHead(&wrap_driver->list);	InitializeListHead(&wrap_driver->settings);	InitializeListHead(&wrap_driver->wrap_devices);	wrap_driver->drv_obj = drv_obj;	RtlInitAnsiString(&ansi_reg, "/tmp");	if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) !=	    STATUS_SUCCESS) {		ERROR("couldn't initialize registry path");		free_custom_extensions(drv_obj->drv_ext);		kfree(drv_obj->drv_ext);		TRACE1("drv_obj: %p", drv_obj);		ObDereferenceObject(drv_obj);		EXIT1(return -EINVAL);	}	strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name));	wrap_driver->name[sizeof(wrap_driver->name)-1] = 0;	if (load_sys_files(wrap_driver, load_driver) ||	    load_bin_files_info(wrap_driver, load_driver) ||	    load_settings(wrap_driver, load_driver) ||	    start_wrap_driver(wrap_driver) ||	    add_wrap_driver(wrap_driver)) {		unload_wrap_driver(wrap_driver);		EXIT1(return -EINVAL);	} else {		printk(KERN_INFO "%s: driver %s (%s) loaded\n",		       DRIVER_NAME, wrap_driver->name, wrap_driver->version);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)		add_taint(TAINT_PROPRIETARY_MODULE);		/* older kernels don't seem to have a way to set		 * tainted information */#endif		EXIT1(return 0);	}}/* register drivers for pci and usb */static void register_devices(void){	int res;	memset(&wrap_pci_device, 0, sizeof(wrap_pci_device));	wrap_pci_device.vendor = PCI_ANY_ID;	wrap_pci_device.device = PCI_ANY_ID;	wrap_pci_device.subvendor = PCI_ANY_ID;	wrap_pci_device.subdevice = PCI_ANY_ID;	memset(&wrap_pci_driver, 0, sizeof(wrap_pci_driver));	wrap_pci_driver.name = DRIVER_NAME;	wrap_pci_driver.id_table = &wrap_pci_device;	wrap_pci_driver.probe = wrap_pnp_start_pci_device;	wrap_pci_driver.remove = __devexit_p(wrap_pnp_remove_pci_device);	wrap_pci_driver.suspend = wrap_pnp_suspend_pci_device;	wrap_pci_driver.resume = wrap_pnp_resume_pci_device;	res = pci_register_driver(&wrap_pci_driver);	if (res < 0) {		ERROR("couldn't register pci driver: %d", res);		wrap_pci_driver.name = NULL;	}#ifdef CONFIG_USB	memset(&wrap_usb_device, 0, sizeof(wrap_usb_device));	wrap_usb_device.driver_info = 1;	memset(&wrap_usb_driver, 0, sizeof(wrap_usb_driver));	wrap_usb_driver.name = DRIVER_NAME;	wrap_usb_driver.id_table = &wrap_usb_device;	wrap_usb_driver.probe = wrap_pnp_start_usb_device;	wrap_usb_driver.disconnect = __devexit_p(wrap_pnp_remove_usb_device);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)	wrap_usb_driver.suspend = wrap_pnp_suspend_usb_device;	wrap_usb_driver.resume = wrap_pnp_resume_usb_device;#endif	res = usb_register(&wrap_usb_driver);	if (res < 0) {		ERROR("couldn't register usb driver: %d", res);		wrap_usb_driver.name = NULL;	}#endif	EXIT1(return);}static void unregister_devices(void){	struct nt_list *cur, *next;	if (down_interruptible(&loader_mutex))		WARNING("couldn't obtain loader_mutex");	nt_list_for_each_safe(cur, next, &wrap_devices) {		struct wrap_device *wd;		wd = container_of(cur, struct wrap_device, list);		set_bit(HW_PRESENT, &wd->hw_status);	}	up(&loader_mutex);	if (wrap_pci_driver.name)		pci_unregister_driver(&wrap_pci_driver);#ifdef CONFIG_USB	if (wrap_usb_driver.name)		usb_deregister(&wrap_usb_driver);#endif}struct wrap_device *load_wrap_device(struct load_device *load_device){	int ret;	struct nt_list *cur;	struct wrap_device *wd = NULL;	char vendor[5], device[5], subvendor[5], subdevice[5], bus[5];	ENTER1("%04x, %04x, %04x, %04x", load_device->vendor,	       load_device->device, load_device->subvendor,	       load_device->subdevice);	if (sprintf(vendor, "%04x", load_device->vendor) == 4 &&	    sprintf(device, "%04x", load_device->device) == 4 &&	    sprintf(subvendor, "%04x", load_device->subvendor) == 4 &&	    sprintf(subdevice, "%04x", load_device->subdevice) == 4 &&	    sprintf(bus, "%04x", load_device->bus) == 4) {		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE,#if defined(DEBUG) && DEBUG >= 1				"1",#else				"0",#endif				UTILS_VERSION, vendor, device,				subvendor, subdevice, bus, NULL};		char *env[] = {NULL};		TRACE2("%s, %s, %s, %s, %s", vendor, device,		       subvendor, subdevice, bus);		if (down_interruptible(&loader_mutex)) {			WARNING("couldn't obtain loader_mutex");			EXIT1(return NULL);		}		INIT_COMPLETION(loader_complete);		ret = call_usermodehelper("/sbin/loadndisdriver", argv, env#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)					  , 1#endif			);		if (ret) {			up(&loader_mutex);			TRACE1("couldn't load device %04x:%04x; check system "			       "log for messages from 'loadndisdriver'",			       load_device->vendor, load_device->device);			EXIT1(return NULL);		}		wait_for_completion(&loader_complete);		wd = NULL;		nt_list_for_each(cur, &wrap_devices) {			wd = container_of(cur, struct wrap_device, list);			TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor,			       wd->device, wd->subvendor, wd->subdevice);			if (wd->vendor == load_device->vendor &&			    wd->device == load_device->device)				break;			else				wd = NULL;		}		up(&loader_mutex);	} else		wd = NULL;	EXIT1(return wd);}struct wrap_device *get_wrap_device(void *dev, int bus){	struct nt_list *cur;	struct wrap_device *wd;	if (down_interruptible(&loader_mutex)) {		WARNING("couldn't obtain loader_mutex");		return NULL;	}	wd = NULL;	nt_list_for_each(cur, &wrap_devices) {		wd = container_of(cur, struct wrap_device, list);		if (bus == WRAP_PCI_BUS &&		    wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev)			break;		else if (bus == WRAP_USB_BUS &&			 wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev)			break;		else			wd = NULL;	}	up(&loader_mutex);	return wd;}/* called with loader_mutex is down */static int wrapper_ioctl(struct inode *inode, struct file *file,			 unsigned int cmd, unsigned long arg){	struct load_driver *load_driver;	struct load_device load_device;	struct load_driver_file load_bin_file;	int ret;	ENTER1("cmd: %u", cmd);	ret = 0;	switch (cmd) {	case WRAP_IOCTL_LOAD_DEVICE:		if (copy_from_user(&load_device, (void *)arg,				   sizeof(load_device))) {			ret = -EFAULT;			break;		}		TRACE2("%04x, %04x, %04x, %04x", load_device.vendor,		       load_device.device, load_device.subvendor,		       load_device.subdevice);		if (load_device.vendor) {			struct wrap_device *wd;			wd = kmalloc(sizeof(*wd), GFP_KERNEL);			if (!wd) {				ret = -ENOMEM;				break;			}			memset(wd, 0, sizeof(*wd));			InitializeListHead(&wd->settings);			wd->dev_bus = WRAP_BUS(load_device.bus);			wd->vendor = load_device.vendor;			wd->device = load_device.device;			wd->subvendor = load_device.subvendor;			wd->subdevice = load_device.subdevice;			strncpy(wd->conf_file_name, load_device.conf_file_name,				sizeof(wd->conf_file_name));			wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0;			strncpy(wd->driver_name, load_device.driver_name,			       sizeof(wd->driver_name));			wd->driver_name[sizeof(wd->driver_name)-1] = 0;			InsertHeadList(&wrap_devices, &wd->list);			ret = 0;		} else			ret = -EINVAL;		break;	case WRAP_IOCTL_LOAD_DRIVER:		TRACE1("loading driver at %p", (void *)arg);		load_driver = vmalloc(sizeof(*load_driver));		if (!load_driver) {			ret = -ENOMEM;			break;		}		if (copy_from_user(load_driver, (void *)arg,				   sizeof(*load_driver)))			ret = -EFAULT;		else			ret = load_user_space_driver(load_driver);		vfree(load_driver);		break;	case WRAP_IOCTL_LOAD_BIN_FILE:		if (copy_from_user(&load_bin_file, (void *)arg,				   sizeof(load_bin_file)))			ret = -EFAULT;		else			ret = add_bin_file(&load_bin_file);		break;	default:		ERROR("unknown ioctl %u", cmd);		ret = -EINVAL;		break;	}	complete(&loader_complete);	EXIT1(return ret);}static int wrapper_ioctl_release(struct inode *inode, struct file *file){	ENTER1("");	return 0;}static struct file_operations wrapper_fops = {	.owner          = THIS_MODULE,	.ioctl		= wrapper_ioctl,	.release	= wrapper_ioctl_release,};static struct miscdevice wrapper_misc = {	.name   = DRIVER_NAME,	.minor	= MISC_DYNAMIC_MINOR,	.fops   = &wrapper_fops};int loader_init(void){	int err;	InitializeListHead(&wrap_drivers);	InitializeListHead(&wrap_devices);	init_MUTEX(&loader_mutex);	init_completion(&loader_complete);	if ((err = misc_register(&wrapper_misc)) < 0 ) {		ERROR("couldn't register module (%d)", err);		unregister_devices();		EXIT1(return err);	}	register_devices();	EXIT1(return 0);}void loader_exit(void){	struct nt_list *cur, *next;	ENTER1("");	misc_deregister(&wrapper_misc);	unregister_devices();	if (down_interruptible(&loader_mutex))		WARNING("couldn't obtain loader_mutex");	nt_list_for_each_safe(cur, next, &wrap_drivers) {		struct wrap_driver *driver;		driver = container_of(cur, struct wrap_driver, list);		unload_wrap_driver(driver);	}	up(&loader_mutex);	EXIT1(return);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -