OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [scripts/] [mod/] [file2alias.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* Simple code to turn various tables in an ELF file into alias definitions.
2
 * This deals with kernel datastructures where they should be
3
 * dealt with: in the kernel source.
4
 *
5
 * Copyright 2002-2003  Rusty Russell, IBM Corporation
6
 *           2003       Kai Germaschewski
7
 *
8
 *
9
 * This software may be used and distributed according to the terms
10
 * of the GNU General Public License, incorporated herein by reference.
11
 */
12
 
13
#include "modpost.h"
14
 
15
/* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
16
 * use either stdint.h or inttypes.h for the rest. */
17
#if KERNEL_ELFCLASS == ELFCLASS32
18
typedef Elf32_Addr      kernel_ulong_t;
19
#define BITS_PER_LONG 32
20
#else
21
typedef Elf64_Addr      kernel_ulong_t;
22
#define BITS_PER_LONG 64
23
#endif
24
#ifdef __sun__
25
#include <inttypes.h>
26
#else
27
#include <stdint.h>
28
#endif
29
 
30
#include <ctype.h>
31
 
32
typedef uint32_t        __u32;
33
typedef uint16_t        __u16;
34
typedef unsigned char   __u8;
35
 
36
/* Big exception to the "don't include kernel headers into userspace, which
37
 * even potentially has different endianness and word sizes, since
38
 * we handle those differences explicitly below */
39
#include "../../include/linux/mod_devicetable.h"
40
 
41
#define ADD(str, sep, cond, field)                              \
42
do {                                                            \
43
        strcat(str, sep);                                       \
44
        if (cond)                                               \
45
                sprintf(str + strlen(str),                      \
46
                        sizeof(field) == 1 ? "%02X" :           \
47
                        sizeof(field) == 2 ? "%04X" :           \
48
                        sizeof(field) == 4 ? "%08X" : "",       \
49
                        field);                                 \
50
        else                                                    \
51
                sprintf(str + strlen(str), "*");                \
52
} while(0)
53
 
54
/**
55
 * Check that sizeof(device_id type) are consistent with size of section
56
 * in .o file. If in-consistent then userspace and kernel does not agree
57
 * on actual size which is a bug.
58
 * Also verify that the final entry in the table is all zeros.
59
 **/
60
static void device_id_check(const char *modname, const char *device_id,
61
                            unsigned long size, unsigned long id_size,
62
                            void *symval)
63
{
64
        int i;
65
 
66
        if (size % id_size || size < id_size) {
67
                fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
68
                      "of the size of section __mod_%s_device_table=%lu.\n"
69
                      "Fix definition of struct %s_device_id "
70
                      "in mod_devicetable.h\n",
71
                      modname, device_id, id_size, device_id, size, device_id);
72
        }
73
        /* Verify last one is a terminator */
74
        for (i = 0; i < id_size; i++ ) {
75
                if (*(uint8_t*)(symval+size-id_size+i)) {
76
                        fprintf(stderr,"%s: struct %s_device_id is %lu bytes.  "
77
                                "The last of %lu is:\n",
78
                                modname, device_id, id_size, size / id_size);
79
                        for (i = 0; i < id_size; i++ )
80
                                fprintf(stderr,"0x%02x ",
81
                                        *(uint8_t*)(symval+size-id_size+i) );
82
                        fprintf(stderr,"\n");
83
                        fatal("%s: struct %s_device_id is not terminated "
84
                                "with a NULL entry!\n", modname, device_id);
85
                }
86
        }
87
}
88
 
89
/* USB is special because the bcdDevice can be matched against a numeric range */
90
/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
91
static void do_usb_entry(struct usb_device_id *id,
92
                         unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
93
                         unsigned char range_lo, unsigned char range_hi,
94
                         struct module *mod)
95
{
96
        char alias[500];
97
        strcpy(alias, "usb:");
98
        ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR,
99
            id->idVendor);
100
        ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
101
            id->idProduct);
102
 
