11da177e4SLinus Torvalds /* Simple code to turn various tables in an ELF file into alias definitions.
21da177e4SLinus Torvalds * This deals with kernel datastructures where they should be
31da177e4SLinus Torvalds * dealt with: in the kernel source.
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright 2002-2003 Rusty Russell, IBM Corporation
61da177e4SLinus Torvalds * 2003 Kai Germaschewski
71da177e4SLinus Torvalds *
81da177e4SLinus Torvalds *
91da177e4SLinus Torvalds * This software may be used and distributed according to the terms
101da177e4SLinus Torvalds * of the GNU General Public License, incorporated herein by reference.
111da177e4SLinus Torvalds */
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds #include "modpost.h"
146543becfSAndreas Schwab #include "devicetable-offsets.h"
151da177e4SLinus Torvalds
161da177e4SLinus Torvalds /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
171da177e4SLinus Torvalds * use either stdint.h or inttypes.h for the rest. */
181da177e4SLinus Torvalds #if KERNEL_ELFCLASS == ELFCLASS32
191da177e4SLinus Torvalds typedef Elf32_Addr kernel_ulong_t;
201d8f430cSRusty Russell #define BITS_PER_LONG 32
211da177e4SLinus Torvalds #else
221da177e4SLinus Torvalds typedef Elf64_Addr kernel_ulong_t;
231d8f430cSRusty Russell #define BITS_PER_LONG 64
241da177e4SLinus Torvalds #endif
251da177e4SLinus Torvalds #ifdef __sun__
261da177e4SLinus Torvalds #include <inttypes.h>
271da177e4SLinus Torvalds #else
281da177e4SLinus Torvalds #include <stdint.h>
291da177e4SLinus Torvalds #endif
301da177e4SLinus Torvalds
315e655772SJeff Mahoney #include <ctype.h>
32626596e2SRusty Russell #include <stdbool.h>
335e655772SJeff Mahoney
341da177e4SLinus Torvalds typedef uint32_t __u32;
351da177e4SLinus Torvalds typedef uint16_t __u16;
361da177e4SLinus Torvalds typedef unsigned char __u8;
3724804329SAndy Shevchenko
3824804329SAndy Shevchenko /* UUID types for backward compatibility, don't use in new code */
39b144ce2dSGreg Kroah-Hartman typedef struct {
40b144ce2dSGreg Kroah-Hartman __u8 b[16];
41389c9af7SHeikki Krogerus } guid_t;
42389c9af7SHeikki Krogerus
430fc1db9dSSumit Garg typedef struct {
440fc1db9dSSumit Garg __u8 b[16];
450fc1db9dSSumit Garg } uuid_t;
4624804329SAndy Shevchenko
47eacc95eaSMattias Jacobsson #define UUID_STRING_LEN 36
481da177e4SLinus Torvalds
4924804329SAndy Shevchenko /* MEI UUID type, don't use anywhere else */
5024804329SAndy Shevchenko typedef struct {
5124804329SAndy Shevchenko __u8 b[16];
5224804329SAndy Shevchenko } uuid_le;
5324804329SAndy Shevchenko
541da177e4SLinus Torvalds /* Big exception to the "don't include kernel headers into userspace, which
551da177e4SLinus Torvalds * even potentially has different endianness and word sizes, since
561da177e4SLinus Torvalds * we handle those differences explicitly below */
571da177e4SLinus Torvalds #include "../../include/linux/mod_devicetable.h"
581da177e4SLinus Torvalds
59e49ce141SRusty Russell /* This array collects all instances that use the generic do_table */
60e49ce141SRusty Russell struct devtable {
6121bdd17bSTom Gundersen const char *device_id; /* name of table, __mod_<name>__*_device_table. */
62e49ce141SRusty Russell unsigned long id_size;
63f880eea6SMasahiro Yamada int (*do_entry)(const char *filename, void *symval, char *alias);
64e49ce141SRusty Russell };
65e49ce141SRusty Russell
66841f1b8fSMattias Jacobsson /* Size of alias provided to do_entry functions */
67841f1b8fSMattias Jacobsson #define ALIAS_SIZE 500
68841f1b8fSMattias Jacobsson
696543becfSAndreas Schwab /* Define a variable f that holds the value of field f of struct devid
706543becfSAndreas Schwab * based at address m.
716543becfSAndreas Schwab */
726543becfSAndreas Schwab #define DEF_FIELD(m, devid, f) \
736543becfSAndreas Schwab typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))
74c2b1a922SLeonardo Bras
75c2b1a922SLeonardo Bras /* Define a variable v that holds the address of field f of struct devid
76c2b1a922SLeonardo Bras * based at address m. Due to the way typeof works, for a field of type
77c2b1a922SLeonardo Bras * T[N] the variable has type T(*)[N], _not_ T*.
78c2b1a922SLeonardo Bras */
79c2b1a922SLeonardo Bras #define DEF_FIELD_ADDR_VAR(m, devid, f, v) \
80c2b1a922SLeonardo Bras typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f)
81c2b1a922SLeonardo Bras
826543becfSAndreas Schwab /* Define a variable f that holds the address of field f of struct devid
836543becfSAndreas Schwab * based at address m. Due to the way typeof works, for a field of type
846543becfSAndreas Schwab * T[N] the variable has type T(*)[N], _not_ T*.
856543becfSAndreas Schwab */
866543becfSAndreas Schwab #define DEF_FIELD_ADDR(m, devid, f) \
87c2b1a922SLeonardo Bras DEF_FIELD_ADDR_VAR(m, devid, f, f)
886543becfSAndreas Schwab
891da177e4SLinus Torvalds #define ADD(str, sep, cond, field) \
901da177e4SLinus Torvalds do { \
911da177e4SLinus Torvalds strcat(str, sep); \
921da177e4SLinus Torvalds if (cond) \
931da177e4SLinus Torvalds sprintf(str + strlen(str), \
941da177e4SLinus Torvalds sizeof(field) == 1 ? "%02X" : \
951da177e4SLinus Torvalds sizeof(field) == 2 ? "%04X" : \
961da177e4SLinus Torvalds sizeof(field) == 4 ? "%08X" : "", \
971da177e4SLinus Torvalds field); \
981da177e4SLinus Torvalds else \
991da177e4SLinus Torvalds sprintf(str + strlen(str), "*"); \
1001da177e4SLinus Torvalds } while(0)
1011da177e4SLinus Torvalds
1022f632369SJavier Martinez Canillas /* End in a wildcard, for future extension */
add_wildcard(char * str)103ac551828SJean Delvare static inline void add_wildcard(char *str)
104ac551828SJean Delvare {
105ac551828SJean Delvare int len = strlen(str);
106ac551828SJean Delvare
107ac551828SJean Delvare if (str[len - 1] != '*')
108ac551828SJean Delvare strcat(str + len, "*");
109ac551828SJean Delvare }
110ac551828SJean Delvare
add_uuid(char * str,uuid_le uuid)111b144ce2dSGreg Kroah-Hartman static inline void add_uuid(char *str, uuid_le uuid)
112c93b76b3STomas Winkler {
113c93b76b3STomas Winkler int len = strlen(str);
114c93b76b3STomas Winkler
11559796edcSPrarit Bhargava sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
11659796edcSPrarit Bhargava uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0],
11759796edcSPrarit Bhargava uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6],
11859796edcSPrarit Bhargava uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11],
11959796edcSPrarit Bhargava uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]);
120c93b76b3STomas Winkler }
121c93b76b3STomas Winkler
add_guid(char * str,guid_t guid)122fa443bc3SThomas Weißschuh static inline void add_guid(char *str, guid_t guid)
123fa443bc3SThomas Weißschuh {
124fa443bc3SThomas Weißschuh int len = strlen(str);
125fa443bc3SThomas Weißschuh
126fa443bc3SThomas Weißschuh sprintf(str + len, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
127fa443bc3SThomas Weißschuh guid.b[3], guid.b[2], guid.b[1], guid.b[0],
128fa443bc3SThomas Weißschuh guid.b[5], guid.b[4], guid.b[7], guid.b[6],
129fa443bc3SThomas Weißschuh guid.b[8], guid.b[9], guid.b[10], guid.b[11],
130fa443bc3SThomas Weißschuh guid.b[12], guid.b[13], guid.b[14], guid.b[15]);
131fa443bc3SThomas Weißschuh }
132fa443bc3SThomas Weißschuh
133fb33d816SSam Ravnborg /**
134fb33d816SSam Ravnborg * Check that sizeof(device_id type) are consistent with size of section
135fb33d816SSam Ravnborg * in .o file. If in-consistent then userspace and kernel does not agree
136fb33d816SSam Ravnborg * on actual size which is a bug.
137e0049825SKees Cook * Also verify that the final entry in the table is all zeros.
1384ce6efedSSam Ravnborg * Ignore both checks if build host differ from target host and size differs.
139fb33d816SSam Ravnborg **/
device_id_check(const char * modname,const char * device_id,unsigned long size,unsigned long id_size,void * symval)140e0049825SKees Cook static void device_id_check(const char *modname, const char *device_id,
141e0049825SKees Cook unsigned long size, unsigned long id_size,
142e0049825SKees Cook void *symval)
143fb33d816SSam Ravnborg {
144e0049825SKees Cook int i;
145e0049825SKees Cook
146fb33d816SSam Ravnborg if (size % id_size || size < id_size) {
1470d2573a2SGeert Uytterhoeven fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo of the size of section __mod_%s__<identifier>_device_table=%lu.\n"
1480d2573a2SGeert Uytterhoeven "Fix definition of struct %s_device_id in mod_devicetable.h\n",
149fb33d816SSam Ravnborg modname, device_id, id_size, device_id, size, device_id);
150fb33d816SSam Ravnborg }
151e0049825SKees Cook /* Verify last one is a terminator */
152e0049825SKees Cook for (i = 0; i < id_size; i++ ) {
153e0049825SKees Cook if (*(uint8_t*)(symval+size-id_size+i)) {
1540d2573a2SGeert Uytterhoeven fprintf(stderr,
1550d2573a2SGeert Uytterhoeven "%s: struct %s_device_id is %lu bytes. The last of %lu is:\n",
156e0049825SKees Cook modname, device_id, id_size, size / id_size);
157e0049825SKees Cook for (i = 0; i < id_size; i++ )
158e0049825SKees Cook fprintf(stderr,"0x%02x ",
159e0049825SKees Cook *(uint8_t*)(symval+size-id_size+i) );
160e0049825SKees Cook fprintf(stderr,"\n");
1610d2573a2SGeert Uytterhoeven fatal("%s: struct %s_device_id is not terminated with a NULL entry!\n",
1620d2573a2SGeert Uytterhoeven modname, device_id);
163e0049825SKees Cook }
164e0049825SKees Cook }
165fb33d816SSam Ravnborg }
166fb33d816SSam Ravnborg
167b19dcd93SRoman Kagan /* USB is special because the bcdDevice can be matched against a numeric range */
16881df2d59SBjørn Mork /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */
do_usb_entry(void * symval,unsigned int bcdDevice_initial,int bcdDevice_initial_digits,unsigned char range_lo,unsigned char range_hi,unsigned char max,struct module * mod)1696543becfSAndreas Schwab static void do_usb_entry(void *symval,
170b19dcd93SRoman Kagan unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
171b19dcd93SRoman Kagan unsigned char range_lo, unsigned char range_hi,
172afe2dab4SNathaniel McCallum unsigned char max, struct module *mod)
1731da177e4SLinus Torvalds {
174b19dcd93SRoman Kagan char alias[500];
1756543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, match_flags);
1766543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, idVendor);
1776543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, idProduct);
1786543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
1796543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bDeviceClass);
1806543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bDeviceSubClass);
1816543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bDeviceProtocol);
1826543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceClass);
1836543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceSubClass);
1846543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceProtocol);
1856543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceNumber);
1866543becfSAndreas Schwab
1871da177e4SLinus Torvalds strcpy(alias, "usb:");
1886543becfSAndreas Schwab ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR,
1896543becfSAndreas Schwab idVendor);
1906543becfSAndreas Schwab ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
1916543becfSAndreas Schwab idProduct);
192b19dcd93SRoman Kagan
193b19dcd93SRoman Kagan strcat(alias, "d");
194b19dcd93SRoman Kagan if (bcdDevice_initial_digits)
195b19dcd93SRoman Kagan sprintf(alias + strlen(alias), "%0*X",
196b19dcd93SRoman Kagan bcdDevice_initial_digits, bcdDevice_initial);
197b19dcd93SRoman Kagan if (range_lo == range_hi)
198afe2dab4SNathaniel McCallum sprintf(alias + strlen(alias), "%X", range_lo);
199afe2dab4SNathaniel McCallum else if (range_lo > 0 || range_hi < max) {
200afe2dab4SNathaniel McCallum if (range_lo > 0x9 || range_hi < 0xA)
201afe2dab4SNathaniel McCallum sprintf(alias + strlen(alias),
202afe2dab4SNathaniel McCallum "[%X-%X]",
203afe2dab4SNathaniel McCallum range_lo,
204afe2dab4SNathaniel McCallum range_hi);
205afe2dab4SNathaniel McCallum else {
206afe2dab4SNathaniel McCallum sprintf(alias + strlen(alias),
207afe2dab4SNathaniel McCallum range_lo < 0x9 ? "[%X-9" : "[%X",
208afe2dab4SNathaniel McCallum range_lo);
209afe2dab4SNathaniel McCallum sprintf(alias + strlen(alias),
21003b56329SJan Moskyto Matejka range_hi > 0xA ? "A-%X]" : "%X]",
21103b56329SJan Moskyto Matejka range_hi);
212afe2dab4SNathaniel McCallum }
213afe2dab4SNathaniel McCallum }
2146543becfSAndreas Schwab if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
215b19dcd93SRoman Kagan strcat(alias, "*");
216b19dcd93SRoman Kagan
2176543becfSAndreas Schwab ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
2186543becfSAndreas Schwab bDeviceClass);
2196543becfSAndreas Schwab ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
2206543becfSAndreas Schwab bDeviceSubClass);
2216543becfSAndreas Schwab ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
2226543becfSAndreas Schwab bDeviceProtocol);
2236543becfSAndreas Schwab ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
2246543becfSAndreas Schwab bInterfaceClass);
2256543becfSAndreas Schwab ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
2266543becfSAndreas Schwab bInterfaceSubClass);
2276543becfSAndreas Schwab ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
2286543becfSAndreas Schwab bInterfaceProtocol);
2296543becfSAndreas Schwab ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER,
2306543becfSAndreas Schwab bInterfaceNumber);
231b19dcd93SRoman Kagan
232ac551828SJean Delvare add_wildcard(alias);
233b19dcd93SRoman Kagan buf_printf(&mod->dev_table_buf,
234b19dcd93SRoman Kagan "MODULE_ALIAS(\"%s\");\n", alias);
235b19dcd93SRoman Kagan }
236b19dcd93SRoman Kagan
23755f49f26SNathaniel McCallum /* Handles increment/decrement of BCD formatted integers */
23855f49f26SNathaniel McCallum /* Returns the previous value, so it works like i++ or i-- */
incbcd(unsigned int * bcd,int inc,unsigned char max,size_t chars)23955f49f26SNathaniel McCallum static unsigned int incbcd(unsigned int *bcd,
24055f49f26SNathaniel McCallum int inc,
24155f49f26SNathaniel McCallum unsigned char max,
24255f49f26SNathaniel McCallum size_t chars)
24355f49f26SNathaniel McCallum {
24455f49f26SNathaniel McCallum unsigned int init = *bcd, i, j;
24555f49f26SNathaniel McCallum unsigned long long c, dec = 0;
24655f49f26SNathaniel McCallum
24755f49f26SNathaniel McCallum /* If bcd is not in BCD format, just increment */
24855f49f26SNathaniel McCallum if (max > 0x9) {
24955f49f26SNathaniel McCallum *bcd += inc;
25055f49f26SNathaniel McCallum return init;
25155f49f26SNathaniel McCallum }
25255f49f26SNathaniel McCallum
25355f49f26SNathaniel McCallum /* Convert BCD to Decimal */
25455f49f26SNathaniel McCallum for (i=0 ; i < chars ; i++) {
25555f49f26SNathaniel McCallum c = (*bcd >> (i << 2)) & 0xf;
25655f49f26SNathaniel McCallum c = c > 9 ? 9 : c; /* force to bcd just in case */
25755f49f26SNathaniel McCallum for (j=0 ; j < i ; j++)
25855f49f26SNathaniel McCallum c = c * 10;
25955f49f26SNathaniel McCallum dec += c;
26055f49f26SNathaniel McCallum }
26155f49f26SNathaniel McCallum
26255f49f26SNathaniel McCallum /* Do our increment/decrement */
26355f49f26SNathaniel McCallum dec += inc;
26455f49f26SNathaniel McCallum *bcd = 0;
26555f49f26SNathaniel McCallum
26655f49f26SNathaniel McCallum /* Convert back to BCD */
26755f49f26SNathaniel McCallum for (i=0 ; i < chars ; i++) {
26855f49f26SNathaniel McCallum for (c=1,j=0 ; j < i ; j++)
26955f49f26SNathaniel McCallum c = c * 10;
27055f49f26SNathaniel McCallum c = (dec / c) % 10;
27155f49f26SNathaniel McCallum *bcd += c << (i << 2);
27255f49f26SNathaniel McCallum }
27355f49f26SNathaniel McCallum return init;
27455f49f26SNathaniel McCallum }
27555f49f26SNathaniel McCallum
do_usb_entry_multi(void * symval,struct module * mod)2766543becfSAndreas Schwab static void do_usb_entry_multi(void *symval, struct module *mod)
277b19dcd93SRoman Kagan {
278b19dcd93SRoman Kagan unsigned int devlo, devhi;
279afe2dab4SNathaniel McCallum unsigned char chi, clo, max;
280b19dcd93SRoman Kagan int ndigits;
281b19dcd93SRoman Kagan
2826543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, match_flags);
2836543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, idVendor);
2846543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, idProduct);
2856543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
2866543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bcdDevice_hi);
2876543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bDeviceClass);
2886543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceClass);
289b19dcd93SRoman Kagan
2906543becfSAndreas Schwab devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
2916543becfSAndreas Schwab bcdDevice_lo : 0x0U;
2926543becfSAndreas Schwab devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
2936543becfSAndreas Schwab bcdDevice_hi : ~0x0U;
294b19dcd93SRoman Kagan
295afe2dab4SNathaniel McCallum /* Figure out if this entry is in bcd or hex format */
296afe2dab4SNathaniel McCallum max = 0x9; /* Default to decimal format */
2976543becfSAndreas Schwab for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) {
298afe2dab4SNathaniel McCallum clo = (devlo >> (ndigits << 2)) & 0xf;
299afe2dab4SNathaniel McCallum chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
300afe2dab4SNathaniel McCallum if (clo > max || chi > max) {
301afe2dab4SNathaniel McCallum max = 0xf;
302afe2dab4SNathaniel McCallum break;
303afe2dab4SNathaniel McCallum }
304afe2dab4SNathaniel McCallum }
305afe2dab4SNathaniel McCallum
306b19dcd93SRoman Kagan /*
307b19dcd93SRoman Kagan * Some modules (visor) have empty slots as placeholder for
308b19dcd93SRoman Kagan * run-time specification that results in catch-all alias
309b19dcd93SRoman Kagan */
3106543becfSAndreas Schwab if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass))
311b19dcd93SRoman Kagan return;
312b19dcd93SRoman Kagan
313b19dcd93SRoman Kagan /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
3146543becfSAndreas Schwab for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
315b19dcd93SRoman Kagan clo = devlo & 0xf;
316b19dcd93SRoman Kagan chi = devhi & 0xf;
317afe2dab4SNathaniel McCallum if (chi > max) /* If we are in bcd mode, truncate if necessary */
318afe2dab4SNathaniel McCallum chi = max;
319b19dcd93SRoman Kagan devlo >>= 4;
320b19dcd93SRoman Kagan devhi >>= 4;
321b19dcd93SRoman Kagan
322b19dcd93SRoman Kagan if (devlo == devhi || !ndigits) {
3236543becfSAndreas Schwab do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod);
324b19dcd93SRoman Kagan break;
325b19dcd93SRoman Kagan }
326b19dcd93SRoman Kagan
327afe2dab4SNathaniel McCallum if (clo > 0x0)
3286543becfSAndreas Schwab do_usb_entry(symval,
32955f49f26SNathaniel McCallum incbcd(&devlo, 1, max,
3306543becfSAndreas Schwab sizeof(bcdDevice_lo) * 2),
33155f49f26SNathaniel McCallum ndigits, clo, max, max, mod);
332b19dcd93SRoman Kagan
333afe2dab4SNathaniel McCallum if (chi < max)
3346543becfSAndreas Schwab do_usb_entry(symval,
33555f49f26SNathaniel McCallum incbcd(&devhi, -1, max,
3366543becfSAndreas Schwab sizeof(bcdDevice_lo) * 2),
33755f49f26SNathaniel McCallum ndigits, 0x0, chi, max, mod);
338b19dcd93SRoman Kagan }
339b19dcd93SRoman Kagan }
340b19dcd93SRoman Kagan
do_usb_table(void * symval,unsigned long size,struct module * mod)341b19dcd93SRoman Kagan static void do_usb_table(void *symval, unsigned long size,
342b19dcd93SRoman Kagan struct module *mod)
343b19dcd93SRoman Kagan {
344b19dcd93SRoman Kagan unsigned int i;
3456543becfSAndreas Schwab const unsigned long id_size = SIZE_usb_device_id;
346b19dcd93SRoman Kagan
347e0049825SKees Cook device_id_check(mod->name, "usb", size, id_size, symval);
348fb33d816SSam Ravnborg
349b19dcd93SRoman Kagan /* Leave last one: it's the terminator. */
350b19dcd93SRoman Kagan size -= id_size;
351b19dcd93SRoman Kagan
352b19dcd93SRoman Kagan for (i = 0; i < size; i += id_size)
353b19dcd93SRoman Kagan do_usb_entry_multi(symval + i, mod);
3541da177e4SLinus Torvalds }
3551da177e4SLinus Torvalds
do_of_entry_multi(void * symval,struct module * mod)356acbef7b7SPhilipp Zabel static void do_of_entry_multi(void *symval, struct module *mod)
357acbef7b7SPhilipp Zabel {
358acbef7b7SPhilipp Zabel char alias[500];
359acbef7b7SPhilipp Zabel int len;
360acbef7b7SPhilipp Zabel char *tmp;
361acbef7b7SPhilipp Zabel
362acbef7b7SPhilipp Zabel DEF_FIELD_ADDR(symval, of_device_id, name);
363acbef7b7SPhilipp Zabel DEF_FIELD_ADDR(symval, of_device_id, type);
364acbef7b7SPhilipp Zabel DEF_FIELD_ADDR(symval, of_device_id, compatible);
365acbef7b7SPhilipp Zabel
366acbef7b7SPhilipp Zabel len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*",
367acbef7b7SPhilipp Zabel (*type)[0] ? *type : "*");
368acbef7b7SPhilipp Zabel
369b3c0a4daSWolfram Sang if ((*compatible)[0])
370acbef7b7SPhilipp Zabel sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
371acbef7b7SPhilipp Zabel *compatible);
372acbef7b7SPhilipp Zabel
373acbef7b7SPhilipp Zabel /* Replace all whitespace with underscores */
374acbef7b7SPhilipp Zabel for (tmp = alias; tmp && *tmp; tmp++)
375acbef7b7SPhilipp Zabel if (isspace(*tmp))
376acbef7b7SPhilipp Zabel *tmp = '_';
377acbef7b7SPhilipp Zabel
378acbef7b7SPhilipp Zabel buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias);
379acbef7b7SPhilipp Zabel strcat(alias, "C");
380acbef7b7SPhilipp Zabel add_wildcard(alias);
381acbef7b7SPhilipp Zabel buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias);
382acbef7b7SPhilipp Zabel }
383acbef7b7SPhilipp Zabel
do_of_table(void * symval,unsigned long size,struct module * mod)384acbef7b7SPhilipp Zabel static void do_of_table(void *symval, unsigned long size,
385acbef7b7SPhilipp Zabel struct module *mod)
386acbef7b7SPhilipp Zabel {
387acbef7b7SPhilipp Zabel unsigned int i;
388acbef7b7SPhilipp Zabel const unsigned long id_size = SIZE_of_device_id;
389acbef7b7SPhilipp Zabel
390acbef7b7SPhilipp Zabel device_id_check(mod->name, "of", size, id_size, symval);
391acbef7b7SPhilipp Zabel
392acbef7b7SPhilipp Zabel /* Leave last one: it's the terminator. */
393acbef7b7SPhilipp Zabel size -= id_size;
394acbef7b7SPhilipp Zabel
395acbef7b7SPhilipp Zabel for (i = 0; i < size; i += id_size)
396acbef7b7SPhilipp Zabel do_of_entry_multi(symval + i, mod);
397acbef7b7SPhilipp Zabel }
398acbef7b7SPhilipp Zabel
399e8c84f9aSJiri Slaby /* Looks like: hid:bNvNpN */
do_hid_entry(const char * filename,void * symval,char * alias)400e8c84f9aSJiri Slaby static int do_hid_entry(const char *filename,
4016543becfSAndreas Schwab void *symval, char *alias)
402e8c84f9aSJiri Slaby {
4036543becfSAndreas Schwab DEF_FIELD(symval, hid_device_id, bus);
4046543becfSAndreas Schwab DEF_FIELD(symval, hid_device_id, group);
4056543becfSAndreas Schwab DEF_FIELD(symval, hid_device_id, vendor);
4066543becfSAndreas Schwab DEF_FIELD(symval, hid_device_id, product);
407e8c84f9aSJiri Slaby
4087431fb76SHenrik Rydberg sprintf(alias, "hid:");
4096543becfSAndreas Schwab ADD(alias, "b", bus != HID_BUS_ANY, bus);
4106543becfSAndreas Schwab ADD(alias, "g", group != HID_GROUP_ANY, group);
4116543becfSAndreas Schwab ADD(alias, "v", vendor != HID_ANY_ID, vendor);
4126543becfSAndreas Schwab ADD(alias, "p", product != HID_ANY_ID, product);
413e8c84f9aSJiri Slaby
414e8c84f9aSJiri Slaby return 1;
415e8c84f9aSJiri Slaby }
416e8c84f9aSJiri Slaby
4171da177e4SLinus Torvalds /* Looks like: ieee1394:venNmoNspNverN */
do_ieee1394_entry(const char * filename,void * symval,char * alias)4181da177e4SLinus Torvalds static int do_ieee1394_entry(const char *filename,
4196543becfSAndreas Schwab void *symval, char *alias)
4201da177e4SLinus Torvalds {
4216543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, match_flags);
4226543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, vendor_id);
4236543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, model_id);
4246543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, specifier_id);
4256543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, version);
4261da177e4SLinus Torvalds
4271da177e4SLinus Torvalds strcpy(alias, "ieee1394:");
4286543becfSAndreas Schwab ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID,
4296543becfSAndreas Schwab vendor_id);
4306543becfSAndreas Schwab ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID,
4316543becfSAndreas Schwab model_id);
4326543becfSAndreas Schwab ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID,
4336543becfSAndreas Schwab specifier_id);
4346543becfSAndreas Schwab ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION,
4356543becfSAndreas Schwab version);
4361da177e4SLinus Torvalds
437ac551828SJean Delvare add_wildcard(alias);
4381da177e4SLinus Torvalds return 1;
4391da177e4SLinus Torvalds }
4401da177e4SLinus Torvalds
441cc6711b0SMax Gurtovoy /* Looks like: pci:vNdNsvNsdNbcNscNiN or <prefix>_pci:vNdNsvNsdNbcNscNiN. */
do_pci_entry(const char * filename,void * symval,char * alias)4421da177e4SLinus Torvalds static int do_pci_entry(const char *filename,
4436543becfSAndreas Schwab void *symval, char *alias)
4441da177e4SLinus Torvalds {
4451da177e4SLinus Torvalds /* Class field can be divided into these three. */
4461da177e4SLinus Torvalds unsigned char baseclass, subclass, interface,
4471da177e4SLinus Torvalds baseclass_mask, subclass_mask, interface_mask;
4481da177e4SLinus Torvalds
4496543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, vendor);
4506543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, device);
4516543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, subvendor);
4526543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, subdevice);
4536543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, class);
4546543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, class_mask);
455cc6711b0SMax Gurtovoy DEF_FIELD(symval, pci_device_id, override_only);
4561da177e4SLinus Torvalds
457cc6711b0SMax Gurtovoy switch (override_only) {
458cc6711b0SMax Gurtovoy case 0:
4591da177e4SLinus Torvalds strcpy(alias, "pci:");
460cc6711b0SMax Gurtovoy break;
461cc6711b0SMax Gurtovoy case PCI_ID_F_VFIO_DRIVER_OVERRIDE:
462cc6711b0SMax Gurtovoy strcpy(alias, "vfio_pci:");
463cc6711b0SMax Gurtovoy break;
464cc6711b0SMax Gurtovoy default:
465cc6711b0SMax Gurtovoy warn("Unknown PCI driver_override alias %08X\n",
466cc6711b0SMax Gurtovoy override_only);
467cc6711b0SMax Gurtovoy return 0;
468cc6711b0SMax Gurtovoy }
469cc6711b0SMax Gurtovoy
4706543becfSAndreas Schwab ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
4716543becfSAndreas Schwab ADD(alias, "d", device != PCI_ANY_ID, device);
4726543becfSAndreas Schwab ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);
4736543becfSAndreas Schwab ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice);
4741da177e4SLinus Torvalds
4756543becfSAndreas Schwab baseclass = (class) >> 16;
4766543becfSAndreas Schwab baseclass_mask = (class_mask) >> 16;
4776543becfSAndreas Schwab subclass = (class) >> 8;
4786543becfSAndreas Schwab subclass_mask = (class_mask) >> 8;
4796543becfSAndreas Schwab interface = class;
4806543becfSAndreas Schwab interface_mask = class_mask;
4811da177e4SLinus Torvalds
4821da177e4SLinus Torvalds if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
4831da177e4SLinus Torvalds || (subclass_mask != 0 && subclass_mask != 0xFF)
4841da177e4SLinus Torvalds || (interface_mask != 0 && interface_mask != 0xFF)) {
485cb80514dSSam Ravnborg warn("Can't handle masks in %s:%04X\n",
4866543becfSAndreas Schwab filename, class_mask);
4871da177e4SLinus Torvalds return 0;
4881da177e4SLinus Torvalds }
4891da177e4SLinus Torvalds
4901da177e4SLinus Torvalds ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
4911da177e4SLinus Torvalds ADD(alias, "sc", subclass_mask == 0xFF, subclass);
4921da177e4SLinus Torvalds ADD(alias, "i", interface_mask == 0xFF, interface);
493ac551828SJean Delvare add_wildcard(alias);
4941da177e4SLinus Torvalds return 1;
4951da177e4SLinus Torvalds }
4961da177e4SLinus Torvalds
4971da177e4SLinus Torvalds /* looks like: "ccw:tNmNdtNdmN" */
do_ccw_entry(const char * filename,void * symval,char * alias)4981da177e4SLinus Torvalds static int do_ccw_entry(const char *filename,
4996543becfSAndreas Schwab void *symval, char *alias)
5001da177e4SLinus Torvalds {
5016543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, match_flags);
5026543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, cu_type);
5036543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, cu_model);
5046543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, dev_type);
5056543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, dev_model);
5061da177e4SLinus Torvalds
5071da177e4SLinus Torvalds strcpy(alias, "ccw:");
5086543becfSAndreas Schwab ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
5096543becfSAndreas Schwab cu_type);
5106543becfSAndreas Schwab ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
5116543becfSAndreas Schwab cu_model);
5126543becfSAndreas Schwab ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
5136543becfSAndreas Schwab dev_type);
5146543becfSAndreas Schwab ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
5156543becfSAndreas Schwab dev_model);
516ac551828SJean Delvare add_wildcard(alias);
5171da177e4SLinus Torvalds return 1;
5181da177e4SLinus Torvalds }
5191da177e4SLinus Torvalds
5201534c382SMartin Schwidefsky /* looks like: "ap:tN" */
do_ap_entry(const char * filename,void * symval,char * alias)5211534c382SMartin Schwidefsky static int do_ap_entry(const char *filename,
5226543becfSAndreas Schwab void *symval, char *alias)
5231534c382SMartin Schwidefsky {
5246543becfSAndreas Schwab DEF_FIELD(symval, ap_device_id, dev_type);
5256543becfSAndreas Schwab
5266543becfSAndreas Schwab sprintf(alias, "ap:t%02X*", dev_type);
5271534c382SMartin Schwidefsky return 1;
5281534c382SMartin Schwidefsky }
5291534c382SMartin Schwidefsky
5307e9db9eaSCornelia Huck /* looks like: "css:tN" */
do_css_entry(const char * filename,void * symval,char * alias)5317e9db9eaSCornelia Huck static int do_css_entry(const char *filename,
5326543becfSAndreas Schwab void *symval, char *alias)
5337e9db9eaSCornelia Huck {
5346543becfSAndreas Schwab DEF_FIELD(symval, css_device_id, type);
5356543becfSAndreas Schwab
5366543becfSAndreas Schwab sprintf(alias, "css:t%01X", type);
5377e9db9eaSCornelia Huck return 1;
5387e9db9eaSCornelia Huck }
5397e9db9eaSCornelia Huck
5401da177e4SLinus Torvalds /* Looks like: "serio:tyNprNidNexN" */
do_serio_entry(const char * filename,void * symval,char * alias)5411da177e4SLinus Torvalds static int do_serio_entry(const char *filename,
5426543becfSAndreas Schwab void *symval, char *alias)
5431da177e4SLinus Torvalds {
5446543becfSAndreas Schwab DEF_FIELD(symval, serio_device_id, type);
5456543becfSAndreas Schwab DEF_FIELD(symval, serio_device_id, proto);
5466543becfSAndreas Schwab DEF_FIELD(symval, serio_device_id, id);
5476543becfSAndreas Schwab DEF_FIELD(symval, serio_device_id, extra);
5481da177e4SLinus Torvalds
5491da177e4SLinus Torvalds strcpy(alias, "serio:");
5506543becfSAndreas Schwab ADD(alias, "ty", type != SERIO_ANY, type);
5516543becfSAndreas Schwab ADD(alias, "pr", proto != SERIO_ANY, proto);
5526543becfSAndreas Schwab ADD(alias, "id", id != SERIO_ANY, id);
5536543becfSAndreas Schwab ADD(alias, "ex", extra != SERIO_ANY, extra);
5541da177e4SLinus Torvalds
555ac551828SJean Delvare add_wildcard(alias);
5561da177e4SLinus Torvalds return 1;
5571da177e4SLinus Torvalds }
5581da177e4SLinus Torvalds
55926095a01SSuthikulpanit, Suravee /* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or
56026095a01SSuthikulpanit, Suravee * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if)
56126095a01SSuthikulpanit, Suravee *
56226095a01SSuthikulpanit, Suravee * NOTE: Each driver should use one of the following : _HID, _CIDs
56326095a01SSuthikulpanit, Suravee * or _CLS. Also, bb, ss, and pp can be substituted with ??
56426095a01SSuthikulpanit, Suravee * as don't care byte.
56526095a01SSuthikulpanit, Suravee */
do_acpi_entry(const char * filename,void * symval,char * alias)56629b71a1cSThomas Renninger static int do_acpi_entry(const char *filename,
5676543becfSAndreas Schwab void *symval, char *alias)
56829b71a1cSThomas Renninger {
5696543becfSAndreas Schwab DEF_FIELD_ADDR(symval, acpi_device_id, id);
57026095a01SSuthikulpanit, Suravee DEF_FIELD_ADDR(symval, acpi_device_id, cls);
57126095a01SSuthikulpanit, Suravee DEF_FIELD_ADDR(symval, acpi_device_id, cls_msk);
57226095a01SSuthikulpanit, Suravee
57326095a01SSuthikulpanit, Suravee if (id && strlen((const char *)*id))
5746543becfSAndreas Schwab sprintf(alias, "acpi*:%s:*", *id);
57526095a01SSuthikulpanit, Suravee else if (cls) {
57626095a01SSuthikulpanit, Suravee int i, byte_shift, cnt = 0;
57726095a01SSuthikulpanit, Suravee unsigned int msk;
57826095a01SSuthikulpanit, Suravee
57926095a01SSuthikulpanit, Suravee sprintf(&alias[cnt], "acpi*:");
58026095a01SSuthikulpanit, Suravee cnt = 6;
58126095a01SSuthikulpanit, Suravee for (i = 1; i <= 3; i++) {
58226095a01SSuthikulpanit, Suravee byte_shift = 8 * (3-i);
58326095a01SSuthikulpanit, Suravee msk = (*cls_msk >> byte_shift) & 0xFF;
58426095a01SSuthikulpanit, Suravee if (msk)
58526095a01SSuthikulpanit, Suravee sprintf(&alias[cnt], "%02x",
58626095a01SSuthikulpanit, Suravee (*cls >> byte_shift) & 0xFF);
58726095a01SSuthikulpanit, Suravee else
58826095a01SSuthikulpanit, Suravee sprintf(&alias[cnt], "??");
58926095a01SSuthikulpanit, Suravee cnt += 2;
59026095a01SSuthikulpanit, Suravee }
59126095a01SSuthikulpanit, Suravee sprintf(&alias[cnt], ":*");
59226095a01SSuthikulpanit, Suravee }
59329b71a1cSThomas Renninger return 1;
59429b71a1cSThomas Renninger }
59529b71a1cSThomas Renninger
5961da177e4SLinus Torvalds /* looks like: "pnp:dD" */
do_pnp_device_entry(void * symval,unsigned long size,struct module * mod)59722454cb9SKay Sievers static void do_pnp_device_entry(void *symval, unsigned long size,
59822454cb9SKay Sievers struct module *mod)
5991da177e4SLinus Torvalds {
6006543becfSAndreas Schwab const unsigned long id_size = SIZE_pnp_device_id;
6015e4c6564SKay Sievers const unsigned int count = (size / id_size)-1;
6025e4c6564SKay Sievers unsigned int i;
60322454cb9SKay Sievers
60422454cb9SKay Sievers device_id_check(mod->name, "pnp", size, id_size, symval);
60522454cb9SKay Sievers
6065e4c6564SKay Sievers for (i = 0; i < count; i++) {
6076543becfSAndreas Schwab DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id);
6086543becfSAndreas Schwab char acpi_id[sizeof(*id)];
60972638f59SKay Sievers int j;
6105e4c6564SKay Sievers
61122454cb9SKay Sievers buf_printf(&mod->dev_table_buf,
6126543becfSAndreas Schwab "MODULE_ALIAS(\"pnp:d%s*\");\n", *id);
61372638f59SKay Sievers
61472638f59SKay Sievers /* fix broken pnp bus lowercasing */
61572638f59SKay Sievers for (j = 0; j < sizeof(acpi_id); j++)
6166543becfSAndreas Schwab acpi_id[j] = toupper((*id)[j]);
61722454cb9SKay Sievers buf_printf(&mod->dev_table_buf,
61872638f59SKay Sievers "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
6195e4c6564SKay Sievers }
6201da177e4SLinus Torvalds }
6211da177e4SLinus Torvalds
6220c81eed4SKay Sievers /* looks like: "pnp:dD" for every device of the card */
do_pnp_card_entries(void * symval,unsigned long size,struct module * mod)6230c81eed4SKay Sievers static void do_pnp_card_entries(void *symval, unsigned long size,
6240c81eed4SKay Sievers struct module *mod)
6251da177e4SLinus Torvalds {
6266543becfSAndreas Schwab const unsigned long id_size = SIZE_pnp_card_device_id;
6270c81eed4SKay Sievers const unsigned int count = (size / id_size)-1;
6280c81eed4SKay Sievers unsigned int i;
6291da177e4SLinus Torvalds
6300c81eed4SKay Sievers device_id_check(mod->name, "pnp", size, id_size, symval);
6310c81eed4SKay Sievers
6320c81eed4SKay Sievers for (i = 0; i < count; i++) {
6330c81eed4SKay Sievers unsigned int j;
6346543becfSAndreas Schwab DEF_FIELD_ADDR(symval + i * id_size, pnp_card_device_id, devs);
6350c81eed4SKay Sievers
6360c81eed4SKay Sievers for (j = 0; j < PNP_MAX_DEVICES; j++) {
6376543becfSAndreas Schwab const char *id = (char *)(*devs)[j].id;
6380c81eed4SKay Sievers int i2, j2;
6390c81eed4SKay Sievers int dup = 0;
6400c81eed4SKay Sievers
6410c81eed4SKay Sievers if (!id[0])
6421da177e4SLinus Torvalds break;
6430c81eed4SKay Sievers
6440c81eed4SKay Sievers /* find duplicate, already added value */
6450c81eed4SKay Sievers for (i2 = 0; i2 < i && !dup; i2++) {
646c2b1a922SLeonardo Bras DEF_FIELD_ADDR_VAR(symval + i2 * id_size,
647c2b1a922SLeonardo Bras pnp_card_device_id,
648c2b1a922SLeonardo Bras devs, devs_dup);
6490c81eed4SKay Sievers
6500c81eed4SKay Sievers for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
651c2b1a922SLeonardo Bras const char *id2 =
652c2b1a922SLeonardo Bras (char *)(*devs_dup)[j2].id;
6530c81eed4SKay Sievers
6540c81eed4SKay Sievers if (!id2[0])
6550c81eed4SKay Sievers break;
6560c81eed4SKay Sievers
6570c81eed4SKay Sievers if (!strcmp(id, id2)) {
6580c81eed4SKay Sievers dup = 1;
6590c81eed4SKay Sievers break;
6601da177e4SLinus Torvalds }
6610c81eed4SKay Sievers }
6620c81eed4SKay Sievers }
6630c81eed4SKay Sievers
6640c81eed4SKay Sievers /* add an individual alias for every device entry */
66522454cb9SKay Sievers if (!dup) {
6666543becfSAndreas Schwab char acpi_id[PNP_ID_LEN];
66772638f59SKay Sievers int k;
66872638f59SKay Sievers
6690c81eed4SKay Sievers buf_printf(&mod->dev_table_buf,
6700c81eed4SKay Sievers "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
67172638f59SKay Sievers
67272638f59SKay Sievers /* fix broken pnp bus lowercasing */
67372638f59SKay Sievers for (k = 0; k < sizeof(acpi_id); k++)
67472638f59SKay Sievers acpi_id[k] = toupper(id[k]);
67522454cb9SKay Sievers buf_printf(&mod->dev_table_buf,
67672638f59SKay Sievers "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
67722454cb9SKay Sievers }
6780c81eed4SKay Sievers }
6790c81eed4SKay Sievers }
6801da177e4SLinus Torvalds }
6811da177e4SLinus Torvalds
68290829cfeSDominik Brodowski /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
do_pcmcia_entry(const char * filename,void * symval,char * alias)68390829cfeSDominik Brodowski static int do_pcmcia_entry(const char *filename,
6846543becfSAndreas Schwab void *symval, char *alias)
68590829cfeSDominik Brodowski {
68690829cfeSDominik Brodowski unsigned int i;
6876543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, match_flags);
6886543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, manf_id);
6896543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, card_id);
6906543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, func_id);
6916543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, function);
6926543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, device_no);
6936543becfSAndreas Schwab DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash);
6944fb7edceSKars de Jong
69590829cfeSDominik Brodowski for (i=0; i<4; i++) {
6966543becfSAndreas Schwab (*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]);
69790829cfeSDominik Brodowski }
69890829cfeSDominik Brodowski
69990829cfeSDominik Brodowski strcpy(alias, "pcmcia:");
7006543becfSAndreas Schwab ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
7016543becfSAndreas Schwab manf_id);
7026543becfSAndreas Schwab ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
7036543becfSAndreas Schwab card_id);
7046543becfSAndreas Schwab ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
7056543becfSAndreas Schwab func_id);
7066543becfSAndreas Schwab ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
7076543becfSAndreas Schwab function);
7086543becfSAndreas Schwab ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
7096543becfSAndreas Schwab device_no);
7106543becfSAndreas Schwab ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]);
7116543becfSAndreas Schwab ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]);
7126543becfSAndreas Schwab ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]);
7136543becfSAndreas Schwab ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]);
71490829cfeSDominik Brodowski
715ac551828SJean Delvare add_wildcard(alias);
71690829cfeSDominik Brodowski return 1;
71790829cfeSDominik Brodowski }
71890829cfeSDominik Brodowski
do_vio_entry(const char * filename,void * symval,char * alias)7196543becfSAndreas Schwab static int do_vio_entry(const char *filename, void *symval,
720fb120da6SStephen Rothwell char *alias)
721fb120da6SStephen Rothwell {
722fb120da6SStephen Rothwell char *tmp;
7236543becfSAndreas Schwab DEF_FIELD_ADDR(symval, vio_device_id, type);
7246543becfSAndreas Schwab DEF_FIELD_ADDR(symval, vio_device_id, compat);
725fb120da6SStephen Rothwell
7266543becfSAndreas Schwab sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*",
7276543becfSAndreas Schwab (*compat)[0] ? *compat : "*");
728fb120da6SStephen Rothwell
729fb120da6SStephen Rothwell /* Replace all whitespace with underscores */
730fb120da6SStephen Rothwell for (tmp = alias; tmp && *tmp; tmp++)
731fb120da6SStephen Rothwell if (isspace (*tmp))
732fb120da6SStephen Rothwell *tmp = '_';
733fb120da6SStephen Rothwell
734ac551828SJean Delvare add_wildcard(alias);
735fb120da6SStephen Rothwell return 1;
736fb120da6SStephen Rothwell }
737fb120da6SStephen Rothwell
do_input(char * alias,kernel_ulong_t * arr,unsigned int min,unsigned int max)7381d8f430cSRusty Russell static void do_input(char *alias,
7391d8f430cSRusty Russell kernel_ulong_t *arr, unsigned int min, unsigned int max)
7401d8f430cSRusty Russell {
7411d8f430cSRusty Russell unsigned int i;
742ddc5d341SDmitry Torokhov
7436543becfSAndreas Schwab for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++)
7446543becfSAndreas Schwab arr[i] = TO_NATIVE(arr[i]);
745*bc6962f2SMasahiro Yamada for (i = min; i <= max; i++)
746f93e9ae0SMasahiro Yamada if (arr[i / BITS_PER_LONG] & (1ULL << (i%BITS_PER_LONG)))
7471d8f430cSRusty Russell sprintf(alias + strlen(alias), "%X,*", i);
7481d8f430cSRusty Russell }
7491d8f430cSRusty Russell
75009c3e01bSDmitry Torokhov /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
do_input_entry(const char * filename,void * symval,char * alias)7516543becfSAndreas Schwab static int do_input_entry(const char *filename, void *symval,
7521d8f430cSRusty Russell char *alias)
7531d8f430cSRusty Russell {
7546543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, flags);
7556543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, bustype);
7566543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, vendor);
7576543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, product);
7586543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, version);
7596543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, evbit);
7606543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, keybit);
7616543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, relbit);
7626543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, absbit);
7636543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, mscbit);
7646543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, ledbit);
7656543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, sndbit);
7666543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, ffbit);
7676543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, swbit);
7686543becfSAndreas Schwab
7691d8f430cSRusty Russell sprintf(alias, "input:");
7701d8f430cSRusty Russell
7716543becfSAndreas Schwab ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype);
7726543becfSAndreas Schwab ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor);
7736543becfSAndreas Schwab ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
7746543becfSAndreas Schwab ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version);
7751d8f430cSRusty Russell
7761d8f430cSRusty Russell sprintf(alias + strlen(alias), "-e*");
7776543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_EVBIT)
7786543becfSAndreas Schwab do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
7791d8f430cSRusty Russell sprintf(alias + strlen(alias), "k*");
7806543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
7816543becfSAndreas Schwab do_input(alias, *keybit,
782dc24f0e7SSam Ravnborg INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
783dc24f0e7SSam Ravnborg INPUT_DEVICE_ID_KEY_MAX);
7841d8f430cSRusty Russell sprintf(alias + strlen(alias), "r*");
7856543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_RELBIT)
7866543becfSAndreas Schwab do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
7871d8f430cSRusty Russell sprintf(alias + strlen(alias), "a*");
7886543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
7896543becfSAndreas Schwab do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
7901d8f430cSRusty Russell sprintf(alias + strlen(alias), "m*");
7916543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_MSCIT)
7926543becfSAndreas Schwab do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
7931d8f430cSRusty Russell sprintf(alias + strlen(alias), "l*");
7946543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
7956543becfSAndreas Schwab do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
7961d8f430cSRusty Russell sprintf(alias + strlen(alias), "s*");
7976543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
7986543becfSAndreas Schwab do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
7991d8f430cSRusty Russell sprintf(alias + strlen(alias), "f*");
8006543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_FFBIT)
8016543becfSAndreas Schwab do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
8021d8f430cSRusty Russell sprintf(alias + strlen(alias), "w*");
8036543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
8046543becfSAndreas Schwab do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
8051d8f430cSRusty Russell return 1;
8061d8f430cSRusty Russell }
8071d8f430cSRusty Russell
do_eisa_entry(const char * filename,void * symval,char * alias)8086543becfSAndreas Schwab static int do_eisa_entry(const char *filename, void *symval,
80907563c71SMichael Tokarev char *alias)
81007563c71SMichael Tokarev {
8116543becfSAndreas Schwab DEF_FIELD_ADDR(symval, eisa_device_id, sig);
8126543becfSAndreas Schwab sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
81307563c71SMichael Tokarev return 1;
81407563c71SMichael Tokarev }
81507563c71SMichael Tokarev
816f3cf2673SKyle McMartin /* Looks like: parisc:tNhvNrevNsvN */
do_parisc_entry(const char * filename,void * symval,char * alias)8176543becfSAndreas Schwab static int do_parisc_entry(const char *filename, void *symval,
818f3cf2673SKyle McMartin char *alias)
819f3cf2673SKyle McMartin {
8206543becfSAndreas Schwab DEF_FIELD(symval, parisc_device_id, hw_type);
8216543becfSAndreas Schwab DEF_FIELD(symval, parisc_device_id, hversion);
8226543becfSAndreas Schwab DEF_FIELD(symval, parisc_device_id, hversion_rev);
8236543becfSAndreas Schwab DEF_FIELD(symval, parisc_device_id, sversion);
824f3cf2673SKyle McMartin
825f3cf2673SKyle McMartin strcpy(alias, "parisc:");
8266543becfSAndreas Schwab ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
8276543becfSAndreas Schwab ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
8286543becfSAndreas Schwab ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
8296543becfSAndreas Schwab ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
830f3cf2673SKyle McMartin
831ac551828SJean Delvare add_wildcard(alias);
832f3cf2673SKyle McMartin return 1;
833f3cf2673SKyle McMartin }
834f3cf2673SKyle McMartin
835d59b66c7SPierre Ossman /* Looks like: sdio:cNvNdN. */
do_sdio_entry(const char * filename,void * symval,char * alias)836d59b66c7SPierre Ossman static int do_sdio_entry(const char *filename,
8376543becfSAndreas Schwab void *symval, char *alias)
838d59b66c7SPierre Ossman {
8396543becfSAndreas Schwab DEF_FIELD(symval, sdio_device_id, class);
8406543becfSAndreas Schwab DEF_FIELD(symval, sdio_device_id, vendor);
8416543becfSAndreas Schwab DEF_FIELD(symval, sdio_device_id, device);
842d59b66c7SPierre Ossman
843d59b66c7SPierre Ossman strcpy(alias, "sdio:");
8446543becfSAndreas Schwab ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
8456543becfSAndreas Schwab ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
8466543becfSAndreas Schwab ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
847ac551828SJean Delvare add_wildcard(alias);
848038a5008SLinus Torvalds return 1;
849038a5008SLinus Torvalds }
850d59b66c7SPierre Ossman
85161e115a5SMichael Buesch /* Looks like: ssb:vNidNrevN. */
do_ssb_entry(const char * filename,void * symval,char * alias)85261e115a5SMichael Buesch static int do_ssb_entry(const char *filename,
8536543becfSAndreas Schwab void *symval, char *alias)
85461e115a5SMichael Buesch {
8556543becfSAndreas Schwab DEF_FIELD(symval, ssb_device_id, vendor);
8566543becfSAndreas Schwab DEF_FIELD(symval, ssb_device_id, coreid);
8576543becfSAndreas Schwab DEF_FIELD(symval, ssb_device_id, revision);
85861e115a5SMichael Buesch
85961e115a5SMichael Buesch strcpy(alias, "ssb:");
8606543becfSAndreas Schwab ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
8616543becfSAndreas Schwab ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
8626543becfSAndreas Schwab ADD(alias, "rev", revision != SSB_ANY_REV, revision);
863ac551828SJean Delvare add_wildcard(alias);
864d59b66c7SPierre Ossman return 1;
865d59b66c7SPierre Ossman }
866d59b66c7SPierre Ossman
8678369ae33SRafał Miłecki /* Looks like: bcma:mNidNrevNclN. */
do_bcma_entry(const char * filename,void * symval,char * alias)8688369ae33SRafał Miłecki static int do_bcma_entry(const char *filename,
8696543becfSAndreas Schwab void *symval, char *alias)
8708369ae33SRafał Miłecki {
8716543becfSAndreas Schwab DEF_FIELD(symval, bcma_device_id, manuf);
8726543becfSAndreas Schwab DEF_FIELD(symval, bcma_device_id, id);
8736543becfSAndreas Schwab DEF_FIELD(symval, bcma_device_id, rev);
8746543becfSAndreas Schwab DEF_FIELD(symval, bcma_device_id, class);
8758369ae33SRafał Miłecki
8768369ae33SRafał Miłecki strcpy(alias, "bcma:");
8776543becfSAndreas Schwab ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
8786543becfSAndreas Schwab ADD(alias, "id", id != BCMA_ANY_ID, id);
8796543becfSAndreas Schwab ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
8806543becfSAndreas Schwab ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
8818369ae33SRafał Miłecki add_wildcard(alias);
8828369ae33SRafał Miłecki return 1;
8838369ae33SRafał Miłecki }
8848369ae33SRafał Miłecki
885b01d9f28SRusty Russell /* Looks like: virtio:dNvN */
do_virtio_entry(const char * filename,void * symval,char * alias)8866543becfSAndreas Schwab static int do_virtio_entry(const char *filename, void *symval,
887b01d9f28SRusty Russell char *alias)
888b01d9f28SRusty Russell {
8896543becfSAndreas Schwab DEF_FIELD(symval, virtio_device_id, device);
8906543becfSAndreas Schwab DEF_FIELD(symval, virtio_device_id, vendor);
891b01d9f28SRusty Russell
892b01d9f28SRusty Russell strcpy(alias, "virtio:");
8936543becfSAndreas Schwab ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
8946543becfSAndreas Schwab ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
895b01d9f28SRusty Russell
896ac551828SJean Delvare add_wildcard(alias);
897b01d9f28SRusty Russell return 1;
898b01d9f28SRusty Russell }
899b01d9f28SRusty Russell
900d2ee52aaSK. Y. Srinivasan /*
901d2ee52aaSK. Y. Srinivasan * Looks like: vmbus:guid
902d2ee52aaSK. Y. Srinivasan * Each byte of the guid will be represented by two hex characters
903d2ee52aaSK. Y. Srinivasan * in the name.
904d2ee52aaSK. Y. Srinivasan */
905d2ee52aaSK. Y. Srinivasan
do_vmbus_entry(const char * filename,void * symval,char * alias)9066543becfSAndreas Schwab static int do_vmbus_entry(const char *filename, void *symval,
907d2ee52aaSK. Y. Srinivasan char *alias)
908d2ee52aaSK. Y. Srinivasan {
909d2ee52aaSK. Y. Srinivasan int i;
9106543becfSAndreas Schwab DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
9116543becfSAndreas Schwab char guid_name[(sizeof(*guid) + 1) * 2];
912d2ee52aaSK. Y. Srinivasan
9136543becfSAndreas Schwab for (i = 0; i < (sizeof(*guid) * 2); i += 2)
914af3ff643SK. Y. Srinivasan sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2]));
915d2ee52aaSK. Y. Srinivasan
916d2ee52aaSK. Y. Srinivasan strcpy(alias, "vmbus:");
917d2ee52aaSK. Y. Srinivasan strcat(alias, guid_name);
918d2ee52aaSK. Y. Srinivasan
919d2ee52aaSK. Y. Srinivasan return 1;
920d2ee52aaSK. Y. Srinivasan }
921d2ee52aaSK. Y. Srinivasan
9225b7d1277SAndrew F. Davis /* Looks like: rpmsg:S */
do_rpmsg_entry(const char * filename,void * symval,char * alias)9235b7d1277SAndrew F. Davis static int do_rpmsg_entry(const char *filename, void *symval,
9245b7d1277SAndrew F. Davis char *alias)
9255b7d1277SAndrew F. Davis {
9265b7d1277SAndrew F. Davis DEF_FIELD_ADDR(symval, rpmsg_device_id, name);
9275b7d1277SAndrew F. Davis sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name);
9285b7d1277SAndrew F. Davis
9295b7d1277SAndrew F. Davis return 1;
9305b7d1277SAndrew F. Davis }
9315b7d1277SAndrew F. Davis
932d2653e92SJean Delvare /* Looks like: i2c:S */
do_i2c_entry(const char * filename,void * symval,char * alias)9336543becfSAndreas Schwab static int do_i2c_entry(const char *filename, void *symval,
934d2653e92SJean Delvare char *alias)
935d2653e92SJean Delvare {
9366543becfSAndreas Schwab DEF_FIELD_ADDR(symval, i2c_device_id, name);
9376543becfSAndreas Schwab sprintf(alias, I2C_MODULE_PREFIX "%s", *name);
938d2653e92SJean Delvare
939d2653e92SJean Delvare return 1;
940d2653e92SJean Delvare }
941d2653e92SJean Delvare
do_i3c_entry(const char * filename,void * symval,char * alias)9421ce589adSBoris Brezillon static int do_i3c_entry(const char *filename, void *symval,
9431ce589adSBoris Brezillon char *alias)
9441ce589adSBoris Brezillon {
9451ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, match_flags);
9461ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, dcr);
9471ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, manuf_id);
9481ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, part_id);
9491ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, extra_info);
9501ce589adSBoris Brezillon
9511ce589adSBoris Brezillon strcpy(alias, "i3c:");
9521ce589adSBoris Brezillon ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr);
9531ce589adSBoris Brezillon ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id);
9541ce589adSBoris Brezillon ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id);
9551ce589adSBoris Brezillon ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info);
9561ce589adSBoris Brezillon
9571ce589adSBoris Brezillon return 1;
9581ce589adSBoris Brezillon }
9591ce589adSBoris Brezillon
960e0626e38SAnton Vorontsov /* Looks like: spi:S */
do_spi_entry(const char * filename,void * symval,char * alias)9616543becfSAndreas Schwab static int do_spi_entry(const char *filename, void *symval,
96275368bf6SAnton Vorontsov char *alias)
96375368bf6SAnton Vorontsov {
9646543becfSAndreas Schwab DEF_FIELD_ADDR(symval, spi_device_id, name);
9656543becfSAndreas Schwab sprintf(alias, SPI_MODULE_PREFIX "%s", *name);
96675368bf6SAnton Vorontsov
96775368bf6SAnton Vorontsov return 1;
96875368bf6SAnton Vorontsov }
96975368bf6SAnton Vorontsov
970d945b697SDavid Woodhouse static const struct dmifield {
971d945b697SDavid Woodhouse const char *prefix;
972d945b697SDavid Woodhouse int field;
973d945b697SDavid Woodhouse } dmi_fields[] = {
974d945b697SDavid Woodhouse { "bvn", DMI_BIOS_VENDOR },
975d945b697SDavid Woodhouse { "bvr", DMI_BIOS_VERSION },
976d945b697SDavid Woodhouse { "bd", DMI_BIOS_DATE },
977f5152f4dSErwan Velu { "br", DMI_BIOS_RELEASE },
978f5152f4dSErwan Velu { "efr", DMI_EC_FIRMWARE_RELEASE },
979d945b697SDavid Woodhouse { "svn", DMI_SYS_VENDOR },
980d945b697SDavid Woodhouse { "pn", DMI_PRODUCT_NAME },
981d945b697SDavid Woodhouse { "pvr", DMI_PRODUCT_VERSION },
982d945b697SDavid Woodhouse { "rvn", DMI_BOARD_VENDOR },
983d945b697SDavid Woodhouse { "rn", DMI_BOARD_NAME },
984d945b697SDavid Woodhouse { "rvr", DMI_BOARD_VERSION },
985d945b697SDavid Woodhouse { "cvn", DMI_CHASSIS_VENDOR },
986d945b697SDavid Woodhouse { "ct", DMI_CHASSIS_TYPE },
987d945b697SDavid Woodhouse { "cvr", DMI_CHASSIS_VERSION },
988d945b697SDavid Woodhouse { NULL, DMI_NONE }
989d945b697SDavid Woodhouse };
990d945b697SDavid Woodhouse
dmi_ascii_filter(char * d,const char * s)991d945b697SDavid Woodhouse static void dmi_ascii_filter(char *d, const char *s)
992d945b697SDavid Woodhouse {
993d945b697SDavid Woodhouse /* Filter out characters we don't want to see in the modalias string */
994d945b697SDavid Woodhouse for (; *s; s++)
995d945b697SDavid Woodhouse if (*s > ' ' && *s < 127 && *s != ':')
996d945b697SDavid Woodhouse *(d++) = *s;
997d945b697SDavid Woodhouse
998d945b697SDavid Woodhouse *d = 0;
999d945b697SDavid Woodhouse }
1000d945b697SDavid Woodhouse
1001d945b697SDavid Woodhouse
do_dmi_entry(const char * filename,void * symval,char * alias)10026543becfSAndreas Schwab static int do_dmi_entry(const char *filename, void *symval,
1003d945b697SDavid Woodhouse char *alias)
1004d945b697SDavid Woodhouse {
1005d945b697SDavid Woodhouse int i, j;
10066543becfSAndreas Schwab DEF_FIELD_ADDR(symval, dmi_system_id, matches);
1007d945b697SDavid Woodhouse sprintf(alias, "dmi*");
1008d945b697SDavid Woodhouse
1009d945b697SDavid Woodhouse for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
1010d945b697SDavid Woodhouse for (j = 0; j < 4; j++) {
10116543becfSAndreas Schwab if ((*matches)[j].slot &&
10126543becfSAndreas Schwab (*matches)[j].slot == dmi_fields[i].field) {
1013d945b697SDavid Woodhouse sprintf(alias + strlen(alias), ":%s*",
1014d945b697SDavid Woodhouse dmi_fields[i].prefix);
1015d945b697SDavid Woodhouse dmi_ascii_filter(alias + strlen(alias),
10166543becfSAndreas Schwab (*matches)[j].substr);
1017d945b697SDavid Woodhouse strcat(alias, "*");
1018d945b697SDavid Woodhouse }
1019d945b697SDavid Woodhouse }
1020d945b697SDavid Woodhouse }
1021d945b697SDavid Woodhouse
1022d945b697SDavid Woodhouse strcat(alias, ":");
1023d945b697SDavid Woodhouse return 1;
1024d945b697SDavid Woodhouse }
102557fee4a5SEric Miao
do_platform_entry(const char * filename,void * symval,char * alias)102657fee4a5SEric Miao static int do_platform_entry(const char *filename,
10276543becfSAndreas Schwab void *symval, char *alias)
102857fee4a5SEric Miao {
10296543becfSAndreas Schwab DEF_FIELD_ADDR(symval, platform_device_id, name);
10306543becfSAndreas Schwab sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name);
103157fee4a5SEric Miao return 1;
103257fee4a5SEric Miao }
103357fee4a5SEric Miao
do_mdio_entry(const char * filename,void * symval,char * alias)10348626d3b4SDavid Woodhouse static int do_mdio_entry(const char *filename,
10356543becfSAndreas Schwab void *symval, char *alias)
10368626d3b4SDavid Woodhouse {
10378626d3b4SDavid Woodhouse int i;
10386543becfSAndreas Schwab DEF_FIELD(symval, mdio_device_id, phy_id);
10396543becfSAndreas Schwab DEF_FIELD(symval, mdio_device_id, phy_id_mask);
10408626d3b4SDavid Woodhouse
10418626d3b4SDavid Woodhouse alias += sprintf(alias, MDIO_MODULE_PREFIX);
10428626d3b4SDavid Woodhouse
10438626d3b4SDavid Woodhouse for (i = 0; i < 32; i++) {
10446543becfSAndreas Schwab if (!((phy_id_mask >> (31-i)) & 1))
10458626d3b4SDavid Woodhouse *(alias++) = '?';
10466543becfSAndreas Schwab else if ((phy_id >> (31-i)) & 1)
10478626d3b4SDavid Woodhouse *(alias++) = '1';
10488626d3b4SDavid Woodhouse else
10498626d3b4SDavid Woodhouse *(alias++) = '0';
10508626d3b4SDavid Woodhouse }
10518626d3b4SDavid Woodhouse
10528626d3b4SDavid Woodhouse /* Terminate the string */
10538626d3b4SDavid Woodhouse *alias = 0;
10548626d3b4SDavid Woodhouse
10558626d3b4SDavid Woodhouse return 1;
10568626d3b4SDavid Woodhouse }
10578626d3b4SDavid Woodhouse
1058bf54a2b3SGeert Uytterhoeven /* Looks like: zorro:iN. */
do_zorro_entry(const char * filename,void * symval,char * alias)10596543becfSAndreas Schwab static int do_zorro_entry(const char *filename, void *symval,
1060bf54a2b3SGeert Uytterhoeven char *alias)
1061bf54a2b3SGeert Uytterhoeven {
10626543becfSAndreas Schwab DEF_FIELD(symval, zorro_device_id, id);
1063bf54a2b3SGeert Uytterhoeven strcpy(alias, "zorro:");
10646543becfSAndreas Schwab ADD(alias, "i", id != ZORRO_WILDCARD, id);
1065bf54a2b3SGeert Uytterhoeven return 1;
1066bf54a2b3SGeert Uytterhoeven }
1067bf54a2b3SGeert Uytterhoeven
1068fedb3d27SOndrej Zary /* looks like: "pnp:dD" */
do_isapnp_entry(const char * filename,void * symval,char * alias)1069fedb3d27SOndrej Zary static int do_isapnp_entry(const char *filename,
10706543becfSAndreas Schwab void *symval, char *alias)
1071fedb3d27SOndrej Zary {
10726543becfSAndreas Schwab DEF_FIELD(symval, isapnp_device_id, vendor);
10736543becfSAndreas Schwab DEF_FIELD(symval, isapnp_device_id, function);
1074fedb3d27SOndrej Zary sprintf(alias, "pnp:d%c%c%c%x%x%x%x*",
10756543becfSAndreas Schwab 'A' + ((vendor >> 2) & 0x3f) - 1,
10766543becfSAndreas Schwab 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
10776543becfSAndreas Schwab 'A' + ((vendor >> 8) & 0x1f) - 1,
10786543becfSAndreas Schwab (function >> 4) & 0x0f, function & 0x0f,
10796543becfSAndreas Schwab (function >> 12) & 0x0f, (function >> 8) & 0x0f);
1080fedb3d27SOndrej Zary return 1;
1081fedb3d27SOndrej Zary }
1082fedb3d27SOndrej Zary
1083849e0ad2SJens Taprogge /* Looks like: "ipack:fNvNdN". */
do_ipack_entry(const char * filename,void * symval,char * alias)1084849e0ad2SJens Taprogge static int do_ipack_entry(const char *filename,
10856543becfSAndreas Schwab void *symval, char *alias)
1086849e0ad2SJens Taprogge {
10876543becfSAndreas Schwab DEF_FIELD(symval, ipack_device_id, format);
10886543becfSAndreas Schwab DEF_FIELD(symval, ipack_device_id, vendor);
10896543becfSAndreas Schwab DEF_FIELD(symval, ipack_device_id, device);
1090849e0ad2SJens Taprogge strcpy(alias, "ipack:");
10916543becfSAndreas Schwab ADD(alias, "f", format != IPACK_ANY_FORMAT, format);
10926543becfSAndreas Schwab ADD(alias, "v", vendor != IPACK_ANY_ID, vendor);
10936543becfSAndreas Schwab ADD(alias, "d", device != IPACK_ANY_ID, device);
1094849e0ad2SJens Taprogge add_wildcard(alias);
1095849e0ad2SJens Taprogge return 1;
1096849e0ad2SJens Taprogge }
1097849e0ad2SJens Taprogge
1098523817bdSDave Martin /*
1099523817bdSDave Martin * Append a match expression for a single masked hex digit.
1100523817bdSDave Martin * outp points to a pointer to the character at which to append.
1101523817bdSDave Martin * *outp is updated on return to point just after the appended text,
1102523817bdSDave Martin * to facilitate further appending.
1103523817bdSDave Martin */
append_nibble_mask(char ** outp,unsigned int nibble,unsigned int mask)1104523817bdSDave Martin static void append_nibble_mask(char **outp,
1105523817bdSDave Martin unsigned int nibble, unsigned int mask)
1106523817bdSDave Martin {
1107523817bdSDave Martin char *p = *outp;
1108523817bdSDave Martin unsigned int i;
1109523817bdSDave Martin
1110523817bdSDave Martin switch (mask) {
1111523817bdSDave Martin case 0:
1112523817bdSDave Martin *p++ = '?';
1113523817bdSDave Martin break;
1114523817bdSDave Martin
1115523817bdSDave Martin case 0xf:
1116523817bdSDave Martin p += sprintf(p, "%X", nibble);
1117523817bdSDave Martin break;
1118523817bdSDave Martin
1119523817bdSDave Martin default:
1120523817bdSDave Martin /*
1121523817bdSDave Martin * Dumbly emit a match pattern for all possible matching
1122523817bdSDave Martin * digits. This could be improved in some cases using ranges,
1123523817bdSDave Martin * but it has the advantage of being trivially correct, and is
1124523817bdSDave Martin * often optimal.
1125523817bdSDave Martin */
1126523817bdSDave Martin *p++ = '[';
1127523817bdSDave Martin for (i = 0; i < 0x10; i++)
1128523817bdSDave Martin if ((i & mask) == nibble)
1129523817bdSDave Martin p += sprintf(p, "%X", i);
1130523817bdSDave Martin *p++ = ']';
1131523817bdSDave Martin }
1132523817bdSDave Martin
1133523817bdSDave Martin /* Ensure that the string remains NUL-terminated: */
1134523817bdSDave Martin *p = '\0';
1135523817bdSDave Martin
1136523817bdSDave Martin /* Advance the caller's end-of-string pointer: */
1137523817bdSDave Martin *outp = p;
1138523817bdSDave Martin }
1139523817bdSDave Martin
1140523817bdSDave Martin /*
1141523817bdSDave Martin * looks like: "amba:dN"
1142523817bdSDave Martin *
1143523817bdSDave Martin * N is exactly 8 digits, where each is an upper-case hex digit, or
1144523817bdSDave Martin * a ? or [] pattern matching exactly one digit.
1145523817bdSDave Martin */
do_amba_entry(const char * filename,void * symval,char * alias)1146523817bdSDave Martin static int do_amba_entry(const char *filename,
11476543becfSAndreas Schwab void *symval, char *alias)
1148523817bdSDave Martin {
1149523817bdSDave Martin unsigned int digit;
1150523817bdSDave Martin char *p = alias;
11516543becfSAndreas Schwab DEF_FIELD(symval, amba_id, id);
11526543becfSAndreas Schwab DEF_FIELD(symval, amba_id, mask);
1153523817bdSDave Martin
11546543becfSAndreas Schwab if ((id & mask) != id)
11550d2573a2SGeert Uytterhoeven fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: id=0x%08X, mask=0x%08X. Please fix this driver.\n",
11566543becfSAndreas Schwab filename, id, mask);
1157523817bdSDave Martin
1158523817bdSDave Martin p += sprintf(alias, "amba:d");
1159523817bdSDave Martin for (digit = 0; digit < 8; digit++)
1160523817bdSDave Martin append_nibble_mask(&p,
11616543becfSAndreas Schwab (id >> (4 * (7 - digit))) & 0xf,
11626543becfSAndreas Schwab (mask >> (4 * (7 - digit))) & 0xf);
1163523817bdSDave Martin
1164523817bdSDave Martin return 1;
1165523817bdSDave Martin }
1166523817bdSDave Martin
11678286ae03SJames Hogan /*
11688286ae03SJames Hogan * looks like: "mipscdmm:tN"
11698286ae03SJames Hogan *
11708286ae03SJames Hogan * N is exactly 2 digits, where each is an upper-case hex digit, or
11718286ae03SJames Hogan * a ? or [] pattern matching exactly one digit.
11728286ae03SJames Hogan */
do_mips_cdmm_entry(const char * filename,void * symval,char * alias)11738286ae03SJames Hogan static int do_mips_cdmm_entry(const char *filename,
11748286ae03SJames Hogan void *symval, char *alias)
11758286ae03SJames Hogan {
11768286ae03SJames Hogan DEF_FIELD(symval, mips_cdmm_device_id, type);
11778286ae03SJames Hogan
11788286ae03SJames Hogan sprintf(alias, "mipscdmm:t%02X*", type);
11798286ae03SJames Hogan return 1;
11808286ae03SJames Hogan }
11818286ae03SJames Hogan
11822b9c1f03SArd Biesheuvel /* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
1183644e9cbbSAndi Kleen * All fields are numbers. It would be nicer to use strings for vendor
1184644e9cbbSAndi Kleen * and feature, but getting those out of the build system here is too
1185644e9cbbSAndi Kleen * complicated.
1186644e9cbbSAndi Kleen */
1187644e9cbbSAndi Kleen
do_x86cpu_entry(const char * filename,void * symval,char * alias)11886543becfSAndreas Schwab static int do_x86cpu_entry(const char *filename, void *symval,
1189644e9cbbSAndi Kleen char *alias)
1190644e9cbbSAndi Kleen {
11916543becfSAndreas Schwab DEF_FIELD(symval, x86_cpu_id, feature);
11926543becfSAndreas Schwab DEF_FIELD(symval, x86_cpu_id, family);
11936543becfSAndreas Schwab DEF_FIELD(symval, x86_cpu_id, model);
11946543becfSAndreas Schwab DEF_FIELD(symval, x86_cpu_id, vendor);
1195644e9cbbSAndi Kleen
11962b9c1f03SArd Biesheuvel strcpy(alias, "cpu:type:x86,");
11972b9c1f03SArd Biesheuvel ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
11982b9c1f03SArd Biesheuvel ADD(alias, "fam", family != X86_FAMILY_ANY, family);
11992b9c1f03SArd Biesheuvel ADD(alias, "mod", model != X86_MODEL_ANY, model);
12005467bddaSBen Hutchings strcat(alias, ":feature:*");
12016543becfSAndreas Schwab if (feature != X86_FEATURE_ANY)
12026543becfSAndreas Schwab sprintf(alias + strlen(alias), "%04X*", feature);
1203644e9cbbSAndi Kleen return 1;
1204644e9cbbSAndi Kleen }
1205644e9cbbSAndi Kleen
120667bad2fdSArd Biesheuvel /* LOOKS like cpu:type:*:feature:*FEAT* */
do_cpu_entry(const char * filename,void * symval,char * alias)120767bad2fdSArd Biesheuvel static int do_cpu_entry(const char *filename, void *symval, char *alias)
120867bad2fdSArd Biesheuvel {
120967bad2fdSArd Biesheuvel DEF_FIELD(symval, cpu_feature, feature);
121067bad2fdSArd Biesheuvel
121167bad2fdSArd Biesheuvel sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
121267bad2fdSArd Biesheuvel return 1;
121367bad2fdSArd Biesheuvel }
121467bad2fdSArd Biesheuvel
1215b26864caSTomas Winkler /* Looks like: mei:S:uuid:N:* */
do_mei_entry(const char * filename,void * symval,char * alias)1216e5354107SSamuel Ortiz static int do_mei_entry(const char *filename, void *symval,
1217e5354107SSamuel Ortiz char *alias)
1218e5354107SSamuel Ortiz {
1219e5354107SSamuel Ortiz DEF_FIELD_ADDR(symval, mei_cl_device_id, name);
1220c93b76b3STomas Winkler DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid);
1221b26864caSTomas Winkler DEF_FIELD(symval, mei_cl_device_id, version);
1222e5354107SSamuel Ortiz
1223c93b76b3STomas Winkler sprintf(alias, MEI_CL_MODULE_PREFIX);
1224c93b76b3STomas Winkler sprintf(alias + strlen(alias), "%s:", (*name)[0] ? *name : "*");
1225c93b76b3STomas Winkler add_uuid(alias, *uuid);
1226b26864caSTomas Winkler ADD(alias, ":", version != MEI_CL_VERSION_ANY, version);
1227c93b76b3STomas Winkler
1228c93b76b3STomas Winkler strcat(alias, ":*");
1229e5354107SSamuel Ortiz
1230e5354107SSamuel Ortiz return 1;
1231e5354107SSamuel Ortiz }
1232e5354107SSamuel Ortiz
12333bdbb62fSAlexandre Bounine /* Looks like: rapidio:vNdNavNadN */
do_rio_entry(const char * filename,void * symval,char * alias)12343bdbb62fSAlexandre Bounine static int do_rio_entry(const char *filename,
12353bdbb62fSAlexandre Bounine void *symval, char *alias)
12363bdbb62fSAlexandre Bounine {
12373bdbb62fSAlexandre Bounine DEF_FIELD(symval, rio_device_id, did);
12383bdbb62fSAlexandre Bounine DEF_FIELD(symval, rio_device_id, vid);
12393bdbb62fSAlexandre Bounine DEF_FIELD(symval, rio_device_id, asm_did);
12403bdbb62fSAlexandre Bounine DEF_FIELD(symval, rio_device_id, asm_vid);
12413bdbb62fSAlexandre Bounine
12423bdbb62fSAlexandre Bounine strcpy(alias, "rapidio:");
12433bdbb62fSAlexandre Bounine ADD(alias, "v", vid != RIO_ANY_ID, vid);
12443bdbb62fSAlexandre Bounine ADD(alias, "d", did != RIO_ANY_ID, did);
12453bdbb62fSAlexandre Bounine ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid);
12463bdbb62fSAlexandre Bounine ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did);
12473bdbb62fSAlexandre Bounine
12483bdbb62fSAlexandre Bounine add_wildcard(alias);
12493bdbb62fSAlexandre Bounine return 1;
12503bdbb62fSAlexandre Bounine }
12513bdbb62fSAlexandre Bounine
1252289fcff4SHeikki Krogerus /* Looks like: ulpi:vNpN */
do_ulpi_entry(const char * filename,void * symval,char * alias)1253289fcff4SHeikki Krogerus static int do_ulpi_entry(const char *filename, void *symval,
1254289fcff4SHeikki Krogerus char *alias)
1255289fcff4SHeikki Krogerus {
1256289fcff4SHeikki Krogerus DEF_FIELD(symval, ulpi_device_id, vendor);
1257289fcff4SHeikki Krogerus DEF_FIELD(symval, ulpi_device_id, product);
1258289fcff4SHeikki Krogerus
1259289fcff4SHeikki Krogerus sprintf(alias, "ulpi:v%04xp%04x", vendor, product);
1260289fcff4SHeikki Krogerus
1261289fcff4SHeikki Krogerus return 1;
1262289fcff4SHeikki Krogerus }
1263289fcff4SHeikki Krogerus
1264da23ac1eSSubhransu S. Prusty /* Looks like: hdaudio:vNrNaN */
do_hda_entry(const char * filename,void * symval,char * alias)1265da23ac1eSSubhransu S. Prusty static int do_hda_entry(const char *filename, void *symval, char *alias)
1266da23ac1eSSubhransu S. Prusty {
1267da23ac1eSSubhransu S. Prusty DEF_FIELD(symval, hda_device_id, vendor_id);
1268da23ac1eSSubhransu S. Prusty DEF_FIELD(symval, hda_device_id, rev_id);
1269da23ac1eSSubhransu S. Prusty DEF_FIELD(symval, hda_device_id, api_version);
1270da23ac1eSSubhransu S. Prusty
1271da23ac1eSSubhransu S. Prusty strcpy(alias, "hdaudio:");
1272da23ac1eSSubhransu S. Prusty ADD(alias, "v", vendor_id != 0, vendor_id);
1273da23ac1eSSubhransu S. Prusty ADD(alias, "r", rev_id != 0, rev_id);
1274da23ac1eSSubhransu S. Prusty ADD(alias, "a", api_version != 0, api_version);
1275da23ac1eSSubhransu S. Prusty
1276da23ac1eSSubhransu S. Prusty add_wildcard(alias);
1277da23ac1eSSubhransu S. Prusty return 1;
1278da23ac1eSSubhransu S. Prusty }
1279da23ac1eSSubhransu S. Prusty
1280b5924268SPierre-Louis Bossart /* Looks like: sdw:mNpNvNcN */
do_sdw_entry(const char * filename,void * symval,char * alias)12819251345dSVinod Koul static int do_sdw_entry(const char *filename, void *symval, char *alias)
12829251345dSVinod Koul {
12839251345dSVinod Koul DEF_FIELD(symval, sdw_device_id, mfg_id);
12849251345dSVinod Koul DEF_FIELD(symval, sdw_device_id, part_id);
1285b5924268SPierre-Louis Bossart DEF_FIELD(symval, sdw_device_id, sdw_version);
1286b5924268SPierre-Louis Bossart DEF_FIELD(symval, sdw_device_id, class_id);
12879251345dSVinod Koul
12889251345dSVinod Koul strcpy(alias, "sdw:");
12899251345dSVinod Koul ADD(alias, "m", mfg_id != 0, mfg_id);
12909251345dSVinod Koul ADD(alias, "p", part_id != 0, part_id);
1291b5924268SPierre-Louis Bossart ADD(alias, "v", sdw_version != 0, sdw_version);
1292b5924268SPierre-Louis Bossart ADD(alias, "c", class_id != 0, class_id);
12939251345dSVinod Koul
12949251345dSVinod Koul add_wildcard(alias);
12959251345dSVinod Koul return 1;
12969251345dSVinod Koul }
12979251345dSVinod Koul
12980afef456SStuart Yoder /* Looks like: fsl-mc:vNdN */
do_fsl_mc_entry(const char * filename,void * symval,char * alias)12990afef456SStuart Yoder static int do_fsl_mc_entry(const char *filename, void *symval,
13000afef456SStuart Yoder char *alias)
13010afef456SStuart Yoder {
13020afef456SStuart Yoder DEF_FIELD(symval, fsl_mc_device_id, vendor);
13030afef456SStuart Yoder DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type);
13040afef456SStuart Yoder
13050afef456SStuart Yoder sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type);
13060afef456SStuart Yoder return 1;
13070afef456SStuart Yoder }
13080afef456SStuart Yoder
1309d1ff7024SMika Westerberg /* Looks like: tbsvc:kSpNvNrN */
do_tbsvc_entry(const char * filename,void * symval,char * alias)1310d1ff7024SMika Westerberg static int do_tbsvc_entry(const char *filename, void *symval, char *alias)
1311d1ff7024SMika Westerberg {
1312d1ff7024SMika Westerberg DEF_FIELD(symval, tb_service_id, match_flags);
1313d1ff7024SMika Westerberg DEF_FIELD_ADDR(symval, tb_service_id, protocol_key);
1314d1ff7024SMika Westerberg DEF_FIELD(symval, tb_service_id, protocol_id);
1315d1ff7024SMika Westerberg DEF_FIELD(symval, tb_service_id, protocol_version);
1316d1ff7024SMika Westerberg DEF_FIELD(symval, tb_service_id, protocol_revision);
1317d1ff7024SMika Westerberg
1318d1ff7024SMika Westerberg strcpy(alias, "tbsvc:");
1319d1ff7024SMika Westerberg if (match_flags & TBSVC_MATCH_PROTOCOL_KEY)
1320d1ff7024SMika Westerberg sprintf(alias + strlen(alias), "k%s", *protocol_key);
1321d1ff7024SMika Westerberg else
1322d1ff7024SMika Westerberg strcat(alias + strlen(alias), "k*");
1323d1ff7024SMika Westerberg ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id);
1324d1ff7024SMika Westerberg ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION,
1325d1ff7024SMika Westerberg protocol_version);
1326d1ff7024SMika Westerberg ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION,
1327d1ff7024SMika Westerberg protocol_revision);
1328d1ff7024SMika Westerberg
1329d1ff7024SMika Westerberg add_wildcard(alias);
1330d1ff7024SMika Westerberg return 1;
1331d1ff7024SMika Westerberg }
1332d1ff7024SMika Westerberg
13338a37d87dSHeikki Krogerus /* Looks like: typec:idNmN */
do_typec_entry(const char * filename,void * symval,char * alias)13348a37d87dSHeikki Krogerus static int do_typec_entry(const char *filename, void *symval, char *alias)
13358a37d87dSHeikki Krogerus {
13368a37d87dSHeikki Krogerus DEF_FIELD(symval, typec_device_id, svid);
13378a37d87dSHeikki Krogerus DEF_FIELD(symval, typec_device_id, mode);
13388a37d87dSHeikki Krogerus
13398a37d87dSHeikki Krogerus sprintf(alias, "typec:id%04X", svid);
13408a37d87dSHeikki Krogerus ADD(alias, "m", mode != TYPEC_ANY_MODE, mode);
13418a37d87dSHeikki Krogerus
13428a37d87dSHeikki Krogerus return 1;
13438a37d87dSHeikki Krogerus }
13448a37d87dSHeikki Krogerus
13450fc1db9dSSumit Garg /* Looks like: tee:uuid */
do_tee_entry(const char * filename,void * symval,char * alias)13460fc1db9dSSumit Garg static int do_tee_entry(const char *filename, void *symval, char *alias)
13470fc1db9dSSumit Garg {
1348a073f26aSMasahiro Yamada DEF_FIELD_ADDR(symval, tee_client_device_id, uuid);
13490fc1db9dSSumit Garg
13500fc1db9dSSumit Garg sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1351a073f26aSMasahiro Yamada uuid->b[0], uuid->b[1], uuid->b[2], uuid->b[3], uuid->b[4],
1352a073f26aSMasahiro Yamada uuid->b[5], uuid->b[6], uuid->b[7], uuid->b[8], uuid->b[9],
1353a073f26aSMasahiro Yamada uuid->b[10], uuid->b[11], uuid->b[12], uuid->b[13], uuid->b[14],
1354a073f26aSMasahiro Yamada uuid->b[15]);
13550fc1db9dSSumit Garg
13560fc1db9dSSumit Garg add_wildcard(alias);
13570fc1db9dSSumit Garg return 1;
13580fc1db9dSSumit Garg }
13590fc1db9dSSumit Garg
13600bc44b2bSMattias Jacobsson /* Looks like: wmi:guid */
do_wmi_entry(const char * filename,void * symval,char * alias)13610bc44b2bSMattias Jacobsson static int do_wmi_entry(const char *filename, void *symval, char *alias)
13620bc44b2bSMattias Jacobsson {
13630bc44b2bSMattias Jacobsson int len;
13640bc44b2bSMattias Jacobsson DEF_FIELD_ADDR(symval, wmi_device_id, guid_string);
13650bc44b2bSMattias Jacobsson
13660bc44b2bSMattias Jacobsson if (strlen(*guid_string) != UUID_STRING_LEN) {
13670bc44b2bSMattias Jacobsson warn("Invalid WMI device id 'wmi:%s' in '%s'\n",
13680bc44b2bSMattias Jacobsson *guid_string, filename);
13690bc44b2bSMattias Jacobsson return 0;
13700bc44b2bSMattias Jacobsson }
13710bc44b2bSMattias Jacobsson
13720bc44b2bSMattias Jacobsson len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string);
13730bc44b2bSMattias Jacobsson if (len < 0 || len >= ALIAS_SIZE) {
13740bc44b2bSMattias Jacobsson warn("Could not generate all MODULE_ALIAS's in '%s'\n",
13750bc44b2bSMattias Jacobsson filename);
13760bc44b2bSMattias Jacobsson return 0;
13770bc44b2bSMattias Jacobsson }
13780bc44b2bSMattias Jacobsson return 1;
13790bc44b2bSMattias Jacobsson }
13800bc44b2bSMattias Jacobsson
1381e6b0de46SManivannan Sadhasivam /* Looks like: mhi:S */
do_mhi_entry(const char * filename,void * symval,char * alias)1382e6b0de46SManivannan Sadhasivam static int do_mhi_entry(const char *filename, void *symval, char *alias)
1383e6b0de46SManivannan Sadhasivam {
1384e6b0de46SManivannan Sadhasivam DEF_FIELD_ADDR(symval, mhi_device_id, chan);
1385e6b0de46SManivannan Sadhasivam sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan);
13867de3697eSDave Ertman return 1;
13877de3697eSDave Ertman }
13887de3697eSDave Ertman
1389c268c0a8SManivannan Sadhasivam /* Looks like: mhi_ep:S */
do_mhi_ep_entry(const char * filename,void * symval,char * alias)1390c268c0a8SManivannan Sadhasivam static int do_mhi_ep_entry(const char *filename, void *symval, char *alias)
1391c268c0a8SManivannan Sadhasivam {
1392c268c0a8SManivannan Sadhasivam DEF_FIELD_ADDR(symval, mhi_device_id, chan);
1393c268c0a8SManivannan Sadhasivam sprintf(alias, MHI_EP_DEVICE_MODALIAS_FMT, *chan);
1394c268c0a8SManivannan Sadhasivam
1395c268c0a8SManivannan Sadhasivam return 1;
1396c268c0a8SManivannan Sadhasivam }
1397c268c0a8SManivannan Sadhasivam
1398fa443bc3SThomas Weißschuh /* Looks like: ishtp:{guid} */
do_ishtp_entry(const char * filename,void * symval,char * alias)1399fa443bc3SThomas Weißschuh static int do_ishtp_entry(const char *filename, void *symval, char *alias)
1400fa443bc3SThomas Weißschuh {
1401106a1f3aSMasahiro Yamada DEF_FIELD_ADDR(symval, ishtp_device_id, guid);
1402fa443bc3SThomas Weißschuh
1403fa443bc3SThomas Weißschuh strcpy(alias, ISHTP_MODULE_PREFIX "{");
1404106a1f3aSMasahiro Yamada add_guid(alias, *guid);
1405fa443bc3SThomas Weißschuh strcat(alias, "}");
1406fa443bc3SThomas Weißschuh
1407fa443bc3SThomas Weißschuh return 1;
1408fa443bc3SThomas Weißschuh }
1409fa443bc3SThomas Weißschuh
do_auxiliary_entry(const char * filename,void * symval,char * alias)14107de3697eSDave Ertman static int do_auxiliary_entry(const char *filename, void *symval, char *alias)
14117de3697eSDave Ertman {
14127de3697eSDave Ertman DEF_FIELD_ADDR(symval, auxiliary_device_id, name);
14137de3697eSDave Ertman sprintf(alias, AUXILIARY_MODULE_PREFIX "%s", *name);
1414e6b0de46SManivannan Sadhasivam
1415e6b0de46SManivannan Sadhasivam return 1;
1416e6b0de46SManivannan Sadhasivam }
1417e6b0de46SManivannan Sadhasivam
1418eb0e90a8SMaximilian Luz /*
1419eb0e90a8SMaximilian Luz * Looks like: ssam:dNcNtNiNfN
1420eb0e90a8SMaximilian Luz *
1421eb0e90a8SMaximilian Luz * N is exactly 2 digits, where each is an upper-case hex digit.
1422eb0e90a8SMaximilian Luz */
do_ssam_entry(const char * filename,void * symval,char * alias)1423eb0e90a8SMaximilian Luz static int do_ssam_entry(const char *filename, void *symval, char *alias)
1424eb0e90a8SMaximilian Luz {
1425eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, match_flags);
1426eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, domain);
1427eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, category);
1428eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, target);
1429eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, instance);
1430eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, function);
1431eb0e90a8SMaximilian Luz
1432eb0e90a8SMaximilian Luz sprintf(alias, "ssam:d%02Xc%02X", domain, category);
1433eb0e90a8SMaximilian Luz ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target);
1434eb0e90a8SMaximilian Luz ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance);
1435eb0e90a8SMaximilian Luz ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function);
1436eb0e90a8SMaximilian Luz
1437eb0e90a8SMaximilian Luz return 1;
1438eb0e90a8SMaximilian Luz }
1439eb0e90a8SMaximilian Luz
14404a224aceSXu Yilun /* Looks like: dfl:tNfN */
do_dfl_entry(const char * filename,void * symval,char * alias)14414a224aceSXu Yilun static int do_dfl_entry(const char *filename, void *symval, char *alias)
14424a224aceSXu Yilun {
14434a224aceSXu Yilun DEF_FIELD(symval, dfl_device_id, type);
14444a224aceSXu Yilun DEF_FIELD(symval, dfl_device_id, feature_id);
14454a224aceSXu Yilun
14464a224aceSXu Yilun sprintf(alias, "dfl:t%04Xf%04X", type, feature_id);
14474a224aceSXu Yilun
14484a224aceSXu Yilun add_wildcard(alias);
14494a224aceSXu Yilun return 1;
14504a224aceSXu Yilun }
14514a224aceSXu Yilun
14522959ab24SNipun Gupta /* Looks like: cdx:vNdN */
do_cdx_entry(const char * filename,void * symval,char * alias)14532959ab24SNipun Gupta static int do_cdx_entry(const char *filename, void *symval,
14542959ab24SNipun Gupta char *alias)
14552959ab24SNipun Gupta {
14562959ab24SNipun Gupta DEF_FIELD(symval, cdx_device_id, vendor);
14572959ab24SNipun Gupta DEF_FIELD(symval, cdx_device_id, device);
1458234489acSNipun Gupta DEF_FIELD(symval, cdx_device_id, override_only);
14592959ab24SNipun Gupta
1460234489acSNipun Gupta switch (override_only) {
1461234489acSNipun Gupta case 0:
1462234489acSNipun Gupta strcpy(alias, "cdx:");
1463234489acSNipun Gupta break;
1464234489acSNipun Gupta case CDX_ID_F_VFIO_DRIVER_OVERRIDE:
1465234489acSNipun Gupta strcpy(alias, "vfio_cdx:");
1466234489acSNipun Gupta break;
1467234489acSNipun Gupta default:
1468234489acSNipun Gupta warn("Unknown CDX driver_override alias %08X\n",
1469234489acSNipun Gupta override_only);
1470234489acSNipun Gupta return 0;
1471234489acSNipun Gupta }
1472234489acSNipun Gupta
1473234489acSNipun Gupta ADD(alias, "v", vendor != CDX_ANY_ID, vendor);
1474234489acSNipun Gupta ADD(alias, "d", device != CDX_ANY_ID, device);
14752959ab24SNipun Gupta return 1;
14762959ab24SNipun Gupta }
14772959ab24SNipun Gupta
1478626596e2SRusty Russell /* Does namelen bytes of name exactly match the symbol? */
sym_is(const char * name,unsigned namelen,const char * symbol)1479626596e2SRusty Russell static bool sym_is(const char *name, unsigned namelen, const char *symbol)
14801da177e4SLinus Torvalds {
1481626596e2SRusty Russell if (namelen != strlen(symbol))
1482626596e2SRusty Russell return false;
14831da177e4SLinus Torvalds
1484626596e2SRusty Russell return memcmp(name, symbol, namelen) == 0;
14851da177e4SLinus Torvalds }
14861da177e4SLinus Torvalds
do_table(void * symval,unsigned long size,unsigned long id_size,const char * device_id,int (* do_entry)(const char * filename,void * symval,char * alias),struct module * mod)14871da177e4SLinus Torvalds static void do_table(void *symval, unsigned long size,
14881da177e4SLinus Torvalds unsigned long id_size,
1489fb33d816SSam Ravnborg const char *device_id,
1490f880eea6SMasahiro Yamada int (*do_entry)(const char *filename, void *symval, char *alias),
14911da177e4SLinus Torvalds struct module *mod)
14921da177e4SLinus Torvalds {
14931da177e4SLinus Torvalds unsigned int i;
1494841f1b8fSMattias Jacobsson char alias[ALIAS_SIZE];
14951da177e4SLinus Torvalds
1496e0049825SKees Cook device_id_check(mod->name, device_id, size, id_size, symval);
14971da177e4SLinus Torvalds /* Leave last one: it's the terminator. */
14981da177e4SLinus Torvalds size -= id_size;
14991da177e4SLinus Torvalds
15001da177e4SLinus Torvalds for (i = 0; i < size; i += id_size) {
15011da177e4SLinus Torvalds if (do_entry(mod->name, symval+i, alias)) {
15021da177e4SLinus Torvalds buf_printf(&mod->dev_table_buf,
15031da177e4SLinus Torvalds "MODULE_ALIAS(\"%s\");\n", alias);
15041da177e4SLinus Torvalds }
15051da177e4SLinus Torvalds }
15061da177e4SLinus Torvalds }
15071da177e4SLinus Torvalds
1508ec91e78dSMasahiro Yamada static const struct devtable devtable[] = {
1509ec91e78dSMasahiro Yamada {"hid", SIZE_hid_device_id, do_hid_entry},
1510ec91e78dSMasahiro Yamada {"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry},
1511ec91e78dSMasahiro Yamada {"pci", SIZE_pci_device_id, do_pci_entry},
1512ec91e78dSMasahiro Yamada {"ccw", SIZE_ccw_device_id, do_ccw_entry},
1513ec91e78dSMasahiro Yamada {"ap", SIZE_ap_device_id, do_ap_entry},
1514ec91e78dSMasahiro Yamada {"css", SIZE_css_device_id, do_css_entry},
1515ec91e78dSMasahiro Yamada {"serio", SIZE_serio_device_id, do_serio_entry},
1516ec91e78dSMasahiro Yamada {"acpi", SIZE_acpi_device_id, do_acpi_entry},
1517ec91e78dSMasahiro Yamada {"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry},
1518ec91e78dSMasahiro Yamada {"vio", SIZE_vio_device_id, do_vio_entry},
1519ec91e78dSMasahiro Yamada {"input", SIZE_input_device_id, do_input_entry},
1520ec91e78dSMasahiro Yamada {"eisa", SIZE_eisa_device_id, do_eisa_entry},
1521ec91e78dSMasahiro Yamada {"parisc", SIZE_parisc_device_id, do_parisc_entry},
1522ec91e78dSMasahiro Yamada {"sdio", SIZE_sdio_device_id, do_sdio_entry},
1523ec91e78dSMasahiro Yamada {"ssb", SIZE_ssb_device_id, do_ssb_entry},
1524ec91e78dSMasahiro Yamada {"bcma", SIZE_bcma_device_id, do_bcma_entry},
1525ec91e78dSMasahiro Yamada {"virtio", SIZE_virtio_device_id, do_virtio_entry},
1526ec91e78dSMasahiro Yamada {"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry},
1527ec91e78dSMasahiro Yamada {"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry},
1528ec91e78dSMasahiro Yamada {"i2c", SIZE_i2c_device_id, do_i2c_entry},
15291ce589adSBoris Brezillon {"i3c", SIZE_i3c_device_id, do_i3c_entry},
1530ec91e78dSMasahiro Yamada {"spi", SIZE_spi_device_id, do_spi_entry},
1531ec91e78dSMasahiro Yamada {"dmi", SIZE_dmi_system_id, do_dmi_entry},
1532ec91e78dSMasahiro Yamada {"platform", SIZE_platform_device_id, do_platform_entry},
1533ec91e78dSMasahiro Yamada {"mdio", SIZE_mdio_device_id, do_mdio_entry},
1534ec91e78dSMasahiro Yamada {"zorro", SIZE_zorro_device_id, do_zorro_entry},
1535ec91e78dSMasahiro Yamada {"isapnp", SIZE_isapnp_device_id, do_isapnp_entry},
1536ec91e78dSMasahiro Yamada {"ipack", SIZE_ipack_device_id, do_ipack_entry},
1537ec91e78dSMasahiro Yamada {"amba", SIZE_amba_id, do_amba_entry},
1538ec91e78dSMasahiro Yamada {"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry},
1539ec91e78dSMasahiro Yamada {"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry},
1540ec91e78dSMasahiro Yamada {"cpu", SIZE_cpu_feature, do_cpu_entry},
1541ec91e78dSMasahiro Yamada {"mei", SIZE_mei_cl_device_id, do_mei_entry},
1542ec91e78dSMasahiro Yamada {"rapidio", SIZE_rio_device_id, do_rio_entry},
1543ec91e78dSMasahiro Yamada {"ulpi", SIZE_ulpi_device_id, do_ulpi_entry},
1544ec91e78dSMasahiro Yamada {"hdaudio", SIZE_hda_device_id, do_hda_entry},
1545ec91e78dSMasahiro Yamada {"sdw", SIZE_sdw_device_id, do_sdw_entry},
1546ec91e78dSMasahiro Yamada {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry},
1547ec91e78dSMasahiro Yamada {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
1548ec91e78dSMasahiro Yamada {"typec", SIZE_typec_device_id, do_typec_entry},
15490fc1db9dSSumit Garg {"tee", SIZE_tee_client_device_id, do_tee_entry},
15500bc44b2bSMattias Jacobsson {"wmi", SIZE_wmi_device_id, do_wmi_entry},
1551e6b0de46SManivannan Sadhasivam {"mhi", SIZE_mhi_device_id, do_mhi_entry},
1552c268c0a8SManivannan Sadhasivam {"mhi_ep", SIZE_mhi_device_id, do_mhi_ep_entry},
15537de3697eSDave Ertman {"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry},
1554eb0e90a8SMaximilian Luz {"ssam", SIZE_ssam_device_id, do_ssam_entry},
15554a224aceSXu Yilun {"dfl", SIZE_dfl_device_id, do_dfl_entry},
1556fa443bc3SThomas Weißschuh {"ishtp", SIZE_ishtp_device_id, do_ishtp_entry},
15572959ab24SNipun Gupta {"cdx", SIZE_cdx_device_id, do_cdx_entry},
1558ec91e78dSMasahiro Yamada };
1559ec91e78dSMasahiro Yamada
15601da177e4SLinus Torvalds /* Create MODULE_ALIAS() statements.
15611da177e4SLinus Torvalds * At this time, we cannot write the actual output C source yet,
15621da177e4SLinus Torvalds * so we write into the mod->dev_table_buf buffer. */
handle_moddevtable(struct module * mod,struct elf_info * info,Elf_Sym * sym,const char * symname)15631da177e4SLinus Torvalds void handle_moddevtable(struct module *mod, struct elf_info *info,
15641da177e4SLinus Torvalds Elf_Sym *sym, const char *symname)
15651da177e4SLinus Torvalds {
15661da177e4SLinus Torvalds void *symval;
1567e0049825SKees Cook char *zeros = NULL;
156821bdd17bSTom Gundersen const char *name, *identifier;
1569626596e2SRusty Russell unsigned int namelen;
15701da177e4SLinus Torvalds
15711da177e4SLinus Torvalds /* We're looking for a section relative symbol */
15721ce53adfSDenys Vlasenko if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
15731da177e4SLinus Torvalds return;
15741da177e4SLinus Torvalds
1575e88aa7bbSDavid Miller /* We're looking for an object */
1576e88aa7bbSDavid Miller if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
1577e88aa7bbSDavid Miller return;
1578e88aa7bbSDavid Miller
1579153e04b3SMasahiro Yamada /* All our symbols are of form __mod_<name>__<identifier>_device_table. */
1580153e04b3SMasahiro Yamada if (strncmp(symname, "__mod_", strlen("__mod_")))
1581626596e2SRusty Russell return;
1582153e04b3SMasahiro Yamada name = symname + strlen("__mod_");
1583626596e2SRusty Russell namelen = strlen(name);
1584626596e2SRusty Russell if (namelen < strlen("_device_table"))
1585626596e2SRusty Russell return;
1586626596e2SRusty Russell if (strcmp(name + namelen - strlen("_device_table"), "_device_table"))
1587626596e2SRusty Russell return;
158821bdd17bSTom Gundersen identifier = strstr(name, "__");
158921bdd17bSTom Gundersen if (!identifier)
159021bdd17bSTom Gundersen return;
159121bdd17bSTom Gundersen namelen = identifier - name;
1592626596e2SRusty Russell
1593e0049825SKees Cook /* Handle all-NULL symbols allocated into .bss */
15941ce53adfSDenys Vlasenko if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
1595e0049825SKees Cook zeros = calloc(1, sym->st_size);
1596e0049825SKees Cook symval = zeros;
1597e0049825SKees Cook } else {
1598abe864b8SMasahiro Yamada symval = sym_get_data(info, sym);
1599e0049825SKees Cook }
16001da177e4SLinus Torvalds
1601626596e2SRusty Russell /* First handle the "special" cases */
1602626596e2SRusty Russell if (sym_is(name, namelen, "usb"))
1603b19dcd93SRoman Kagan do_usb_table(symval, sym->st_size, mod);
1604cbc3d00cSMauricio Faria de Oliveira else if (sym_is(name, namelen, "of"))
1605acbef7b7SPhilipp Zabel do_of_table(symval, sym->st_size, mod);
1606626596e2SRusty Russell else if (sym_is(name, namelen, "pnp"))
160722454cb9SKay Sievers do_pnp_device_entry(symval, sym->st_size, mod);
1608626596e2SRusty Russell else if (sym_is(name, namelen, "pnp_card"))
16090c81eed4SKay Sievers do_pnp_card_entries(symval, sym->st_size, mod);
1610626596e2SRusty Russell else {
1611ec91e78dSMasahiro Yamada int i;
1612626596e2SRusty Russell
1613ec91e78dSMasahiro Yamada for (i = 0; i < ARRAY_SIZE(devtable); i++) {
1614ec91e78dSMasahiro Yamada const struct devtable *p = &devtable[i];
1615ec91e78dSMasahiro Yamada
1616ec91e78dSMasahiro Yamada if (sym_is(name, namelen, p->device_id)) {
1617ec91e78dSMasahiro Yamada do_table(symval, sym->st_size, p->id_size,
1618f880eea6SMasahiro Yamada p->device_id, p->do_entry, mod);
1619626596e2SRusty Russell break;
1620626596e2SRusty Russell }
1621626596e2SRusty Russell }
1622626596e2SRusty Russell }
1623e0049825SKees Cook free(zeros);
16241da177e4SLinus Torvalds }
16251da177e4SLinus Torvalds
16261da177e4SLinus Torvalds /* Now add out buffered information to the generated C source */
add_moddevtable(struct buffer * buf,struct module * mod)16271da177e4SLinus Torvalds void add_moddevtable(struct buffer *buf, struct module *mod)
16281da177e4SLinus Torvalds {
16291da177e4SLinus Torvalds buf_printf(buf, "\n");
16301da177e4SLinus Torvalds buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
16311da177e4SLinus Torvalds free(mod->dev_table_buf.p);
16321da177e4SLinus Torvalds }
1633