~ubuntu-branches/ubuntu/vivid/linux-ti-omap/vivid

« back to all changes in this revision

Viewing changes to ubuntu/ndiswrapper/loader.c

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bader, Amit Kucheria
  • Date: 2010-03-23 18:05:12 UTC
  • Revision ID: james.westby@ubuntu.com-20100323180512-iavj906ocnphdubp
Tags: 2.6.33-500.3
[ Amit Kucheria ]

* [Config] Fix the debug package name to end in -dbgsym
* SAUCE: Add the ubuntu/ drivers to omap
* SAUCE: Re-export the symbols for aufs
* [Config] Enable AUFS and COMPCACHE

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
14
 */
 
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
/*
 
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}
 
31
*/
 
32
 
 
33
/* the indices used here must match macros WRAP_NDIS_DEVICE etc. */
 
34
static struct guid class_guids[] = {
 
35
        /* Network */
 
36
        {0x4d36e972, 0xe325, 0x11ce, },
 
37
        /* USB WDM */
 
38
        {0x36fc9e60, 0xc465, 0x11cf, },
 
39
        /* Bluetooth */
 
40
        {0xe0cbf06c, 0xcd8b, 0x4647, },
 
41
        /* ivtcorporatino.com's bluetooth device claims this is
 
42
         * bluetooth guid */
 
43
        {0xf12d3cf8, 0xb11d, 0x457e, },
 
44
};
 
45
 
 
46
struct semaphore 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 < sizeof(class_guids) / sizeof(class_guids[0]); 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
/* load driver for given device, if not already loaded */
 
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
        if (down_interruptible(&loader_mutex)) {
 
72
                WARNING("couldn't obtain loader_mutex");
 
73
                EXIT1(return NULL);
 
74
        }
 
75
        wrap_driver = NULL;
 
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);
 
80
                        break;
 
81
                } else
 
82
                        wrap_driver = NULL;
 
83
        }
 
84
        up(&loader_mutex);
 
85
 
 
86
        if (!wrap_driver) {
 
87
                char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_DRIVER,
 
88
#if defined(DEBUG) && DEBUG >= 1
 
89
                                "1",
 
90
#else
 
91
                                "0",
 
92
#endif
 
93
                                UTILS_VERSION, wd->driver_name,
 
94
                                wd->conf_file_name, NULL};
 
95
                char *env[] = {NULL};
 
96
 
 
97
                TRACE1("loading driver %s", wd->driver_name);
 
98
                if (down_interruptible(&loader_mutex)) {
 
99
                        WARNING("couldn't obtain loader_mutex");
 
100
                        EXIT1(return NULL);
 
101
                }
 
102
                INIT_COMPLETION(loader_complete);
 
103
                ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
 
104
                if (ret) {
 
105
                        up(&loader_mutex);
 
106
                        ERROR("couldn't load driver %s; check system log "
 
107
                              "for messages from 'loadndisdriver'",
 
108
                              wd->driver_name);
 
109
                        EXIT1(return NULL);
 
110
                }
 
111
                wait_for_completion(&loader_complete);
 
112
                TRACE1("%s", wd->driver_name);
 
113
                wrap_driver = NULL;
 
114
                nt_list_for_each(cur, &wrap_drivers) {
 
115
                        wrap_driver = container_of(cur, struct wrap_driver,
 
116
                                                   list);
 
117
                        if (!stricmp(wrap_driver->name, wd->driver_name)) {
 
118
                                wd->driver = wrap_driver;
 
119
                                break;
 
120
                        } else
 
121
                                wrap_driver = NULL;
 
122
                }
 
123
                up(&loader_mutex);
 
124
                if (wrap_driver)
 
125
                        TRACE1("driver %s is loaded", wrap_driver->name);
 
126
                else
 
127
                        ERROR("couldn't load driver '%s'", wd->driver_name);
 
128
        }
 
129
        EXIT1(return wrap_driver);
 
130
}
 
131
 
 
132
/* load the driver files from userspace. */
 
133
static int load_sys_files(struct wrap_driver *driver,
 
134
                          struct load_driver *load_driver)
 
135
{
 
136
        int i, err;
 
137
 
 
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);
 
143
        err = 0;
 
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];
 
148
 
 
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);
 
154
 
 
155
#ifdef CONFIG_X86_64
 
156
#ifdef PAGE_KERNEL_EXECUTABLE
 
157
                pe_image->image =
 
158
                        __vmalloc(load_driver->sys_files[i].size,
 
159
                                  GFP_KERNEL | __GFP_HIGHMEM,
 
160
                                  PAGE_KERNEL_EXECUTABLE);
 