103
        strcat(alias, "d");
104
        if (bcdDevice_initial_digits)
105
                sprintf(alias + strlen(alias), "%0*X",
106
                        bcdDevice_initial_digits, bcdDevice_initial);
107
        if (range_lo == range_hi)
108
                sprintf(alias + strlen(alias), "%u", range_lo);
109
        else if (range_lo > 0 || range_hi < 9)
110
                sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi);
111
        if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
112
                strcat(alias, "*");
113
 
114
        ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
115
            id->bDeviceClass);
116
        ADD(alias, "dsc",
117
            id->match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
118
            id->bDeviceSubClass);
119
        ADD(alias, "dp",
120
            id->match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
121
            id->bDeviceProtocol);
122
        ADD(alias, "ic",
123
            id->match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
124
            id->bInterfaceClass);
125
        ADD(alias, "isc",
126
            id->match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
127
            id->bInterfaceSubClass);
128
        ADD(alias, "ip",
129
            id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
130
            id->bInterfaceProtocol);
131
 
132
        /* Always end in a wildcard, for future extension */
133
        if (alias[strlen(alias)-1] != '*')
134
                strcat(alias, "*");
135
        buf_printf(&mod->dev_table_buf,
136
                   "MODULE_ALIAS(\"%s\");\n", alias);
137
}
138
 
139
static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
140
{
141
        unsigned int devlo, devhi;
142
        unsigned char chi, clo;
143
        int ndigits;
144
 
145
        id->match_flags = TO_NATIVE(id->match_flags);
146
        id->idVendor = TO_NATIVE(id->idVendor);
147
        id->idProduct = TO_NATIVE(id->idProduct);
148
 
149
        devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
150
                TO_NATIVE(id->bcdDevice_lo) : 0x0U;
151
        devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
152
                TO_NATIVE(id->bcdDevice_hi) : ~0x0U;
153
 
154
        /*
155
         * Some modules (visor) have empty slots as placeholder for
156
         * run-time specification that results in catch-all alias
157
         */
158
        if (!(id->idVendor | id->bDeviceClass | id->bInterfaceClass))
159
                return;
160
 
161
        /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
162
        for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
163
                clo = devlo & 0xf;
164
                chi = devhi & 0xf;
165
                if (chi > 9)    /* it's bcd not hex */
166
                        chi = 9;
167
                devlo >>= 4;
168
                devhi >>= 4;
169
 
170
                if (devlo == devhi || !ndigits) {
171
                        do_usb_entry(id, devlo, ndigits, clo, chi, mod);
172
                        break;
173
                }
174
 
175
                if (clo > 0)
176
                        do_usb_entry(id, devlo++, ndigits, clo, 9, mod);
177
 
178
                if (chi < 9)
179
                        do_usb_entry(id, devhi--, ndigits, 0, chi, mod);
180
        }
181
}
182
 
183
static void do_usb_table(void *symval, unsigned long size,
184
                         struct module *mod)
185
{
186
        unsigned int i;
187
        const unsigned long id_size = sizeof(struct usb_device_id);
188
 
189
        device_id_check(mod->name, "usb", size, id_size, symval);
190
 
191
        /* Leave last one: it's the terminator. */
192
        size -= id_size;
193
 
194
        for (i = 0; i < size; i += id_size)
195
                do_usb_entry_multi(symval + i, mod);
196
}
197
 
198
/* Looks like: ieee1394:venNmoNspNverN */
199
static int do_ieee1394_entry(const char *filename,
200
                             struct ieee1394_device_id *id, char *alias)
