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

📄 loader.c

📁 ndis在linux下的无线网卡驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *  GNU General Public License for more details. * */#include "ndis.h"#include "loader.h"#include "wrapndis.h"#include "pnp.h"#include <linux/module.h>#include <linux/kmod.h>#include <linux/miscdevice.h>#include <asm/uaccess.h>/*  Network adapter: ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318}  Network client: ClassGuid = {4d36e973-e325-11ce-bfc1-08002be10318}  PCMCIA adapter: ClassGuid = {4d36e977-e325-11ce-bfc1-08002be10318}  USB: ClassGuid = {36fc9e60-c465-11cf-8056-444553540000}*//* the indices used here must match macros WRAP_NDIS_DEVICE etc. */static struct guid class_guids[] = {	/* Network */	{0x4d36e972, 0xe325, 0x11ce, },	/* USB WDM */	{0x36fc9e60, 0xc465, 0x11cf, },	/* Bluetooth */	{0xe0cbf06c, 0xcd8b, 0x4647, },	/* ivtcorporatino.com's bluetooth device claims this is	 * bluetooth guid */	{0xf12d3cf8, 0xb11d, 0x457e, },};struct semaphore loader_mutex;static struct completion loader_complete;static struct nt_list wrap_devices;static struct nt_list wrap_drivers;static struct pci_device_id wrap_pci_device;static struct pci_driver wrap_pci_driver;#if defined(CONFIG_USB)static struct usb_device_id wrap_usb_device;static struct usb_driver wrap_usb_driver;#endifint wrap_device_type(int data1){	int i;	for (i = 0; i < sizeof(class_guids) / sizeof(class_guids[0]); i++)		if (data1 == class_guids[i].data1)			return i;	ERROR("unknown device: 0x%x\n", data1);	return -1;}/* load driver for given device, if not already loaded */struct wrap_driver *load_wrap_driver(struct wrap_device *wd){	int ret;	struct nt_list *cur;	struct wrap_driver *wrap_driver;	ENTER1("device: %04X:%04X:%04X:%04X", wd->vendor, wd->device,	       wd->subvendor, wd->subdevice);	if (down_interruptible(&loader_mutex)) {		WARNING("couldn't obtain loader_mutex");		EXIT1(return NULL);	}	wrap_driver = NULL;	nt_list_for_each(cur, &wrap_drivers) {		wrap_driver = container_of(cur, struct wrap_driver, list);		if (!stricmp(wrap_driver->name, wd->driver_name)) {			TRACE1("driver %s already loaded", wrap_driver->name);			break;		} else			wrap_driver = NULL;	}	up(&loader_mutex);	if (!wrap_driver) {		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER,#if defined(DEBUG) && DEBUG >= 1				"1",#else				"0",#endif				UTILS_VERSION, wd->driver_name,				wd->conf_file_name, NULL};		char *env[] = {NULL};		TRACE1("loading driver %s", wd->driver_name);		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);			ERROR("couldn't load driver %s; check system log "			      "for messages from 'loadndisdriver'",			      wd->driver_name);			EXIT1(return NULL);		}		wait_for_completion(&loader_complete);		TRACE1("%s", wd->driver_name);		wrap_driver = NULL;		nt_list_for_each(cur, &wrap_drivers) {			wrap_driver = container_of(cur, struct wrap_driver,						   list);			if (!stricmp(wrap_driver->name, wd->driver_name)) {				wd->driver = wrap_driver;				break;			} else				wrap_driver = NULL;		}		up(&loader_mutex);		if (wrap_driver)			TRACE1("driver %s is loaded", wrap_driver->name);		else			ERROR("couldn't load driver '%s'", wd->driver_name);	}	EXIT1(return wrap_driver);}/* load the driver files from userspace. */static int load_sys_files(struct wrap_driver *driver,			  struct load_driver *load_driver){	int i, err;	TRACE1("num_pe_images = %d", load_driver->nr_sys_files);	TRACE1("loading driver: %s", load_driver->name);	strncpy(driver->name, load_driver->name, sizeof(driver->name));	driver->name[sizeof(driver->name)-1] = 0;	TRACE1("driver: %s", driver->name);	err = 0;	driver->num_pe_images = 0;	for (i = 0; i < load_driver->nr_sys_files; i++) {		struct pe_image *pe_image;		pe_image = &driver->pe_images[driver->num_pe_images];		strncpy(pe_image->name, load_driver->sys_files[i].name,			sizeof(pe_image->name));		pe_image->name[sizeof(pe_image->name)-1] = 0;		TRACE1("image size: %lu bytes",		       (unsigned long)load_driver->sys_files[i].size);#ifdef CONFIG_X86_64#ifdef PAGE_KERNEL_EXECUTABLE		pe_image->image =			__vmalloc(load_driver->sys_files[i].size,				  GFP_KERNEL | __GFP_HIGHMEM,				  PAGE_KERNEL_EXECUTABLE);#elif defined PAGE_KERNEL_EXEC		pe_image->image =			__vmalloc(load_driver->sys_files[i].size,				  GFP_KERNEL | __GFP_HIGHMEM,				  PAGE_KERNEL_EXEC);#else#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC#endif#else		/* hate to play with kernel macros, but PAGE_KERNEL_EXEC is		 * not available to modules! */#ifdef cpu_has_nx		if (cpu_has_nx)			pe_image->image =				__vmalloc(load_driver->sys_files[i].size,					  GFP_KERNEL | __GFP_HIGHMEM,					  __pgprot(__PAGE_KERNEL & ~_PAGE_NX));		else			pe_image->image =				vmalloc(load_driver->sys_files[i].size);#else			pe_image->image =				vmalloc(load_driver->sys_files[i].size);#endif#endif		if (!pe_image->image) {			ERROR("couldn't allocate memory");			err = -ENOMEM;			break;		}		TRACE1("image is at %p", pe_image->image);		if (copy_from_user(pe_image->image,				   load_driver->sys_files[i].data,				   load_driver->sys_files[i].size)) {			ERROR("couldn't load file %s",			      load_driver->sys_files[i].name);			err = -EFAULT;			break;		}		pe_image->size = load_driver->sys_files[i].size;		driver->num_pe_images++;	}	if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) {		ERROR("couldn't prepare driver '%s'", load_driver->name);		err = -EINVAL;	}	if (driver->num_pe_images < load_driver->nr_sys_files || err) {		for (i = 0; i < driver->num_pe_images; i++)			if (driver->pe_images[i].image)				vfree(driver->pe_images[i].image);		driver->num_pe_images = 0;		EXIT1(return err);	} else		EXIT1(return 0);}struct wrap_bin_file *get_bin_file(char *bin_file_name){	int i = 0;	struct wrap_driver *driver, *cur;	ENTER1("%s", bin_file_name);	if (down_interruptible(&loader_mutex)) {		WARNING("couldn't obtain loader_mutex");		EXIT1(return NULL);	}	driver = NULL;	nt_list_for_each_entry(cur, &wrap_drivers, list) {		for (i = 0; i < cur->num_bin_files; i++)			if (!stricmp(cur->bin_files[i].name, bin_file_name)) {				driver = cur;				break;			}		if (driver)			break;	}	up(&loader_mutex);	if (!driver) {		TRACE1("coudln't find bin file '%s'", bin_file_name);		return NULL;	}	if (!driver->bin_files[i].data) {		char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE,#if defined(DEBUG) && DEBUG >= 1				"1",#else				"0",#endif				UTILS_VERSION, driver->name,				driver->bin_files[i].name, NULL};		char *env[] = {NULL};		int ret;		TRACE1("loading bin file %s/%s", driver->name,		       driver->bin_files[i].name);		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);			ERROR("couldn't load file %s/%s; check system log "			      "for messages from 'loadndisdriver'",			      driver->name, driver->bin_files[i].name);			EXIT1(return NULL);		}		wait_for_completion(&loader_complete);		up(&loader_mutex);		if (!driver->bin_files[i].data) {			WARNING("couldn't load binary file %s",				driver->bin_files[i].name);			EXIT1(return NULL);		}	}	EXIT2(return &(driver->bin_files[i]));}/* called with loader_mutex down */static int add_bin_file(struct load_driver_file *driver_file){	struct wrap_driver *driver, *cur;	struct wrap_bin_file *bin_file;	int i = 0;	driver = NULL;	nt_list_for_each_entry(cur, &wrap_drivers, list) {		for (i = 0; i < cur->num_bin_files; i++)			if (!stricmp(cur->bin_files[i].name,				     driver_file->name)) {				driver = cur;				break;			}		if (driver)			break;	}	if (!driver) {		ERROR("couldn't find %s", driver_file->name);		return -EINVAL;	}	bin_file = &driver->bin_files[i];	strncpy(bin_file->name, driver_file->name, sizeof(bin_file->name));	bin_file->name[sizeof(bin_file->name)-1] = 0;	bin_file->data = vmalloc(driver_file->size);	if (!bin_file->data) {		ERROR("couldn't allocate memory");		return -ENOMEM;	}	bin_file->size = driver_file->size;	if (copy_from_user(bin_file->data, driver_file->data, bin_file->size)) {		ERROR("couldn't copy data");		free_bin_file(bin_file);		return -EFAULT;	}	return 0;}void free_bin_file(struct wrap_bin_file *bin_file){	TRACE2("unloading %s", bin_file->name);	if (bin_file->data)		vfree(bin_file->data);	bin_file->data = NULL;	bin_file->size = 0;	EXIT2(return);}/* load firmware files from userspace */static int load_bin_files_info(struct wrap_driver *driver,			       struct load_driver *load_driver){	struct wrap_bin_file *bin_files;	int i;	ENTER1("loading bin files for driver %s", load_driver->name);	bin_files = kmalloc(load_driver->nr_bin_files * sizeof(*bin_files),			    GFP_KERNEL);	if (!bin_files) {		ERROR("couldn't allocate memory");		EXIT1(return -ENOMEM);	}	memset(bin_files, 0, load_driver->nr_bin_files * sizeof(*bin_files));	for (i = 0; i < load_driver->nr_bin_files; i++) {		strncpy(bin_files[i].name, load_driver->bin_files[i].name,			sizeof(bin_files[i].name));		bin_files[i].name[sizeof(bin_files[i].name)-1] = 0;		TRACE2("loaded bin file %s", bin_files[i].name);	}	driver->num_bin_files = load_driver->nr_bin_files;	driver->bin_files = bin_files;	EXIT1(return 0);}/* load settnigs for a device. called with loader_mutex down */static int load_settings(struct wrap_driver *wrap_driver,			 struct load_driver *load_driver){	int i, nr_settings;	ENTER1("%p, %p", wrap_driver, load_driver);	nr_settings = 0;	for (i = 0; i < load_driver->nr_settings; i++) {		struct load_device_setting *load_setting =			&load_driver->settings[i];		struct wrap_device_setting *setting;		ULONG data1;		setting = kmalloc(sizeof(*setting), GFP_KERNEL);		if (!setting) {			ERROR("couldn't allocate memory");			break;		}		memset(setting, 0, sizeof(*setting));		strncpy(setting->name, load_setting->name,			sizeof(setting->name));		setting->name[sizeof(setting->name)-1] = 0;		strncpy(setting->value, load_setting->value,		       sizeof(setting->value));		setting->value[sizeof(setting->value)-1] = 0;		TRACE2("%p: %s=%s", setting, setting->name, setting->value);		if (strcmp(setting->name, "driver_version") == 0) {			strncpy(wrap_driver->version, setting->value,				sizeof(wrap_driver->version));			wrap_driver->version[sizeof(wrap_driver->version)-1] = 0;		} else if (strcmp(setting->name, "class_guid") == 0 &&			   sscanf(setting->value, "%x", &data1) == 1) {			wrap_driver->dev_type = wrap_device_type(data1);			if (wrap_driver->dev_type < 0) {				WARNING("unknown guid: %x", data1);				wrap_driver->dev_type = 0;			}		}		InsertTailList(&wrap_driver->settings, &setting->list);		nr_settings++;	}	/* it is not a fatal error if some settings couldn't be loaded */	if (nr_settings > 0)		EXIT1(return 0);	else		EXIT1(return -EINVAL);}void unload_wrap_device(struct wrap_device *wd){	struct nt_list *cur;	ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd,	       wd->vendor, wd->device, wd->subvendor, wd->subdevice,	       wd->driver_name);	if (down_interruptible(&loader_mutex))		WARNING("couldn't obtain loader_mutex");	while ((cur = RemoveHeadList(&wd->settings))) {		struct wrap_device_setting *setting;		setting = container_of(cur, struct wrap_device_setting, list);		kfree(setting);	}	RemoveEntryList(&wd->list);	up(&loader_mutex);	kfree(wd);	EXIT1(return);}/* should be called with loader_mutex down */void unload_wrap_driver(struct wrap_driver *driver){	int i;	struct driver_object *drv_obj;	struct nt_list *cur, *next;

⌨️ 快捷键说明

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