161
#elif defined PAGE_KERNEL_EXEC
 
162
                pe_image->image =
 
163
                        __vmalloc(load_driver->sys_files[i].size,
 
164
                                  GFP_KERNEL | __GFP_HIGHMEM,
 
165
                                  PAGE_KERNEL_EXEC);
 
166
#else
 
167
#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC
 
168
#endif
 
169
#else
 
170
                /* hate to play with kernel macros, but PAGE_KERNEL_EXEC is
 
171
                 * not available to modules! */
 
172
#ifdef cpu_has_nx
 
173
                if (cpu_has_nx)
 
174
                        pe_image->image =
 
175
                                __vmalloc(load_driver->sys_files[i].size,
 
176
                                          GFP_KERNEL | __GFP_HIGHMEM,
 
177
                                          __pgprot(__PAGE_KERNEL & ~_PAGE_NX));
 
178
                else
 
179
                        pe_image->image =
 
180
                                vmalloc(load_driver->sys_files[i].size);
 
181
#else
 
182
                        pe_image->image =
 
183
                                vmalloc(load_driver->sys_files[i].size);
 
184
#endif
 
185
#endif
 
186
                if (!pe_image->image) {
 
187
                        ERROR("couldn't allocate memory");
 
188
                        err = -ENOMEM;
 
189
                        break;
 
190
                }
 
191
                TRACE1("image is at %p", pe_image->image);
 
192
 
 
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);
 
198
                        err = -EFAULT;
 
199
                        break;
 
200
                }
 
201
                pe_image->size = load_driver->sys_files[i].size;
 
202
                driver->num_pe_images++;
 
203
        }
 
204
 
 
205
        if (!err && link_pe_images(driver->pe_images, driver->num_pe_images)) {
 
206
                ERROR("couldn't prepare driver '%s'", load_driver->name);
 
207
                err = -EINVAL;
 
208
        }
 
209
 
 
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;
 
215
                EXIT1(return err);
 
216
        } else
 
217
                EXIT1(return 0);
 
218
}
 
219
 
 
220
struct wrap_bin_file *get_bin_file(char *bin_file_name)
 
221
{
 
222
        int i = 0;
 
223
        struct wrap_driver *driver, *cur;
 
224
 
 
225
        ENTER1("%s", bin_file_name);
 
226
        if (down_interruptible(&loader_mutex)) {
 
227
                WARNING("couldn't obtain loader_mutex");
 
228
                EXIT1(return NULL);
 
229
        }
 
230
        driver = NULL;
 
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)) {
 
234
                                driver = cur;
 
235
                                break;
 
236
                        }
 
237
                if (driver)
 
238
                        break;
 
239
        }
 
240
        up(&loader_mutex);
 
241
        if (!driver) {
 
242
                TRACE1("coudln't find bin file '%s'", bin_file_name);
 
243
                return NULL;
 
244
        }
 
245
 
 
246
        if (!driver->bin_files[i].data) {
 
247
                char *argv[] = {"loadndisdriver", WRAP_CMD_LOAD_BIN_FILE,
 
248
#if defined(DEBUG) && DEBUG >= 1
 
249
                                "1",
 
250
#else
 
251
                                "0",
 
252
#endif
 
253
                                UTILS_VERSION, driver->name,
 
254
                                driver->bin_files[i].name, NULL};
 
255
                char *env[] = {NULL};
 
256
                int ret;
 
257
 
 
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");
 
262
                        EXIT1(return NULL);
 
263
                }
 
264
                INIT_COMPLETION(loader_complete);
 
265
                ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
 
266
                if (ret) {
 
267
                        up(&loader_mutex);
 
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);
 
271
                        EXIT1(return NULL);
 
272
                }
 
273
                wait_for_completion(&loader_complete);
 
274
                up(&loader_mutex);
 
275
                if (!driver->bin_files[i].data) {
 
276
                        WARNING("couldn't load binary file %s",
 
277
                                driver->bin_files[i].name);
 
278
                        EXIT1(return NULL);
 
279
                }
 
280
        }
 
281
        EXIT2(return &(driver->bin_files[i]));
 
282
}
 
283
 
 
284
/* called with loader_mutex down */
 
285
static int add_bin_file(struct load_driver_file *driver_file)
 
286
{
 
287
        struct wrap_driver *driver, *cur;
 
288
        struct wrap_bin_file *bin_file;
 
289
        int i = 0;
 
290
 
 
291
        driver = NULL;
 
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)) {
 
296
                                driver = cur;
 
297
                                break;
 
298
                        }
 
