2
* Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
21
#include <linux/module.h>
22
#include <linux/kmod.h>
23
#include <linux/miscdevice.h>
24
#include <asm/uaccess.h>
27
Network adapter: ClassGuid = {4d36e972-e325-11ce-bfc1-08002be10318}
28
Network client: ClassGuid = {4d36e973-e325-11ce-bfc1-08002be10318}
29
PCMCIA adapter: ClassGuid = {4d36e977-e325-11ce-bfc1-08002be10318}
30
USB: ClassGuid = {36fc9e60-c465-11cf-8056-444553540000}
33
/* the indices used here must match macros WRAP_NDIS_DEVICE etc. */
34
static struct guid class_guids[] = {
36
{0x4d36e972, 0xe325, 0x11ce, },
38
{0x36fc9e60, 0xc465, 0x11cf, },
40
{0xe0cbf06c, 0xcd8b, 0x4647, },
41
/* ivtcorporatino.com's bluetooth device claims this is
43
{0xf12d3cf8, 0xb11d, 0x457e, },
46
struct semaphore loader_mutex;
47
static struct completion loader_complete;
49
static struct nt_list wrap_devices;
50
static struct nt_list wrap_drivers;
52
static int wrap_device_type(int data1)
55
for (i = 0; i < sizeof(class_guids) / sizeof(class_guids[0]); i++)
56
if (data1 == class_guids[i].data1)
58
ERROR("unknown device: 0x%x\n", data1);
62
/* load driver for given device, if not already loaded */
63
struct wrap_driver *load_wrap_driver(struct wrap_device *wd)
67
struct wrap_driver *wrap_driver;
69
ENTER1("device: %04X:%04X:%04X:%04X", wd->vendor, wd->device,
70
wd->subvendor, wd->subdevice);
71
if (down_interruptible(&loader_mutex)) {
72
WARNING("couldn't obtain loader_mutex");
76
nt_list_for_each(cur, &wrap_drivers) {
77
wrap_driver = container_of(cur, struct wrap_driver, list);
78
if (!stricmp(wrap_driver->name, wd->driver_name)) {
79
TRACE1("driver %s already loaded", wrap_driver->name);
87
char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER,
88
#if defined(DEBUG) && DEBUG >= 1
93
UTILS_VERSION, wd->driver_name,
94
wd->conf_file_name, NULL};
97
TRACE1("loading driver %s", wd->driver_name);
98
if (down_interruptible(&loader_mutex)) {
99
WARNING("couldn't obtain loader_mutex");
102
INIT_COMPLETION(loader_complete);
103
ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
106
ERROR("couldn't load driver %s; check system log "
107
"for messages from 'loadndisdriver'",
111
wait_for_completion(&loader_complete);
112
TRACE1("%s", wd->driver_name);
114
nt_list_for_each(cur, &wrap_drivers) {
115
wrap_driver = container_of(cur, struct wrap_driver,
117
if (!stricmp(wrap_driver->name, wd->driver_name)) {
118
wd->driver = wrap_driver;
125
TRACE1("driver %s is loaded", wrap_driver->name);
127
ERROR("couldn't load driver '%s'", wd->driver_name);
129
EXIT1(return wrap_driver);
132
/* load the driver files from userspace. */
133
static int load_sys_files(struct wrap_driver *driver,
134
struct load_driver *load_driver)
138
TRACE1("num_pe_images = %d", load_driver->num_sys_files);
139
TRACE1("loading driver: %s", load_driver->name);
140
strncpy(driver->name, load_driver->name, sizeof(driver->name));
141
driver->name[sizeof(driver->name)-1] = 0;
142
TRACE1("driver: %s", driver->name);
144
driver->num_pe_images = 0;
145
for (i = 0; i < load_driver->num_sys_files; i++) {
146
struct pe_image *pe_image;
147
pe_image = &driver->pe_images[driver->num_pe_images];
149
strncpy(pe_image->name, load_driver->sys_files[i].name,
150
sizeof(pe_image->name));
151
pe_image->name[sizeof(pe_image->name)-1] = 0;
152
TRACE1("image size: %lu bytes",
153
(unsigned long)load_driver->sys_files[i].size);
156
#ifdef PAGE_KERNEL_EXECUTABLE
158
__vmalloc(load_driver->sys_files[i].size,
159
GFP_KERNEL | __GFP_HIGHMEM,
160
PAGE_KERNEL_EXECUTABLE);
161
#elif defined PAGE_KERNEL_EXEC
163
__vmalloc(load_driver->sys_files[i].size,
164
GFP_KERNEL | __GFP_HIGHMEM,
167
#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
170
/* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
171
* not available to modules! */
175
__vmalloc(load_driver->sys_files[i].size,
176
GFP_KERNEL | __GFP_HIGHMEM,
177
__pgprot(__PAGE_KERNEL & ~_PAGE_NX));
180
vmalloc(load_driver->sys_files[i].size);
183
vmalloc(load_driver->sys_files[i].size);
186
if (!pe_image->image) {
187
ERROR("couldn't allocate memory");
191
TRACE1("image is at %p", pe_image->image);
193
if (copy_from_user(pe_image->image,
194
load_driver->sys_files[i].data,
195
load_driver->sys_files[i].size)) {
196
ERROR("couldn't load file %s",
197
load_driver->sys_files[i].name);
201
pe_image->size = load_driver->sys_files[i].size;
202
driver->num_pe_images++;
205
if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) {
206
ERROR("couldn't prepare driver '%s'", load_driver->name);
210
if (driver->num_pe_images < load_driver->num_sys_files || err) {
211
for (i = 0; i < driver->num_pe_images; i++)
212
if (driver->pe_images[i].image)
213
vfree(driver->pe_images[i].image);
214
driver->num_pe_images = 0;
220
struct wrap_bin_file *get_bin_file(char *bin_file_name)
223
struct wrap_driver *driver, *cur;
225
ENTER1("%s", bin_file_name);
226
if (down_interruptible(&loader_mutex)) {
227
WARNING("couldn't obtain loader_mutex");
231
nt_list_for_each_entry(cur, &wrap_drivers, list) {
232
for (i = 0; i < cur->num_bin_files; i++)
233
if (!stricmp(cur->bin_files[i].name, bin_file_name)) {
242
TRACE1("coudln't find bin file '%s'", bin_file_name);
246
if (!driver->bin_files[i].data) {
247
char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE,
248
#if defined(DEBUG) && DEBUG >= 1
253
UTILS_VERSION, driver->name,
254
driver->bin_files[i].name, NULL};
255
char *env[] = {NULL};
258
TRACE1("loading bin file %s/%s", driver->name,
259
driver->bin_files[i].name);
260
if (down_interruptible(&loader_mutex)) {
261
WARNING("couldn't obtain loader_mutex");
264
INIT_COMPLETION(loader_complete);
265
ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
268
ERROR("couldn't load file %s/%s; check system log "
269
"for messages from 'loadndisdriver' (%d)",
270
driver->name, driver->bin_files[i].name, ret);
273
wait_for_completion(&loader_complete);
275
if (!driver->bin_files[i].data) {
276
WARNING("couldn't load binary file %s",
277
driver->bin_files[i].name);
281
EXIT2(return &(driver->bin_files[i]));
284
/* called with loader_mutex down */
285
static int add_bin_file(struct load_driver_file *driver_file)
287
struct wrap_driver *driver, *cur;
288
struct wrap_bin_file *bin_file;
292
nt_list_for_each_entry(cur, &wrap_drivers, list) {
293
for (i = 0; i < cur->num_bin_files; i++)
294
if (!stricmp(cur->bin_files[i].name,
295
driver_file->name)) {
303
ERROR("couldn't find %s", driver_file->name);
306
bin_file = &driver->bin_files[i];
307
strncpy(bin_file->name, driver_file->name, sizeof(bin_file->name));
308
bin_file->name[sizeof(bin_file->name)-1] = 0;
309
bin_file->data = vmalloc(driver_file->size);
310
if (!bin_file->data) {
311
ERROR("couldn't allocate memory");
314
bin_file->size = driver_file->size;
315
if (copy_from_user(bin_file->data, driver_file->data, bin_file->size)) {
316
ERROR("couldn't copy data");
317
free_bin_file(bin_file);
323
void free_bin_file(struct wrap_bin_file *bin_file)
325
TRACE2("unloading %s", bin_file->name);
327
vfree(bin_file->data);
328
bin_file->data = NULL;
333
/* load firmware files from userspace */
334
static int load_bin_files_info(struct wrap_driver *driver,
335
struct load_driver *load_driver)
337
struct wrap_bin_file *bin_files;
340
ENTER1("%s, %d", load_driver->name, load_driver->num_bin_files);
341
driver->num_bin_files = 0;
342
driver->bin_files = NULL;
343
if (load_driver->num_bin_files == 0)
345
bin_files = kzalloc(load_driver->num_bin_files * sizeof(*bin_files),
348
ERROR("couldn't allocate memory");
349
EXIT1(return -ENOMEM);
352
for (i = 0; i < load_driver->num_bin_files; i++) {
353
strncpy(bin_files[i].name, load_driver->bin_files[i].name,
354
sizeof(bin_files[i].name));
355
bin_files[i].name[sizeof(bin_files[i].name)-1] = 0;
356
TRACE2("loaded bin file %s", bin_files[i].name);
358
driver->num_bin_files = load_driver->num_bin_files;
359
driver->bin_files = bin_files;
363
/* load settnigs for a device. called with loader_mutex down */
364
static int load_settings(struct wrap_driver *wrap_driver,
365
struct load_driver *load_driver)
369
ENTER1("%p, %p", wrap_driver, load_driver);
372
for (i = 0; i < load_driver->num_settings; i++) {
373
struct load_device_setting *load_setting =
374
&load_driver->settings[i];
375
struct wrap_device_setting *setting;
378
setting = kzalloc(sizeof(*setting), GFP_KERNEL);
380
ERROR("couldn't allocate memory");
383
strncpy(setting->name, load_setting->name,
384
sizeof(setting->name));
385
setting->name[sizeof(setting->name)-1] = 0;
386
strncpy(setting->value, load_setting->value,
387
sizeof(setting->value));
388
setting->value[sizeof(setting->value)-1] = 0;
389
TRACE2("%p: %s=%s", setting, setting->name, setting->value);
391
if (strcmp(setting->name, "driver_version") == 0) {
392
strncpy(wrap_driver->version, setting->value,
393
sizeof(wrap_driver->version));
394
wrap_driver->version[sizeof(wrap_driver->version)-1] = 0;
395
} else if (strcmp(setting->name, "class_guid") == 0 &&
396
sscanf(setting->value, "%x", &data1) == 1) {
397
wrap_driver->dev_type = wrap_device_type(data1);
398
if (wrap_driver->dev_type < 0) {
399
WARNING("unknown guid: %x", data1);
400
wrap_driver->dev_type = 0;
403
InsertTailList(&wrap_driver->settings, &setting->list);
406
/* it is not a fatal error if some settings couldn't be loaded */
407
if (num_settings > 0)
410
EXIT1(return -EINVAL);
413
void unload_wrap_device(struct wrap_device *wd)
416
ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd,
417
wd->vendor, wd->device, wd->subvendor, wd->subdevice,
419
if (down_interruptible(&loader_mutex))
420
WARNING("couldn't obtain loader_mutex");
421
while ((cur = RemoveHeadList(&wd->settings))) {
422
struct wrap_device_setting *setting;
423
setting = container_of(cur, struct wrap_device_setting, list);
426
RemoveEntryList(&wd->list);
432
/* should be called with loader_mutex down */
433
void unload_wrap_driver(struct wrap_driver *driver)
436
struct driver_object *drv_obj;
437
struct nt_list *cur, *next;
439
ENTER1("unloading driver: %s (%p)", driver->name, driver);
440
TRACE1("freeing %d images", driver->num_pe_images);
441
drv_obj = driver->drv_obj;
442
for (i = 0; i < driver->num_pe_images; i++)
443
if (driver->pe_images[i].image) {
444
TRACE1("freeing image at %p",
445
driver->pe_images[i].image);
446
vfree(driver->pe_images[i].image);
449
TRACE1("freeing %d bin files", driver->num_bin_files);
450
for (i = 0; i < driver->num_bin_files; i++) {
451
TRACE1("freeing image at %p", driver->bin_files[i].data);
452
if (driver->bin_files[i].data)
453
vfree(driver->bin_files[i].data);
455
if (driver->bin_files)
456
kfree(driver->bin_files);
457
RtlFreeUnicodeString(&drv_obj->name);
458
RemoveEntryList(&driver->list);
459
nt_list_for_each_safe(cur, next, &driver->settings) {
460
struct wrap_device_setting *setting;
461
struct ndis_configuration_parameter *param;
463
setting = container_of(cur, struct wrap_device_setting, list);
464
TRACE2("%p", setting);
465
param = setting->encoded;
468
if (param->type == NdisParameterString)
469
RtlFreeUnicodeString(¶m->data.string);
474
/* this frees driver */
475
free_custom_extensions(drv_obj->drv_ext);
476
kfree(drv_obj->drv_ext);
477
TRACE1("drv_obj: %p", drv_obj);
482
/* call the entry point of the driver */
483
static int start_wrap_driver(struct wrap_driver *driver)
487
struct driver_object *drv_obj;
488
typeof(driver->pe_images[0].entry) entry;
490
ENTER1("%s", driver->name);
491
drv_obj = driver->drv_obj;
492
for (ret = res = 0, i = 0; i < driver->num_pe_images; i++)
493
/* dlls are already started by loader */
494
if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) {
495
entry = driver->pe_images[i].entry;
496
drv_obj->start = driver->pe_images[i].entry;
497
drv_obj->driver_size = driver->pe_images[i].size;
498
TRACE1("entry: %p, %p, drv_obj: %p",
499
entry, *entry, drv_obj);
500
res = LIN2WIN2(entry, drv_obj, &drv_obj->name);
502
TRACE1("entry returns %08X", res);
506
ERROR("driver initialization failed: %08X", ret);
507
RtlFreeUnicodeString(&drv_obj->name);
508
/* this frees ndis_driver */
509
free_custom_extensions(drv_obj->drv_ext);
510
kfree(drv_obj->drv_ext);
511
TRACE1("drv_obj: %p", drv_obj);
512
ObDereferenceObject(drv_obj);
513
EXIT1(return -EINVAL);
519
* add driver to list of loaded driver but make sure this driver is
520
* not loaded before. called with loader_mutex down
522
static int add_wrap_driver(struct wrap_driver *driver)
524
struct wrap_driver *tmp;
526
ENTER1("name: %s", driver->name);
527
nt_list_for_each_entry(tmp, &wrap_drivers, list) {
528
if (stricmp(tmp->name, driver->name) == 0) {
529
ERROR("cannot add duplicate driver");
530
EXIT1(return -EBUSY);
533
InsertHeadList(&wrap_drivers, &driver->list);
537
/* load a driver from userspace and initialize it. called with
538
* loader_mutex down */
539
static int load_user_space_driver(struct load_driver *load_driver)
541
struct driver_object *drv_obj;
542
struct ansi_string ansi_reg;
543
struct wrap_driver *wrap_driver = NULL;
545
ENTER1("%p", load_driver);
546
drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL);
548
ERROR("couldn't allocate memory");
549
EXIT1(return -ENOMEM);
551
TRACE1("drv_obj: %p", drv_obj);
552
drv_obj->drv_ext = kzalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL);
553
if (!drv_obj->drv_ext) {
554
ERROR("couldn't allocate memory");
555
ObDereferenceObject(drv_obj);
556
EXIT1(return -ENOMEM);
558
InitializeListHead(&drv_obj->drv_ext->custom_ext);
559
if (IoAllocateDriverObjectExtension(drv_obj,
560
(void *)WRAP_DRIVER_CLIENT_ID,
561
sizeof(*wrap_driver),
562
(void **)&wrap_driver) !=
564
EXIT1(return -ENOMEM);
565
TRACE1("driver: %p", wrap_driver);
566
memset(wrap_driver, 0, sizeof(*wrap_driver));
567
InitializeListHead(&wrap_driver->list);
568
InitializeListHead(&wrap_driver->settings);
569
InitializeListHead(&wrap_driver->wrap_devices);
570
wrap_driver->drv_obj = drv_obj;
571
RtlInitAnsiString(&ansi_reg, "/tmp");
572
if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) !=
574
ERROR("couldn't initialize registry path");
575
free_custom_extensions(drv_obj->drv_ext);
576
kfree(drv_obj->drv_ext);
577
TRACE1("drv_obj: %p", drv_obj);
578
ObDereferenceObject(drv_obj);
579
EXIT1(return -EINVAL);
581
strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name));
582
wrap_driver->name[sizeof(wrap_driver->name)-1] = 0;
583
if (load_sys_files(wrap_driver, load_driver) ||
584
load_bin_files_info(wrap_driver, load_driver) ||
585
load_settings(wrap_driver, load_driver) ||
586
start_wrap_driver(wrap_driver) ||
587
add_wrap_driver(wrap_driver)) {
588
unload_wrap_driver(wrap_driver);
589
EXIT1(return -EINVAL);
591
printk(KERN_INFO "%s: driver %s (%s) loaded\n",
592
DRIVER_NAME, wrap_driver->name, wrap_driver->version);
593
add_taint(TAINT_PROPRIETARY_MODULE);
598
static struct pci_device_id wrap_pci_id_table[] = {
599
{PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID},
602
static struct pci_driver wrap_pci_driver = {
604
.id_table = wrap_pci_id_table,
605
.probe = wrap_pnp_start_pci_device,
606
.remove = __devexit_p(wrap_pnp_remove_pci_device),
607
.suspend = wrap_pnp_suspend_pci_device,
608
.resume = wrap_pnp_resume_pci_device,
612
static struct usb_device_id wrap_usb_id_table[] = {
618
static struct usb_driver wrap_usb_driver = {
620
.id_table = wrap_usb_id_table,
621
.probe = wrap_pnp_start_usb_device,
622
.disconnect = __devexit_p(wrap_pnp_remove_usb_device),
623
.suspend = wrap_pnp_suspend_usb_device,
624
.resume = wrap_pnp_resume_usb_device,
628
/* register drivers for pci and usb */
629
static void register_devices(void)
633
res = pci_register_driver(&wrap_pci_driver);
635
ERROR("couldn't register pci driver: %d", res);
636
wrap_pci_driver.name = NULL;
640
res = usb_register(&wrap_usb_driver);
642
ERROR("couldn't register usb driver: %d", res);
643
wrap_usb_driver.name = NULL;
649
static void unregister_devices(void)
651
struct nt_list *cur, *next;
653
if (down_interruptible(&loader_mutex))
654
WARNING("couldn't obtain loader_mutex");
655
nt_list_for_each_safe(cur, next, &wrap_devices) {
656
struct wrap_device *wd;
657
wd = container_of(cur, struct wrap_device, list);
658
set_bit(HW_PRESENT, &wd->hw_status);
662
if (wrap_pci_driver.name)
663
pci_unregister_driver(&wrap_pci_driver);
665
if (wrap_usb_driver.name)
666
usb_deregister(&wrap_usb_driver);
670
struct wrap_device *load_wrap_device(struct load_device *load_device)
674
struct wrap_device *wd = NULL;
675
char vendor[5], device[5], subvendor[5], subdevice[5], bus[5];
677
ENTER1("%04x, %04x, %04x, %04x", load_device->vendor,
678
load_device->device, load_device->subvendor,
679
load_device->subdevice);
680
if (sprintf(vendor, "%04x", load_device->vendor) == 4 &&
681
sprintf(device, "%04x", load_device->device) == 4 &&
682
sprintf(subvendor, "%04x", load_device->subvendor) == 4 &&
683
sprintf(subdevice, "%04x", load_device->subdevice) == 4 &&
684
sprintf(bus, "%04x", load_device->bus) == 4) {
685
char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE,
686
#if defined(DEBUG) && DEBUG >= 1
691
UTILS_VERSION, vendor, device,
692
subvendor, subdevice, bus, NULL};
693
char *env[] = {NULL};
694
TRACE2("%s, %s, %s, %s, %s", vendor, device,
695
subvendor, subdevice, bus);
696
if (down_interruptible(&loader_mutex)) {
697
WARNING("couldn't obtain loader_mutex");
700
INIT_COMPLETION(loader_complete);
701
ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
704
TRACE1("couldn't load device %04x:%04x; check system "
705
"log for messages from 'loadndisdriver'",
706
load_device->vendor, load_device->device);
709
wait_for_completion(&loader_complete);
711
nt_list_for_each(cur, &wrap_devices) {
712
wd = container_of(cur, struct wrap_device, list);
713
TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor,
714
wd->device, wd->subvendor, wd->subdevice);
715
if (wd->vendor == load_device->vendor &&
716
wd->device == load_device->device)
727
struct wrap_device *get_wrap_device(void *dev, int bus)
730
struct wrap_device *wd;
732
if (down_interruptible(&loader_mutex)) {
733
WARNING("couldn't obtain loader_mutex");
737
nt_list_for_each(cur, &wrap_devices) {
738
wd = container_of(cur, struct wrap_device, list);
739
if (bus == WRAP_PCI_BUS &&
740
wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev)
742
else if (bus == WRAP_USB_BUS &&
743
wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev)
752
/* called with loader_mutex is down */
753
static int wrapper_ioctl(struct inode *inode, struct file *file,
754
unsigned int cmd, unsigned long arg)
756
struct load_driver *load_driver;
757
struct load_device load_device;
758
struct load_driver_file load_bin_file;
760
void __user *addr = (void __user *)arg;
762
ENTER1("cmd: %u", cmd);
766
case WRAP_IOCTL_LOAD_DEVICE:
767
if (copy_from_user(&load_device, addr, sizeof(load_device))) {
771
TRACE2("%04x, %04x, %04x, %04x", load_device.vendor,
772
load_device.device, load_device.subvendor,
773
load_device.subdevice);
774
if (load_device.vendor) {
775
struct wrap_device *wd;
776
wd = kzalloc(sizeof(*wd), GFP_KERNEL);
781
InitializeListHead(&wd->settings);
782
wd->dev_bus = WRAP_BUS(load_device.bus);
783
wd->vendor = load_device.vendor;
784
wd->device = load_device.device;
785
wd->subvendor = load_device.subvendor;
786
wd->subdevice = load_device.subdevice;
787
strncpy(wd->conf_file_name, load_device.conf_file_name,
788
sizeof(wd->conf_file_name));
789
wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0;
790
strncpy(wd->driver_name, load_device.driver_name,
791
sizeof(wd->driver_name));
792
wd->driver_name[sizeof(wd->driver_name)-1] = 0;
793
InsertHeadList(&wrap_devices, &wd->list);
798
case WRAP_IOCTL_LOAD_DRIVER:
799
TRACE1("loading driver at %p", addr);
800
load_driver = vmalloc(sizeof(*load_driver));
805
if (copy_from_user(load_driver, addr, sizeof(*load_driver)))
808
ret = load_user_space_driver(load_driver);
811
case WRAP_IOCTL_LOAD_BIN_FILE:
812
if (copy_from_user(&load_bin_file, addr, sizeof(load_bin_file)))
815
ret = add_bin_file(&load_bin_file);
818
ERROR("unknown ioctl %u", cmd);
822
complete(&loader_complete);
826
static int wrapper_ioctl_release(struct inode *inode, struct file *file)
832
static struct file_operations wrapper_fops = {
833
.owner = THIS_MODULE,
834
.ioctl = wrapper_ioctl,
835
.release = wrapper_ioctl_release,
838
static struct miscdevice wrapper_misc = {
840
.minor = MISC_DYNAMIC_MINOR,
841
.fops = &wrapper_fops
844
int loader_init(void)
848
InitializeListHead(&wrap_drivers);
849
InitializeListHead(&wrap_devices);
850
init_MUTEX(&loader_mutex);
851
init_completion(&loader_complete);
852
if ((err = misc_register(&wrapper_misc)) < 0 ) {
853
ERROR("couldn't register module (%d)", err);
854
unregister_devices();
861
void loader_exit(void)
863
struct nt_list *cur, *next;
866
misc_deregister(&wrapper_misc);
867
unregister_devices();
868
if (down_interruptible(&loader_mutex))
869
WARNING("couldn't obtain loader_mutex");
870
nt_list_for_each_safe(cur, next, &wrap_drivers) {
871
struct wrap_driver *driver;
872
driver = container_of(cur, struct wrap_driver, list);
873
unload_wrap_driver(driver);