1 /* 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.
5 * Copyright 2002-2003 Rusty Russell, IBM Corporation
6 * 2003 Kai Germaschewski
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
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
21 typedef Elf64_Addr kernel_ulong_t
;
22 #define BITS_PER_LONG 64
33 typedef uint32_t __u32
;
34 typedef uint16_t __u16
;
35 typedef unsigned char __u8
;
37 /* Big exception to the "don't include kernel headers into userspace, which
38 * even potentially has different endianness and word sizes, since
39 * we handle those differences explicitly below */
40 #include "../../include/linux/mod_devicetable.h"
42 /* This array collects all instances that use the generic do_table */
44 const char *device_id
; /* name of table, __mod_<name>_device_table. */
45 unsigned long id_size
;
49 /* We construct a table of pointers in an ELF section (pointers generally
50 * go unpadded by gcc). ld creates boundary syms for us. */
51 extern struct devtable
*__start___devtable
[], *__stop___devtable
[];
52 #define ___cat(a,b) a ## b
53 #define __cat(a,b) ___cat(a,b)
55 #if __GNUC__ == 3 && __GNUC_MINOR__ < 3
56 # define __used __attribute__((__unused__))
58 # define __used __attribute__((__used__))
61 /* Add a table entry. We test function type matches while we're here. */
62 #define ADD_TO_DEVTABLE(device_id, type, function) \
63 static struct devtable __cat(devtable,__LINE__) = { \
64 device_id + 0*sizeof((function)((const char *)NULL, \
67 sizeof(type), (function) }; \
68 static struct devtable *__attribute__((section("__devtable"))) \
69 __used __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__)
71 #define ADD(str, sep, cond, field) \
75 sprintf(str + strlen(str), \
76 sizeof(field) == 1 ? "%02X" : \
77 sizeof(field) == 2 ? "%04X" : \
78 sizeof(field) == 4 ? "%08X" : "", \
81 sprintf(str + strlen(str), "*"); \
84 /* Always end in a wildcard, for future extension */
85 static inline void add_wildcard(char *str
)
87 int len
= strlen(str
);
89 if (str
[len
- 1] != '*')
90 strcat(str
+ len
, "*");
93 unsigned int cross_build
= 0;
95 * Check that sizeof(device_id type) are consistent with size of section
96 * in .o file. If in-consistent then userspace and kernel does not agree
97 * on actual size which is a bug.
98 * Also verify that the final entry in the table is all zeros.
99 * Ignore both checks if build host differ from target host and size differs.
101 static void device_id_check(const char *modname
, const char *device_id
,
102 unsigned long size
, unsigned long id_size
,
107 if (size
% id_size
|| size
< id_size
) {
108 if (cross_build
!= 0)
110 fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
111 "of the size of section __mod_%s_device_table=%lu.\n"
112 "Fix definition of struct %s_device_id "
113 "in mod_devicetable.h\n",
114 modname
, device_id
, id_size
, device_id
, size
, device_id
);
116 /* Verify last one is a terminator */
117 for (i
= 0; i
< id_size
; i
++ ) {
118 if (*(uint8_t*)(symval
+size
-id_size
+i
)) {
119 fprintf(stderr
,"%s: struct %s_device_id is %lu bytes. "
120 "The last of %lu is:\n",
121 modname
, device_id
, id_size
, size
/ id_size
);
122 for (i
= 0; i
< id_size
; i
++ )
123 fprintf(stderr
,"0x%02x ",
124 *(uint8_t*)(symval
+size
-id_size
+i
) );
125 fprintf(stderr
,"\n");
126 fatal("%s: struct %s_device_id is not terminated "
127 "with a NULL entry!\n", modname
, device_id
);
132 /* USB is special because the bcdDevice can be matched against a numeric range */
133 /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
134 static void do_usb_entry(struct usb_device_id
*id
,
135 unsigned int bcdDevice_initial
, int bcdDevice_initial_digits
,
136 unsigned char range_lo
, unsigned char range_hi
,
137 unsigned char max
, struct module
*mod
)
140 strcpy(alias
, "usb:");
141 ADD(alias
, "v", id
->match_flags
&USB_DEVICE_ID_MATCH_VENDOR
,
143 ADD(alias
, "p", id
->match_flags
&USB_DEVICE_ID_MATCH_PRODUCT
,
147 if (bcdDevice_initial_digits
)
148 sprintf(alias
+ strlen(alias
), "%0*X",
149 bcdDevice_initial_digits
, bcdDevice_initial
);
150 if (range_lo
== range_hi
)
151 sprintf(alias
+ strlen(alias
), "%X", range_lo
);
152 else if (range_lo
> 0 || range_hi
< max
) {
153 if (range_lo
> 0x9 || range_hi
< 0xA)
154 sprintf(alias
+ strlen(alias
),
159 sprintf(alias
+ strlen(alias
),
160 range_lo
< 0x9 ? "[%X-9" : "[%X",
162 sprintf(alias
+ strlen(alias
),
163 range_hi
> 0xA ? "a-%X]" : "%X]",
167 if (bcdDevice_initial_digits
< (sizeof(id
->bcdDevice_lo
) * 2 - 1))
170 ADD(alias
, "dc", id
->match_flags
&USB_DEVICE_ID_MATCH_DEV_CLASS
,
173 id
->match_flags
&USB_DEVICE_ID_MATCH_DEV_SUBCLASS
,
174 id
->bDeviceSubClass
);
176 id
->match_flags
&USB_DEVICE_ID_MATCH_DEV_PROTOCOL
,
177 id
->bDeviceProtocol
);
179 id
->match_flags
&USB_DEVICE_ID_MATCH_INT_CLASS
,
180 id
->bInterfaceClass
);
182 id
->match_flags
&USB_DEVICE_ID_MATCH_INT_SUBCLASS
,
183 id
->bInterfaceSubClass
);
185 id
->match_flags
&USB_DEVICE_ID_MATCH_INT_PROTOCOL
,
186 id
->bInterfaceProtocol
);
189 buf_printf(&mod
->dev_table_buf
,
190 "MODULE_ALIAS(\"%s\");\n", alias
);
193 /* Handles increment/decrement of BCD formatted integers */
194 /* Returns the previous value, so it works like i++ or i-- */
195 static unsigned int incbcd(unsigned int *bcd
,
200 unsigned int init
= *bcd
, i
, j
;
201 unsigned long long c
, dec
= 0;
203 /* If bcd is not in BCD format, just increment */
209 /* Convert BCD to Decimal */
210 for (i
=0 ; i
< chars
; i
++) {
211 c
= (*bcd
>> (i
<< 2)) & 0xf;
212 c
= c
> 9 ? 9 : c
; /* force to bcd just in case */
213 for (j
=0 ; j
< i
; j
++)
218 /* Do our increment/decrement */
222 /* Convert back to BCD */
223 for (i
=0 ; i
< chars
; i
++) {
224 for (c
=1,j
=0 ; j
< i
; j
++)
227 *bcd
+= c
<< (i
<< 2);
232 static void do_usb_entry_multi(struct usb_device_id
*id
, struct module
*mod
)
234 unsigned int devlo
, devhi
;
235 unsigned char chi
, clo
, max
;
238 id
->match_flags
= TO_NATIVE(id
->match_flags
);
239 id
->idVendor
= TO_NATIVE(id
->idVendor
);
240 id
->idProduct
= TO_NATIVE(id
->idProduct
);
242 devlo
= id
->match_flags
& USB_DEVICE_ID_MATCH_DEV_LO
?
243 TO_NATIVE(id
->bcdDevice_lo
) : 0x0U
;
244 devhi
= id
->match_flags
& USB_DEVICE_ID_MATCH_DEV_HI
?
245 TO_NATIVE(id
->bcdDevice_hi
) : ~0x0U
;
247 /* Figure out if this entry is in bcd or hex format */
248 max
= 0x9; /* Default to decimal format */
249 for (ndigits
= 0 ; ndigits
< sizeof(id
->bcdDevice_lo
) * 2 ; ndigits
++) {
250 clo
= (devlo
>> (ndigits
<< 2)) & 0xf;
251 chi
= ((devhi
> 0x9999 ? 0x9999 : devhi
) >> (ndigits
<< 2)) & 0xf;
252 if (clo
> max
|| chi
> max
) {
259 * Some modules (visor) have empty slots as placeholder for
260 * run-time specification that results in catch-all alias
262 if (!(id
->idVendor
| id
->idProduct
| id
->bDeviceClass
| id
->bInterfaceClass
))
265 /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
266 for (ndigits
= sizeof(id
->bcdDevice_lo
) * 2 - 1; devlo
<= devhi
; ndigits
--) {
269 if (chi
> max
) /* If we are in bcd mode, truncate if necessary */
274 if (devlo
== devhi
|| !ndigits
) {
275 do_usb_entry(id
, devlo
, ndigits
, clo
, chi
, max
, mod
);
281 incbcd(&devlo
, 1, max
,
282 sizeof(id
->bcdDevice_lo
) * 2),
283 ndigits
, clo
, max
, max
, mod
);
287 incbcd(&devhi
, -1, max
,
288 sizeof(id
->bcdDevice_lo
) * 2),
289 ndigits
, 0x0, chi
, max
, mod
);
293 static void do_usb_table(void *symval
, unsigned long size
,
297 const unsigned long id_size
= sizeof(struct usb_device_id
);
299 device_id_check(mod
->name
, "usb", size
, id_size
, symval
);
301 /* Leave last one: it's the terminator. */
304 for (i
= 0; i
< size
; i
+= id_size
)
305 do_usb_entry_multi(symval
+ i
, mod
);
308 /* Looks like: hid:bNvNpN */
309 static int do_hid_entry(const char *filename
,
310 struct hid_device_id
*id
, char *alias
)
312 id
->bus
= TO_NATIVE(id
->bus
);
313 id
->vendor
= TO_NATIVE(id
->vendor
);
314 id
->product
= TO_NATIVE(id
->product
);
316 sprintf(alias
, "hid:b%04X", id
->bus
);
317 ADD(alias
, "v", id
->vendor
!= HID_ANY_ID
, id
->vendor
);
318 ADD(alias
, "p", id
->product
!= HID_ANY_ID
, id
->product
);
322 ADD_TO_DEVTABLE("hid", struct hid_device_id
, do_hid_entry
);
324 /* Looks like: ieee1394:venNmoNspNverN */
325 static int do_ieee1394_entry(const char *filename
,
326 struct ieee1394_device_id
*id
, char *alias
)
328 id
->match_flags
= TO_NATIVE(id
->match_flags
);
329 id
->vendor_id
= TO_NATIVE(id
->vendor_id
);
330 id
->model_id
= TO_NATIVE(id
->model_id
);
331 id
->specifier_id
= TO_NATIVE(id
->specifier_id
);
332 id
->version
= TO_NATIVE(id
->version
);
334 strcpy(alias
, "ieee1394:");
335 ADD(alias
, "ven", id
->match_flags
& IEEE1394_MATCH_VENDOR_ID
,
337 ADD(alias
, "mo", id
->match_flags
& IEEE1394_MATCH_MODEL_ID
,
339 ADD(alias
, "sp", id
->match_flags
& IEEE1394_MATCH_SPECIFIER_ID
,
341 ADD(alias
, "ver", id
->match_flags
& IEEE1394_MATCH_VERSION
,
347 ADD_TO_DEVTABLE("ieee1394", struct ieee1394_device_id
, do_ieee1394_entry
);
349 /* Looks like: pci:vNdNsvNsdNbcNscNiN. */
350 static int do_pci_entry(const char *filename
,
351 struct pci_device_id
*id
, char *alias
)
353 /* Class field can be divided into these three. */
354 unsigned char baseclass
, subclass
, interface
,
355 baseclass_mask
, subclass_mask
, interface_mask
;
357 id
->vendor
= TO_NATIVE(id
->vendor
);
358 id
->device
= TO_NATIVE(id
->device
);
359 id
->subvendor
= TO_NATIVE(id
->subvendor
);
360 id
->subdevice
= TO_NATIVE(id
->subdevice
);
361 id
->class = TO_NATIVE(id
->class);
362 id
->class_mask
= TO_NATIVE(id
->class_mask
);
364 strcpy(alias
, "pci:");
365 ADD(alias
, "v", id
->vendor
!= PCI_ANY_ID
, id
->vendor
);
366 ADD(alias
, "d", id
->device
!= PCI_ANY_ID
, id
->device
);
367 ADD(alias
, "sv", id
->subvendor
!= PCI_ANY_ID
, id
->subvendor
);
368 ADD(alias
, "sd", id
->subdevice
!= PCI_ANY_ID
, id
->subdevice
);
370 baseclass
= (id
->class) >> 16;
371 baseclass_mask
= (id
->class_mask
) >> 16;
372 subclass
= (id
->class) >> 8;
373 subclass_mask
= (id
->class_mask
) >> 8;
374 interface
= id
->class;
375 interface_mask
= id
->class_mask
;
377 if ((baseclass_mask
!= 0 && baseclass_mask
!= 0xFF)
378 || (subclass_mask
!= 0 && subclass_mask
!= 0xFF)
379 || (interface_mask
!= 0 && interface_mask
!= 0xFF)) {
380 warn("Can't handle masks in %s:%04X\n",
381 filename
, id
->class_mask
);
385 ADD(alias
, "bc", baseclass_mask
== 0xFF, baseclass
);
386 ADD(alias
, "sc", subclass_mask
== 0xFF, subclass
);
387 ADD(alias
, "i", interface_mask
== 0xFF, interface
);
391 ADD_TO_DEVTABLE("pci", struct pci_device_id
, do_pci_entry
);
393 /* looks like: "ccw:tNmNdtNdmN" */
394 static int do_ccw_entry(const char *filename
,
395 struct ccw_device_id
*id
, char *alias
)
397 id
->match_flags
= TO_NATIVE(id
->match_flags
);
398 id
->cu_type
= TO_NATIVE(id
->cu_type
);
399 id
->cu_model
= TO_NATIVE(id
->cu_model
);
400 id
->dev_type
= TO_NATIVE(id
->dev_type
);
401 id
->dev_model
= TO_NATIVE(id
->dev_model
);
403 strcpy(alias
, "ccw:");
404 ADD(alias
, "t", id
->match_flags
&CCW_DEVICE_ID_MATCH_CU_TYPE
,
406 ADD(alias
, "m", id
->match_flags
&CCW_DEVICE_ID_MATCH_CU_MODEL
,
408 ADD(alias
, "dt", id
->match_flags
&CCW_DEVICE_ID_MATCH_DEVICE_TYPE
,
410 ADD(alias
, "dm", id
->match_flags
&CCW_DEVICE_ID_MATCH_DEVICE_MODEL
,
415 ADD_TO_DEVTABLE("ccw", struct ccw_device_id
, do_ccw_entry
);
417 /* looks like: "ap:tN" */
418 static int do_ap_entry(const char *filename
,
419 struct ap_device_id
*id
, char *alias
)
421 sprintf(alias
, "ap:t%02X*", id
->dev_type
);
424 ADD_TO_DEVTABLE("ap", struct ap_device_id
, do_ap_entry
);
426 /* looks like: "css:tN" */
427 static int do_css_entry(const char *filename
,
428 struct css_device_id
*id
, char *alias
)
430 sprintf(alias
, "css:t%01X", id
->type
);
433 ADD_TO_DEVTABLE("css", struct css_device_id
, do_css_entry
);
435 /* Looks like: "serio:tyNprNidNexN" */
436 static int do_serio_entry(const char *filename
,
437 struct serio_device_id
*id
, char *alias
)
439 id
->type
= TO_NATIVE(id
->type
);
440 id
->proto
= TO_NATIVE(id
->proto
);
441 id
->id
= TO_NATIVE(id
->id
);
442 id
->extra
= TO_NATIVE(id
->extra
);
444 strcpy(alias
, "serio:");
445 ADD(alias
, "ty", id
->type
!= SERIO_ANY
, id
->type
);
446 ADD(alias
, "pr", id
->proto
!= SERIO_ANY
, id
->proto
);
447 ADD(alias
, "id", id
->id
!= SERIO_ANY
, id
->id
);
448 ADD(alias
, "ex", id
->extra
!= SERIO_ANY
, id
->extra
);
453 ADD_TO_DEVTABLE("serio", struct serio_device_id
, do_serio_entry
);
455 /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */
456 static int do_acpi_entry(const char *filename
,
457 struct acpi_device_id
*id
, char *alias
)
459 sprintf(alias
, "acpi*:%s:*", id
->id
);
462 ADD_TO_DEVTABLE("acpi", struct acpi_device_id
, do_acpi_entry
);
464 /* looks like: "pnp:dD" */
465 static void do_pnp_device_entry(void *symval
, unsigned long size
,
468 const unsigned long id_size
= sizeof(struct pnp_device_id
);
469 const unsigned int count
= (size
/ id_size
)-1;
470 const struct pnp_device_id
*devs
= symval
;
473 device_id_check(mod
->name
, "pnp", size
, id_size
, symval
);
475 for (i
= 0; i
< count
; i
++) {
476 const char *id
= (char *)devs
[i
].id
;
477 char acpi_id
[sizeof(devs
[0].id
)];
480 buf_printf(&mod
->dev_table_buf
,
481 "MODULE_ALIAS(\"pnp:d%s*\");\n", id
);
483 /* fix broken pnp bus lowercasing */
484 for (j
= 0; j
< sizeof(acpi_id
); j
++)
485 acpi_id
[j
] = toupper(id
[j
]);
486 buf_printf(&mod
->dev_table_buf
,
487 "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id
);
491 /* looks like: "pnp:dD" for every device of the card */
492 static void do_pnp_card_entries(void *symval
, unsigned long size
,
495 const unsigned long id_size
= sizeof(struct pnp_card_device_id
);
496 const unsigned int count
= (size
/ id_size
)-1;
497 const struct pnp_card_device_id
*cards
= symval
;
500 device_id_check(mod
->name
, "pnp", size
, id_size
, symval
);
502 for (i
= 0; i
< count
; i
++) {
504 const struct pnp_card_device_id
*card
= &cards
[i
];
506 for (j
= 0; j
< PNP_MAX_DEVICES
; j
++) {
507 const char *id
= (char *)card
->devs
[j
].id
;
514 /* find duplicate, already added value */
515 for (i2
= 0; i2
< i
&& !dup
; i2
++) {
516 const struct pnp_card_device_id
*card2
= &cards
[i2
];
518 for (j2
= 0; j2
< PNP_MAX_DEVICES
; j2
++) {
519 const char *id2
= (char *)card2
->devs
[j2
].id
;
524 if (!strcmp(id
, id2
)) {
531 /* add an individual alias for every device entry */
533 char acpi_id
[sizeof(card
->devs
[0].id
)];
536 buf_printf(&mod
->dev_table_buf
,
537 "MODULE_ALIAS(\"pnp:d%s*\");\n", id
);
539 /* fix broken pnp bus lowercasing */
540 for (k
= 0; k
< sizeof(acpi_id
); k
++)
541 acpi_id
[k
] = toupper(id
[k
]);
542 buf_printf(&mod
->dev_table_buf
,
543 "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id
);
549 /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
550 static int do_pcmcia_entry(const char *filename
,
551 struct pcmcia_device_id
*id
, char *alias
)
555 id
->match_flags
= TO_NATIVE(id
->match_flags
);
556 id
->manf_id
= TO_NATIVE(id
->manf_id
);
557 id
->card_id
= TO_NATIVE(id
->card_id
);
558 id
->func_id
= TO_NATIVE(id
->func_id
);
559 id
->function
= TO_NATIVE(id
->function
);
560 id
->device_no
= TO_NATIVE(id
->device_no
);
562 for (i
=0; i
<4; i
++) {
563 id
->prod_id_hash
[i
] = TO_NATIVE(id
->prod_id_hash
[i
]);
566 strcpy(alias
, "pcmcia:");
567 ADD(alias
, "m", id
->match_flags
& PCMCIA_DEV_ID_MATCH_MANF_ID
,
569 ADD(alias
, "c", id
->match_flags
& PCMCIA_DEV_ID_MATCH_CARD_ID
,
571 ADD(alias
, "f", id
->match_flags
& PCMCIA_DEV_ID_MATCH_FUNC_ID
,
573 ADD(alias
, "fn", id
->match_flags
& PCMCIA_DEV_ID_MATCH_FUNCTION
,
575 ADD(alias
, "pfn", id
->match_flags
& PCMCIA_DEV_ID_MATCH_DEVICE_NO
,
577 ADD(alias
, "pa", id
->match_flags
& PCMCIA_DEV_ID_MATCH_PROD_ID1
, id
->prod_id_hash
[0]);
578 ADD(alias
, "pb", id
->match_flags
& PCMCIA_DEV_ID_MATCH_PROD_ID2
, id
->prod_id_hash
[1]);
579 ADD(alias
, "pc", id
->match_flags
& PCMCIA_DEV_ID_MATCH_PROD_ID3
, id
->prod_id_hash
[2]);
580 ADD(alias
, "pd", id
->match_flags
& PCMCIA_DEV_ID_MATCH_PROD_ID4
, id
->prod_id_hash
[3]);
585 ADD_TO_DEVTABLE("pcmcia", struct pcmcia_device_id
, do_pcmcia_entry
);
587 static int do_of_entry (const char *filename
, struct of_device_id
*of
, char *alias
)
591 len
= sprintf (alias
, "of:N%sT%s",
592 of
->name
[0] ? of
->name
: "*",
593 of
->type
[0] ? of
->type
: "*");
595 if (of
->compatible
[0])
596 sprintf (&alias
[len
], "%sC%s",
597 of
->type
[0] ? "*" : "",
600 /* Replace all whitespace with underscores */
601 for (tmp
= alias
; tmp
&& *tmp
; tmp
++)
608 ADD_TO_DEVTABLE("of", struct of_device_id
, do_of_entry
);
610 static int do_vio_entry(const char *filename
, struct vio_device_id
*vio
,
615 sprintf(alias
, "vio:T%sS%s", vio
->type
[0] ? vio
->type
: "*",
616 vio
->compat
[0] ? vio
->compat
: "*");
618 /* Replace all whitespace with underscores */
619 for (tmp
= alias
; tmp
&& *tmp
; tmp
++)
626 ADD_TO_DEVTABLE("vio", struct vio_device_id
, do_vio_entry
);
628 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
630 static void do_input(char *alias
,
631 kernel_ulong_t
*arr
, unsigned int min
, unsigned int max
)
635 for (i
= min
; i
< max
; i
++)
636 if (arr
[i
/ BITS_PER_LONG
] & (1L << (i
%BITS_PER_LONG
)))
637 sprintf(alias
+ strlen(alias
), "%X,*", i
);
640 /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
641 static int do_input_entry(const char *filename
, struct input_device_id
*id
,
644 sprintf(alias
, "input:");
646 ADD(alias
, "b", id
->flags
& INPUT_DEVICE_ID_MATCH_BUS
, id
->bustype
);
647 ADD(alias
, "v", id
->flags
& INPUT_DEVICE_ID_MATCH_VENDOR
, id
->vendor
);
648 ADD(alias
, "p", id
->flags
& INPUT_DEVICE_ID_MATCH_PRODUCT
, id
->product
);
649 ADD(alias
, "e", id
->flags
& INPUT_DEVICE_ID_MATCH_VERSION
, id
->version
);
651 sprintf(alias
+ strlen(alias
), "-e*");
652 if (id
->flags
& INPUT_DEVICE_ID_MATCH_EVBIT
)
653 do_input(alias
, id
->evbit
, 0, INPUT_DEVICE_ID_EV_MAX
);
654 sprintf(alias
+ strlen(alias
), "k*");
655 if (id
->flags
& INPUT_DEVICE_ID_MATCH_KEYBIT
)
656 do_input(alias
, id
->keybit
,
657 INPUT_DEVICE_ID_KEY_MIN_INTERESTING
,
658 INPUT_DEVICE_ID_KEY_MAX
);
659 sprintf(alias
+ strlen(alias
), "r*");
660 if (id
->flags
& INPUT_DEVICE_ID_MATCH_RELBIT
)
661 do_input(alias
, id
->relbit
, 0, INPUT_DEVICE_ID_REL_MAX
);
662 sprintf(alias
+ strlen(alias
), "a*");
663 if (id
->flags
& INPUT_DEVICE_ID_MATCH_ABSBIT
)
664 do_input(alias
, id
->absbit
, 0, INPUT_DEVICE_ID_ABS_MAX
);
665 sprintf(alias
+ strlen(alias
), "m*");
666 if (id
->flags
& INPUT_DEVICE_ID_MATCH_MSCIT
)
667 do_input(alias
, id
->mscbit
, 0, INPUT_DEVICE_ID_MSC_MAX
);
668 sprintf(alias
+ strlen(alias
), "l*");
669 if (id
->flags
& INPUT_DEVICE_ID_MATCH_LEDBIT
)
670 do_input(alias
, id
->ledbit
, 0, INPUT_DEVICE_ID_LED_MAX
);
671 sprintf(alias
+ strlen(alias
), "s*");
672 if (id
->flags
& INPUT_DEVICE_ID_MATCH_SNDBIT
)
673 do_input(alias
, id
->sndbit
, 0, INPUT_DEVICE_ID_SND_MAX
);
674 sprintf(alias
+ strlen(alias
), "f*");
675 if (id
->flags
& INPUT_DEVICE_ID_MATCH_FFBIT
)
676 do_input(alias
, id
->ffbit
, 0, INPUT_DEVICE_ID_FF_MAX
);
677 sprintf(alias
+ strlen(alias
), "w*");
678 if (id
->flags
& INPUT_DEVICE_ID_MATCH_SWBIT
)
679 do_input(alias
, id
->swbit
, 0, INPUT_DEVICE_ID_SW_MAX
);
682 ADD_TO_DEVTABLE("input", struct input_device_id
, do_input_entry
);
684 static int do_eisa_entry(const char *filename
, struct eisa_device_id
*eisa
,
688 sprintf(alias
, EISA_DEVICE_MODALIAS_FMT
"*", eisa
->sig
);
693 ADD_TO_DEVTABLE("eisa", struct eisa_device_id
, do_eisa_entry
);
695 /* Looks like: parisc:tNhvNrevNsvN */
696 static int do_parisc_entry(const char *filename
, struct parisc_device_id
*id
,
699 id
->hw_type
= TO_NATIVE(id
->hw_type
);
700 id
->hversion
= TO_NATIVE(id
->hversion
);
701 id
->hversion_rev
= TO_NATIVE(id
->hversion_rev
);
702 id
->sversion
= TO_NATIVE(id
->sversion
);
704 strcpy(alias
, "parisc:");
705 ADD(alias
, "t", id
->hw_type
!= PA_HWTYPE_ANY_ID
, id
->hw_type
);
706 ADD(alias
, "hv", id
->hversion
!= PA_HVERSION_ANY_ID
, id
->hversion
);
707 ADD(alias
, "rev", id
->hversion_rev
!= PA_HVERSION_REV_ANY_ID
, id
->hversion_rev
);
708 ADD(alias
, "sv", id
->sversion
!= PA_SVERSION_ANY_ID
, id
->sversion
);
713 ADD_TO_DEVTABLE("parisc", struct parisc_device_id
, do_parisc_entry
);
715 /* Looks like: sdio:cNvNdN. */
716 static int do_sdio_entry(const char *filename
,
717 struct sdio_device_id
*id
, char *alias
)
719 id
->class = TO_NATIVE(id
->class);
720 id
->vendor
= TO_NATIVE(id
->vendor
);
721 id
->device
= TO_NATIVE(id
->device
);
723 strcpy(alias
, "sdio:");
724 ADD(alias
, "c", id
->class != (__u8
)SDIO_ANY_ID
, id
->class);
725 ADD(alias
, "v", id
->vendor
!= (__u16
)SDIO_ANY_ID
, id
->vendor
);
726 ADD(alias
, "d", id
->device
!= (__u16
)SDIO_ANY_ID
, id
->device
);
730 ADD_TO_DEVTABLE("sdio", struct sdio_device_id
, do_sdio_entry
);
732 /* Looks like: ssb:vNidNrevN. */
733 static int do_ssb_entry(const char *filename
,
734 struct ssb_device_id
*id
, char *alias
)
736 id
->vendor
= TO_NATIVE(id
->vendor
);
737 id
->coreid
= TO_NATIVE(id
->coreid
);
738 id
->revision
= TO_NATIVE(id
->revision
);
740 strcpy(alias
, "ssb:");
741 ADD(alias
, "v", id
->vendor
!= SSB_ANY_VENDOR
, id
->vendor
);
742 ADD(alias
, "id", id
->coreid
!= SSB_ANY_ID
, id
->coreid
);
743 ADD(alias
, "rev", id
->revision
!= SSB_ANY_REV
, id
->revision
);
747 ADD_TO_DEVTABLE("ssb", struct ssb_device_id
, do_ssb_entry
);
749 /* Looks like: bcma:mNidNrevNclN. */
750 static int do_bcma_entry(const char *filename
,
751 struct bcma_device_id
*id
, char *alias
)
753 id
->manuf
= TO_NATIVE(id
->manuf
);
754 id
->id
= TO_NATIVE(id
->id
);
755 id
->rev
= TO_NATIVE(id
->rev
);
756 id
->class = TO_NATIVE(id
->class);
758 strcpy(alias
, "bcma:");
759 ADD(alias
, "m", id
->manuf
!= BCMA_ANY_MANUF
, id
->manuf
);
760 ADD(alias
, "id", id
->id
!= BCMA_ANY_ID
, id
->id
);
761 ADD(alias
, "rev", id
->rev
!= BCMA_ANY_REV
, id
->rev
);
762 ADD(alias
, "cl", id
->class != BCMA_ANY_CLASS
, id
->class);
766 ADD_TO_DEVTABLE("bcma", struct bcma_device_id
, do_bcma_entry
);
768 /* Looks like: virtio:dNvN */
769 static int do_virtio_entry(const char *filename
, struct virtio_device_id
*id
,
772 id
->device
= TO_NATIVE(id
->device
);
773 id
->vendor
= TO_NATIVE(id
->vendor
);
775 strcpy(alias
, "virtio:");
776 ADD(alias
, "d", id
->device
!= VIRTIO_DEV_ANY_ID
, id
->device
);
777 ADD(alias
, "v", id
->vendor
!= VIRTIO_DEV_ANY_ID
, id
->vendor
);
782 ADD_TO_DEVTABLE("virtio", struct virtio_device_id
, do_virtio_entry
);
785 * Looks like: vmbus:guid
786 * Each byte of the guid will be represented by two hex characters
790 static int do_vmbus_entry(const char *filename
, struct hv_vmbus_device_id
*id
,
794 char guid_name
[((sizeof(id
->guid
) + 1)) * 2];
796 for (i
= 0; i
< (sizeof(id
->guid
) * 2); i
+= 2)
797 sprintf(&guid_name
[i
], "%02x", id
->guid
[i
/2]);
799 strcpy(alias
, "vmbus:");
800 strcat(alias
, guid_name
);
804 ADD_TO_DEVTABLE("vmbus", struct hv_vmbus_device_id
, do_vmbus_entry
);
806 /* Looks like: i2c:S */
807 static int do_i2c_entry(const char *filename
, struct i2c_device_id
*id
,
810 sprintf(alias
, I2C_MODULE_PREFIX
"%s", id
->name
);
814 ADD_TO_DEVTABLE("i2c", struct i2c_device_id
, do_i2c_entry
);
816 /* Looks like: spi:S */
817 static int do_spi_entry(const char *filename
, struct spi_device_id
*id
,
820 sprintf(alias
, SPI_MODULE_PREFIX
"%s", id
->name
);
824 ADD_TO_DEVTABLE("spi", struct spi_device_id
, do_spi_entry
);
826 /* Looks like: mcp:S */
827 static int do_mcp_entry(const char *filename
, struct mcp_device_id
*id
,
830 sprintf(alias
, MCP_MODULE_PREFIX
"%s", id
->name
);
834 ADD_TO_DEVTABLE("mcp", struct mcp_device_id
, do_mcp_entry
);
836 static const struct dmifield
{
840 { "bvn", DMI_BIOS_VENDOR
},
841 { "bvr", DMI_BIOS_VERSION
},
842 { "bd", DMI_BIOS_DATE
},
843 { "svn", DMI_SYS_VENDOR
},
844 { "pn", DMI_PRODUCT_NAME
},
845 { "pvr", DMI_PRODUCT_VERSION
},
846 { "rvn", DMI_BOARD_VENDOR
},
847 { "rn", DMI_BOARD_NAME
},
848 { "rvr", DMI_BOARD_VERSION
},
849 { "cvn", DMI_CHASSIS_VENDOR
},
850 { "ct", DMI_CHASSIS_TYPE
},
851 { "cvr", DMI_CHASSIS_VERSION
},
855 static void dmi_ascii_filter(char *d
, const char *s
)
857 /* Filter out characters we don't want to see in the modalias string */
859 if (*s
> ' ' && *s
< 127 && *s
!= ':')
866 static int do_dmi_entry(const char *filename
, struct dmi_system_id
*id
,
871 sprintf(alias
, "dmi*");
873 for (i
= 0; i
< ARRAY_SIZE(dmi_fields
); i
++) {
874 for (j
= 0; j
< 4; j
++) {
875 if (id
->matches
[j
].slot
&&
876 id
->matches
[j
].slot
== dmi_fields
[i
].field
) {
877 sprintf(alias
+ strlen(alias
), ":%s*",
878 dmi_fields
[i
].prefix
);
879 dmi_ascii_filter(alias
+ strlen(alias
),
880 id
->matches
[j
].substr
);
889 ADD_TO_DEVTABLE("dmi", struct dmi_system_id
, do_dmi_entry
);
891 static int do_platform_entry(const char *filename
,
892 struct platform_device_id
*id
, char *alias
)
894 sprintf(alias
, PLATFORM_MODULE_PREFIX
"%s", id
->name
);
897 ADD_TO_DEVTABLE("platform", struct platform_device_id
, do_platform_entry
);
899 static int do_mdio_entry(const char *filename
,
900 struct mdio_device_id
*id
, char *alias
)
904 alias
+= sprintf(alias
, MDIO_MODULE_PREFIX
);
906 for (i
= 0; i
< 32; i
++) {
907 if (!((id
->phy_id_mask
>> (31-i
)) & 1))
909 else if ((id
->phy_id
>> (31-i
)) & 1)
915 /* Terminate the string */
920 ADD_TO_DEVTABLE("mdio", struct mdio_device_id
, do_mdio_entry
);
922 /* Looks like: zorro:iN. */
923 static int do_zorro_entry(const char *filename
, struct zorro_device_id
*id
,
926 id
->id
= TO_NATIVE(id
->id
);
927 strcpy(alias
, "zorro:");
928 ADD(alias
, "i", id
->id
!= ZORRO_WILDCARD
, id
->id
);
931 ADD_TO_DEVTABLE("zorro", struct zorro_device_id
, do_zorro_entry
);
933 /* looks like: "pnp:dD" */
934 static int do_isapnp_entry(const char *filename
,
935 struct isapnp_device_id
*id
, char *alias
)
937 sprintf(alias
, "pnp:d%c%c%c%x%x%x%x*",
938 'A' + ((id
->vendor
>> 2) & 0x3f) - 1,
939 'A' + (((id
->vendor
& 3) << 3) | ((id
->vendor
>> 13) & 7)) - 1,
940 'A' + ((id
->vendor
>> 8) & 0x1f) - 1,
941 (id
->function
>> 4) & 0x0f, id
->function
& 0x0f,
942 (id
->function
>> 12) & 0x0f, (id
->function
>> 8) & 0x0f);
945 ADD_TO_DEVTABLE("isa", struct isapnp_device_id
, do_isapnp_entry
);
948 * Append a match expression for a single masked hex digit.
949 * outp points to a pointer to the character at which to append.
950 * *outp is updated on return to point just after the appended text,
951 * to facilitate further appending.
953 static void append_nibble_mask(char **outp
,
954 unsigned int nibble
, unsigned int mask
)
965 p
+= sprintf(p
, "%X", nibble
);
970 * Dumbly emit a match pattern for all possible matching
971 * digits. This could be improved in some cases using ranges,
972 * but it has the advantage of being trivially correct, and is
976 for (i
= 0; i
< 0x10; i
++)
977 if ((i
& mask
) == nibble
)
978 p
+= sprintf(p
, "%X", i
);
982 /* Ensure that the string remains NUL-terminated: */
985 /* Advance the caller's end-of-string pointer: */
990 * looks like: "amba:dN"
992 * N is exactly 8 digits, where each is an upper-case hex digit, or
993 * a ? or [] pattern matching exactly one digit.
995 static int do_amba_entry(const char *filename
,
996 struct amba_id
*id
, char *alias
)
1001 if ((id
->id
& id
->mask
) != id
->id
)
1002 fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: "
1003 "id=0x%08X, mask=0x%08X. Please fix this driver.\n",
1004 filename
, id
->id
, id
->mask
);
1006 p
+= sprintf(alias
, "amba:d");
1007 for (digit
= 0; digit
< 8; digit
++)
1008 append_nibble_mask(&p
,
1009 (id
->id
>> (4 * (7 - digit
))) & 0xf,
1010 (id
->mask
>> (4 * (7 - digit
))) & 0xf);
1014 ADD_TO_DEVTABLE("amba", struct amba_id
, do_amba_entry
);
1016 /* Does namelen bytes of name exactly match the symbol? */
1017 static bool sym_is(const char *name
, unsigned namelen
, const char *symbol
)
1019 if (namelen
!= strlen(symbol
))
1022 return memcmp(name
, symbol
, namelen
) == 0;
1025 static void do_table(void *symval
, unsigned long size
,
1026 unsigned long id_size
,
1027 const char *device_id
,
1033 int (*do_entry
)(const char *, void *entry
, char *alias
) = function
;
1035 device_id_check(mod
->name
, device_id
, size
, id_size
, symval
);
1036 /* Leave last one: it's the terminator. */
1039 for (i
= 0; i
< size
; i
+= id_size
) {
1040 if (do_entry(mod
->name
, symval
+i
, alias
)) {
1041 buf_printf(&mod
->dev_table_buf
,
1042 "MODULE_ALIAS(\"%s\");\n", alias
);
1047 /* Create MODULE_ALIAS() statements.
1048 * At this time, we cannot write the actual output C source yet,
1049 * so we write into the mod->dev_table_buf buffer. */
1050 void handle_moddevtable(struct module
*mod
, struct elf_info
*info
,
1051 Elf_Sym
*sym
, const char *symname
)
1056 unsigned int namelen
;
1058 /* We're looking for a section relative symbol */
1059 if (!sym
->st_shndx
|| get_secindex(info
, sym
) >= info
->num_sections
)
1062 /* All our symbols are of form <prefix>__mod_XXX_device_table. */
1063 name
= strstr(symname
, "__mod_");
1066 name
+= strlen("__mod_");
1067 namelen
= strlen(name
);
1068 if (namelen
< strlen("_device_table"))
1070 if (strcmp(name
+ namelen
- strlen("_device_table"), "_device_table"))
1072 namelen
-= strlen("_device_table");
1074 /* Handle all-NULL symbols allocated into .bss */
1075 if (info
->sechdrs
[get_secindex(info
, sym
)].sh_type
& SHT_NOBITS
) {
1076 zeros
= calloc(1, sym
->st_size
);
1079 symval
= (void *)info
->hdr
1080 + info
->sechdrs
[get_secindex(info
, sym
)].sh_offset
1084 /* First handle the "special" cases */
1085 if (sym_is(name
, namelen
, "usb"))
1086 do_usb_table(symval
, sym
->st_size
, mod
);
1087 else if (sym_is(name
, namelen
, "pnp"))
1088 do_pnp_device_entry(symval
, sym
->st_size
, mod
);
1089 else if (sym_is(name
, namelen
, "pnp_card"))
1090 do_pnp_card_entries(symval
, sym
->st_size
, mod
);
1092 struct devtable
**p
;
1094 for (p
= __start___devtable
; p
< __stop___devtable
; p
++) {
1095 if (sym_is(name
, namelen
, (*p
)->device_id
)) {
1096 do_table(symval
, sym
->st_size
, (*p
)->id_size
,
1097 (*p
)->device_id
, (*p
)->function
, mod
);
1105 /* Now add out buffered information to the generated C source */
1106 void add_moddevtable(struct buffer
*buf
, struct module
*mod
)
1108 buf_printf(buf
, "\n");
1109 buf_write(buf
, mod
->dev_table_buf
.p
, mod
->dev_table_buf
.pos
);
1110 free(mod
->dev_table_buf
.p
);