1
15
16 #include "ndis.h"
17 #include "loader.h"
18 #include "wrapndis.h"
19 #include "pnp.h"
20
21 #include <linux/module.h>
22 #include <linux/kmod.h>
23 #include <linux/miscdevice.h>
24 #include <asm/uaccess.h>
25
26
32
33
34 static struct guid class_guids[] = {
35
36 { .data1 = 0x4d36e972, .data2 = 0xe325, .data3 = 0x11ce },
37
38 { .data1 = 0x36fc9e60, .data2 = 0xc465, .data3 = 0x11cf },
39
40 { .data1 = 0xe0cbf06c, .data2 = 0xcd8b, .data3 = 0x4647 },
41
43 { .data1 = 0xf12d3cf8, .data2 = 0xb11d, .data3 = 0x457e},
44 };
45
46 struct mutex loader_mutex;
47 static struct completion loader_complete;
48
49 static struct nt_list wrap_devices;
50 static struct nt_list wrap_drivers;
51
52 static int wrap_device_type(int data1)
53 {
54 int i;
55 for (i = 0; i < ARRAY_SIZE(class_guids); i++)
56 if (data1 == class_guids[i].data1)
57 return i;
58 ERROR("unknown device: 0x%x\n", data1);
59 return -1;
60 }
61
62
63 struct wrap_driver *load_wrap_driver(struct wrap_device *wd)
64 {
65 int ret;
66 struct nt_list *cur;
67 struct wrap_driver *wrap_driver;
68
69 ENTER1("device: %04X:%04X:%04X:%04X", wd->vendor, wd->device,
70 wd->subvendor, wd->subdevice);
71 mutex_lock(&loader_mutex);
72 wrap_driver = NULL;
73 nt_list_for_each(cur, &wrap_drivers) {
74 wrap_driver = container_of(cur, struct wrap_driver, list);
75 if (!stricmp(wrap_driver->name, wd->driver_name)) {
76 TRACE1("driver %s already loaded", wrap_driver->name);
77 break;
78 } else
79 wrap_driver = NULL;
80 }
81 mutex_unlock(&loader_mutex);
82
83 if (!wrap_driver) {
84 char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER,
85 #if DEBUG >= 1
86 "1",
87 #else
88 "0",
89 #endif
90 UTILS_VERSION, wd->driver_name,
91 wd->conf_file_name, NULL};
92 char *env[] = {NULL};
93
94 TRACE1("loading driver %s", wd->driver_name);
95 mutex_lock(&loader_mutex);
96 reinit_completion(&loader_complete);
97 ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
98 UMH_WAIT_PROC);
99 if (ret) {
100 mutex_unlock(&loader_mutex);
101 ERROR("couldn't load driver %s; check system log "
102 "for messages from 'loadndisdriver'",
103 wd->driver_name);
104 EXIT1(return NULL);
105 }
106 wait_for_completion(&loader_complete);
107 TRACE1("%s", wd->driver_name);
108 wrap_driver = NULL;
109 nt_list_for_each(cur, &wrap_drivers) {
110 wrap_driver = container_of(cur, struct wrap_driver,
111 list);
112 if (!stricmp(wrap_driver->name, wd->driver_name)) {
113 wd->driver = wrap_driver;
114 break;
115 } else
116 wrap_driver = NULL;
117 }
118 mutex_unlock(&loader_mutex);
119 if (wrap_driver)
120 TRACE1("driver %s is loaded", wrap_driver->name);
121 else
122 ERROR("couldn't load driver '%s'", wd->driver_name);
123 }
124 EXIT1(return wrap_driver);
125 }
126
127
128 static int load_sys_files(struct wrap_driver *driver,
129 struct load_driver *load_driver)
130 {
131 int i, err;
132
133 TRACE1("num_pe_images = %d", load_driver->num_sys_files);
134 TRACE1("loading driver: %s", load_driver->name);
135 strncpy(driver->name, load_driver->name, sizeof(driver->name));
136 driver->name[sizeof(driver->name)-1] = 0;
137 TRACE1("driver: %s", driver->name);
138 err = 0;
139 driver->num_pe_images = 0;
140 for (i = 0; i < load_driver->num_sys_files; i++) {
141 struct pe_image *pe_image;
142 pe_image = &driver->pe_images[driver->num_pe_images];
143
144 strncpy(pe_image->name, load_driver->sys_files[i].name,
145 sizeof(pe_image->name));
146 pe_image->name[sizeof(pe_image->name)-1] = 0;
147 TRACE1("image size: %zu bytes", load_driver->sys_files[i].size);
148
149 #ifdef CONFIG_X86_64
150 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
151 image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM);
152 #else
153 #ifdef PAGE_KERNEL_EXECUTABLE
154 pe_image->image =
155 __vmalloc(load_driver->sys_files[i].size,
156 GFP_KERNEL | __GFP_HIGHMEM,
157 PAGE_KERNEL_EXECUTABLE);
158 #elif defined PAGE_KERNEL_EXEC
159 pe_image->image =
160 __vmalloc(load_driver->sys_files[i].size,
161 GFP_KERNEL | __GFP_HIGHMEM,
162 PAGE_KERNEL_EXEC);
163 #else
164 #error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
165 #endif
166 #endif /* kernel 5.8 */
167 #else
168
170 #ifdef cpu_has_nx
171 if (cpu_has_nx)
172 pe_image->image =
173 __vmalloc(load_driver->sys_files[i].size,
174 GFP_KERNEL | __GFP_HIGHMEM,
175 __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
176 else
177 pe_image->image =
178 vmalloc(load_driver->sys_files[i].size);
179 #else
180 pe_image->image =
181 vmalloc(load_driver->sys_files[i].size);
182 #endif
183 #endif
184 if (!pe_image->image) {
185 ERROR("couldn't allocate memory");
186 err = -ENOMEM;
187 break;
188 }
189 TRACE1("image is at %p", pe_image->image);
190
191 if (copy_from_user(pe_image->image,
192 load_driver->sys_files[i].data,
193 load_driver->sys_files[i].size)) {
194 ERROR("couldn't load file %s",
195 load_driver->sys_files[i].name);
196 err = -EFAULT;
197 break;
198 }
199 pe_image->size = load_driver->sys_files[i].size;
200 driver->num_pe_images++;
201 }
202
203 if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) {
204 ERROR("couldn't prepare driver '%s'", load_driver->name);
205 err = -EINVAL;
206 }
207
208 if (driver->num_pe_images < load_driver->num_sys_files || err) {
209 for (i = 0; i < driver->num_pe_images; i++)
210 if (driver->pe_images[i].image)
211 vfree(driver->pe_images[i].image);
212 driver->num_pe_images = 0;
213 EXIT1(return err);
214 } else
215 EXIT1(return 0);
216 }
217
218 struct wrap_bin_file *get_bin_file(char *bin_file_name)
219 {
220 int i = 0;
221 struct wrap_driver *driver, *cur;
222
223 ENTER1("%s", bin_file_name);
224 mutex_lock(&loader_mutex);
225 driver = NULL;
226 nt_list_for_each_entry(cur, &wrap_drivers, list) {
227 for (i = 0; i < cur->num_bin_files; i++)
228 if (!stricmp(cur->bin_files[i].name, bin_file_name)) {
229 driver = cur;
230 break;
231 }
232 if (driver)
233 break;
234 }
235 mutex_unlock(&loader_mutex);
236 if (!driver) {
237 TRACE1("couldn't find bin file '%s'", bin_file_name);
238 return NULL;
239 }
240
241 if (!driver->bin_files[i].data) {
242 char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE,
243 #if DEBUG >= 1
244 "1",
245 #else
246 "0",
247 #endif
248 UTILS_VERSION, driver->name,
249 driver->bin_files[i].name, NULL};
250 char *env[] = {NULL};
251 int ret;
252
253 TRACE1("loading bin file %s/%s", driver->name,
254 driver->bin_files[i].name);
255 mutex_lock(&loader_mutex);
256 reinit_completion(&loader_complete);
257 ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
258 UMH_WAIT_PROC);
259 if (ret) {
260 mutex_unlock(&loader_mutex);
261 ERROR("couldn't load file %s/%s; check system log "
262 "for messages from 'loadndisdriver' (%d)",
263 driver->name, driver->bin_files[i].name, ret);
264 EXIT1(return NULL);
265 }
266 wait_for_completion(&loader_complete);
267 mutex_unlock(&loader_mutex);
268 if (!driver->bin_files[i].data) {
269 WARNING("couldn't load binary file %s",
270 driver->bin_files[i].name);
271 EXIT1(return NULL);
272 }
273 }
274 EXIT2(return &(driver->bin_files[i]));
275 }
276
277
278 static int add_bin_file(struct load_driver_file *driver_file)
279 {
280 struct wrap_driver *driver, *cur;
281 struct wrap_bin_file *bin_file;
282 int i = 0;
283
284 driver = NULL;
285 nt_list_for_each_entry(cur, &wrap_drivers, list) {
286 for (i = 0; i < cur->num_bin_files; i++)
287 if (!stricmp(cur->bin_files[i].name,
288 driver_file->name)) {
289 driver = cur;
290 break;
291 }
292 if (driver)
293 break;
294 }
295 if (!driver) {
296 ERROR("couldn't find %s", driver_file->name);
297 return -EINVAL;
298 }
299 bin_file = &driver->bin_files[i];
300 strncpy(bin_file->name, driver_file->name, sizeof(bin_file->name));
301 bin_file->name[sizeof(bin_file->name)-1] = 0;
302 bin_file->data = vmalloc(driver_file->size);
303 if (!bin_file->data) {
304 ERROR("couldn't allocate memory");
305 return -ENOMEM;
306 }
307 bin_file->size = driver_file->size;
308 if (copy_from_user(bin_file->data, driver_file->data, bin_file->size)) {
309 ERROR("couldn't copy data");
310 free_bin_file(bin_file);
311 return -EFAULT;
312 }
313 return 0;
314 }
315
316 void free_bin_file(struct wrap_bin_file *bin_file)
317 {
318 TRACE2("unloading %s", bin_file->name);
319 if (bin_file->data)
320 vfree(bin_file->data);
321 bin_file->data = NULL;
322 bin_file->size = 0;
323 EXIT2(return);
324 }
325
326
327 static int load_bin_files_info(struct wrap_driver *driver,
328 struct load_driver *load_driver)
329 {
330 struct wrap_bin_file *bin_files;
331 int i;
332
333 ENTER1("%s, %d", load_driver->name, load_driver->num_bin_files);
334 driver->num_bin_files = 0;
335 driver->bin_files = NULL;
336 if (load_driver->num_bin_files == 0)
337 EXIT1(return 0);
338 bin_files = kzalloc(load_driver->num_bin_files * sizeof(*bin_files),
339 GFP_KERNEL);
340 if (!bin_files) {
341 ERROR("couldn't allocate memory");
342 EXIT1(return -ENOMEM);
343 }
344
345 for (i = 0; i < load_driver->num_bin_files; i++) {
346 strncpy(bin_files[i].name, load_driver->bin_files[i].name,
347 sizeof(bin_files[i].name));
348 bin_files[i].name[sizeof(bin_files[i].name)-1] = 0;
349 TRACE2("loaded bin file %s", bin_files[i].name);
350 }
351 driver->num_bin_files = load_driver->num_bin_files;
352 driver->bin_files = bin_files;
353 EXIT1(return 0);
354 }
355
356
357 static int load_settings(struct wrap_driver *wrap_driver,
358 struct load_driver *load_driver)
359 {
360 int i, num_settings;
361
362 ENTER1("%p, %p", wrap_driver, load_driver);
363
364 num_settings = 0;
365 for (i = 0; i < load_driver->num_settings; i++) {
366 struct load_device_setting *load_setting =
367 &load_driver->settings[i];
368 struct wrap_device_setting *setting;
369 ULONG data1;
370
371 setting = kzalloc(sizeof(*setting), GFP_KERNEL);
372 if (!setting) {
373 ERROR("couldn't allocate memory");
374 break;
375 }
376 strncpy(setting->name, load_setting->name,
377 sizeof(setting->name));
378 setting->name[sizeof(setting->name)-1] = 0;
379 strncpy(setting->value, load_setting->value,
380 sizeof(setting->value));
381 setting->value[sizeof(setting->value)-1] = 0;
382 TRACE2("%p: %s=%s", setting, setting->name, setting->value);
383
384 if (strcmp(setting->name, "driver_version") == 0) {
385 strncpy(wrap_driver->version, setting->value,
386 sizeof(wrap_driver->version));
387 wrap_driver->version[sizeof(wrap_driver->version)-1] = 0;
388 } else if (strcmp(setting->name, "class_guid") == 0 &&
389 sscanf(setting->value, "%x", &data1) == 1) {
390 wrap_driver->dev_type = wrap_device_type(data1);
391 if (wrap_driver->dev_type < 0) {
392 WARNING("unknown guid: %x", data1);
393 wrap_driver->dev_type = 0;
394 }
395 }
396 InsertTailList(&wrap_driver->settings, &setting->list);
397 num_settings++;
398 }
399
400 if (num_settings > 0)
401 EXIT1(return 0);
402 else
403 EXIT1(return -EINVAL);
404 }
405
406 void unload_wrap_device(struct wrap_device *wd)
407 {
408 struct nt_list *cur;
409 ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd,
410 wd->vendor, wd->device, wd->subvendor, wd->subdevice,
411 wd->driver_name);
412 mutex_lock(&loader_mutex);
413 while ((cur = RemoveHeadList(&wd->settings))) {
414 struct wrap_device_setting *setting;
415 setting = container_of(cur, struct wrap_device_setting, list);
416 kfree(setting);
417 }
418 RemoveEntryList(&wd->list);
419 mutex_unlock(&loader_mutex);
420 kfree(wd);
421 EXIT1(return);
422 }
423
424
425 void unload_wrap_driver(struct wrap_driver *driver)
426 {
427 int i;
428 struct driver_object *drv_obj;
429 struct nt_list *cur, *next;
430
431 ENTER1("unloading driver: %s (%p)", driver->name, driver);
432 TRACE1("freeing %d images", driver->num_pe_images);
433 drv_obj = driver->drv_obj;
434 for (i = 0; i < driver->num_pe_images; i++)
435 if (driver->pe_images[i].image) {
436 TRACE1("freeing image at %p",
437 driver->pe_images[i].image);
438 vfree(driver->pe_images[i].image);
439 }
440
441 TRACE1("freeing %d bin files", driver->num_bin_files);
442 for (i = 0; i < driver->num_bin_files; i++) {
443 TRACE1("freeing image at %p", driver->bin_files[i].data);
444 if (driver->bin_files[i].data)
445 vfree(driver->bin_files[i].data);
446 }
447 kfree(driver->bin_files);
448 RtlFreeUnicodeString(&drv_obj->name);
449 RemoveEntryList(&driver->list);
450 nt_list_for_each_safe(cur, next, &driver->settings) {
451 struct wrap_device_setting *setting;
452 struct ndis_configuration_parameter *param;
453
454 setting = container_of(cur, struct wrap_device_setting, list);
455 TRACE2("%p", setting);
456 param = setting->encoded;
457 if (param) {
458 TRACE2("%p", param);
459 if (param->type == NdisParameterString)
460 RtlFreeUnicodeString(¶m->data.string);
461 ExFreePool(param);
462 }
463 kfree(setting);
464 }
465
466 free_custom_extensions(drv_obj->drv_ext);
467 kfree(drv_obj->drv_ext);
468 TRACE1("drv_obj: %p", drv_obj);
469
470 EXIT1(return);
471 }
472
473
474 static int start_wrap_driver(struct wrap_driver *driver)
475 {
476 int i;
477 NTSTATUS ret, res;
478 struct driver_object *drv_obj;
479 typeof(driver->pe_images[0].entry) entry;
480
481 ENTER1("%s", driver->name);
482 drv_obj = driver->drv_obj;
483 for (ret = res = 0, i = 0; i < driver->num_pe_images; i++)
484
485 if (driver->pe_images[i].type == IMAGE_FILE_EXECUTABLE_IMAGE) {
486 entry = driver->pe_images[i].entry;
487 drv_obj->start = driver->pe_images[i].entry;
488 drv_obj->driver_size = driver->pe_images[i].size;
489 TRACE1("entry: %p, %p, drv_obj: %p",
490 entry, *entry, drv_obj);
491 res = LIN2WIN2(entry, drv_obj, &drv_obj->name);
492 ret |= res;
493 TRACE1("entry returns %08X", res);
494 break;
495 }
496 if (ret) {
497 ERROR("driver initialization failed: %08X", ret);
498 RtlFreeUnicodeString(&drv_obj->name);
499
500 free_custom_extensions(drv_obj->drv_ext);
501 kfree(drv_obj->drv_ext);
502 TRACE1("drv_obj: %p", drv_obj);
503 ObDereferenceObject(drv_obj);
504 EXIT1(return -EINVAL);
505 }
506 EXIT1(return 0);
507 }
508
509
513 static int add_wrap_driver(struct wrap_driver *driver)
514 {
515 struct wrap_driver *tmp;
516
517 ENTER1("name: %s", driver->name);
518 nt_list_for_each_entry(tmp, &wrap_drivers, list) {
519 if (stricmp(tmp->name, driver->name) == 0) {
520 ERROR("cannot add duplicate driver");
521 EXIT1(return -EBUSY);
522 }
523 }
524 InsertHeadList(&wrap_drivers, &driver->list);
525 EXIT1(return 0);
526 }
527
528
530 static int load_user_space_driver(struct load_driver *load_driver)
531 {
532 struct driver_object *drv_obj;
533 struct ansi_string ansi_reg;
534 struct wrap_driver *wrap_driver = NULL;
535
536 ENTER1("%p", load_driver);
537 drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL);
538 if (!drv_obj) {
539 ERROR("couldn't allocate memory");
540 EXIT1(return -ENOMEM);
541 }
542 TRACE1("drv_obj: %p", drv_obj);
543 drv_obj->drv_ext = kzalloc(sizeof(*(drv_obj->drv_ext)), GFP_KERNEL);
544 if (!drv_obj->drv_ext) {
545 ERROR("couldn't allocate memory");
546 ObDereferenceObject(drv_obj);
547 EXIT1(return -ENOMEM);
548 }
549 InitializeListHead(&drv_obj->drv_ext->custom_ext);
550 if (IoAllocateDriverObjectExtension(drv_obj,
551 (void *)WRAP_DRIVER_CLIENT_ID,
552 sizeof(*wrap_driver),
553 (void **)&wrap_driver) !=
554 STATUS_SUCCESS)
555 EXIT1(return -ENOMEM);
556 TRACE1("driver: %p", wrap_driver);
557 memset(wrap_driver, 0, sizeof(*wrap_driver));
558 InitializeListHead(&wrap_driver->list);
559 InitializeListHead(&wrap_driver->settings);
560 wrap_driver->drv_obj = drv_obj;
561 RtlInitAnsiString(&ansi_reg, "/tmp");
562 if (RtlAnsiStringToUnicodeString(&drv_obj->name, &ansi_reg, TRUE) !=
563 STATUS_SUCCESS) {
564 ERROR("couldn't initialize registry path");
565 free_custom_extensions(drv_obj->drv_ext);
566 kfree(drv_obj->drv_ext);
567 TRACE1("drv_obj: %p", drv_obj);
568 ObDereferenceObject(drv_obj);
569 EXIT1(return -EINVAL);
570 }
571 strncpy(wrap_driver->name, load_driver->name, sizeof(wrap_driver->name));
572 wrap_driver->name[sizeof(wrap_driver->name)-1] = 0;
573 if (load_sys_files(wrap_driver, load_driver) ||
574 load_bin_files_info(wrap_driver, load_driver) ||
575 load_settings(wrap_driver, load_driver) ||
576 start_wrap_driver(wrap_driver) ||
577 add_wrap_driver(wrap_driver)) {
578 unload_wrap_driver(wrap_driver);
579 ObDereferenceObject(drv_obj);
580 EXIT1(return -EINVAL);
581 } else {
582 printk(KERN_INFO "%s: driver %s (%s) loaded\n",
583 DRIVER_NAME, wrap_driver->name, wrap_driver->version);
584 add_taint(TAINT_PROPRIETARY_MODULE, LOCKDEP_NOW_UNRELIABLE);
585 EXIT1(return 0);
586 }
587 }
588
589 static struct pci_device_id wrap_pci_id_table[] = {
590 {
591 .vendor = PCI_ANY_ID,
592 .device = PCI_ANY_ID,
593 .subvendor = PCI_ANY_ID,
594 .subdevice = PCI_ANY_ID,
595 .class = 0,
596 .class_mask = 0,
597 .driver_data = 0
598 }
599 };
600
601 static struct pci_driver wrap_pci_driver = {
602 .name = DRIVER_NAME,
603 .id_table = wrap_pci_id_table,
604 .probe = wrap_pnp_start_pci_device,
605 .remove = wrap_pnp_remove_pci_device,
606 .suspend = wrap_pnp_suspend_pci_device,
607 .resume = wrap_pnp_resume_pci_device,
608 };
609
610 #ifdef ENABLE_USB
611 static struct usb_device_id wrap_usb_id_table[] = {
612 {
613 .driver_info = 1
614 },
615 };
616
617 static struct usb_driver wrap_usb_driver = {
618 .name = DRIVER_NAME,
619 .id_table = wrap_usb_id_table,
620 .probe = wrap_pnp_start_usb_device,
621 .disconnect = wrap_pnp_remove_usb_device,
622 .suspend = wrap_pnp_suspend_usb_device,
623 .resume = wrap_pnp_resume_usb_device,
624 };
625 #endif
626
627
628 static void register_devices(void)
629 {
630 int res;
631
632 res = pci_register_driver(&wrap_pci_driver);
633 if (res < 0) {
634 ERROR("couldn't register pci driver: %d", res);
635 wrap_pci_driver.name = NULL;
636 }
637
638 #ifdef ENABLE_USB
639 res = usb_register(&wrap_usb_driver);
640 if (res < 0) {
641 ERROR("couldn't register usb driver: %d", res);
642 wrap_usb_driver.name = NULL;
643 }
644 #endif
645 EXIT1(return);
646 }
647
648 static void unregister_devices(void)
649 {
650 struct nt_list *cur, *next;
651
652 mutex_lock(&loader_mutex);
653 nt_list_for_each_safe(cur, next, &wrap_devices) {
654 struct wrap_device *wd;
655 wd = container_of(cur, struct wrap_device, list);
656 set_bit(HW_DISABLED, &wd->hw_status);
657 }
658 mutex_unlock(&loader_mutex);
659
660 if (wrap_pci_driver.name)
661 pci_unregister_driver(&wrap_pci_driver);
662 #ifdef ENABLE_USB
663 if (wrap_usb_driver.name)
664 usb_deregister(&wrap_usb_driver);
665 #endif
666 }
667
668 struct wrap_device *load_wrap_device(struct load_device *load_device)
669 {
670 int ret;
671 struct nt_list *cur;
672 struct wrap_device *wd = NULL;
673 char vendor[5], device[5], subvendor[5], subdevice[5], bus[5];
674
675 ENTER1("%04x, %04x, %04x, %04x", load_device->vendor,
676 load_device->device, load_device->subvendor,
677 load_device->subdevice);
678 if (sprintf(vendor, "%04x", load_device->vendor) == 4 &&
679 sprintf(device, "%04x", load_device->device) == 4 &&
680 sprintf(subvendor, "%04x", load_device->subvendor) == 4 &&
681 sprintf(subdevice, "%04x", load_device->subdevice) == 4 &&
682 sprintf(bus, "%04x", load_device->bus) == 4) {
683 char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DEVICE,
684 #if DEBUG >= 1
685 "1",
686 #else
687 "0",
688 #endif
689 UTILS_VERSION, vendor, device,
690 subvendor, subdevice, bus, NULL};
691 char *env[] = {NULL};
692 TRACE2("%s, %s, %s, %s, %s", vendor, device,
693 subvendor, subdevice, bus);
694 mutex_lock(&loader_mutex);
695 reinit_completion(&loader_complete);
696 ret = call_usermodehelper("/sbin/loadndisdriver", argv, env,
697 UMH_WAIT_PROC);
698 if (ret) {
699 mutex_unlock(&loader_mutex);
700 TRACE1("couldn't load device %04x:%04x; check system "
701 "log for messages from 'loadndisdriver'",
702 load_device->vendor, load_device->device);
703 EXIT1(return NULL);
704 }
705 wait_for_completion(&loader_complete);
706 wd = NULL;
707 nt_list_for_each(cur, &wrap_devices) {
708 wd = container_of(cur, struct wrap_device, list);
709 TRACE2("%p, %04x, %04x, %04x, %04x", wd, wd->vendor,
710 wd->device, wd->subvendor, wd->subdevice);
711 if (wd->vendor == load_device->vendor &&
712 wd->device == load_device->device)
713 break;
714 else
715 wd = NULL;
716 }
717 mutex_unlock(&loader_mutex);
718 } else
719 wd = NULL;
720 EXIT1(return wd);
721 }
722
723 struct wrap_device *get_wrap_device(void *dev, int bus)
724 {
725 struct nt_list *cur;
726 struct wrap_device *wd;
727
728 mutex_lock(&loader_mutex);
729 wd = NULL;
730 nt_list_for_each(cur, &wrap_devices) {
731 wd = container_of(cur, struct wrap_device, list);
732 if (bus == WRAP_PCI_BUS &&
733 wrap_is_pci_bus(wd->dev_bus) && wd->pci.pdev == dev)
734 break;
735 else if (bus == WRAP_USB_BUS &&
736 wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev)
737 break;
738 else
739 wd = NULL;
740 }
741 mutex_unlock(&loader_mutex);
742 return wd;
743 }
744
745
746 static long wrapper_ioctl(struct file *file, unsigned int cmd,
747 unsigned long arg)
748 {
749 struct load_driver *load_driver;
750 struct load_device load_device;
751 struct load_driver_file load_bin_file;
752 int ret;
753 void __user *addr = (void __user *)arg;
754
755 ENTER1("cmd: 0x%x", cmd);
756
757 ret = 0;
758 switch (cmd) {
759 case WRAP_IOCTL_LOAD_DEVICE:
760 if (copy_from_user(&load_device, addr, sizeof(load_device))) {
761 ret = -EFAULT;
762 break;
763 }
764 TRACE2("%04x, %04x, %04x, %04x", load_device.vendor,
765 load_device.device, load_device.subvendor,
766 load_device.subdevice);
767 if (load_device.vendor) {
768 struct wrap_device *wd;
769 wd = kzalloc(sizeof(*wd), GFP_KERNEL);
770 if (!wd) {
771 ret = -ENOMEM;
772 break;
773 }
774 InitializeListHead(&wd->settings);
775 wd->dev_bus = WRAP_BUS(load_device.bus);
776 wd->vendor = load_device.vendor;
777 wd->device = load_device.device;
778 wd->subvendor = load_device.subvendor;
779 wd->subdevice = load_device.subdevice;
780 strncpy(wd->conf_file_name, load_device.conf_file_name,
781 sizeof(wd->conf_file_name));
782 wd->conf_file_name[sizeof(wd->conf_file_name)-1] = 0;
783 strncpy(wd->driver_name, load_device.driver_name,
784 sizeof(wd->driver_name));
785 wd->driver_name[sizeof(wd->driver_name)-1] = 0;
786 InsertHeadList(&wrap_devices, &wd->list);
787 ret = 0;
788 } else
789 ret = -EINVAL;
790 break;
791 case WRAP_IOCTL_LOAD_DRIVER:
792 TRACE1("loading driver at %p", addr);
793 load_driver = vmalloc(sizeof(*load_driver));
794 if (!load_driver) {
795 ret = -ENOMEM;
796 break;
797 }
798 if (copy_from_user(load_driver, addr, sizeof(*load_driver)))
799 ret = -EFAULT;
800 else
801 ret = load_user_space_driver(load_driver);
802 vfree(load_driver);
803 break;
804 case WRAP_IOCTL_LOAD_BIN_FILE:
805 if (copy_from_user(&load_bin_file, addr, sizeof(load_bin_file)))
806 ret = -EFAULT;
807 else
808 ret = add_bin_file(&load_bin_file);
809 break;
810 default:
811 ERROR("unknown ioctl 0x%x", cmd);
812 ret = -EINVAL;
813 break;
814 }
815 complete(&loader_complete);
816 EXIT1(return ret);
817 }
818
819 #ifdef CONFIG_COMPAT
820 static int copy_load_driver_file32(struct load_driver_file *k,
821 struct load_driver_file32 __user *u)
822 {
823 u32 data;
824
825 if (copy_from_user(&k->driver_name, &u->driver_name,
826 sizeof(u->driver_name) + sizeof(u->name)))
827 return -EFAULT;
828
829 if (get_user(k->size, &u->size))
830 return -EFAULT;
831 if (get_user(data, &u->data))
832 return -EFAULT;
833
834 k->data = (void __user *)(unsigned long)data;
835 return 0;
836 }
837
838 static int copy_load_driver32(struct load_driver *k,
839 struct load_driver32 __user *u)
840 {
841 int i;
842
843 if (copy_from_user(&k->name, &u->name,
844 sizeof(u->name) + sizeof(u->conf_file_name)))
845 return -EFAULT;
846
847 if (get_user(k->num_sys_files, &u->num_sys_files))
848 return -EFAULT;
849
850 for (i = 0; i < k->num_sys_files; i++)
851 if (copy_load_driver_file32(&k->sys_files[i], &u->sys_files[i]))
852 return -EFAULT;
853
854 if (get_user(k->num_settings, &u->num_settings))
855 return -EFAULT;
856
857 if (copy_from_user(&k->settings, &u->settings,
858 sizeof(u->settings[0]) * k->num_settings))
859 return -EFAULT;
860
861 if (get_user(k->num_bin_files, &u->num_bin_files))
862 return -EFAULT;
863
864 for (i = 0; i < k->num_bin_files; i++)
865 if (copy_load_driver_file32(&k->bin_files[i], &u->bin_files[i]))
866 return -EFAULT;
867
868 return 0;
869 }
870
871 static long wrapper_ioctl_compat(struct file *file, unsigned int cmd,
872 unsigned long arg)
873 {
874 int ret = 0;
875 void __user *addr = (void __user *)arg;
876 struct load_driver *kdriver;
877 struct load_driver32 __user *udriver = addr;
878 struct load_driver_file kfile;
879 struct load_driver_file32 __user *ufile = addr;
880
881 ENTER1("cmd: 0x%x", cmd);
882
883 switch (cmd) {
884 case WRAP_IOCTL_LOAD_DEVICE32:
885 return wrapper_ioctl(file, WRAP_IOCTL_LOAD_DEVICE, arg);
886 case WRAP_IOCTL_LOAD_DRIVER32:
887 TRACE1("loading driver at %p", addr);
888 kdriver = vmalloc(sizeof(*kdriver));
889 if (!kdriver) {
890 ret = -ENOMEM;
891 break;
892 }
893
894 ret = copy_load_driver32(kdriver, udriver);
895 if (!ret)
896 ret = load_user_space_driver(kdriver);
897
898 vfree(kdriver);
899 break;
900 case WRAP_IOCTL_LOAD_BIN_FILE32:
901 ret = copy_load_driver_file32(&kfile, ufile);
902 if (ret)
903 break;
904
905 ret = add_bin_file(&kfile);
906 break;
907 default:
908 ERROR("unknown ioctl 0x%x", cmd);
909 ret = -EINVAL;
910 break;
911 }
912 complete(&loader_complete);
913 EXIT1(return ret);
914 }
915 #endif
916
917 static int wrapper_ioctl_release(struct inode *inode, struct file *file)
918 {
919 ENTER1("");
920 complete(&loader_complete);
921 return 0;
922 }
923
924 static struct file_operations wrapper_fops = {
925 .owner = THIS_MODULE,
926 .unlocked_ioctl = wrapper_ioctl,
927 #ifdef CONFIG_COMPAT
928 .compat_ioctl = wrapper_ioctl_compat,
929 #endif
930 .release = wrapper_ioctl_release,
931 };
932
933 static struct miscdevice wrapper_misc = {
934 .name = DRIVER_NAME,
935 .minor = MISC_DYNAMIC_MINOR,
936 .fops = &wrapper_fops
937 };
938
939 int loader_init(void)
940 {
941 int err;
942
943 InitializeListHead(&wrap_drivers);
944 InitializeListHead(&wrap_devices);
945 mutex_init(&loader_mutex);
946 init_completion(&loader_complete);
947 if ((err = misc_register(&wrapper_misc)) < 0) {
948 ERROR("couldn't register module (%d)", err);
949 unregister_devices();
950 EXIT1(return err);
951 }
952 register_devices();
953 EXIT1(return 0);
954 }
955
956 void loader_exit(void)
957 {
958 struct nt_list *cur, *next;
959
960 ENTER1("");
961 misc_deregister(&wrapper_misc);
962 unregister_devices();
963 mutex_lock(&loader_mutex);
964 nt_list_for_each_safe(cur, next, &wrap_drivers) {
965 struct wrap_driver *driver;
966 driver = container_of(cur, struct wrap_driver, list);
967 unload_wrap_driver(driver);
968 }
969 mutex_unlock(&loader_mutex);
970 EXIT1(return);
971 }