11da177e4SLinus Torvalds /* Simple code to turn various tables in an ELF file into alias definitions. 21da177e4SLinus Torvalds * This deals with kernel datastructures where they should be 31da177e4SLinus Torvalds * dealt with: in the kernel source. 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * Copyright 2002-2003 Rusty Russell, IBM Corporation 61da177e4SLinus Torvalds * 2003 Kai Germaschewski 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * This software may be used and distributed according to the terms 101da177e4SLinus Torvalds * of the GNU General Public License, incorporated herein by reference. 111da177e4SLinus Torvalds */ 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds #include "modpost.h" 146543becfSAndreas Schwab #include "devicetable-offsets.h" 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and 171da177e4SLinus Torvalds * use either stdint.h or inttypes.h for the rest. */ 181da177e4SLinus Torvalds #if KERNEL_ELFCLASS == ELFCLASS32 191da177e4SLinus Torvalds typedef Elf32_Addr kernel_ulong_t; 201d8f430cSRusty Russell #define BITS_PER_LONG 32 211da177e4SLinus Torvalds #else 221da177e4SLinus Torvalds typedef Elf64_Addr kernel_ulong_t; 231d8f430cSRusty Russell #define BITS_PER_LONG 64 241da177e4SLinus Torvalds #endif 251da177e4SLinus Torvalds #ifdef __sun__ 261da177e4SLinus Torvalds #include <inttypes.h> 271da177e4SLinus Torvalds #else 281da177e4SLinus Torvalds #include <stdint.h> 291da177e4SLinus Torvalds #endif 301da177e4SLinus Torvalds 315e655772SJeff Mahoney #include <ctype.h> 32626596e2SRusty Russell #include <stdbool.h> 335e655772SJeff Mahoney 341da177e4SLinus Torvalds typedef uint32_t __u32; 351da177e4SLinus Torvalds typedef uint16_t __u16; 361da177e4SLinus Torvalds typedef unsigned char __u8; 3724804329SAndy Shevchenko 3824804329SAndy Shevchenko /* UUID types for backward compatibility, don't use in new code */ 39b144ce2dSGreg Kroah-Hartman typedef struct { 40b144ce2dSGreg Kroah-Hartman __u8 b[16]; 41389c9af7SHeikki Krogerus } guid_t; 42389c9af7SHeikki Krogerus 430fc1db9dSSumit Garg typedef struct { 440fc1db9dSSumit Garg __u8 b[16]; 450fc1db9dSSumit Garg } uuid_t; 4624804329SAndy Shevchenko 47eacc95eaSMattias Jacobsson #define UUID_STRING_LEN 36 481da177e4SLinus Torvalds 4924804329SAndy Shevchenko /* MEI UUID type, don't use anywhere else */ 5024804329SAndy Shevchenko typedef struct { 5124804329SAndy Shevchenko __u8 b[16]; 5224804329SAndy Shevchenko } uuid_le; 5324804329SAndy Shevchenko 541da177e4SLinus Torvalds /* Big exception to the "don't include kernel headers into userspace, which 551da177e4SLinus Torvalds * even potentially has different endianness and word sizes, since 561da177e4SLinus Torvalds * we handle those differences explicitly below */ 571da177e4SLinus Torvalds #include "../../include/linux/mod_devicetable.h" 581da177e4SLinus Torvalds 59e49ce141SRusty Russell /* This array collects all instances that use the generic do_table */ 60e49ce141SRusty Russell struct devtable { 6121bdd17bSTom Gundersen const char *device_id; /* name of table, __mod_<name>__*_device_table. */ 62e49ce141SRusty Russell unsigned long id_size; 63f880eea6SMasahiro Yamada int (*do_entry)(const char *filename, void *symval, char *alias); 64e49ce141SRusty Russell }; 65e49ce141SRusty Russell 66841f1b8fSMattias Jacobsson /* Size of alias provided to do_entry functions */ 67841f1b8fSMattias Jacobsson #define ALIAS_SIZE 500 68841f1b8fSMattias Jacobsson 696543becfSAndreas Schwab /* Define a variable f that holds the value of field f of struct devid 706543becfSAndreas Schwab * based at address m. 716543becfSAndreas Schwab */ 726543becfSAndreas Schwab #define DEF_FIELD(m, devid, f) \ 736543becfSAndreas Schwab typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f)) 74c2b1a922SLeonardo Bras 75c2b1a922SLeonardo Bras /* Define a variable v that holds the address of field f of struct devid 76c2b1a922SLeonardo Bras * based at address m. Due to the way typeof works, for a field of type 77c2b1a922SLeonardo Bras * T[N] the variable has type T(*)[N], _not_ T*. 78c2b1a922SLeonardo Bras */ 79c2b1a922SLeonardo Bras #define DEF_FIELD_ADDR_VAR(m, devid, f, v) \ 80c2b1a922SLeonardo Bras typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f) 81c2b1a922SLeonardo Bras 826543becfSAndreas Schwab /* Define a variable f that holds the address of field f of struct devid 836543becfSAndreas Schwab * based at address m. Due to the way typeof works, for a field of type 846543becfSAndreas Schwab * T[N] the variable has type T(*)[N], _not_ T*. 856543becfSAndreas Schwab */ 866543becfSAndreas Schwab #define DEF_FIELD_ADDR(m, devid, f) \ 87c2b1a922SLeonardo Bras DEF_FIELD_ADDR_VAR(m, devid, f, f) 886543becfSAndreas Schwab 891da177e4SLinus Torvalds #define ADD(str, sep, cond, field) \ 901da177e4SLinus Torvalds do { \ 911da177e4SLinus Torvalds strcat(str, sep); \ 921da177e4SLinus Torvalds if (cond) \ 931da177e4SLinus Torvalds sprintf(str + strlen(str), \ 941da177e4SLinus Torvalds sizeof(field) == 1 ? "%02X" : \ 951da177e4SLinus Torvalds sizeof(field) == 2 ? "%04X" : \ 961da177e4SLinus Torvalds sizeof(field) == 4 ? "%08X" : "", \ 971da177e4SLinus Torvalds field); \ 981da177e4SLinus Torvalds else \ 991da177e4SLinus Torvalds sprintf(str + strlen(str), "*"); \ 1001da177e4SLinus Torvalds } while(0) 1011da177e4SLinus Torvalds 1022f632369SJavier Martinez Canillas /* End in a wildcard, for future extension */ 103ac551828SJean Delvare static inline void add_wildcard(char *str) 104ac551828SJean Delvare { 105ac551828SJean Delvare int len = strlen(str); 106ac551828SJean Delvare 107ac551828SJean Delvare if (str[len - 1] != '*') 108ac551828SJean Delvare strcat(str + len, "*"); 109ac551828SJean Delvare } 110ac551828SJean Delvare 111b144ce2dSGreg Kroah-Hartman static inline void add_uuid(char *str, uuid_le uuid) 112c93b76b3STomas Winkler { 113c93b76b3STomas Winkler int len = strlen(str); 114c93b76b3STomas Winkler 11559796edcSPrarit Bhargava sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 11659796edcSPrarit Bhargava uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0], 11759796edcSPrarit Bhargava uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6], 11859796edcSPrarit Bhargava uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11], 11959796edcSPrarit Bhargava uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]); 120c93b76b3STomas Winkler } 121c93b76b3STomas Winkler 122fa443bc3SThomas Weißschuh static inline void add_guid(char *str, guid_t guid) 123fa443bc3SThomas Weißschuh { 124fa443bc3SThomas Weißschuh int len = strlen(str); 125fa443bc3SThomas Weißschuh 126fa443bc3SThomas Weißschuh sprintf(str + len, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 127fa443bc3SThomas Weißschuh guid.b[3], guid.b[2], guid.b[1], guid.b[0], 128fa443bc3SThomas Weißschuh guid.b[5], guid.b[4], guid.b[7], guid.b[6], 129fa443bc3SThomas Weißschuh guid.b[8], guid.b[9], guid.b[10], guid.b[11], 130fa443bc3SThomas Weißschuh guid.b[12], guid.b[13], guid.b[14], guid.b[15]); 131fa443bc3SThomas Weißschuh } 132fa443bc3SThomas Weißschuh 133fb33d816SSam Ravnborg /** 134fb33d816SSam Ravnborg * Check that sizeof(device_id type) are consistent with size of section 135fb33d816SSam Ravnborg * in .o file. If in-consistent then userspace and kernel does not agree 136fb33d816SSam Ravnborg * on actual size which is a bug. 137e0049825SKees Cook * Also verify that the final entry in the table is all zeros. 1384ce6efedSSam Ravnborg * Ignore both checks if build host differ from target host and size differs. 139fb33d816SSam Ravnborg **/ 140e0049825SKees Cook static void device_id_check(const char *modname, const char *device_id, 141e0049825SKees Cook unsigned long size, unsigned long id_size, 142e0049825SKees Cook void *symval) 143fb33d816SSam Ravnborg { 144e0049825SKees Cook int i; 145e0049825SKees Cook 146fb33d816SSam Ravnborg if (size % id_size || size < id_size) { 1470d2573a2SGeert Uytterhoeven fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo of the size of section __mod_%s__<identifier>_device_table=%lu.\n" 1480d2573a2SGeert Uytterhoeven "Fix definition of struct %s_device_id in mod_devicetable.h\n", 149fb33d816SSam Ravnborg modname, device_id, id_size, device_id, size, device_id); 150fb33d816SSam Ravnborg } 151e0049825SKees Cook /* Verify last one is a terminator */ 152e0049825SKees Cook for (i = 0; i < id_size; i++ ) { 153e0049825SKees Cook if (*(uint8_t*)(symval+size-id_size+i)) { 1540d2573a2SGeert Uytterhoeven fprintf(stderr, 1550d2573a2SGeert Uytterhoeven "%s: struct %s_device_id is %lu bytes. The last of %lu is:\n", 156e0049825SKees Cook modname, device_id, id_size, size / id_size); 157e0049825SKees Cook for (i = 0; i < id_size; i++ ) 158e0049825SKees Cook fprintf(stderr,"0x%02x ", 159e0049825SKees Cook *(uint8_t*)(symval+size-id_size+i) ); 160e0049825SKees Cook fprintf(stderr,"\n"); 1610d2573a2SGeert Uytterhoeven fatal("%s: struct %s_device_id is not terminated with a NULL entry!\n", 1620d2573a2SGeert Uytterhoeven modname, device_id); 163e0049825SKees Cook } 164e0049825SKees Cook } 165fb33d816SSam Ravnborg } 166fb33d816SSam Ravnborg 167b19dcd93SRoman Kagan /* USB is special because the bcdDevice can be matched against a numeric range */ 16881df2d59SBjørn Mork /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */ 1696543becfSAndreas Schwab static void do_usb_entry(void *symval, 170b19dcd93SRoman Kagan unsigned int bcdDevice_initial, int bcdDevice_initial_digits, 171b19dcd93SRoman Kagan unsigned char range_lo, unsigned char range_hi, 172afe2dab4SNathaniel McCallum unsigned char max, struct module *mod) 1731da177e4SLinus Torvalds { 174b19dcd93SRoman Kagan char alias[500]; 1756543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, match_flags); 1766543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, idVendor); 1776543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, idProduct); 1786543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bcdDevice_lo); 1796543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bDeviceClass); 1806543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bDeviceSubClass); 1816543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bDeviceProtocol); 1826543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceClass); 1836543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceSubClass); 1846543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceProtocol); 1856543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceNumber); 1866543becfSAndreas Schwab 1871da177e4SLinus Torvalds strcpy(alias, "usb:"); 1886543becfSAndreas Schwab ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR, 1896543becfSAndreas Schwab idVendor); 1906543becfSAndreas Schwab ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT, 1916543becfSAndreas Schwab idProduct); 192b19dcd93SRoman Kagan 193b19dcd93SRoman Kagan strcat(alias, "d"); 194b19dcd93SRoman Kagan if (bcdDevice_initial_digits) 195b19dcd93SRoman Kagan sprintf(alias + strlen(alias), "%0*X", 196b19dcd93SRoman Kagan bcdDevice_initial_digits, bcdDevice_initial); 197b19dcd93SRoman Kagan if (range_lo == range_hi) 198afe2dab4SNathaniel McCallum sprintf(alias + strlen(alias), "%X", range_lo); 199afe2dab4SNathaniel McCallum else if (range_lo > 0 || range_hi < max) { 200afe2dab4SNathaniel McCallum if (range_lo > 0x9 || range_hi < 0xA) 201afe2dab4SNathaniel McCallum sprintf(alias + strlen(alias), 202afe2dab4SNathaniel McCallum "[%X-%X]", 203afe2dab4SNathaniel McCallum range_lo, 204afe2dab4SNathaniel McCallum range_hi); 205afe2dab4SNathaniel McCallum else { 206afe2dab4SNathaniel McCallum sprintf(alias + strlen(alias), 207afe2dab4SNathaniel McCallum range_lo < 0x9 ? "[%X-9" : "[%X", 208afe2dab4SNathaniel McCallum range_lo); 209afe2dab4SNathaniel McCallum sprintf(alias + strlen(alias), 21003b56329SJan Moskyto Matejka range_hi > 0xA ? "A-%X]" : "%X]", 21103b56329SJan Moskyto Matejka range_hi); 212afe2dab4SNathaniel McCallum } 213afe2dab4SNathaniel McCallum } 2146543becfSAndreas Schwab if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1)) 215b19dcd93SRoman Kagan strcat(alias, "*"); 216b19dcd93SRoman Kagan 2176543becfSAndreas Schwab ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, 2186543becfSAndreas Schwab bDeviceClass); 2196543becfSAndreas Schwab ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS, 2206543becfSAndreas Schwab bDeviceSubClass); 2216543becfSAndreas Schwab ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL, 2226543becfSAndreas Schwab bDeviceProtocol); 2236543becfSAndreas Schwab ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS, 2246543becfSAndreas Schwab bInterfaceClass); 2256543becfSAndreas Schwab ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2266543becfSAndreas Schwab bInterfaceSubClass); 2276543becfSAndreas Schwab ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, 2286543becfSAndreas Schwab bInterfaceProtocol); 2296543becfSAndreas Schwab ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER, 2306543becfSAndreas Schwab bInterfaceNumber); 231b19dcd93SRoman Kagan 232ac551828SJean Delvare add_wildcard(alias); 233b19dcd93SRoman Kagan buf_printf(&mod->dev_table_buf, 234b19dcd93SRoman Kagan "MODULE_ALIAS(\"%s\");\n", alias); 235b19dcd93SRoman Kagan } 236b19dcd93SRoman Kagan 23755f49f26SNathaniel McCallum /* Handles increment/decrement of BCD formatted integers */ 23855f49f26SNathaniel McCallum /* Returns the previous value, so it works like i++ or i-- */ 23955f49f26SNathaniel McCallum static unsigned int incbcd(unsigned int *bcd, 24055f49f26SNathaniel McCallum int inc, 24155f49f26SNathaniel McCallum unsigned char max, 24255f49f26SNathaniel McCallum size_t chars) 24355f49f26SNathaniel McCallum { 24455f49f26SNathaniel McCallum unsigned int init = *bcd, i, j; 24555f49f26SNathaniel McCallum unsigned long long c, dec = 0; 24655f49f26SNathaniel McCallum 24755f49f26SNathaniel McCallum /* If bcd is not in BCD format, just increment */ 24855f49f26SNathaniel McCallum if (max > 0x9) { 24955f49f26SNathaniel McCallum *bcd += inc; 25055f49f26SNathaniel McCallum return init; 25155f49f26SNathaniel McCallum } 25255f49f26SNathaniel McCallum 25355f49f26SNathaniel McCallum /* Convert BCD to Decimal */ 25455f49f26SNathaniel McCallum for (i=0 ; i < chars ; i++) { 25555f49f26SNathaniel McCallum c = (*bcd >> (i << 2)) & 0xf; 25655f49f26SNathaniel McCallum c = c > 9 ? 9 : c; /* force to bcd just in case */ 25755f49f26SNathaniel McCallum for (j=0 ; j < i ; j++) 25855f49f26SNathaniel McCallum c = c * 10; 25955f49f26SNathaniel McCallum dec += c; 26055f49f26SNathaniel McCallum } 26155f49f26SNathaniel McCallum 26255f49f26SNathaniel McCallum /* Do our increment/decrement */ 26355f49f26SNathaniel McCallum dec += inc; 26455f49f26SNathaniel McCallum *bcd = 0; 26555f49f26SNathaniel McCallum 26655f49f26SNathaniel McCallum /* Convert back to BCD */ 26755f49f26SNathaniel McCallum for (i=0 ; i < chars ; i++) { 26855f49f26SNathaniel McCallum for (c=1,j=0 ; j < i ; j++) 26955f49f26SNathaniel McCallum c = c * 10; 27055f49f26SNathaniel McCallum c = (dec / c) % 10; 27155f49f26SNathaniel McCallum *bcd += c << (i << 2); 27255f49f26SNathaniel McCallum } 27355f49f26SNathaniel McCallum return init; 27455f49f26SNathaniel McCallum } 27555f49f26SNathaniel McCallum 2766543becfSAndreas Schwab static void do_usb_entry_multi(void *symval, struct module *mod) 277b19dcd93SRoman Kagan { 278b19dcd93SRoman Kagan unsigned int devlo, devhi; 279afe2dab4SNathaniel McCallum unsigned char chi, clo, max; 280b19dcd93SRoman Kagan int ndigits; 281b19dcd93SRoman Kagan 2826543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, match_flags); 2836543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, idVendor); 2846543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, idProduct); 2856543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bcdDevice_lo); 2866543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bcdDevice_hi); 2876543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bDeviceClass); 2886543becfSAndreas Schwab DEF_FIELD(symval, usb_device_id, bInterfaceClass); 289b19dcd93SRoman Kagan 2906543becfSAndreas Schwab devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ? 2916543becfSAndreas Schwab bcdDevice_lo : 0x0U; 2926543becfSAndreas Schwab devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? 2936543becfSAndreas Schwab bcdDevice_hi : ~0x0U; 294b19dcd93SRoman Kagan 295afe2dab4SNathaniel McCallum /* Figure out if this entry is in bcd or hex format */ 296afe2dab4SNathaniel McCallum max = 0x9; /* Default to decimal format */ 2976543becfSAndreas Schwab for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) { 298afe2dab4SNathaniel McCallum clo = (devlo >> (ndigits << 2)) & 0xf; 299afe2dab4SNathaniel McCallum chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf; 300afe2dab4SNathaniel McCallum if (clo > max || chi > max) { 301afe2dab4SNathaniel McCallum max = 0xf; 302afe2dab4SNathaniel McCallum break; 303afe2dab4SNathaniel McCallum } 304afe2dab4SNathaniel McCallum } 305afe2dab4SNathaniel McCallum 306b19dcd93SRoman Kagan /* 307b19dcd93SRoman Kagan * Some modules (visor) have empty slots as placeholder for 308b19dcd93SRoman Kagan * run-time specification that results in catch-all alias 309b19dcd93SRoman Kagan */ 3106543becfSAndreas Schwab if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass)) 311b19dcd93SRoman Kagan return; 312b19dcd93SRoman Kagan 313b19dcd93SRoman Kagan /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */ 3146543becfSAndreas Schwab for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { 315b19dcd93SRoman Kagan clo = devlo & 0xf; 316b19dcd93SRoman Kagan chi = devhi & 0xf; 317afe2dab4SNathaniel McCallum if (chi > max) /* If we are in bcd mode, truncate if necessary */ 318afe2dab4SNathaniel McCallum chi = max; 319b19dcd93SRoman Kagan devlo >>= 4; 320b19dcd93SRoman Kagan devhi >>= 4; 321b19dcd93SRoman Kagan 322b19dcd93SRoman Kagan if (devlo == devhi || !ndigits) { 3236543becfSAndreas Schwab do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod); 324b19dcd93SRoman Kagan break; 325b19dcd93SRoman Kagan } 326b19dcd93SRoman Kagan 327afe2dab4SNathaniel McCallum if (clo > 0x0) 3286543becfSAndreas Schwab do_usb_entry(symval, 32955f49f26SNathaniel McCallum incbcd(&devlo, 1, max, 3306543becfSAndreas Schwab sizeof(bcdDevice_lo) * 2), 33155f49f26SNathaniel McCallum ndigits, clo, max, max, mod); 332b19dcd93SRoman Kagan 333afe2dab4SNathaniel McCallum if (chi < max) 3346543becfSAndreas Schwab do_usb_entry(symval, 33555f49f26SNathaniel McCallum incbcd(&devhi, -1, max, 3366543becfSAndreas Schwab sizeof(bcdDevice_lo) * 2), 33755f49f26SNathaniel McCallum ndigits, 0x0, chi, max, mod); 338b19dcd93SRoman Kagan } 339b19dcd93SRoman Kagan } 340b19dcd93SRoman Kagan 341b19dcd93SRoman Kagan static void do_usb_table(void *symval, unsigned long size, 342b19dcd93SRoman Kagan struct module *mod) 343b19dcd93SRoman Kagan { 344b19dcd93SRoman Kagan unsigned int i; 3456543becfSAndreas Schwab const unsigned long id_size = SIZE_usb_device_id; 346b19dcd93SRoman Kagan 347e0049825SKees Cook device_id_check(mod->name, "usb", size, id_size, symval); 348fb33d816SSam Ravnborg 349b19dcd93SRoman Kagan /* Leave last one: it's the terminator. */ 350b19dcd93SRoman Kagan size -= id_size; 351b19dcd93SRoman Kagan 352b19dcd93SRoman Kagan for (i = 0; i < size; i += id_size) 353b19dcd93SRoman Kagan do_usb_entry_multi(symval + i, mod); 3541da177e4SLinus Torvalds } 3551da177e4SLinus Torvalds 356acbef7b7SPhilipp Zabel static void do_of_entry_multi(void *symval, struct module *mod) 357acbef7b7SPhilipp Zabel { 358acbef7b7SPhilipp Zabel char alias[500]; 359acbef7b7SPhilipp Zabel int len; 360acbef7b7SPhilipp Zabel char *tmp; 361acbef7b7SPhilipp Zabel 362acbef7b7SPhilipp Zabel DEF_FIELD_ADDR(symval, of_device_id, name); 363acbef7b7SPhilipp Zabel DEF_FIELD_ADDR(symval, of_device_id, type); 364acbef7b7SPhilipp Zabel DEF_FIELD_ADDR(symval, of_device_id, compatible); 365acbef7b7SPhilipp Zabel 366acbef7b7SPhilipp Zabel len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*", 367acbef7b7SPhilipp Zabel (*type)[0] ? *type : "*"); 368acbef7b7SPhilipp Zabel 369b3c0a4daSWolfram Sang if ((*compatible)[0]) 370acbef7b7SPhilipp Zabel sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "", 371acbef7b7SPhilipp Zabel *compatible); 372acbef7b7SPhilipp Zabel 373acbef7b7SPhilipp Zabel /* Replace all whitespace with underscores */ 374acbef7b7SPhilipp Zabel for (tmp = alias; tmp && *tmp; tmp++) 375acbef7b7SPhilipp Zabel if (isspace(*tmp)) 376acbef7b7SPhilipp Zabel *tmp = '_'; 377acbef7b7SPhilipp Zabel 378acbef7b7SPhilipp Zabel buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias); 379acbef7b7SPhilipp Zabel strcat(alias, "C"); 380acbef7b7SPhilipp Zabel add_wildcard(alias); 381acbef7b7SPhilipp Zabel buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias); 382acbef7b7SPhilipp Zabel } 383acbef7b7SPhilipp Zabel 384acbef7b7SPhilipp Zabel static void do_of_table(void *symval, unsigned long size, 385acbef7b7SPhilipp Zabel struct module *mod) 386acbef7b7SPhilipp Zabel { 387acbef7b7SPhilipp Zabel unsigned int i; 388acbef7b7SPhilipp Zabel const unsigned long id_size = SIZE_of_device_id; 389acbef7b7SPhilipp Zabel 390acbef7b7SPhilipp Zabel device_id_check(mod->name, "of", size, id_size, symval); 391acbef7b7SPhilipp Zabel 392acbef7b7SPhilipp Zabel /* Leave last one: it's the terminator. */ 393acbef7b7SPhilipp Zabel size -= id_size; 394acbef7b7SPhilipp Zabel 395acbef7b7SPhilipp Zabel for (i = 0; i < size; i += id_size) 396acbef7b7SPhilipp Zabel do_of_entry_multi(symval + i, mod); 397acbef7b7SPhilipp Zabel } 398acbef7b7SPhilipp Zabel 399e8c84f9aSJiri Slaby /* Looks like: hid:bNvNpN */ 400e8c84f9aSJiri Slaby static int do_hid_entry(const char *filename, 4016543becfSAndreas Schwab void *symval, char *alias) 402e8c84f9aSJiri Slaby { 4036543becfSAndreas Schwab DEF_FIELD(symval, hid_device_id, bus); 4046543becfSAndreas Schwab DEF_FIELD(symval, hid_device_id, group); 4056543becfSAndreas Schwab DEF_FIELD(symval, hid_device_id, vendor); 4066543becfSAndreas Schwab DEF_FIELD(symval, hid_device_id, product); 407e8c84f9aSJiri Slaby 4087431fb76SHenrik Rydberg sprintf(alias, "hid:"); 4096543becfSAndreas Schwab ADD(alias, "b", bus != HID_BUS_ANY, bus); 4106543becfSAndreas Schwab ADD(alias, "g", group != HID_GROUP_ANY, group); 4116543becfSAndreas Schwab ADD(alias, "v", vendor != HID_ANY_ID, vendor); 4126543becfSAndreas Schwab ADD(alias, "p", product != HID_ANY_ID, product); 413e8c84f9aSJiri Slaby 414e8c84f9aSJiri Slaby return 1; 415e8c84f9aSJiri Slaby } 416e8c84f9aSJiri Slaby 4171da177e4SLinus Torvalds /* Looks like: ieee1394:venNmoNspNverN */ 4181da177e4SLinus Torvalds static int do_ieee1394_entry(const char *filename, 4196543becfSAndreas Schwab void *symval, char *alias) 4201da177e4SLinus Torvalds { 4216543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, match_flags); 4226543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, vendor_id); 4236543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, model_id); 4246543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, specifier_id); 4256543becfSAndreas Schwab DEF_FIELD(symval, ieee1394_device_id, version); 4261da177e4SLinus Torvalds 4271da177e4SLinus Torvalds strcpy(alias, "ieee1394:"); 4286543becfSAndreas Schwab ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID, 4296543becfSAndreas Schwab vendor_id); 4306543becfSAndreas Schwab ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID, 4316543becfSAndreas Schwab model_id); 4326543becfSAndreas Schwab ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID, 4336543becfSAndreas Schwab specifier_id); 4346543becfSAndreas Schwab ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION, 4356543becfSAndreas Schwab version); 4361da177e4SLinus Torvalds 437ac551828SJean Delvare add_wildcard(alias); 4381da177e4SLinus Torvalds return 1; 4391da177e4SLinus Torvalds } 4401da177e4SLinus Torvalds 441cc6711b0SMax Gurtovoy /* Looks like: pci:vNdNsvNsdNbcNscNiN or <prefix>_pci:vNdNsvNsdNbcNscNiN. */ 4421da177e4SLinus Torvalds static int do_pci_entry(const char *filename, 4436543becfSAndreas Schwab void *symval, char *alias) 4441da177e4SLinus Torvalds { 4451da177e4SLinus Torvalds /* Class field can be divided into these three. */ 4461da177e4SLinus Torvalds unsigned char baseclass, subclass, interface, 4471da177e4SLinus Torvalds baseclass_mask, subclass_mask, interface_mask; 4481da177e4SLinus Torvalds 4496543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, vendor); 4506543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, device); 4516543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, subvendor); 4526543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, subdevice); 4536543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, class); 4546543becfSAndreas Schwab DEF_FIELD(symval, pci_device_id, class_mask); 455cc6711b0SMax Gurtovoy DEF_FIELD(symval, pci_device_id, override_only); 4561da177e4SLinus Torvalds 457cc6711b0SMax Gurtovoy switch (override_only) { 458cc6711b0SMax Gurtovoy case 0: 4591da177e4SLinus Torvalds strcpy(alias, "pci:"); 460cc6711b0SMax Gurtovoy break; 461cc6711b0SMax Gurtovoy case PCI_ID_F_VFIO_DRIVER_OVERRIDE: 462cc6711b0SMax Gurtovoy strcpy(alias, "vfio_pci:"); 463cc6711b0SMax Gurtovoy break; 464cc6711b0SMax Gurtovoy default: 465cc6711b0SMax Gurtovoy warn("Unknown PCI driver_override alias %08X\n", 466cc6711b0SMax Gurtovoy override_only); 467cc6711b0SMax Gurtovoy return 0; 468cc6711b0SMax Gurtovoy } 469cc6711b0SMax Gurtovoy 4706543becfSAndreas Schwab ADD(alias, "v", vendor != PCI_ANY_ID, vendor); 4716543becfSAndreas Schwab ADD(alias, "d", device != PCI_ANY_ID, device); 4726543becfSAndreas Schwab ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor); 4736543becfSAndreas Schwab ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice); 4741da177e4SLinus Torvalds 4756543becfSAndreas Schwab baseclass = (class) >> 16; 4766543becfSAndreas Schwab baseclass_mask = (class_mask) >> 16; 4776543becfSAndreas Schwab subclass = (class) >> 8; 4786543becfSAndreas Schwab subclass_mask = (class_mask) >> 8; 4796543becfSAndreas Schwab interface = class; 4806543becfSAndreas Schwab interface_mask = class_mask; 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds if ((baseclass_mask != 0 && baseclass_mask != 0xFF) 4831da177e4SLinus Torvalds || (subclass_mask != 0 && subclass_mask != 0xFF) 4841da177e4SLinus Torvalds || (interface_mask != 0 && interface_mask != 0xFF)) { 485cb80514dSSam Ravnborg warn("Can't handle masks in %s:%04X\n", 4866543becfSAndreas Schwab filename, class_mask); 4871da177e4SLinus Torvalds return 0; 4881da177e4SLinus Torvalds } 4891da177e4SLinus Torvalds 4901da177e4SLinus Torvalds ADD(alias, "bc", baseclass_mask == 0xFF, baseclass); 4911da177e4SLinus Torvalds ADD(alias, "sc", subclass_mask == 0xFF, subclass); 4921da177e4SLinus Torvalds ADD(alias, "i", interface_mask == 0xFF, interface); 493ac551828SJean Delvare add_wildcard(alias); 4941da177e4SLinus Torvalds return 1; 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 4971da177e4SLinus Torvalds /* looks like: "ccw:tNmNdtNdmN" */ 4981da177e4SLinus Torvalds static int do_ccw_entry(const char *filename, 4996543becfSAndreas Schwab void *symval, char *alias) 5001da177e4SLinus Torvalds { 5016543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, match_flags); 5026543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, cu_type); 5036543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, cu_model); 5046543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, dev_type); 5056543becfSAndreas Schwab DEF_FIELD(symval, ccw_device_id, dev_model); 5061da177e4SLinus Torvalds 5071da177e4SLinus Torvalds strcpy(alias, "ccw:"); 5086543becfSAndreas Schwab ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE, 5096543becfSAndreas Schwab cu_type); 5106543becfSAndreas Schwab ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL, 5116543becfSAndreas Schwab cu_model); 5126543becfSAndreas Schwab ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE, 5136543becfSAndreas Schwab dev_type); 5146543becfSAndreas Schwab ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL, 5156543becfSAndreas Schwab dev_model); 516ac551828SJean Delvare add_wildcard(alias); 5171da177e4SLinus Torvalds return 1; 5181da177e4SLinus Torvalds } 5191da177e4SLinus Torvalds 5201534c382SMartin Schwidefsky /* looks like: "ap:tN" */ 5211534c382SMartin Schwidefsky static int do_ap_entry(const char *filename, 5226543becfSAndreas Schwab void *symval, char *alias) 5231534c382SMartin Schwidefsky { 5246543becfSAndreas Schwab DEF_FIELD(symval, ap_device_id, dev_type); 5256543becfSAndreas Schwab 5266543becfSAndreas Schwab sprintf(alias, "ap:t%02X*", dev_type); 5271534c382SMartin Schwidefsky return 1; 5281534c382SMartin Schwidefsky } 5291534c382SMartin Schwidefsky 5307e9db9eaSCornelia Huck /* looks like: "css:tN" */ 5317e9db9eaSCornelia Huck static int do_css_entry(const char *filename, 5326543becfSAndreas Schwab void *symval, char *alias) 5337e9db9eaSCornelia Huck { 5346543becfSAndreas Schwab DEF_FIELD(symval, css_device_id, type); 5356543becfSAndreas Schwab 5366543becfSAndreas Schwab sprintf(alias, "css:t%01X", type); 5377e9db9eaSCornelia Huck return 1; 5387e9db9eaSCornelia Huck } 5397e9db9eaSCornelia Huck 5401da177e4SLinus Torvalds /* Looks like: "serio:tyNprNidNexN" */ 5411da177e4SLinus Torvalds static int do_serio_entry(const char *filename, 5426543becfSAndreas Schwab void *symval, char *alias) 5431da177e4SLinus Torvalds { 5446543becfSAndreas Schwab DEF_FIELD(symval, serio_device_id, type); 5456543becfSAndreas Schwab DEF_FIELD(symval, serio_device_id, proto); 5466543becfSAndreas Schwab DEF_FIELD(symval, serio_device_id, id); 5476543becfSAndreas Schwab DEF_FIELD(symval, serio_device_id, extra); 5481da177e4SLinus Torvalds 5491da177e4SLinus Torvalds strcpy(alias, "serio:"); 5506543becfSAndreas Schwab ADD(alias, "ty", type != SERIO_ANY, type); 5516543becfSAndreas Schwab ADD(alias, "pr", proto != SERIO_ANY, proto); 5526543becfSAndreas Schwab ADD(alias, "id", id != SERIO_ANY, id); 5536543becfSAndreas Schwab ADD(alias, "ex", extra != SERIO_ANY, extra); 5541da177e4SLinus Torvalds 555ac551828SJean Delvare add_wildcard(alias); 5561da177e4SLinus Torvalds return 1; 5571da177e4SLinus Torvalds } 5581da177e4SLinus Torvalds 55926095a01SSuthikulpanit, Suravee /* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or 56026095a01SSuthikulpanit, Suravee * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if) 56126095a01SSuthikulpanit, Suravee * 56226095a01SSuthikulpanit, Suravee * NOTE: Each driver should use one of the following : _HID, _CIDs 56326095a01SSuthikulpanit, Suravee * or _CLS. Also, bb, ss, and pp can be substituted with ?? 56426095a01SSuthikulpanit, Suravee * as don't care byte. 56526095a01SSuthikulpanit, Suravee */ 56629b71a1cSThomas Renninger static int do_acpi_entry(const char *filename, 5676543becfSAndreas Schwab void *symval, char *alias) 56829b71a1cSThomas Renninger { 5696543becfSAndreas Schwab DEF_FIELD_ADDR(symval, acpi_device_id, id); 57026095a01SSuthikulpanit, Suravee DEF_FIELD_ADDR(symval, acpi_device_id, cls); 57126095a01SSuthikulpanit, Suravee DEF_FIELD_ADDR(symval, acpi_device_id, cls_msk); 57226095a01SSuthikulpanit, Suravee 57326095a01SSuthikulpanit, Suravee if (id && strlen((const char *)*id)) 5746543becfSAndreas Schwab sprintf(alias, "acpi*:%s:*", *id); 57526095a01SSuthikulpanit, Suravee else if (cls) { 57626095a01SSuthikulpanit, Suravee int i, byte_shift, cnt = 0; 57726095a01SSuthikulpanit, Suravee unsigned int msk; 57826095a01SSuthikulpanit, Suravee 57926095a01SSuthikulpanit, Suravee sprintf(&alias[cnt], "acpi*:"); 58026095a01SSuthikulpanit, Suravee cnt = 6; 58126095a01SSuthikulpanit, Suravee for (i = 1; i <= 3; i++) { 58226095a01SSuthikulpanit, Suravee byte_shift = 8 * (3-i); 58326095a01SSuthikulpanit, Suravee msk = (*cls_msk >> byte_shift) & 0xFF; 58426095a01SSuthikulpanit, Suravee if (msk) 58526095a01SSuthikulpanit, Suravee sprintf(&alias[cnt], "%02x", 58626095a01SSuthikulpanit, Suravee (*cls >> byte_shift) & 0xFF); 58726095a01SSuthikulpanit, Suravee else 58826095a01SSuthikulpanit, Suravee sprintf(&alias[cnt], "??"); 58926095a01SSuthikulpanit, Suravee cnt += 2; 59026095a01SSuthikulpanit, Suravee } 59126095a01SSuthikulpanit, Suravee sprintf(&alias[cnt], ":*"); 59226095a01SSuthikulpanit, Suravee } 59329b71a1cSThomas Renninger return 1; 59429b71a1cSThomas Renninger } 59529b71a1cSThomas Renninger 5961da177e4SLinus Torvalds /* looks like: "pnp:dD" */ 59722454cb9SKay Sievers static void do_pnp_device_entry(void *symval, unsigned long size, 59822454cb9SKay Sievers struct module *mod) 5991da177e4SLinus Torvalds { 6006543becfSAndreas Schwab const unsigned long id_size = SIZE_pnp_device_id; 6015e4c6564SKay Sievers const unsigned int count = (size / id_size)-1; 6025e4c6564SKay Sievers unsigned int i; 60322454cb9SKay Sievers 60422454cb9SKay Sievers device_id_check(mod->name, "pnp", size, id_size, symval); 60522454cb9SKay Sievers 6065e4c6564SKay Sievers for (i = 0; i < count; i++) { 6076543becfSAndreas Schwab DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id); 6086543becfSAndreas Schwab char acpi_id[sizeof(*id)]; 60972638f59SKay Sievers int j; 6105e4c6564SKay Sievers 61122454cb9SKay Sievers buf_printf(&mod->dev_table_buf, 6126543becfSAndreas Schwab "MODULE_ALIAS(\"pnp:d%s*\");\n", *id); 61372638f59SKay Sievers 61472638f59SKay Sievers /* fix broken pnp bus lowercasing */ 61572638f59SKay Sievers for (j = 0; j < sizeof(acpi_id); j++) 6166543becfSAndreas Schwab acpi_id[j] = toupper((*id)[j]); 61722454cb9SKay Sievers buf_printf(&mod->dev_table_buf, 61872638f59SKay Sievers "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id); 6195e4c6564SKay Sievers } 6201da177e4SLinus Torvalds } 6211da177e4SLinus Torvalds 6220c81eed4SKay Sievers /* looks like: "pnp:dD" for every device of the card */ 6230c81eed4SKay Sievers static void do_pnp_card_entries(void *symval, unsigned long size, 6240c81eed4SKay Sievers struct module *mod) 6251da177e4SLinus Torvalds { 6266543becfSAndreas Schwab const unsigned long id_size = SIZE_pnp_card_device_id; 6270c81eed4SKay Sievers const unsigned int count = (size / id_size)-1; 6280c81eed4SKay Sievers unsigned int i; 6291da177e4SLinus Torvalds 6300c81eed4SKay Sievers device_id_check(mod->name, "pnp", size, id_size, symval); 6310c81eed4SKay Sievers 6320c81eed4SKay Sievers for (i = 0; i < count; i++) { 6330c81eed4SKay Sievers unsigned int j; 6346543becfSAndreas Schwab DEF_FIELD_ADDR(symval + i * id_size, pnp_card_device_id, devs); 6350c81eed4SKay Sievers 6360c81eed4SKay Sievers for (j = 0; j < PNP_MAX_DEVICES; j++) { 6376543becfSAndreas Schwab const char *id = (char *)(*devs)[j].id; 6380c81eed4SKay Sievers int i2, j2; 6390c81eed4SKay Sievers int dup = 0; 6400c81eed4SKay Sievers 6410c81eed4SKay Sievers if (!id[0]) 6421da177e4SLinus Torvalds break; 6430c81eed4SKay Sievers 6440c81eed4SKay Sievers /* find duplicate, already added value */ 6450c81eed4SKay Sievers for (i2 = 0; i2 < i && !dup; i2++) { 646c2b1a922SLeonardo Bras DEF_FIELD_ADDR_VAR(symval + i2 * id_size, 647c2b1a922SLeonardo Bras pnp_card_device_id, 648c2b1a922SLeonardo Bras devs, devs_dup); 6490c81eed4SKay Sievers 6500c81eed4SKay Sievers for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) { 651c2b1a922SLeonardo Bras const char *id2 = 652c2b1a922SLeonardo Bras (char *)(*devs_dup)[j2].id; 6530c81eed4SKay Sievers 6540c81eed4SKay Sievers if (!id2[0]) 6550c81eed4SKay Sievers break; 6560c81eed4SKay Sievers 6570c81eed4SKay Sievers if (!strcmp(id, id2)) { 6580c81eed4SKay Sievers dup = 1; 6590c81eed4SKay Sievers break; 6601da177e4SLinus Torvalds } 6610c81eed4SKay Sievers } 6620c81eed4SKay Sievers } 6630c81eed4SKay Sievers 6640c81eed4SKay Sievers /* add an individual alias for every device entry */ 66522454cb9SKay Sievers if (!dup) { 6666543becfSAndreas Schwab char acpi_id[PNP_ID_LEN]; 66772638f59SKay Sievers int k; 66872638f59SKay Sievers 6690c81eed4SKay Sievers buf_printf(&mod->dev_table_buf, 6700c81eed4SKay Sievers "MODULE_ALIAS(\"pnp:d%s*\");\n", id); 67172638f59SKay Sievers 67272638f59SKay Sievers /* fix broken pnp bus lowercasing */ 67372638f59SKay Sievers for (k = 0; k < sizeof(acpi_id); k++) 67472638f59SKay Sievers acpi_id[k] = toupper(id[k]); 67522454cb9SKay Sievers buf_printf(&mod->dev_table_buf, 67672638f59SKay Sievers "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id); 67722454cb9SKay Sievers } 6780c81eed4SKay Sievers } 6790c81eed4SKay Sievers } 6801da177e4SLinus Torvalds } 6811da177e4SLinus Torvalds 68290829cfeSDominik Brodowski /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */ 68390829cfeSDominik Brodowski static int do_pcmcia_entry(const char *filename, 6846543becfSAndreas Schwab void *symval, char *alias) 68590829cfeSDominik Brodowski { 68690829cfeSDominik Brodowski unsigned int i; 6876543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, match_flags); 6886543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, manf_id); 6896543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, card_id); 6906543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, func_id); 6916543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, function); 6926543becfSAndreas Schwab DEF_FIELD(symval, pcmcia_device_id, device_no); 6936543becfSAndreas Schwab DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash); 6944fb7edceSKars de Jong 69590829cfeSDominik Brodowski for (i=0; i<4; i++) { 6966543becfSAndreas Schwab (*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]); 69790829cfeSDominik Brodowski } 69890829cfeSDominik Brodowski 69990829cfeSDominik Brodowski strcpy(alias, "pcmcia:"); 7006543becfSAndreas Schwab ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID, 7016543becfSAndreas Schwab manf_id); 7026543becfSAndreas Schwab ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID, 7036543becfSAndreas Schwab card_id); 7046543becfSAndreas Schwab ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID, 7056543becfSAndreas Schwab func_id); 7066543becfSAndreas Schwab ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION, 7076543becfSAndreas Schwab function); 7086543becfSAndreas Schwab ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO, 7096543becfSAndreas Schwab device_no); 7106543becfSAndreas Schwab ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]); 7116543becfSAndreas Schwab ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]); 7126543becfSAndreas Schwab ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]); 7136543becfSAndreas Schwab ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]); 71490829cfeSDominik Brodowski 715ac551828SJean Delvare add_wildcard(alias); 71690829cfeSDominik Brodowski return 1; 71790829cfeSDominik Brodowski } 71890829cfeSDominik Brodowski 7196543becfSAndreas Schwab static int do_vio_entry(const char *filename, void *symval, 720fb120da6SStephen Rothwell char *alias) 721fb120da6SStephen Rothwell { 722fb120da6SStephen Rothwell char *tmp; 7236543becfSAndreas Schwab DEF_FIELD_ADDR(symval, vio_device_id, type); 7246543becfSAndreas Schwab DEF_FIELD_ADDR(symval, vio_device_id, compat); 725fb120da6SStephen Rothwell 7266543becfSAndreas Schwab sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*", 7276543becfSAndreas Schwab (*compat)[0] ? *compat : "*"); 728fb120da6SStephen Rothwell 729fb120da6SStephen Rothwell /* Replace all whitespace with underscores */ 730fb120da6SStephen Rothwell for (tmp = alias; tmp && *tmp; tmp++) 731fb120da6SStephen Rothwell if (isspace (*tmp)) 732fb120da6SStephen Rothwell *tmp = '_'; 733fb120da6SStephen Rothwell 734ac551828SJean Delvare add_wildcard(alias); 735fb120da6SStephen Rothwell return 1; 736fb120da6SStephen Rothwell } 737fb120da6SStephen Rothwell 7381d8f430cSRusty Russell static void do_input(char *alias, 7391d8f430cSRusty Russell kernel_ulong_t *arr, unsigned int min, unsigned int max) 7401d8f430cSRusty Russell { 7411d8f430cSRusty Russell unsigned int i; 742ddc5d341SDmitry Torokhov 7436543becfSAndreas Schwab for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++) 7446543becfSAndreas Schwab arr[i] = TO_NATIVE(arr[i]); 745ddc5d341SDmitry Torokhov for (i = min; i < max; i++) 746e0e92632SHans de Goede if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) 7471d8f430cSRusty Russell sprintf(alias + strlen(alias), "%X,*", i); 7481d8f430cSRusty Russell } 7491d8f430cSRusty Russell 75009c3e01bSDmitry Torokhov /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */ 7516543becfSAndreas Schwab static int do_input_entry(const char *filename, void *symval, 7521d8f430cSRusty Russell char *alias) 7531d8f430cSRusty Russell { 7546543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, flags); 7556543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, bustype); 7566543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, vendor); 7576543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, product); 7586543becfSAndreas Schwab DEF_FIELD(symval, input_device_id, version); 7596543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, evbit); 7606543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, keybit); 7616543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, relbit); 7626543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, absbit); 7636543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, mscbit); 7646543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, ledbit); 7656543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, sndbit); 7666543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, ffbit); 7676543becfSAndreas Schwab DEF_FIELD_ADDR(symval, input_device_id, swbit); 7686543becfSAndreas Schwab 7691d8f430cSRusty Russell sprintf(alias, "input:"); 7701d8f430cSRusty Russell 7716543becfSAndreas Schwab ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype); 7726543becfSAndreas Schwab ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor); 7736543becfSAndreas Schwab ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product); 7746543becfSAndreas Schwab ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version); 7751d8f430cSRusty Russell 7761d8f430cSRusty Russell sprintf(alias + strlen(alias), "-e*"); 7776543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_EVBIT) 7786543becfSAndreas Schwab do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX); 7791d8f430cSRusty Russell sprintf(alias + strlen(alias), "k*"); 7806543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT) 7816543becfSAndreas Schwab do_input(alias, *keybit, 782dc24f0e7SSam Ravnborg INPUT_DEVICE_ID_KEY_MIN_INTERESTING, 783dc24f0e7SSam Ravnborg INPUT_DEVICE_ID_KEY_MAX); 7841d8f430cSRusty Russell sprintf(alias + strlen(alias), "r*"); 7856543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_RELBIT) 7866543becfSAndreas Schwab do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX); 7871d8f430cSRusty Russell sprintf(alias + strlen(alias), "a*"); 7886543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT) 7896543becfSAndreas Schwab do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX); 7901d8f430cSRusty Russell sprintf(alias + strlen(alias), "m*"); 7916543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_MSCIT) 7926543becfSAndreas Schwab do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX); 7931d8f430cSRusty Russell sprintf(alias + strlen(alias), "l*"); 7946543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT) 7956543becfSAndreas Schwab do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX); 7961d8f430cSRusty Russell sprintf(alias + strlen(alias), "s*"); 7976543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT) 7986543becfSAndreas Schwab do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX); 7991d8f430cSRusty Russell sprintf(alias + strlen(alias), "f*"); 8006543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_FFBIT) 8016543becfSAndreas Schwab do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX); 8021d8f430cSRusty Russell sprintf(alias + strlen(alias), "w*"); 8036543becfSAndreas Schwab if (flags & INPUT_DEVICE_ID_MATCH_SWBIT) 8046543becfSAndreas Schwab do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX); 8051d8f430cSRusty Russell return 1; 8061d8f430cSRusty Russell } 8071d8f430cSRusty Russell 8086543becfSAndreas Schwab static int do_eisa_entry(const char *filename, void *symval, 80907563c71SMichael Tokarev char *alias) 81007563c71SMichael Tokarev { 8116543becfSAndreas Schwab DEF_FIELD_ADDR(symval, eisa_device_id, sig); 8126543becfSAndreas Schwab if (sig[0]) 8136543becfSAndreas Schwab sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig); 814ac551828SJean Delvare else 815ac551828SJean Delvare strcat(alias, "*"); 81607563c71SMichael Tokarev return 1; 81707563c71SMichael Tokarev } 81807563c71SMichael Tokarev 819f3cf2673SKyle McMartin /* Looks like: parisc:tNhvNrevNsvN */ 8206543becfSAndreas Schwab static int do_parisc_entry(const char *filename, void *symval, 821f3cf2673SKyle McMartin char *alias) 822f3cf2673SKyle McMartin { 8236543becfSAndreas Schwab DEF_FIELD(symval, parisc_device_id, hw_type); 8246543becfSAndreas Schwab DEF_FIELD(symval, parisc_device_id, hversion); 8256543becfSAndreas Schwab DEF_FIELD(symval, parisc_device_id, hversion_rev); 8266543becfSAndreas Schwab DEF_FIELD(symval, parisc_device_id, sversion); 827f3cf2673SKyle McMartin 828f3cf2673SKyle McMartin strcpy(alias, "parisc:"); 8296543becfSAndreas Schwab ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type); 8306543becfSAndreas Schwab ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion); 8316543becfSAndreas Schwab ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev); 8326543becfSAndreas Schwab ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion); 833f3cf2673SKyle McMartin 834ac551828SJean Delvare add_wildcard(alias); 835f3cf2673SKyle McMartin return 1; 836f3cf2673SKyle McMartin } 837f3cf2673SKyle McMartin 838d59b66c7SPierre Ossman /* Looks like: sdio:cNvNdN. */ 839d59b66c7SPierre Ossman static int do_sdio_entry(const char *filename, 8406543becfSAndreas Schwab void *symval, char *alias) 841d59b66c7SPierre Ossman { 8426543becfSAndreas Schwab DEF_FIELD(symval, sdio_device_id, class); 8436543becfSAndreas Schwab DEF_FIELD(symval, sdio_device_id, vendor); 8446543becfSAndreas Schwab DEF_FIELD(symval, sdio_device_id, device); 845d59b66c7SPierre Ossman 846d59b66c7SPierre Ossman strcpy(alias, "sdio:"); 8476543becfSAndreas Schwab ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class); 8486543becfSAndreas Schwab ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor); 8496543becfSAndreas Schwab ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device); 850ac551828SJean Delvare add_wildcard(alias); 851038a5008SLinus Torvalds return 1; 852038a5008SLinus Torvalds } 853d59b66c7SPierre Ossman 85461e115a5SMichael Buesch /* Looks like: ssb:vNidNrevN. */ 85561e115a5SMichael Buesch static int do_ssb_entry(const char *filename, 8566543becfSAndreas Schwab void *symval, char *alias) 85761e115a5SMichael Buesch { 8586543becfSAndreas Schwab DEF_FIELD(symval, ssb_device_id, vendor); 8596543becfSAndreas Schwab DEF_FIELD(symval, ssb_device_id, coreid); 8606543becfSAndreas Schwab DEF_FIELD(symval, ssb_device_id, revision); 86161e115a5SMichael Buesch 86261e115a5SMichael Buesch strcpy(alias, "ssb:"); 8636543becfSAndreas Schwab ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor); 8646543becfSAndreas Schwab ADD(alias, "id", coreid != SSB_ANY_ID, coreid); 8656543becfSAndreas Schwab ADD(alias, "rev", revision != SSB_ANY_REV, revision); 866ac551828SJean Delvare add_wildcard(alias); 867d59b66c7SPierre Ossman return 1; 868d59b66c7SPierre Ossman } 869d59b66c7SPierre Ossman 8708369ae33SRafał Miłecki /* Looks like: bcma:mNidNrevNclN. */ 8718369ae33SRafał Miłecki static int do_bcma_entry(const char *filename, 8726543becfSAndreas Schwab void *symval, char *alias) 8738369ae33SRafał Miłecki { 8746543becfSAndreas Schwab DEF_FIELD(symval, bcma_device_id, manuf); 8756543becfSAndreas Schwab DEF_FIELD(symval, bcma_device_id, id); 8766543becfSAndreas Schwab DEF_FIELD(symval, bcma_device_id, rev); 8776543becfSAndreas Schwab DEF_FIELD(symval, bcma_device_id, class); 8788369ae33SRafał Miłecki 8798369ae33SRafał Miłecki strcpy(alias, "bcma:"); 8806543becfSAndreas Schwab ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf); 8816543becfSAndreas Schwab ADD(alias, "id", id != BCMA_ANY_ID, id); 8826543becfSAndreas Schwab ADD(alias, "rev", rev != BCMA_ANY_REV, rev); 8836543becfSAndreas Schwab ADD(alias, "cl", class != BCMA_ANY_CLASS, class); 8848369ae33SRafał Miłecki add_wildcard(alias); 8858369ae33SRafał Miłecki return 1; 8868369ae33SRafał Miłecki } 8878369ae33SRafał Miłecki 888b01d9f28SRusty Russell /* Looks like: virtio:dNvN */ 8896543becfSAndreas Schwab static int do_virtio_entry(const char *filename, void *symval, 890b01d9f28SRusty Russell char *alias) 891b01d9f28SRusty Russell { 8926543becfSAndreas Schwab DEF_FIELD(symval, virtio_device_id, device); 8936543becfSAndreas Schwab DEF_FIELD(symval, virtio_device_id, vendor); 894b01d9f28SRusty Russell 895b01d9f28SRusty Russell strcpy(alias, "virtio:"); 8966543becfSAndreas Schwab ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device); 8976543becfSAndreas Schwab ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor); 898b01d9f28SRusty Russell 899ac551828SJean Delvare add_wildcard(alias); 900b01d9f28SRusty Russell return 1; 901b01d9f28SRusty Russell } 902b01d9f28SRusty Russell 903d2ee52aaSK. Y. Srinivasan /* 904d2ee52aaSK. Y. Srinivasan * Looks like: vmbus:guid 905d2ee52aaSK. Y. Srinivasan * Each byte of the guid will be represented by two hex characters 906d2ee52aaSK. Y. Srinivasan * in the name. 907d2ee52aaSK. Y. Srinivasan */ 908d2ee52aaSK. Y. Srinivasan 9096543becfSAndreas Schwab static int do_vmbus_entry(const char *filename, void *symval, 910d2ee52aaSK. Y. Srinivasan char *alias) 911d2ee52aaSK. Y. Srinivasan { 912d2ee52aaSK. Y. Srinivasan int i; 9136543becfSAndreas Schwab DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid); 9146543becfSAndreas Schwab char guid_name[(sizeof(*guid) + 1) * 2]; 915d2ee52aaSK. Y. Srinivasan 9166543becfSAndreas Schwab for (i = 0; i < (sizeof(*guid) * 2); i += 2) 917af3ff643SK. Y. Srinivasan sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2])); 918d2ee52aaSK. Y. Srinivasan 919d2ee52aaSK. Y. Srinivasan strcpy(alias, "vmbus:"); 920d2ee52aaSK. Y. Srinivasan strcat(alias, guid_name); 921d2ee52aaSK. Y. Srinivasan 922d2ee52aaSK. Y. Srinivasan return 1; 923d2ee52aaSK. Y. Srinivasan } 924d2ee52aaSK. Y. Srinivasan 9255b7d1277SAndrew F. Davis /* Looks like: rpmsg:S */ 9265b7d1277SAndrew F. Davis static int do_rpmsg_entry(const char *filename, void *symval, 9275b7d1277SAndrew F. Davis char *alias) 9285b7d1277SAndrew F. Davis { 9295b7d1277SAndrew F. Davis DEF_FIELD_ADDR(symval, rpmsg_device_id, name); 9305b7d1277SAndrew F. Davis sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name); 9315b7d1277SAndrew F. Davis 9325b7d1277SAndrew F. Davis return 1; 9335b7d1277SAndrew F. Davis } 9345b7d1277SAndrew F. Davis 935d2653e92SJean Delvare /* Looks like: i2c:S */ 9366543becfSAndreas Schwab static int do_i2c_entry(const char *filename, void *symval, 937d2653e92SJean Delvare char *alias) 938d2653e92SJean Delvare { 9396543becfSAndreas Schwab DEF_FIELD_ADDR(symval, i2c_device_id, name); 9406543becfSAndreas Schwab sprintf(alias, I2C_MODULE_PREFIX "%s", *name); 941d2653e92SJean Delvare 942d2653e92SJean Delvare return 1; 943d2653e92SJean Delvare } 944d2653e92SJean Delvare 9451ce589adSBoris Brezillon static int do_i3c_entry(const char *filename, void *symval, 9461ce589adSBoris Brezillon char *alias) 9471ce589adSBoris Brezillon { 9481ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, match_flags); 9491ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, dcr); 9501ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, manuf_id); 9511ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, part_id); 9521ce589adSBoris Brezillon DEF_FIELD(symval, i3c_device_id, extra_info); 9531ce589adSBoris Brezillon 9541ce589adSBoris Brezillon strcpy(alias, "i3c:"); 9551ce589adSBoris Brezillon ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr); 9561ce589adSBoris Brezillon ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id); 9571ce589adSBoris Brezillon ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id); 9581ce589adSBoris Brezillon ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info); 9591ce589adSBoris Brezillon 9601ce589adSBoris Brezillon return 1; 9611ce589adSBoris Brezillon } 9621ce589adSBoris Brezillon 963e0626e38SAnton Vorontsov /* Looks like: spi:S */ 9646543becfSAndreas Schwab static int do_spi_entry(const char *filename, void *symval, 96575368bf6SAnton Vorontsov char *alias) 96675368bf6SAnton Vorontsov { 9676543becfSAndreas Schwab DEF_FIELD_ADDR(symval, spi_device_id, name); 9686543becfSAndreas Schwab sprintf(alias, SPI_MODULE_PREFIX "%s", *name); 96975368bf6SAnton Vorontsov 97075368bf6SAnton Vorontsov return 1; 97175368bf6SAnton Vorontsov } 97275368bf6SAnton Vorontsov 973d945b697SDavid Woodhouse static const struct dmifield { 974d945b697SDavid Woodhouse const char *prefix; 975d945b697SDavid Woodhouse int field; 976d945b697SDavid Woodhouse } dmi_fields[] = { 977d945b697SDavid Woodhouse { "bvn", DMI_BIOS_VENDOR }, 978d945b697SDavid Woodhouse { "bvr", DMI_BIOS_VERSION }, 979d945b697SDavid Woodhouse { "bd", DMI_BIOS_DATE }, 980f5152f4dSErwan Velu { "br", DMI_BIOS_RELEASE }, 981f5152f4dSErwan Velu { "efr", DMI_EC_FIRMWARE_RELEASE }, 982d945b697SDavid Woodhouse { "svn", DMI_SYS_VENDOR }, 983d945b697SDavid Woodhouse { "pn", DMI_PRODUCT_NAME }, 984d945b697SDavid Woodhouse { "pvr", DMI_PRODUCT_VERSION }, 985d945b697SDavid Woodhouse { "rvn", DMI_BOARD_VENDOR }, 986d945b697SDavid Woodhouse { "rn", DMI_BOARD_NAME }, 987d945b697SDavid Woodhouse { "rvr", DMI_BOARD_VERSION }, 988d945b697SDavid Woodhouse { "cvn", DMI_CHASSIS_VENDOR }, 989d945b697SDavid Woodhouse { "ct", DMI_CHASSIS_TYPE }, 990d945b697SDavid Woodhouse { "cvr", DMI_CHASSIS_VERSION }, 991d945b697SDavid Woodhouse { NULL, DMI_NONE } 992d945b697SDavid Woodhouse }; 993d945b697SDavid Woodhouse 994d945b697SDavid Woodhouse static void dmi_ascii_filter(char *d, const char *s) 995d945b697SDavid Woodhouse { 996d945b697SDavid Woodhouse /* Filter out characters we don't want to see in the modalias string */ 997d945b697SDavid Woodhouse for (; *s; s++) 998d945b697SDavid Woodhouse if (*s > ' ' && *s < 127 && *s != ':') 999d945b697SDavid Woodhouse *(d++) = *s; 1000d945b697SDavid Woodhouse 1001d945b697SDavid Woodhouse *d = 0; 1002d945b697SDavid Woodhouse } 1003d945b697SDavid Woodhouse 1004d945b697SDavid Woodhouse 10056543becfSAndreas Schwab static int do_dmi_entry(const char *filename, void *symval, 1006d945b697SDavid Woodhouse char *alias) 1007d945b697SDavid Woodhouse { 1008d945b697SDavid Woodhouse int i, j; 10096543becfSAndreas Schwab DEF_FIELD_ADDR(symval, dmi_system_id, matches); 1010d945b697SDavid Woodhouse sprintf(alias, "dmi*"); 1011d945b697SDavid Woodhouse 1012d945b697SDavid Woodhouse for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) { 1013d945b697SDavid Woodhouse for (j = 0; j < 4; j++) { 10146543becfSAndreas Schwab if ((*matches)[j].slot && 10156543becfSAndreas Schwab (*matches)[j].slot == dmi_fields[i].field) { 1016d945b697SDavid Woodhouse sprintf(alias + strlen(alias), ":%s*", 1017d945b697SDavid Woodhouse dmi_fields[i].prefix); 1018d945b697SDavid Woodhouse dmi_ascii_filter(alias + strlen(alias), 10196543becfSAndreas Schwab (*matches)[j].substr); 1020d945b697SDavid Woodhouse strcat(alias, "*"); 1021d945b697SDavid Woodhouse } 1022d945b697SDavid Woodhouse } 1023d945b697SDavid Woodhouse } 1024d945b697SDavid Woodhouse 1025d945b697SDavid Woodhouse strcat(alias, ":"); 1026d945b697SDavid Woodhouse return 1; 1027d945b697SDavid Woodhouse } 102857fee4a5SEric Miao 102957fee4a5SEric Miao static int do_platform_entry(const char *filename, 10306543becfSAndreas Schwab void *symval, char *alias) 103157fee4a5SEric Miao { 10326543becfSAndreas Schwab DEF_FIELD_ADDR(symval, platform_device_id, name); 10336543becfSAndreas Schwab sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name); 103457fee4a5SEric Miao return 1; 103557fee4a5SEric Miao } 103657fee4a5SEric Miao 10378626d3b4SDavid Woodhouse static int do_mdio_entry(const char *filename, 10386543becfSAndreas Schwab void *symval, char *alias) 10398626d3b4SDavid Woodhouse { 10408626d3b4SDavid Woodhouse int i; 10416543becfSAndreas Schwab DEF_FIELD(symval, mdio_device_id, phy_id); 10426543becfSAndreas Schwab DEF_FIELD(symval, mdio_device_id, phy_id_mask); 10438626d3b4SDavid Woodhouse 10448626d3b4SDavid Woodhouse alias += sprintf(alias, MDIO_MODULE_PREFIX); 10458626d3b4SDavid Woodhouse 10468626d3b4SDavid Woodhouse for (i = 0; i < 32; i++) { 10476543becfSAndreas Schwab if (!((phy_id_mask >> (31-i)) & 1)) 10488626d3b4SDavid Woodhouse *(alias++) = '?'; 10496543becfSAndreas Schwab else if ((phy_id >> (31-i)) & 1) 10508626d3b4SDavid Woodhouse *(alias++) = '1'; 10518626d3b4SDavid Woodhouse else 10528626d3b4SDavid Woodhouse *(alias++) = '0'; 10538626d3b4SDavid Woodhouse } 10548626d3b4SDavid Woodhouse 10558626d3b4SDavid Woodhouse /* Terminate the string */ 10568626d3b4SDavid Woodhouse *alias = 0; 10578626d3b4SDavid Woodhouse 10588626d3b4SDavid Woodhouse return 1; 10598626d3b4SDavid Woodhouse } 10608626d3b4SDavid Woodhouse 1061bf54a2b3SGeert Uytterhoeven /* Looks like: zorro:iN. */ 10626543becfSAndreas Schwab static int do_zorro_entry(const char *filename, void *symval, 1063bf54a2b3SGeert Uytterhoeven char *alias) 1064bf54a2b3SGeert Uytterhoeven { 10656543becfSAndreas Schwab DEF_FIELD(symval, zorro_device_id, id); 1066bf54a2b3SGeert Uytterhoeven strcpy(alias, "zorro:"); 10676543becfSAndreas Schwab ADD(alias, "i", id != ZORRO_WILDCARD, id); 1068bf54a2b3SGeert Uytterhoeven return 1; 1069bf54a2b3SGeert Uytterhoeven } 1070bf54a2b3SGeert Uytterhoeven 1071fedb3d27SOndrej Zary /* looks like: "pnp:dD" */ 1072fedb3d27SOndrej Zary static int do_isapnp_entry(const char *filename, 10736543becfSAndreas Schwab void *symval, char *alias) 1074fedb3d27SOndrej Zary { 10756543becfSAndreas Schwab DEF_FIELD(symval, isapnp_device_id, vendor); 10766543becfSAndreas Schwab DEF_FIELD(symval, isapnp_device_id, function); 1077fedb3d27SOndrej Zary sprintf(alias, "pnp:d%c%c%c%x%x%x%x*", 10786543becfSAndreas Schwab 'A' + ((vendor >> 2) & 0x3f) - 1, 10796543becfSAndreas Schwab 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, 10806543becfSAndreas Schwab 'A' + ((vendor >> 8) & 0x1f) - 1, 10816543becfSAndreas Schwab (function >> 4) & 0x0f, function & 0x0f, 10826543becfSAndreas Schwab (function >> 12) & 0x0f, (function >> 8) & 0x0f); 1083fedb3d27SOndrej Zary return 1; 1084fedb3d27SOndrej Zary } 1085fedb3d27SOndrej Zary 1086849e0ad2SJens Taprogge /* Looks like: "ipack:fNvNdN". */ 1087849e0ad2SJens Taprogge static int do_ipack_entry(const char *filename, 10886543becfSAndreas Schwab void *symval, char *alias) 1089849e0ad2SJens Taprogge { 10906543becfSAndreas Schwab DEF_FIELD(symval, ipack_device_id, format); 10916543becfSAndreas Schwab DEF_FIELD(symval, ipack_device_id, vendor); 10926543becfSAndreas Schwab DEF_FIELD(symval, ipack_device_id, device); 1093849e0ad2SJens Taprogge strcpy(alias, "ipack:"); 10946543becfSAndreas Schwab ADD(alias, "f", format != IPACK_ANY_FORMAT, format); 10956543becfSAndreas Schwab ADD(alias, "v", vendor != IPACK_ANY_ID, vendor); 10966543becfSAndreas Schwab ADD(alias, "d", device != IPACK_ANY_ID, device); 1097849e0ad2SJens Taprogge add_wildcard(alias); 1098849e0ad2SJens Taprogge return 1; 1099849e0ad2SJens Taprogge } 1100849e0ad2SJens Taprogge 1101523817bdSDave Martin /* 1102523817bdSDave Martin * Append a match expression for a single masked hex digit. 1103523817bdSDave Martin * outp points to a pointer to the character at which to append. 1104523817bdSDave Martin * *outp is updated on return to point just after the appended text, 1105523817bdSDave Martin * to facilitate further appending. 1106523817bdSDave Martin */ 1107523817bdSDave Martin static void append_nibble_mask(char **outp, 1108523817bdSDave Martin unsigned int nibble, unsigned int mask) 1109523817bdSDave Martin { 1110523817bdSDave Martin char *p = *outp; 1111523817bdSDave Martin unsigned int i; 1112523817bdSDave Martin 1113523817bdSDave Martin switch (mask) { 1114523817bdSDave Martin case 0: 1115523817bdSDave Martin *p++ = '?'; 1116523817bdSDave Martin break; 1117523817bdSDave Martin 1118523817bdSDave Martin case 0xf: 1119523817bdSDave Martin p += sprintf(p, "%X", nibble); 1120523817bdSDave Martin break; 1121523817bdSDave Martin 1122523817bdSDave Martin default: 1123523817bdSDave Martin /* 1124523817bdSDave Martin * Dumbly emit a match pattern for all possible matching 1125523817bdSDave Martin * digits. This could be improved in some cases using ranges, 1126523817bdSDave Martin * but it has the advantage of being trivially correct, and is 1127523817bdSDave Martin * often optimal. 1128523817bdSDave Martin */ 1129523817bdSDave Martin *p++ = '['; 1130523817bdSDave Martin for (i = 0; i < 0x10; i++) 1131523817bdSDave Martin if ((i & mask) == nibble) 1132523817bdSDave Martin p += sprintf(p, "%X", i); 1133523817bdSDave Martin *p++ = ']'; 1134523817bdSDave Martin } 1135523817bdSDave Martin 1136523817bdSDave Martin /* Ensure that the string remains NUL-terminated: */ 1137523817bdSDave Martin *p = '\0'; 1138523817bdSDave Martin 1139523817bdSDave Martin /* Advance the caller's end-of-string pointer: */ 1140523817bdSDave Martin *outp = p; 1141523817bdSDave Martin } 1142523817bdSDave Martin 1143523817bdSDave Martin /* 1144523817bdSDave Martin * looks like: "amba:dN" 1145523817bdSDave Martin * 1146523817bdSDave Martin * N is exactly 8 digits, where each is an upper-case hex digit, or 1147523817bdSDave Martin * a ? or [] pattern matching exactly one digit. 1148523817bdSDave Martin */ 1149523817bdSDave Martin static int do_amba_entry(const char *filename, 11506543becfSAndreas Schwab void *symval, char *alias) 1151523817bdSDave Martin { 1152523817bdSDave Martin unsigned int digit; 1153523817bdSDave Martin char *p = alias; 11546543becfSAndreas Schwab DEF_FIELD(symval, amba_id, id); 11556543becfSAndreas Schwab DEF_FIELD(symval, amba_id, mask); 1156523817bdSDave Martin 11576543becfSAndreas Schwab if ((id & mask) != id) 11580d2573a2SGeert Uytterhoeven fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: id=0x%08X, mask=0x%08X. Please fix this driver.\n", 11596543becfSAndreas Schwab filename, id, mask); 1160523817bdSDave Martin 1161523817bdSDave Martin p += sprintf(alias, "amba:d"); 1162523817bdSDave Martin for (digit = 0; digit < 8; digit++) 1163523817bdSDave Martin append_nibble_mask(&p, 11646543becfSAndreas Schwab (id >> (4 * (7 - digit))) & 0xf, 11656543becfSAndreas Schwab (mask >> (4 * (7 - digit))) & 0xf); 1166523817bdSDave Martin 1167523817bdSDave Martin return 1; 1168523817bdSDave Martin } 1169523817bdSDave Martin 11708286ae03SJames Hogan /* 11718286ae03SJames Hogan * looks like: "mipscdmm:tN" 11728286ae03SJames Hogan * 11738286ae03SJames Hogan * N is exactly 2 digits, where each is an upper-case hex digit, or 11748286ae03SJames Hogan * a ? or [] pattern matching exactly one digit. 11758286ae03SJames Hogan */ 11768286ae03SJames Hogan static int do_mips_cdmm_entry(const char *filename, 11778286ae03SJames Hogan void *symval, char *alias) 11788286ae03SJames Hogan { 11798286ae03SJames Hogan DEF_FIELD(symval, mips_cdmm_device_id, type); 11808286ae03SJames Hogan 11818286ae03SJames Hogan sprintf(alias, "mipscdmm:t%02X*", type); 11828286ae03SJames Hogan return 1; 11838286ae03SJames Hogan } 11848286ae03SJames Hogan 11852b9c1f03SArd Biesheuvel /* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,* 1186644e9cbbSAndi Kleen * All fields are numbers. It would be nicer to use strings for vendor 1187644e9cbbSAndi Kleen * and feature, but getting those out of the build system here is too 1188644e9cbbSAndi Kleen * complicated. 1189644e9cbbSAndi Kleen */ 1190644e9cbbSAndi Kleen 11916543becfSAndreas Schwab static int do_x86cpu_entry(const char *filename, void *symval, 1192644e9cbbSAndi Kleen char *alias) 1193644e9cbbSAndi Kleen { 11946543becfSAndreas Schwab DEF_FIELD(symval, x86_cpu_id, feature); 11956543becfSAndreas Schwab DEF_FIELD(symval, x86_cpu_id, family); 11966543becfSAndreas Schwab DEF_FIELD(symval, x86_cpu_id, model); 11976543becfSAndreas Schwab DEF_FIELD(symval, x86_cpu_id, vendor); 1198644e9cbbSAndi Kleen 11992b9c1f03SArd Biesheuvel strcpy(alias, "cpu:type:x86,"); 12002b9c1f03SArd Biesheuvel ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor); 12012b9c1f03SArd Biesheuvel ADD(alias, "fam", family != X86_FAMILY_ANY, family); 12022b9c1f03SArd Biesheuvel ADD(alias, "mod", model != X86_MODEL_ANY, model); 12035467bddaSBen Hutchings strcat(alias, ":feature:*"); 12046543becfSAndreas Schwab if (feature != X86_FEATURE_ANY) 12056543becfSAndreas Schwab sprintf(alias + strlen(alias), "%04X*", feature); 1206644e9cbbSAndi Kleen return 1; 1207644e9cbbSAndi Kleen } 1208644e9cbbSAndi Kleen 120967bad2fdSArd Biesheuvel /* LOOKS like cpu:type:*:feature:*FEAT* */ 121067bad2fdSArd Biesheuvel static int do_cpu_entry(const char *filename, void *symval, char *alias) 121167bad2fdSArd Biesheuvel { 121267bad2fdSArd Biesheuvel DEF_FIELD(symval, cpu_feature, feature); 121367bad2fdSArd Biesheuvel 121467bad2fdSArd Biesheuvel sprintf(alias, "cpu:type:*:feature:*%04X*", feature); 121567bad2fdSArd Biesheuvel return 1; 121667bad2fdSArd Biesheuvel } 121767bad2fdSArd Biesheuvel 1218b26864caSTomas Winkler /* Looks like: mei:S:uuid:N:* */ 1219e5354107SSamuel Ortiz static int do_mei_entry(const char *filename, void *symval, 1220e5354107SSamuel Ortiz char *alias) 1221e5354107SSamuel Ortiz { 1222e5354107SSamuel Ortiz DEF_FIELD_ADDR(symval, mei_cl_device_id, name); 1223c93b76b3STomas Winkler DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid); 1224b26864caSTomas Winkler DEF_FIELD(symval, mei_cl_device_id, version); 1225e5354107SSamuel Ortiz 1226c93b76b3STomas Winkler sprintf(alias, MEI_CL_MODULE_PREFIX); 1227c93b76b3STomas Winkler sprintf(alias + strlen(alias), "%s:", (*name)[0] ? *name : "*"); 1228c93b76b3STomas Winkler add_uuid(alias, *uuid); 1229b26864caSTomas Winkler ADD(alias, ":", version != MEI_CL_VERSION_ANY, version); 1230c93b76b3STomas Winkler 1231c93b76b3STomas Winkler strcat(alias, ":*"); 1232e5354107SSamuel Ortiz 1233e5354107SSamuel Ortiz return 1; 1234e5354107SSamuel Ortiz } 1235e5354107SSamuel Ortiz 12363bdbb62fSAlexandre Bounine /* Looks like: rapidio:vNdNavNadN */ 12373bdbb62fSAlexandre Bounine static int do_rio_entry(const char *filename, 12383bdbb62fSAlexandre Bounine void *symval, char *alias) 12393bdbb62fSAlexandre Bounine { 12403bdbb62fSAlexandre Bounine DEF_FIELD(symval, rio_device_id, did); 12413bdbb62fSAlexandre Bounine DEF_FIELD(symval, rio_device_id, vid); 12423bdbb62fSAlexandre Bounine DEF_FIELD(symval, rio_device_id, asm_did); 12433bdbb62fSAlexandre Bounine DEF_FIELD(symval, rio_device_id, asm_vid); 12443bdbb62fSAlexandre Bounine 12453bdbb62fSAlexandre Bounine strcpy(alias, "rapidio:"); 12463bdbb62fSAlexandre Bounine ADD(alias, "v", vid != RIO_ANY_ID, vid); 12473bdbb62fSAlexandre Bounine ADD(alias, "d", did != RIO_ANY_ID, did); 12483bdbb62fSAlexandre Bounine ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid); 12493bdbb62fSAlexandre Bounine ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did); 12503bdbb62fSAlexandre Bounine 12513bdbb62fSAlexandre Bounine add_wildcard(alias); 12523bdbb62fSAlexandre Bounine return 1; 12533bdbb62fSAlexandre Bounine } 12543bdbb62fSAlexandre Bounine 1255289fcff4SHeikki Krogerus /* Looks like: ulpi:vNpN */ 1256289fcff4SHeikki Krogerus static int do_ulpi_entry(const char *filename, void *symval, 1257289fcff4SHeikki Krogerus char *alias) 1258289fcff4SHeikki Krogerus { 1259289fcff4SHeikki Krogerus DEF_FIELD(symval, ulpi_device_id, vendor); 1260289fcff4SHeikki Krogerus DEF_FIELD(symval, ulpi_device_id, product); 1261289fcff4SHeikki Krogerus 1262289fcff4SHeikki Krogerus sprintf(alias, "ulpi:v%04xp%04x", vendor, product); 1263289fcff4SHeikki Krogerus 1264289fcff4SHeikki Krogerus return 1; 1265289fcff4SHeikki Krogerus } 1266289fcff4SHeikki Krogerus 1267da23ac1eSSubhransu S. Prusty /* Looks like: hdaudio:vNrNaN */ 1268da23ac1eSSubhransu S. Prusty static int do_hda_entry(const char *filename, void *symval, char *alias) 1269da23ac1eSSubhransu S. Prusty { 1270da23ac1eSSubhransu S. Prusty DEF_FIELD(symval, hda_device_id, vendor_id); 1271da23ac1eSSubhransu S. Prusty DEF_FIELD(symval, hda_device_id, rev_id); 1272da23ac1eSSubhransu S. Prusty DEF_FIELD(symval, hda_device_id, api_version); 1273da23ac1eSSubhransu S. Prusty 1274da23ac1eSSubhransu S. Prusty strcpy(alias, "hdaudio:"); 1275da23ac1eSSubhransu S. Prusty ADD(alias, "v", vendor_id != 0, vendor_id); 1276da23ac1eSSubhransu S. Prusty ADD(alias, "r", rev_id != 0, rev_id); 1277da23ac1eSSubhransu S. Prusty ADD(alias, "a", api_version != 0, api_version); 1278da23ac1eSSubhransu S. Prusty 1279da23ac1eSSubhransu S. Prusty add_wildcard(alias); 1280da23ac1eSSubhransu S. Prusty return 1; 1281da23ac1eSSubhransu S. Prusty } 1282da23ac1eSSubhransu S. Prusty 1283b5924268SPierre-Louis Bossart /* Looks like: sdw:mNpNvNcN */ 12849251345dSVinod Koul static int do_sdw_entry(const char *filename, void *symval, char *alias) 12859251345dSVinod Koul { 12869251345dSVinod Koul DEF_FIELD(symval, sdw_device_id, mfg_id); 12879251345dSVinod Koul DEF_FIELD(symval, sdw_device_id, part_id); 1288b5924268SPierre-Louis Bossart DEF_FIELD(symval, sdw_device_id, sdw_version); 1289b5924268SPierre-Louis Bossart DEF_FIELD(symval, sdw_device_id, class_id); 12909251345dSVinod Koul 12919251345dSVinod Koul strcpy(alias, "sdw:"); 12929251345dSVinod Koul ADD(alias, "m", mfg_id != 0, mfg_id); 12939251345dSVinod Koul ADD(alias, "p", part_id != 0, part_id); 1294b5924268SPierre-Louis Bossart ADD(alias, "v", sdw_version != 0, sdw_version); 1295b5924268SPierre-Louis Bossart ADD(alias, "c", class_id != 0, class_id); 12969251345dSVinod Koul 12979251345dSVinod Koul add_wildcard(alias); 12989251345dSVinod Koul return 1; 12999251345dSVinod Koul } 13009251345dSVinod Koul 13010afef456SStuart Yoder /* Looks like: fsl-mc:vNdN */ 13020afef456SStuart Yoder static int do_fsl_mc_entry(const char *filename, void *symval, 13030afef456SStuart Yoder char *alias) 13040afef456SStuart Yoder { 13050afef456SStuart Yoder DEF_FIELD(symval, fsl_mc_device_id, vendor); 13060afef456SStuart Yoder DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type); 13070afef456SStuart Yoder 13080afef456SStuart Yoder sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type); 13090afef456SStuart Yoder return 1; 13100afef456SStuart Yoder } 13110afef456SStuart Yoder 1312d1ff7024SMika Westerberg /* Looks like: tbsvc:kSpNvNrN */ 1313d1ff7024SMika Westerberg static int do_tbsvc_entry(const char *filename, void *symval, char *alias) 1314d1ff7024SMika Westerberg { 1315d1ff7024SMika Westerberg DEF_FIELD(symval, tb_service_id, match_flags); 1316d1ff7024SMika Westerberg DEF_FIELD_ADDR(symval, tb_service_id, protocol_key); 1317d1ff7024SMika Westerberg DEF_FIELD(symval, tb_service_id, protocol_id); 1318d1ff7024SMika Westerberg DEF_FIELD(symval, tb_service_id, protocol_version); 1319d1ff7024SMika Westerberg DEF_FIELD(symval, tb_service_id, protocol_revision); 1320d1ff7024SMika Westerberg 1321d1ff7024SMika Westerberg strcpy(alias, "tbsvc:"); 1322d1ff7024SMika Westerberg if (match_flags & TBSVC_MATCH_PROTOCOL_KEY) 1323d1ff7024SMika Westerberg sprintf(alias + strlen(alias), "k%s", *protocol_key); 1324d1ff7024SMika Westerberg else 1325d1ff7024SMika Westerberg strcat(alias + strlen(alias), "k*"); 1326d1ff7024SMika Westerberg ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id); 1327d1ff7024SMika Westerberg ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION, 1328d1ff7024SMika Westerberg protocol_version); 1329d1ff7024SMika Westerberg ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION, 1330d1ff7024SMika Westerberg protocol_revision); 1331d1ff7024SMika Westerberg 1332d1ff7024SMika Westerberg add_wildcard(alias); 1333d1ff7024SMika Westerberg return 1; 1334d1ff7024SMika Westerberg } 1335d1ff7024SMika Westerberg 13368a37d87dSHeikki Krogerus /* Looks like: typec:idNmN */ 13378a37d87dSHeikki Krogerus static int do_typec_entry(const char *filename, void *symval, char *alias) 13388a37d87dSHeikki Krogerus { 13398a37d87dSHeikki Krogerus DEF_FIELD(symval, typec_device_id, svid); 13408a37d87dSHeikki Krogerus DEF_FIELD(symval, typec_device_id, mode); 13418a37d87dSHeikki Krogerus 13428a37d87dSHeikki Krogerus sprintf(alias, "typec:id%04X", svid); 13438a37d87dSHeikki Krogerus ADD(alias, "m", mode != TYPEC_ANY_MODE, mode); 13448a37d87dSHeikki Krogerus 13458a37d87dSHeikki Krogerus return 1; 13468a37d87dSHeikki Krogerus } 13478a37d87dSHeikki Krogerus 13480fc1db9dSSumit Garg /* Looks like: tee:uuid */ 13490fc1db9dSSumit Garg static int do_tee_entry(const char *filename, void *symval, char *alias) 13500fc1db9dSSumit Garg { 13510fc1db9dSSumit Garg DEF_FIELD(symval, tee_client_device_id, uuid); 13520fc1db9dSSumit Garg 13530fc1db9dSSumit Garg sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 13540fc1db9dSSumit Garg uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4], 13550fc1db9dSSumit Garg uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9], 13560fc1db9dSSumit Garg uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14], 13570fc1db9dSSumit Garg uuid.b[15]); 13580fc1db9dSSumit Garg 13590fc1db9dSSumit Garg add_wildcard(alias); 13600fc1db9dSSumit Garg return 1; 13610fc1db9dSSumit Garg } 13620fc1db9dSSumit Garg 13630bc44b2bSMattias Jacobsson /* Looks like: wmi:guid */ 13640bc44b2bSMattias Jacobsson static int do_wmi_entry(const char *filename, void *symval, char *alias) 13650bc44b2bSMattias Jacobsson { 13660bc44b2bSMattias Jacobsson int len; 13670bc44b2bSMattias Jacobsson DEF_FIELD_ADDR(symval, wmi_device_id, guid_string); 13680bc44b2bSMattias Jacobsson 13690bc44b2bSMattias Jacobsson if (strlen(*guid_string) != UUID_STRING_LEN) { 13700bc44b2bSMattias Jacobsson warn("Invalid WMI device id 'wmi:%s' in '%s'\n", 13710bc44b2bSMattias Jacobsson *guid_string, filename); 13720bc44b2bSMattias Jacobsson return 0; 13730bc44b2bSMattias Jacobsson } 13740bc44b2bSMattias Jacobsson 13750bc44b2bSMattias Jacobsson len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string); 13760bc44b2bSMattias Jacobsson if (len < 0 || len >= ALIAS_SIZE) { 13770bc44b2bSMattias Jacobsson warn("Could not generate all MODULE_ALIAS's in '%s'\n", 13780bc44b2bSMattias Jacobsson filename); 13790bc44b2bSMattias Jacobsson return 0; 13800bc44b2bSMattias Jacobsson } 13810bc44b2bSMattias Jacobsson return 1; 13820bc44b2bSMattias Jacobsson } 13830bc44b2bSMattias Jacobsson 1384e6b0de46SManivannan Sadhasivam /* Looks like: mhi:S */ 1385e6b0de46SManivannan Sadhasivam static int do_mhi_entry(const char *filename, void *symval, char *alias) 1386e6b0de46SManivannan Sadhasivam { 1387e6b0de46SManivannan Sadhasivam DEF_FIELD_ADDR(symval, mhi_device_id, chan); 1388e6b0de46SManivannan Sadhasivam sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan); 13897de3697eSDave Ertman return 1; 13907de3697eSDave Ertman } 13917de3697eSDave Ertman 1392c268c0a8SManivannan Sadhasivam /* Looks like: mhi_ep:S */ 1393c268c0a8SManivannan Sadhasivam static int do_mhi_ep_entry(const char *filename, void *symval, char *alias) 1394c268c0a8SManivannan Sadhasivam { 1395c268c0a8SManivannan Sadhasivam DEF_FIELD_ADDR(symval, mhi_device_id, chan); 1396c268c0a8SManivannan Sadhasivam sprintf(alias, MHI_EP_DEVICE_MODALIAS_FMT, *chan); 1397c268c0a8SManivannan Sadhasivam 1398c268c0a8SManivannan Sadhasivam return 1; 1399c268c0a8SManivannan Sadhasivam } 1400c268c0a8SManivannan Sadhasivam 1401fa443bc3SThomas Weißschuh /* Looks like: ishtp:{guid} */ 1402fa443bc3SThomas Weißschuh static int do_ishtp_entry(const char *filename, void *symval, char *alias) 1403fa443bc3SThomas Weißschuh { 1404fa443bc3SThomas Weißschuh DEF_FIELD(symval, ishtp_device_id, guid); 1405fa443bc3SThomas Weißschuh 1406fa443bc3SThomas Weißschuh strcpy(alias, ISHTP_MODULE_PREFIX "{"); 1407fa443bc3SThomas Weißschuh add_guid(alias, guid); 1408fa443bc3SThomas Weißschuh strcat(alias, "}"); 1409fa443bc3SThomas Weißschuh 1410fa443bc3SThomas Weißschuh return 1; 1411fa443bc3SThomas Weißschuh } 1412fa443bc3SThomas Weißschuh 14137de3697eSDave Ertman static int do_auxiliary_entry(const char *filename, void *symval, char *alias) 14147de3697eSDave Ertman { 14157de3697eSDave Ertman DEF_FIELD_ADDR(symval, auxiliary_device_id, name); 14167de3697eSDave Ertman sprintf(alias, AUXILIARY_MODULE_PREFIX "%s", *name); 1417e6b0de46SManivannan Sadhasivam 1418e6b0de46SManivannan Sadhasivam return 1; 1419e6b0de46SManivannan Sadhasivam } 1420e6b0de46SManivannan Sadhasivam 1421eb0e90a8SMaximilian Luz /* 1422eb0e90a8SMaximilian Luz * Looks like: ssam:dNcNtNiNfN 1423eb0e90a8SMaximilian Luz * 1424eb0e90a8SMaximilian Luz * N is exactly 2 digits, where each is an upper-case hex digit. 1425eb0e90a8SMaximilian Luz */ 1426eb0e90a8SMaximilian Luz static int do_ssam_entry(const char *filename, void *symval, char *alias) 1427eb0e90a8SMaximilian Luz { 1428eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, match_flags); 1429eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, domain); 1430eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, category); 1431eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, target); 1432eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, instance); 1433eb0e90a8SMaximilian Luz DEF_FIELD(symval, ssam_device_id, function); 1434eb0e90a8SMaximilian Luz 1435eb0e90a8SMaximilian Luz sprintf(alias, "ssam:d%02Xc%02X", domain, category); 1436eb0e90a8SMaximilian Luz ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target); 1437eb0e90a8SMaximilian Luz ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance); 1438eb0e90a8SMaximilian Luz ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function); 1439eb0e90a8SMaximilian Luz 1440eb0e90a8SMaximilian Luz return 1; 1441eb0e90a8SMaximilian Luz } 1442eb0e90a8SMaximilian Luz 14434a224aceSXu Yilun /* Looks like: dfl:tNfN */ 14444a224aceSXu Yilun static int do_dfl_entry(const char *filename, void *symval, char *alias) 14454a224aceSXu Yilun { 14464a224aceSXu Yilun DEF_FIELD(symval, dfl_device_id, type); 14474a224aceSXu Yilun DEF_FIELD(symval, dfl_device_id, feature_id); 14484a224aceSXu Yilun 14494a224aceSXu Yilun sprintf(alias, "dfl:t%04Xf%04X", type, feature_id); 14504a224aceSXu Yilun 14514a224aceSXu Yilun add_wildcard(alias); 14524a224aceSXu Yilun return 1; 14534a224aceSXu Yilun } 14544a224aceSXu Yilun 14552959ab24SNipun Gupta /* Looks like: cdx:vNdN */ 14562959ab24SNipun Gupta static int do_cdx_entry(const char *filename, void *symval, 14572959ab24SNipun Gupta char *alias) 14582959ab24SNipun Gupta { 14592959ab24SNipun Gupta DEF_FIELD(symval, cdx_device_id, vendor); 14602959ab24SNipun Gupta DEF_FIELD(symval, cdx_device_id, device); 1461234489acSNipun Gupta DEF_FIELD(symval, cdx_device_id, override_only); 14622959ab24SNipun Gupta 1463234489acSNipun Gupta switch (override_only) { 1464234489acSNipun Gupta case 0: 1465234489acSNipun Gupta strcpy(alias, "cdx:"); 1466234489acSNipun Gupta break; 1467234489acSNipun Gupta case CDX_ID_F_VFIO_DRIVER_OVERRIDE: 1468234489acSNipun Gupta strcpy(alias, "vfio_cdx:"); 1469234489acSNipun Gupta break; 1470234489acSNipun Gupta default: 1471234489acSNipun Gupta warn("Unknown CDX driver_override alias %08X\n", 1472234489acSNipun Gupta override_only); 1473234489acSNipun Gupta return 0; 1474234489acSNipun Gupta } 1475234489acSNipun Gupta 1476234489acSNipun Gupta ADD(alias, "v", vendor != CDX_ANY_ID, vendor); 1477234489acSNipun Gupta ADD(alias, "d", device != CDX_ANY_ID, device); 14782959ab24SNipun Gupta return 1; 14792959ab24SNipun Gupta } 14802959ab24SNipun Gupta 1481*1fa05877SUmang Jain static int do_vchiq_entry(const char *filename, void *symval, char *alias) 1482*1fa05877SUmang Jain { 1483*1fa05877SUmang Jain DEF_FIELD_ADDR(symval, vchiq_device_id, name); 1484*1fa05877SUmang Jain sprintf(alias, "vchiq:%s", *name); 1485*1fa05877SUmang Jain 1486*1fa05877SUmang Jain return 1; 1487*1fa05877SUmang Jain } 1488*1fa05877SUmang Jain 1489626596e2SRusty Russell /* Does namelen bytes of name exactly match the symbol? */ 1490626596e2SRusty Russell static bool sym_is(const char *name, unsigned namelen, const char *symbol) 14911da177e4SLinus Torvalds { 1492626596e2SRusty Russell if (namelen != strlen(symbol)) 1493626596e2SRusty Russell return false; 14941da177e4SLinus Torvalds 1495626596e2SRusty Russell return memcmp(name, symbol, namelen) == 0; 14961da177e4SLinus Torvalds } 14971da177e4SLinus Torvalds 14981da177e4SLinus Torvalds static void do_table(void *symval, unsigned long size, 14991da177e4SLinus Torvalds unsigned long id_size, 1500fb33d816SSam Ravnborg const char *device_id, 1501f880eea6SMasahiro Yamada int (*do_entry)(const char *filename, void *symval, char *alias), 15021da177e4SLinus Torvalds struct module *mod) 15031da177e4SLinus Torvalds { 15041da177e4SLinus Torvalds unsigned int i; 1505841f1b8fSMattias Jacobsson char alias[ALIAS_SIZE]; 15061da177e4SLinus Torvalds 1507e0049825SKees Cook device_id_check(mod->name, device_id, size, id_size, symval); 15081da177e4SLinus Torvalds /* Leave last one: it's the terminator. */ 15091da177e4SLinus Torvalds size -= id_size; 15101da177e4SLinus Torvalds 15111da177e4SLinus Torvalds for (i = 0; i < size; i += id_size) { 15121da177e4SLinus Torvalds if (do_entry(mod->name, symval+i, alias)) { 15131da177e4SLinus Torvalds buf_printf(&mod->dev_table_buf, 15141da177e4SLinus Torvalds "MODULE_ALIAS(\"%s\");\n", alias); 15151da177e4SLinus Torvalds } 15161da177e4SLinus Torvalds } 15171da177e4SLinus Torvalds } 15181da177e4SLinus Torvalds 1519ec91e78dSMasahiro Yamada static const struct devtable devtable[] = { 1520ec91e78dSMasahiro Yamada {"hid", SIZE_hid_device_id, do_hid_entry}, 1521ec91e78dSMasahiro Yamada {"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry}, 1522ec91e78dSMasahiro Yamada {"pci", SIZE_pci_device_id, do_pci_entry}, 1523ec91e78dSMasahiro Yamada {"ccw", SIZE_ccw_device_id, do_ccw_entry}, 1524ec91e78dSMasahiro Yamada {"ap", SIZE_ap_device_id, do_ap_entry}, 1525ec91e78dSMasahiro Yamada {"css", SIZE_css_device_id, do_css_entry}, 1526ec91e78dSMasahiro Yamada {"serio", SIZE_serio_device_id, do_serio_entry}, 1527ec91e78dSMasahiro Yamada {"acpi", SIZE_acpi_device_id, do_acpi_entry}, 1528ec91e78dSMasahiro Yamada {"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry}, 1529ec91e78dSMasahiro Yamada {"vio", SIZE_vio_device_id, do_vio_entry}, 1530ec91e78dSMasahiro Yamada {"input", SIZE_input_device_id, do_input_entry}, 1531ec91e78dSMasahiro Yamada {"eisa", SIZE_eisa_device_id, do_eisa_entry}, 1532ec91e78dSMasahiro Yamada {"parisc", SIZE_parisc_device_id, do_parisc_entry}, 1533ec91e78dSMasahiro Yamada {"sdio", SIZE_sdio_device_id, do_sdio_entry}, 1534ec91e78dSMasahiro Yamada {"ssb", SIZE_ssb_device_id, do_ssb_entry}, 1535ec91e78dSMasahiro Yamada {"bcma", SIZE_bcma_device_id, do_bcma_entry}, 1536ec91e78dSMasahiro Yamada {"virtio", SIZE_virtio_device_id, do_virtio_entry}, 1537ec91e78dSMasahiro Yamada {"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry}, 1538ec91e78dSMasahiro Yamada {"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry}, 1539ec91e78dSMasahiro Yamada {"i2c", SIZE_i2c_device_id, do_i2c_entry}, 15401ce589adSBoris Brezillon {"i3c", SIZE_i3c_device_id, do_i3c_entry}, 1541ec91e78dSMasahiro Yamada {"spi", SIZE_spi_device_id, do_spi_entry}, 1542ec91e78dSMasahiro Yamada {"dmi", SIZE_dmi_system_id, do_dmi_entry}, 1543ec91e78dSMasahiro Yamada {"platform", SIZE_platform_device_id, do_platform_entry}, 1544ec91e78dSMasahiro Yamada {"mdio", SIZE_mdio_device_id, do_mdio_entry}, 1545ec91e78dSMasahiro Yamada {"zorro", SIZE_zorro_device_id, do_zorro_entry}, 1546ec91e78dSMasahiro Yamada {"isapnp", SIZE_isapnp_device_id, do_isapnp_entry}, 1547ec91e78dSMasahiro Yamada {"ipack", SIZE_ipack_device_id, do_ipack_entry}, 1548ec91e78dSMasahiro Yamada {"amba", SIZE_amba_id, do_amba_entry}, 1549ec91e78dSMasahiro Yamada {"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry}, 1550ec91e78dSMasahiro Yamada {"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry}, 1551ec91e78dSMasahiro Yamada {"cpu", SIZE_cpu_feature, do_cpu_entry}, 1552ec91e78dSMasahiro Yamada {"mei", SIZE_mei_cl_device_id, do_mei_entry}, 1553ec91e78dSMasahiro Yamada {"rapidio", SIZE_rio_device_id, do_rio_entry}, 1554ec91e78dSMasahiro Yamada {"ulpi", SIZE_ulpi_device_id, do_ulpi_entry}, 1555ec91e78dSMasahiro Yamada {"hdaudio", SIZE_hda_device_id, do_hda_entry}, 1556ec91e78dSMasahiro Yamada {"sdw", SIZE_sdw_device_id, do_sdw_entry}, 1557ec91e78dSMasahiro Yamada {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry}, 1558ec91e78dSMasahiro Yamada {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry}, 1559ec91e78dSMasahiro Yamada {"typec", SIZE_typec_device_id, do_typec_entry}, 15600fc1db9dSSumit Garg {"tee", SIZE_tee_client_device_id, do_tee_entry}, 15610bc44b2bSMattias Jacobsson {"wmi", SIZE_wmi_device_id, do_wmi_entry}, 1562e6b0de46SManivannan Sadhasivam {"mhi", SIZE_mhi_device_id, do_mhi_entry}, 1563c268c0a8SManivannan Sadhasivam {"mhi_ep", SIZE_mhi_device_id, do_mhi_ep_entry}, 15647de3697eSDave Ertman {"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry}, 1565eb0e90a8SMaximilian Luz {"ssam", SIZE_ssam_device_id, do_ssam_entry}, 15664a224aceSXu Yilun {"dfl", SIZE_dfl_device_id, do_dfl_entry}, 1567fa443bc3SThomas Weißschuh {"ishtp", SIZE_ishtp_device_id, do_ishtp_entry}, 15682959ab24SNipun Gupta {"cdx", SIZE_cdx_device_id, do_cdx_entry}, 1569*1fa05877SUmang Jain {"vchiq", SIZE_vchiq_device_id, do_vchiq_entry}, 1570ec91e78dSMasahiro Yamada }; 1571ec91e78dSMasahiro Yamada 15721da177e4SLinus Torvalds /* Create MODULE_ALIAS() statements. 15731da177e4SLinus Torvalds * At this time, we cannot write the actual output C source yet, 15741da177e4SLinus Torvalds * so we write into the mod->dev_table_buf buffer. */ 15751da177e4SLinus Torvalds void handle_moddevtable(struct module *mod, struct elf_info *info, 15761da177e4SLinus Torvalds Elf_Sym *sym, const char *symname) 15771da177e4SLinus Torvalds { 15781da177e4SLinus Torvalds void *symval; 1579e0049825SKees Cook char *zeros = NULL; 158021bdd17bSTom Gundersen const char *name, *identifier; 1581626596e2SRusty Russell unsigned int namelen; 15821da177e4SLinus Torvalds 15831da177e4SLinus Torvalds /* We're looking for a section relative symbol */ 15841ce53adfSDenys Vlasenko if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) 15851da177e4SLinus Torvalds return; 15861da177e4SLinus Torvalds 1587e88aa7bbSDavid Miller /* We're looking for an object */ 1588e88aa7bbSDavid Miller if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) 1589e88aa7bbSDavid Miller return; 1590e88aa7bbSDavid Miller 1591153e04b3SMasahiro Yamada /* All our symbols are of form __mod_<name>__<identifier>_device_table. */ 1592153e04b3SMasahiro Yamada if (strncmp(symname, "__mod_", strlen("__mod_"))) 1593626596e2SRusty Russell return; 1594153e04b3SMasahiro Yamada name = symname + strlen("__mod_"); 1595626596e2SRusty Russell namelen = strlen(name); 1596626596e2SRusty Russell if (namelen < strlen("_device_table")) 1597626596e2SRusty Russell return; 1598626596e2SRusty Russell if (strcmp(name + namelen - strlen("_device_table"), "_device_table")) 1599626596e2SRusty Russell return; 160021bdd17bSTom Gundersen identifier = strstr(name, "__"); 160121bdd17bSTom Gundersen if (!identifier) 160221bdd17bSTom Gundersen return; 160321bdd17bSTom Gundersen namelen = identifier - name; 1604626596e2SRusty Russell 1605e0049825SKees Cook /* Handle all-NULL symbols allocated into .bss */ 16061ce53adfSDenys Vlasenko if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { 1607e0049825SKees Cook zeros = calloc(1, sym->st_size); 1608e0049825SKees Cook symval = zeros; 1609e0049825SKees Cook } else { 1610abe864b8SMasahiro Yamada symval = sym_get_data(info, sym); 1611e0049825SKees Cook } 16121da177e4SLinus Torvalds 1613626596e2SRusty Russell /* First handle the "special" cases */ 1614626596e2SRusty Russell if (sym_is(name, namelen, "usb")) 1615b19dcd93SRoman Kagan do_usb_table(symval, sym->st_size, mod); 1616acbef7b7SPhilipp Zabel if (sym_is(name, namelen, "of")) 1617acbef7b7SPhilipp Zabel do_of_table(symval, sym->st_size, mod); 1618626596e2SRusty Russell else if (sym_is(name, namelen, "pnp")) 161922454cb9SKay Sievers do_pnp_device_entry(symval, sym->st_size, mod); 1620626596e2SRusty Russell else if (sym_is(name, namelen, "pnp_card")) 16210c81eed4SKay Sievers do_pnp_card_entries(symval, sym->st_size, mod); 1622626596e2SRusty Russell else { 1623ec91e78dSMasahiro Yamada int i; 1624626596e2SRusty Russell 1625ec91e78dSMasahiro Yamada for (i = 0; i < ARRAY_SIZE(devtable); i++) { 1626ec91e78dSMasahiro Yamada const struct devtable *p = &devtable[i]; 1627ec91e78dSMasahiro Yamada 1628ec91e78dSMasahiro Yamada if (sym_is(name, namelen, p->device_id)) { 1629ec91e78dSMasahiro Yamada do_table(symval, sym->st_size, p->id_size, 1630f880eea6SMasahiro Yamada p->device_id, p->do_entry, mod); 1631626596e2SRusty Russell break; 1632626596e2SRusty Russell } 1633626596e2SRusty Russell } 1634626596e2SRusty Russell } 1635e0049825SKees Cook free(zeros); 16361da177e4SLinus Torvalds } 16371da177e4SLinus Torvalds 16381da177e4SLinus Torvalds /* Now add out buffered information to the generated C source */ 16391da177e4SLinus Torvalds void add_moddevtable(struct buffer *buf, struct module *mod) 16401da177e4SLinus Torvalds { 16411da177e4SLinus Torvalds buf_printf(buf, "\n"); 16421da177e4SLinus Torvalds buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos); 16431da177e4SLinus Torvalds free(mod->dev_table_buf.p); 16441da177e4SLinus Torvalds } 1645