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 #define ___cat(a,b) a ## b
50 #define __cat(a,b) ___cat(a,b)
52 /* we need some special handling for this host tool running eventually on
53 * Darwin. The Mach-O section handling is a bit different than ELF section
54 * handling. The differnces in detail are:
55 * a) we have segments which have sections
56 * b) we need a API call to get the respective section symbols */
58 #include <mach-o/getsect.h>
60 #define INIT_SECTION(name) do { \
61 unsigned long name ## _len; \
62 char *__cat(pstart_,name) = getsectdata("__TEXT", \
63 #name, &__cat(name,_len)); \
64 char *__cat(pstop_,name) = __cat(pstart_,name) + \
66 __cat(__start_,name) = (void *)__cat(pstart_,name); \
67 __cat(__stop_,name) = (void *)__cat(pstop_,name); \
69 #define SECTION(name) __attribute__((section("__TEXT, " #name)))
71 struct devtable
**__start___devtable
, **__stop___devtable
;
73 #define INIT_SECTION(name) /* no-op for ELF */
74 #define SECTION(name) __attribute__((section(#name)))
76 /* We construct a table of pointers in an ELF section (pointers generally
77 * go unpadded by gcc). ld creates boundary syms for us. */
78 extern struct devtable
*__start___devtable
[], *__stop___devtable
[];
81 #if __GNUC__ == 3 && __GNUC_MINOR__ < 3
82 # define __used __attribute__((__unused__))
84 # define __used __attribute__((__used__))
87 /* Add a table entry. We test function type matches while we're here. */
88 #define ADD_TO_DEVTABLE(device_id, type, function) \
89 static struct devtable __cat(devtable,__LINE__) = { \
90 device_id + 0*sizeof((function)((const char *)NULL, \
93 sizeof(type), (function) }; \
94 static struct devtable *SECTION(__devtable) __used \
95 __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__)
97 #define ADD(str, sep, cond, field) \
101 sprintf(str + strlen(str), \
102 sizeof(field) == 1 ? "%02X" : \
103 sizeof(field) == 2 ? "%04X" : \
104 sizeof(field) == 4 ? "%08X" : "", \
107 sprintf(str + strlen(str), "*"); \
110 /* Always end in a wildcard, for future extension */
111 static inline void add_wildcard(char *str
)
113 int len
= strlen(str
);
115 if (str
[len
- 1] != '*')
116 strcat(str
+ len
, "*");
119 unsigned int cross_build
= 0;
121 * Check that sizeof(device_id type) are consistent with size of section
122 * in .o file. If in-consistent then userspace and kernel does not agree
123 * on actual size which is a bug.
124 * Also verify that the final entry in the table is all zeros.
125 * Ignore both checks if build host differ from target host and size differs.
127 static void device_id_check(const char *modname
, const char *device_id
,
128 unsigned long size
, unsigned long id_size
,
133 if (size
% id_size
|| size
< id_size
) {
134 if (cross_build
!= 0)
136 fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
137 "of the size of section __mod_%s_device_table=%lu.\n"
138 "Fix definition of struct %s_device_id "
139 "in mod_devicetable.h\n",
140 modname
, device_id
, id_size
, device_id
, size
, device_id
);
142 /* Verify last one is a terminator */
143 for (i
= 0; i
< id_size
; i
++ ) {
144 if (*(uint8_t*)(symval
+size
-id_size
+i
)) {
145 fprintf(stderr
,"%s: struct %s_device_id is %lu bytes. "
146 "The last of %lu is:\n",
147 modname
, device_id
, id_size
, size
/ id_size
);
148 for (i
= 0; i
< id_size
; i
++ )
149 fprintf(stderr
,"0x%02x ",
150 *(uint8_t*)(symval
+size
-id_size
+i
) );
151 fprintf(stderr
,"\n");
152 fatal("%s: struct %s_device_id is not terminated "
153 "with a NULL entry!\n", modname
, device_id
);
158 /* USB is special because the bcdDevice can be matched against a numeric range */
159 /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
160 static void do_usb_entry(struct usb_device_id
*id
,
161 unsigned int bcdDevice_initial
, int bcdDevice_initial_digits
,
162 unsigned char range_lo
, unsigned char range_hi
,
163 unsigned char max
, struct module
*mod
)
166 strcpy(alias
, "usb:");
167 ADD(alias
, "v", id
->match_flags
&USB_DEVICE_ID_MATCH_VENDOR
,
169 ADD(alias
, "p", id
->match_flags
&USB_DEVICE_ID_MATCH_PRODUCT
,
173 if (bcdDevice_initial_digits
)
174 sprintf(alias
+ strlen(alias
), "%0*X",
175 bcdDevice_initial_digits
, bcdDevice_initial
);
176 if (range_lo
== range_hi
)
177 sprintf(alias
+ strlen(alias
), "%X", range_lo
);
178 else if (range_lo
> 0 || range_hi
< max
) {
179 if (range_lo
> 0x9 || range_hi
< 0xA)
180 sprintf(alias
+ strlen(alias
),
185 sprintf(alias
+ strlen(alias
),
186 range_lo
< 0x9 ? "[%X-9" : "[%X",
188 sprintf(alias
+ strlen(alias
),
189 range_hi
> 0xA ? "a-%X]" : "%X]",
193 if (bcdDevice_initial_digits
< (sizeof(id
->bcdDevice_lo
) * 2 - 1))
196 ADD(alias
, "dc", id
->match_flags
&USB_DEVICE_ID_MATCH_DEV_CLASS
,
199 id
->match_flags
&USB_DEVICE_ID_MATCH_DEV_SUBCLASS
,
200 id
->bDeviceSubClass
);
202 id
->match_flags
&USB_DEVICE_ID_MATCH_DEV_PROTOCOL
,
203 id
->bDeviceProtocol
);
205 id
->match_flags
&USB_DEVICE_ID_MATCH_INT_CLASS
,
206 id
->bInterfaceClass
);
208 id
->match_flags
&USB_DEVICE_ID_MATCH_INT_SUBCLASS
,
209 id
->bInterfaceSubClass
);
211 id
->match_flags
&USB_DEVICE_ID_MATCH_INT_PROTOCOL
,
212 id
->bInterfaceProtocol
);
215 buf_printf(&mod
->dev_table_buf
,
216 "MODULE_ALIAS(\"%s\");\n", alias
);
219 /* Handles increment/decrement of BCD formatted integers */
220 /* Returns the previous value, so it works like i++ or i-- */
221 static unsigned int incbcd(unsigned int *bcd
,
226 unsigned int init
= *bcd
, i
, j
;
227 unsigned long long c
, dec
= 0;
229 /* If bcd is not in BCD format, just increment */
235 /* Convert BCD to Decimal */
236 for (i
=0 ; i
< chars
; i
++) {
237 c
= (*bcd
>> (i
<< 2)) & 0xf;
238 c
= c
> 9 ? 9 : c
; /* force to bcd just in case */
239 for (j
=0 ; j
< i
; j
++)
244 /* Do our increment/decrement */
248 /* Convert back to BCD */
249 for (i
=0 ; i
< chars
; i
++) {
250 for (c
=1,j
=0 ; j
< i
; j
++)
253 *bcd
+= c
<< (i
<< 2);
258 static void do_usb_entry_multi(struct usb_device_id
*id
, struct module
*mod
)
260 unsigned int devlo
, devhi
;
261 unsigned char chi
, clo
, max
;
264 id
->match_flags
= TO_NATIVE(id
->match_flags
);
265 id
->idVendor
= TO_NATIVE(id
->idVendor
);
266 id
->idProduct
= TO_NATIVE(id
->idProduct
);
268 devlo
= id
->match_flags
& USB_DEVICE_ID_MATCH_DEV_LO
?
269 TO_NATIVE(id
->bcdDevice_lo
) : 0x0U
;
270 devhi
= id
->match_flags
& USB_DEVICE_ID_MATCH_DEV_HI
?
271 TO_NATIVE(id
->bcdDevice_hi
) : ~0x0U
;
273 /* Figure out if this entry is in bcd or hex format */
274 max
= 0x9; /* Default to decimal format */
275 for (ndigits
= 0 ; ndigits
< sizeof(id
->bcdDevice_lo
) * 2 ; ndigits
++) {
276 clo
= (devlo
>> (ndigits
<< 2)) & 0xf;
277 chi
= ((devhi
> 0x9999 ? 0x9999 : devhi
) >> (ndigits
<< 2)) & 0xf;
278 if (clo
> max
|| chi
> max
) {
285 * Some modules (visor) have empty slots as placeholder for
286 * run-time specification that results in catch-all alias
288 if (!(id
->idVendor
| id
->idProduct
| id
->bDeviceClass
| id
->bInterfaceClass
))
291 /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
292 for (ndigits
= sizeof(id
->bcdDevice_lo
) * 2 - 1; devlo
<= devhi
; ndigits
--) {
295 if (chi
> max
) /* If we are in bcd mode, truncate if necessary */
300 if (devlo
== devhi
|| !ndigits
) {
301 do_usb_entry(id
, devlo
, ndigits
, clo
, chi
, max
, mod
);
307 incbcd(&devlo
, 1, max
,
308 sizeof(id
->bcdDevice_lo
) * 2),
309 ndigits
, clo
, max
, max
, mod
);
313 incbcd(&devhi
, -1, max
,
314 sizeof(id
->bcdDevice_lo
) * 2),
315 ndigits
, 0x0, chi
, max
, mod
);
319 static void do_usb_table(void *symval
, unsigned long size
,
323 const unsigned long id_size
= sizeof(struct usb_device_id
);
325 device_id_check(mod
->name
, "usb", size
, id_size
, symval
);
327 /* Leave last one: it's the terminator. */
330 for (i
= 0; i
< size
; i
+= id_size
)
331 do_usb_entry_multi(symval
+ i
, mod
);
334 /* Looks like: hid:bNvNpN */
335 static int do_hid_entry(const char *filename
,
336 struct hid_device_id
*id
, char *alias
)
338 id
->bus
= TO_NATIVE(id
->bus
);
339 id
->vendor
= TO_NATIVE(id
->vendor
);
340 id
->product
= TO_NATIVE(id
->product
);
342 sprintf(alias
, "hid:b%04X", id
->bus
);
343 ADD(alias
, "v", id
->vendor
!= HID_ANY_ID
, id
->vendor
);
344 ADD(alias
, "p", id
->product
!= HID_ANY_ID
, id
->product
);
348 ADD_TO_DEVTABLE("hid", struct hid_device_id
, do_hid_entry
);
350 /* Looks like: ieee1394:venNmoNspNverN */
351 static int do_ieee1394_entry(const char *filename
,
352 struct ieee1394_device_id
*id
, char *alias
)
354 id
->match_flags
= TO_NATIVE(id
->match_flags
);
355 id
->vendor_id
= TO_NATIVE(id
->vendor_id
);
356 id
->model_id
= TO_NATIVE(id
->model_id
);
357 id
->specifier_id
= TO_NATIVE(id
->specifier_id
);
358 id
->version
= TO_NATIVE(id
->version
);
360 strcpy(alias
, "ieee1394:");
361 ADD(alias
, "ven", id
->match_flags
& IEEE1394_MATCH_VENDOR_ID
,
363 ADD(alias
, "mo", id
->match_flags
& IEEE1394_MATCH_MODEL_ID
,
365 ADD(alias
, "sp", id
->match_flags
& IEEE1394_MATCH_SPECIFIER_ID
,
367 ADD(alias
, "ver", id
->match_flags
& IEEE1394_MATCH_VERSION
,
373 ADD_TO_DEVTABLE("ieee1394", struct ieee1394_device_id
, do_ieee1394_entry
);
375 /* Looks like: pci:vNdNsvNsdNbcNscNiN. */
376 static int do_pci_entry(const char *filename
,
377 struct pci_device_id
*id
, char *alias
)
379 /* Class field can be divided into these three. */
380 unsigned char baseclass
, subclass
, interface
,
381 baseclass_mask
, subclass_mask
, interface_mask
;
383 id
->vendor
= TO_NATIVE(id
->vendor
);
384 id
->device
= TO_NATIVE(id
->device
);
385 id
->subvendor
= TO_NATIVE(id
->subvendor
);
386 id
->subdevice
= TO_NATIVE(id
->subdevice
);
387 id
->class = TO_NATIVE(id
->class);
388 id
->class_mask
= TO_NATIVE(id
->class_mask
);
390 strcpy(alias
, "pci:");
391 ADD(alias
, "v", id
->vendor
!= PCI_ANY_ID
, id
->vendor
);
392 ADD(alias
, "d", id
->device
!= PCI_ANY_ID
, id
->device
);
393 ADD(alias
, "sv", id
->subvendor
!= PCI_ANY_ID
, id
->subvendor
);
394 ADD(alias
, "sd", id
->subdevice
!= PCI_ANY_ID
, id
->subdevice
);
396 baseclass
= (id
->class) >> 16;
397 baseclass_mask
= (id
->class_mask
) >> 16;
398 subclass
= (id
->class) >> 8;
399 subclass_mask
= (id
->class_mask
) >> 8;
400 interface
= id
->class;
401 interface_mask
= id
->class_mask
;
403 if ((baseclass_mask
!= 0 && baseclass_mask
!= 0xFF)
404 || (subclass_mask
!= 0 && subclass_mask
!= 0xFF)
405 || (interface_mask
!= 0 && interface_mask
!= 0xFF)) {
406 warn("Can't handle masks in %s:%04X\n",
407 filename
, id
->class_mask
);
411 ADD(alias
, "bc", baseclass_mask
== 0xFF, baseclass
);
412 ADD(alias
, "sc", subclass_mask
== 0xFF, subclass
);
413 ADD(alias
, "i", interface_mask
== 0xFF, interface
);
417 ADD_TO_DEVTABLE("pci", struct pci_device_id
, do_pci_entry
);
419 /* looks like: "ccw:tNmNdtNdmN" */
420 static int do_ccw_entry(const char *filename
,
421 struct ccw_device_id
*id
, char *alias
)
423 id
->match_flags
= TO_NATIVE(id
->match_flags
);
424 id
->cu_type
= TO_NATIVE(id
->cu_type
);
425 id
->cu_model
= TO_NATIVE(id
->cu_model
);
426 id
->dev_type
= TO_NATIVE(id
->dev_type
);
427 id
->dev_model
= TO_NATIVE(id
->dev_model
);
429 strcpy(alias
, "ccw:");
430 ADD(alias
, "t", id
->match_flags
&CCW_DEVICE_ID_MATCH_CU_TYPE
,
432 ADD(alias
, "m", id
->match_flags
&CCW_DEVICE_ID_MATCH_CU_MODEL
,
434 ADD(alias
, "dt", id
->match_flags
&CCW_DEVICE_ID_MATCH_DEVICE_TYPE
,
436 ADD(alias
, "dm", id
->match_flags
&CCW_DEVICE_ID_MATCH_DEVICE_MODEL
,
441 ADD_TO_DEVTABLE("ccw", struct ccw_device_id
, do_ccw_entry
);
443 /* looks like: "ap:tN" */
444 static int do_ap_entry(const char *filename
,
445 struct ap_device_id
*id
, char *alias
)
447 sprintf(alias
, "ap:t%02X*", id
->dev_type
);
450 ADD_TO_DEVTABLE("ap", struct ap_device_id
, do_ap_entry
);
452 /* looks like: "css:tN" */
453 static int do_css_entry(const char *filename
,
454 struct css_device_id
*id
, char *alias
)
456 sprintf(alias
, "css:t%01X", id
->type
);
459 ADD_TO_DEVTABLE("css", struct css_device_id
, do_css_entry
);
461 /* Looks like: "serio:tyNprNidNexN" */
462 static int do_serio_entry(const char *filename
,
463 struct serio_device_id
*id
, char *alias
)
465 id
->type
= TO_NATIVE(id
->type
);
466 id
->proto
= TO_NATIVE(id
->proto
);
467 id
->id
= TO_NATIVE(id
->id
);
468 id
->extra
= TO_NATIVE(id
->extra
);
470 strcpy(alias
, "serio:");
471 ADD(alias
, "ty", id
->type
!= SERIO_ANY
, id
->type
);
472 ADD(alias
, "pr", id
->proto
!= SERIO_ANY
, id
->proto
);
473 ADD(alias
, "id", id
->id
!= SERIO_ANY
, id
->id
);
474 ADD(alias
, "ex", id
->extra
!= SERIO_ANY
, id
->extra
);
479 ADD_TO_DEVTABLE("serio", struct serio_device_id
, do_serio_entry
);
481 /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */
482 static int do_acpi_entry(const char *filename
,
483 struct acpi_device_id
*id
, char *alias
)
485 sprintf(alias
, "acpi*:%s:*", id
->id
);
488 ADD_TO_DEVTABLE("acpi", struct acpi_device_id
, do_acpi_entry
);
490 /* looks like: "pnp:dD" */
491 static void do_pnp_device_entry(void *symval
, unsigned long size
,
494 const unsigned long id_size
= sizeof(struct pnp_device_id
);
495 const unsigned int count
= (size
/ id_size
)-1;
496 const struct pnp_device_id
*devs
= symval
;
499 device_id_check(mod
->name
, "pnp", size
, id_size
, symval
);
501 for (i
= 0; i
< count
; i
++) {
502 const char *id
= (char *)devs
[i
].id
;
503 char acpi_id
[sizeof(devs
[0].id
)];
506 buf_printf(&mod
->dev_table_buf
,
507 "MODULE_ALIAS(\"pnp:d%s*\");\n", id
);
509 /* fix broken pnp bus lowercasing */
510 for (j
= 0; j
< sizeof(acpi_id
); j
++)
511 acpi_id
[j
] = toupper(id
[j
]);
512 buf_printf(&mod
->dev_table_buf
,
513 "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id
);
517 /* looks like: "pnp:dD" for every device of the card */
518 static void do_pnp_card_entries(void *symval
, unsigned long size
,
521 const unsigned long id_size
= sizeof(struct pnp_card_device_id
);
522 const unsigned int count
= (size
/ id_size
)-1;
523 const struct pnp_card_device_id
*cards
= symval
;
526 device_id_check(mod
->name
, "pnp", size
, id_size
, symval
);
528 for (i
= 0; i
< count
; i
++) {
530 const struct pnp_card_device_id
*card
= &cards
[i
];
532 for (j
= 0; j
< PNP_MAX_DEVICES
; j
++) {
533 const char *id
= (char *)card
->devs
[j
].id
;
540 /* find duplicate, already added value */
541 for (i2
= 0; i2
< i
&& !dup
; i2
++) {
542 const struct pnp_card_device_id
*card2
= &cards
[i2
];
544 for (j2
= 0; j2
< PNP_MAX_DEVICES
; j2
++) {
545 const char *id2
= (char *)card2
->devs
[j2
].id
;
550 if (!strcmp(id
, id2
)) {
557 /* add an individual alias for every device entry */
559 char acpi_id
[sizeof(card
->devs
[0].id
)];
562 buf_printf(&mod
->dev_table_buf
,
563 "MODULE_ALIAS(\"pnp:d%s*\");\n", id
);
565 /* fix broken pnp bus lowercasing */
566 for (k
= 0; k
< sizeof(acpi_id
); k
++)
567 acpi_id
[k
] = toupper(id
[k
]);
568 buf_printf(&mod
->dev_table_buf
,
569 "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id
);
575 /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
576 static int do_pcmcia_entry(const char *filename
,
577 struct pcmcia_device_id
*id
, char *alias
)
581 id
->match_flags
= TO_NATIVE(id
->match_flags
);
582 id
->manf_id
= TO_NATIVE(id
->manf_id
);
583 id
->card_id
= TO_NATIVE(id
->card_id
);
584 id
->func_id
= TO_NATIVE(id
->func_id
);
585 id
->function
= TO_NATIVE(id
->function
);
586 id
->device_no
= TO_NATIVE(id
->device_no
);
588 for (i
=0; i
<4; i
++) {
589 id
->prod_id_hash
[i
] = TO_NATIVE(id
->prod_id_hash
[i
]);
592 strcpy(alias
, "pcmcia:");
593 ADD(alias
, "m", id
->match_flags
& PCMCIA_DEV_ID_MATCH_MANF_ID
,
595 ADD(alias
, "c", id
->match_flags
& PCMCIA_DEV_ID_MATCH_CARD_ID
,
597 ADD(alias
, "f", id
->match_flags
& PCMCIA_DEV_ID_MATCH_FUNC_ID
,
599 ADD(alias
, "fn", id
->match_flags
& PCMCIA_DEV_ID_MATCH_FUNCTION
,
601 ADD(alias
, "pfn", id
->match_flags
& PCMCIA_DEV_ID_MATCH_DEVICE_NO
,
603 ADD(alias
, "pa", id
->match_flags
& PCMCIA_DEV_ID_MATCH_PROD_ID1
, id
->prod_id_hash
[0]);
604 ADD(alias
, "pb", id
->match_flags
& PCMCIA_DEV_ID_MATCH_PROD_ID2
, id
->prod_id_hash
[1]);
605 ADD(alias
, "pc", id
->match_flags
& PCMCIA_DEV_ID_MATCH_PROD_ID3
, id
->prod_id_hash
[2]);
606 ADD(alias
, "pd", id
->match_flags
& PCMCIA_DEV_ID_MATCH_PROD_ID4
, id
->prod_id_hash
[3]);
611 ADD_TO_DEVTABLE("pcmcia", struct pcmcia_device_id
, do_pcmcia_entry
);
613 static int do_of_entry (const char *filename
, struct of_device_id
*of
, char *alias
)
617 len
= sprintf (alias
, "of:N%sT%s",
618 of
->name
[0] ? of
->name
: "*",
619 of
->type
[0] ? of
->type
: "*");
621 if (of
->compatible
[0])
622 sprintf (&alias
[len
], "%sC%s",
623 of
->type
[0] ? "*" : "",
626 /* Replace all whitespace with underscores */
627 for (tmp
= alias
; tmp
&& *tmp
; tmp
++)
634 ADD_TO_DEVTABLE("of", struct of_device_id
, do_of_entry
);
636 static int do_vio_entry(const char *filename
, struct vio_device_id
*vio
,
641 sprintf(alias
, "vio:T%sS%s", vio
->type
[0] ? vio
->type
: "*",
642 vio
->compat
[0] ? vio
->compat
: "*");
644 /* Replace all whitespace with underscores */
645 for (tmp
= alias
; tmp
&& *tmp
; tmp
++)
652 ADD_TO_DEVTABLE("vio", struct vio_device_id
, do_vio_entry
);
654 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
656 static void do_input(char *alias
,
657 kernel_ulong_t
*arr
, unsigned int min
, unsigned int max
)
661 for (i
= min
; i
< max
; i
++)
662 if (arr
[i
/ BITS_PER_LONG
] & (1L << (i
%BITS_PER_LONG
)))
663 sprintf(alias
+ strlen(alias
), "%X,*", i
);
666 /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
667 static int do_input_entry(const char *filename
, struct input_device_id
*id
,
670 sprintf(alias
, "input:");
672 ADD(alias
, "b", id
->flags
& INPUT_DEVICE_ID_MATCH_BUS
, id
->bustype
);
673 ADD(alias
, "v", id
->flags
& INPUT_DEVICE_ID_MATCH_VENDOR
, id
->vendor
);
674 ADD(alias
, "p", id
->flags
& INPUT_DEVICE_ID_MATCH_PRODUCT
, id
->product
);
675 ADD(alias
, "e", id
->flags
& INPUT_DEVICE_ID_MATCH_VERSION
, id
->version
);
677 sprintf(alias
+ strlen(alias
), "-e*");
678 if (id
->flags
& INPUT_DEVICE_ID_MATCH_EVBIT
)
679 do_input(alias
, id
->evbit
, 0, INPUT_DEVICE_ID_EV_MAX
);
680 sprintf(alias
+ strlen(alias
), "k*");
681 if (id
->flags
& INPUT_DEVICE_ID_MATCH_KEYBIT
)
682 do_input(alias
, id
->keybit
,
683 INPUT_DEVICE_ID_KEY_MIN_INTERESTING
,
684 INPUT_DEVICE_ID_KEY_MAX
);
685 sprintf(alias
+ strlen(alias
), "r*");
686 if (id
->flags
& INPUT_DEVICE_ID_MATCH_RELBIT
)
687 do_input(alias
, id
->relbit
, 0, INPUT_DEVICE_ID_REL_MAX
);
688 sprintf(alias
+ strlen(alias
), "a*");
689 if (id
->flags
& INPUT_DEVICE_ID_MATCH_ABSBIT
)
690 do_input(alias
, id
->absbit
, 0, INPUT_DEVICE_ID_ABS_MAX
);
691 sprintf(alias
+ strlen(alias
), "m*");
692 if (id
->flags
& INPUT_DEVICE_ID_MATCH_MSCIT
)
693 do_input(alias
, id
->mscbit
, 0, INPUT_DEVICE_ID_MSC_MAX
);
694 sprintf(alias
+ strlen(alias
), "l*");
695 if (id
->flags
& INPUT_DEVICE_ID_MATCH_LEDBIT
)
696 do_input(alias
, id
->ledbit
, 0, INPUT_DEVICE_ID_LED_MAX
);
697 sprintf(alias
+ strlen(alias
), "s*");
698 if (id
->flags
& INPUT_DEVICE_ID_MATCH_SNDBIT
)
699 do_input(alias
, id
->sndbit
, 0, INPUT_DEVICE_ID_SND_MAX
);
700 sprintf(alias
+ strlen(alias
), "f*");
701 if (id
->flags
& INPUT_DEVICE_ID_MATCH_FFBIT
)
702 do_input(alias
, id
->ffbit
, 0, INPUT_DEVICE_ID_FF_MAX
);
703 sprintf(alias
+ strlen(alias
), "w*");
704 if (id
->flags
& INPUT_DEVICE_ID_MATCH_SWBIT
)
705 do_input(alias
, id
->swbit
, 0, INPUT_DEVICE_ID_SW_MAX
);
708 ADD_TO_DEVTABLE("input", struct input_device_id
, do_input_entry
);
710 static int do_eisa_entry(const char *filename
, struct eisa_device_id
*eisa
,
714 sprintf(alias
, EISA_DEVICE_MODALIAS_FMT
"*", eisa
->sig
);
719 ADD_TO_DEVTABLE("eisa", struct eisa_device_id
, do_eisa_entry
);
721 /* Looks like: parisc:tNhvNrevNsvN */
722 static int do_parisc_entry(const char *filename
, struct parisc_device_id
*id
,
725 id
->hw_type
= TO_NATIVE(id
->hw_type
);
726 id
->hversion
= TO_NATIVE(id
->hversion
);
727 id
->hversion_rev
= TO_NATIVE(id
->hversion_rev
);
728 id
->sversion
= TO_NATIVE(id
->sversion
);
730 strcpy(alias
, "parisc:");
731 ADD(alias
, "t", id
->hw_type
!= PA_HWTYPE_ANY_ID
, id
->hw_type
);
732 ADD(alias
, "hv", id
->hversion
!= PA_HVERSION_ANY_ID
, id
->hversion
);
733 ADD(alias
, "rev", id
->hversion_rev
!= PA_HVERSION_REV_ANY_ID
, id
->hversion_rev
);
734 ADD(alias
, "sv", id
->sversion
!= PA_SVERSION_ANY_ID
, id
->sversion
);
739 ADD_TO_DEVTABLE("parisc", struct parisc_device_id
, do_parisc_entry
);
741 /* Looks like: sdio:cNvNdN. */
742 static int do_sdio_entry(const char *filename
,
743 struct sdio_device_id
*id
, char *alias
)
745 id
->class = TO_NATIVE(id
->class);
746 id
->vendor
= TO_NATIVE(id
->vendor
);
747 id
->device
= TO_NATIVE(id
->device
);
749 strcpy(alias
, "sdio:");
750 ADD(alias
, "c", id
->class != (__u8
)SDIO_ANY_ID
, id
->class);
751 ADD(alias
, "v", id
->vendor
!= (__u16
)SDIO_ANY_ID
, id
->vendor
);
752 ADD(alias
, "d", id
->device
!= (__u16
)SDIO_ANY_ID
, id
->device
);
756 ADD_TO_DEVTABLE("sdio", struct sdio_device_id
, do_sdio_entry
);
758 /* Looks like: ssb:vNidNrevN. */
759 static int do_ssb_entry(const char *filename
,
760 struct ssb_device_id
*id
, char *alias
)
762 id
->vendor
= TO_NATIVE(id
->vendor
);
763 id
->coreid
= TO_NATIVE(id
->coreid
);
764 id
->revision
= TO_NATIVE(id
->revision
);
766 strcpy(alias
, "ssb:");
767 ADD(alias
, "v", id
->vendor
!= SSB_ANY_VENDOR
, id
->vendor
);
768 ADD(alias
, "id", id
->coreid
!= SSB_ANY_ID
, id
->coreid
);
769 ADD(alias
, "rev", id
->revision
!= SSB_ANY_REV
, id
->revision
);
773 ADD_TO_DEVTABLE("ssb", struct ssb_device_id
, do_ssb_entry
);
775 /* Looks like: bcma:mNidNrevNclN. */
776 static int do_bcma_entry(const char *filename
,
777 struct bcma_device_id
*id
, char *alias
)
779 id
->manuf
= TO_NATIVE(id
->manuf
);
780 id
->id
= TO_NATIVE(id
->id
);
781 id
->rev
= TO_NATIVE(id
->rev
);
782 id
->class = TO_NATIVE(id
->class);
784 strcpy(alias
, "bcma:");
785 ADD(alias
, "m", id
->manuf
!= BCMA_ANY_MANUF
, id
->manuf
);
786 ADD(alias
, "id", id
->id
!= BCMA_ANY_ID
, id
->id
);
787 ADD(alias
, "rev", id
->rev
!= BCMA_ANY_REV
, id
->rev
);
788 ADD(alias
, "cl", id
->class != BCMA_ANY_CLASS
, id
->class);
792 ADD_TO_DEVTABLE("bcma", struct bcma_device_id
, do_bcma_entry
);
794 /* Looks like: virtio:dNvN */
795 static int do_virtio_entry(const char *filename
, struct virtio_device_id
*id
,
798 id
->device
= TO_NATIVE(id
->device
);
799 id
->vendor
= TO_NATIVE(id
->vendor
);
801 strcpy(alias
, "virtio:");
802 ADD(alias
, "d", id
->device
!= VIRTIO_DEV_ANY_ID
, id
->device
);
803 ADD(alias
, "v", id
->vendor
!= VIRTIO_DEV_ANY_ID
, id
->vendor
);
808 ADD_TO_DEVTABLE("virtio", struct virtio_device_id
, do_virtio_entry
);
811 * Looks like: vmbus:guid
812 * Each byte of the guid will be represented by two hex characters
816 static int do_vmbus_entry(const char *filename
, struct hv_vmbus_device_id
*id
,
820 char guid_name
[((sizeof(id
->guid
) + 1)) * 2];
822 for (i
= 0; i
< (sizeof(id
->guid
) * 2); i
+= 2)
823 sprintf(&guid_name
[i
], "%02x", id
->guid
[i
/2]);
825 strcpy(alias
, "vmbus:");
826 strcat(alias
, guid_name
);
830 ADD_TO_DEVTABLE("vmbus", struct hv_vmbus_device_id
, do_vmbus_entry
);
832 /* Looks like: i2c:S */
833 static int do_i2c_entry(const char *filename
, struct i2c_device_id
*id
,
836 sprintf(alias
, I2C_MODULE_PREFIX
"%s", id
->name
);
840 ADD_TO_DEVTABLE("i2c", struct i2c_device_id
, do_i2c_entry
);
842 /* Looks like: spi:S */
843 static int do_spi_entry(const char *filename
, struct spi_device_id
*id
,
846 sprintf(alias
, SPI_MODULE_PREFIX
"%s", id
->name
);
850 ADD_TO_DEVTABLE("spi", struct spi_device_id
, do_spi_entry
);
852 static const struct dmifield
{
856 { "bvn", DMI_BIOS_VENDOR
},
857 { "bvr", DMI_BIOS_VERSION
},
858 { "bd", DMI_BIOS_DATE
},
859 { "svn", DMI_SYS_VENDOR
},
860 { "pn", DMI_PRODUCT_NAME
},
861 { "pvr", DMI_PRODUCT_VERSION
},
862 { "rvn", DMI_BOARD_VENDOR
},
863 { "rn", DMI_BOARD_NAME
},
864 { "rvr", DMI_BOARD_VERSION
},
865 { "cvn", DMI_CHASSIS_VENDOR
},
866 { "ct", DMI_CHASSIS_TYPE
},
867 { "cvr", DMI_CHASSIS_VERSION
},
871 static void dmi_ascii_filter(char *d
, const char *s
)
873 /* Filter out characters we don't want to see in the modalias string */
875 if (*s
> ' ' && *s
< 127 && *s
!= ':')
882 static int do_dmi_entry(const char *filename
, struct dmi_system_id
*id
,
887 sprintf(alias
, "dmi*");
889 for (i
= 0; i
< ARRAY_SIZE(dmi_fields
); i
++) {
890 for (j
= 0; j
< 4; j
++) {
891 if (id
->matches
[j
].slot
&&
892 id
->matches
[j
].slot
== dmi_fields
[i
].field
) {
893 sprintf(alias
+ strlen(alias
), ":%s*",
894 dmi_fields
[i
].prefix
);
895 dmi_ascii_filter(alias
+ strlen(alias
),
896 id
->matches
[j
].substr
);
905 ADD_TO_DEVTABLE("dmi", struct dmi_system_id
, do_dmi_entry
);
907 static int do_platform_entry(const char *filename
,
908 struct platform_device_id
*id
, char *alias
)
910 sprintf(alias
, PLATFORM_MODULE_PREFIX
"%s", id
->name
);
913 ADD_TO_DEVTABLE("platform", struct platform_device_id
, do_platform_entry
);
915 static int do_mdio_entry(const char *filename
,
916 struct mdio_device_id
*id
, char *alias
)
920 alias
+= sprintf(alias
, MDIO_MODULE_PREFIX
);
922 for (i
= 0; i
< 32; i
++) {
923 if (!((id
->phy_id_mask
>> (31-i
)) & 1))
925 else if ((id
->phy_id
>> (31-i
)) & 1)
931 /* Terminate the string */
936 ADD_TO_DEVTABLE("mdio", struct mdio_device_id
, do_mdio_entry
);
938 /* Looks like: zorro:iN. */
939 static int do_zorro_entry(const char *filename
, struct zorro_device_id
*id
,
942 id
->id
= TO_NATIVE(id
->id
);
943 strcpy(alias
, "zorro:");
944 ADD(alias
, "i", id
->id
!= ZORRO_WILDCARD
, id
->id
);
947 ADD_TO_DEVTABLE("zorro", struct zorro_device_id
, do_zorro_entry
);
949 /* looks like: "pnp:dD" */
950 static int do_isapnp_entry(const char *filename
,
951 struct isapnp_device_id
*id
, char *alias
)
953 sprintf(alias
, "pnp:d%c%c%c%x%x%x%x*",
954 'A' + ((id
->vendor
>> 2) & 0x3f) - 1,
955 'A' + (((id
->vendor
& 3) << 3) | ((id
->vendor
>> 13) & 7)) - 1,
956 'A' + ((id
->vendor
>> 8) & 0x1f) - 1,
957 (id
->function
>> 4) & 0x0f, id
->function
& 0x0f,
958 (id
->function
>> 12) & 0x0f, (id
->function
>> 8) & 0x0f);
961 ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id
, do_isapnp_entry
);
964 * Append a match expression for a single masked hex digit.
965 * outp points to a pointer to the character at which to append.
966 * *outp is updated on return to point just after the appended text,
967 * to facilitate further appending.
969 static void append_nibble_mask(char **outp
,
970 unsigned int nibble
, unsigned int mask
)
981 p
+= sprintf(p
, "%X", nibble
);
986 * Dumbly emit a match pattern for all possible matching
987 * digits. This could be improved in some cases using ranges,
988 * but it has the advantage of being trivially correct, and is
992 for (i
= 0; i
< 0x10; i
++)
993 if ((i
& mask
) == nibble
)
994 p
+= sprintf(p
, "%X", i
);
998 /* Ensure that the string remains NUL-terminated: */
1001 /* Advance the caller's end-of-string pointer: */
1006 * looks like: "amba:dN"
1008 * N is exactly 8 digits, where each is an upper-case hex digit, or
1009 * a ? or [] pattern matching exactly one digit.
1011 static int do_amba_entry(const char *filename
,
1012 struct amba_id
*id
, char *alias
)
1017 if ((id
->id
& id
->mask
) != id
->id
)
1018 fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: "
1019 "id=0x%08X, mask=0x%08X. Please fix this driver.\n",
1020 filename
, id
->id
, id
->mask
);
1022 p
+= sprintf(alias
, "amba:d");
1023 for (digit
= 0; digit
< 8; digit
++)
1024 append_nibble_mask(&p
,
1025 (id
->id
>> (4 * (7 - digit
))) & 0xf,
1026 (id
->mask
>> (4 * (7 - digit
))) & 0xf);
1030 ADD_TO_DEVTABLE("amba", struct amba_id
, do_amba_entry
);
1032 /* Does namelen bytes of name exactly match the symbol? */
1033 static bool sym_is(const char *name
, unsigned namelen
, const char *symbol
)
1035 if (namelen
!= strlen(symbol
))
1038 return memcmp(name
, symbol
, namelen
) == 0;
1041 static void do_table(void *symval
, unsigned long size
,
1042 unsigned long id_size
,
1043 const char *device_id
,
1049 int (*do_entry
)(const char *, void *entry
, char *alias
) = function
;
1051 device_id_check(mod
->name
, device_id
, size
, id_size
, symval
);
1052 /* Leave last one: it's the terminator. */
1055 for (i
= 0; i
< size
; i
+= id_size
) {
1056 if (do_entry(mod
->name
, symval
+i
, alias
)) {
1057 buf_printf(&mod
->dev_table_buf
,
1058 "MODULE_ALIAS(\"%s\");\n", alias
);
1063 /* Create MODULE_ALIAS() statements.
1064 * At this time, we cannot write the actual output C source yet,
1065 * so we write into the mod->dev_table_buf buffer. */
1066 void handle_moddevtable(struct module
*mod
, struct elf_info
*info
,
1067 Elf_Sym
*sym
, const char *symname
)
1072 unsigned int namelen
;
1074 /* We're looking for a section relative symbol */
1075 if (!sym
->st_shndx
|| get_secindex(info
, sym
) >= info
->num_sections
)
1078 /* All our symbols are of form <prefix>__mod_XXX_device_table. */
1079 name
= strstr(symname
, "__mod_");
1082 name
+= strlen("__mod_");
1083 namelen
= strlen(name
);
1084 if (namelen
< strlen("_device_table"))
1086 if (strcmp(name
+ namelen
- strlen("_device_table"), "_device_table"))
1088 namelen
-= strlen("_device_table");
1090 /* Handle all-NULL symbols allocated into .bss */
1091 if (info
->sechdrs
[get_secindex(info
, sym
)].sh_type
& SHT_NOBITS
) {
1092 zeros
= calloc(1, sym
->st_size
);
1095 symval
= (void *)info
->hdr
1096 + info
->sechdrs
[get_secindex(info
, sym
)].sh_offset
1100 /* First handle the "special" cases */
1101 if (sym_is(name
, namelen
, "usb"))
1102 do_usb_table(symval
, sym
->st_size
, mod
);
1103 else if (sym_is(name
, namelen
, "pnp"))
1104 do_pnp_device_entry(symval
, sym
->st_size
, mod
);
1105 else if (sym_is(name
, namelen
, "pnp_card"))
1106 do_pnp_card_entries(symval
, sym
->st_size
, mod
);
1108 struct devtable
**p
;
1109 INIT_SECTION(__devtable
);
1111 for (p
= __start___devtable
; p
< __stop___devtable
; p
++) {
1112 if (sym_is(name
, namelen
, (*p
)->device_id
)) {
1113 do_table(symval
, sym
->st_size
, (*p
)->id_size
,
1114 (*p
)->device_id
, (*p
)->function
, mod
);
1122 /* Now add out buffered information to the generated C source */
1123 void add_moddevtable(struct buffer
*buf
, struct module
*mod
)
1125 buf_printf(buf
, "\n");
1126 buf_write(buf
, mod
->dev_table_buf
.p
, mod
->dev_table_buf
.pos
);
1127 free(mod
->dev_table_buf
.p
);