xref: /linux-6.15/scripts/mod/file2alias.c (revision 8fe1a63d)
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 
13f4fdb17cSMasahiro Yamada #include <stdarg.h>
14f4fdb17cSMasahiro Yamada #include <stdio.h>
15f4fdb17cSMasahiro Yamada 
16f4fdb17cSMasahiro Yamada #include "list.h"
17f4fdb17cSMasahiro Yamada #include "xalloc.h"
18f4fdb17cSMasahiro Yamada 
191da177e4SLinus Torvalds #include "modpost.h"
206543becfSAndreas Schwab #include "devicetable-offsets.h"
211da177e4SLinus Torvalds 
221da177e4SLinus Torvalds /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
231da177e4SLinus Torvalds  * use either stdint.h or inttypes.h for the rest. */
241da177e4SLinus Torvalds #if KERNEL_ELFCLASS == ELFCLASS32
251da177e4SLinus Torvalds typedef Elf32_Addr	kernel_ulong_t;
261d8f430cSRusty Russell #define BITS_PER_LONG 32
271da177e4SLinus Torvalds #else
281da177e4SLinus Torvalds typedef Elf64_Addr	kernel_ulong_t;
291d8f430cSRusty Russell #define BITS_PER_LONG 64
301da177e4SLinus Torvalds #endif
311da177e4SLinus Torvalds #ifdef __sun__
321da177e4SLinus Torvalds #include <inttypes.h>
331da177e4SLinus Torvalds #else
341da177e4SLinus Torvalds #include <stdint.h>
351da177e4SLinus Torvalds #endif
361da177e4SLinus Torvalds 
375e655772SJeff Mahoney #include <ctype.h>
38626596e2SRusty Russell #include <stdbool.h>
395e655772SJeff Mahoney 
40f4fdb17cSMasahiro Yamada /**
41f4fdb17cSMasahiro Yamada  * module_alias_printf - add auto-generated MODULE_ALIAS()
42f4fdb17cSMasahiro Yamada  *
43f4fdb17cSMasahiro Yamada  * @mod: module
44f4fdb17cSMasahiro Yamada  * @append_wildcard: append '*' for future extension if not exist yet
45f4fdb17cSMasahiro Yamada  * @fmt: printf(3)-like format
46f4fdb17cSMasahiro Yamada  */
47f4fdb17cSMasahiro Yamada static void __attribute__((format (printf, 3, 4)))
module_alias_printf(struct module * mod,bool append_wildcard,const char * fmt,...)48f4fdb17cSMasahiro Yamada module_alias_printf(struct module *mod, bool append_wildcard,
49f4fdb17cSMasahiro Yamada 		    const char *fmt, ...)
50f4fdb17cSMasahiro Yamada {
51d92b7a3bSMasahiro Yamada 	struct module_alias *new, *als;
52f4fdb17cSMasahiro Yamada 	size_t len;
53f4fdb17cSMasahiro Yamada 	int n;
54f4fdb17cSMasahiro Yamada 	va_list ap;
55f4fdb17cSMasahiro Yamada 
56f4fdb17cSMasahiro Yamada 	/* Determine required size. */
57f4fdb17cSMasahiro Yamada 	va_start(ap, fmt);
58f4fdb17cSMasahiro Yamada 	n = vsnprintf(NULL, 0, fmt, ap);
59f4fdb17cSMasahiro Yamada 	va_end(ap);
60f4fdb17cSMasahiro Yamada 
61f4fdb17cSMasahiro Yamada 	if (n < 0) {
62f4fdb17cSMasahiro Yamada 		error("vsnprintf failed\n");
63f4fdb17cSMasahiro Yamada 		return;
64f4fdb17cSMasahiro Yamada 	}
65f4fdb17cSMasahiro Yamada 
66f4fdb17cSMasahiro Yamada 	len = n + 1;	/* extra byte for '\0' */
67f4fdb17cSMasahiro Yamada 
68f4fdb17cSMasahiro Yamada 	if (append_wildcard)
69f4fdb17cSMasahiro Yamada 		len++;	/* extra byte for '*' */
70f4fdb17cSMasahiro Yamada 
71f4fdb17cSMasahiro Yamada 	new = xmalloc(sizeof(*new) + len);
72f4fdb17cSMasahiro Yamada 
73f4fdb17cSMasahiro Yamada 	/* Now, really print it to the allocated buffer */
74f4fdb17cSMasahiro Yamada 	va_start(ap, fmt);
75f4fdb17cSMasahiro Yamada 	n = vsnprintf(new->str, len, fmt, ap);
76f4fdb17cSMasahiro Yamada 	va_end(ap);
77f4fdb17cSMasahiro Yamada 
78f4fdb17cSMasahiro Yamada 	if (n < 0) {
79f4fdb17cSMasahiro Yamada 		error("vsnprintf failed\n");
80f4fdb17cSMasahiro Yamada 		free(new);
81f4fdb17cSMasahiro Yamada 		return;
82f4fdb17cSMasahiro Yamada 	}
83f4fdb17cSMasahiro Yamada 
84f4fdb17cSMasahiro Yamada 	if (append_wildcard && (n == 0 || new->str[n - 1] != '*')) {
85f4fdb17cSMasahiro Yamada 		new->str[n] = '*';
86f4fdb17cSMasahiro Yamada 		new->str[n + 1] = '\0';
87f4fdb17cSMasahiro Yamada 	}
88f4fdb17cSMasahiro Yamada 
89d92b7a3bSMasahiro Yamada 	/* avoid duplication */
90d92b7a3bSMasahiro Yamada 	list_for_each_entry(als, &mod->aliases, node) {
91d92b7a3bSMasahiro Yamada 		if (!strcmp(als->str, new->str)) {
92d92b7a3bSMasahiro Yamada 			free(new);
93d92b7a3bSMasahiro Yamada 			return;
94d92b7a3bSMasahiro Yamada 		}
95d92b7a3bSMasahiro Yamada 	}
96d92b7a3bSMasahiro Yamada 
97f4fdb17cSMasahiro Yamada 	list_add_tail(&new->node, &mod->aliases);
98f4fdb17cSMasahiro Yamada }
99f4fdb17cSMasahiro Yamada 
1001da177e4SLinus Torvalds typedef uint32_t	__u32;
1011da177e4SLinus Torvalds typedef uint16_t	__u16;
1021da177e4SLinus Torvalds typedef unsigned char	__u8;
10324804329SAndy Shevchenko 
10424804329SAndy Shevchenko /* UUID types for backward compatibility, don't use in new code */
105b144ce2dSGreg Kroah-Hartman typedef struct {
106b144ce2dSGreg Kroah-Hartman 	__u8 b[16];
107389c9af7SHeikki Krogerus } guid_t;
108389c9af7SHeikki Krogerus 
1090fc1db9dSSumit Garg typedef struct {
1100fc1db9dSSumit Garg 	__u8 b[16];
1110fc1db9dSSumit Garg } uuid_t;
11224804329SAndy Shevchenko 
113eacc95eaSMattias Jacobsson #define	UUID_STRING_LEN		36
1141da177e4SLinus Torvalds 
11524804329SAndy Shevchenko /* MEI UUID type, don't use anywhere else */
11624804329SAndy Shevchenko typedef struct {
11724804329SAndy Shevchenko 	__u8 b[16];
11824804329SAndy Shevchenko } uuid_le;
11924804329SAndy Shevchenko 
1201da177e4SLinus Torvalds /* Big exception to the "don't include kernel headers into userspace, which
1211da177e4SLinus Torvalds  * even potentially has different endianness and word sizes, since
1221da177e4SLinus Torvalds  * we handle those differences explicitly below */
1231da177e4SLinus Torvalds #include "../../include/linux/mod_devicetable.h"
1241da177e4SLinus Torvalds 
125e49ce141SRusty Russell struct devtable {
126054a9cd3SMasahiro Yamada 	const char *device_id;
127e49ce141SRusty Russell 	unsigned long id_size;
1286d3b3dd2SMasahiro Yamada 	void (*do_entry)(struct module *mod, void *symval);
129e49ce141SRusty Russell };
130e49ce141SRusty Russell 
1316543becfSAndreas Schwab /* Define a variable f that holds the value of field f of struct devid
1326543becfSAndreas Schwab  * based at address m.
1336543becfSAndreas Schwab  */
1346543becfSAndreas Schwab #define DEF_FIELD(m, devid, f) \
135*8fe1a63dSMasahiro Yamada 	typeof(((struct devid *)0)->f) f = \
136*8fe1a63dSMasahiro Yamada 		get_unaligned_native((typeof(f) *)((m) + OFF_##devid##_##f))
137c2b1a922SLeonardo Bras 
1386543becfSAndreas Schwab /* Define a variable f that holds the address of field f of struct devid
1396543becfSAndreas Schwab  * based at address m.  Due to the way typeof works, for a field of type
1406543becfSAndreas Schwab  * T[N] the variable has type T(*)[N], _not_ T*.
1416543becfSAndreas Schwab  */
1426543becfSAndreas Schwab #define DEF_FIELD_ADDR(m, devid, f) \
143c4d1a9f9SMasahiro Yamada 	typeof(((struct devid *)0)->f) *f = ((m) + OFF_##devid##_##f)
1446543becfSAndreas Schwab 
1451da177e4SLinus Torvalds #define ADD(str, sep, cond, field)                              \
1461da177e4SLinus Torvalds do {                                                            \
1471da177e4SLinus Torvalds         strcat(str, sep);                                       \
1481da177e4SLinus Torvalds         if (cond)                                               \
1491da177e4SLinus Torvalds                 sprintf(str + strlen(str),                      \
1501da177e4SLinus Torvalds                         sizeof(field) == 1 ? "%02X" :           \
1511da177e4SLinus Torvalds                         sizeof(field) == 2 ? "%04X" :           \
1521da177e4SLinus Torvalds                         sizeof(field) == 4 ? "%08X" : "",       \
1531da177e4SLinus Torvalds                         field);                                 \
1541da177e4SLinus Torvalds         else                                                    \
1551da177e4SLinus Torvalds                 sprintf(str + strlen(str), "*");                \
1561da177e4SLinus Torvalds } while(0)
1571da177e4SLinus Torvalds 
add_uuid(char * str,uuid_le uuid)158b144ce2dSGreg Kroah-Hartman static inline void add_uuid(char *str, uuid_le uuid)
159c93b76b3STomas Winkler {
160c93b76b3STomas Winkler 	int len = strlen(str);
161c93b76b3STomas Winkler 
16259796edcSPrarit Bhargava 	sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
16359796edcSPrarit Bhargava 		uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0],
16459796edcSPrarit Bhargava 		uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6],
16559796edcSPrarit Bhargava 		uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11],
16659796edcSPrarit Bhargava 		uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]);
167c93b76b3STomas Winkler }
168c93b76b3STomas Winkler 
add_guid(char * str,guid_t guid)169fa443bc3SThomas Weißschuh static inline void add_guid(char *str, guid_t guid)
170fa443bc3SThomas Weißschuh {
171fa443bc3SThomas Weißschuh 	int len = strlen(str);
172fa443bc3SThomas Weißschuh 
173fa443bc3SThomas Weißschuh 	sprintf(str + len, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
174fa443bc3SThomas Weißschuh 		guid.b[3], guid.b[2], guid.b[1], guid.b[0],
175fa443bc3SThomas Weißschuh 		guid.b[5], guid.b[4], guid.b[7], guid.b[6],
176fa443bc3SThomas Weißschuh 		guid.b[8], guid.b[9], guid.b[10], guid.b[11],
177fa443bc3SThomas Weißschuh 		guid.b[12], guid.b[13], guid.b[14], guid.b[15]);
178fa443bc3SThomas Weißschuh }
179fa443bc3SThomas Weißschuh 
180b19dcd93SRoman Kagan /* USB is special because the bcdDevice can be matched against a numeric range */
18181df2d59SBjørn Mork /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */
do_usb_entry(void * symval,unsigned int bcdDevice_initial,int bcdDevice_initial_digits,unsigned char range_lo,unsigned char range_hi,unsigned char max,struct module * mod)1826543becfSAndreas Schwab static void do_usb_entry(void *symval,
183b19dcd93SRoman Kagan 			 unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
184b19dcd93SRoman Kagan 			 unsigned char range_lo, unsigned char range_hi,
185afe2dab4SNathaniel McCallum 			 unsigned char max, struct module *mod)
1861da177e4SLinus Torvalds {
187b19dcd93SRoman Kagan 	char alias[500];
1886543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, match_flags);
1896543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, idVendor);
1906543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, idProduct);
1916543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
1926543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bDeviceClass);
1936543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bDeviceSubClass);
1946543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bDeviceProtocol);
1956543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bInterfaceClass);
1966543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bInterfaceSubClass);
1976543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bInterfaceProtocol);
1986543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bInterfaceNumber);
1996543becfSAndreas Schwab 
2001da177e4SLinus Torvalds 	strcpy(alias, "usb:");
2016543becfSAndreas Schwab 	ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR,
2026543becfSAndreas Schwab 	    idVendor);
2036543becfSAndreas Schwab 	ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
2046543becfSAndreas Schwab 	    idProduct);
205b19dcd93SRoman Kagan 
206b19dcd93SRoman Kagan 	strcat(alias, "d");
207b19dcd93SRoman Kagan 	if (bcdDevice_initial_digits)
208b19dcd93SRoman Kagan 		sprintf(alias + strlen(alias), "%0*X",
209b19dcd93SRoman Kagan 			bcdDevice_initial_digits, bcdDevice_initial);
210b19dcd93SRoman Kagan 	if (range_lo == range_hi)
211afe2dab4SNathaniel McCallum 		sprintf(alias + strlen(alias), "%X", range_lo);
212afe2dab4SNathaniel McCallum 	else if (range_lo > 0 || range_hi < max) {
213afe2dab4SNathaniel McCallum 		if (range_lo > 0x9 || range_hi < 0xA)
214afe2dab4SNathaniel McCallum 			sprintf(alias + strlen(alias),
215afe2dab4SNathaniel McCallum 				"[%X-%X]",
216afe2dab4SNathaniel McCallum 				range_lo,
217afe2dab4SNathaniel McCallum 				range_hi);
218afe2dab4SNathaniel McCallum 		else {
219afe2dab4SNathaniel McCallum 			sprintf(alias + strlen(alias),
220afe2dab4SNathaniel McCallum 				range_lo < 0x9 ? "[%X-9" : "[%X",
221afe2dab4SNathaniel McCallum 				range_lo);
222afe2dab4SNathaniel McCallum 			sprintf(alias + strlen(alias),
22303b56329SJan Moskyto Matejka 				range_hi > 0xA ? "A-%X]" : "%X]",
22403b56329SJan Moskyto Matejka 				range_hi);
225afe2dab4SNathaniel McCallum 		}
226afe2dab4SNathaniel McCallum 	}
2276543becfSAndreas Schwab 	if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
228b19dcd93SRoman Kagan 		strcat(alias, "*");
229b19dcd93SRoman Kagan 
2306543becfSAndreas Schwab 	ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
2316543becfSAndreas Schwab 	    bDeviceClass);
2326543becfSAndreas Schwab 	ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
2336543becfSAndreas Schwab 	    bDeviceSubClass);
2346543becfSAndreas Schwab 	ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
2356543becfSAndreas Schwab 	    bDeviceProtocol);
2366543becfSAndreas Schwab 	ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
2376543becfSAndreas Schwab 	    bInterfaceClass);
2386543becfSAndreas Schwab 	ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
2396543becfSAndreas Schwab 	    bInterfaceSubClass);
2406543becfSAndreas Schwab 	ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
2416543becfSAndreas Schwab 	    bInterfaceProtocol);
2426543becfSAndreas Schwab 	ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER,
2436543becfSAndreas Schwab 	    bInterfaceNumber);
244b19dcd93SRoman Kagan 
245f4fdb17cSMasahiro Yamada 	module_alias_printf(mod, true, "%s", alias);
246b19dcd93SRoman Kagan }
247b19dcd93SRoman Kagan 
24855f49f26SNathaniel McCallum /* Handles increment/decrement of BCD formatted integers */
24955f49f26SNathaniel McCallum /* Returns the previous value, so it works like i++ or i-- */
incbcd(unsigned int * bcd,int inc,unsigned char max,size_t chars)25055f49f26SNathaniel McCallum static unsigned int incbcd(unsigned int *bcd,
25155f49f26SNathaniel McCallum 			   int inc,
25255f49f26SNathaniel McCallum 			   unsigned char max,
25355f49f26SNathaniel McCallum 			   size_t chars)
25455f49f26SNathaniel McCallum {
25555f49f26SNathaniel McCallum 	unsigned int init = *bcd, i, j;
25655f49f26SNathaniel McCallum 	unsigned long long c, dec = 0;
25755f49f26SNathaniel McCallum 
25855f49f26SNathaniel McCallum 	/* If bcd is not in BCD format, just increment */
25955f49f26SNathaniel McCallum 	if (max > 0x9) {
26055f49f26SNathaniel McCallum 		*bcd += inc;
26155f49f26SNathaniel McCallum 		return init;
26255f49f26SNathaniel McCallum 	}
26355f49f26SNathaniel McCallum 
26455f49f26SNathaniel McCallum 	/* Convert BCD to Decimal */
26555f49f26SNathaniel McCallum 	for (i=0 ; i < chars ; i++) {
26655f49f26SNathaniel McCallum 		c = (*bcd >> (i << 2)) & 0xf;
26755f49f26SNathaniel McCallum 		c = c > 9 ? 9 : c; /* force to bcd just in case */
26855f49f26SNathaniel McCallum 		for (j=0 ; j < i ; j++)
26955f49f26SNathaniel McCallum 			c = c * 10;
27055f49f26SNathaniel McCallum 		dec += c;
27155f49f26SNathaniel McCallum 	}
27255f49f26SNathaniel McCallum 
27355f49f26SNathaniel McCallum 	/* Do our increment/decrement */
27455f49f26SNathaniel McCallum 	dec += inc;
27555f49f26SNathaniel McCallum 	*bcd  = 0;
27655f49f26SNathaniel McCallum 
27755f49f26SNathaniel McCallum 	/* Convert back to BCD */
27855f49f26SNathaniel McCallum 	for (i=0 ; i < chars ; i++) {
27955f49f26SNathaniel McCallum 		for (c=1,j=0 ; j < i ; j++)
28055f49f26SNathaniel McCallum 			c = c * 10;
28155f49f26SNathaniel McCallum 		c = (dec / c) % 10;
28255f49f26SNathaniel McCallum 		*bcd += c << (i << 2);
28355f49f26SNathaniel McCallum 	}
28455f49f26SNathaniel McCallum 	return init;
28555f49f26SNathaniel McCallum }
28655f49f26SNathaniel McCallum 
do_usb_entry_multi(struct module * mod,void * symval)287abd20428SMasahiro Yamada static void do_usb_entry_multi(struct module *mod, void *symval)
288b19dcd93SRoman Kagan {
289b19dcd93SRoman Kagan 	unsigned int devlo, devhi;
290afe2dab4SNathaniel McCallum 	unsigned char chi, clo, max;
291b19dcd93SRoman Kagan 	int ndigits;
292b19dcd93SRoman Kagan 
2936543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, match_flags);
2946543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, idVendor);
2956543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, idProduct);
2966543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
2976543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bcdDevice_hi);
2986543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bDeviceClass);
2996543becfSAndreas Schwab 	DEF_FIELD(symval, usb_device_id, bInterfaceClass);
300b19dcd93SRoman Kagan 
3016543becfSAndreas Schwab 	devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
3026543becfSAndreas Schwab 		bcdDevice_lo : 0x0U;
3036543becfSAndreas Schwab 	devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
3046543becfSAndreas Schwab 		bcdDevice_hi : ~0x0U;
305b19dcd93SRoman Kagan 
306afe2dab4SNathaniel McCallum 	/* Figure out if this entry is in bcd or hex format */
307afe2dab4SNathaniel McCallum 	max = 0x9; /* Default to decimal format */
3086543becfSAndreas Schwab 	for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) {
309afe2dab4SNathaniel McCallum 		clo = (devlo >> (ndigits << 2)) & 0xf;
310afe2dab4SNathaniel McCallum 		chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
311afe2dab4SNathaniel McCallum 		if (clo > max || chi > max) {
312afe2dab4SNathaniel McCallum 			max = 0xf;
313afe2dab4SNathaniel McCallum 			break;
314afe2dab4SNathaniel McCallum 		}
315afe2dab4SNathaniel McCallum 	}
316afe2dab4SNathaniel McCallum 
317b19dcd93SRoman Kagan 	/*
318b19dcd93SRoman Kagan 	 * Some modules (visor) have empty slots as placeholder for
319b19dcd93SRoman Kagan 	 * run-time specification that results in catch-all alias
320b19dcd93SRoman Kagan 	 */
3216543becfSAndreas Schwab 	if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass))
322b19dcd93SRoman Kagan 		return;
323b19dcd93SRoman Kagan 
324b19dcd93SRoman Kagan 	/* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
3256543becfSAndreas Schwab 	for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
326b19dcd93SRoman Kagan 		clo = devlo & 0xf;
327b19dcd93SRoman Kagan 		chi = devhi & 0xf;
328afe2dab4SNathaniel McCallum 		if (chi > max)	/* If we are in bcd mode, truncate if necessary */
329afe2dab4SNathaniel McCallum 			chi = max;
330b19dcd93SRoman Kagan 		devlo >>= 4;
331b19dcd93SRoman Kagan 		devhi >>= 4;
332b19dcd93SRoman Kagan 
333b19dcd93SRoman Kagan 		if (devlo == devhi || !ndigits) {
3346543becfSAndreas Schwab 			do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod);
335b19dcd93SRoman Kagan 			break;
336b19dcd93SRoman Kagan 		}
337b19dcd93SRoman Kagan 
338afe2dab4SNathaniel McCallum 		if (clo > 0x0)
3396543becfSAndreas Schwab 			do_usb_entry(symval,
34055f49f26SNathaniel McCallum 				     incbcd(&devlo, 1, max,
3416543becfSAndreas Schwab 					    sizeof(bcdDevice_lo) * 2),
34255f49f26SNathaniel McCallum 				     ndigits, clo, max, max, mod);
343b19dcd93SRoman Kagan 
344afe2dab4SNathaniel McCallum 		if (chi < max)
3456543becfSAndreas Schwab 			do_usb_entry(symval,
34655f49f26SNathaniel McCallum 				     incbcd(&devhi, -1, max,
3476543becfSAndreas Schwab 					    sizeof(bcdDevice_lo) * 2),
34855f49f26SNathaniel McCallum 				     ndigits, 0x0, chi, max, mod);
349b19dcd93SRoman Kagan 	}
350b19dcd93SRoman Kagan }
351b19dcd93SRoman Kagan 
do_of_entry(struct module * mod,void * symval)352c58854c8SMasahiro Yamada static void do_of_entry(struct module *mod, void *symval)
353acbef7b7SPhilipp Zabel {
354acbef7b7SPhilipp Zabel 	char alias[500];
355acbef7b7SPhilipp Zabel 	int len;
356acbef7b7SPhilipp Zabel 	char *tmp;
357acbef7b7SPhilipp Zabel 
358acbef7b7SPhilipp Zabel 	DEF_FIELD_ADDR(symval, of_device_id, name);
359acbef7b7SPhilipp Zabel 	DEF_FIELD_ADDR(symval, of_device_id, type);
360acbef7b7SPhilipp Zabel 	DEF_FIELD_ADDR(symval, of_device_id, compatible);
361acbef7b7SPhilipp Zabel 
362acbef7b7SPhilipp Zabel 	len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*",
363acbef7b7SPhilipp Zabel 		      (*type)[0] ? *type : "*");
364acbef7b7SPhilipp Zabel 
365b3c0a4daSWolfram Sang 	if ((*compatible)[0])
366acbef7b7SPhilipp Zabel 		sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
367acbef7b7SPhilipp Zabel 			*compatible);
368acbef7b7SPhilipp Zabel 
369acbef7b7SPhilipp Zabel 	/* Replace all whitespace with underscores */
370acbef7b7SPhilipp Zabel 	for (tmp = alias; tmp && *tmp; tmp++)
371acbef7b7SPhilipp Zabel 		if (isspace(*tmp))
372acbef7b7SPhilipp Zabel 			*tmp = '_';
373acbef7b7SPhilipp Zabel 
374f4fdb17cSMasahiro Yamada 	module_alias_printf(mod, false, "%s", alias);
375f4fdb17cSMasahiro Yamada 	module_alias_printf(mod, false, "%sC*", alias);
376acbef7b7SPhilipp Zabel }
377acbef7b7SPhilipp Zabel 
378e8c84f9aSJiri Slaby /* Looks like: hid:bNvNpN */
do_hid_entry(struct module * mod,void * symval)3796d3b3dd2SMasahiro Yamada static void do_hid_entry(struct module *mod, void *symval)
380e8c84f9aSJiri Slaby {
3816d3b3dd2SMasahiro Yamada 	char alias[256] = {};
3826d3b3dd2SMasahiro Yamada 
3836543becfSAndreas Schwab 	DEF_FIELD(symval, hid_device_id, bus);
3846543becfSAndreas Schwab 	DEF_FIELD(symval, hid_device_id, group);
3856543becfSAndreas Schwab 	DEF_FIELD(symval, hid_device_id, vendor);
3866543becfSAndreas Schwab 	DEF_FIELD(symval, hid_device_id, product);
387e8c84f9aSJiri Slaby 
3886543becfSAndreas Schwab 	ADD(alias, "b", bus != HID_BUS_ANY, bus);
3896543becfSAndreas Schwab 	ADD(alias, "g", group != HID_GROUP_ANY, group);
3906543becfSAndreas Schwab 	ADD(alias, "v", vendor != HID_ANY_ID, vendor);
3916543becfSAndreas Schwab 	ADD(alias, "p", product != HID_ANY_ID, product);
392e8c84f9aSJiri Slaby 
3936d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "hid:%s", alias);
394e8c84f9aSJiri Slaby }
395e8c84f9aSJiri Slaby 
3961da177e4SLinus Torvalds /* Looks like: ieee1394:venNmoNspNverN */
do_ieee1394_entry(struct module * mod,void * symval)3976d3b3dd2SMasahiro Yamada static void do_ieee1394_entry(struct module *mod, void *symval)
3981da177e4SLinus Torvalds {
3996d3b3dd2SMasahiro Yamada 	char alias[256] = {};
4006d3b3dd2SMasahiro Yamada 
4016543becfSAndreas Schwab 	DEF_FIELD(symval, ieee1394_device_id, match_flags);
4026543becfSAndreas Schwab 	DEF_FIELD(symval, ieee1394_device_id, vendor_id);
4036543becfSAndreas Schwab 	DEF_FIELD(symval, ieee1394_device_id, model_id);
4046543becfSAndreas Schwab 	DEF_FIELD(symval, ieee1394_device_id, specifier_id);
4056543becfSAndreas Schwab 	DEF_FIELD(symval, ieee1394_device_id, version);
4061da177e4SLinus Torvalds 
4076543becfSAndreas Schwab 	ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID,
4086543becfSAndreas Schwab 	    vendor_id);
4096543becfSAndreas Schwab 	ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID,
4106543becfSAndreas Schwab 	    model_id);
4116543becfSAndreas Schwab 	ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID,
4126543becfSAndreas Schwab 	    specifier_id);
4136543becfSAndreas Schwab 	ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION,
4146543becfSAndreas Schwab 	    version);
4151da177e4SLinus Torvalds 
4166d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "ieee1394:%s", alias);
4171da177e4SLinus Torvalds }
4181da177e4SLinus Torvalds 
419cc6711b0SMax Gurtovoy /* Looks like: pci:vNdNsvNsdNbcNscNiN or <prefix>_pci:vNdNsvNsdNbcNscNiN. */
do_pci_entry(struct module * mod,void * symval)4206d3b3dd2SMasahiro Yamada static void do_pci_entry(struct module *mod, void *symval)
4211da177e4SLinus Torvalds {
4226d3b3dd2SMasahiro Yamada 	char alias[256];
4231da177e4SLinus Torvalds 	/* Class field can be divided into these three. */
4241da177e4SLinus Torvalds 	unsigned char baseclass, subclass, interface,
4251da177e4SLinus Torvalds 		baseclass_mask, subclass_mask, interface_mask;
4261da177e4SLinus Torvalds 
4276543becfSAndreas Schwab 	DEF_FIELD(symval, pci_device_id, vendor);
4286543becfSAndreas Schwab 	DEF_FIELD(symval, pci_device_id, device);
4296543becfSAndreas Schwab 	DEF_FIELD(symval, pci_device_id, subvendor);
4306543becfSAndreas Schwab 	DEF_FIELD(symval, pci_device_id, subdevice);
4316543becfSAndreas Schwab 	DEF_FIELD(symval, pci_device_id, class);
4326543becfSAndreas Schwab 	DEF_FIELD(symval, pci_device_id, class_mask);
433cc6711b0SMax Gurtovoy 	DEF_FIELD(symval, pci_device_id, override_only);
4341da177e4SLinus Torvalds 
435cc6711b0SMax Gurtovoy 	switch (override_only) {
436cc6711b0SMax Gurtovoy 	case 0:
4371da177e4SLinus Torvalds 		strcpy(alias, "pci:");
438cc6711b0SMax Gurtovoy 		break;
439cc6711b0SMax Gurtovoy 	case PCI_ID_F_VFIO_DRIVER_OVERRIDE:
440cc6711b0SMax Gurtovoy 		strcpy(alias, "vfio_pci:");
441cc6711b0SMax Gurtovoy 		break;
442cc6711b0SMax Gurtovoy 	default:
443cc6711b0SMax Gurtovoy 		warn("Unknown PCI driver_override alias %08X\n",
444cc6711b0SMax Gurtovoy 		     override_only);
445cc6711b0SMax Gurtovoy 	}
446cc6711b0SMax Gurtovoy 
4476543becfSAndreas Schwab 	ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
4486543becfSAndreas Schwab 	ADD(alias, "d", device != PCI_ANY_ID, device);
4496543becfSAndreas Schwab 	ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);
4506543becfSAndreas Schwab 	ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice);
4511da177e4SLinus Torvalds 
4526543becfSAndreas Schwab 	baseclass = (class) >> 16;
4536543becfSAndreas Schwab 	baseclass_mask = (class_mask) >> 16;
4546543becfSAndreas Schwab 	subclass = (class) >> 8;
4556543becfSAndreas Schwab 	subclass_mask = (class_mask) >> 8;
4566543becfSAndreas Schwab 	interface = class;
4576543becfSAndreas Schwab 	interface_mask = class_mask;
4581da177e4SLinus Torvalds 
4591da177e4SLinus Torvalds 	if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
4601da177e4SLinus Torvalds 	    || (subclass_mask != 0 && subclass_mask != 0xFF)
4611da177e4SLinus Torvalds 	    || (interface_mask != 0 && interface_mask != 0xFF)) {
462cb80514dSSam Ravnborg 		warn("Can't handle masks in %s:%04X\n",
463c7c24d60SMasahiro Yamada 		     mod->name, class_mask);
4646d3b3dd2SMasahiro Yamada 		return;
4651da177e4SLinus Torvalds 	}
4661da177e4SLinus Torvalds 
4671da177e4SLinus Torvalds 	ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
4681da177e4SLinus Torvalds 	ADD(alias, "sc", subclass_mask == 0xFF, subclass);
4691da177e4SLinus Torvalds 	ADD(alias, "i", interface_mask == 0xFF, interface);
4706d3b3dd2SMasahiro Yamada 
4716d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "%s", alias);
4721da177e4SLinus Torvalds }
4731da177e4SLinus Torvalds 
4741da177e4SLinus Torvalds /* looks like: "ccw:tNmNdtNdmN" */
do_ccw_entry(struct module * mod,void * symval)4756d3b3dd2SMasahiro Yamada static void do_ccw_entry(struct module *mod, void *symval)
4761da177e4SLinus Torvalds {
4776d3b3dd2SMasahiro Yamada 	char alias[256] = {};
4786d3b3dd2SMasahiro Yamada 
4796543becfSAndreas Schwab 	DEF_FIELD(symval, ccw_device_id, match_flags);
4806543becfSAndreas Schwab 	DEF_FIELD(symval, ccw_device_id, cu_type);
4816543becfSAndreas Schwab 	DEF_FIELD(symval, ccw_device_id, cu_model);
4826543becfSAndreas Schwab 	DEF_FIELD(symval, ccw_device_id, dev_type);
4836543becfSAndreas Schwab 	DEF_FIELD(symval, ccw_device_id, dev_model);
4841da177e4SLinus Torvalds 
4856543becfSAndreas Schwab 	ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
4866543becfSAndreas Schwab 	    cu_type);
4876543becfSAndreas Schwab 	ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
4886543becfSAndreas Schwab 	    cu_model);
4896543becfSAndreas Schwab 	ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
4906543becfSAndreas Schwab 	    dev_type);
4916543becfSAndreas Schwab 	ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
4926543becfSAndreas Schwab 	    dev_model);
4936d3b3dd2SMasahiro Yamada 
4946d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "ccw:%s", alias);
4951da177e4SLinus Torvalds }
4961da177e4SLinus Torvalds 
4971534c382SMartin Schwidefsky /* looks like: "ap:tN" */
do_ap_entry(struct module * mod,void * symval)4986d3b3dd2SMasahiro Yamada static void do_ap_entry(struct module *mod, void *symval)
4991534c382SMartin Schwidefsky {
5006543becfSAndreas Schwab 	DEF_FIELD(symval, ap_device_id, dev_type);
5016543becfSAndreas Schwab 
5026d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "ap:t%02X*", dev_type);
5031534c382SMartin Schwidefsky }
5041534c382SMartin Schwidefsky 
5057e9db9eaSCornelia Huck /* looks like: "css:tN" */
do_css_entry(struct module * mod,void * symval)5066d3b3dd2SMasahiro Yamada static void do_css_entry(struct module *mod, void *symval)
5077e9db9eaSCornelia Huck {
5086543becfSAndreas Schwab 	DEF_FIELD(symval, css_device_id, type);
5096543becfSAndreas Schwab 
5106d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "css:t%01X", type);
5117e9db9eaSCornelia Huck }
5127e9db9eaSCornelia Huck 
5131da177e4SLinus Torvalds /* Looks like: "serio:tyNprNidNexN" */
do_serio_entry(struct module * mod,void * symval)5146d3b3dd2SMasahiro Yamada static void do_serio_entry(struct module *mod, void *symval)
5151da177e4SLinus Torvalds {
5166d3b3dd2SMasahiro Yamada 	char alias[256] = {};
5176d3b3dd2SMasahiro Yamada 
5186543becfSAndreas Schwab 	DEF_FIELD(symval, serio_device_id, type);
5196543becfSAndreas Schwab 	DEF_FIELD(symval, serio_device_id, proto);
5206543becfSAndreas Schwab 	DEF_FIELD(symval, serio_device_id, id);
5216543becfSAndreas Schwab 	DEF_FIELD(symval, serio_device_id, extra);
5221da177e4SLinus Torvalds 
5236543becfSAndreas Schwab 	ADD(alias, "ty", type != SERIO_ANY, type);
5246543becfSAndreas Schwab 	ADD(alias, "pr", proto != SERIO_ANY, proto);
5256543becfSAndreas Schwab 	ADD(alias, "id", id != SERIO_ANY, id);
5266543becfSAndreas Schwab 	ADD(alias, "ex", extra != SERIO_ANY, extra);
5271da177e4SLinus Torvalds 
5286d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "serio:%s", alias);
5291da177e4SLinus Torvalds }
5301da177e4SLinus Torvalds 
53126095a01SSuthikulpanit, Suravee /* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or
53226095a01SSuthikulpanit, Suravee  *             "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if)
53326095a01SSuthikulpanit, Suravee  *
53426095a01SSuthikulpanit, Suravee  * NOTE: Each driver should use one of the following : _HID, _CIDs
53526095a01SSuthikulpanit, Suravee  *       or _CLS. Also, bb, ss, and pp can be substituted with ??
53626095a01SSuthikulpanit, Suravee  *       as don't care byte.
53726095a01SSuthikulpanit, Suravee  */
do_acpi_entry(struct module * mod,void * symval)5386d3b3dd2SMasahiro Yamada static void do_acpi_entry(struct module *mod, void *symval)
53929b71a1cSThomas Renninger {
5406543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, acpi_device_id, id);
5412e766a1fSMasahiro Yamada 	DEF_FIELD(symval, acpi_device_id, cls);
5422e766a1fSMasahiro Yamada 	DEF_FIELD(symval, acpi_device_id, cls_msk);
54326095a01SSuthikulpanit, Suravee 
544b7bca42dSMasahiro Yamada 	if ((*id)[0])
5456d3b3dd2SMasahiro Yamada 		module_alias_printf(mod, false, "acpi*:%s:*", *id);
5462e766a1fSMasahiro Yamada 	else {
5476d3b3dd2SMasahiro Yamada 		char alias[256];
54826095a01SSuthikulpanit, Suravee 		int i, byte_shift, cnt = 0;
54926095a01SSuthikulpanit, Suravee 		unsigned int msk;
55026095a01SSuthikulpanit, Suravee 
55126095a01SSuthikulpanit, Suravee 		for (i = 1; i <= 3; i++) {
55226095a01SSuthikulpanit, Suravee 			byte_shift = 8 * (3-i);
5532e766a1fSMasahiro Yamada 			msk = (cls_msk >> byte_shift) & 0xFF;
55426095a01SSuthikulpanit, Suravee 			if (msk)
55526095a01SSuthikulpanit, Suravee 				sprintf(&alias[cnt], "%02x",
5562e766a1fSMasahiro Yamada 					(cls >> byte_shift) & 0xFF);
55726095a01SSuthikulpanit, Suravee 			else
55826095a01SSuthikulpanit, Suravee 				sprintf(&alias[cnt], "??");
55926095a01SSuthikulpanit, Suravee 			cnt += 2;
56026095a01SSuthikulpanit, Suravee 		}
5616d3b3dd2SMasahiro Yamada 		module_alias_printf(mod, false, "acpi*:%s:*", alias);
56226095a01SSuthikulpanit, Suravee 	}
56329b71a1cSThomas Renninger }
56429b71a1cSThomas Renninger 
5651da177e4SLinus Torvalds /* looks like: "pnp:dD" */
do_pnp_device_entry(struct module * mod,void * symval)566600dbaf1SMasahiro Yamada static void do_pnp_device_entry(struct module *mod, void *symval)
5671da177e4SLinus Torvalds {
568600dbaf1SMasahiro Yamada 	DEF_FIELD_ADDR(symval, pnp_device_id, id);
5696543becfSAndreas Schwab 	char acpi_id[sizeof(*id)];
57072638f59SKay Sievers 
57172638f59SKay Sievers 	/* fix broken pnp bus lowercasing */
572600dbaf1SMasahiro Yamada 	for (unsigned int i = 0; i < sizeof(acpi_id); i++)
573600dbaf1SMasahiro Yamada 		acpi_id[i] = toupper((*id)[i]);
574600dbaf1SMasahiro Yamada 	module_alias_printf(mod, false, "pnp:d%s*", *id);
575f4fdb17cSMasahiro Yamada 	module_alias_printf(mod, false, "acpi*:%s:*", acpi_id);
5765e4c6564SKay Sievers }
5771da177e4SLinus Torvalds 
5780c81eed4SKay Sievers /* looks like: "pnp:dD" for every device of the card */
do_pnp_card_entry(struct module * mod,void * symval)579a5d8d417SMasahiro Yamada static void do_pnp_card_entry(struct module *mod, void *symval)
5801da177e4SLinus Torvalds {
581a5d8d417SMasahiro Yamada 	DEF_FIELD_ADDR(symval, pnp_card_device_id, devs);
5821da177e4SLinus Torvalds 
583a5d8d417SMasahiro Yamada 	for (unsigned int i = 0; i < PNP_MAX_DEVICES; i++) {
584a5d8d417SMasahiro Yamada 		const char *id = (char *)(*devs)[i].id;
585d92b7a3bSMasahiro Yamada 		char acpi_id[PNP_ID_LEN];
5860c81eed4SKay Sievers 
5870c81eed4SKay Sievers 		if (!id[0])
5881da177e4SLinus Torvalds 			break;
5890c81eed4SKay Sievers 
590a5d8d417SMasahiro Yamada 		/* fix broken pnp bus lowercasing */
591a5d8d417SMasahiro Yamada 		for (unsigned int j = 0; j < sizeof(acpi_id); j++)
592a5d8d417SMasahiro Yamada 			acpi_id[j] = toupper(id[j]);
593a5d8d417SMasahiro Yamada 
5940c81eed4SKay Sievers 		/* add an individual alias for every device entry */
595f4fdb17cSMasahiro Yamada 		module_alias_printf(mod, false, "pnp:d%s*", id);
596f4fdb17cSMasahiro Yamada 		module_alias_printf(mod, false, "acpi*:%s:*", acpi_id);
59722454cb9SKay Sievers 	}
5980c81eed4SKay Sievers }
5991da177e4SLinus Torvalds 
60090829cfeSDominik Brodowski /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
do_pcmcia_entry(struct module * mod,void * symval)6016d3b3dd2SMasahiro Yamada static void do_pcmcia_entry(struct module *mod, void *symval)
60290829cfeSDominik Brodowski {
6036d3b3dd2SMasahiro Yamada 	char alias[256] = {};
604*8fe1a63dSMasahiro Yamada 
6056543becfSAndreas Schwab 	DEF_FIELD(symval, pcmcia_device_id, match_flags);
6066543becfSAndreas Schwab 	DEF_FIELD(symval, pcmcia_device_id, manf_id);
6076543becfSAndreas Schwab 	DEF_FIELD(symval, pcmcia_device_id, card_id);
6086543becfSAndreas Schwab 	DEF_FIELD(symval, pcmcia_device_id, func_id);
6096543becfSAndreas Schwab 	DEF_FIELD(symval, pcmcia_device_id, function);
6106543becfSAndreas Schwab 	DEF_FIELD(symval, pcmcia_device_id, device_no);
6116543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash);
6124fb7edceSKars de Jong 
6136543becfSAndreas Schwab 	ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
6146543becfSAndreas Schwab 	    manf_id);
6156543becfSAndreas Schwab 	ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
6166543becfSAndreas Schwab 	    card_id);
6176543becfSAndreas Schwab 	ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
6186543becfSAndreas Schwab 	    func_id);
6196543becfSAndreas Schwab 	ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
6206543becfSAndreas Schwab 	    function);
6216543becfSAndreas Schwab 	ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
6226543becfSAndreas Schwab 	    device_no);
623*8fe1a63dSMasahiro Yamada 	ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1,
624*8fe1a63dSMasahiro Yamada 	    get_unaligned_native(*prod_id_hash + 0));
625*8fe1a63dSMasahiro Yamada 	ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2,
626*8fe1a63dSMasahiro Yamada 	    get_unaligned_native(*prod_id_hash + 1));
627*8fe1a63dSMasahiro Yamada 	ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3,
628*8fe1a63dSMasahiro Yamada 	    get_unaligned_native(*prod_id_hash + 2));
629*8fe1a63dSMasahiro Yamada 	ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4,
630*8fe1a63dSMasahiro Yamada 	    get_unaligned_native(*prod_id_hash + 3));
63190829cfeSDominik Brodowski 
6326d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "pcmcia:%s", alias);
63390829cfeSDominik Brodowski }
63490829cfeSDominik Brodowski 
do_vio_entry(struct module * mod,void * symval)6356d3b3dd2SMasahiro Yamada static void do_vio_entry(struct module *mod, void *symval)
636fb120da6SStephen Rothwell {
6376d3b3dd2SMasahiro Yamada 	char alias[256];
638fb120da6SStephen Rothwell 	char *tmp;
6396543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, vio_device_id, type);
6406543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, vio_device_id, compat);
641fb120da6SStephen Rothwell 
6426543becfSAndreas Schwab 	sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*",
6436543becfSAndreas Schwab 			(*compat)[0] ? *compat : "*");
644fb120da6SStephen Rothwell 
645fb120da6SStephen Rothwell 	/* Replace all whitespace with underscores */
646fb120da6SStephen Rothwell 	for (tmp = alias; tmp && *tmp; tmp++)
647fb120da6SStephen Rothwell 		if (isspace (*tmp))
648fb120da6SStephen Rothwell 			*tmp = '_';
649fb120da6SStephen Rothwell 
6506d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "%s", alias);
651fb120da6SStephen Rothwell }
652fb120da6SStephen Rothwell 
do_input(char * alias,kernel_ulong_t * arr,unsigned int min,unsigned int max)6531d8f430cSRusty Russell static void do_input(char *alias,
6541d8f430cSRusty Russell 		     kernel_ulong_t *arr, unsigned int min, unsigned int max)
6551d8f430cSRusty Russell {
6561d8f430cSRusty Russell 	unsigned int i;
657ddc5d341SDmitry Torokhov 
658bf36b4bfSMasahiro Yamada 	for (i = min; i <= max; i++)
659*8fe1a63dSMasahiro Yamada 		if (get_unaligned_native(arr + i / BITS_PER_LONG) &
660*8fe1a63dSMasahiro Yamada 		    (1ULL << (i % BITS_PER_LONG)))
6611d8f430cSRusty Russell 			sprintf(alias + strlen(alias), "%X,*", i);
6621d8f430cSRusty Russell }
6631d8f430cSRusty Russell 
66409c3e01bSDmitry Torokhov /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
do_input_entry(struct module * mod,void * symval)6656d3b3dd2SMasahiro Yamada static void do_input_entry(struct module *mod, void *symval)
6661d8f430cSRusty Russell {
6676d3b3dd2SMasahiro Yamada 	char alias[256] = {};
6686d3b3dd2SMasahiro Yamada 
6696543becfSAndreas Schwab 	DEF_FIELD(symval, input_device_id, flags);
6706543becfSAndreas Schwab 	DEF_FIELD(symval, input_device_id, bustype);
6716543becfSAndreas Schwab 	DEF_FIELD(symval, input_device_id, vendor);
6726543becfSAndreas Schwab 	DEF_FIELD(symval, input_device_id, product);
6736543becfSAndreas Schwab 	DEF_FIELD(symval, input_device_id, version);
6746543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, evbit);
6756543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, keybit);
6766543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, relbit);
6776543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, absbit);
6786543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, mscbit);
6796543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, ledbit);
6806543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, sndbit);
6816543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, ffbit);
6826543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, input_device_id, swbit);
6836543becfSAndreas Schwab 
6846543becfSAndreas Schwab 	ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype);
6856543becfSAndreas Schwab 	ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor);
6866543becfSAndreas Schwab 	ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
6876543becfSAndreas Schwab 	ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version);
6881d8f430cSRusty Russell 
6891d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "-e*");
6906543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_EVBIT)
6916543becfSAndreas Schwab 		do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
6921d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "k*");
6936543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
6946543becfSAndreas Schwab 		do_input(alias, *keybit,
695dc24f0e7SSam Ravnborg 			 INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
696dc24f0e7SSam Ravnborg 			 INPUT_DEVICE_ID_KEY_MAX);
6971d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "r*");
6986543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_RELBIT)
6996543becfSAndreas Schwab 		do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
7001d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "a*");
7016543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
7026543becfSAndreas Schwab 		do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
7031d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "m*");
7046543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_MSCIT)
7056543becfSAndreas Schwab 		do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
7061d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "l*");
7076543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
7086543becfSAndreas Schwab 		do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
7091d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "s*");
7106543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
7116543becfSAndreas Schwab 		do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
7121d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "f*");
7136543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_FFBIT)
7146543becfSAndreas Schwab 		do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
7151d8f430cSRusty Russell 	sprintf(alias + strlen(alias), "w*");
7166543becfSAndreas Schwab 	if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
7176543becfSAndreas Schwab 		do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
7186d3b3dd2SMasahiro Yamada 
7196d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "input:%s", alias);
7201d8f430cSRusty Russell }
7211d8f430cSRusty Russell 
do_eisa_entry(struct module * mod,void * symval)7226d3b3dd2SMasahiro Yamada static void do_eisa_entry(struct module *mod, void *symval)
72307563c71SMichael Tokarev {
7246543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, eisa_device_id, sig);
7256d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, EISA_DEVICE_MODALIAS_FMT "*", *sig);
72607563c71SMichael Tokarev }
72707563c71SMichael Tokarev 
728f3cf2673SKyle McMartin /* Looks like: parisc:tNhvNrevNsvN */
do_parisc_entry(struct module * mod,void * symval)7296d3b3dd2SMasahiro Yamada static void do_parisc_entry(struct module *mod, void *symval)
730f3cf2673SKyle McMartin {
7316d3b3dd2SMasahiro Yamada 	char alias[256] = {};
7326d3b3dd2SMasahiro Yamada 
7336543becfSAndreas Schwab 	DEF_FIELD(symval, parisc_device_id, hw_type);
7346543becfSAndreas Schwab 	DEF_FIELD(symval, parisc_device_id, hversion);
7356543becfSAndreas Schwab 	DEF_FIELD(symval, parisc_device_id, hversion_rev);
7366543becfSAndreas Schwab 	DEF_FIELD(symval, parisc_device_id, sversion);
737f3cf2673SKyle McMartin 
7386543becfSAndreas Schwab 	ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
7396543becfSAndreas Schwab 	ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
7406543becfSAndreas Schwab 	ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
7416543becfSAndreas Schwab 	ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
742f3cf2673SKyle McMartin 
7436d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "parisc:%s", alias);
744f3cf2673SKyle McMartin }
745f3cf2673SKyle McMartin 
746d59b66c7SPierre Ossman /* Looks like: sdio:cNvNdN. */
do_sdio_entry(struct module * mod,void * symval)7476d3b3dd2SMasahiro Yamada static void do_sdio_entry(struct module *mod, void *symval)
748d59b66c7SPierre Ossman {
7496d3b3dd2SMasahiro Yamada 	char alias[256] = {};
7506d3b3dd2SMasahiro Yamada 
7516543becfSAndreas Schwab 	DEF_FIELD(symval, sdio_device_id, class);
7526543becfSAndreas Schwab 	DEF_FIELD(symval, sdio_device_id, vendor);
7536543becfSAndreas Schwab 	DEF_FIELD(symval, sdio_device_id, device);
754d59b66c7SPierre Ossman 
7556543becfSAndreas Schwab 	ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
7566543becfSAndreas Schwab 	ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
7576543becfSAndreas Schwab 	ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
7586d3b3dd2SMasahiro Yamada 
7596d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "sdio:%s", alias);
760038a5008SLinus Torvalds }
761d59b66c7SPierre Ossman 
76261e115a5SMichael Buesch /* Looks like: ssb:vNidNrevN. */
do_ssb_entry(struct module * mod,void * symval)7636d3b3dd2SMasahiro Yamada static void do_ssb_entry(struct module *mod, void *symval)
76461e115a5SMichael Buesch {
7656d3b3dd2SMasahiro Yamada 	char alias[256] = {};
7666d3b3dd2SMasahiro Yamada 
7676543becfSAndreas Schwab 	DEF_FIELD(symval, ssb_device_id, vendor);
7686543becfSAndreas Schwab 	DEF_FIELD(symval, ssb_device_id, coreid);
7696543becfSAndreas Schwab 	DEF_FIELD(symval, ssb_device_id, revision);
77061e115a5SMichael Buesch 
7716543becfSAndreas Schwab 	ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
7726543becfSAndreas Schwab 	ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
7736543becfSAndreas Schwab 	ADD(alias, "rev", revision != SSB_ANY_REV, revision);
7746d3b3dd2SMasahiro Yamada 
7756d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "ssb:%s", alias);
776d59b66c7SPierre Ossman }
777d59b66c7SPierre Ossman 
7788369ae33SRafał Miłecki /* Looks like: bcma:mNidNrevNclN. */
do_bcma_entry(struct module * mod,void * symval)7796d3b3dd2SMasahiro Yamada static void do_bcma_entry(struct module *mod, void *symval)
7808369ae33SRafał Miłecki {
7816d3b3dd2SMasahiro Yamada 	char alias[256] = {};
7826d3b3dd2SMasahiro Yamada 
7836543becfSAndreas Schwab 	DEF_FIELD(symval, bcma_device_id, manuf);
7846543becfSAndreas Schwab 	DEF_FIELD(symval, bcma_device_id, id);
7856543becfSAndreas Schwab 	DEF_FIELD(symval, bcma_device_id, rev);
7866543becfSAndreas Schwab 	DEF_FIELD(symval, bcma_device_id, class);
7878369ae33SRafał Miłecki 
7886543becfSAndreas Schwab 	ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
7896543becfSAndreas Schwab 	ADD(alias, "id", id != BCMA_ANY_ID, id);
7906543becfSAndreas Schwab 	ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
7916543becfSAndreas Schwab 	ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
7926d3b3dd2SMasahiro Yamada 
7936d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "bcma:%s", alias);
7948369ae33SRafał Miłecki }
7958369ae33SRafał Miłecki 
796b01d9f28SRusty Russell /* Looks like: virtio:dNvN */
do_virtio_entry(struct module * mod,void * symval)7976d3b3dd2SMasahiro Yamada static void do_virtio_entry(struct module *mod, void *symval)
798b01d9f28SRusty Russell {
7996d3b3dd2SMasahiro Yamada 	char alias[256] = {};
8006d3b3dd2SMasahiro Yamada 
8016543becfSAndreas Schwab 	DEF_FIELD(symval, virtio_device_id, device);
8026543becfSAndreas Schwab 	DEF_FIELD(symval, virtio_device_id, vendor);
803b01d9f28SRusty Russell 
8046543becfSAndreas Schwab 	ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
8056543becfSAndreas Schwab 	ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
806b01d9f28SRusty Russell 
8076d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "virtio:%s", alias);
808b01d9f28SRusty Russell }
809b01d9f28SRusty Russell 
810d2ee52aaSK. Y. Srinivasan /*
811d2ee52aaSK. Y. Srinivasan  * Looks like: vmbus:guid
812d2ee52aaSK. Y. Srinivasan  * Each byte of the guid will be represented by two hex characters
813d2ee52aaSK. Y. Srinivasan  * in the name.
814d2ee52aaSK. Y. Srinivasan  */
do_vmbus_entry(struct module * mod,void * symval)8156d3b3dd2SMasahiro Yamada static void do_vmbus_entry(struct module *mod, void *symval)
816d2ee52aaSK. Y. Srinivasan {
8176543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
818e1352d7eSMasahiro Yamada 	char guid_name[sizeof(*guid) * 2 + 1];
819d2ee52aaSK. Y. Srinivasan 
820e1352d7eSMasahiro Yamada 	for (int i = 0; i < sizeof(*guid); i++)
821e1352d7eSMasahiro Yamada 		sprintf(&guid_name[i * 2], "%02x", guid->b[i]);
822d2ee52aaSK. Y. Srinivasan 
8236d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "vmbus:%s", guid_name);
824d2ee52aaSK. Y. Srinivasan }
825d2ee52aaSK. Y. Srinivasan 
8265b7d1277SAndrew F. Davis /* Looks like: rpmsg:S */
do_rpmsg_entry(struct module * mod,void * symval)8276d3b3dd2SMasahiro Yamada static void do_rpmsg_entry(struct module *mod, void *symval)
8285b7d1277SAndrew F. Davis {
8295b7d1277SAndrew F. Davis 	DEF_FIELD_ADDR(symval, rpmsg_device_id, name);
8305b7d1277SAndrew F. Davis 
8316d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, RPMSG_DEVICE_MODALIAS_FMT, *name);
8325b7d1277SAndrew F. Davis }
8335b7d1277SAndrew F. Davis 
834d2653e92SJean Delvare /* Looks like: i2c:S */
do_i2c_entry(struct module * mod,void * symval)8356d3b3dd2SMasahiro Yamada static void do_i2c_entry(struct module *mod, void *symval)
836d2653e92SJean Delvare {
8376543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, i2c_device_id, name);
838d2653e92SJean Delvare 
8396d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, I2C_MODULE_PREFIX "%s", *name);
840d2653e92SJean Delvare }
841d2653e92SJean Delvare 
do_i3c_entry(struct module * mod,void * symval)8426d3b3dd2SMasahiro Yamada static void do_i3c_entry(struct module *mod, void *symval)
8431ce589adSBoris Brezillon {
8446d3b3dd2SMasahiro Yamada 	char alias[256] = {};
8456d3b3dd2SMasahiro Yamada 
8461ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, match_flags);
8471ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, dcr);
8481ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, manuf_id);
8491ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, part_id);
8501ce589adSBoris Brezillon 	DEF_FIELD(symval, i3c_device_id, extra_info);
8511ce589adSBoris Brezillon 
8521ce589adSBoris Brezillon 	ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr);
8531ce589adSBoris Brezillon 	ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id);
8541ce589adSBoris Brezillon 	ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id);
8551ce589adSBoris Brezillon 	ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info);
8561ce589adSBoris Brezillon 
8576d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "i3c:%s", alias);
8581ce589adSBoris Brezillon }
8591ce589adSBoris Brezillon 
do_slim_entry(struct module * mod,void * symval)8606d3b3dd2SMasahiro Yamada static void do_slim_entry(struct module *mod, void *symval)
861b4b81830SMasahiro Yamada {
862b4b81830SMasahiro Yamada 	DEF_FIELD(symval, slim_device_id, manf_id);
863b4b81830SMasahiro Yamada 	DEF_FIELD(symval, slim_device_id, prod_code);
864b4b81830SMasahiro Yamada 
8656d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "slim:%x:%x:*", manf_id, prod_code);
866b4b81830SMasahiro Yamada }
867b4b81830SMasahiro Yamada 
868e0626e38SAnton Vorontsov /* Looks like: spi:S */
do_spi_entry(struct module * mod,void * symval)8696d3b3dd2SMasahiro Yamada static void do_spi_entry(struct module *mod, void *symval)
87075368bf6SAnton Vorontsov {
8716543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, spi_device_id, name);
87275368bf6SAnton Vorontsov 
8736d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, SPI_MODULE_PREFIX "%s", *name);
87475368bf6SAnton Vorontsov }
87575368bf6SAnton Vorontsov 
876d945b697SDavid Woodhouse static const struct dmifield {
877d945b697SDavid Woodhouse 	const char *prefix;
878d945b697SDavid Woodhouse 	int field;
879d945b697SDavid Woodhouse } dmi_fields[] = {
880d945b697SDavid Woodhouse 	{ "bvn", DMI_BIOS_VENDOR },
881d945b697SDavid Woodhouse 	{ "bvr", DMI_BIOS_VERSION },
882d945b697SDavid Woodhouse 	{ "bd",  DMI_BIOS_DATE },
883f5152f4dSErwan Velu 	{ "br",  DMI_BIOS_RELEASE },
884f5152f4dSErwan Velu 	{ "efr", DMI_EC_FIRMWARE_RELEASE },
885d945b697SDavid Woodhouse 	{ "svn", DMI_SYS_VENDOR },
886d945b697SDavid Woodhouse 	{ "pn",  DMI_PRODUCT_NAME },
887d945b697SDavid Woodhouse 	{ "pvr", DMI_PRODUCT_VERSION },
888d945b697SDavid Woodhouse 	{ "rvn", DMI_BOARD_VENDOR },
889d945b697SDavid Woodhouse 	{ "rn",  DMI_BOARD_NAME },
890d945b697SDavid Woodhouse 	{ "rvr", DMI_BOARD_VERSION },
891d945b697SDavid Woodhouse 	{ "cvn", DMI_CHASSIS_VENDOR },
892d945b697SDavid Woodhouse 	{ "ct",  DMI_CHASSIS_TYPE },
893d945b697SDavid Woodhouse 	{ "cvr", DMI_CHASSIS_VERSION },
894d945b697SDavid Woodhouse 	{ NULL,  DMI_NONE }
895d945b697SDavid Woodhouse };
896d945b697SDavid Woodhouse 
dmi_ascii_filter(char * d,const char * s)897d945b697SDavid Woodhouse static void dmi_ascii_filter(char *d, const char *s)
898d945b697SDavid Woodhouse {
899d945b697SDavid Woodhouse 	/* Filter out characters we don't want to see in the modalias string */
900d945b697SDavid Woodhouse 	for (; *s; s++)
901d945b697SDavid Woodhouse 		if (*s > ' ' && *s < 127 && *s != ':')
902d945b697SDavid Woodhouse 			*(d++) = *s;
903d945b697SDavid Woodhouse 
904d945b697SDavid Woodhouse 	*d = 0;
905d945b697SDavid Woodhouse }
906d945b697SDavid Woodhouse 
907d945b697SDavid Woodhouse 
do_dmi_entry(struct module * mod,void * symval)9086d3b3dd2SMasahiro Yamada static void do_dmi_entry(struct module *mod, void *symval)
909d945b697SDavid Woodhouse {
9106d3b3dd2SMasahiro Yamada 	char alias[256] = {};
911d945b697SDavid Woodhouse 	int i, j;
9126543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, dmi_system_id, matches);
913d945b697SDavid Woodhouse 
914d945b697SDavid Woodhouse 	for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
915d945b697SDavid Woodhouse 		for (j = 0; j < 4; j++) {
9166543becfSAndreas Schwab 			if ((*matches)[j].slot &&
9176543becfSAndreas Schwab 			    (*matches)[j].slot == dmi_fields[i].field) {
918d945b697SDavid Woodhouse 				sprintf(alias + strlen(alias), ":%s*",
919d945b697SDavid Woodhouse 					dmi_fields[i].prefix);
920d945b697SDavid Woodhouse 				dmi_ascii_filter(alias + strlen(alias),
9216543becfSAndreas Schwab 						 (*matches)[j].substr);
922d945b697SDavid Woodhouse 				strcat(alias, "*");
923d945b697SDavid Woodhouse 			}
924d945b697SDavid Woodhouse 		}
925d945b697SDavid Woodhouse 	}
926d945b697SDavid Woodhouse 
9276d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "dmi*%s:", alias);
928d945b697SDavid Woodhouse }
92957fee4a5SEric Miao 
do_platform_entry(struct module * mod,void * symval)9306d3b3dd2SMasahiro Yamada static void do_platform_entry(struct module *mod, void *symval)
93157fee4a5SEric Miao {
9326543becfSAndreas Schwab 	DEF_FIELD_ADDR(symval, platform_device_id, name);
9336d3b3dd2SMasahiro Yamada 
9346d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, PLATFORM_MODULE_PREFIX "%s", *name);
93557fee4a5SEric Miao }
93657fee4a5SEric Miao 
do_mdio_entry(struct module * mod,void * symval)9376d3b3dd2SMasahiro Yamada static void do_mdio_entry(struct module *mod, void *symval)
9388626d3b4SDavid Woodhouse {
9396d3b3dd2SMasahiro Yamada 	char id[33];
9408626d3b4SDavid Woodhouse 	int i;
9416543becfSAndreas Schwab 	DEF_FIELD(symval, mdio_device_id, phy_id);
9426543becfSAndreas Schwab 	DEF_FIELD(symval, mdio_device_id, phy_id_mask);
9438626d3b4SDavid Woodhouse 
9448626d3b4SDavid Woodhouse 	for (i = 0; i < 32; i++) {
9456543becfSAndreas Schwab 		if (!((phy_id_mask >> (31-i)) & 1))
9466d3b3dd2SMasahiro Yamada 			id[i] = '?';
9476543becfSAndreas Schwab 		else if ((phy_id >> (31-i)) & 1)
9486d3b3dd2SMasahiro Yamada 			id[i] = '1';
9498626d3b4SDavid Woodhouse 		else
9506d3b3dd2SMasahiro Yamada 			id[i] = '0';
9518626d3b4SDavid Woodhouse 	}
9528626d3b4SDavid Woodhouse 
9538626d3b4SDavid Woodhouse 	/* Terminate the string */
9546d3b3dd2SMasahiro Yamada 	id[32] = '\0';
9558626d3b4SDavid Woodhouse 
9566d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, MDIO_MODULE_PREFIX "%s", id);
9578626d3b4SDavid Woodhouse }
9588626d3b4SDavid Woodhouse 
959bf54a2b3SGeert Uytterhoeven /* Looks like: zorro:iN. */
do_zorro_entry(struct module * mod,void * symval)9606d3b3dd2SMasahiro Yamada static void do_zorro_entry(struct module *mod, void *symval)
961bf54a2b3SGeert Uytterhoeven {
9626d3b3dd2SMasahiro Yamada 	char alias[256] = {};
9636543becfSAndreas Schwab 	DEF_FIELD(symval, zorro_device_id, id);
9646d3b3dd2SMasahiro Yamada 
9656543becfSAndreas Schwab 	ADD(alias, "i", id != ZORRO_WILDCARD, id);
9666d3b3dd2SMasahiro Yamada 
9676d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "zorro:%s", alias);
968bf54a2b3SGeert Uytterhoeven }
969bf54a2b3SGeert Uytterhoeven 
970fedb3d27SOndrej Zary /* looks like: "pnp:dD" */
do_isapnp_entry(struct module * mod,void * symval)9716d3b3dd2SMasahiro Yamada static void do_isapnp_entry(struct module *mod, void *symval)
972fedb3d27SOndrej Zary {
9736543becfSAndreas Schwab 	DEF_FIELD(symval, isapnp_device_id, vendor);
9746543becfSAndreas Schwab 	DEF_FIELD(symval, isapnp_device_id, function);
9756d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "pnp:d%c%c%c%x%x%x%x*",
9766543becfSAndreas Schwab 		'A' + ((vendor >> 2) & 0x3f) - 1,
9776543becfSAndreas Schwab 		'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
9786543becfSAndreas Schwab 		'A' + ((vendor >> 8) & 0x1f) - 1,
9796543becfSAndreas Schwab 		(function >> 4) & 0x0f, function & 0x0f,
9806543becfSAndreas Schwab 		(function >> 12) & 0x0f, (function >> 8) & 0x0f);
981fedb3d27SOndrej Zary }
982fedb3d27SOndrej Zary 
983849e0ad2SJens Taprogge /* Looks like: "ipack:fNvNdN". */
do_ipack_entry(struct module * mod,void * symval)9846d3b3dd2SMasahiro Yamada static void do_ipack_entry(struct module *mod, void *symval)
985849e0ad2SJens Taprogge {
9866d3b3dd2SMasahiro Yamada 	char alias[256] = {};
9876543becfSAndreas Schwab 	DEF_FIELD(symval, ipack_device_id, format);
9886543becfSAndreas Schwab 	DEF_FIELD(symval, ipack_device_id, vendor);
9896543becfSAndreas Schwab 	DEF_FIELD(symval, ipack_device_id, device);
9906d3b3dd2SMasahiro Yamada 
9916543becfSAndreas Schwab 	ADD(alias, "f", format != IPACK_ANY_FORMAT, format);
9926543becfSAndreas Schwab 	ADD(alias, "v", vendor != IPACK_ANY_ID, vendor);
9936543becfSAndreas Schwab 	ADD(alias, "d", device != IPACK_ANY_ID, device);
9946d3b3dd2SMasahiro Yamada 
9956d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "ipack:%s", alias);
996849e0ad2SJens Taprogge }
997849e0ad2SJens Taprogge 
998523817bdSDave Martin /*
999523817bdSDave Martin  * Append a match expression for a single masked hex digit.
1000523817bdSDave Martin  * outp points to a pointer to the character at which to append.
1001523817bdSDave Martin  *	*outp is updated on return to point just after the appended text,
1002523817bdSDave Martin  *	to facilitate further appending.
1003523817bdSDave Martin  */
append_nibble_mask(char ** outp,unsigned int nibble,unsigned int mask)1004523817bdSDave Martin static void append_nibble_mask(char **outp,
1005523817bdSDave Martin 			       unsigned int nibble, unsigned int mask)
1006523817bdSDave Martin {
1007523817bdSDave Martin 	char *p = *outp;
1008523817bdSDave Martin 	unsigned int i;
1009523817bdSDave Martin 
1010523817bdSDave Martin 	switch (mask) {
1011523817bdSDave Martin 	case 0:
1012523817bdSDave Martin 		*p++ = '?';
1013523817bdSDave Martin 		break;
1014523817bdSDave Martin 
1015523817bdSDave Martin 	case 0xf:
1016523817bdSDave Martin 		p += sprintf(p, "%X",  nibble);
1017523817bdSDave Martin 		break;
1018523817bdSDave Martin 
1019523817bdSDave Martin 	default:
1020523817bdSDave Martin 		/*
1021523817bdSDave Martin 		 * Dumbly emit a match pattern for all possible matching
1022523817bdSDave Martin 		 * digits.  This could be improved in some cases using ranges,
1023523817bdSDave Martin 		 * but it has the advantage of being trivially correct, and is
1024523817bdSDave Martin 		 * often optimal.
1025523817bdSDave Martin 		 */
1026523817bdSDave Martin 		*p++ = '[';
1027523817bdSDave Martin 		for (i = 0; i < 0x10; i++)
1028523817bdSDave Martin 			if ((i & mask) == nibble)
1029523817bdSDave Martin 				p += sprintf(p, "%X", i);
1030523817bdSDave Martin 		*p++ = ']';
1031523817bdSDave Martin 	}
1032523817bdSDave Martin 
1033523817bdSDave Martin 	/* Ensure that the string remains NUL-terminated: */
1034523817bdSDave Martin 	*p = '\0';
1035523817bdSDave Martin 
1036523817bdSDave Martin 	/* Advance the caller's end-of-string pointer: */
1037523817bdSDave Martin 	*outp = p;
1038523817bdSDave Martin }
1039523817bdSDave Martin 
1040523817bdSDave Martin /*
1041523817bdSDave Martin  * looks like: "amba:dN"
1042523817bdSDave Martin  *
1043523817bdSDave Martin  * N is exactly 8 digits, where each is an upper-case hex digit, or
1044523817bdSDave Martin  *	a ? or [] pattern matching exactly one digit.
1045523817bdSDave Martin  */
do_amba_entry(struct module * mod,void * symval)10466d3b3dd2SMasahiro Yamada static void do_amba_entry(struct module *mod, void *symval)
1047523817bdSDave Martin {
10486d3b3dd2SMasahiro Yamada 	char alias[256];
1049523817bdSDave Martin 	unsigned int digit;
1050523817bdSDave Martin 	char *p = alias;
10516543becfSAndreas Schwab 	DEF_FIELD(symval, amba_id, id);
10526543becfSAndreas Schwab 	DEF_FIELD(symval, amba_id, mask);
1053523817bdSDave Martin 
10546543becfSAndreas Schwab 	if ((id & mask) != id)
10550d2573a2SGeert 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",
1056c7c24d60SMasahiro Yamada 		      mod->name, id, mask);
1057523817bdSDave Martin 
1058523817bdSDave Martin 	for (digit = 0; digit < 8; digit++)
1059523817bdSDave Martin 		append_nibble_mask(&p,
10606543becfSAndreas Schwab 				   (id >> (4 * (7 - digit))) & 0xf,
10616543becfSAndreas Schwab 				   (mask >> (4 * (7 - digit))) & 0xf);
1062523817bdSDave Martin 
10636d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "amba:d%s", alias);
1064523817bdSDave Martin }
1065523817bdSDave Martin 
10668286ae03SJames Hogan /*
10678286ae03SJames Hogan  * looks like: "mipscdmm:tN"
10688286ae03SJames Hogan  *
10698286ae03SJames Hogan  * N is exactly 2 digits, where each is an upper-case hex digit, or
10708286ae03SJames Hogan  *	a ? or [] pattern matching exactly one digit.
10718286ae03SJames Hogan  */
do_mips_cdmm_entry(struct module * mod,void * symval)10726d3b3dd2SMasahiro Yamada static void do_mips_cdmm_entry(struct module *mod, void *symval)
10738286ae03SJames Hogan {
10748286ae03SJames Hogan 	DEF_FIELD(symval, mips_cdmm_device_id, type);
10758286ae03SJames Hogan 
10766d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "mipscdmm:t%02X*", type);
10778286ae03SJames Hogan }
10788286ae03SJames Hogan 
10792b9c1f03SArd Biesheuvel /* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
1080644e9cbbSAndi Kleen  * All fields are numbers. It would be nicer to use strings for vendor
1081644e9cbbSAndi Kleen  * and feature, but getting those out of the build system here is too
1082644e9cbbSAndi Kleen  * complicated.
1083644e9cbbSAndi Kleen  */
1084644e9cbbSAndi Kleen 
do_x86cpu_entry(struct module * mod,void * symval)10856d3b3dd2SMasahiro Yamada static void do_x86cpu_entry(struct module *mod, void *symval)
1086644e9cbbSAndi Kleen {
10876d3b3dd2SMasahiro Yamada 	char alias[256] = {};
10886d3b3dd2SMasahiro Yamada 
10896543becfSAndreas Schwab 	DEF_FIELD(symval, x86_cpu_id, feature);
10906543becfSAndreas Schwab 	DEF_FIELD(symval, x86_cpu_id, family);
10916543becfSAndreas Schwab 	DEF_FIELD(symval, x86_cpu_id, model);
10926543becfSAndreas Schwab 	DEF_FIELD(symval, x86_cpu_id, vendor);
1093644e9cbbSAndi Kleen 
10942b9c1f03SArd Biesheuvel 	ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
10952b9c1f03SArd Biesheuvel 	ADD(alias, "fam", family != X86_FAMILY_ANY, family);
10962b9c1f03SArd Biesheuvel 	ADD(alias, "mod", model  != X86_MODEL_ANY,  model);
10975467bddaSBen Hutchings 	strcat(alias, ":feature:*");
10986543becfSAndreas Schwab 	if (feature != X86_FEATURE_ANY)
10996543becfSAndreas Schwab 		sprintf(alias + strlen(alias), "%04X*", feature);
11006d3b3dd2SMasahiro Yamada 
11016d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "cpu:type:x86,%s", alias);
1102644e9cbbSAndi Kleen }
1103644e9cbbSAndi Kleen 
110467bad2fdSArd Biesheuvel /* LOOKS like cpu:type:*:feature:*FEAT* */
do_cpu_entry(struct module * mod,void * symval)11056d3b3dd2SMasahiro Yamada static void do_cpu_entry(struct module *mod, void *symval)
110667bad2fdSArd Biesheuvel {
110767bad2fdSArd Biesheuvel 	DEF_FIELD(symval, cpu_feature, feature);
110867bad2fdSArd Biesheuvel 
11096d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "cpu:type:*:feature:*%04X*", feature);
111067bad2fdSArd Biesheuvel }
111167bad2fdSArd Biesheuvel 
1112b26864caSTomas Winkler /* Looks like: mei:S:uuid:N:* */
do_mei_entry(struct module * mod,void * symval)11136d3b3dd2SMasahiro Yamada static void do_mei_entry(struct module *mod, void *symval)
1114e5354107SSamuel Ortiz {
11156d3b3dd2SMasahiro Yamada 	char alias[256] = {};
11166d3b3dd2SMasahiro Yamada 
1117e5354107SSamuel Ortiz 	DEF_FIELD_ADDR(symval, mei_cl_device_id, name);
1118c93b76b3STomas Winkler 	DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid);
1119b26864caSTomas Winkler 	DEF_FIELD(symval, mei_cl_device_id, version);
1120e5354107SSamuel Ortiz 
1121c93b76b3STomas Winkler 	add_uuid(alias, *uuid);
1122b26864caSTomas Winkler 	ADD(alias, ":", version != MEI_CL_VERSION_ANY, version);
1123c93b76b3STomas Winkler 
11246d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, MEI_CL_MODULE_PREFIX "%s:%s:*",
11256d3b3dd2SMasahiro Yamada 			    (*name)[0] ? *name : "*", alias);
1126e5354107SSamuel Ortiz }
1127e5354107SSamuel Ortiz 
11283bdbb62fSAlexandre Bounine /* Looks like: rapidio:vNdNavNadN */
do_rio_entry(struct module * mod,void * symval)11296d3b3dd2SMasahiro Yamada static void do_rio_entry(struct module *mod, void *symval)
11303bdbb62fSAlexandre Bounine {
11316d3b3dd2SMasahiro Yamada 	char alias[256] = {};
11326d3b3dd2SMasahiro Yamada 
11333bdbb62fSAlexandre Bounine 	DEF_FIELD(symval, rio_device_id, did);
11343bdbb62fSAlexandre Bounine 	DEF_FIELD(symval, rio_device_id, vid);
11353bdbb62fSAlexandre Bounine 	DEF_FIELD(symval, rio_device_id, asm_did);
11363bdbb62fSAlexandre Bounine 	DEF_FIELD(symval, rio_device_id, asm_vid);
11373bdbb62fSAlexandre Bounine 
11383bdbb62fSAlexandre Bounine 	ADD(alias, "v", vid != RIO_ANY_ID, vid);
11393bdbb62fSAlexandre Bounine 	ADD(alias, "d", did != RIO_ANY_ID, did);
11403bdbb62fSAlexandre Bounine 	ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid);
11413bdbb62fSAlexandre Bounine 	ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did);
11423bdbb62fSAlexandre Bounine 
11436d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "rapidio:%s", alias);
11443bdbb62fSAlexandre Bounine }
11453bdbb62fSAlexandre Bounine 
1146289fcff4SHeikki Krogerus /* Looks like: ulpi:vNpN */
do_ulpi_entry(struct module * mod,void * symval)11476d3b3dd2SMasahiro Yamada static void do_ulpi_entry(struct module *mod, void *symval)
1148289fcff4SHeikki Krogerus {
1149289fcff4SHeikki Krogerus 	DEF_FIELD(symval, ulpi_device_id, vendor);
1150289fcff4SHeikki Krogerus 	DEF_FIELD(symval, ulpi_device_id, product);
1151289fcff4SHeikki Krogerus 
11526d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "ulpi:v%04xp%04x", vendor, product);
1153289fcff4SHeikki Krogerus }
1154289fcff4SHeikki Krogerus 
1155da23ac1eSSubhransu S. Prusty /* Looks like: hdaudio:vNrNaN */
do_hda_entry(struct module * mod,void * symval)11566d3b3dd2SMasahiro Yamada static void do_hda_entry(struct module *mod, void *symval)
1157da23ac1eSSubhransu S. Prusty {
11586d3b3dd2SMasahiro Yamada 	char alias[256] = {};
11596d3b3dd2SMasahiro Yamada 
1160da23ac1eSSubhransu S. Prusty 	DEF_FIELD(symval, hda_device_id, vendor_id);
1161da23ac1eSSubhransu S. Prusty 	DEF_FIELD(symval, hda_device_id, rev_id);
1162da23ac1eSSubhransu S. Prusty 	DEF_FIELD(symval, hda_device_id, api_version);
1163da23ac1eSSubhransu S. Prusty 
1164da23ac1eSSubhransu S. Prusty 	ADD(alias, "v", vendor_id != 0, vendor_id);
1165da23ac1eSSubhransu S. Prusty 	ADD(alias, "r", rev_id != 0, rev_id);
1166da23ac1eSSubhransu S. Prusty 	ADD(alias, "a", api_version != 0, api_version);
1167da23ac1eSSubhransu S. Prusty 
11686d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "hdaudio:%s", alias);
1169da23ac1eSSubhransu S. Prusty }
1170da23ac1eSSubhransu S. Prusty 
1171b5924268SPierre-Louis Bossart /* Looks like: sdw:mNpNvNcN */
do_sdw_entry(struct module * mod,void * symval)11726d3b3dd2SMasahiro Yamada static void do_sdw_entry(struct module *mod, void *symval)
11739251345dSVinod Koul {
11746d3b3dd2SMasahiro Yamada 	char alias[256] = {};
11756d3b3dd2SMasahiro Yamada 
11769251345dSVinod Koul 	DEF_FIELD(symval, sdw_device_id, mfg_id);
11779251345dSVinod Koul 	DEF_FIELD(symval, sdw_device_id, part_id);
1178b5924268SPierre-Louis Bossart 	DEF_FIELD(symval, sdw_device_id, sdw_version);
1179b5924268SPierre-Louis Bossart 	DEF_FIELD(symval, sdw_device_id, class_id);
11809251345dSVinod Koul 
11819251345dSVinod Koul 	ADD(alias, "m", mfg_id != 0, mfg_id);
11829251345dSVinod Koul 	ADD(alias, "p", part_id != 0, part_id);
1183b5924268SPierre-Louis Bossart 	ADD(alias, "v", sdw_version != 0, sdw_version);
1184b5924268SPierre-Louis Bossart 	ADD(alias, "c", class_id != 0, class_id);
11859251345dSVinod Koul 
11866d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "sdw:%s", alias);
11879251345dSVinod Koul }
11889251345dSVinod Koul 
11890afef456SStuart Yoder /* Looks like: fsl-mc:vNdN */
do_fsl_mc_entry(struct module * mod,void * symval)11906d3b3dd2SMasahiro Yamada static void do_fsl_mc_entry(struct module *mod, void *symval)
11910afef456SStuart Yoder {
11920afef456SStuart Yoder 	DEF_FIELD(symval, fsl_mc_device_id, vendor);
11930afef456SStuart Yoder 	DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type);
11940afef456SStuart Yoder 
11956d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, "fsl-mc:v%08Xd%s", vendor, *obj_type);
11960afef456SStuart Yoder }
11970afef456SStuart Yoder 
1198d1ff7024SMika Westerberg /* Looks like: tbsvc:kSpNvNrN */
do_tbsvc_entry(struct module * mod,void * symval)11996d3b3dd2SMasahiro Yamada static void do_tbsvc_entry(struct module *mod, void *symval)
1200d1ff7024SMika Westerberg {
12016d3b3dd2SMasahiro Yamada 	char alias[256] = {};
12026d3b3dd2SMasahiro Yamada 
1203d1ff7024SMika Westerberg 	DEF_FIELD(symval, tb_service_id, match_flags);
1204d1ff7024SMika Westerberg 	DEF_FIELD_ADDR(symval, tb_service_id, protocol_key);
1205d1ff7024SMika Westerberg 	DEF_FIELD(symval, tb_service_id, protocol_id);
1206d1ff7024SMika Westerberg 	DEF_FIELD(symval, tb_service_id, protocol_version);
1207d1ff7024SMika Westerberg 	DEF_FIELD(symval, tb_service_id, protocol_revision);
1208d1ff7024SMika Westerberg 
1209d1ff7024SMika Westerberg 	if (match_flags & TBSVC_MATCH_PROTOCOL_KEY)
1210d1ff7024SMika Westerberg 		sprintf(alias + strlen(alias), "k%s", *protocol_key);
1211d1ff7024SMika Westerberg 	else
1212d1ff7024SMika Westerberg 		strcat(alias + strlen(alias), "k*");
1213d1ff7024SMika Westerberg 	ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id);
1214d1ff7024SMika Westerberg 	ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION,
1215d1ff7024SMika Westerberg 	    protocol_version);
1216d1ff7024SMika Westerberg 	ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION,
1217d1ff7024SMika Westerberg 	    protocol_revision);
1218d1ff7024SMika Westerberg 
12196d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "tbsvc:%s", alias);
1220d1ff7024SMika Westerberg }
1221d1ff7024SMika Westerberg 
12228a37d87dSHeikki Krogerus /* Looks like: typec:idN */
do_typec_entry(struct module * mod,void * symval)12236d3b3dd2SMasahiro Yamada static void do_typec_entry(struct module *mod, void *symval)
12248a37d87dSHeikki Krogerus {
12256d3b3dd2SMasahiro Yamada 	DEF_FIELD(symval, typec_device_id, svid);
12266d3b3dd2SMasahiro Yamada 
12278a37d87dSHeikki Krogerus 	module_alias_printf(mod, false, "typec:id%04X", svid);
12288a37d87dSHeikki Krogerus }
12298a37d87dSHeikki Krogerus 
12308a37d87dSHeikki Krogerus /* Looks like: tee:uuid */
do_tee_entry(struct module * mod,void * symval)12318a37d87dSHeikki Krogerus static void do_tee_entry(struct module *mod, void *symval)
12326d3b3dd2SMasahiro Yamada {
12338a37d87dSHeikki Krogerus 	DEF_FIELD_ADDR(symval, tee_client_device_id, uuid);
12348a37d87dSHeikki Krogerus 
12350fc1db9dSSumit Garg 	module_alias_printf(mod, true,
12366d3b3dd2SMasahiro Yamada 			    "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
12370fc1db9dSSumit Garg 		uuid->b[0], uuid->b[1], uuid->b[2], uuid->b[3], uuid->b[4],
12387f54e00eSMasahiro Yamada 		uuid->b[5], uuid->b[6], uuid->b[7], uuid->b[8], uuid->b[9],
12390fc1db9dSSumit Garg 		uuid->b[10], uuid->b[11], uuid->b[12], uuid->b[13], uuid->b[14],
12406d3b3dd2SMasahiro Yamada 		uuid->b[15]);
12416d3b3dd2SMasahiro Yamada }
12427f54e00eSMasahiro Yamada 
12437f54e00eSMasahiro Yamada /* Looks like: wmi:guid */
do_wmi_entry(struct module * mod,void * symval)12447f54e00eSMasahiro Yamada static void do_wmi_entry(struct module *mod, void *symval)
12457f54e00eSMasahiro Yamada {
12460fc1db9dSSumit Garg 	DEF_FIELD_ADDR(symval, wmi_device_id, guid_string);
12470fc1db9dSSumit Garg 
12480bc44b2bSMattias Jacobsson 	if (strlen(*guid_string) != UUID_STRING_LEN) {
12496d3b3dd2SMasahiro Yamada 		warn("Invalid WMI device id 'wmi:%s' in '%s'\n",
12500bc44b2bSMattias Jacobsson 				*guid_string, mod->name);
12510bc44b2bSMattias Jacobsson 		return;
12520bc44b2bSMattias Jacobsson 	}
12530bc44b2bSMattias Jacobsson 
12540bc44b2bSMattias Jacobsson 	module_alias_printf(mod, false, WMI_MODULE_PREFIX "%s", *guid_string);
1255c7c24d60SMasahiro Yamada }
12566d3b3dd2SMasahiro Yamada 
12570bc44b2bSMattias Jacobsson /* Looks like: mhi:S */
do_mhi_entry(struct module * mod,void * symval)12580bc44b2bSMattias Jacobsson static void do_mhi_entry(struct module *mod, void *symval)
12596d3b3dd2SMasahiro Yamada {
12600bc44b2bSMattias Jacobsson 	DEF_FIELD_ADDR(symval, mhi_device_id, chan);
12610bc44b2bSMattias Jacobsson 	module_alias_printf(mod, false, MHI_DEVICE_MODALIAS_FMT, *chan);
1262e6b0de46SManivannan Sadhasivam }
12636d3b3dd2SMasahiro Yamada 
1264e6b0de46SManivannan Sadhasivam /* Looks like: mhi_ep:S */
do_mhi_ep_entry(struct module * mod,void * symval)1265e6b0de46SManivannan Sadhasivam static void do_mhi_ep_entry(struct module *mod, void *symval)
12666d3b3dd2SMasahiro Yamada {
12677de3697eSDave Ertman 	DEF_FIELD_ADDR(symval, mhi_device_id, chan);
12687de3697eSDave Ertman 
1269c268c0a8SManivannan Sadhasivam 	module_alias_printf(mod, false, MHI_EP_DEVICE_MODALIAS_FMT, *chan);
12706d3b3dd2SMasahiro Yamada }
1271c268c0a8SManivannan Sadhasivam 
1272c268c0a8SManivannan Sadhasivam /* Looks like: ishtp:{guid} */
do_ishtp_entry(struct module * mod,void * symval)1273c268c0a8SManivannan Sadhasivam static void do_ishtp_entry(struct module *mod, void *symval)
12746d3b3dd2SMasahiro Yamada {
1275c268c0a8SManivannan Sadhasivam 	char alias[256] = {};
1276c268c0a8SManivannan Sadhasivam 	DEF_FIELD_ADDR(symval, ishtp_device_id, guid);
1277fa443bc3SThomas Weißschuh 
12786d3b3dd2SMasahiro Yamada 	add_guid(alias, *guid);
1279fa443bc3SThomas Weißschuh 
12806d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, false, ISHTP_MODULE_PREFIX "{%s}", alias);
1281ac96a15aSMasahiro Yamada }
1282fa443bc3SThomas Weißschuh 
do_auxiliary_entry(struct module * mod,void * symval)1283ac96a15aSMasahiro Yamada static void do_auxiliary_entry(struct module *mod, void *symval)
1284fa443bc3SThomas Weißschuh {
12856d3b3dd2SMasahiro Yamada 	DEF_FIELD_ADDR(symval, auxiliary_device_id, name);
1286fa443bc3SThomas Weißschuh 
1287fa443bc3SThomas Weißschuh 	module_alias_printf(mod, false, AUXILIARY_MODULE_PREFIX "%s", *name);
12886d3b3dd2SMasahiro Yamada }
12897de3697eSDave Ertman 
12907de3697eSDave Ertman /*
1291e6b0de46SManivannan Sadhasivam  * Looks like: ssam:dNcNtNiNfN
12926d3b3dd2SMasahiro Yamada  *
1293e6b0de46SManivannan Sadhasivam  * N is exactly 2 digits, where each is an upper-case hex digit.
1294e6b0de46SManivannan Sadhasivam  */
do_ssam_entry(struct module * mod,void * symval)1295eb0e90a8SMaximilian Luz static void do_ssam_entry(struct module *mod, void *symval)
1296eb0e90a8SMaximilian Luz {
1297eb0e90a8SMaximilian Luz 	char alias[256] = {};
1298eb0e90a8SMaximilian Luz 
1299eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, match_flags);
13006d3b3dd2SMasahiro Yamada 	DEF_FIELD(symval, ssam_device_id, domain);
1301eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, category);
13026d3b3dd2SMasahiro Yamada 	DEF_FIELD(symval, ssam_device_id, target);
13036d3b3dd2SMasahiro Yamada 	DEF_FIELD(symval, ssam_device_id, instance);
1304eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, ssam_device_id, function);
1305eb0e90a8SMaximilian Luz 
1306eb0e90a8SMaximilian Luz 	ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target);
1307eb0e90a8SMaximilian Luz 	ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance);
1308eb0e90a8SMaximilian Luz 	ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function);
1309eb0e90a8SMaximilian Luz 
1310eb0e90a8SMaximilian Luz 	module_alias_printf(mod, false, "ssam:d%02Xc%02X%s",
1311eb0e90a8SMaximilian Luz 			    domain, category, alias);
1312eb0e90a8SMaximilian Luz }
1313eb0e90a8SMaximilian Luz 
1314eb0e90a8SMaximilian Luz /* Looks like: dfl:tNfN */
do_dfl_entry(struct module * mod,void * symval)13156d3b3dd2SMasahiro Yamada static void do_dfl_entry(struct module *mod, void *symval)
13166d3b3dd2SMasahiro Yamada {
1317eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, dfl_device_id, type);
1318eb0e90a8SMaximilian Luz 	DEF_FIELD(symval, dfl_device_id, feature_id);
13194a224aceSXu Yilun 
13206d3b3dd2SMasahiro Yamada 	module_alias_printf(mod, true, "dfl:t%04Xf%04X", type, feature_id);
13214a224aceSXu Yilun }
13224a224aceSXu Yilun 
13234a224aceSXu Yilun /* Looks like: cdx:vNdN */
do_cdx_entry(struct module * mod,void * symval)13244a224aceSXu Yilun static void do_cdx_entry(struct module *mod, void *symval)
13256d3b3dd2SMasahiro Yamada {
13264a224aceSXu Yilun 	char alias[256];
13274a224aceSXu Yilun 
13282959ab24SNipun Gupta 	DEF_FIELD(symval, cdx_device_id, vendor);
13296d3b3dd2SMasahiro Yamada 	DEF_FIELD(symval, cdx_device_id, device);
13302959ab24SNipun Gupta 	DEF_FIELD(symval, cdx_device_id, subvendor);
13316d3b3dd2SMasahiro Yamada 	DEF_FIELD(symval, cdx_device_id, subdevice);
13326d3b3dd2SMasahiro Yamada 	DEF_FIELD(symval, cdx_device_id, class);
13332959ab24SNipun Gupta 	DEF_FIELD(symval, cdx_device_id, class_mask);
13342959ab24SNipun Gupta 	DEF_FIELD(symval, cdx_device_id, override_only);
1335fa10f413SAbhijit Gangurde 
1336fa10f413SAbhijit Gangurde 	switch (override_only) {
1337fa10f413SAbhijit Gangurde 	case 0:
1338fa10f413SAbhijit Gangurde 		strcpy(alias, "cdx:");
1339234489acSNipun Gupta 		break;
13402959ab24SNipun Gupta 	case CDX_ID_F_VFIO_DRIVER_OVERRIDE:
1341234489acSNipun Gupta 		strcpy(alias, "vfio_cdx:");
1342234489acSNipun Gupta 		break;
1343234489acSNipun Gupta 	default:
1344234489acSNipun Gupta 		warn("Unknown CDX driver_override alias %08X\n",
1345234489acSNipun Gupta 		     override_only);
1346234489acSNipun Gupta 		return;
1347234489acSNipun Gupta 	}
1348234489acSNipun Gupta 
1349234489acSNipun Gupta 	ADD(alias, "v", vendor != CDX_ANY_ID, vendor);
1350234489acSNipun Gupta 	ADD(alias, "d", device != CDX_ANY_ID, device);
13516d3b3dd2SMasahiro Yamada 	ADD(alias, "sv", subvendor != CDX_ANY_ID, subvendor);
1352234489acSNipun Gupta 	ADD(alias, "sd", subdevice != CDX_ANY_ID, subdevice);
1353234489acSNipun Gupta 	ADD(alias, "c", class_mask == 0xFFFFFF, class);
1354234489acSNipun Gupta 
1355234489acSNipun Gupta 	module_alias_printf(mod, false, "%s", alias);
1356fa10f413SAbhijit Gangurde }
1357fa10f413SAbhijit Gangurde 
do_vchiq_entry(struct module * mod,void * symval)1358fa10f413SAbhijit Gangurde static void do_vchiq_entry(struct module *mod, void *symval)
1359fa10f413SAbhijit Gangurde {
13606d3b3dd2SMasahiro Yamada 	DEF_FIELD_ADDR(symval, vchiq_device_id, name);
13612959ab24SNipun Gupta 
13622959ab24SNipun Gupta 	module_alias_printf(mod, false, "vchiq:%s", *name);
13636d3b3dd2SMasahiro Yamada }
13641fa05877SUmang Jain 
13651fa05877SUmang Jain /* Looks like: coreboot:tN */
do_coreboot_entry(struct module * mod,void * symval)13661fa05877SUmang Jain static void do_coreboot_entry(struct module *mod, void *symval)
13676d3b3dd2SMasahiro Yamada {
13681fa05877SUmang Jain 	DEF_FIELD(symval, coreboot_device_id, tag);
13691fa05877SUmang Jain 
1370f1cebae1SNícolas F. R. A. Prado 	module_alias_printf(mod, false, "coreboot:t%08X", tag);
13716d3b3dd2SMasahiro Yamada }
1372f1cebae1SNícolas F. R. A. Prado 
1373f1cebae1SNícolas F. R. A. Prado /* Does namelen bytes of name exactly match the symbol? */
sym_is(const char * name,unsigned namelen,const char * symbol)1374f1cebae1SNícolas F. R. A. Prado static bool sym_is(const char *name, unsigned namelen, const char *symbol)
13756d3b3dd2SMasahiro Yamada {
1376f1cebae1SNícolas F. R. A. Prado 	if (namelen != strlen(symbol))
1377f1cebae1SNícolas F. R. A. Prado 		return false;
1378626596e2SRusty Russell 
1379626596e2SRusty Russell 	return memcmp(name, symbol, namelen) == 0;
13801da177e4SLinus Torvalds }
1381626596e2SRusty Russell 
do_table(const char * name,void * symval,unsigned long size,unsigned long id_size,const char * device_id,void (* do_entry)(struct module * mod,void * symval),struct module * mod)1382626596e2SRusty Russell static void do_table(const char *name, void *symval, unsigned long size,
13831da177e4SLinus Torvalds 		     unsigned long id_size,
1384626596e2SRusty Russell 		     const char *device_id,
13851da177e4SLinus Torvalds 		     void (*do_entry)(struct module *mod, void *symval),
13861da177e4SLinus Torvalds 		     struct module *mod)
13872b1bd507SMasahiro Yamada {
13881da177e4SLinus Torvalds 	unsigned int i;
1389fb33d816SSam Ravnborg 
13906d3b3dd2SMasahiro Yamada 	if (size % id_size || size < id_size) {
13911da177e4SLinus Torvalds 		error("%s: type mismatch between %s[] and MODULE_DEVICE_TABLE(%s, ...)\n",
13921da177e4SLinus Torvalds 		      mod->name, name, device_id);
13931da177e4SLinus Torvalds 		return;
13941da177e4SLinus Torvalds 	}
13952b1bd507SMasahiro Yamada 
13962b1bd507SMasahiro Yamada 	/* Verify the last entry is a terminator */
13972b1bd507SMasahiro Yamada 	for (i = size - id_size; i < size; i++) {
13982b1bd507SMasahiro Yamada 		if (*(uint8_t *)(symval + i)) {
13992b1bd507SMasahiro Yamada 			error("%s: %s[] is not terminated with a NULL entry\n",
14002b1bd507SMasahiro Yamada 			      mod->name, name);
14012b1bd507SMasahiro Yamada 			return;
14022b1bd507SMasahiro Yamada 		}
14032b1bd507SMasahiro Yamada 	}
14042b1bd507SMasahiro Yamada 
14052b1bd507SMasahiro Yamada 	/* Leave last one: it's the terminator. */
14062b1bd507SMasahiro Yamada 	size -= id_size;
14072b1bd507SMasahiro Yamada 
14082b1bd507SMasahiro Yamada 	for (i = 0; i < size; i += id_size)
14092b1bd507SMasahiro Yamada 		do_entry(mod, symval + i);
14101da177e4SLinus Torvalds }
14111da177e4SLinus Torvalds 
14121da177e4SLinus Torvalds static const struct devtable devtable[] = {
14136d3b3dd2SMasahiro Yamada 	{"hid", SIZE_hid_device_id, do_hid_entry},
14146d3b3dd2SMasahiro Yamada 	{"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry},
14151da177e4SLinus Torvalds 	{"pci", SIZE_pci_device_id, do_pci_entry},
14161da177e4SLinus Torvalds 	{"ccw", SIZE_ccw_device_id, do_ccw_entry},
1417ec91e78dSMasahiro Yamada 	{"ap", SIZE_ap_device_id, do_ap_entry},
1418ec91e78dSMasahiro Yamada 	{"css", SIZE_css_device_id, do_css_entry},
1419ec91e78dSMasahiro Yamada 	{"serio", SIZE_serio_device_id, do_serio_entry},
1420ec91e78dSMasahiro Yamada 	{"acpi", SIZE_acpi_device_id, do_acpi_entry},
1421ec91e78dSMasahiro Yamada 	{"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry},
1422ec91e78dSMasahiro Yamada 	{"vio", SIZE_vio_device_id, do_vio_entry},
1423ec91e78dSMasahiro Yamada 	{"input", SIZE_input_device_id, do_input_entry},
1424ec91e78dSMasahiro Yamada 	{"eisa", SIZE_eisa_device_id, do_eisa_entry},
1425ec91e78dSMasahiro Yamada 	{"parisc", SIZE_parisc_device_id, do_parisc_entry},
1426ec91e78dSMasahiro Yamada 	{"sdio", SIZE_sdio_device_id, do_sdio_entry},
1427ec91e78dSMasahiro Yamada 	{"ssb", SIZE_ssb_device_id, do_ssb_entry},
1428ec91e78dSMasahiro Yamada 	{"bcma", SIZE_bcma_device_id, do_bcma_entry},
1429ec91e78dSMasahiro Yamada 	{"virtio", SIZE_virtio_device_id, do_virtio_entry},
1430ec91e78dSMasahiro Yamada 	{"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry},
1431ec91e78dSMasahiro Yamada 	{"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry},
1432ec91e78dSMasahiro Yamada 	{"i2c", SIZE_i2c_device_id, do_i2c_entry},
1433ec91e78dSMasahiro Yamada 	{"i3c", SIZE_i3c_device_id, do_i3c_entry},
1434ec91e78dSMasahiro Yamada 	{"slim", SIZE_slim_device_id, do_slim_entry},
1435ec91e78dSMasahiro Yamada 	{"spi", SIZE_spi_device_id, do_spi_entry},
1436ec91e78dSMasahiro Yamada 	{"dmi", SIZE_dmi_system_id, do_dmi_entry},
1437ec91e78dSMasahiro Yamada 	{"platform", SIZE_platform_device_id, do_platform_entry},
14381ce589adSBoris Brezillon 	{"mdio", SIZE_mdio_device_id, do_mdio_entry},
1439b4b81830SMasahiro Yamada 	{"zorro", SIZE_zorro_device_id, do_zorro_entry},
1440ec91e78dSMasahiro Yamada 	{"isapnp", SIZE_isapnp_device_id, do_isapnp_entry},
1441ec91e78dSMasahiro Yamada 	{"ipack", SIZE_ipack_device_id, do_ipack_entry},
1442ec91e78dSMasahiro Yamada 	{"amba", SIZE_amba_id, do_amba_entry},
1443ec91e78dSMasahiro Yamada 	{"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry},
1444ec91e78dSMasahiro Yamada 	{"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry},
1445ec91e78dSMasahiro Yamada 	{"cpu", SIZE_cpu_feature, do_cpu_entry},
1446ec91e78dSMasahiro Yamada 	{"mei", SIZE_mei_cl_device_id, do_mei_entry},
1447ec91e78dSMasahiro Yamada 	{"rapidio", SIZE_rio_device_id, do_rio_entry},
1448ec91e78dSMasahiro Yamada 	{"ulpi", SIZE_ulpi_device_id, do_ulpi_entry},
1449ec91e78dSMasahiro Yamada 	{"hdaudio", SIZE_hda_device_id, do_hda_entry},
1450ec91e78dSMasahiro Yamada 	{"sdw", SIZE_sdw_device_id, do_sdw_entry},
1451ec91e78dSMasahiro Yamada 	{"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry},
1452ec91e78dSMasahiro Yamada 	{"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
1453ec91e78dSMasahiro Yamada 	{"typec", SIZE_typec_device_id, do_typec_entry},
1454ec91e78dSMasahiro Yamada 	{"tee", SIZE_tee_client_device_id, do_tee_entry},
1455ec91e78dSMasahiro Yamada 	{"wmi", SIZE_wmi_device_id, do_wmi_entry},
1456ec91e78dSMasahiro Yamada 	{"mhi", SIZE_mhi_device_id, do_mhi_entry},
1457ec91e78dSMasahiro Yamada 	{"mhi_ep", SIZE_mhi_device_id, do_mhi_ep_entry},
1458ec91e78dSMasahiro Yamada 	{"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry},
14590fc1db9dSSumit Garg 	{"ssam", SIZE_ssam_device_id, do_ssam_entry},
14600bc44b2bSMattias Jacobsson 	{"dfl", SIZE_dfl_device_id, do_dfl_entry},
1461e6b0de46SManivannan Sadhasivam 	{"ishtp", SIZE_ishtp_device_id, do_ishtp_entry},
1462c268c0a8SManivannan Sadhasivam 	{"cdx", SIZE_cdx_device_id, do_cdx_entry},
14637de3697eSDave Ertman 	{"vchiq", SIZE_vchiq_device_id, do_vchiq_entry},
1464eb0e90a8SMaximilian Luz 	{"coreboot", SIZE_coreboot_device_id, do_coreboot_entry},
14654a224aceSXu Yilun 	{"of", SIZE_of_device_id, do_of_entry},
1466fa443bc3SThomas Weißschuh 	{"usb", SIZE_usb_device_id, do_usb_entry_multi},
14672959ab24SNipun Gupta 	{"pnp", SIZE_pnp_device_id, do_pnp_device_entry},
14681fa05877SUmang Jain 	{"pnp_card", SIZE_pnp_card_device_id, do_pnp_card_entry},
1469f1cebae1SNícolas F. R. A. Prado };
1470c58854c8SMasahiro Yamada 
1471abd20428SMasahiro Yamada /* Create MODULE_ALIAS() statements.
1472600dbaf1SMasahiro Yamada  * At this time, we cannot write the actual output C source yet,
1473a5d8d417SMasahiro Yamada  * so we write into the mod->dev_table_buf buffer. */
handle_moddevtable(struct module * mod,struct elf_info * info,Elf_Sym * sym,const char * symname)1474ec91e78dSMasahiro Yamada void handle_moddevtable(struct module *mod, struct elf_info *info,
1475ec91e78dSMasahiro Yamada 			Elf_Sym *sym, const char *symname)
14761da177e4SLinus Torvalds {
14771da177e4SLinus Torvalds 	void *symval;
14781da177e4SLinus Torvalds 	char *zeros = NULL;
14791da177e4SLinus Torvalds 	const char *type, *name;
14801da177e4SLinus Torvalds 	size_t typelen;
14811da177e4SLinus Torvalds 	static const char *prefix = "__mod_device_table__";
14821da177e4SLinus Torvalds 
1483e0049825SKees Cook 	/* We're looking for a section relative symbol */
14849a8ace8bSMasahiro Yamada 	if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
14859a8ace8bSMasahiro Yamada 		return;
1486054a9cd3SMasahiro Yamada 
14871da177e4SLinus Torvalds 	/* We're looking for an object */
14881da177e4SLinus Torvalds 	if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
14891ce53adfSDenys Vlasenko 		return;
14901da177e4SLinus Torvalds 
14911da177e4SLinus Torvalds 	/* All our symbols are of form __mod_device_table__<type>__<name>. */
1492e88aa7bbSDavid Miller 	if (!strstarts(symname, prefix))
1493e88aa7bbSDavid Miller 		return;
1494e88aa7bbSDavid Miller 	type = symname + strlen(prefix);
1495e88aa7bbSDavid Miller 
1496054a9cd3SMasahiro Yamada 	name = strstr(type, "__");
1497054a9cd3SMasahiro Yamada 	if (!name)
1498626596e2SRusty Russell 		return;
1499054a9cd3SMasahiro Yamada 	typelen = name - type;
1500054a9cd3SMasahiro Yamada 	name += strlen("__");
15019a8ace8bSMasahiro Yamada 
15029a8ace8bSMasahiro Yamada 	/* Handle all-NULL symbols allocated into .bss */
150321bdd17bSTom Gundersen 	if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
15049a8ace8bSMasahiro Yamada 		zeros = calloc(1, sym->st_size);
15052b1bd507SMasahiro Yamada 		symval = zeros;
1506626596e2SRusty Russell 	} else {
1507e0049825SKees Cook 		symval = sym_get_data(info, sym);
15081ce53adfSDenys Vlasenko 	}
1509e0049825SKees Cook 
1510e0049825SKees Cook 	for (int i = 0; i < ARRAY_SIZE(devtable); i++) {
1511e0049825SKees Cook 		const struct devtable *p = &devtable[i];
1512abe864b8SMasahiro Yamada 
1513e0049825SKees Cook 		if (sym_is(type, typelen, p->device_id)) {
15141da177e4SLinus Torvalds 			do_table(name, symval, sym->st_size, p->id_size,
1515abd20428SMasahiro Yamada 				 p->device_id, p->do_entry, mod);
1516ec91e78dSMasahiro Yamada 			break;
1517ec91e78dSMasahiro Yamada 		}
15189a8ace8bSMasahiro Yamada 	}
15192b1bd507SMasahiro Yamada 
1520f880eea6SMasahiro Yamada 	free(zeros);
1521626596e2SRusty Russell }
1522626596e2SRusty Russell