201
{
202
        id->match_flags = TO_NATIVE(id->match_flags);
203
        id->vendor_id = TO_NATIVE(id->vendor_id);
204
        id->model_id = TO_NATIVE(id->model_id);
205
        id->specifier_id = TO_NATIVE(id->specifier_id);
206
        id->version = TO_NATIVE(id->version);
207
 
208
        strcpy(alias, "ieee1394:");
209
        ADD(alias, "ven", id->match_flags & IEEE1394_MATCH_VENDOR_ID,
210
            id->vendor_id);
211
        ADD(alias, "mo", id->match_flags & IEEE1394_MATCH_MODEL_ID,
212
            id->model_id);
213
        ADD(alias, "sp", id->match_flags & IEEE1394_MATCH_SPECIFIER_ID,
214
            id->specifier_id);
215
        ADD(alias, "ver", id->match_flags & IEEE1394_MATCH_VERSION,
216
            id->version);
217
 
218
        return 1;
219
}
220
 
221
/* Looks like: pci:vNdNsvNsdNbcNscNiN. */
222
static int do_pci_entry(const char *filename,
223
                        struct pci_device_id *id, char *alias)
224
{
225
        /* Class field can be divided into these three. */
226
        unsigned char baseclass, subclass, interface,
227
                baseclass_mask, subclass_mask, interface_mask;
228
 
229
        id->vendor = TO_NATIVE(id->vendor);
230
        id->device = TO_NATIVE(id->device);
231
        id->subvendor = TO_NATIVE(id->subvendor);
232
        id->subdevice = TO_NATIVE(id->subdevice);
233
        id->class = TO_NATIVE(id->class);
234
        id->class_mask = TO_NATIVE(id->class_mask);
235
 
236
        strcpy(alias, "pci:");
237
        ADD(alias, "v", id->vendor != PCI_ANY_ID, id->vendor);
238
        ADD(alias, "d", id->device != PCI_ANY_ID, id->device);
239
        ADD(alias, "sv", id->subvendor != PCI_ANY_ID, id->subvendor);
240
        ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice);
241
 
242
        baseclass = (id->class) >> 16;
243
        baseclass_mask = (id->class_mask) >> 16;
244
        subclass = (id->class) >> 8;
245
        subclass_mask = (id->class_mask) >> 8;
246
        interface = id->class;
247
        interface_mask = id->class_mask;
248
 
249
        if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
250
            || (subclass_mask != 0 && subclass_mask != 0xFF)
251
            || (interface_mask != 0 && interface_mask != 0xFF)) {
252
                warn("Can't handle masks in %s:%04X\n",
253
                     filename, id->class_mask);
254
                return 0;
255
        }
256
 
257
        ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
258
        ADD(alias, "sc", subclass_mask == 0xFF, subclass);
259
        ADD(alias, "i", interface_mask == 0xFF, interface);
260
        return 1;
261
}
262
 
263
/* looks like: "ccw:tNmNdtNdmN" */
264
static int do_ccw_entry(const char *filename,
265
                        struct ccw_device_id *id, char *alias)
266
{
267
        id->match_flags = TO_NATIVE(id->match_flags);
268
        id->cu_type = TO_NATIVE(id->cu_type);
269
        id->cu_model = TO_NATIVE(id->cu_model);
270
        id->dev_type = TO_NATIVE(id->dev_type);
271
        id->dev_model = TO_NATIVE(id->dev_model);
272
 
273
        strcpy(alias, "ccw:");
274
        ADD(alias, "t", id->match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
275
            id->cu_type);
276
        ADD(alias, "m", id->match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
277
            id->cu_model);
278
        ADD(alias, "dt", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
279
            id->dev_type);
280
        ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
281
            id->dev_model);
282
        return 1;
283
}
284
 
285
/* looks like: "ap:tN" */
286
static int do_ap_entry(const char *filename,
287
                       struct ap_device_id *id, char *alias)
288
{
289
        sprintf(alias, "ap:t%02X", id->dev_type);
290
        return 1;
291
}
292
 
293
/* Looks like: "serio:tyNprNidNexN" */
294
static int do_serio_entry(const char *filename,
295
                          struct serio_device_id *id, char *alias)
