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