299
                if (driver)
 
300
                        break;
 
301
        }
 
302
        if (!driver) {
 
303
                ERROR("couldn't find %s", driver_file->name);
 
304
                return -EINVAL;
 
305
        }
 
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");
 
312
                return -ENOMEM;
 
313
        }
 
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);
 
318
                return -EFAULT;
 
319
        }
 
320
        return 0;
 
321
}
 
322
 
 
323
void free_bin_file(struct wrap_bin_file *bin_file)
 
324
{
 
325
        TRACE2("unloading %s", bin_file->name);
 
326
        if (bin_file->data)
 
327
                vfree(bin_file->data);
 
328
        bin_file->data = NULL;
 
329
        bin_file->size = 0;
 
330
        EXIT2(return);
 
331
}
 
332
 
 
333
/* load firmware files from userspace */
 
334
static int load_bin_files_info(struct wrap_driver *driver,
 
335
                               struct load_driver *load_driver)
 
336
{
 
337
        struct wrap_bin_file *bin_files;
 
338
        int i;
 
339
 
 
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)
 
344
                EXIT1(return 0);
 
345
        bin_files = kzalloc(load_driver->num_bin_files * sizeof(*bin_files),
 
346
                            GFP_KERNEL);
 
347
        if (!bin_files) {
 
348
                ERROR("couldn't allocate memory");
 
349
                EXIT1(return -ENOMEM);
 
350
        }
 
351
 
 
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);
 
357
        }
 
358
        driver->num_bin_files = load_driver->num_bin_files;
 
359
        driver->bin_files = bin_files;
 
360
        EXIT1(return 0);
 
361
}
 
362
 
 
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)
 
366
{
 
367
        int i, num_settings;
 
368
 
 
369
        ENTER1("%p, %p", wrap_driver, load_driver);
 
370
 
 
371
        num_settings = 0;
 
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;
 
376
                ULONG data1;
 
377
 
 
378
                setting = kzalloc(sizeof(*setting), GFP_KERNEL);
 
379
                if (!setting) {
 
380
                        ERROR("couldn't allocate memory");
 
381
                        break;
 
382
                }
 
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);
 
390
 
 
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;
 
401
                        }
 
402
                }
 
403
                InsertTailList(&wrap_driver->settings, &setting->list);
 
404
                num_settings++;
 
405
        }
 
406
        /* it is not a fatal error if some settings couldn't be loaded */
 
407
        if (num_settings > 0)
 
408
                EXIT1(return 0);
 
409
        else
 
410
                EXIT1(return -EINVAL);
 
411
}
 
412
 
 
413
void unload_wrap_device(struct wrap_device *wd)
 
414
{
 
415
        struct nt_list *cur;
 
416
        ENTER1("unloading device %p (%04X:%04X:%04X:%04X), driver %s", wd,
 
417
               wd->vendor, wd->device, wd->subvendor, wd->subdevice,
 
418
               wd->driver_name);
 
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);
 
424
                kfree(setting);
 
425
        }
 
426
        RemoveEntryList(&wd->list);
 
427
        up(&loader_mutex);
 
428
        kfree(wd);
 
429
        EXIT1(return);
 
430
}
 
431
 
 
432
/* should be called with loader_mutex down */
 
433
void unload_wrap_driver(struct wrap_driver *driver)
 
434
{
 
435
        int i;
 
436
        struct driver_object *drv_obj;
 
437
        struct nt_list *cur, *next;
 
438
 
 
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);
 
447
                }
 
448
 
 
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);
 
454
        }
 
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;
 
462
 
 
463
                setting = container_of(cur, struct wrap_device_setting, list);
 
464
                TRACE2("%p", setting);
 
465
                param = setting->encoded;
 
466
                if (param) {
 
467
                        TRACE2("%p", param);
 
468
                        if (param->type == NdisParameterString)
 
469
                                RtlFreeUnicodeString(&param->data.string);
 
470
                        ExFreePool(param);
 
471
                }
 
472
                kfree(setting);
 
473
        }
 
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);
 
478
 
 
479
        EXIT1(return);
 
480
}
 
481
 
 
482
/* call the entry point of the driver */
 
483
static int start_wrap_driver(struct wrap_driver *driver)
 
484
{
 
485
        int i;
 
486
        NTSTATUS ret, res;
 
487
        struct driver_object *drv_obj;
 
488
        typeof(driver->pe_images[0].entry) entry;
 
489
 
 
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);
 
