18c2ecf20Sopenharmony_ci/* Simple code to turn various tables in an ELF file into alias definitions. 28c2ecf20Sopenharmony_ci * This deals with kernel datastructures where they should be 38c2ecf20Sopenharmony_ci * dealt with: in the kernel source. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2002-2003 Rusty Russell, IBM Corporation 68c2ecf20Sopenharmony_ci * 2003 Kai Germaschewski 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This software may be used and distributed according to the terms 108c2ecf20Sopenharmony_ci * of the GNU General Public License, incorporated herein by reference. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include "modpost.h" 148c2ecf20Sopenharmony_ci#include "devicetable-offsets.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* We use the ELF typedefs for kernel_ulong_t but bite the bullet and 178c2ecf20Sopenharmony_ci * use either stdint.h or inttypes.h for the rest. */ 188c2ecf20Sopenharmony_ci#if KERNEL_ELFCLASS == ELFCLASS32 198c2ecf20Sopenharmony_citypedef Elf32_Addr kernel_ulong_t; 208c2ecf20Sopenharmony_ci#define BITS_PER_LONG 32 218c2ecf20Sopenharmony_ci#else 228c2ecf20Sopenharmony_citypedef Elf64_Addr kernel_ulong_t; 238c2ecf20Sopenharmony_ci#define BITS_PER_LONG 64 248c2ecf20Sopenharmony_ci#endif 258c2ecf20Sopenharmony_ci#ifdef __sun__ 268c2ecf20Sopenharmony_ci#include <inttypes.h> 278c2ecf20Sopenharmony_ci#else 288c2ecf20Sopenharmony_ci#include <stdint.h> 298c2ecf20Sopenharmony_ci#endif 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#include <ctype.h> 328c2ecf20Sopenharmony_ci#include <stdbool.h> 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_citypedef uint32_t __u32; 358c2ecf20Sopenharmony_citypedef uint16_t __u16; 368c2ecf20Sopenharmony_citypedef unsigned char __u8; 378c2ecf20Sopenharmony_citypedef struct { 388c2ecf20Sopenharmony_ci __u8 b[16]; 398c2ecf20Sopenharmony_ci} guid_t; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* backwards compatibility, don't use in new code */ 428c2ecf20Sopenharmony_citypedef struct { 438c2ecf20Sopenharmony_ci __u8 b[16]; 448c2ecf20Sopenharmony_ci} uuid_le; 458c2ecf20Sopenharmony_citypedef struct { 468c2ecf20Sopenharmony_ci __u8 b[16]; 478c2ecf20Sopenharmony_ci} uuid_t; 488c2ecf20Sopenharmony_ci#define UUID_STRING_LEN 36 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci/* Big exception to the "don't include kernel headers into userspace, which 518c2ecf20Sopenharmony_ci * even potentially has different endianness and word sizes, since 528c2ecf20Sopenharmony_ci * we handle those differences explicitly below */ 538c2ecf20Sopenharmony_ci#include "../../include/linux/mod_devicetable.h" 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* This array collects all instances that use the generic do_table */ 568c2ecf20Sopenharmony_cistruct devtable { 578c2ecf20Sopenharmony_ci const char *device_id; /* name of table, __mod_<name>__*_device_table. */ 588c2ecf20Sopenharmony_ci unsigned long id_size; 598c2ecf20Sopenharmony_ci int (*do_entry)(const char *filename, void *symval, char *alias); 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci/* Size of alias provided to do_entry functions */ 638c2ecf20Sopenharmony_ci#define ALIAS_SIZE 500 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci/* Define a variable f that holds the value of field f of struct devid 668c2ecf20Sopenharmony_ci * based at address m. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_ci#define DEF_FIELD(m, devid, f) \ 698c2ecf20Sopenharmony_ci typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f)) 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/* Define a variable v that holds the address of field f of struct devid 728c2ecf20Sopenharmony_ci * based at address m. Due to the way typeof works, for a field of type 738c2ecf20Sopenharmony_ci * T[N] the variable has type T(*)[N], _not_ T*. 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_ci#define DEF_FIELD_ADDR_VAR(m, devid, f, v) \ 768c2ecf20Sopenharmony_ci typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f) 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* Define a variable f that holds the address of field f of struct devid 798c2ecf20Sopenharmony_ci * based at address m. Due to the way typeof works, for a field of type 808c2ecf20Sopenharmony_ci * T[N] the variable has type T(*)[N], _not_ T*. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci#define DEF_FIELD_ADDR(m, devid, f) \ 838c2ecf20Sopenharmony_ci DEF_FIELD_ADDR_VAR(m, devid, f, f) 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci#define ADD(str, sep, cond, field) \ 868c2ecf20Sopenharmony_cido { \ 878c2ecf20Sopenharmony_ci strcat(str, sep); \ 888c2ecf20Sopenharmony_ci if (cond) \ 898c2ecf20Sopenharmony_ci sprintf(str + strlen(str), \ 908c2ecf20Sopenharmony_ci sizeof(field) == 1 ? "%02X" : \ 918c2ecf20Sopenharmony_ci sizeof(field) == 2 ? "%04X" : \ 928c2ecf20Sopenharmony_ci sizeof(field) == 4 ? "%08X" : "", \ 938c2ecf20Sopenharmony_ci field); \ 948c2ecf20Sopenharmony_ci else \ 958c2ecf20Sopenharmony_ci sprintf(str + strlen(str), "*"); \ 968c2ecf20Sopenharmony_ci} while(0) 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/* End in a wildcard, for future extension */ 998c2ecf20Sopenharmony_cistatic inline void add_wildcard(char *str) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci int len = strlen(str); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (str[len - 1] != '*') 1048c2ecf20Sopenharmony_ci strcat(str + len, "*"); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic inline void add_uuid(char *str, uuid_le uuid) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci int len = strlen(str); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 1128c2ecf20Sopenharmony_ci uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0], 1138c2ecf20Sopenharmony_ci uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6], 1148c2ecf20Sopenharmony_ci uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11], 1158c2ecf20Sopenharmony_ci uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci/** 1198c2ecf20Sopenharmony_ci * Check that sizeof(device_id type) are consistent with size of section 1208c2ecf20Sopenharmony_ci * in .o file. If in-consistent then userspace and kernel does not agree 1218c2ecf20Sopenharmony_ci * on actual size which is a bug. 1228c2ecf20Sopenharmony_ci * Also verify that the final entry in the table is all zeros. 1238c2ecf20Sopenharmony_ci * Ignore both checks if build host differ from target host and size differs. 1248c2ecf20Sopenharmony_ci **/ 1258c2ecf20Sopenharmony_cistatic void device_id_check(const char *modname, const char *device_id, 1268c2ecf20Sopenharmony_ci unsigned long size, unsigned long id_size, 1278c2ecf20Sopenharmony_ci void *symval) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci int i; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (size % id_size || size < id_size) { 1328c2ecf20Sopenharmony_ci fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo " 1338c2ecf20Sopenharmony_ci "of the size of " 1348c2ecf20Sopenharmony_ci "section __mod_%s__<identifier>_device_table=%lu.\n" 1358c2ecf20Sopenharmony_ci "Fix definition of struct %s_device_id " 1368c2ecf20Sopenharmony_ci "in mod_devicetable.h\n", 1378c2ecf20Sopenharmony_ci modname, device_id, id_size, device_id, size, device_id); 1388c2ecf20Sopenharmony_ci } 1398c2ecf20Sopenharmony_ci /* Verify last one is a terminator */ 1408c2ecf20Sopenharmony_ci for (i = 0; i < id_size; i++ ) { 1418c2ecf20Sopenharmony_ci if (*(uint8_t*)(symval+size-id_size+i)) { 1428c2ecf20Sopenharmony_ci fprintf(stderr,"%s: struct %s_device_id is %lu bytes. " 1438c2ecf20Sopenharmony_ci "The last of %lu is:\n", 1448c2ecf20Sopenharmony_ci modname, device_id, id_size, size / id_size); 1458c2ecf20Sopenharmony_ci for (i = 0; i < id_size; i++ ) 1468c2ecf20Sopenharmony_ci fprintf(stderr,"0x%02x ", 1478c2ecf20Sopenharmony_ci *(uint8_t*)(symval+size-id_size+i) ); 1488c2ecf20Sopenharmony_ci fprintf(stderr,"\n"); 1498c2ecf20Sopenharmony_ci fatal("%s: struct %s_device_id is not terminated " 1508c2ecf20Sopenharmony_ci "with a NULL entry!\n", modname, device_id); 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci/* USB is special because the bcdDevice can be matched against a numeric range */ 1568c2ecf20Sopenharmony_ci/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */ 1578c2ecf20Sopenharmony_cistatic void do_usb_entry(void *symval, 1588c2ecf20Sopenharmony_ci unsigned int bcdDevice_initial, int bcdDevice_initial_digits, 1598c2ecf20Sopenharmony_ci unsigned char range_lo, unsigned char range_hi, 1608c2ecf20Sopenharmony_ci unsigned char max, struct module *mod) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci char alias[500]; 1638c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, match_flags); 1648c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, idVendor); 1658c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, idProduct); 1668c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bcdDevice_lo); 1678c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bDeviceClass); 1688c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bDeviceSubClass); 1698c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bDeviceProtocol); 1708c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceClass); 1718c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceSubClass); 1728c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceProtocol); 1738c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceNumber); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci strcpy(alias, "usb:"); 1768c2ecf20Sopenharmony_ci ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR, 1778c2ecf20Sopenharmony_ci idVendor); 1788c2ecf20Sopenharmony_ci ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT, 1798c2ecf20Sopenharmony_ci idProduct); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci strcat(alias, "d"); 1828c2ecf20Sopenharmony_ci if (bcdDevice_initial_digits) 1838c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "%0*X", 1848c2ecf20Sopenharmony_ci bcdDevice_initial_digits, bcdDevice_initial); 1858c2ecf20Sopenharmony_ci if (range_lo == range_hi) 1868c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "%X", range_lo); 1878c2ecf20Sopenharmony_ci else if (range_lo > 0 || range_hi < max) { 1888c2ecf20Sopenharmony_ci if (range_lo > 0x9 || range_hi < 0xA) 1898c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), 1908c2ecf20Sopenharmony_ci "[%X-%X]", 1918c2ecf20Sopenharmony_ci range_lo, 1928c2ecf20Sopenharmony_ci range_hi); 1938c2ecf20Sopenharmony_ci else { 1948c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), 1958c2ecf20Sopenharmony_ci range_lo < 0x9 ? "[%X-9" : "[%X", 1968c2ecf20Sopenharmony_ci range_lo); 1978c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), 1988c2ecf20Sopenharmony_ci range_hi > 0xA ? "A-%X]" : "%X]", 1998c2ecf20Sopenharmony_ci range_hi); 2008c2ecf20Sopenharmony_ci } 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1)) 2038c2ecf20Sopenharmony_ci strcat(alias, "*"); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, 2068c2ecf20Sopenharmony_ci bDeviceClass); 2078c2ecf20Sopenharmony_ci ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS, 2088c2ecf20Sopenharmony_ci bDeviceSubClass); 2098c2ecf20Sopenharmony_ci ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL, 2108c2ecf20Sopenharmony_ci bDeviceProtocol); 2118c2ecf20Sopenharmony_ci ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS, 2128c2ecf20Sopenharmony_ci bInterfaceClass); 2138c2ecf20Sopenharmony_ci ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS, 2148c2ecf20Sopenharmony_ci bInterfaceSubClass); 2158c2ecf20Sopenharmony_ci ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, 2168c2ecf20Sopenharmony_ci bInterfaceProtocol); 2178c2ecf20Sopenharmony_ci ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER, 2188c2ecf20Sopenharmony_ci bInterfaceNumber); 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci add_wildcard(alias); 2218c2ecf20Sopenharmony_ci buf_printf(&mod->dev_table_buf, 2228c2ecf20Sopenharmony_ci "MODULE_ALIAS(\"%s\");\n", alias); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/* Handles increment/decrement of BCD formatted integers */ 2268c2ecf20Sopenharmony_ci/* Returns the previous value, so it works like i++ or i-- */ 2278c2ecf20Sopenharmony_cistatic unsigned int incbcd(unsigned int *bcd, 2288c2ecf20Sopenharmony_ci int inc, 2298c2ecf20Sopenharmony_ci unsigned char max, 2308c2ecf20Sopenharmony_ci size_t chars) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci unsigned int init = *bcd, i, j; 2338c2ecf20Sopenharmony_ci unsigned long long c, dec = 0; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci /* If bcd is not in BCD format, just increment */ 2368c2ecf20Sopenharmony_ci if (max > 0x9) { 2378c2ecf20Sopenharmony_ci *bcd += inc; 2388c2ecf20Sopenharmony_ci return init; 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* Convert BCD to Decimal */ 2428c2ecf20Sopenharmony_ci for (i=0 ; i < chars ; i++) { 2438c2ecf20Sopenharmony_ci c = (*bcd >> (i << 2)) & 0xf; 2448c2ecf20Sopenharmony_ci c = c > 9 ? 9 : c; /* force to bcd just in case */ 2458c2ecf20Sopenharmony_ci for (j=0 ; j < i ; j++) 2468c2ecf20Sopenharmony_ci c = c * 10; 2478c2ecf20Sopenharmony_ci dec += c; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Do our increment/decrement */ 2518c2ecf20Sopenharmony_ci dec += inc; 2528c2ecf20Sopenharmony_ci *bcd = 0; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* Convert back to BCD */ 2558c2ecf20Sopenharmony_ci for (i=0 ; i < chars ; i++) { 2568c2ecf20Sopenharmony_ci for (c=1,j=0 ; j < i ; j++) 2578c2ecf20Sopenharmony_ci c = c * 10; 2588c2ecf20Sopenharmony_ci c = (dec / c) % 10; 2598c2ecf20Sopenharmony_ci *bcd += c << (i << 2); 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci return init; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic void do_usb_entry_multi(void *symval, struct module *mod) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci unsigned int devlo, devhi; 2678c2ecf20Sopenharmony_ci unsigned char chi, clo, max; 2688c2ecf20Sopenharmony_ci int ndigits; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, match_flags); 2718c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, idVendor); 2728c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, idProduct); 2738c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bcdDevice_lo); 2748c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bcdDevice_hi); 2758c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bDeviceClass); 2768c2ecf20Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceClass); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ? 2798c2ecf20Sopenharmony_ci bcdDevice_lo : 0x0U; 2808c2ecf20Sopenharmony_ci devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? 2818c2ecf20Sopenharmony_ci bcdDevice_hi : ~0x0U; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci /* Figure out if this entry is in bcd or hex format */ 2848c2ecf20Sopenharmony_ci max = 0x9; /* Default to decimal format */ 2858c2ecf20Sopenharmony_ci for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) { 2868c2ecf20Sopenharmony_ci clo = (devlo >> (ndigits << 2)) & 0xf; 2878c2ecf20Sopenharmony_ci chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf; 2888c2ecf20Sopenharmony_ci if (clo > max || chi > max) { 2898c2ecf20Sopenharmony_ci max = 0xf; 2908c2ecf20Sopenharmony_ci break; 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci /* 2958c2ecf20Sopenharmony_ci * Some modules (visor) have empty slots as placeholder for 2968c2ecf20Sopenharmony_ci * run-time specification that results in catch-all alias 2978c2ecf20Sopenharmony_ci */ 2988c2ecf20Sopenharmony_ci if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass)) 2998c2ecf20Sopenharmony_ci return; 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */ 3028c2ecf20Sopenharmony_ci for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { 3038c2ecf20Sopenharmony_ci clo = devlo & 0xf; 3048c2ecf20Sopenharmony_ci chi = devhi & 0xf; 3058c2ecf20Sopenharmony_ci if (chi > max) /* If we are in bcd mode, truncate if necessary */ 3068c2ecf20Sopenharmony_ci chi = max; 3078c2ecf20Sopenharmony_ci devlo >>= 4; 3088c2ecf20Sopenharmony_ci devhi >>= 4; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci if (devlo == devhi || !ndigits) { 3118c2ecf20Sopenharmony_ci do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod); 3128c2ecf20Sopenharmony_ci break; 3138c2ecf20Sopenharmony_ci } 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (clo > 0x0) 3168c2ecf20Sopenharmony_ci do_usb_entry(symval, 3178c2ecf20Sopenharmony_ci incbcd(&devlo, 1, max, 3188c2ecf20Sopenharmony_ci sizeof(bcdDevice_lo) * 2), 3198c2ecf20Sopenharmony_ci ndigits, clo, max, max, mod); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci if (chi < max) 3228c2ecf20Sopenharmony_ci do_usb_entry(symval, 3238c2ecf20Sopenharmony_ci incbcd(&devhi, -1, max, 3248c2ecf20Sopenharmony_ci sizeof(bcdDevice_lo) * 2), 3258c2ecf20Sopenharmony_ci ndigits, 0x0, chi, max, mod); 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic void do_usb_table(void *symval, unsigned long size, 3308c2ecf20Sopenharmony_ci struct module *mod) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci unsigned int i; 3338c2ecf20Sopenharmony_ci const unsigned long id_size = SIZE_usb_device_id; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci device_id_check(mod->name, "usb", size, id_size, symval); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci /* Leave last one: it's the terminator. */ 3388c2ecf20Sopenharmony_ci size -= id_size; 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci for (i = 0; i < size; i += id_size) 3418c2ecf20Sopenharmony_ci do_usb_entry_multi(symval + i, mod); 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistatic void do_of_entry_multi(void *symval, struct module *mod) 3458c2ecf20Sopenharmony_ci{ 3468c2ecf20Sopenharmony_ci char alias[500]; 3478c2ecf20Sopenharmony_ci int len; 3488c2ecf20Sopenharmony_ci char *tmp; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, of_device_id, name); 3518c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, of_device_id, type); 3528c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, of_device_id, compatible); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*", 3558c2ecf20Sopenharmony_ci (*type)[0] ? *type : "*"); 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if ((*compatible)[0]) 3588c2ecf20Sopenharmony_ci sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "", 3598c2ecf20Sopenharmony_ci *compatible); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci /* Replace all whitespace with underscores */ 3628c2ecf20Sopenharmony_ci for (tmp = alias; tmp && *tmp; tmp++) 3638c2ecf20Sopenharmony_ci if (isspace(*tmp)) 3648c2ecf20Sopenharmony_ci *tmp = '_'; 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias); 3678c2ecf20Sopenharmony_ci strcat(alias, "C"); 3688c2ecf20Sopenharmony_ci add_wildcard(alias); 3698c2ecf20Sopenharmony_ci buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias); 3708c2ecf20Sopenharmony_ci} 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic void do_of_table(void *symval, unsigned long size, 3738c2ecf20Sopenharmony_ci struct module *mod) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci unsigned int i; 3768c2ecf20Sopenharmony_ci const unsigned long id_size = SIZE_of_device_id; 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci device_id_check(mod->name, "of", size, id_size, symval); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci /* Leave last one: it's the terminator. */ 3818c2ecf20Sopenharmony_ci size -= id_size; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci for (i = 0; i < size; i += id_size) 3848c2ecf20Sopenharmony_ci do_of_entry_multi(symval + i, mod); 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci/* Looks like: hid:bNvNpN */ 3888c2ecf20Sopenharmony_cistatic int do_hid_entry(const char *filename, 3898c2ecf20Sopenharmony_ci void *symval, char *alias) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci DEF_FIELD(symval, hid_device_id, bus); 3928c2ecf20Sopenharmony_ci DEF_FIELD(symval, hid_device_id, group); 3938c2ecf20Sopenharmony_ci DEF_FIELD(symval, hid_device_id, vendor); 3948c2ecf20Sopenharmony_ci DEF_FIELD(symval, hid_device_id, product); 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci sprintf(alias, "hid:"); 3978c2ecf20Sopenharmony_ci ADD(alias, "b", bus != HID_BUS_ANY, bus); 3988c2ecf20Sopenharmony_ci ADD(alias, "g", group != HID_GROUP_ANY, group); 3998c2ecf20Sopenharmony_ci ADD(alias, "v", vendor != HID_ANY_ID, vendor); 4008c2ecf20Sopenharmony_ci ADD(alias, "p", product != HID_ANY_ID, product); 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci return 1; 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci/* Looks like: ieee1394:venNmoNspNverN */ 4068c2ecf20Sopenharmony_cistatic int do_ieee1394_entry(const char *filename, 4078c2ecf20Sopenharmony_ci void *symval, char *alias) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, match_flags); 4108c2ecf20Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, vendor_id); 4118c2ecf20Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, model_id); 4128c2ecf20Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, specifier_id); 4138c2ecf20Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, version); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci strcpy(alias, "ieee1394:"); 4168c2ecf20Sopenharmony_ci ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID, 4178c2ecf20Sopenharmony_ci vendor_id); 4188c2ecf20Sopenharmony_ci ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID, 4198c2ecf20Sopenharmony_ci model_id); 4208c2ecf20Sopenharmony_ci ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID, 4218c2ecf20Sopenharmony_ci specifier_id); 4228c2ecf20Sopenharmony_ci ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION, 4238c2ecf20Sopenharmony_ci version); 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci add_wildcard(alias); 4268c2ecf20Sopenharmony_ci return 1; 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci/* Looks like: pci:vNdNsvNsdNbcNscNiN. */ 4308c2ecf20Sopenharmony_cistatic int do_pci_entry(const char *filename, 4318c2ecf20Sopenharmony_ci void *symval, char *alias) 4328c2ecf20Sopenharmony_ci{ 4338c2ecf20Sopenharmony_ci /* Class field can be divided into these three. */ 4348c2ecf20Sopenharmony_ci unsigned char baseclass, subclass, interface, 4358c2ecf20Sopenharmony_ci baseclass_mask, subclass_mask, interface_mask; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci DEF_FIELD(symval, pci_device_id, vendor); 4388c2ecf20Sopenharmony_ci DEF_FIELD(symval, pci_device_id, device); 4398c2ecf20Sopenharmony_ci DEF_FIELD(symval, pci_device_id, subvendor); 4408c2ecf20Sopenharmony_ci DEF_FIELD(symval, pci_device_id, subdevice); 4418c2ecf20Sopenharmony_ci DEF_FIELD(symval, pci_device_id, class); 4428c2ecf20Sopenharmony_ci DEF_FIELD(symval, pci_device_id, class_mask); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci strcpy(alias, "pci:"); 4458c2ecf20Sopenharmony_ci ADD(alias, "v", vendor != PCI_ANY_ID, vendor); 4468c2ecf20Sopenharmony_ci ADD(alias, "d", device != PCI_ANY_ID, device); 4478c2ecf20Sopenharmony_ci ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor); 4488c2ecf20Sopenharmony_ci ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice); 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci baseclass = (class) >> 16; 4518c2ecf20Sopenharmony_ci baseclass_mask = (class_mask) >> 16; 4528c2ecf20Sopenharmony_ci subclass = (class) >> 8; 4538c2ecf20Sopenharmony_ci subclass_mask = (class_mask) >> 8; 4548c2ecf20Sopenharmony_ci interface = class; 4558c2ecf20Sopenharmony_ci interface_mask = class_mask; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci if ((baseclass_mask != 0 && baseclass_mask != 0xFF) 4588c2ecf20Sopenharmony_ci || (subclass_mask != 0 && subclass_mask != 0xFF) 4598c2ecf20Sopenharmony_ci || (interface_mask != 0 && interface_mask != 0xFF)) { 4608c2ecf20Sopenharmony_ci warn("Can't handle masks in %s:%04X\n", 4618c2ecf20Sopenharmony_ci filename, class_mask); 4628c2ecf20Sopenharmony_ci return 0; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci ADD(alias, "bc", baseclass_mask == 0xFF, baseclass); 4668c2ecf20Sopenharmony_ci ADD(alias, "sc", subclass_mask == 0xFF, subclass); 4678c2ecf20Sopenharmony_ci ADD(alias, "i", interface_mask == 0xFF, interface); 4688c2ecf20Sopenharmony_ci add_wildcard(alias); 4698c2ecf20Sopenharmony_ci return 1; 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci/* looks like: "ccw:tNmNdtNdmN" */ 4738c2ecf20Sopenharmony_cistatic int do_ccw_entry(const char *filename, 4748c2ecf20Sopenharmony_ci void *symval, char *alias) 4758c2ecf20Sopenharmony_ci{ 4768c2ecf20Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, match_flags); 4778c2ecf20Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, cu_type); 4788c2ecf20Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, cu_model); 4798c2ecf20Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, dev_type); 4808c2ecf20Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, dev_model); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci strcpy(alias, "ccw:"); 4838c2ecf20Sopenharmony_ci ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE, 4848c2ecf20Sopenharmony_ci cu_type); 4858c2ecf20Sopenharmony_ci ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL, 4868c2ecf20Sopenharmony_ci cu_model); 4878c2ecf20Sopenharmony_ci ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE, 4888c2ecf20Sopenharmony_ci dev_type); 4898c2ecf20Sopenharmony_ci ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL, 4908c2ecf20Sopenharmony_ci dev_model); 4918c2ecf20Sopenharmony_ci add_wildcard(alias); 4928c2ecf20Sopenharmony_ci return 1; 4938c2ecf20Sopenharmony_ci} 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci/* looks like: "ap:tN" */ 4968c2ecf20Sopenharmony_cistatic int do_ap_entry(const char *filename, 4978c2ecf20Sopenharmony_ci void *symval, char *alias) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci DEF_FIELD(symval, ap_device_id, dev_type); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci sprintf(alias, "ap:t%02X*", dev_type); 5028c2ecf20Sopenharmony_ci return 1; 5038c2ecf20Sopenharmony_ci} 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci/* looks like: "css:tN" */ 5068c2ecf20Sopenharmony_cistatic int do_css_entry(const char *filename, 5078c2ecf20Sopenharmony_ci void *symval, char *alias) 5088c2ecf20Sopenharmony_ci{ 5098c2ecf20Sopenharmony_ci DEF_FIELD(symval, css_device_id, type); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci sprintf(alias, "css:t%01X", type); 5128c2ecf20Sopenharmony_ci return 1; 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci/* Looks like: "serio:tyNprNidNexN" */ 5168c2ecf20Sopenharmony_cistatic int do_serio_entry(const char *filename, 5178c2ecf20Sopenharmony_ci void *symval, char *alias) 5188c2ecf20Sopenharmony_ci{ 5198c2ecf20Sopenharmony_ci DEF_FIELD(symval, serio_device_id, type); 5208c2ecf20Sopenharmony_ci DEF_FIELD(symval, serio_device_id, proto); 5218c2ecf20Sopenharmony_ci DEF_FIELD(symval, serio_device_id, id); 5228c2ecf20Sopenharmony_ci DEF_FIELD(symval, serio_device_id, extra); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci strcpy(alias, "serio:"); 5258c2ecf20Sopenharmony_ci ADD(alias, "ty", type != SERIO_ANY, type); 5268c2ecf20Sopenharmony_ci ADD(alias, "pr", proto != SERIO_ANY, proto); 5278c2ecf20Sopenharmony_ci ADD(alias, "id", id != SERIO_ANY, id); 5288c2ecf20Sopenharmony_ci ADD(alias, "ex", extra != SERIO_ANY, extra); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci add_wildcard(alias); 5318c2ecf20Sopenharmony_ci return 1; 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci/* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or 5358c2ecf20Sopenharmony_ci * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if) 5368c2ecf20Sopenharmony_ci * 5378c2ecf20Sopenharmony_ci * NOTE: Each driver should use one of the following : _HID, _CIDs 5388c2ecf20Sopenharmony_ci * or _CLS. Also, bb, ss, and pp can be substituted with ?? 5398c2ecf20Sopenharmony_ci * as don't care byte. 5408c2ecf20Sopenharmony_ci */ 5418c2ecf20Sopenharmony_cistatic int do_acpi_entry(const char *filename, 5428c2ecf20Sopenharmony_ci void *symval, char *alias) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, acpi_device_id, id); 5458c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, acpi_device_id, cls); 5468c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, acpi_device_id, cls_msk); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci if (id && strlen((const char *)*id)) 5498c2ecf20Sopenharmony_ci sprintf(alias, "acpi*:%s:*", *id); 5508c2ecf20Sopenharmony_ci else if (cls) { 5518c2ecf20Sopenharmony_ci int i, byte_shift, cnt = 0; 5528c2ecf20Sopenharmony_ci unsigned int msk; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci sprintf(&alias[cnt], "acpi*:"); 5558c2ecf20Sopenharmony_ci cnt = 6; 5568c2ecf20Sopenharmony_ci for (i = 1; i <= 3; i++) { 5578c2ecf20Sopenharmony_ci byte_shift = 8 * (3-i); 5588c2ecf20Sopenharmony_ci msk = (*cls_msk >> byte_shift) & 0xFF; 5598c2ecf20Sopenharmony_ci if (msk) 5608c2ecf20Sopenharmony_ci sprintf(&alias[cnt], "%02x", 5618c2ecf20Sopenharmony_ci (*cls >> byte_shift) & 0xFF); 5628c2ecf20Sopenharmony_ci else 5638c2ecf20Sopenharmony_ci sprintf(&alias[cnt], "??"); 5648c2ecf20Sopenharmony_ci cnt += 2; 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci sprintf(&alias[cnt], ":*"); 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci return 1; 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci/* looks like: "pnp:dD" */ 5728c2ecf20Sopenharmony_cistatic void do_pnp_device_entry(void *symval, unsigned long size, 5738c2ecf20Sopenharmony_ci struct module *mod) 5748c2ecf20Sopenharmony_ci{ 5758c2ecf20Sopenharmony_ci const unsigned long id_size = SIZE_pnp_device_id; 5768c2ecf20Sopenharmony_ci const unsigned int count = (size / id_size)-1; 5778c2ecf20Sopenharmony_ci unsigned int i; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci device_id_check(mod->name, "pnp", size, id_size, symval); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 5828c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id); 5838c2ecf20Sopenharmony_ci char acpi_id[sizeof(*id)]; 5848c2ecf20Sopenharmony_ci int j; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci buf_printf(&mod->dev_table_buf, 5878c2ecf20Sopenharmony_ci "MODULE_ALIAS(\"pnp:d%s*\");\n", *id); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci /* fix broken pnp bus lowercasing */ 5908c2ecf20Sopenharmony_ci for (j = 0; j < sizeof(acpi_id); j++) 5918c2ecf20Sopenharmony_ci acpi_id[j] = toupper((*id)[j]); 5928c2ecf20Sopenharmony_ci buf_printf(&mod->dev_table_buf, 5938c2ecf20Sopenharmony_ci "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id); 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci} 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci/* looks like: "pnp:dD" for every device of the card */ 5988c2ecf20Sopenharmony_cistatic void do_pnp_card_entries(void *symval, unsigned long size, 5998c2ecf20Sopenharmony_ci struct module *mod) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci const unsigned long id_size = SIZE_pnp_card_device_id; 6028c2ecf20Sopenharmony_ci const unsigned int count = (size / id_size)-1; 6038c2ecf20Sopenharmony_ci unsigned int i; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci device_id_check(mod->name, "pnp", size, id_size, symval); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci for (i = 0; i < count; i++) { 6088c2ecf20Sopenharmony_ci unsigned int j; 6098c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval + i * id_size, pnp_card_device_id, devs); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci for (j = 0; j < PNP_MAX_DEVICES; j++) { 6128c2ecf20Sopenharmony_ci const char *id = (char *)(*devs)[j].id; 6138c2ecf20Sopenharmony_ci int i2, j2; 6148c2ecf20Sopenharmony_ci int dup = 0; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci if (!id[0]) 6178c2ecf20Sopenharmony_ci break; 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci /* find duplicate, already added value */ 6208c2ecf20Sopenharmony_ci for (i2 = 0; i2 < i && !dup; i2++) { 6218c2ecf20Sopenharmony_ci DEF_FIELD_ADDR_VAR(symval + i2 * id_size, 6228c2ecf20Sopenharmony_ci pnp_card_device_id, 6238c2ecf20Sopenharmony_ci devs, devs_dup); 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) { 6268c2ecf20Sopenharmony_ci const char *id2 = 6278c2ecf20Sopenharmony_ci (char *)(*devs_dup)[j2].id; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci if (!id2[0]) 6308c2ecf20Sopenharmony_ci break; 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci if (!strcmp(id, id2)) { 6338c2ecf20Sopenharmony_ci dup = 1; 6348c2ecf20Sopenharmony_ci break; 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci /* add an individual alias for every device entry */ 6408c2ecf20Sopenharmony_ci if (!dup) { 6418c2ecf20Sopenharmony_ci char acpi_id[PNP_ID_LEN]; 6428c2ecf20Sopenharmony_ci int k; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci buf_printf(&mod->dev_table_buf, 6458c2ecf20Sopenharmony_ci "MODULE_ALIAS(\"pnp:d%s*\");\n", id); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* fix broken pnp bus lowercasing */ 6488c2ecf20Sopenharmony_ci for (k = 0; k < sizeof(acpi_id); k++) 6498c2ecf20Sopenharmony_ci acpi_id[k] = toupper(id[k]); 6508c2ecf20Sopenharmony_ci buf_printf(&mod->dev_table_buf, 6518c2ecf20Sopenharmony_ci "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id); 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci} 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci/* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */ 6588c2ecf20Sopenharmony_cistatic int do_pcmcia_entry(const char *filename, 6598c2ecf20Sopenharmony_ci void *symval, char *alias) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci unsigned int i; 6628c2ecf20Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, match_flags); 6638c2ecf20Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, manf_id); 6648c2ecf20Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, card_id); 6658c2ecf20Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, func_id); 6668c2ecf20Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, function); 6678c2ecf20Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, device_no); 6688c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci for (i=0; i<4; i++) { 6718c2ecf20Sopenharmony_ci (*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]); 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci strcpy(alias, "pcmcia:"); 6758c2ecf20Sopenharmony_ci ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID, 6768c2ecf20Sopenharmony_ci manf_id); 6778c2ecf20Sopenharmony_ci ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID, 6788c2ecf20Sopenharmony_ci card_id); 6798c2ecf20Sopenharmony_ci ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID, 6808c2ecf20Sopenharmony_ci func_id); 6818c2ecf20Sopenharmony_ci ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION, 6828c2ecf20Sopenharmony_ci function); 6838c2ecf20Sopenharmony_ci ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO, 6848c2ecf20Sopenharmony_ci device_no); 6858c2ecf20Sopenharmony_ci ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]); 6868c2ecf20Sopenharmony_ci ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]); 6878c2ecf20Sopenharmony_ci ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]); 6888c2ecf20Sopenharmony_ci ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]); 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci add_wildcard(alias); 6918c2ecf20Sopenharmony_ci return 1; 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_cistatic int do_vio_entry(const char *filename, void *symval, 6958c2ecf20Sopenharmony_ci char *alias) 6968c2ecf20Sopenharmony_ci{ 6978c2ecf20Sopenharmony_ci char *tmp; 6988c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, vio_device_id, type); 6998c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, vio_device_id, compat); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*", 7028c2ecf20Sopenharmony_ci (*compat)[0] ? *compat : "*"); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci /* Replace all whitespace with underscores */ 7058c2ecf20Sopenharmony_ci for (tmp = alias; tmp && *tmp; tmp++) 7068c2ecf20Sopenharmony_ci if (isspace (*tmp)) 7078c2ecf20Sopenharmony_ci *tmp = '_'; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci add_wildcard(alias); 7108c2ecf20Sopenharmony_ci return 1; 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_ci#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_cistatic void do_input(char *alias, 7168c2ecf20Sopenharmony_ci kernel_ulong_t *arr, unsigned int min, unsigned int max) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci unsigned int i; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++) 7218c2ecf20Sopenharmony_ci arr[i] = TO_NATIVE(arr[i]); 7228c2ecf20Sopenharmony_ci for (i = min; i < max; i++) 7238c2ecf20Sopenharmony_ci if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) 7248c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "%X,*", i); 7258c2ecf20Sopenharmony_ci} 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */ 7288c2ecf20Sopenharmony_cistatic int do_input_entry(const char *filename, void *symval, 7298c2ecf20Sopenharmony_ci char *alias) 7308c2ecf20Sopenharmony_ci{ 7318c2ecf20Sopenharmony_ci DEF_FIELD(symval, input_device_id, flags); 7328c2ecf20Sopenharmony_ci DEF_FIELD(symval, input_device_id, bustype); 7338c2ecf20Sopenharmony_ci DEF_FIELD(symval, input_device_id, vendor); 7348c2ecf20Sopenharmony_ci DEF_FIELD(symval, input_device_id, product); 7358c2ecf20Sopenharmony_ci DEF_FIELD(symval, input_device_id, version); 7368c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, evbit); 7378c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, keybit); 7388c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, relbit); 7398c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, absbit); 7408c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, mscbit); 7418c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, ledbit); 7428c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, sndbit); 7438c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, ffbit); 7448c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, swbit); 7458c2ecf20Sopenharmony_ci 7468c2ecf20Sopenharmony_ci sprintf(alias, "input:"); 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype); 7498c2ecf20Sopenharmony_ci ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor); 7508c2ecf20Sopenharmony_ci ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product); 7518c2ecf20Sopenharmony_ci ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version); 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "-e*"); 7548c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_EVBIT) 7558c2ecf20Sopenharmony_ci do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX); 7568c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "k*"); 7578c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT) 7588c2ecf20Sopenharmony_ci do_input(alias, *keybit, 7598c2ecf20Sopenharmony_ci INPUT_DEVICE_ID_KEY_MIN_INTERESTING, 7608c2ecf20Sopenharmony_ci INPUT_DEVICE_ID_KEY_MAX); 7618c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "r*"); 7628c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_RELBIT) 7638c2ecf20Sopenharmony_ci do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX); 7648c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "a*"); 7658c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT) 7668c2ecf20Sopenharmony_ci do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX); 7678c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "m*"); 7688c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_MSCIT) 7698c2ecf20Sopenharmony_ci do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX); 7708c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "l*"); 7718c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT) 7728c2ecf20Sopenharmony_ci do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX); 7738c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "s*"); 7748c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT) 7758c2ecf20Sopenharmony_ci do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX); 7768c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "f*"); 7778c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_FFBIT) 7788c2ecf20Sopenharmony_ci do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX); 7798c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "w*"); 7808c2ecf20Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_SWBIT) 7818c2ecf20Sopenharmony_ci do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX); 7828c2ecf20Sopenharmony_ci return 1; 7838c2ecf20Sopenharmony_ci} 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_cistatic int do_eisa_entry(const char *filename, void *symval, 7868c2ecf20Sopenharmony_ci char *alias) 7878c2ecf20Sopenharmony_ci{ 7888c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, eisa_device_id, sig); 7898c2ecf20Sopenharmony_ci if (sig[0]) 7908c2ecf20Sopenharmony_ci sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig); 7918c2ecf20Sopenharmony_ci else 7928c2ecf20Sopenharmony_ci strcat(alias, "*"); 7938c2ecf20Sopenharmony_ci return 1; 7948c2ecf20Sopenharmony_ci} 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_ci/* Looks like: parisc:tNhvNrevNsvN */ 7978c2ecf20Sopenharmony_cistatic int do_parisc_entry(const char *filename, void *symval, 7988c2ecf20Sopenharmony_ci char *alias) 7998c2ecf20Sopenharmony_ci{ 8008c2ecf20Sopenharmony_ci DEF_FIELD(symval, parisc_device_id, hw_type); 8018c2ecf20Sopenharmony_ci DEF_FIELD(symval, parisc_device_id, hversion); 8028c2ecf20Sopenharmony_ci DEF_FIELD(symval, parisc_device_id, hversion_rev); 8038c2ecf20Sopenharmony_ci DEF_FIELD(symval, parisc_device_id, sversion); 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci strcpy(alias, "parisc:"); 8068c2ecf20Sopenharmony_ci ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type); 8078c2ecf20Sopenharmony_ci ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion); 8088c2ecf20Sopenharmony_ci ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev); 8098c2ecf20Sopenharmony_ci ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci add_wildcard(alias); 8128c2ecf20Sopenharmony_ci return 1; 8138c2ecf20Sopenharmony_ci} 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci/* Looks like: sdio:cNvNdN. */ 8168c2ecf20Sopenharmony_cistatic int do_sdio_entry(const char *filename, 8178c2ecf20Sopenharmony_ci void *symval, char *alias) 8188c2ecf20Sopenharmony_ci{ 8198c2ecf20Sopenharmony_ci DEF_FIELD(symval, sdio_device_id, class); 8208c2ecf20Sopenharmony_ci DEF_FIELD(symval, sdio_device_id, vendor); 8218c2ecf20Sopenharmony_ci DEF_FIELD(symval, sdio_device_id, device); 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci strcpy(alias, "sdio:"); 8248c2ecf20Sopenharmony_ci ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class); 8258c2ecf20Sopenharmony_ci ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor); 8268c2ecf20Sopenharmony_ci ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device); 8278c2ecf20Sopenharmony_ci add_wildcard(alias); 8288c2ecf20Sopenharmony_ci return 1; 8298c2ecf20Sopenharmony_ci} 8308c2ecf20Sopenharmony_ci 8318c2ecf20Sopenharmony_ci/* Looks like: ssb:vNidNrevN. */ 8328c2ecf20Sopenharmony_cistatic int do_ssb_entry(const char *filename, 8338c2ecf20Sopenharmony_ci void *symval, char *alias) 8348c2ecf20Sopenharmony_ci{ 8358c2ecf20Sopenharmony_ci DEF_FIELD(symval, ssb_device_id, vendor); 8368c2ecf20Sopenharmony_ci DEF_FIELD(symval, ssb_device_id, coreid); 8378c2ecf20Sopenharmony_ci DEF_FIELD(symval, ssb_device_id, revision); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci strcpy(alias, "ssb:"); 8408c2ecf20Sopenharmony_ci ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor); 8418c2ecf20Sopenharmony_ci ADD(alias, "id", coreid != SSB_ANY_ID, coreid); 8428c2ecf20Sopenharmony_ci ADD(alias, "rev", revision != SSB_ANY_REV, revision); 8438c2ecf20Sopenharmony_ci add_wildcard(alias); 8448c2ecf20Sopenharmony_ci return 1; 8458c2ecf20Sopenharmony_ci} 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci/* Looks like: bcma:mNidNrevNclN. */ 8488c2ecf20Sopenharmony_cistatic int do_bcma_entry(const char *filename, 8498c2ecf20Sopenharmony_ci void *symval, char *alias) 8508c2ecf20Sopenharmony_ci{ 8518c2ecf20Sopenharmony_ci DEF_FIELD(symval, bcma_device_id, manuf); 8528c2ecf20Sopenharmony_ci DEF_FIELD(symval, bcma_device_id, id); 8538c2ecf20Sopenharmony_ci DEF_FIELD(symval, bcma_device_id, rev); 8548c2ecf20Sopenharmony_ci DEF_FIELD(symval, bcma_device_id, class); 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci strcpy(alias, "bcma:"); 8578c2ecf20Sopenharmony_ci ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf); 8588c2ecf20Sopenharmony_ci ADD(alias, "id", id != BCMA_ANY_ID, id); 8598c2ecf20Sopenharmony_ci ADD(alias, "rev", rev != BCMA_ANY_REV, rev); 8608c2ecf20Sopenharmony_ci ADD(alias, "cl", class != BCMA_ANY_CLASS, class); 8618c2ecf20Sopenharmony_ci add_wildcard(alias); 8628c2ecf20Sopenharmony_ci return 1; 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci/* Looks like: virtio:dNvN */ 8668c2ecf20Sopenharmony_cistatic int do_virtio_entry(const char *filename, void *symval, 8678c2ecf20Sopenharmony_ci char *alias) 8688c2ecf20Sopenharmony_ci{ 8698c2ecf20Sopenharmony_ci DEF_FIELD(symval, virtio_device_id, device); 8708c2ecf20Sopenharmony_ci DEF_FIELD(symval, virtio_device_id, vendor); 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci strcpy(alias, "virtio:"); 8738c2ecf20Sopenharmony_ci ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device); 8748c2ecf20Sopenharmony_ci ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci add_wildcard(alias); 8778c2ecf20Sopenharmony_ci return 1; 8788c2ecf20Sopenharmony_ci} 8798c2ecf20Sopenharmony_ci 8808c2ecf20Sopenharmony_ci/* 8818c2ecf20Sopenharmony_ci * Looks like: vmbus:guid 8828c2ecf20Sopenharmony_ci * Each byte of the guid will be represented by two hex characters 8838c2ecf20Sopenharmony_ci * in the name. 8848c2ecf20Sopenharmony_ci */ 8858c2ecf20Sopenharmony_ci 8868c2ecf20Sopenharmony_cistatic int do_vmbus_entry(const char *filename, void *symval, 8878c2ecf20Sopenharmony_ci char *alias) 8888c2ecf20Sopenharmony_ci{ 8898c2ecf20Sopenharmony_ci int i; 8908c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid); 8918c2ecf20Sopenharmony_ci char guid_name[(sizeof(*guid) + 1) * 2]; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci for (i = 0; i < (sizeof(*guid) * 2); i += 2) 8948c2ecf20Sopenharmony_ci sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2])); 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_ci strcpy(alias, "vmbus:"); 8978c2ecf20Sopenharmony_ci strcat(alias, guid_name); 8988c2ecf20Sopenharmony_ci 8998c2ecf20Sopenharmony_ci return 1; 9008c2ecf20Sopenharmony_ci} 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci/* Looks like: rpmsg:S */ 9038c2ecf20Sopenharmony_cistatic int do_rpmsg_entry(const char *filename, void *symval, 9048c2ecf20Sopenharmony_ci char *alias) 9058c2ecf20Sopenharmony_ci{ 9068c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, rpmsg_device_id, name); 9078c2ecf20Sopenharmony_ci sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci return 1; 9108c2ecf20Sopenharmony_ci} 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci/* Looks like: i2c:S */ 9138c2ecf20Sopenharmony_cistatic int do_i2c_entry(const char *filename, void *symval, 9148c2ecf20Sopenharmony_ci char *alias) 9158c2ecf20Sopenharmony_ci{ 9168c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, i2c_device_id, name); 9178c2ecf20Sopenharmony_ci sprintf(alias, I2C_MODULE_PREFIX "%s", *name); 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci return 1; 9208c2ecf20Sopenharmony_ci} 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_cistatic int do_i3c_entry(const char *filename, void *symval, 9238c2ecf20Sopenharmony_ci char *alias) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, match_flags); 9268c2ecf20Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, dcr); 9278c2ecf20Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, manuf_id); 9288c2ecf20Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, part_id); 9298c2ecf20Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, extra_info); 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci strcpy(alias, "i3c:"); 9328c2ecf20Sopenharmony_ci ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr); 9338c2ecf20Sopenharmony_ci ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id); 9348c2ecf20Sopenharmony_ci ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id); 9358c2ecf20Sopenharmony_ci ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info); 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci return 1; 9388c2ecf20Sopenharmony_ci} 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci/* Looks like: spi:S */ 9418c2ecf20Sopenharmony_cistatic int do_spi_entry(const char *filename, void *symval, 9428c2ecf20Sopenharmony_ci char *alias) 9438c2ecf20Sopenharmony_ci{ 9448c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, spi_device_id, name); 9458c2ecf20Sopenharmony_ci sprintf(alias, SPI_MODULE_PREFIX "%s", *name); 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci return 1; 9488c2ecf20Sopenharmony_ci} 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_cistatic const struct dmifield { 9518c2ecf20Sopenharmony_ci const char *prefix; 9528c2ecf20Sopenharmony_ci int field; 9538c2ecf20Sopenharmony_ci} dmi_fields[] = { 9548c2ecf20Sopenharmony_ci { "bvn", DMI_BIOS_VENDOR }, 9558c2ecf20Sopenharmony_ci { "bvr", DMI_BIOS_VERSION }, 9568c2ecf20Sopenharmony_ci { "bd", DMI_BIOS_DATE }, 9578c2ecf20Sopenharmony_ci { "br", DMI_BIOS_RELEASE }, 9588c2ecf20Sopenharmony_ci { "efr", DMI_EC_FIRMWARE_RELEASE }, 9598c2ecf20Sopenharmony_ci { "svn", DMI_SYS_VENDOR }, 9608c2ecf20Sopenharmony_ci { "pn", DMI_PRODUCT_NAME }, 9618c2ecf20Sopenharmony_ci { "pvr", DMI_PRODUCT_VERSION }, 9628c2ecf20Sopenharmony_ci { "rvn", DMI_BOARD_VENDOR }, 9638c2ecf20Sopenharmony_ci { "rn", DMI_BOARD_NAME }, 9648c2ecf20Sopenharmony_ci { "rvr", DMI_BOARD_VERSION }, 9658c2ecf20Sopenharmony_ci { "cvn", DMI_CHASSIS_VENDOR }, 9668c2ecf20Sopenharmony_ci { "ct", DMI_CHASSIS_TYPE }, 9678c2ecf20Sopenharmony_ci { "cvr", DMI_CHASSIS_VERSION }, 9688c2ecf20Sopenharmony_ci { NULL, DMI_NONE } 9698c2ecf20Sopenharmony_ci}; 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_cistatic void dmi_ascii_filter(char *d, const char *s) 9728c2ecf20Sopenharmony_ci{ 9738c2ecf20Sopenharmony_ci /* Filter out characters we don't want to see in the modalias string */ 9748c2ecf20Sopenharmony_ci for (; *s; s++) 9758c2ecf20Sopenharmony_ci if (*s > ' ' && *s < 127 && *s != ':') 9768c2ecf20Sopenharmony_ci *(d++) = *s; 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci *d = 0; 9798c2ecf20Sopenharmony_ci} 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_cistatic int do_dmi_entry(const char *filename, void *symval, 9838c2ecf20Sopenharmony_ci char *alias) 9848c2ecf20Sopenharmony_ci{ 9858c2ecf20Sopenharmony_ci int i, j; 9868c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, dmi_system_id, matches); 9878c2ecf20Sopenharmony_ci sprintf(alias, "dmi*"); 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) { 9908c2ecf20Sopenharmony_ci for (j = 0; j < 4; j++) { 9918c2ecf20Sopenharmony_ci if ((*matches)[j].slot && 9928c2ecf20Sopenharmony_ci (*matches)[j].slot == dmi_fields[i].field) { 9938c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), ":%s*", 9948c2ecf20Sopenharmony_ci dmi_fields[i].prefix); 9958c2ecf20Sopenharmony_ci dmi_ascii_filter(alias + strlen(alias), 9968c2ecf20Sopenharmony_ci (*matches)[j].substr); 9978c2ecf20Sopenharmony_ci strcat(alias, "*"); 9988c2ecf20Sopenharmony_ci } 9998c2ecf20Sopenharmony_ci } 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci strcat(alias, ":"); 10038c2ecf20Sopenharmony_ci return 1; 10048c2ecf20Sopenharmony_ci} 10058c2ecf20Sopenharmony_ci 10068c2ecf20Sopenharmony_cistatic int do_platform_entry(const char *filename, 10078c2ecf20Sopenharmony_ci void *symval, char *alias) 10088c2ecf20Sopenharmony_ci{ 10098c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, platform_device_id, name); 10108c2ecf20Sopenharmony_ci sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name); 10118c2ecf20Sopenharmony_ci return 1; 10128c2ecf20Sopenharmony_ci} 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_cistatic int do_mdio_entry(const char *filename, 10158c2ecf20Sopenharmony_ci void *symval, char *alias) 10168c2ecf20Sopenharmony_ci{ 10178c2ecf20Sopenharmony_ci int i; 10188c2ecf20Sopenharmony_ci DEF_FIELD(symval, mdio_device_id, phy_id); 10198c2ecf20Sopenharmony_ci DEF_FIELD(symval, mdio_device_id, phy_id_mask); 10208c2ecf20Sopenharmony_ci 10218c2ecf20Sopenharmony_ci alias += sprintf(alias, MDIO_MODULE_PREFIX); 10228c2ecf20Sopenharmony_ci 10238c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++) { 10248c2ecf20Sopenharmony_ci if (!((phy_id_mask >> (31-i)) & 1)) 10258c2ecf20Sopenharmony_ci *(alias++) = '?'; 10268c2ecf20Sopenharmony_ci else if ((phy_id >> (31-i)) & 1) 10278c2ecf20Sopenharmony_ci *(alias++) = '1'; 10288c2ecf20Sopenharmony_ci else 10298c2ecf20Sopenharmony_ci *(alias++) = '0'; 10308c2ecf20Sopenharmony_ci } 10318c2ecf20Sopenharmony_ci 10328c2ecf20Sopenharmony_ci /* Terminate the string */ 10338c2ecf20Sopenharmony_ci *alias = 0; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci return 1; 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci/* Looks like: zorro:iN. */ 10398c2ecf20Sopenharmony_cistatic int do_zorro_entry(const char *filename, void *symval, 10408c2ecf20Sopenharmony_ci char *alias) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci DEF_FIELD(symval, zorro_device_id, id); 10438c2ecf20Sopenharmony_ci strcpy(alias, "zorro:"); 10448c2ecf20Sopenharmony_ci ADD(alias, "i", id != ZORRO_WILDCARD, id); 10458c2ecf20Sopenharmony_ci return 1; 10468c2ecf20Sopenharmony_ci} 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci/* looks like: "pnp:dD" */ 10498c2ecf20Sopenharmony_cistatic int do_isapnp_entry(const char *filename, 10508c2ecf20Sopenharmony_ci void *symval, char *alias) 10518c2ecf20Sopenharmony_ci{ 10528c2ecf20Sopenharmony_ci DEF_FIELD(symval, isapnp_device_id, vendor); 10538c2ecf20Sopenharmony_ci DEF_FIELD(symval, isapnp_device_id, function); 10548c2ecf20Sopenharmony_ci sprintf(alias, "pnp:d%c%c%c%x%x%x%x*", 10558c2ecf20Sopenharmony_ci 'A' + ((vendor >> 2) & 0x3f) - 1, 10568c2ecf20Sopenharmony_ci 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, 10578c2ecf20Sopenharmony_ci 'A' + ((vendor >> 8) & 0x1f) - 1, 10588c2ecf20Sopenharmony_ci (function >> 4) & 0x0f, function & 0x0f, 10598c2ecf20Sopenharmony_ci (function >> 12) & 0x0f, (function >> 8) & 0x0f); 10608c2ecf20Sopenharmony_ci return 1; 10618c2ecf20Sopenharmony_ci} 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci/* Looks like: "ipack:fNvNdN". */ 10648c2ecf20Sopenharmony_cistatic int do_ipack_entry(const char *filename, 10658c2ecf20Sopenharmony_ci void *symval, char *alias) 10668c2ecf20Sopenharmony_ci{ 10678c2ecf20Sopenharmony_ci DEF_FIELD(symval, ipack_device_id, format); 10688c2ecf20Sopenharmony_ci DEF_FIELD(symval, ipack_device_id, vendor); 10698c2ecf20Sopenharmony_ci DEF_FIELD(symval, ipack_device_id, device); 10708c2ecf20Sopenharmony_ci strcpy(alias, "ipack:"); 10718c2ecf20Sopenharmony_ci ADD(alias, "f", format != IPACK_ANY_FORMAT, format); 10728c2ecf20Sopenharmony_ci ADD(alias, "v", vendor != IPACK_ANY_ID, vendor); 10738c2ecf20Sopenharmony_ci ADD(alias, "d", device != IPACK_ANY_ID, device); 10748c2ecf20Sopenharmony_ci add_wildcard(alias); 10758c2ecf20Sopenharmony_ci return 1; 10768c2ecf20Sopenharmony_ci} 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci/* 10798c2ecf20Sopenharmony_ci * Append a match expression for a single masked hex digit. 10808c2ecf20Sopenharmony_ci * outp points to a pointer to the character at which to append. 10818c2ecf20Sopenharmony_ci * *outp is updated on return to point just after the appended text, 10828c2ecf20Sopenharmony_ci * to facilitate further appending. 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_cistatic void append_nibble_mask(char **outp, 10858c2ecf20Sopenharmony_ci unsigned int nibble, unsigned int mask) 10868c2ecf20Sopenharmony_ci{ 10878c2ecf20Sopenharmony_ci char *p = *outp; 10888c2ecf20Sopenharmony_ci unsigned int i; 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci switch (mask) { 10918c2ecf20Sopenharmony_ci case 0: 10928c2ecf20Sopenharmony_ci *p++ = '?'; 10938c2ecf20Sopenharmony_ci break; 10948c2ecf20Sopenharmony_ci 10958c2ecf20Sopenharmony_ci case 0xf: 10968c2ecf20Sopenharmony_ci p += sprintf(p, "%X", nibble); 10978c2ecf20Sopenharmony_ci break; 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci default: 11008c2ecf20Sopenharmony_ci /* 11018c2ecf20Sopenharmony_ci * Dumbly emit a match pattern for all possible matching 11028c2ecf20Sopenharmony_ci * digits. This could be improved in some cases using ranges, 11038c2ecf20Sopenharmony_ci * but it has the advantage of being trivially correct, and is 11048c2ecf20Sopenharmony_ci * often optimal. 11058c2ecf20Sopenharmony_ci */ 11068c2ecf20Sopenharmony_ci *p++ = '['; 11078c2ecf20Sopenharmony_ci for (i = 0; i < 0x10; i++) 11088c2ecf20Sopenharmony_ci if ((i & mask) == nibble) 11098c2ecf20Sopenharmony_ci p += sprintf(p, "%X", i); 11108c2ecf20Sopenharmony_ci *p++ = ']'; 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci /* Ensure that the string remains NUL-terminated: */ 11148c2ecf20Sopenharmony_ci *p = '\0'; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci /* Advance the caller's end-of-string pointer: */ 11178c2ecf20Sopenharmony_ci *outp = p; 11188c2ecf20Sopenharmony_ci} 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci/* 11218c2ecf20Sopenharmony_ci * looks like: "amba:dN" 11228c2ecf20Sopenharmony_ci * 11238c2ecf20Sopenharmony_ci * N is exactly 8 digits, where each is an upper-case hex digit, or 11248c2ecf20Sopenharmony_ci * a ? or [] pattern matching exactly one digit. 11258c2ecf20Sopenharmony_ci */ 11268c2ecf20Sopenharmony_cistatic int do_amba_entry(const char *filename, 11278c2ecf20Sopenharmony_ci void *symval, char *alias) 11288c2ecf20Sopenharmony_ci{ 11298c2ecf20Sopenharmony_ci unsigned int digit; 11308c2ecf20Sopenharmony_ci char *p = alias; 11318c2ecf20Sopenharmony_ci DEF_FIELD(symval, amba_id, id); 11328c2ecf20Sopenharmony_ci DEF_FIELD(symval, amba_id, mask); 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci if ((id & mask) != id) 11358c2ecf20Sopenharmony_ci fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: " 11368c2ecf20Sopenharmony_ci "id=0x%08X, mask=0x%08X. Please fix this driver.\n", 11378c2ecf20Sopenharmony_ci filename, id, mask); 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci p += sprintf(alias, "amba:d"); 11408c2ecf20Sopenharmony_ci for (digit = 0; digit < 8; digit++) 11418c2ecf20Sopenharmony_ci append_nibble_mask(&p, 11428c2ecf20Sopenharmony_ci (id >> (4 * (7 - digit))) & 0xf, 11438c2ecf20Sopenharmony_ci (mask >> (4 * (7 - digit))) & 0xf); 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci return 1; 11468c2ecf20Sopenharmony_ci} 11478c2ecf20Sopenharmony_ci 11488c2ecf20Sopenharmony_ci/* 11498c2ecf20Sopenharmony_ci * looks like: "mipscdmm:tN" 11508c2ecf20Sopenharmony_ci * 11518c2ecf20Sopenharmony_ci * N is exactly 2 digits, where each is an upper-case hex digit, or 11528c2ecf20Sopenharmony_ci * a ? or [] pattern matching exactly one digit. 11538c2ecf20Sopenharmony_ci */ 11548c2ecf20Sopenharmony_cistatic int do_mips_cdmm_entry(const char *filename, 11558c2ecf20Sopenharmony_ci void *symval, char *alias) 11568c2ecf20Sopenharmony_ci{ 11578c2ecf20Sopenharmony_ci DEF_FIELD(symval, mips_cdmm_device_id, type); 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci sprintf(alias, "mipscdmm:t%02X*", type); 11608c2ecf20Sopenharmony_ci return 1; 11618c2ecf20Sopenharmony_ci} 11628c2ecf20Sopenharmony_ci 11638c2ecf20Sopenharmony_ci/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,* 11648c2ecf20Sopenharmony_ci * All fields are numbers. It would be nicer to use strings for vendor 11658c2ecf20Sopenharmony_ci * and feature, but getting those out of the build system here is too 11668c2ecf20Sopenharmony_ci * complicated. 11678c2ecf20Sopenharmony_ci */ 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic int do_x86cpu_entry(const char *filename, void *symval, 11708c2ecf20Sopenharmony_ci char *alias) 11718c2ecf20Sopenharmony_ci{ 11728c2ecf20Sopenharmony_ci DEF_FIELD(symval, x86_cpu_id, feature); 11738c2ecf20Sopenharmony_ci DEF_FIELD(symval, x86_cpu_id, family); 11748c2ecf20Sopenharmony_ci DEF_FIELD(symval, x86_cpu_id, model); 11758c2ecf20Sopenharmony_ci DEF_FIELD(symval, x86_cpu_id, vendor); 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci strcpy(alias, "cpu:type:x86,"); 11788c2ecf20Sopenharmony_ci ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor); 11798c2ecf20Sopenharmony_ci ADD(alias, "fam", family != X86_FAMILY_ANY, family); 11808c2ecf20Sopenharmony_ci ADD(alias, "mod", model != X86_MODEL_ANY, model); 11818c2ecf20Sopenharmony_ci strcat(alias, ":feature:*"); 11828c2ecf20Sopenharmony_ci if (feature != X86_FEATURE_ANY) 11838c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "%04X*", feature); 11848c2ecf20Sopenharmony_ci return 1; 11858c2ecf20Sopenharmony_ci} 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci/* LOOKS like cpu:type:*:feature:*FEAT* */ 11888c2ecf20Sopenharmony_cistatic int do_cpu_entry(const char *filename, void *symval, char *alias) 11898c2ecf20Sopenharmony_ci{ 11908c2ecf20Sopenharmony_ci DEF_FIELD(symval, cpu_feature, feature); 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci sprintf(alias, "cpu:type:*:feature:*%04X*", feature); 11938c2ecf20Sopenharmony_ci return 1; 11948c2ecf20Sopenharmony_ci} 11958c2ecf20Sopenharmony_ci 11968c2ecf20Sopenharmony_ci/* Looks like: mei:S:uuid:N:* */ 11978c2ecf20Sopenharmony_cistatic int do_mei_entry(const char *filename, void *symval, 11988c2ecf20Sopenharmony_ci char *alias) 11998c2ecf20Sopenharmony_ci{ 12008c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, mei_cl_device_id, name); 12018c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid); 12028c2ecf20Sopenharmony_ci DEF_FIELD(symval, mei_cl_device_id, version); 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_ci sprintf(alias, MEI_CL_MODULE_PREFIX); 12058c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "%s:", (*name)[0] ? *name : "*"); 12068c2ecf20Sopenharmony_ci add_uuid(alias, *uuid); 12078c2ecf20Sopenharmony_ci ADD(alias, ":", version != MEI_CL_VERSION_ANY, version); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci strcat(alias, ":*"); 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_ci return 1; 12128c2ecf20Sopenharmony_ci} 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci/* Looks like: rapidio:vNdNavNadN */ 12158c2ecf20Sopenharmony_cistatic int do_rio_entry(const char *filename, 12168c2ecf20Sopenharmony_ci void *symval, char *alias) 12178c2ecf20Sopenharmony_ci{ 12188c2ecf20Sopenharmony_ci DEF_FIELD(symval, rio_device_id, did); 12198c2ecf20Sopenharmony_ci DEF_FIELD(symval, rio_device_id, vid); 12208c2ecf20Sopenharmony_ci DEF_FIELD(symval, rio_device_id, asm_did); 12218c2ecf20Sopenharmony_ci DEF_FIELD(symval, rio_device_id, asm_vid); 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci strcpy(alias, "rapidio:"); 12248c2ecf20Sopenharmony_ci ADD(alias, "v", vid != RIO_ANY_ID, vid); 12258c2ecf20Sopenharmony_ci ADD(alias, "d", did != RIO_ANY_ID, did); 12268c2ecf20Sopenharmony_ci ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid); 12278c2ecf20Sopenharmony_ci ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci add_wildcard(alias); 12308c2ecf20Sopenharmony_ci return 1; 12318c2ecf20Sopenharmony_ci} 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci/* Looks like: ulpi:vNpN */ 12348c2ecf20Sopenharmony_cistatic int do_ulpi_entry(const char *filename, void *symval, 12358c2ecf20Sopenharmony_ci char *alias) 12368c2ecf20Sopenharmony_ci{ 12378c2ecf20Sopenharmony_ci DEF_FIELD(symval, ulpi_device_id, vendor); 12388c2ecf20Sopenharmony_ci DEF_FIELD(symval, ulpi_device_id, product); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci sprintf(alias, "ulpi:v%04xp%04x", vendor, product); 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci return 1; 12438c2ecf20Sopenharmony_ci} 12448c2ecf20Sopenharmony_ci 12458c2ecf20Sopenharmony_ci/* Looks like: hdaudio:vNrNaN */ 12468c2ecf20Sopenharmony_cistatic int do_hda_entry(const char *filename, void *symval, char *alias) 12478c2ecf20Sopenharmony_ci{ 12488c2ecf20Sopenharmony_ci DEF_FIELD(symval, hda_device_id, vendor_id); 12498c2ecf20Sopenharmony_ci DEF_FIELD(symval, hda_device_id, rev_id); 12508c2ecf20Sopenharmony_ci DEF_FIELD(symval, hda_device_id, api_version); 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci strcpy(alias, "hdaudio:"); 12538c2ecf20Sopenharmony_ci ADD(alias, "v", vendor_id != 0, vendor_id); 12548c2ecf20Sopenharmony_ci ADD(alias, "r", rev_id != 0, rev_id); 12558c2ecf20Sopenharmony_ci ADD(alias, "a", api_version != 0, api_version); 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci add_wildcard(alias); 12588c2ecf20Sopenharmony_ci return 1; 12598c2ecf20Sopenharmony_ci} 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci/* Looks like: sdw:mNpNvNcN */ 12628c2ecf20Sopenharmony_cistatic int do_sdw_entry(const char *filename, void *symval, char *alias) 12638c2ecf20Sopenharmony_ci{ 12648c2ecf20Sopenharmony_ci DEF_FIELD(symval, sdw_device_id, mfg_id); 12658c2ecf20Sopenharmony_ci DEF_FIELD(symval, sdw_device_id, part_id); 12668c2ecf20Sopenharmony_ci DEF_FIELD(symval, sdw_device_id, sdw_version); 12678c2ecf20Sopenharmony_ci DEF_FIELD(symval, sdw_device_id, class_id); 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci strcpy(alias, "sdw:"); 12708c2ecf20Sopenharmony_ci ADD(alias, "m", mfg_id != 0, mfg_id); 12718c2ecf20Sopenharmony_ci ADD(alias, "p", part_id != 0, part_id); 12728c2ecf20Sopenharmony_ci ADD(alias, "v", sdw_version != 0, sdw_version); 12738c2ecf20Sopenharmony_ci ADD(alias, "c", class_id != 0, class_id); 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci add_wildcard(alias); 12768c2ecf20Sopenharmony_ci return 1; 12778c2ecf20Sopenharmony_ci} 12788c2ecf20Sopenharmony_ci 12798c2ecf20Sopenharmony_ci/* Looks like: fsl-mc:vNdN */ 12808c2ecf20Sopenharmony_cistatic int do_fsl_mc_entry(const char *filename, void *symval, 12818c2ecf20Sopenharmony_ci char *alias) 12828c2ecf20Sopenharmony_ci{ 12838c2ecf20Sopenharmony_ci DEF_FIELD(symval, fsl_mc_device_id, vendor); 12848c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type); 12858c2ecf20Sopenharmony_ci 12868c2ecf20Sopenharmony_ci sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type); 12878c2ecf20Sopenharmony_ci return 1; 12888c2ecf20Sopenharmony_ci} 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci/* Looks like: tbsvc:kSpNvNrN */ 12918c2ecf20Sopenharmony_cistatic int do_tbsvc_entry(const char *filename, void *symval, char *alias) 12928c2ecf20Sopenharmony_ci{ 12938c2ecf20Sopenharmony_ci DEF_FIELD(symval, tb_service_id, match_flags); 12948c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, tb_service_id, protocol_key); 12958c2ecf20Sopenharmony_ci DEF_FIELD(symval, tb_service_id, protocol_id); 12968c2ecf20Sopenharmony_ci DEF_FIELD(symval, tb_service_id, protocol_version); 12978c2ecf20Sopenharmony_ci DEF_FIELD(symval, tb_service_id, protocol_revision); 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci strcpy(alias, "tbsvc:"); 13008c2ecf20Sopenharmony_ci if (match_flags & TBSVC_MATCH_PROTOCOL_KEY) 13018c2ecf20Sopenharmony_ci sprintf(alias + strlen(alias), "k%s", *protocol_key); 13028c2ecf20Sopenharmony_ci else 13038c2ecf20Sopenharmony_ci strcat(alias + strlen(alias), "k*"); 13048c2ecf20Sopenharmony_ci ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id); 13058c2ecf20Sopenharmony_ci ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION, 13068c2ecf20Sopenharmony_ci protocol_version); 13078c2ecf20Sopenharmony_ci ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION, 13088c2ecf20Sopenharmony_ci protocol_revision); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci add_wildcard(alias); 13118c2ecf20Sopenharmony_ci return 1; 13128c2ecf20Sopenharmony_ci} 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ci/* Looks like: typec:idNmN */ 13158c2ecf20Sopenharmony_cistatic int do_typec_entry(const char *filename, void *symval, char *alias) 13168c2ecf20Sopenharmony_ci{ 13178c2ecf20Sopenharmony_ci DEF_FIELD(symval, typec_device_id, svid); 13188c2ecf20Sopenharmony_ci DEF_FIELD(symval, typec_device_id, mode); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci sprintf(alias, "typec:id%04X", svid); 13218c2ecf20Sopenharmony_ci ADD(alias, "m", mode != TYPEC_ANY_MODE, mode); 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci return 1; 13248c2ecf20Sopenharmony_ci} 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci/* Looks like: tee:uuid */ 13278c2ecf20Sopenharmony_cistatic int do_tee_entry(const char *filename, void *symval, char *alias) 13288c2ecf20Sopenharmony_ci{ 13298c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, tee_client_device_id, uuid); 13308c2ecf20Sopenharmony_ci 13318c2ecf20Sopenharmony_ci sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 13328c2ecf20Sopenharmony_ci uuid->b[0], uuid->b[1], uuid->b[2], uuid->b[3], uuid->b[4], 13338c2ecf20Sopenharmony_ci uuid->b[5], uuid->b[6], uuid->b[7], uuid->b[8], uuid->b[9], 13348c2ecf20Sopenharmony_ci uuid->b[10], uuid->b[11], uuid->b[12], uuid->b[13], uuid->b[14], 13358c2ecf20Sopenharmony_ci uuid->b[15]); 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci add_wildcard(alias); 13388c2ecf20Sopenharmony_ci return 1; 13398c2ecf20Sopenharmony_ci} 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci/* Looks like: wmi:guid */ 13428c2ecf20Sopenharmony_cistatic int do_wmi_entry(const char *filename, void *symval, char *alias) 13438c2ecf20Sopenharmony_ci{ 13448c2ecf20Sopenharmony_ci int len; 13458c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, wmi_device_id, guid_string); 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_ci if (strlen(*guid_string) != UUID_STRING_LEN) { 13488c2ecf20Sopenharmony_ci warn("Invalid WMI device id 'wmi:%s' in '%s'\n", 13498c2ecf20Sopenharmony_ci *guid_string, filename); 13508c2ecf20Sopenharmony_ci return 0; 13518c2ecf20Sopenharmony_ci } 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string); 13548c2ecf20Sopenharmony_ci if (len < 0 || len >= ALIAS_SIZE) { 13558c2ecf20Sopenharmony_ci warn("Could not generate all MODULE_ALIAS's in '%s'\n", 13568c2ecf20Sopenharmony_ci filename); 13578c2ecf20Sopenharmony_ci return 0; 13588c2ecf20Sopenharmony_ci } 13598c2ecf20Sopenharmony_ci return 1; 13608c2ecf20Sopenharmony_ci} 13618c2ecf20Sopenharmony_ci 13628c2ecf20Sopenharmony_ci/* Looks like: mhi:S */ 13638c2ecf20Sopenharmony_cistatic int do_mhi_entry(const char *filename, void *symval, char *alias) 13648c2ecf20Sopenharmony_ci{ 13658c2ecf20Sopenharmony_ci DEF_FIELD_ADDR(symval, mhi_device_id, chan); 13668c2ecf20Sopenharmony_ci sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan); 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci return 1; 13698c2ecf20Sopenharmony_ci} 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci/* Does namelen bytes of name exactly match the symbol? */ 13728c2ecf20Sopenharmony_cistatic bool sym_is(const char *name, unsigned namelen, const char *symbol) 13738c2ecf20Sopenharmony_ci{ 13748c2ecf20Sopenharmony_ci if (namelen != strlen(symbol)) 13758c2ecf20Sopenharmony_ci return false; 13768c2ecf20Sopenharmony_ci 13778c2ecf20Sopenharmony_ci return memcmp(name, symbol, namelen) == 0; 13788c2ecf20Sopenharmony_ci} 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_cistatic void do_table(void *symval, unsigned long size, 13818c2ecf20Sopenharmony_ci unsigned long id_size, 13828c2ecf20Sopenharmony_ci const char *device_id, 13838c2ecf20Sopenharmony_ci int (*do_entry)(const char *filename, void *symval, char *alias), 13848c2ecf20Sopenharmony_ci struct module *mod) 13858c2ecf20Sopenharmony_ci{ 13868c2ecf20Sopenharmony_ci unsigned int i; 13878c2ecf20Sopenharmony_ci char alias[ALIAS_SIZE]; 13888c2ecf20Sopenharmony_ci 13898c2ecf20Sopenharmony_ci device_id_check(mod->name, device_id, size, id_size, symval); 13908c2ecf20Sopenharmony_ci /* Leave last one: it's the terminator. */ 13918c2ecf20Sopenharmony_ci size -= id_size; 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_ci for (i = 0; i < size; i += id_size) { 13948c2ecf20Sopenharmony_ci if (do_entry(mod->name, symval+i, alias)) { 13958c2ecf20Sopenharmony_ci buf_printf(&mod->dev_table_buf, 13968c2ecf20Sopenharmony_ci "MODULE_ALIAS(\"%s\");\n", alias); 13978c2ecf20Sopenharmony_ci } 13988c2ecf20Sopenharmony_ci } 13998c2ecf20Sopenharmony_ci} 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_cistatic const struct devtable devtable[] = { 14028c2ecf20Sopenharmony_ci {"hid", SIZE_hid_device_id, do_hid_entry}, 14038c2ecf20Sopenharmony_ci {"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry}, 14048c2ecf20Sopenharmony_ci {"pci", SIZE_pci_device_id, do_pci_entry}, 14058c2ecf20Sopenharmony_ci {"ccw", SIZE_ccw_device_id, do_ccw_entry}, 14068c2ecf20Sopenharmony_ci {"ap", SIZE_ap_device_id, do_ap_entry}, 14078c2ecf20Sopenharmony_ci {"css", SIZE_css_device_id, do_css_entry}, 14088c2ecf20Sopenharmony_ci {"serio", SIZE_serio_device_id, do_serio_entry}, 14098c2ecf20Sopenharmony_ci {"acpi", SIZE_acpi_device_id, do_acpi_entry}, 14108c2ecf20Sopenharmony_ci {"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry}, 14118c2ecf20Sopenharmony_ci {"vio", SIZE_vio_device_id, do_vio_entry}, 14128c2ecf20Sopenharmony_ci {"input", SIZE_input_device_id, do_input_entry}, 14138c2ecf20Sopenharmony_ci {"eisa", SIZE_eisa_device_id, do_eisa_entry}, 14148c2ecf20Sopenharmony_ci {"parisc", SIZE_parisc_device_id, do_parisc_entry}, 14158c2ecf20Sopenharmony_ci {"sdio", SIZE_sdio_device_id, do_sdio_entry}, 14168c2ecf20Sopenharmony_ci {"ssb", SIZE_ssb_device_id, do_ssb_entry}, 14178c2ecf20Sopenharmony_ci {"bcma", SIZE_bcma_device_id, do_bcma_entry}, 14188c2ecf20Sopenharmony_ci {"virtio", SIZE_virtio_device_id, do_virtio_entry}, 14198c2ecf20Sopenharmony_ci {"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry}, 14208c2ecf20Sopenharmony_ci {"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry}, 14218c2ecf20Sopenharmony_ci {"i2c", SIZE_i2c_device_id, do_i2c_entry}, 14228c2ecf20Sopenharmony_ci {"i3c", SIZE_i3c_device_id, do_i3c_entry}, 14238c2ecf20Sopenharmony_ci {"spi", SIZE_spi_device_id, do_spi_entry}, 14248c2ecf20Sopenharmony_ci {"dmi", SIZE_dmi_system_id, do_dmi_entry}, 14258c2ecf20Sopenharmony_ci {"platform", SIZE_platform_device_id, do_platform_entry}, 14268c2ecf20Sopenharmony_ci {"mdio", SIZE_mdio_device_id, do_mdio_entry}, 14278c2ecf20Sopenharmony_ci {"zorro", SIZE_zorro_device_id, do_zorro_entry}, 14288c2ecf20Sopenharmony_ci {"isapnp", SIZE_isapnp_device_id, do_isapnp_entry}, 14298c2ecf20Sopenharmony_ci {"ipack", SIZE_ipack_device_id, do_ipack_entry}, 14308c2ecf20Sopenharmony_ci {"amba", SIZE_amba_id, do_amba_entry}, 14318c2ecf20Sopenharmony_ci {"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry}, 14328c2ecf20Sopenharmony_ci {"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry}, 14338c2ecf20Sopenharmony_ci {"cpu", SIZE_cpu_feature, do_cpu_entry}, 14348c2ecf20Sopenharmony_ci {"mei", SIZE_mei_cl_device_id, do_mei_entry}, 14358c2ecf20Sopenharmony_ci {"rapidio", SIZE_rio_device_id, do_rio_entry}, 14368c2ecf20Sopenharmony_ci {"ulpi", SIZE_ulpi_device_id, do_ulpi_entry}, 14378c2ecf20Sopenharmony_ci {"hdaudio", SIZE_hda_device_id, do_hda_entry}, 14388c2ecf20Sopenharmony_ci {"sdw", SIZE_sdw_device_id, do_sdw_entry}, 14398c2ecf20Sopenharmony_ci {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry}, 14408c2ecf20Sopenharmony_ci {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry}, 14418c2ecf20Sopenharmony_ci {"typec", SIZE_typec_device_id, do_typec_entry}, 14428c2ecf20Sopenharmony_ci {"tee", SIZE_tee_client_device_id, do_tee_entry}, 14438c2ecf20Sopenharmony_ci {"wmi", SIZE_wmi_device_id, do_wmi_entry}, 14448c2ecf20Sopenharmony_ci {"mhi", SIZE_mhi_device_id, do_mhi_entry}, 14458c2ecf20Sopenharmony_ci}; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci/* Create MODULE_ALIAS() statements. 14488c2ecf20Sopenharmony_ci * At this time, we cannot write the actual output C source yet, 14498c2ecf20Sopenharmony_ci * so we write into the mod->dev_table_buf buffer. */ 14508c2ecf20Sopenharmony_civoid handle_moddevtable(struct module *mod, struct elf_info *info, 14518c2ecf20Sopenharmony_ci Elf_Sym *sym, const char *symname) 14528c2ecf20Sopenharmony_ci{ 14538c2ecf20Sopenharmony_ci void *symval; 14548c2ecf20Sopenharmony_ci char *zeros = NULL; 14558c2ecf20Sopenharmony_ci const char *name, *identifier; 14568c2ecf20Sopenharmony_ci unsigned int namelen; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci /* We're looking for a section relative symbol */ 14598c2ecf20Sopenharmony_ci if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) 14608c2ecf20Sopenharmony_ci return; 14618c2ecf20Sopenharmony_ci 14628c2ecf20Sopenharmony_ci /* We're looking for an object */ 14638c2ecf20Sopenharmony_ci if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) 14648c2ecf20Sopenharmony_ci return; 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci /* All our symbols are of form __mod_<name>__<identifier>_device_table. */ 14678c2ecf20Sopenharmony_ci if (strncmp(symname, "__mod_", strlen("__mod_"))) 14688c2ecf20Sopenharmony_ci return; 14698c2ecf20Sopenharmony_ci name = symname + strlen("__mod_"); 14708c2ecf20Sopenharmony_ci namelen = strlen(name); 14718c2ecf20Sopenharmony_ci if (namelen < strlen("_device_table")) 14728c2ecf20Sopenharmony_ci return; 14738c2ecf20Sopenharmony_ci if (strcmp(name + namelen - strlen("_device_table"), "_device_table")) 14748c2ecf20Sopenharmony_ci return; 14758c2ecf20Sopenharmony_ci identifier = strstr(name, "__"); 14768c2ecf20Sopenharmony_ci if (!identifier) 14778c2ecf20Sopenharmony_ci return; 14788c2ecf20Sopenharmony_ci namelen = identifier - name; 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci /* Handle all-NULL symbols allocated into .bss */ 14818c2ecf20Sopenharmony_ci if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { 14828c2ecf20Sopenharmony_ci zeros = calloc(1, sym->st_size); 14838c2ecf20Sopenharmony_ci symval = zeros; 14848c2ecf20Sopenharmony_ci } else { 14858c2ecf20Sopenharmony_ci symval = (void *)info->hdr 14868c2ecf20Sopenharmony_ci + info->sechdrs[get_secindex(info, sym)].sh_offset 14878c2ecf20Sopenharmony_ci + sym->st_value; 14888c2ecf20Sopenharmony_ci } 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci /* First handle the "special" cases */ 14918c2ecf20Sopenharmony_ci if (sym_is(name, namelen, "usb")) 14928c2ecf20Sopenharmony_ci do_usb_table(symval, sym->st_size, mod); 14938c2ecf20Sopenharmony_ci else if (sym_is(name, namelen, "of")) 14948c2ecf20Sopenharmony_ci do_of_table(symval, sym->st_size, mod); 14958c2ecf20Sopenharmony_ci else if (sym_is(name, namelen, "pnp")) 14968c2ecf20Sopenharmony_ci do_pnp_device_entry(symval, sym->st_size, mod); 14978c2ecf20Sopenharmony_ci else if (sym_is(name, namelen, "pnp_card")) 14988c2ecf20Sopenharmony_ci do_pnp_card_entries(symval, sym->st_size, mod); 14998c2ecf20Sopenharmony_ci else { 15008c2ecf20Sopenharmony_ci int i; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(devtable); i++) { 15038c2ecf20Sopenharmony_ci const struct devtable *p = &devtable[i]; 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci if (sym_is(name, namelen, p->device_id)) { 15068c2ecf20Sopenharmony_ci do_table(symval, sym->st_size, p->id_size, 15078c2ecf20Sopenharmony_ci p->device_id, p->do_entry, mod); 15088c2ecf20Sopenharmony_ci break; 15098c2ecf20Sopenharmony_ci } 15108c2ecf20Sopenharmony_ci } 15118c2ecf20Sopenharmony_ci } 15128c2ecf20Sopenharmony_ci free(zeros); 15138c2ecf20Sopenharmony_ci} 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci/* Now add out buffered information to the generated C source */ 15168c2ecf20Sopenharmony_civoid add_moddevtable(struct buffer *buf, struct module *mod) 15178c2ecf20Sopenharmony_ci{ 15188c2ecf20Sopenharmony_ci buf_printf(buf, "\n"); 15198c2ecf20Sopenharmony_ci buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos); 15208c2ecf20Sopenharmony_ci free(mod->dev_table_buf.p); 15218c2ecf20Sopenharmony_ci} 1522