xref: /linux/scripts/mod/file2alias.c (revision 1fa05877588a02fdad995385eaafea4798022cd4)
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 */
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 
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 
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  **/
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" */
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-- */
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 
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 
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 
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 
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 */
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 */
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. */
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" */
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" */
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" */
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" */
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  */
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" */
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 */
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. */
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 
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 
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]);
745ddc5d341SDmitry Torokhov 	for (i = min; i < max; i++)
746e0e92632SHans de Goede 		if (arr[i / BITS_PER_LONG] & (1L << (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. */
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 
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 	if (sig[0])
8136543becfSAndreas Schwab 		sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
814ac551828SJean Delvare 	else
815ac551828SJean Delvare 		strcat(alias, "*");
81607563c71SMichael Tokarev 	return 1;
81707563c71SMichael Tokarev }
81807563c71SMichael Tokarev 
819f3cf2673SKyle McMartin /* Looks like: parisc:tNhvNrevNsvN */
8206543becfSAndreas Schwab static int do_parisc_entry(const char *filename, void *symval,
821f3cf2673SKyle McMartin 		char *alias)
822f3cf2673SKyle McMartin {
8236543becfSAndreas Schwab 	DEF_FIELD(symval, parisc_device_id, hw_type);
8246543becfSAndreas Schwab 	DEF_FIELD(symval, parisc_device_id, hversion);
8256543becfSAndreas Schwab 	DEF_FIELD(symval, parisc_device_id, hversion_rev);
8266543becfSAndreas Schwab 	DEF_FIELD(symval, parisc_device_id, sversion);
827f3cf2673SKyle McMartin 
828f3cf2673SKyle McMartin 	strcpy(alias, "parisc:");
8296543becfSAndreas Schwab 	ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
8306543becfSAndreas Schwab 	ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
8316543becfSAndreas Schwab 	ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
8326543becfSAndreas Schwab 	ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
833f3cf2673SKyle McMartin 
834ac551828SJean Delvare 	add_wildcard(alias);
835f3cf2673SKyle McMartin 	return 1;
836f3cf2673SKyle McMartin }
837f3cf2673SKyle McMartin 
838d59b66c7SPierre Ossman /* Looks like: sdio:cNvNdN. */
839d59b66c7SPierre Ossman static int do_sdio_entry(const char *filename,
8406543becfSAndreas Schwab 			void *symval, char *alias)
841d59b66c7SPierre Ossman {
8426543becfSAndreas Schwab 	DEF_FIELD(symval, sdio_device_id, class);
8436543becfSAndreas Schwab 	DEF_FIELD(symval, sdio_device_id, vendor);
8446543becfSAndreas Schwab 	DEF_FIELD(symval, sdio_device_id, device);
845d59b66c7SPierre Ossman 
846d59b66c7SPierre Ossman 	strcpy(alias, "sdio:");
8476543becfSAndreas Schwab 	ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
8486543becfSAndreas Schwab 	ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
8496543becfSAndreas Schwab 	ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
850ac551828SJean Delvare 	add_wildcard(alias);
851038a5008SLinus Torvalds 	return 1;
852038a5008SLinus Torvalds }
853d59b66c7SPierre Ossman 
85461e115a5SMichael Buesch /* Looks like: ssb:vNidNrevN. */
85561e115a5SMichael Buesch static int do_ssb_entry(const char *filename,
8566543becfSAndreas Schwab 			void *symval, char *alias)
85761e115a5SMichael Buesch {
8586543becfSAndreas Schwab 	DEF_FIELD(symval, ssb_device_id, vendor);
8596543becfSAndreas Schwab 	DEF_FIELD(symval, ssb_device_id, coreid);
8606543becfSAndreas Schwab 	DEF_FIELD(symval, ssb_device_id, revision);
86161e115a5SMichael Buesch 
86261e115a5SMichael Buesch 	strcpy(alias, "ssb:");
8636543becfSAndreas Schwab 	ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
8646543becfSAndreas Schwab 	ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
8656543becfSAndreas Schwab 	ADD(alias, "rev", revision != SSB_ANY_REV, revision);
866ac551828SJean Delvare 	add_wildcard(alias);
867d59b66c7SPierre Ossman 	return 1;
868d59b66c7SPierre Ossman }
869d59b66c7SPierre Ossman 
8708369ae33SRafał Miłecki /* Looks like: bcma:mNidNrevNclN. */
8718369ae33SRafał Miłecki static int do_bcma_entry(const char *filename,
8726543becfSAndreas Schwab 			 void *symval, char *alias)
8738369ae33SRafał Miłecki {
8746543becfSAndreas Schwab 	DEF_FIELD(symval, bcma_device_id, manuf);
8756543becfSAndreas Schwab 	DEF_FIELD(symval, bcma_device_id, id);
8766543becfSAndreas Schwab 	DEF_FIELD(symval, bcma_device_id, rev);
8776543becfSAndreas Schwab 	DEF_FIELD(symval, bcma_device_id, class);
8788369ae33SRafał Miłecki 
8798369ae33SRafał Miłecki 	strcpy(alias, "bcma:");
8806543becfSAndreas Schwab 	ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
8816543becfSAndreas Schwab 	ADD(alias, "id", id != BCMA_ANY_ID, id);
8826543becfSAndreas Schwab 	ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
8836543becfSAndreas Schwab 	ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
8848369ae33SRafał Miłecki 	add_wildcard(alias);
8858369ae33SRafał Miłecki 	return 1;
8868369ae33SRafał Miłecki }
8878369ae33SRafał Miłecki 
888b01d9f28SRusty Russell /* Looks like: virtio:dNvN */
8896543becfSAndreas Schwab static int do_virtio_entry(const char *filename, void *symval,
890b01d9f28SRusty Russell 			   char *alias)
891b01d9f28SRusty Russell {
8926543becfSAndreas Schwab 	DEF_FIELD(symval, virtio_device_id, device);
8936543becfSAndreas Schwab 	DEF_FIELD(symval, virtio_device_id, vendor);
894b01d9f28SRusty Russell 
895b01d9f28SRusty Russell 	strcpy(alias, "virtio:");
8966543becfSAndreas Schwab 	ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
8976543becfSAndreas Schwab 	ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
898b01d9f28SRusty Russell 
899ac551828SJean Delvare 	add_wildcard(alias);
900b01d9f28SRusty Russell 	return 1;
901b01d9f28SRusty Russell }
902b01d9f28SRusty Russell 
903d2ee52aaSK. Y. Srinivasan /*
904d2ee52aaSK. Y. Srinivasan  * Looks like: vmbus:guid
905d2ee52aaSK. Y. Srinivasan  * Each byte of the guid will be represented by two hex characters
906d2ee52aaSK. Y. Srinivasan  * in the name.
907d2ee52aaSK. Y. Srinivasan  */
908d2ee52aaSK. Y. Srinivasan 
9096543becfSAndreas Schwab static int do_vmbus_entry(const char *filename, void *symval,
910d2ee52aaSK. Y. Srinivasan 			  char *alias)
911d2ee52aaSK. Y. Srinivasan {
912d2ee52aaSK. Y. Srinivasan 	int i;
9136543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
9146543becfSAndreas Schwab 	char guid_name[(sizeof(*guid) + 1) * 2];
915d2ee52aaSK. Y. Srinivasan 
9166543becfSAndreas Schwab 	for (i = 0; i < (sizeof(*guid) * 2); i += 2)
917af3ff643SK. Y. Srinivasan 		sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2]));
918d2ee52aaSK. Y. Srinivasan 
919d2ee52aaSK. Y. Srinivasan 	strcpy(alias, "vmbus:");
920d2ee52aaSK. Y. Srinivasan 	strcat(alias, guid_name);
921d2ee52aaSK. Y. Srinivasan 
922d2ee52aaSK. Y. Srinivasan 	return 1;
923d2ee52aaSK. Y. Srinivasan }
924d2ee52aaSK. Y. Srinivasan 
9255b7d1277SAndrew F. Davis /* Looks like: rpmsg:S */
9265b7d1277SAndrew F. Davis static int do_rpmsg_entry(const char *filename, void *symval,
9275b7d1277SAndrew F. Davis 			  char *alias)
9285b7d1277SAndrew F. Davis {
9295b7d1277SAndrew F. Davis 	DEF_FIELD_ADDR(symval, rpmsg_device_id, name);
9305b7d1277SAndrew F. Davis 	sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name);
9315b7d1277SAndrew F. Davis 
9325b7d1277SAndrew F. Davis 	return 1;
9335b7d1277SAndrew F. Davis }
9345b7d1277SAndrew F. Davis 
935d2653e92SJean Delvare /* Looks like: i2c:S */
9366543becfSAndreas Schwab static int do_i2c_entry(const char *filename, void *symval,
937d2653e92SJean Delvare 			char *alias)
938d2653e92SJean Delvare {
9396543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, i2c_device_id, name);
9406543becfSAndreas Schwab 	sprintf(alias, I2C_MODULE_PREFIX "%s", *name);
941d2653e92SJean Delvare 
942d2653e92SJean Delvare 	return 1;
943d2653e92SJean Delvare }
944d2653e92SJean Delvare 
9451ce589adSBoris Brezillon static int do_i3c_entry(const char *filename, void *symval,
9461ce589adSBoris Brezillon 			char *alias)
9471ce589adSBoris Brezillon {
9481ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, match_flags);
9491ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, dcr);
9501ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, manuf_id);
9511ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, part_id);
9521ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, extra_info);
9531ce589adSBoris Brezillon 
9541ce589adSBoris Brezillon 	strcpy(alias, "i3c:");
9551ce589adSBoris Brezillon 	ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr);
9561ce589adSBoris Brezillon 	ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id);
9571ce589adSBoris Brezillon 	ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id);
9581ce589adSBoris Brezillon 	ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info);
9591ce589adSBoris Brezillon 
9601ce589adSBoris Brezillon 	return 1;
9611ce589adSBoris Brezillon }
9621ce589adSBoris Brezillon 
963e0626e38SAnton Vorontsov /* Looks like: spi:S */
9646543becfSAndreas Schwab static int do_spi_entry(const char *filename, void *symval,
96575368bf6SAnton Vorontsov 			char *alias)
96675368bf6SAnton Vorontsov {
9676543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, spi_device_id, name);
9686543becfSAndreas Schwab 	sprintf(alias, SPI_MODULE_PREFIX "%s", *name);
96975368bf6SAnton Vorontsov 
97075368bf6SAnton Vorontsov 	return 1;
97175368bf6SAnton Vorontsov }
97275368bf6SAnton Vorontsov 
973d945b697SDavid Woodhouse static const struct dmifield {
974d945b697SDavid Woodhouse 	const char *prefix;
975d945b697SDavid Woodhouse 	int field;
976d945b697SDavid Woodhouse } dmi_fields[] = {
977d945b697SDavid Woodhouse 	{ "bvn", DMI_BIOS_VENDOR },
978d945b697SDavid Woodhouse 	{ "bvr", DMI_BIOS_VERSION },
979d945b697SDavid Woodhouse 	{ "bd",  DMI_BIOS_DATE },
980f5152f4dSErwan Velu 	{ "br",  DMI_BIOS_RELEASE },
981f5152f4dSErwan Velu 	{ "efr", DMI_EC_FIRMWARE_RELEASE },
982d945b697SDavid Woodhouse 	{ "svn", DMI_SYS_VENDOR },
983d945b697SDavid Woodhouse 	{ "pn",  DMI_PRODUCT_NAME },
984d945b697SDavid Woodhouse 	{ "pvr", DMI_PRODUCT_VERSION },
985d945b697SDavid Woodhouse 	{ "rvn", DMI_BOARD_VENDOR },
986d945b697SDavid Woodhouse 	{ "rn",  DMI_BOARD_NAME },
987d945b697SDavid Woodhouse 	{ "rvr", DMI_BOARD_VERSION },
988d945b697SDavid Woodhouse 	{ "cvn", DMI_CHASSIS_VENDOR },
989d945b697SDavid Woodhouse 	{ "ct",  DMI_CHASSIS_TYPE },
990d945b697SDavid Woodhouse 	{ "cvr", DMI_CHASSIS_VERSION },
991d945b697SDavid Woodhouse 	{ NULL,  DMI_NONE }
992d945b697SDavid Woodhouse };
993d945b697SDavid Woodhouse 
994d945b697SDavid Woodhouse static void dmi_ascii_filter(char *d, const char *s)
995d945b697SDavid Woodhouse {
996d945b697SDavid Woodhouse 	/* Filter out characters we don't want to see in the modalias string */
997d945b697SDavid Woodhouse 	for (; *s; s++)
998d945b697SDavid Woodhouse 		if (*s > ' ' && *s < 127 && *s != ':')
999d945b697SDavid Woodhouse 			*(d++) = *s;
1000d945b697SDavid Woodhouse 
1001d945b697SDavid Woodhouse 	*d = 0;
1002d945b697SDavid Woodhouse }
1003d945b697SDavid Woodhouse 
1004d945b697SDavid Woodhouse 
10056543becfSAndreas Schwab static int do_dmi_entry(const char *filename, void *symval,
1006d945b697SDavid Woodhouse 			char *alias)
1007d945b697SDavid Woodhouse {
1008d945b697SDavid Woodhouse 	int i, j;
10096543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, dmi_system_id, matches);
1010d945b697SDavid Woodhouse 	sprintf(alias, "dmi*");
1011d945b697SDavid Woodhouse 
1012d945b697SDavid Woodhouse 	for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
1013d945b697SDavid Woodhouse 		for (j = 0; j < 4; j++) {
10146543becfSAndreas Schwab 			if ((*matches)[j].slot &&
10156543becfSAndreas Schwab 			    (*matches)[j].slot == dmi_fields[i].field) {
1016d945b697SDavid Woodhouse 				sprintf(alias + strlen(alias), ":%s*",
1017d945b697SDavid Woodhouse 					dmi_fields[i].prefix);
1018d945b697SDavid Woodhouse 				dmi_ascii_filter(alias + strlen(alias),
10196543becfSAndreas Schwab 						 (*matches)[j].substr);
1020d945b697SDavid Woodhouse 				strcat(alias, "*");
1021d945b697SDavid Woodhouse 			}
1022d945b697SDavid Woodhouse 		}
1023d945b697SDavid Woodhouse 	}
1024d945b697SDavid Woodhouse 
1025d945b697SDavid Woodhouse 	strcat(alias, ":");
1026d945b697SDavid Woodhouse 	return 1;
1027d945b697SDavid Woodhouse }
102857fee4a5SEric Miao 
102957fee4a5SEric Miao static int do_platform_entry(const char *filename,
10306543becfSAndreas Schwab 			     void *symval, char *alias)
103157fee4a5SEric Miao {
10326543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, platform_device_id, name);
10336543becfSAndreas Schwab 	sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name);
103457fee4a5SEric Miao 	return 1;
103557fee4a5SEric Miao }
103657fee4a5SEric Miao 
10378626d3b4SDavid Woodhouse static int do_mdio_entry(const char *filename,
10386543becfSAndreas Schwab 			 void *symval, char *alias)
10398626d3b4SDavid Woodhouse {
10408626d3b4SDavid Woodhouse 	int i;
10416543becfSAndreas Schwab 	DEF_FIELD(symval, mdio_device_id, phy_id);
10426543becfSAndreas Schwab 	DEF_FIELD(symval, mdio_device_id, phy_id_mask);
10438626d3b4SDavid Woodhouse 
10448626d3b4SDavid Woodhouse 	alias += sprintf(alias, MDIO_MODULE_PREFIX);
10458626d3b4SDavid Woodhouse 
10468626d3b4SDavid Woodhouse 	for (i = 0; i < 32; i++) {
10476543becfSAndreas Schwab 		if (!((phy_id_mask >> (31-i)) & 1))
10488626d3b4SDavid Woodhouse 			*(alias++) = '?';
10496543becfSAndreas Schwab 		else if ((phy_id >> (31-i)) & 1)
10508626d3b4SDavid Woodhouse 			*(alias++) = '1';
10518626d3b4SDavid Woodhouse 		else
10528626d3b4SDavid Woodhouse 			*(alias++) = '0';
10538626d3b4SDavid Woodhouse 	}
10548626d3b4SDavid Woodhouse 
10558626d3b4SDavid Woodhouse 	/* Terminate the string */
10568626d3b4SDavid Woodhouse 	*alias = 0;
10578626d3b4SDavid Woodhouse 
10588626d3b4SDavid Woodhouse 	return 1;
10598626d3b4SDavid Woodhouse }
10608626d3b4SDavid Woodhouse 
1061bf54a2b3SGeert Uytterhoeven /* Looks like: zorro:iN. */
10626543becfSAndreas Schwab static int do_zorro_entry(const char *filename, void *symval,
1063bf54a2b3SGeert Uytterhoeven 			  char *alias)
1064bf54a2b3SGeert Uytterhoeven {
10656543becfSAndreas Schwab 	DEF_FIELD(symval, zorro_device_id, id);
1066bf54a2b3SGeert Uytterhoeven 	strcpy(alias, "zorro:");
10676543becfSAndreas Schwab 	ADD(alias, "i", id != ZORRO_WILDCARD, id);
1068bf54a2b3SGeert Uytterhoeven 	return 1;
1069bf54a2b3SGeert Uytterhoeven }
1070bf54a2b3SGeert Uytterhoeven 
1071fedb3d27SOndrej Zary /* looks like: "pnp:dD" */
1072fedb3d27SOndrej Zary static int do_isapnp_entry(const char *filename,
10736543becfSAndreas Schwab 			   void *symval, char *alias)
1074fedb3d27SOndrej Zary {
10756543becfSAndreas Schwab 	DEF_FIELD(symval, isapnp_device_id, vendor);
10766543becfSAndreas Schwab 	DEF_FIELD(symval, isapnp_device_id, function);
1077fedb3d27SOndrej Zary 	sprintf(alias, "pnp:d%c%c%c%x%x%x%x*",
10786543becfSAndreas Schwab 		'A' + ((vendor >> 2) & 0x3f) - 1,
10796543becfSAndreas Schwab 		'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
10806543becfSAndreas Schwab 		'A' + ((vendor >> 8) & 0x1f) - 1,
10816543becfSAndreas Schwab 		(function >> 4) & 0x0f, function & 0x0f,
10826543becfSAndreas Schwab 		(function >> 12) & 0x0f, (function >> 8) & 0x0f);
1083fedb3d27SOndrej Zary 	return 1;
1084fedb3d27SOndrej Zary }
1085fedb3d27SOndrej Zary 
1086849e0ad2SJens Taprogge /* Looks like: "ipack:fNvNdN". */
1087849e0ad2SJens Taprogge static int do_ipack_entry(const char *filename,
10886543becfSAndreas Schwab 			  void *symval, char *alias)
1089849e0ad2SJens Taprogge {
10906543becfSAndreas Schwab 	DEF_FIELD(symval, ipack_device_id, format);
10916543becfSAndreas Schwab 	DEF_FIELD(symval, ipack_device_id, vendor);
10926543becfSAndreas Schwab 	DEF_FIELD(symval, ipack_device_id, device);
1093849e0ad2SJens Taprogge 	strcpy(alias, "ipack:");
10946543becfSAndreas Schwab 	ADD(alias, "f", format != IPACK_ANY_FORMAT, format);
10956543becfSAndreas Schwab 	ADD(alias, "v", vendor != IPACK_ANY_ID, vendor);
10966543becfSAndreas Schwab 	ADD(alias, "d", device != IPACK_ANY_ID, device);
1097849e0ad2SJens Taprogge 	add_wildcard(alias);
1098849e0ad2SJens Taprogge 	return 1;
1099849e0ad2SJens Taprogge }
1100849e0ad2SJens Taprogge 
1101523817bdSDave Martin /*
1102523817bdSDave Martin  * Append a match expression for a single masked hex digit.
1103523817bdSDave Martin  * outp points to a pointer to the character at which to append.
1104523817bdSDave Martin  *	*outp is updated on return to point just after the appended text,
1105523817bdSDave Martin  *	to facilitate further appending.
1106523817bdSDave Martin  */
1107523817bdSDave Martin static void append_nibble_mask(char **outp,
1108523817bdSDave Martin 			       unsigned int nibble, unsigned int mask)
1109523817bdSDave Martin {
1110523817bdSDave Martin 	char *p = *outp;
1111523817bdSDave Martin 	unsigned int i;
1112523817bdSDave Martin 
1113523817bdSDave Martin 	switch (mask) {
1114523817bdSDave Martin 	case 0:
1115523817bdSDave Martin 		*p++ = '?';
1116523817bdSDave Martin 		break;
1117523817bdSDave Martin 
1118523817bdSDave Martin 	case 0xf:
1119523817bdSDave Martin 		p += sprintf(p, "%X",  nibble);
1120523817bdSDave Martin 		break;
1121523817bdSDave Martin 
1122523817bdSDave Martin 	default:
1123523817bdSDave Martin 		/*
1124523817bdSDave Martin 		 * Dumbly emit a match pattern for all possible matching
1125523817bdSDave Martin 		 * digits.  This could be improved in some cases using ranges,
1126523817bdSDave Martin 		 * but it has the advantage of being trivially correct, and is
1127523817bdSDave Martin 		 * often optimal.
1128523817bdSDave Martin 		 */
1129523817bdSDave Martin 		*p++ = '[';
1130523817bdSDave Martin 		for (i = 0; i < 0x10; i++)
1131523817bdSDave Martin 			if ((i & mask) == nibble)
1132523817bdSDave Martin 				p += sprintf(p, "%X", i);
1133523817bdSDave Martin 		*p++ = ']';
1134523817bdSDave Martin 	}
1135523817bdSDave Martin 
1136523817bdSDave Martin 	/* Ensure that the string remains NUL-terminated: */
1137523817bdSDave Martin 	*p = '\0';
1138523817bdSDave Martin 
1139523817bdSDave Martin 	/* Advance the caller's end-of-string pointer: */
1140523817bdSDave Martin 	*outp = p;
1141523817bdSDave Martin }
1142523817bdSDave Martin 
1143523817bdSDave Martin /*
1144523817bdSDave Martin  * looks like: "amba:dN"
1145523817bdSDave Martin  *
1146523817bdSDave Martin  * N is exactly 8 digits, where each is an upper-case hex digit, or
1147523817bdSDave Martin  *	a ? or [] pattern matching exactly one digit.
1148523817bdSDave Martin  */
1149523817bdSDave Martin static int do_amba_entry(const char *filename,
11506543becfSAndreas Schwab 			 void *symval, char *alias)
1151523817bdSDave Martin {
1152523817bdSDave Martin 	unsigned int digit;
1153523817bdSDave Martin 	char *p = alias;
11546543becfSAndreas Schwab 	DEF_FIELD(symval, amba_id, id);
11556543becfSAndreas Schwab 	DEF_FIELD(symval, amba_id, mask);
1156523817bdSDave Martin 
11576543becfSAndreas Schwab 	if ((id & mask) != id)
11580d2573a2SGeert 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",
11596543becfSAndreas Schwab 		      filename, id, mask);
1160523817bdSDave Martin 
1161523817bdSDave Martin 	p += sprintf(alias, "amba:d");
1162523817bdSDave Martin 	for (digit = 0; digit < 8; digit++)
1163523817bdSDave Martin 		append_nibble_mask(&p,
11646543becfSAndreas Schwab 				   (id >> (4 * (7 - digit))) & 0xf,
11656543becfSAndreas Schwab 				   (mask >> (4 * (7 - digit))) & 0xf);
1166523817bdSDave Martin 
1167523817bdSDave Martin 	return 1;
1168523817bdSDave Martin }
1169523817bdSDave Martin 
11708286ae03SJames Hogan /*
11718286ae03SJames Hogan  * looks like: "mipscdmm:tN"
11728286ae03SJames Hogan  *
11738286ae03SJames Hogan  * N is exactly 2 digits, where each is an upper-case hex digit, or
11748286ae03SJames Hogan  *	a ? or [] pattern matching exactly one digit.
11758286ae03SJames Hogan  */
11768286ae03SJames Hogan static int do_mips_cdmm_entry(const char *filename,
11778286ae03SJames Hogan 			      void *symval, char *alias)
11788286ae03SJames Hogan {
11798286ae03SJames Hogan 	DEF_FIELD(symval, mips_cdmm_device_id, type);
11808286ae03SJames Hogan 
11818286ae03SJames Hogan 	sprintf(alias, "mipscdmm:t%02X*", type);
11828286ae03SJames Hogan 	return 1;
11838286ae03SJames Hogan }
11848286ae03SJames Hogan 
11852b9c1f03SArd Biesheuvel /* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
1186644e9cbbSAndi Kleen  * All fields are numbers. It would be nicer to use strings for vendor
1187644e9cbbSAndi Kleen  * and feature, but getting those out of the build system here is too
1188644e9cbbSAndi Kleen  * complicated.
1189644e9cbbSAndi Kleen  */
1190644e9cbbSAndi Kleen 
11916543becfSAndreas Schwab static int do_x86cpu_entry(const char *filename, void *symval,
1192644e9cbbSAndi Kleen 			   char *alias)
1193644e9cbbSAndi Kleen {
11946543becfSAndreas Schwab 	DEF_FIELD(symval, x86_cpu_id, feature);
11956543becfSAndreas Schwab 	DEF_FIELD(symval, x86_cpu_id, family);
11966543becfSAndreas Schwab 	DEF_FIELD(symval, x86_cpu_id, model);
11976543becfSAndreas Schwab 	DEF_FIELD(symval, x86_cpu_id, vendor);
1198644e9cbbSAndi Kleen 
11992b9c1f03SArd Biesheuvel 	strcpy(alias, "cpu:type:x86,");
12002b9c1f03SArd Biesheuvel 	ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
12012b9c1f03SArd Biesheuvel 	ADD(alias, "fam", family != X86_FAMILY_ANY, family);
12022b9c1f03SArd Biesheuvel 	ADD(alias, "mod", model  != X86_MODEL_ANY,  model);
12035467bddaSBen Hutchings 	strcat(alias, ":feature:*");
12046543becfSAndreas Schwab 	if (feature != X86_FEATURE_ANY)
12056543becfSAndreas Schwab 		sprintf(alias + strlen(alias), "%04X*", feature);
1206644e9cbbSAndi Kleen 	return 1;
1207644e9cbbSAndi Kleen }
1208644e9cbbSAndi Kleen 
120967bad2fdSArd Biesheuvel /* LOOKS like cpu:type:*:feature:*FEAT* */
121067bad2fdSArd Biesheuvel static int do_cpu_entry(const char *filename, void *symval, char *alias)
121167bad2fdSArd Biesheuvel {
121267bad2fdSArd Biesheuvel 	DEF_FIELD(symval, cpu_feature, feature);
121367bad2fdSArd Biesheuvel 
121467bad2fdSArd Biesheuvel 	sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
121567bad2fdSArd Biesheuvel 	return 1;
121667bad2fdSArd Biesheuvel }
121767bad2fdSArd Biesheuvel 
1218b26864caSTomas Winkler /* Looks like: mei:S:uuid:N:* */
1219e5354107SSamuel Ortiz static int do_mei_entry(const char *filename, void *symval,
1220e5354107SSamuel Ortiz 			char *alias)
1221e5354107SSamuel Ortiz {
1222e5354107SSamuel Ortiz 	DEF_FIELD_ADDR(symval, mei_cl_device_id, name);
1223c93b76b3STomas Winkler 	DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid);
1224b26864caSTomas Winkler 	DEF_FIELD(symval, mei_cl_device_id, version);
1225e5354107SSamuel Ortiz 
1226c93b76b3STomas Winkler 	sprintf(alias, MEI_CL_MODULE_PREFIX);
1227c93b76b3STomas Winkler 	sprintf(alias + strlen(alias), "%s:",  (*name)[0]  ? *name : "*");
1228c93b76b3STomas Winkler 	add_uuid(alias, *uuid);
1229b26864caSTomas Winkler 	ADD(alias, ":", version != MEI_CL_VERSION_ANY, version);
1230c93b76b3STomas Winkler 
1231c93b76b3STomas Winkler 	strcat(alias, ":*");
1232e5354107SSamuel Ortiz 
1233e5354107SSamuel Ortiz 	return 1;
1234e5354107SSamuel Ortiz }
1235e5354107SSamuel Ortiz 
12363bdbb62fSAlexandre Bounine /* Looks like: rapidio:vNdNavNadN */
12373bdbb62fSAlexandre Bounine static int do_rio_entry(const char *filename,
12383bdbb62fSAlexandre Bounine 			void *symval, char *alias)
12393bdbb62fSAlexandre Bounine {
12403bdbb62fSAlexandre Bounine 	DEF_FIELD(symval, rio_device_id, did);
12413bdbb62fSAlexandre Bounine 	DEF_FIELD(symval, rio_device_id, vid);
12423bdbb62fSAlexandre Bounine 	DEF_FIELD(symval, rio_device_id, asm_did);
12433bdbb62fSAlexandre Bounine 	DEF_FIELD(symval, rio_device_id, asm_vid);
12443bdbb62fSAlexandre Bounine 
12453bdbb62fSAlexandre Bounine 	strcpy(alias, "rapidio:");
12463bdbb62fSAlexandre Bounine 	ADD(alias, "v", vid != RIO_ANY_ID, vid);
12473bdbb62fSAlexandre Bounine 	ADD(alias, "d", did != RIO_ANY_ID, did);
12483bdbb62fSAlexandre Bounine 	ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid);
12493bdbb62fSAlexandre Bounine 	ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did);
12503bdbb62fSAlexandre Bounine 
12513bdbb62fSAlexandre Bounine 	add_wildcard(alias);
12523bdbb62fSAlexandre Bounine 	return 1;
12533bdbb62fSAlexandre Bounine }
12543bdbb62fSAlexandre Bounine 
1255289fcff4SHeikki Krogerus /* Looks like: ulpi:vNpN */
1256289fcff4SHeikki Krogerus static int do_ulpi_entry(const char *filename, void *symval,
1257289fcff4SHeikki Krogerus 			 char *alias)
1258289fcff4SHeikki Krogerus {
1259289fcff4SHeikki Krogerus 	DEF_FIELD(symval, ulpi_device_id, vendor);
1260289fcff4SHeikki Krogerus 	DEF_FIELD(symval, ulpi_device_id, product);
1261289fcff4SHeikki Krogerus 
1262289fcff4SHeikki Krogerus 	sprintf(alias, "ulpi:v%04xp%04x", vendor, product);
1263289fcff4SHeikki Krogerus 
1264289fcff4SHeikki Krogerus 	return 1;
1265289fcff4SHeikki Krogerus }
1266289fcff4SHeikki Krogerus 
1267da23ac1eSSubhransu S. Prusty /* Looks like: hdaudio:vNrNaN */
1268da23ac1eSSubhransu S. Prusty static int do_hda_entry(const char *filename, void *symval, char *alias)
1269da23ac1eSSubhransu S. Prusty {
1270da23ac1eSSubhransu S. Prusty 	DEF_FIELD(symval, hda_device_id, vendor_id);
1271da23ac1eSSubhransu S. Prusty 	DEF_FIELD(symval, hda_device_id, rev_id);
1272da23ac1eSSubhransu S. Prusty 	DEF_FIELD(symval, hda_device_id, api_version);
1273da23ac1eSSubhransu S. Prusty 
1274da23ac1eSSubhransu S. Prusty 	strcpy(alias, "hdaudio:");
1275da23ac1eSSubhransu S. Prusty 	ADD(alias, "v", vendor_id != 0, vendor_id);
1276da23ac1eSSubhransu S. Prusty 	ADD(alias, "r", rev_id != 0, rev_id);
1277da23ac1eSSubhransu S. Prusty 	ADD(alias, "a", api_version != 0, api_version);
1278da23ac1eSSubhransu S. Prusty 
1279da23ac1eSSubhransu S. Prusty 	add_wildcard(alias);
1280da23ac1eSSubhransu S. Prusty 	return 1;
1281da23ac1eSSubhransu S. Prusty }
1282da23ac1eSSubhransu S. Prusty 
1283b5924268SPierre-Louis Bossart /* Looks like: sdw:mNpNvNcN */
12849251345dSVinod Koul static int do_sdw_entry(const char *filename, void *symval, char *alias)
12859251345dSVinod Koul {
12869251345dSVinod Koul 	DEF_FIELD(symval, sdw_device_id, mfg_id);
12879251345dSVinod Koul 	DEF_FIELD(symval, sdw_device_id, part_id);
1288b5924268SPierre-Louis Bossart 	DEF_FIELD(symval, sdw_device_id, sdw_version);
1289b5924268SPierre-Louis Bossart 	DEF_FIELD(symval, sdw_device_id, class_id);
12909251345dSVinod Koul 
12919251345dSVinod Koul 	strcpy(alias, "sdw:");
12929251345dSVinod Koul 	ADD(alias, "m", mfg_id != 0, mfg_id);
12939251345dSVinod Koul 	ADD(alias, "p", part_id != 0, part_id);
1294b5924268SPierre-Louis Bossart 	ADD(alias, "v", sdw_version != 0, sdw_version);
1295b5924268SPierre-Louis Bossart 	ADD(alias, "c", class_id != 0, class_id);
12969251345dSVinod Koul 
12979251345dSVinod Koul 	add_wildcard(alias);
12989251345dSVinod Koul 	return 1;
12999251345dSVinod Koul }
13009251345dSVinod Koul 
13010afef456SStuart Yoder /* Looks like: fsl-mc:vNdN */
13020afef456SStuart Yoder static int do_fsl_mc_entry(const char *filename, void *symval,
13030afef456SStuart Yoder 			   char *alias)
13040afef456SStuart Yoder {
13050afef456SStuart Yoder 	DEF_FIELD(symval, fsl_mc_device_id, vendor);
13060afef456SStuart Yoder 	DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type);
13070afef456SStuart Yoder 
13080afef456SStuart Yoder 	sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type);
13090afef456SStuart Yoder 	return 1;
13100afef456SStuart Yoder }
13110afef456SStuart Yoder 
1312d1ff7024SMika Westerberg /* Looks like: tbsvc:kSpNvNrN */
1313d1ff7024SMika Westerberg static int do_tbsvc_entry(const char *filename, void *symval, char *alias)
1314d1ff7024SMika Westerberg {
1315d1ff7024SMika Westerberg 	DEF_FIELD(symval, tb_service_id, match_flags);
1316d1ff7024SMika Westerberg 	DEF_FIELD_ADDR(symval, tb_service_id, protocol_key);
1317d1ff7024SMika Westerberg 	DEF_FIELD(symval, tb_service_id, protocol_id);
1318d1ff7024SMika Westerberg 	DEF_FIELD(symval, tb_service_id, protocol_version);
1319d1ff7024SMika Westerberg 	DEF_FIELD(symval, tb_service_id, protocol_revision);
1320d1ff7024SMika Westerberg 
1321d1ff7024SMika Westerberg 	strcpy(alias, "tbsvc:");
1322d1ff7024SMika Westerberg 	if (match_flags & TBSVC_MATCH_PROTOCOL_KEY)
1323d1ff7024SMika Westerberg 		sprintf(alias + strlen(alias), "k%s", *protocol_key);
1324d1ff7024SMika Westerberg 	else
1325d1ff7024SMika Westerberg 		strcat(alias + strlen(alias), "k*");
1326d1ff7024SMika Westerberg 	ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id);
1327d1ff7024SMika Westerberg 	ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION,
1328d1ff7024SMika Westerberg 	    protocol_version);
1329d1ff7024SMika Westerberg 	ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION,
1330d1ff7024SMika Westerberg 	    protocol_revision);
1331d1ff7024SMika Westerberg 
1332d1ff7024SMika Westerberg 	add_wildcard(alias);
1333d1ff7024SMika Westerberg 	return 1;
1334d1ff7024SMika Westerberg }
1335d1ff7024SMika Westerberg 
13368a37d87dSHeikki Krogerus /* Looks like: typec:idNmN */
13378a37d87dSHeikki Krogerus static int do_typec_entry(const char *filename, void *symval, char *alias)
13388a37d87dSHeikki Krogerus {
13398a37d87dSHeikki Krogerus 	DEF_FIELD(symval, typec_device_id, svid);
13408a37d87dSHeikki Krogerus 	DEF_FIELD(symval, typec_device_id, mode);
13418a37d87dSHeikki Krogerus 
13428a37d87dSHeikki Krogerus 	sprintf(alias, "typec:id%04X", svid);
13438a37d87dSHeikki Krogerus 	ADD(alias, "m", mode != TYPEC_ANY_MODE, mode);
13448a37d87dSHeikki Krogerus 
13458a37d87dSHeikki Krogerus 	return 1;
13468a37d87dSHeikki Krogerus }
13478a37d87dSHeikki Krogerus 
13480fc1db9dSSumit Garg /* Looks like: tee:uuid */
13490fc1db9dSSumit Garg static int do_tee_entry(const char *filename, void *symval, char *alias)
13500fc1db9dSSumit Garg {
13510fc1db9dSSumit Garg 	DEF_FIELD(symval, tee_client_device_id, uuid);
13520fc1db9dSSumit Garg 
13530fc1db9dSSumit Garg 	sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
13540fc1db9dSSumit Garg 		uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4],
13550fc1db9dSSumit Garg 		uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9],
13560fc1db9dSSumit Garg 		uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14],
13570fc1db9dSSumit Garg 		uuid.b[15]);
13580fc1db9dSSumit Garg 
13590fc1db9dSSumit Garg 	add_wildcard(alias);
13600fc1db9dSSumit Garg 	return 1;
13610fc1db9dSSumit Garg }
13620fc1db9dSSumit Garg 
13630bc44b2bSMattias Jacobsson /* Looks like: wmi:guid */
13640bc44b2bSMattias Jacobsson static int do_wmi_entry(const char *filename, void *symval, char *alias)
13650bc44b2bSMattias Jacobsson {
13660bc44b2bSMattias Jacobsson 	int len;
13670bc44b2bSMattias Jacobsson 	DEF_FIELD_ADDR(symval, wmi_device_id, guid_string);
13680bc44b2bSMattias Jacobsson 
13690bc44b2bSMattias Jacobsson 	if (strlen(*guid_string) != UUID_STRING_LEN) {
13700bc44b2bSMattias Jacobsson 		warn("Invalid WMI device id 'wmi:%s' in '%s'\n",
13710bc44b2bSMattias Jacobsson 				*guid_string, filename);
13720bc44b2bSMattias Jacobsson 		return 0;
13730bc44b2bSMattias Jacobsson 	}
13740bc44b2bSMattias Jacobsson 
13750bc44b2bSMattias Jacobsson 	len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string);
13760bc44b2bSMattias Jacobsson 	if (len < 0 || len >= ALIAS_SIZE) {
13770bc44b2bSMattias Jacobsson 		warn("Could not generate all MODULE_ALIAS's in '%s'\n",
13780bc44b2bSMattias Jacobsson 				filename);
13790bc44b2bSMattias Jacobsson 		return 0;
13800bc44b2bSMattias Jacobsson 	}
13810bc44b2bSMattias Jacobsson 	return 1;
13820bc44b2bSMattias Jacobsson }
13830bc44b2bSMattias Jacobsson 
1384e6b0de46SManivannan Sadhasivam /* Looks like: mhi:S */
1385e6b0de46SManivannan Sadhasivam static int do_mhi_entry(const char *filename, void *symval, char *alias)
1386e6b0de46SManivannan Sadhasivam {
1387e6b0de46SManivannan Sadhasivam 	DEF_FIELD_ADDR(symval, mhi_device_id, chan);
1388e6b0de46SManivannan Sadhasivam 	sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan);
13897de3697eSDave Ertman 	return 1;
13907de3697eSDave Ertman }
13917de3697eSDave Ertman 
1392c268c0a8SManivannan Sadhasivam /* Looks like: mhi_ep:S */
1393c268c0a8SManivannan Sadhasivam static int do_mhi_ep_entry(const char *filename, void *symval, char *alias)
1394c268c0a8SManivannan Sadhasivam {
1395c268c0a8SManivannan Sadhasivam 	DEF_FIELD_ADDR(symval, mhi_device_id, chan);
1396c268c0a8SManivannan Sadhasivam 	sprintf(alias, MHI_EP_DEVICE_MODALIAS_FMT, *chan);
1397c268c0a8SManivannan Sadhasivam 
1398c268c0a8SManivannan Sadhasivam 	return 1;
1399c268c0a8SManivannan Sadhasivam }
1400c268c0a8SManivannan Sadhasivam 
1401fa443bc3SThomas Weißschuh /* Looks like: ishtp:{guid} */
1402fa443bc3SThomas Weißschuh static int do_ishtp_entry(const char *filename, void *symval, char *alias)
1403fa443bc3SThomas Weißschuh {
1404fa443bc3SThomas Weißschuh 	DEF_FIELD(symval, ishtp_device_id, guid);
1405fa443bc3SThomas Weißschuh 
1406fa443bc3SThomas Weißschuh 	strcpy(alias, ISHTP_MODULE_PREFIX "{");
1407fa443bc3SThomas Weißschuh 	add_guid(alias, guid);
1408fa443bc3SThomas Weißschuh 	strcat(alias, "}");
1409fa443bc3SThomas Weißschuh 
1410fa443bc3SThomas Weißschuh 	return 1;
1411fa443bc3SThomas Weißschuh }
1412fa443bc3SThomas Weißschuh 
14137de3697eSDave Ertman static int do_auxiliary_entry(const char *filename, void *symval, char *alias)
14147de3697eSDave Ertman {
14157de3697eSDave Ertman 	DEF_FIELD_ADDR(symval, auxiliary_device_id, name);
14167de3697eSDave Ertman 	sprintf(alias, AUXILIARY_MODULE_PREFIX "%s", *name);
1417e6b0de46SManivannan Sadhasivam 
1418e6b0de46SManivannan Sadhasivam 	return 1;
1419e6b0de46SManivannan Sadhasivam }
1420e6b0de46SManivannan Sadhasivam 
1421eb0e90a8SMaximilian Luz /*
1422eb0e90a8SMaximilian Luz  * Looks like: ssam:dNcNtNiNfN
1423eb0e90a8SMaximilian Luz  *
1424eb0e90a8SMaximilian Luz  * N is exactly 2 digits, where each is an upper-case hex digit.
1425eb0e90a8SMaximilian Luz  */
1426eb0e90a8SMaximilian Luz static int do_ssam_entry(const char *filename, void *symval, char *alias)
1427eb0e90a8SMaximilian Luz {
1428eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, match_flags);
1429eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, domain);
1430eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, category);
1431eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, target);
1432eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, instance);
1433eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, function);
1434eb0e90a8SMaximilian Luz 
1435eb0e90a8SMaximilian Luz 	sprintf(alias, "ssam:d%02Xc%02X", domain, category);
1436eb0e90a8SMaximilian Luz 	ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target);
1437eb0e90a8SMaximilian Luz 	ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance);
1438eb0e90a8SMaximilian Luz 	ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function);
1439eb0e90a8SMaximilian Luz 
1440eb0e90a8SMaximilian Luz 	return 1;
1441eb0e90a8SMaximilian Luz }
1442eb0e90a8SMaximilian Luz 
14434a224aceSXu Yilun /* Looks like: dfl:tNfN */
14444a224aceSXu Yilun static int do_dfl_entry(const char *filename, void *symval, char *alias)
14454a224aceSXu Yilun {
14464a224aceSXu Yilun 	DEF_FIELD(symval, dfl_device_id, type);
14474a224aceSXu Yilun 	DEF_FIELD(symval, dfl_device_id, feature_id);
14484a224aceSXu Yilun 
14494a224aceSXu Yilun 	sprintf(alias, "dfl:t%04Xf%04X", type, feature_id);
14504a224aceSXu Yilun 
14514a224aceSXu Yilun 	add_wildcard(alias);
14524a224aceSXu Yilun 	return 1;
14534a224aceSXu Yilun }
14544a224aceSXu Yilun 
14552959ab24SNipun Gupta /* Looks like: cdx:vNdN */
14562959ab24SNipun Gupta static int do_cdx_entry(const char *filename, void *symval,
14572959ab24SNipun Gupta 			char *alias)
14582959ab24SNipun Gupta {
14592959ab24SNipun Gupta 	DEF_FIELD(symval, cdx_device_id, vendor);
14602959ab24SNipun Gupta 	DEF_FIELD(symval, cdx_device_id, device);
1461234489acSNipun Gupta 	DEF_FIELD(symval, cdx_device_id, override_only);
14622959ab24SNipun Gupta 
1463234489acSNipun Gupta 	switch (override_only) {
1464234489acSNipun Gupta 	case 0:
1465234489acSNipun Gupta 		strcpy(alias, "cdx:");
1466234489acSNipun Gupta 		break;
1467234489acSNipun Gupta 	case CDX_ID_F_VFIO_DRIVER_OVERRIDE:
1468234489acSNipun Gupta 		strcpy(alias, "vfio_cdx:");
1469234489acSNipun Gupta 		break;
1470234489acSNipun Gupta 	default:
1471234489acSNipun Gupta 		warn("Unknown CDX driver_override alias %08X\n",
1472234489acSNipun Gupta 		     override_only);
1473234489acSNipun Gupta 		return 0;
1474234489acSNipun Gupta 	}
1475234489acSNipun Gupta 
1476234489acSNipun Gupta 	ADD(alias, "v", vendor != CDX_ANY_ID, vendor);
1477234489acSNipun Gupta 	ADD(alias, "d", device != CDX_ANY_ID, device);
14782959ab24SNipun Gupta 	return 1;
14792959ab24SNipun Gupta }
14802959ab24SNipun Gupta 
1481*1fa05877SUmang Jain static int do_vchiq_entry(const char *filename, void *symval, char *alias)
1482*1fa05877SUmang Jain {
1483*1fa05877SUmang Jain 	DEF_FIELD_ADDR(symval, vchiq_device_id, name);
1484*1fa05877SUmang Jain 	sprintf(alias, "vchiq:%s", *name);
1485*1fa05877SUmang Jain 
1486*1fa05877SUmang Jain 	return 1;
1487*1fa05877SUmang Jain }
1488*1fa05877SUmang Jain 
1489626596e2SRusty Russell /* Does namelen bytes of name exactly match the symbol? */
1490626596e2SRusty Russell static bool sym_is(const char *name, unsigned namelen, const char *symbol)
14911da177e4SLinus Torvalds {
1492626596e2SRusty Russell 	if (namelen != strlen(symbol))
1493626596e2SRusty Russell 		return false;
14941da177e4SLinus Torvalds 
1495626596e2SRusty Russell 	return memcmp(name, symbol, namelen) == 0;
14961da177e4SLinus Torvalds }
14971da177e4SLinus Torvalds 
14981da177e4SLinus Torvalds static void do_table(void *symval, unsigned long size,
14991da177e4SLinus Torvalds 		     unsigned long id_size,
1500fb33d816SSam Ravnborg 		     const char *device_id,
1501f880eea6SMasahiro Yamada 		     int (*do_entry)(const char *filename, void *symval, char *alias),
15021da177e4SLinus Torvalds 		     struct module *mod)
15031da177e4SLinus Torvalds {
15041da177e4SLinus Torvalds 	unsigned int i;
1505841f1b8fSMattias Jacobsson 	char alias[ALIAS_SIZE];
15061da177e4SLinus Torvalds 
1507e0049825SKees Cook 	device_id_check(mod->name, device_id, size, id_size, symval);
15081da177e4SLinus Torvalds 	/* Leave last one: it's the terminator. */
15091da177e4SLinus Torvalds 	size -= id_size;
15101da177e4SLinus Torvalds 
15111da177e4SLinus Torvalds 	for (i = 0; i < size; i += id_size) {
15121da177e4SLinus Torvalds 		if (do_entry(mod->name, symval+i, alias)) {
15131da177e4SLinus Torvalds 			buf_printf(&mod->dev_table_buf,
15141da177e4SLinus Torvalds 				   "MODULE_ALIAS(\"%s\");\n", alias);
15151da177e4SLinus Torvalds 		}
15161da177e4SLinus Torvalds 	}
15171da177e4SLinus Torvalds }
15181da177e4SLinus Torvalds 
1519ec91e78dSMasahiro Yamada static const struct devtable devtable[] = {
1520ec91e78dSMasahiro Yamada 	{"hid", SIZE_hid_device_id, do_hid_entry},
1521ec91e78dSMasahiro Yamada 	{"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry},
1522ec91e78dSMasahiro Yamada 	{"pci", SIZE_pci_device_id, do_pci_entry},
1523ec91e78dSMasahiro Yamada 	{"ccw", SIZE_ccw_device_id, do_ccw_entry},
1524ec91e78dSMasahiro Yamada 	{"ap", SIZE_ap_device_id, do_ap_entry},
1525ec91e78dSMasahiro Yamada 	{"css", SIZE_css_device_id, do_css_entry},
1526ec91e78dSMasahiro Yamada 	{"serio", SIZE_serio_device_id, do_serio_entry},
1527ec91e78dSMasahiro Yamada 	{"acpi", SIZE_acpi_device_id, do_acpi_entry},
1528ec91e78dSMasahiro Yamada 	{"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry},
1529ec91e78dSMasahiro Yamada 	{"vio", SIZE_vio_device_id, do_vio_entry},
1530ec91e78dSMasahiro Yamada 	{"input", SIZE_input_device_id, do_input_entry},
1531ec91e78dSMasahiro Yamada 	{"eisa", SIZE_eisa_device_id, do_eisa_entry},
1532ec91e78dSMasahiro Yamada 	{"parisc", SIZE_parisc_device_id, do_parisc_entry},
1533ec91e78dSMasahiro Yamada 	{"sdio", SIZE_sdio_device_id, do_sdio_entry},
1534ec91e78dSMasahiro Yamada 	{"ssb", SIZE_ssb_device_id, do_ssb_entry},
1535ec91e78dSMasahiro Yamada 	{"bcma", SIZE_bcma_device_id, do_bcma_entry},
1536ec91e78dSMasahiro Yamada 	{"virtio", SIZE_virtio_device_id, do_virtio_entry},
1537ec91e78dSMasahiro Yamada 	{"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry},
1538ec91e78dSMasahiro Yamada 	{"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry},
1539ec91e78dSMasahiro Yamada 	{"i2c", SIZE_i2c_device_id, do_i2c_entry},
15401ce589adSBoris Brezillon 	{"i3c", SIZE_i3c_device_id, do_i3c_entry},
1541ec91e78dSMasahiro Yamada 	{"spi", SIZE_spi_device_id, do_spi_entry},
1542ec91e78dSMasahiro Yamada 	{"dmi", SIZE_dmi_system_id, do_dmi_entry},
1543ec91e78dSMasahiro Yamada 	{"platform", SIZE_platform_device_id, do_platform_entry},
1544ec91e78dSMasahiro Yamada 	{"mdio", SIZE_mdio_device_id, do_mdio_entry},
1545ec91e78dSMasahiro Yamada 	{"zorro", SIZE_zorro_device_id, do_zorro_entry},
1546ec91e78dSMasahiro Yamada 	{"isapnp", SIZE_isapnp_device_id, do_isapnp_entry},
1547ec91e78dSMasahiro Yamada 	{"ipack", SIZE_ipack_device_id, do_ipack_entry},
1548ec91e78dSMasahiro Yamada 	{"amba", SIZE_amba_id, do_amba_entry},
1549ec91e78dSMasahiro Yamada 	{"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry},
1550ec91e78dSMasahiro Yamada 	{"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry},
1551ec91e78dSMasahiro Yamada 	{"cpu", SIZE_cpu_feature, do_cpu_entry},
1552ec91e78dSMasahiro Yamada 	{"mei", SIZE_mei_cl_device_id, do_mei_entry},
1553ec91e78dSMasahiro Yamada 	{"rapidio", SIZE_rio_device_id, do_rio_entry},
1554ec91e78dSMasahiro Yamada 	{"ulpi", SIZE_ulpi_device_id, do_ulpi_entry},
1555ec91e78dSMasahiro Yamada 	{"hdaudio", SIZE_hda_device_id, do_hda_entry},
1556ec91e78dSMasahiro Yamada 	{"sdw", SIZE_sdw_device_id, do_sdw_entry},
1557ec91e78dSMasahiro Yamada 	{"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry},
1558ec91e78dSMasahiro Yamada 	{"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
1559ec91e78dSMasahiro Yamada 	{"typec", SIZE_typec_device_id, do_typec_entry},
15600fc1db9dSSumit Garg 	{"tee", SIZE_tee_client_device_id, do_tee_entry},
15610bc44b2bSMattias Jacobsson 	{"wmi", SIZE_wmi_device_id, do_wmi_entry},
1562e6b0de46SManivannan Sadhasivam 	{"mhi", SIZE_mhi_device_id, do_mhi_entry},
1563c268c0a8SManivannan Sadhasivam 	{"mhi_ep", SIZE_mhi_device_id, do_mhi_ep_entry},
15647de3697eSDave Ertman 	{"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry},
1565eb0e90a8SMaximilian Luz 	{"ssam", SIZE_ssam_device_id, do_ssam_entry},
15664a224aceSXu Yilun 	{"dfl", SIZE_dfl_device_id, do_dfl_entry},
1567fa443bc3SThomas Weißschuh 	{"ishtp", SIZE_ishtp_device_id, do_ishtp_entry},
15682959ab24SNipun Gupta 	{"cdx", SIZE_cdx_device_id, do_cdx_entry},
1569*1fa05877SUmang Jain 	{"vchiq", SIZE_vchiq_device_id, do_vchiq_entry},
1570ec91e78dSMasahiro Yamada };
1571ec91e78dSMasahiro Yamada 
15721da177e4SLinus Torvalds /* Create MODULE_ALIAS() statements.
15731da177e4SLinus Torvalds  * At this time, we cannot write the actual output C source yet,
15741da177e4SLinus Torvalds  * so we write into the mod->dev_table_buf buffer. */
15751da177e4SLinus Torvalds void handle_moddevtable(struct module *mod, struct elf_info *info,
15761da177e4SLinus Torvalds 			Elf_Sym *sym, const char *symname)
15771da177e4SLinus Torvalds {
15781da177e4SLinus Torvalds 	void *symval;
1579e0049825SKees Cook 	char *zeros = NULL;
158021bdd17bSTom Gundersen 	const char *name, *identifier;
1581626596e2SRusty Russell 	unsigned int namelen;
15821da177e4SLinus Torvalds 
15831da177e4SLinus Torvalds 	/* We're looking for a section relative symbol */
15841ce53adfSDenys Vlasenko 	if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
15851da177e4SLinus Torvalds 		return;
15861da177e4SLinus Torvalds 
1587e88aa7bbSDavid Miller 	/* We're looking for an object */
1588e88aa7bbSDavid Miller 	if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
1589e88aa7bbSDavid Miller 		return;
1590e88aa7bbSDavid Miller 
1591153e04b3SMasahiro Yamada 	/* All our symbols are of form __mod_<name>__<identifier>_device_table. */
1592153e04b3SMasahiro Yamada 	if (strncmp(symname, "__mod_", strlen("__mod_")))
1593626596e2SRusty Russell 		return;
1594153e04b3SMasahiro Yamada 	name = symname + strlen("__mod_");
1595626596e2SRusty Russell 	namelen = strlen(name);
1596626596e2SRusty Russell 	if (namelen < strlen("_device_table"))
1597626596e2SRusty Russell 		return;
1598626596e2SRusty Russell 	if (strcmp(name + namelen - strlen("_device_table"), "_device_table"))
1599626596e2SRusty Russell 		return;
160021bdd17bSTom Gundersen 	identifier = strstr(name, "__");
160121bdd17bSTom Gundersen 	if (!identifier)
160221bdd17bSTom Gundersen 		return;
160321bdd17bSTom Gundersen 	namelen = identifier - name;
1604626596e2SRusty Russell 
1605e0049825SKees Cook 	/* Handle all-NULL symbols allocated into .bss */
16061ce53adfSDenys Vlasenko 	if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
1607e0049825SKees Cook 		zeros = calloc(1, sym->st_size);
1608e0049825SKees Cook 		symval = zeros;
1609e0049825SKees Cook 	} else {
1610abe864b8SMasahiro Yamada 		symval = sym_get_data(info, sym);
1611e0049825SKees Cook 	}
16121da177e4SLinus Torvalds 
1613626596e2SRusty Russell 	/* First handle the "special" cases */
1614626596e2SRusty Russell 	if (sym_is(name, namelen, "usb"))
1615b19dcd93SRoman Kagan 		do_usb_table(symval, sym->st_size, mod);
1616acbef7b7SPhilipp Zabel 	if (sym_is(name, namelen, "of"))
1617acbef7b7SPhilipp Zabel 		do_of_table(symval, sym->st_size, mod);
1618626596e2SRusty Russell 	else if (sym_is(name, namelen, "pnp"))
161922454cb9SKay Sievers 		do_pnp_device_entry(symval, sym->st_size, mod);
1620626596e2SRusty Russell 	else if (sym_is(name, namelen, "pnp_card"))
16210c81eed4SKay Sievers 		do_pnp_card_entries(symval, sym->st_size, mod);
1622626596e2SRusty Russell 	else {
1623ec91e78dSMasahiro Yamada 		int i;
1624626596e2SRusty Russell 
1625ec91e78dSMasahiro Yamada 		for (i = 0; i < ARRAY_SIZE(devtable); i++) {
1626ec91e78dSMasahiro Yamada 			const struct devtable *p = &devtable[i];
1627ec91e78dSMasahiro Yamada 
1628ec91e78dSMasahiro Yamada 			if (sym_is(name, namelen, p->device_id)) {
1629ec91e78dSMasahiro Yamada 				do_table(symval, sym->st_size, p->id_size,
1630f880eea6SMasahiro Yamada 					 p->device_id, p->do_entry, mod);
1631626596e2SRusty Russell 				break;
1632626596e2SRusty Russell 			}
1633626596e2SRusty Russell 		}
1634626596e2SRusty Russell 	}
1635e0049825SKees Cook 	free(zeros);
16361da177e4SLinus Torvalds }
16371da177e4SLinus Torvalds 
16381da177e4SLinus Torvalds /* Now add out buffered information to the generated C source */
16391da177e4SLinus Torvalds void add_moddevtable(struct buffer *buf, struct module *mod)
16401da177e4SLinus Torvalds {
16411da177e4SLinus Torvalds 	buf_printf(buf, "\n");
16421da177e4SLinus Torvalds 	buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
16431da177e4SLinus Torvalds 	free(mod->dev_table_buf.p);
16441da177e4SLinus Torvalds }
1645