501
                        ret |= res;
 
502
                        TRACE1("entry returns %08X", res);
 
503
                        break;
 
504
                }
 
505
        if (ret) {
 
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);
 
514
        }
 
515
        EXIT1(return 0);
 
516
}
 
517
 
 
518
/*
 
519
 * add driver to list of loaded driver but make sure this driver is
 
520
 * not loaded before. called with loader_mutex down
 
521
 */
 
522
static int add_wrap_driver(struct wrap_driver *driver)
 
523
{
 
524
        struct wrap_driver *tmp;
 
525
 
 
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);
 
531
                }
 
532
        }
 
533
        InsertHeadList(&wrap_drivers, &driver->list);
 
534
        EXIT1(return 0);
 
535
}
 
536
 
 
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)
 
540
{
 
541
        struct driver_object *drv_obj;
 
542
        struct ansi_string ansi_reg;
 
543
        struct wrap_driver *wrap_driver = NULL;
 
544
 
 
545
        ENTER1("%p", load_driver);
 
546
        drv_obj = allocate_object(sizeof(*drv_obj), OBJECT_TYPE_DRIVER, NULL);
 
547
        if (!drv_obj) {
 
548
                ERROR("couldn't allocate memory");
 
549
                EXIT1(return -ENOMEM);
 
550
        }
 
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);
 
557
        }
 
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) !=
 
563
            STATUS_SUCCESS)
 
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) !=
 
573
            STATUS_SUCCESS) {
 
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);
 
580
        }
 
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);
 
590
        } else {
 
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);
 
594
                EXIT1(return 0);
 
595
        }
 
596
}
 
597
 
 
598
static struct pci_device_id wrap_pci_id_table[] = {
 
599
        {PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID},
 
600
};
 
601
 
 
602
static struct pci_driver wrap_pci_driver = {
 
603
        .name           = DRIVER_NAME,
 
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,
 
609
};
 
610
 
 
611
#ifdef ENABLE_USB
 
612
static struct usb_device_id wrap_usb_id_table[] = {
 
613
        {
 
614
                .driver_info = 1
 
615
        },
 
616
};
 
617
 
 
618
static struct usb_driver wrap_usb_driver = {
 
619
        .name = DRIVER_NAME,
 
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,
 
625
};
 
626
#endif
 
627
 
 
628
/* register drivers for pci and usb */
 
629
static void register_devices(void)
 
630
{
 
631
        int res;
 
632
 
 
633
        res = pci_register_driver(&wrap_pci_driver);
 
634
        if (res < 0) {
 
635
                ERROR("couldn't register pci driver: %d", res);
 
636
                wrap_pci_driver.name = NULL;
 
637
        }
 
638
 
 
639
#ifdef ENABLE_USB
 
640
        res = usb_register(&wrap_usb_driver);
 
641
        if (res < 0) {
 
642
                ERROR("couldn't register usb driver: %d", res);
 
643
                wrap_usb_driver.name = NULL;
 
644
        }
 
645
#endif
 
646
        EXIT1(return);
 
647
}
 
648
 
 
649
static void unregister_devices(void)
 
650
{
 
651
        struct nt_list *cur, *next;
 
652
 
 
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);
 
659
        }
 
660
        up(&loader_mutex);
 
661
 
 
662
        if (wrap_pci_driver.name)
 
663
                pci_unregister_driver(&wrap_pci_driver);
 
664
#ifdef ENABLE_USB
 
665
        if (wrap_usb_driver.name)
 
666
                usb_deregister(&wrap_usb_driver);
 
667
#endif
 
668
}
 
669
 
 
670
struct wrap_device *load_wrap_device(struct load_device *load_device)
 
671
{
 
672
        int ret;
 
673
        struct nt_list *cur;
 
674
        struct wrap_device *wd = NULL;
 
675
        char vendor[5], device[5], subvendor[5], subdevice[5], bus[5];
 
676
 
 
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
 
687
                                "1",
 
688
#else
 
689
                                "0",
 
690
#endif
 
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");
 
698
                        EXIT1(return NULL);
 
699
                }
 
700
                INIT_COMPLETION(loader_complete);
 
701
                ret = call_usermodehelper("/sbin/loadndisdriver", argv, env, 1);
 
702
                if (ret) {
 
703
                        up(&loader_mutex);
 
704
                        TRACE1("couldn't load device %04x:%04x; check system "
 
705
                               "log for messages from 'loadndisdriver'",
 
706
                               load_device->vendor, load_device->device);
 
707
                        EXIT1(return NULL);
 
708
                }
 