296
{
297
        id->type = TO_NATIVE(id->type);
298
        id->proto = TO_NATIVE(id->proto);
299
        id->id = TO_NATIVE(id->id);
300
        id->extra = TO_NATIVE(id->extra);
301
 
302
        strcpy(alias, "serio:");
303
        ADD(alias, "ty", id->type != SERIO_ANY, id->type);
304
        ADD(alias, "pr", id->proto != SERIO_ANY, id->proto);
305
        ADD(alias, "id", id->id != SERIO_ANY, id->id);
306
        ADD(alias, "ex", id->extra != SERIO_ANY, id->extra);
307
 
308
        return 1;
309
}
310
 
311
/* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */
312
static int do_acpi_entry(const char *filename,
313
                        struct acpi_device_id *id, char *alias)
314
{
315
        sprintf(alias, "acpi*:%s:", id->id);
316
        return 1;
317
}
318
 
319
/* looks like: "pnp:dD" */
320
static int do_pnp_entry(const char *filename,
321
                        struct pnp_device_id *id, char *alias)
322
{
323
        sprintf(alias, "pnp:d%s", id->id);
324
        return 1;
325
}
326
 
327
/* looks like: "pnp:cCdD..." */
328
static int do_pnp_card_entry(const char *filename,
329
                        struct pnp_card_device_id *id, char *alias)
330
{
331
        int i;
332
 
333
        sprintf(alias, "pnp:c%s", id->id);
334
        for (i = 0; i < PNP_MAX_DEVICES; i++) {
335
                if (! *id->devs[i].id)
336
                        break;
337
                sprintf(alias + strlen(alias), "d%s", id->devs[i].id);
338
        }
339
        return 1;
340
}
341
 
342
/* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
343
static int do_pcmcia_entry(const char *filename,
344
                           struct pcmcia_device_id *id, char *alias)
345
{
346
        unsigned int i;
347
 
348
        id->match_flags = TO_NATIVE(id->match_flags);
349
        id->manf_id = TO_NATIVE(id->manf_id);
350
        id->card_id = TO_NATIVE(id->card_id);
351
        id->func_id = TO_NATIVE(id->func_id);
352
        id->function = TO_NATIVE(id->function);
353
        id->device_no = TO_NATIVE(id->device_no);
354
 
355
        for (i=0; i<4; i++) {
356
                id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]);
357
       }
358
 
359
       strcpy(alias, "pcmcia:");
360
       ADD(alias, "m", id->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
361
           id->manf_id);
362
       ADD(alias, "c", id->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
363
           id->card_id);
364
       ADD(alias, "f", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
365
           id->func_id);
366
       ADD(alias, "fn", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
367
           id->function);
368
       ADD(alias, "pfn", id->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
369
           id->device_no);
370
       ADD(alias, "pa", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, id->prod_id_hash[0]);
371
       ADD(alias, "pb", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, id->prod_id_hash[1]);
372
       ADD(alias, "pc", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, id->prod_id_hash[2]);
373
       ADD(alias, "pd", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, id->prod_id_hash[3]);
374
 
375
       return 1;
376
}
377
 
378
 
379
 
380
static int do_of_entry (const char *filename, struct of_device_id *of, char *alias)
381
{
382
    int len;
383
    char *tmp;
384
    len = sprintf (alias, "of:N%sT%s",
385
                    of->name[0] ? of->name : "*",
386
                    of->type[0] ? of->type : "*");
387
 
388
    if (of->compatible[0])
389
        sprintf (&alias[len], "%sC%s",
390
                     of->type[0] ? "*" : "",
391
                     of->compatible);
392
 
393
    /* Replace all whitespace with underscores */
394
    for (tmp = alias; tmp && *tmp; tmp++)
395
        if (isspace (*tmp))
396
            *tmp = '_';
397
 
398
    return 1;
399
}
400
 
401
static int do_vio_entry(const char *filename, struct vio_device_id *vio,
402
                char *alias)