709
                wait_for_completion(&loader_complete);
 
710
                wd = NULL;
 
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)
 
717
                                break;
 
718
                        else
 
719
                                wd = NULL;
 
720
                }
 
721
                up(&loader_mutex);
 
722
        } else
 
723
                wd = NULL;
 
724
        EXIT1(return wd);
 
725
}
 
726
 
 
727
struct wrap_device *get_wrap_device(void *dev, int bus)
 
728
{
 
729
        struct nt_list *cur;
 
730
        struct wrap_device *wd;
 
731
 
 
732
        if (down_interruptible(&loader_mutex)) {
 
733
                WARNING("couldn't obtain loader_mutex");
 
734
                return NULL;
 
735
        }
 
736
        wd = NULL;
 
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)
 
741
                        break;
 
742
                else if (bus == WRAP_USB_BUS &&
 
743
                         wrap_is_usb_bus(wd->dev_bus) && wd->usb.udev == dev)
 
744
                        break;
 
745
                else
 
746
                        wd = NULL;
 
747
        }
 
748
        up(&loader_mutex);
 
749
        return wd;
 
750
}
 
751
 
 
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)
 
755
{
 
756
        struct load_driver *load_driver;
 
757
        struct load_device load_device;
 
758
        struct load_driver_file load_bin_file;
 
759
        int ret;
 
760
        void __user *addr = (void __user *)arg;
 
761
 
 
762
        ENTER1("cmd: %u", cmd);
 
763
 
 
764
        ret = 0;
 
765
        switch (cmd) {
 
766
        case WRAP_IOCTL_LOAD_DEVICE:
 
767
                if (copy_from_user(&load_device, addr, sizeof(load_device))) {
 
768
                        ret = -EFAULT;
 
769
                        break;
 
770
                }
 
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);
 
777
                        if (!wd) {
 
778
                                ret = -ENOMEM;
 
779
                                break;
 
780
                        }
 
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);
 
794
                        ret = 0;
 
795
                } else
 
796
                        ret = -EINVAL;
 
797
                break;
 
798
        case WRAP_IOCTL_LOAD_DRIVER:
 
799
                TRACE1("loading driver at %p", addr);
 
800
                load_driver = vmalloc(sizeof(*load_driver));
 
801
                if (!load_driver) {
 
802
                        ret = -ENOMEM;
 
803
                        break;
 
804
                }
 
805
                if (copy_from_user(load_driver, addr, sizeof(*load_driver)))
 
806
                        ret = -EFAULT;
 
807
                else
 
808
                        ret = load_user_space_driver(load_driver);
 
809
                vfree(load_driver);
 
810
                break;
 
811
        case WRAP_IOCTL_LOAD_BIN_FILE:
 
812
                if (copy_from_user(&load_bin_file, addr, sizeof(load_bin_file)))
 
813
                        ret = -EFAULT;
 
814
                else
 
815
                        ret = add_bin_file(&load_bin_file);
 
816
                break;
 
817
        default:
 
818
                ERROR("unknown ioctl %u", cmd);
 
819
                ret = -EINVAL;
 
820
                break;
 
821
        }
 
822
        complete(&loader_complete);
 
823
        EXIT1(return ret);
 
824
}
 
825
 
 
826
static int wrapper_ioctl_release(struct inode *inode, struct file *file)
 
827
{
 
828
        ENTER1("");
 
829
        return 0;
 
830
}
 
831
 
 
832
static struct file_operations wrapper_fops = {
 
833
        .owner          = THIS_MODULE,
 
834
        .ioctl          = wrapper_ioctl,
 
835
        .release        = wrapper_ioctl_release,
 
836
};
 
837
 
 
838
static struct miscdevice wrapper_misc = {
 
839
        .name   = DRIVER_NAME,
 
840
        .minor  = MISC_DYNAMIC_MINOR,
 
841
        .fops   = &wrapper_fops
 
842
};
 
843
 
 
844
int loader_init(void)
 
845
{
 
846
        int err;
 
847
 
 
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();
 
855
                EXIT1(return err);
 
856
        }
 
857
        register_devices();
 
858
        EXIT1(return 0);
 
859
}
 
860
 
 
861
void loader_exit(void)
 
862
{
 
863
        struct nt_list *cur, *next;
 
864
 
 
865
        ENTER1("");
 
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);
 
874
        }
 
875
        up(&loader_mutex);
 
876
        EXIT1(return);
 
877
}