403
{
404
        char *tmp;
405
 
406
        sprintf(alias, "vio:T%sS%s", vio->type[0] ? vio->type : "*",
407
                        vio->compat[0] ? vio->compat : "*");
408
 
409
        /* Replace all whitespace with underscores */
410
        for (tmp = alias; tmp && *tmp; tmp++)
411
                if (isspace (*tmp))
412
                        *tmp = '_';
413
 
414
        return 1;
415
}
416
 
417
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
418
 
419
static void do_input(char *alias,
420
                     kernel_ulong_t *arr, unsigned int min, unsigned int max)
421
{
422
        unsigned int i;
423
 
424
        for (i = min; i < max; i++)
425
                if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
426
                        sprintf(alias + strlen(alias), "%X,*", i);
427
}
428
 
429
/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
430
static int do_input_entry(const char *filename, struct input_device_id *id,
431
                          char *alias)
432
{
433
        sprintf(alias, "input:");
434
 
435
        ADD(alias, "b", id->flags & INPUT_DEVICE_ID_MATCH_BUS, id->bustype);
436
        ADD(alias, "v", id->flags & INPUT_DEVICE_ID_MATCH_VENDOR, id->vendor);
437
        ADD(alias, "p", id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT, id->product);
438
        ADD(alias, "e", id->flags & INPUT_DEVICE_ID_MATCH_VERSION, id->version);
439
 
440
        sprintf(alias + strlen(alias), "-e*");
441
        if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
442
                do_input(alias, id->evbit, 0, INPUT_DEVICE_ID_EV_MAX);
443
        sprintf(alias + strlen(alias), "k*");
444
        if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
445
                do_input(alias, id->keybit,
446
                         INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
447
                         INPUT_DEVICE_ID_KEY_MAX);
448
        sprintf(alias + strlen(alias), "r*");
449
        if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
450
                do_input(alias, id->relbit, 0, INPUT_DEVICE_ID_REL_MAX);
451
        sprintf(alias + strlen(alias), "a*");
452
        if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
453
                do_input(alias, id->absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
454
        sprintf(alias + strlen(alias), "m*");
455
        if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
456
                do_input(alias, id->mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
457
        sprintf(alias + strlen(alias), "l*");
458
        if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
459
                do_input(alias, id->ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
460
        sprintf(alias + strlen(alias), "s*");
461
        if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
462
                do_input(alias, id->sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
463
        sprintf(alias + strlen(alias), "f*");
464
        if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
465
                do_input(alias, id->ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
466
        sprintf(alias + strlen(alias), "w*");
467
        if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
468
                do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX);
469
        return 1;
470
}
471
 
472
static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa,
473
                char *alias)
474
{
475
        if (eisa->sig[0])
476
                sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", eisa->sig);
477
        return 1;
478
}
479
 
480
/* Looks like: parisc:tNhvNrevNsvN */
481
static int do_parisc_entry(const char *filename, struct parisc_device_id *id,
482
                char *alias)
483
{
484
        id->hw_type = TO_NATIVE(id->hw_type);
485
        id->hversion = TO_NATIVE(id->hversion);
486
        id->hversion_rev = TO_NATIVE(id->hversion_rev);
487
        id->sversion = TO_NATIVE(id->sversion);
488
 
489
        strcpy(alias, "parisc:");
490
        ADD(alias, "t", id->hw_type != PA_HWTYPE_ANY_ID, id->hw_type);
491
        ADD(alias, "hv", id->hversion != PA_HVERSION_ANY_ID, id->hversion);
492
        ADD(alias, "rev", id->hversion_rev != PA_HVERSION_REV_ANY_ID, id->hversion_rev);
493
        ADD(alias, "sv", id->sversion != PA_SVERSION_ANY_ID, id->sversion);
494
 
495
        return 1;
496
}
497
 
498
/* Looks like: sdio:cNvNdN. */
499
static int do_sdio_entry(const char *filename,
500
                        struct sdio_device_id *id, char *alias)
501
{
502
        id->class = TO_NATIVE(id->class);
503
        id->vendor = TO_NATIVE(id->vendor);
504
        id->device = TO_NATIVE(id->device);
505
 
506
        strcpy(alias, "sdio:");
507
        ADD(alias, "c", id->class != (__u8)SDIO_ANY_ID, id->class);
508
        ADD(alias, "v", id->vendor != (__u16)SDIO_ANY_ID, id->vendor);
509
        ADD(alias, "d", id->device != (__u16)SDIO_ANY_ID, id->device);
510
        return 1;
511
}
512
 
513
/* Looks like: ssb:vNidNrevN. */
514
static int do_ssb_entry(const char *filename,
515
                        struct ssb_device_id *id, char *alias)
516
{
517
        id->vendor = TO_NATIVE(id->vendor);
518
        id->coreid = TO_NATIVE(id->coreid);
519
        id->revision = TO_NATIVE(id->revision);
520
 
521
        strcpy(alias, "ssb:");
522
        ADD(alias, "v", id->vendor != SSB_ANY_VENDOR, id->vendor);
523
        ADD(alias, "id", id->coreid != SSB_ANY_ID, id->coreid);
524
        ADD(alias, "rev", id->revision != SSB_ANY_REV, id->revision);
525
        return 1;
526
}
527
 
528
/* Looks like: virtio:dNvN */
529
static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
530
                           char *alias)
531
{
532
        id->device = TO_NATIVE(id->device);
533
        id->vendor = TO_NATIVE(id->vendor);
534
 
535
        strcpy(alias, "virtio:");
536
        ADD(alias, "d", 1, id->device);
537
        ADD(alias, "v", id->vendor != VIRTIO_DEV_ANY_ID, id->vendor);
538
 
539
        return 1;
540
}
541
 
542
/* Ignore any prefix, eg. v850 prepends _ */
543
static inline int sym_is(const char *symbol, const char *name)
544
{
545
        const char *match;
546
 
547
        match = strstr(symbol, name);
548
        if (!match)
549
                return 0;
550
        return match[strlen(symbol)] == '\0';
551
}
552
 
553
static void do_table(void *symval, unsigned long size,
554
                     unsigned long id_size,
555
                     const char *device_id,
556
                     void *function,
557
                     struct module *mod)
558
{
559
        unsigned int i;
560
        char alias[500];
561
        int (*do_entry)(const char *, void *entry, char *alias) = function;
562
 
563
        device_id_check(mod->name, device_id, size, id_size, symval);
564
        /* Leave last one: it's the terminator. */
565
        size -= id_size;
566
 
567
        for (i = 0; i < size; i += id_size) {
568
                if (do_entry(mod->name, symval+i, alias)) {
569
                        /* Always end in a wildcard, for future extension */
570
                        if (alias[strlen(alias)-1] != '*')
571
                                strcat(alias, "*");
572
                        buf_printf(&mod->dev_table_buf,
573
                                   "MODULE_ALIAS(\"%s\");\n", alias);
574
                }
575
        }
576
}
577
 
578
/* Create MODULE_ALIAS() statements.
579
 * At this time, we cannot write the actual output C source yet,
580
 * so we write into the mod->dev_table_buf buffer. */
581
void handle_moddevtable(struct module *mod, struct elf_info *info,
582
                        Elf_Sym *sym, const char *symname)
583
{
584
        void *symval;
585
        char *zeros = NULL;
586
 
587
        /* We're looking for a section relative symbol */
588
        if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
589
                return;
590
 
591
        /* Handle all-NULL symbols allocated into .bss */
592
        if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) {
593
                zeros = calloc(1, sym->st_size);
594
                symval = zeros;
595
        } else {
596
                symval = (void *)info->hdr
597
                        + info->sechdrs[sym->st_shndx].sh_offset
598
                        + sym->st_value;
599
        }
600
 
601
        if (sym_is(symname, "__mod_pci_device_table"))
602
                do_table(symval, sym->st_size,
603
                         sizeof(struct pci_device_id), "pci",
604
                         do_pci_entry, mod);
605
        else if (sym_is(symname, "__mod_usb_device_table"))
606
                /* special case to handle bcdDevice ranges */
607
                do_usb_table(symval, sym->st_size, mod);
608
        else if (sym_is(symname, "__mod_ieee1394_device_table"))
609
                do_table(symval, sym->st_size,
610
                         sizeof(struct ieee1394_device_id), "ieee1394",
611
                         do_ieee1394_entry, mod);
612
        else if (sym_is(symname, "__mod_ccw_device_table"))
613
                do_table(symval, sym->st_size,
614
                         sizeof(struct ccw_device_id), "ccw",
615
                         do_ccw_entry, mod);
616
        else if (sym_is(symname, "__mod_ap_device_table"))
617
                do_table(symval, sym->st_size,
618
                         sizeof(struct ap_device_id), "ap",
619
                         do_ap_entry, mod);
620
        else if (sym_is(symname, "__mod_serio_device_table"))
621
                do_table(symval, sym->st_size,
622
                         sizeof(struct serio_device_id), "serio",
623
                         do_serio_entry, mod);
624
        else if (sym_is(symname, "__mod_acpi_device_table"))
625
                do_table(symval, sym->st_size,
626
                         sizeof(struct acpi_device_id), "acpi",
627
                         do_acpi_entry, mod);
628
        else if (sym_is(symname, "__mod_pnp_device_table"))
629
                do_table(symval, sym->st_size,
630
                         sizeof(struct pnp_device_id), "pnp",
631
                         do_pnp_entry, mod);
632
        else if (sym_is(symname, "__mod_pnp_card_device_table"))
633
                do_table(symval, sym->st_size,
634
                         sizeof(struct pnp_card_device_id), "pnp_card",
635
                         do_pnp_card_entry, mod);
636
        else if (sym_is(symname, "__mod_pcmcia_device_table"))
637
                do_table(symval, sym->st_size,
638
                         sizeof(struct pcmcia_device_id), "pcmcia",
639
                         do_pcmcia_entry, mod);
640
        else if (sym_is(symname, "__mod_of_device_table"))
641
                do_table(symval, sym->st_size,
642
                         sizeof(struct of_device_id), "of",
643
                         do_of_entry, mod);
644
        else if (sym_is(symname, "__mod_vio_device_table"))
645
                do_table(symval, sym->st_size,
646
                         sizeof(struct vio_device_id), "vio",
647
                         do_vio_entry, mod);
648
        else if (sym_is(symname, "__mod_input_device_table"))
649
                do_table(symval, sym->st_size,
650
                         sizeof(struct input_device_id), "input",
651
                         do_input_entry, mod);
652
        else if (sym_is(symname, "__mod_eisa_device_table"))
653
                do_table(symval, sym->st_size,
654
                         sizeof(struct eisa_device_id), "eisa",
655
                         do_eisa_entry, mod);
656
        else if (sym_is(symname, "__mod_parisc_device_table"))
657
                do_table(symval, sym->st_size,
658
                         sizeof(struct parisc_device_id), "parisc",
659
                         do_parisc_entry, mod);
660
        else if (sym_is(symname, "__mod_sdio_device_table"))
661
                do_table(symval, sym->st_size,
662
                         sizeof(struct sdio_device_id), "sdio",
663
                         do_sdio_entry, mod);
664
        else if (sym_is(symname, "__mod_ssb_device_table"))
665
                do_table(symval, sym->st_size,
666
                         sizeof(struct ssb_device_id), "ssb",
667
                         do_ssb_entry, mod);
668
        else if (sym_is(symname, "__mod_virtio_device_table"))
669
                do_table(symval, sym->st_size,
670
                         sizeof(struct virtio_device_id), "virtio",
671
                         do_virtio_entry, mod);
672
        free(zeros);
673
}
674
 
675
/* Now add out buffered information to the generated C source */
676
void add_moddevtable(struct buffer *buf, struct module *mod)
677
{
678
        buf_printf(buf, "\n");
679
        buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
680
        free(mod->dev_table_buf.p);
681
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.