162306a36Sopenharmony_ci/* Simple code to turn various tables in an ELF file into alias definitions. 262306a36Sopenharmony_ci * This deals with kernel datastructures where they should be 362306a36Sopenharmony_ci * dealt with: in the kernel source. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright 2002-2003 Rusty Russell, IBM Corporation 662306a36Sopenharmony_ci * 2003 Kai Germaschewski 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * This software may be used and distributed according to the terms 1062306a36Sopenharmony_ci * of the GNU General Public License, incorporated herein by reference. 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include "modpost.h" 1462306a36Sopenharmony_ci#include "devicetable-offsets.h" 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* We use the ELF typedefs for kernel_ulong_t but bite the bullet and 1762306a36Sopenharmony_ci * use either stdint.h or inttypes.h for the rest. */ 1862306a36Sopenharmony_ci#if KERNEL_ELFCLASS == ELFCLASS32 1962306a36Sopenharmony_citypedef Elf32_Addr kernel_ulong_t; 2062306a36Sopenharmony_ci#define BITS_PER_LONG 32 2162306a36Sopenharmony_ci#else 2262306a36Sopenharmony_citypedef Elf64_Addr kernel_ulong_t; 2362306a36Sopenharmony_ci#define BITS_PER_LONG 64 2462306a36Sopenharmony_ci#endif 2562306a36Sopenharmony_ci#ifdef __sun__ 2662306a36Sopenharmony_ci#include <inttypes.h> 2762306a36Sopenharmony_ci#else 2862306a36Sopenharmony_ci#include <stdint.h> 2962306a36Sopenharmony_ci#endif 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include <ctype.h> 3262306a36Sopenharmony_ci#include <stdbool.h> 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_citypedef uint32_t __u32; 3562306a36Sopenharmony_citypedef uint16_t __u16; 3662306a36Sopenharmony_citypedef unsigned char __u8; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/* UUID types for backward compatibility, don't use in new code */ 3962306a36Sopenharmony_citypedef struct { 4062306a36Sopenharmony_ci __u8 b[16]; 4162306a36Sopenharmony_ci} guid_t; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_citypedef struct { 4462306a36Sopenharmony_ci __u8 b[16]; 4562306a36Sopenharmony_ci} uuid_t; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define UUID_STRING_LEN 36 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* MEI UUID type, don't use anywhere else */ 5062306a36Sopenharmony_citypedef struct { 5162306a36Sopenharmony_ci __u8 b[16]; 5262306a36Sopenharmony_ci} uuid_le; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* Big exception to the "don't include kernel headers into userspace, which 5562306a36Sopenharmony_ci * even potentially has different endianness and word sizes, since 5662306a36Sopenharmony_ci * we handle those differences explicitly below */ 5762306a36Sopenharmony_ci#include "../../include/linux/mod_devicetable.h" 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* This array collects all instances that use the generic do_table */ 6062306a36Sopenharmony_cistruct devtable { 6162306a36Sopenharmony_ci const char *device_id; /* name of table, __mod_<name>__*_device_table. */ 6262306a36Sopenharmony_ci unsigned long id_size; 6362306a36Sopenharmony_ci int (*do_entry)(const char *filename, void *symval, char *alias); 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* Size of alias provided to do_entry functions */ 6762306a36Sopenharmony_ci#define ALIAS_SIZE 500 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* Define a variable f that holds the value of field f of struct devid 7062306a36Sopenharmony_ci * based at address m. 7162306a36Sopenharmony_ci */ 7262306a36Sopenharmony_ci#define DEF_FIELD(m, devid, f) \ 7362306a36Sopenharmony_ci typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f)) 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci/* Define a variable v that holds the address of field f of struct devid 7662306a36Sopenharmony_ci * based at address m. Due to the way typeof works, for a field of type 7762306a36Sopenharmony_ci * T[N] the variable has type T(*)[N], _not_ T*. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci#define DEF_FIELD_ADDR_VAR(m, devid, f, v) \ 8062306a36Sopenharmony_ci typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f) 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/* Define a variable f that holds the address of field f of struct devid 8362306a36Sopenharmony_ci * based at address m. Due to the way typeof works, for a field of type 8462306a36Sopenharmony_ci * T[N] the variable has type T(*)[N], _not_ T*. 8562306a36Sopenharmony_ci */ 8662306a36Sopenharmony_ci#define DEF_FIELD_ADDR(m, devid, f) \ 8762306a36Sopenharmony_ci DEF_FIELD_ADDR_VAR(m, devid, f, f) 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#define ADD(str, sep, cond, field) \ 9062306a36Sopenharmony_cido { \ 9162306a36Sopenharmony_ci strcat(str, sep); \ 9262306a36Sopenharmony_ci if (cond) \ 9362306a36Sopenharmony_ci sprintf(str + strlen(str), \ 9462306a36Sopenharmony_ci sizeof(field) == 1 ? "%02X" : \ 9562306a36Sopenharmony_ci sizeof(field) == 2 ? "%04X" : \ 9662306a36Sopenharmony_ci sizeof(field) == 4 ? "%08X" : "", \ 9762306a36Sopenharmony_ci field); \ 9862306a36Sopenharmony_ci else \ 9962306a36Sopenharmony_ci sprintf(str + strlen(str), "*"); \ 10062306a36Sopenharmony_ci} while(0) 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* End in a wildcard, for future extension */ 10362306a36Sopenharmony_cistatic inline void add_wildcard(char *str) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci int len = strlen(str); 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (str[len - 1] != '*') 10862306a36Sopenharmony_ci strcat(str + len, "*"); 10962306a36Sopenharmony_ci} 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic inline void add_uuid(char *str, uuid_le uuid) 11262306a36Sopenharmony_ci{ 11362306a36Sopenharmony_ci int len = strlen(str); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 11662306a36Sopenharmony_ci uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0], 11762306a36Sopenharmony_ci uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6], 11862306a36Sopenharmony_ci uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11], 11962306a36Sopenharmony_ci uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]); 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic inline void add_guid(char *str, guid_t guid) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci int len = strlen(str); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci sprintf(str + len, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", 12762306a36Sopenharmony_ci guid.b[3], guid.b[2], guid.b[1], guid.b[0], 12862306a36Sopenharmony_ci guid.b[5], guid.b[4], guid.b[7], guid.b[6], 12962306a36Sopenharmony_ci guid.b[8], guid.b[9], guid.b[10], guid.b[11], 13062306a36Sopenharmony_ci guid.b[12], guid.b[13], guid.b[14], guid.b[15]); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/** 13462306a36Sopenharmony_ci * Check that sizeof(device_id type) are consistent with size of section 13562306a36Sopenharmony_ci * in .o file. If in-consistent then userspace and kernel does not agree 13662306a36Sopenharmony_ci * on actual size which is a bug. 13762306a36Sopenharmony_ci * Also verify that the final entry in the table is all zeros. 13862306a36Sopenharmony_ci * Ignore both checks if build host differ from target host and size differs. 13962306a36Sopenharmony_ci **/ 14062306a36Sopenharmony_cistatic void device_id_check(const char *modname, const char *device_id, 14162306a36Sopenharmony_ci unsigned long size, unsigned long id_size, 14262306a36Sopenharmony_ci void *symval) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci int i; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (size % id_size || size < id_size) { 14762306a36Sopenharmony_ci fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo of the size of section __mod_%s__<identifier>_device_table=%lu.\n" 14862306a36Sopenharmony_ci "Fix definition of struct %s_device_id in mod_devicetable.h\n", 14962306a36Sopenharmony_ci modname, device_id, id_size, device_id, size, device_id); 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci /* Verify last one is a terminator */ 15262306a36Sopenharmony_ci for (i = 0; i < id_size; i++ ) { 15362306a36Sopenharmony_ci if (*(uint8_t*)(symval+size-id_size+i)) { 15462306a36Sopenharmony_ci fprintf(stderr, 15562306a36Sopenharmony_ci "%s: struct %s_device_id is %lu bytes. The last of %lu is:\n", 15662306a36Sopenharmony_ci modname, device_id, id_size, size / id_size); 15762306a36Sopenharmony_ci for (i = 0; i < id_size; i++ ) 15862306a36Sopenharmony_ci fprintf(stderr,"0x%02x ", 15962306a36Sopenharmony_ci *(uint8_t*)(symval+size-id_size+i) ); 16062306a36Sopenharmony_ci fprintf(stderr,"\n"); 16162306a36Sopenharmony_ci fatal("%s: struct %s_device_id is not terminated with a NULL entry!\n", 16262306a36Sopenharmony_ci modname, device_id); 16362306a36Sopenharmony_ci } 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci/* USB is special because the bcdDevice can be matched against a numeric range */ 16862306a36Sopenharmony_ci/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */ 16962306a36Sopenharmony_cistatic void do_usb_entry(void *symval, 17062306a36Sopenharmony_ci unsigned int bcdDevice_initial, int bcdDevice_initial_digits, 17162306a36Sopenharmony_ci unsigned char range_lo, unsigned char range_hi, 17262306a36Sopenharmony_ci unsigned char max, struct module *mod) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci char alias[500]; 17562306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, match_flags); 17662306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, idVendor); 17762306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, idProduct); 17862306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bcdDevice_lo); 17962306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bDeviceClass); 18062306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bDeviceSubClass); 18162306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bDeviceProtocol); 18262306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceClass); 18362306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceSubClass); 18462306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceProtocol); 18562306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceNumber); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci strcpy(alias, "usb:"); 18862306a36Sopenharmony_ci ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR, 18962306a36Sopenharmony_ci idVendor); 19062306a36Sopenharmony_ci ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT, 19162306a36Sopenharmony_ci idProduct); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci strcat(alias, "d"); 19462306a36Sopenharmony_ci if (bcdDevice_initial_digits) 19562306a36Sopenharmony_ci sprintf(alias + strlen(alias), "%0*X", 19662306a36Sopenharmony_ci bcdDevice_initial_digits, bcdDevice_initial); 19762306a36Sopenharmony_ci if (range_lo == range_hi) 19862306a36Sopenharmony_ci sprintf(alias + strlen(alias), "%X", range_lo); 19962306a36Sopenharmony_ci else if (range_lo > 0 || range_hi < max) { 20062306a36Sopenharmony_ci if (range_lo > 0x9 || range_hi < 0xA) 20162306a36Sopenharmony_ci sprintf(alias + strlen(alias), 20262306a36Sopenharmony_ci "[%X-%X]", 20362306a36Sopenharmony_ci range_lo, 20462306a36Sopenharmony_ci range_hi); 20562306a36Sopenharmony_ci else { 20662306a36Sopenharmony_ci sprintf(alias + strlen(alias), 20762306a36Sopenharmony_ci range_lo < 0x9 ? "[%X-9" : "[%X", 20862306a36Sopenharmony_ci range_lo); 20962306a36Sopenharmony_ci sprintf(alias + strlen(alias), 21062306a36Sopenharmony_ci range_hi > 0xA ? "A-%X]" : "%X]", 21162306a36Sopenharmony_ci range_hi); 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1)) 21562306a36Sopenharmony_ci strcat(alias, "*"); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, 21862306a36Sopenharmony_ci bDeviceClass); 21962306a36Sopenharmony_ci ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS, 22062306a36Sopenharmony_ci bDeviceSubClass); 22162306a36Sopenharmony_ci ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL, 22262306a36Sopenharmony_ci bDeviceProtocol); 22362306a36Sopenharmony_ci ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS, 22462306a36Sopenharmony_ci bInterfaceClass); 22562306a36Sopenharmony_ci ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS, 22662306a36Sopenharmony_ci bInterfaceSubClass); 22762306a36Sopenharmony_ci ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, 22862306a36Sopenharmony_ci bInterfaceProtocol); 22962306a36Sopenharmony_ci ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER, 23062306a36Sopenharmony_ci bInterfaceNumber); 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci add_wildcard(alias); 23362306a36Sopenharmony_ci buf_printf(&mod->dev_table_buf, 23462306a36Sopenharmony_ci "MODULE_ALIAS(\"%s\");\n", alias); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/* Handles increment/decrement of BCD formatted integers */ 23862306a36Sopenharmony_ci/* Returns the previous value, so it works like i++ or i-- */ 23962306a36Sopenharmony_cistatic unsigned int incbcd(unsigned int *bcd, 24062306a36Sopenharmony_ci int inc, 24162306a36Sopenharmony_ci unsigned char max, 24262306a36Sopenharmony_ci size_t chars) 24362306a36Sopenharmony_ci{ 24462306a36Sopenharmony_ci unsigned int init = *bcd, i, j; 24562306a36Sopenharmony_ci unsigned long long c, dec = 0; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* If bcd is not in BCD format, just increment */ 24862306a36Sopenharmony_ci if (max > 0x9) { 24962306a36Sopenharmony_ci *bcd += inc; 25062306a36Sopenharmony_ci return init; 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci /* Convert BCD to Decimal */ 25462306a36Sopenharmony_ci for (i=0 ; i < chars ; i++) { 25562306a36Sopenharmony_ci c = (*bcd >> (i << 2)) & 0xf; 25662306a36Sopenharmony_ci c = c > 9 ? 9 : c; /* force to bcd just in case */ 25762306a36Sopenharmony_ci for (j=0 ; j < i ; j++) 25862306a36Sopenharmony_ci c = c * 10; 25962306a36Sopenharmony_ci dec += c; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Do our increment/decrement */ 26362306a36Sopenharmony_ci dec += inc; 26462306a36Sopenharmony_ci *bcd = 0; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* Convert back to BCD */ 26762306a36Sopenharmony_ci for (i=0 ; i < chars ; i++) { 26862306a36Sopenharmony_ci for (c=1,j=0 ; j < i ; j++) 26962306a36Sopenharmony_ci c = c * 10; 27062306a36Sopenharmony_ci c = (dec / c) % 10; 27162306a36Sopenharmony_ci *bcd += c << (i << 2); 27262306a36Sopenharmony_ci } 27362306a36Sopenharmony_ci return init; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic void do_usb_entry_multi(void *symval, struct module *mod) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci unsigned int devlo, devhi; 27962306a36Sopenharmony_ci unsigned char chi, clo, max; 28062306a36Sopenharmony_ci int ndigits; 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, match_flags); 28362306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, idVendor); 28462306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, idProduct); 28562306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bcdDevice_lo); 28662306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bcdDevice_hi); 28762306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bDeviceClass); 28862306a36Sopenharmony_ci DEF_FIELD(symval, usb_device_id, bInterfaceClass); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ? 29162306a36Sopenharmony_ci bcdDevice_lo : 0x0U; 29262306a36Sopenharmony_ci devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? 29362306a36Sopenharmony_ci bcdDevice_hi : ~0x0U; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* Figure out if this entry is in bcd or hex format */ 29662306a36Sopenharmony_ci max = 0x9; /* Default to decimal format */ 29762306a36Sopenharmony_ci for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) { 29862306a36Sopenharmony_ci clo = (devlo >> (ndigits << 2)) & 0xf; 29962306a36Sopenharmony_ci chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf; 30062306a36Sopenharmony_ci if (clo > max || chi > max) { 30162306a36Sopenharmony_ci max = 0xf; 30262306a36Sopenharmony_ci break; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci /* 30762306a36Sopenharmony_ci * Some modules (visor) have empty slots as placeholder for 30862306a36Sopenharmony_ci * run-time specification that results in catch-all alias 30962306a36Sopenharmony_ci */ 31062306a36Sopenharmony_ci if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass)) 31162306a36Sopenharmony_ci return; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */ 31462306a36Sopenharmony_ci for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { 31562306a36Sopenharmony_ci clo = devlo & 0xf; 31662306a36Sopenharmony_ci chi = devhi & 0xf; 31762306a36Sopenharmony_ci if (chi > max) /* If we are in bcd mode, truncate if necessary */ 31862306a36Sopenharmony_ci chi = max; 31962306a36Sopenharmony_ci devlo >>= 4; 32062306a36Sopenharmony_ci devhi >>= 4; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (devlo == devhi || !ndigits) { 32362306a36Sopenharmony_ci do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod); 32462306a36Sopenharmony_ci break; 32562306a36Sopenharmony_ci } 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (clo > 0x0) 32862306a36Sopenharmony_ci do_usb_entry(symval, 32962306a36Sopenharmony_ci incbcd(&devlo, 1, max, 33062306a36Sopenharmony_ci sizeof(bcdDevice_lo) * 2), 33162306a36Sopenharmony_ci ndigits, clo, max, max, mod); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (chi < max) 33462306a36Sopenharmony_ci do_usb_entry(symval, 33562306a36Sopenharmony_ci incbcd(&devhi, -1, max, 33662306a36Sopenharmony_ci sizeof(bcdDevice_lo) * 2), 33762306a36Sopenharmony_ci ndigits, 0x0, chi, max, mod); 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_cistatic void do_usb_table(void *symval, unsigned long size, 34262306a36Sopenharmony_ci struct module *mod) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci unsigned int i; 34562306a36Sopenharmony_ci const unsigned long id_size = SIZE_usb_device_id; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci device_id_check(mod->name, "usb", size, id_size, symval); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* Leave last one: it's the terminator. */ 35062306a36Sopenharmony_ci size -= id_size; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci for (i = 0; i < size; i += id_size) 35362306a36Sopenharmony_ci do_usb_entry_multi(symval + i, mod); 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic void do_of_entry_multi(void *symval, struct module *mod) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci char alias[500]; 35962306a36Sopenharmony_ci int len; 36062306a36Sopenharmony_ci char *tmp; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, of_device_id, name); 36362306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, of_device_id, type); 36462306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, of_device_id, compatible); 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*", 36762306a36Sopenharmony_ci (*type)[0] ? *type : "*"); 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if ((*compatible)[0]) 37062306a36Sopenharmony_ci sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "", 37162306a36Sopenharmony_ci *compatible); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci /* Replace all whitespace with underscores */ 37462306a36Sopenharmony_ci for (tmp = alias; tmp && *tmp; tmp++) 37562306a36Sopenharmony_ci if (isspace(*tmp)) 37662306a36Sopenharmony_ci *tmp = '_'; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias); 37962306a36Sopenharmony_ci strcat(alias, "C"); 38062306a36Sopenharmony_ci add_wildcard(alias); 38162306a36Sopenharmony_ci buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic void do_of_table(void *symval, unsigned long size, 38562306a36Sopenharmony_ci struct module *mod) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci unsigned int i; 38862306a36Sopenharmony_ci const unsigned long id_size = SIZE_of_device_id; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci device_id_check(mod->name, "of", size, id_size, symval); 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci /* Leave last one: it's the terminator. */ 39362306a36Sopenharmony_ci size -= id_size; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci for (i = 0; i < size; i += id_size) 39662306a36Sopenharmony_ci do_of_entry_multi(symval + i, mod); 39762306a36Sopenharmony_ci} 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci/* Looks like: hid:bNvNpN */ 40062306a36Sopenharmony_cistatic int do_hid_entry(const char *filename, 40162306a36Sopenharmony_ci void *symval, char *alias) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci DEF_FIELD(symval, hid_device_id, bus); 40462306a36Sopenharmony_ci DEF_FIELD(symval, hid_device_id, group); 40562306a36Sopenharmony_ci DEF_FIELD(symval, hid_device_id, vendor); 40662306a36Sopenharmony_ci DEF_FIELD(symval, hid_device_id, product); 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci sprintf(alias, "hid:"); 40962306a36Sopenharmony_ci ADD(alias, "b", bus != HID_BUS_ANY, bus); 41062306a36Sopenharmony_ci ADD(alias, "g", group != HID_GROUP_ANY, group); 41162306a36Sopenharmony_ci ADD(alias, "v", vendor != HID_ANY_ID, vendor); 41262306a36Sopenharmony_ci ADD(alias, "p", product != HID_ANY_ID, product); 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci return 1; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci/* Looks like: ieee1394:venNmoNspNverN */ 41862306a36Sopenharmony_cistatic int do_ieee1394_entry(const char *filename, 41962306a36Sopenharmony_ci void *symval, char *alias) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, match_flags); 42262306a36Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, vendor_id); 42362306a36Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, model_id); 42462306a36Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, specifier_id); 42562306a36Sopenharmony_ci DEF_FIELD(symval, ieee1394_device_id, version); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci strcpy(alias, "ieee1394:"); 42862306a36Sopenharmony_ci ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID, 42962306a36Sopenharmony_ci vendor_id); 43062306a36Sopenharmony_ci ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID, 43162306a36Sopenharmony_ci model_id); 43262306a36Sopenharmony_ci ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID, 43362306a36Sopenharmony_ci specifier_id); 43462306a36Sopenharmony_ci ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION, 43562306a36Sopenharmony_ci version); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci add_wildcard(alias); 43862306a36Sopenharmony_ci return 1; 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci/* Looks like: pci:vNdNsvNsdNbcNscNiN or <prefix>_pci:vNdNsvNsdNbcNscNiN. */ 44262306a36Sopenharmony_cistatic int do_pci_entry(const char *filename, 44362306a36Sopenharmony_ci void *symval, char *alias) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci /* Class field can be divided into these three. */ 44662306a36Sopenharmony_ci unsigned char baseclass, subclass, interface, 44762306a36Sopenharmony_ci baseclass_mask, subclass_mask, interface_mask; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci DEF_FIELD(symval, pci_device_id, vendor); 45062306a36Sopenharmony_ci DEF_FIELD(symval, pci_device_id, device); 45162306a36Sopenharmony_ci DEF_FIELD(symval, pci_device_id, subvendor); 45262306a36Sopenharmony_ci DEF_FIELD(symval, pci_device_id, subdevice); 45362306a36Sopenharmony_ci DEF_FIELD(symval, pci_device_id, class); 45462306a36Sopenharmony_ci DEF_FIELD(symval, pci_device_id, class_mask); 45562306a36Sopenharmony_ci DEF_FIELD(symval, pci_device_id, override_only); 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci switch (override_only) { 45862306a36Sopenharmony_ci case 0: 45962306a36Sopenharmony_ci strcpy(alias, "pci:"); 46062306a36Sopenharmony_ci break; 46162306a36Sopenharmony_ci case PCI_ID_F_VFIO_DRIVER_OVERRIDE: 46262306a36Sopenharmony_ci strcpy(alias, "vfio_pci:"); 46362306a36Sopenharmony_ci break; 46462306a36Sopenharmony_ci default: 46562306a36Sopenharmony_ci warn("Unknown PCI driver_override alias %08X\n", 46662306a36Sopenharmony_ci override_only); 46762306a36Sopenharmony_ci return 0; 46862306a36Sopenharmony_ci } 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci ADD(alias, "v", vendor != PCI_ANY_ID, vendor); 47162306a36Sopenharmony_ci ADD(alias, "d", device != PCI_ANY_ID, device); 47262306a36Sopenharmony_ci ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor); 47362306a36Sopenharmony_ci ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci baseclass = (class) >> 16; 47662306a36Sopenharmony_ci baseclass_mask = (class_mask) >> 16; 47762306a36Sopenharmony_ci subclass = (class) >> 8; 47862306a36Sopenharmony_ci subclass_mask = (class_mask) >> 8; 47962306a36Sopenharmony_ci interface = class; 48062306a36Sopenharmony_ci interface_mask = class_mask; 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci if ((baseclass_mask != 0 && baseclass_mask != 0xFF) 48362306a36Sopenharmony_ci || (subclass_mask != 0 && subclass_mask != 0xFF) 48462306a36Sopenharmony_ci || (interface_mask != 0 && interface_mask != 0xFF)) { 48562306a36Sopenharmony_ci warn("Can't handle masks in %s:%04X\n", 48662306a36Sopenharmony_ci filename, class_mask); 48762306a36Sopenharmony_ci return 0; 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci ADD(alias, "bc", baseclass_mask == 0xFF, baseclass); 49162306a36Sopenharmony_ci ADD(alias, "sc", subclass_mask == 0xFF, subclass); 49262306a36Sopenharmony_ci ADD(alias, "i", interface_mask == 0xFF, interface); 49362306a36Sopenharmony_ci add_wildcard(alias); 49462306a36Sopenharmony_ci return 1; 49562306a36Sopenharmony_ci} 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci/* looks like: "ccw:tNmNdtNdmN" */ 49862306a36Sopenharmony_cistatic int do_ccw_entry(const char *filename, 49962306a36Sopenharmony_ci void *symval, char *alias) 50062306a36Sopenharmony_ci{ 50162306a36Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, match_flags); 50262306a36Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, cu_type); 50362306a36Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, cu_model); 50462306a36Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, dev_type); 50562306a36Sopenharmony_ci DEF_FIELD(symval, ccw_device_id, dev_model); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci strcpy(alias, "ccw:"); 50862306a36Sopenharmony_ci ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE, 50962306a36Sopenharmony_ci cu_type); 51062306a36Sopenharmony_ci ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL, 51162306a36Sopenharmony_ci cu_model); 51262306a36Sopenharmony_ci ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE, 51362306a36Sopenharmony_ci dev_type); 51462306a36Sopenharmony_ci ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL, 51562306a36Sopenharmony_ci dev_model); 51662306a36Sopenharmony_ci add_wildcard(alias); 51762306a36Sopenharmony_ci return 1; 51862306a36Sopenharmony_ci} 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci/* looks like: "ap:tN" */ 52162306a36Sopenharmony_cistatic int do_ap_entry(const char *filename, 52262306a36Sopenharmony_ci void *symval, char *alias) 52362306a36Sopenharmony_ci{ 52462306a36Sopenharmony_ci DEF_FIELD(symval, ap_device_id, dev_type); 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci sprintf(alias, "ap:t%02X*", dev_type); 52762306a36Sopenharmony_ci return 1; 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci/* looks like: "css:tN" */ 53162306a36Sopenharmony_cistatic int do_css_entry(const char *filename, 53262306a36Sopenharmony_ci void *symval, char *alias) 53362306a36Sopenharmony_ci{ 53462306a36Sopenharmony_ci DEF_FIELD(symval, css_device_id, type); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci sprintf(alias, "css:t%01X", type); 53762306a36Sopenharmony_ci return 1; 53862306a36Sopenharmony_ci} 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci/* Looks like: "serio:tyNprNidNexN" */ 54162306a36Sopenharmony_cistatic int do_serio_entry(const char *filename, 54262306a36Sopenharmony_ci void *symval, char *alias) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci DEF_FIELD(symval, serio_device_id, type); 54562306a36Sopenharmony_ci DEF_FIELD(symval, serio_device_id, proto); 54662306a36Sopenharmony_ci DEF_FIELD(symval, serio_device_id, id); 54762306a36Sopenharmony_ci DEF_FIELD(symval, serio_device_id, extra); 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci strcpy(alias, "serio:"); 55062306a36Sopenharmony_ci ADD(alias, "ty", type != SERIO_ANY, type); 55162306a36Sopenharmony_ci ADD(alias, "pr", proto != SERIO_ANY, proto); 55262306a36Sopenharmony_ci ADD(alias, "id", id != SERIO_ANY, id); 55362306a36Sopenharmony_ci ADD(alias, "ex", extra != SERIO_ANY, extra); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci add_wildcard(alias); 55662306a36Sopenharmony_ci return 1; 55762306a36Sopenharmony_ci} 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci/* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or 56062306a36Sopenharmony_ci * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if) 56162306a36Sopenharmony_ci * 56262306a36Sopenharmony_ci * NOTE: Each driver should use one of the following : _HID, _CIDs 56362306a36Sopenharmony_ci * or _CLS. Also, bb, ss, and pp can be substituted with ?? 56462306a36Sopenharmony_ci * as don't care byte. 56562306a36Sopenharmony_ci */ 56662306a36Sopenharmony_cistatic int do_acpi_entry(const char *filename, 56762306a36Sopenharmony_ci void *symval, char *alias) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, acpi_device_id, id); 57062306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, acpi_device_id, cls); 57162306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, acpi_device_id, cls_msk); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci if (id && strlen((const char *)*id)) 57462306a36Sopenharmony_ci sprintf(alias, "acpi*:%s:*", *id); 57562306a36Sopenharmony_ci else if (cls) { 57662306a36Sopenharmony_ci int i, byte_shift, cnt = 0; 57762306a36Sopenharmony_ci unsigned int msk; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci sprintf(&alias[cnt], "acpi*:"); 58062306a36Sopenharmony_ci cnt = 6; 58162306a36Sopenharmony_ci for (i = 1; i <= 3; i++) { 58262306a36Sopenharmony_ci byte_shift = 8 * (3-i); 58362306a36Sopenharmony_ci msk = (*cls_msk >> byte_shift) & 0xFF; 58462306a36Sopenharmony_ci if (msk) 58562306a36Sopenharmony_ci sprintf(&alias[cnt], "%02x", 58662306a36Sopenharmony_ci (*cls >> byte_shift) & 0xFF); 58762306a36Sopenharmony_ci else 58862306a36Sopenharmony_ci sprintf(&alias[cnt], "??"); 58962306a36Sopenharmony_ci cnt += 2; 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci sprintf(&alias[cnt], ":*"); 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci return 1; 59462306a36Sopenharmony_ci} 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci/* looks like: "pnp:dD" */ 59762306a36Sopenharmony_cistatic void do_pnp_device_entry(void *symval, unsigned long size, 59862306a36Sopenharmony_ci struct module *mod) 59962306a36Sopenharmony_ci{ 60062306a36Sopenharmony_ci const unsigned long id_size = SIZE_pnp_device_id; 60162306a36Sopenharmony_ci const unsigned int count = (size / id_size)-1; 60262306a36Sopenharmony_ci unsigned int i; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci device_id_check(mod->name, "pnp", size, id_size, symval); 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci for (i = 0; i < count; i++) { 60762306a36Sopenharmony_ci DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id); 60862306a36Sopenharmony_ci char acpi_id[sizeof(*id)]; 60962306a36Sopenharmony_ci int j; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci buf_printf(&mod->dev_table_buf, 61262306a36Sopenharmony_ci "MODULE_ALIAS(\"pnp:d%s*\");\n", *id); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci /* fix broken pnp bus lowercasing */ 61562306a36Sopenharmony_ci for (j = 0; j < sizeof(acpi_id); j++) 61662306a36Sopenharmony_ci acpi_id[j] = toupper((*id)[j]); 61762306a36Sopenharmony_ci buf_printf(&mod->dev_table_buf, 61862306a36Sopenharmony_ci "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id); 61962306a36Sopenharmony_ci } 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci/* looks like: "pnp:dD" for every device of the card */ 62362306a36Sopenharmony_cistatic void do_pnp_card_entries(void *symval, unsigned long size, 62462306a36Sopenharmony_ci struct module *mod) 62562306a36Sopenharmony_ci{ 62662306a36Sopenharmony_ci const unsigned long id_size = SIZE_pnp_card_device_id; 62762306a36Sopenharmony_ci const unsigned int count = (size / id_size)-1; 62862306a36Sopenharmony_ci unsigned int i; 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci device_id_check(mod->name, "pnp", size, id_size, symval); 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci for (i = 0; i < count; i++) { 63362306a36Sopenharmony_ci unsigned int j; 63462306a36Sopenharmony_ci DEF_FIELD_ADDR(symval + i * id_size, pnp_card_device_id, devs); 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci for (j = 0; j < PNP_MAX_DEVICES; j++) { 63762306a36Sopenharmony_ci const char *id = (char *)(*devs)[j].id; 63862306a36Sopenharmony_ci int i2, j2; 63962306a36Sopenharmony_ci int dup = 0; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci if (!id[0]) 64262306a36Sopenharmony_ci break; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* find duplicate, already added value */ 64562306a36Sopenharmony_ci for (i2 = 0; i2 < i && !dup; i2++) { 64662306a36Sopenharmony_ci DEF_FIELD_ADDR_VAR(symval + i2 * id_size, 64762306a36Sopenharmony_ci pnp_card_device_id, 64862306a36Sopenharmony_ci devs, devs_dup); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) { 65162306a36Sopenharmony_ci const char *id2 = 65262306a36Sopenharmony_ci (char *)(*devs_dup)[j2].id; 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci if (!id2[0]) 65562306a36Sopenharmony_ci break; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci if (!strcmp(id, id2)) { 65862306a36Sopenharmony_ci dup = 1; 65962306a36Sopenharmony_ci break; 66062306a36Sopenharmony_ci } 66162306a36Sopenharmony_ci } 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /* add an individual alias for every device entry */ 66562306a36Sopenharmony_ci if (!dup) { 66662306a36Sopenharmony_ci char acpi_id[PNP_ID_LEN]; 66762306a36Sopenharmony_ci int k; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci buf_printf(&mod->dev_table_buf, 67062306a36Sopenharmony_ci "MODULE_ALIAS(\"pnp:d%s*\");\n", id); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci /* fix broken pnp bus lowercasing */ 67362306a36Sopenharmony_ci for (k = 0; k < sizeof(acpi_id); k++) 67462306a36Sopenharmony_ci acpi_id[k] = toupper(id[k]); 67562306a36Sopenharmony_ci buf_printf(&mod->dev_table_buf, 67662306a36Sopenharmony_ci "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id); 67762306a36Sopenharmony_ci } 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci/* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */ 68362306a36Sopenharmony_cistatic int do_pcmcia_entry(const char *filename, 68462306a36Sopenharmony_ci void *symval, char *alias) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci unsigned int i; 68762306a36Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, match_flags); 68862306a36Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, manf_id); 68962306a36Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, card_id); 69062306a36Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, func_id); 69162306a36Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, function); 69262306a36Sopenharmony_ci DEF_FIELD(symval, pcmcia_device_id, device_no); 69362306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash); 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci for (i=0; i<4; i++) { 69662306a36Sopenharmony_ci (*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]); 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci strcpy(alias, "pcmcia:"); 70062306a36Sopenharmony_ci ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID, 70162306a36Sopenharmony_ci manf_id); 70262306a36Sopenharmony_ci ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID, 70362306a36Sopenharmony_ci card_id); 70462306a36Sopenharmony_ci ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID, 70562306a36Sopenharmony_ci func_id); 70662306a36Sopenharmony_ci ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION, 70762306a36Sopenharmony_ci function); 70862306a36Sopenharmony_ci ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO, 70962306a36Sopenharmony_ci device_no); 71062306a36Sopenharmony_ci ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]); 71162306a36Sopenharmony_ci ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]); 71262306a36Sopenharmony_ci ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]); 71362306a36Sopenharmony_ci ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci add_wildcard(alias); 71662306a36Sopenharmony_ci return 1; 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_cistatic int do_vio_entry(const char *filename, void *symval, 72062306a36Sopenharmony_ci char *alias) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci char *tmp; 72362306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, vio_device_id, type); 72462306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, vio_device_id, compat); 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*", 72762306a36Sopenharmony_ci (*compat)[0] ? *compat : "*"); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* Replace all whitespace with underscores */ 73062306a36Sopenharmony_ci for (tmp = alias; tmp && *tmp; tmp++) 73162306a36Sopenharmony_ci if (isspace (*tmp)) 73262306a36Sopenharmony_ci *tmp = '_'; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci add_wildcard(alias); 73562306a36Sopenharmony_ci return 1; 73662306a36Sopenharmony_ci} 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cistatic void do_input(char *alias, 73962306a36Sopenharmony_ci kernel_ulong_t *arr, unsigned int min, unsigned int max) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci unsigned int i; 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++) 74462306a36Sopenharmony_ci arr[i] = TO_NATIVE(arr[i]); 74562306a36Sopenharmony_ci for (i = min; i < max; i++) 74662306a36Sopenharmony_ci if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) 74762306a36Sopenharmony_ci sprintf(alias + strlen(alias), "%X,*", i); 74862306a36Sopenharmony_ci} 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */ 75162306a36Sopenharmony_cistatic int do_input_entry(const char *filename, void *symval, 75262306a36Sopenharmony_ci char *alias) 75362306a36Sopenharmony_ci{ 75462306a36Sopenharmony_ci DEF_FIELD(symval, input_device_id, flags); 75562306a36Sopenharmony_ci DEF_FIELD(symval, input_device_id, bustype); 75662306a36Sopenharmony_ci DEF_FIELD(symval, input_device_id, vendor); 75762306a36Sopenharmony_ci DEF_FIELD(symval, input_device_id, product); 75862306a36Sopenharmony_ci DEF_FIELD(symval, input_device_id, version); 75962306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, evbit); 76062306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, keybit); 76162306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, relbit); 76262306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, absbit); 76362306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, mscbit); 76462306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, ledbit); 76562306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, sndbit); 76662306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, ffbit); 76762306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, input_device_id, swbit); 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci sprintf(alias, "input:"); 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype); 77262306a36Sopenharmony_ci ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor); 77362306a36Sopenharmony_ci ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product); 77462306a36Sopenharmony_ci ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version); 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci sprintf(alias + strlen(alias), "-e*"); 77762306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_EVBIT) 77862306a36Sopenharmony_ci do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX); 77962306a36Sopenharmony_ci sprintf(alias + strlen(alias), "k*"); 78062306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT) 78162306a36Sopenharmony_ci do_input(alias, *keybit, 78262306a36Sopenharmony_ci INPUT_DEVICE_ID_KEY_MIN_INTERESTING, 78362306a36Sopenharmony_ci INPUT_DEVICE_ID_KEY_MAX); 78462306a36Sopenharmony_ci sprintf(alias + strlen(alias), "r*"); 78562306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_RELBIT) 78662306a36Sopenharmony_ci do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX); 78762306a36Sopenharmony_ci sprintf(alias + strlen(alias), "a*"); 78862306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT) 78962306a36Sopenharmony_ci do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX); 79062306a36Sopenharmony_ci sprintf(alias + strlen(alias), "m*"); 79162306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_MSCIT) 79262306a36Sopenharmony_ci do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX); 79362306a36Sopenharmony_ci sprintf(alias + strlen(alias), "l*"); 79462306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT) 79562306a36Sopenharmony_ci do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX); 79662306a36Sopenharmony_ci sprintf(alias + strlen(alias), "s*"); 79762306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT) 79862306a36Sopenharmony_ci do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX); 79962306a36Sopenharmony_ci sprintf(alias + strlen(alias), "f*"); 80062306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_FFBIT) 80162306a36Sopenharmony_ci do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX); 80262306a36Sopenharmony_ci sprintf(alias + strlen(alias), "w*"); 80362306a36Sopenharmony_ci if (flags & INPUT_DEVICE_ID_MATCH_SWBIT) 80462306a36Sopenharmony_ci do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX); 80562306a36Sopenharmony_ci return 1; 80662306a36Sopenharmony_ci} 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_cistatic int do_eisa_entry(const char *filename, void *symval, 80962306a36Sopenharmony_ci char *alias) 81062306a36Sopenharmony_ci{ 81162306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, eisa_device_id, sig); 81262306a36Sopenharmony_ci if (sig[0]) 81362306a36Sopenharmony_ci sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig); 81462306a36Sopenharmony_ci else 81562306a36Sopenharmony_ci strcat(alias, "*"); 81662306a36Sopenharmony_ci return 1; 81762306a36Sopenharmony_ci} 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci/* Looks like: parisc:tNhvNrevNsvN */ 82062306a36Sopenharmony_cistatic int do_parisc_entry(const char *filename, void *symval, 82162306a36Sopenharmony_ci char *alias) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci DEF_FIELD(symval, parisc_device_id, hw_type); 82462306a36Sopenharmony_ci DEF_FIELD(symval, parisc_device_id, hversion); 82562306a36Sopenharmony_ci DEF_FIELD(symval, parisc_device_id, hversion_rev); 82662306a36Sopenharmony_ci DEF_FIELD(symval, parisc_device_id, sversion); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci strcpy(alias, "parisc:"); 82962306a36Sopenharmony_ci ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type); 83062306a36Sopenharmony_ci ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion); 83162306a36Sopenharmony_ci ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev); 83262306a36Sopenharmony_ci ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci add_wildcard(alias); 83562306a36Sopenharmony_ci return 1; 83662306a36Sopenharmony_ci} 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_ci/* Looks like: sdio:cNvNdN. */ 83962306a36Sopenharmony_cistatic int do_sdio_entry(const char *filename, 84062306a36Sopenharmony_ci void *symval, char *alias) 84162306a36Sopenharmony_ci{ 84262306a36Sopenharmony_ci DEF_FIELD(symval, sdio_device_id, class); 84362306a36Sopenharmony_ci DEF_FIELD(symval, sdio_device_id, vendor); 84462306a36Sopenharmony_ci DEF_FIELD(symval, sdio_device_id, device); 84562306a36Sopenharmony_ci 84662306a36Sopenharmony_ci strcpy(alias, "sdio:"); 84762306a36Sopenharmony_ci ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class); 84862306a36Sopenharmony_ci ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor); 84962306a36Sopenharmony_ci ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device); 85062306a36Sopenharmony_ci add_wildcard(alias); 85162306a36Sopenharmony_ci return 1; 85262306a36Sopenharmony_ci} 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci/* Looks like: ssb:vNidNrevN. */ 85562306a36Sopenharmony_cistatic int do_ssb_entry(const char *filename, 85662306a36Sopenharmony_ci void *symval, char *alias) 85762306a36Sopenharmony_ci{ 85862306a36Sopenharmony_ci DEF_FIELD(symval, ssb_device_id, vendor); 85962306a36Sopenharmony_ci DEF_FIELD(symval, ssb_device_id, coreid); 86062306a36Sopenharmony_ci DEF_FIELD(symval, ssb_device_id, revision); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci strcpy(alias, "ssb:"); 86362306a36Sopenharmony_ci ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor); 86462306a36Sopenharmony_ci ADD(alias, "id", coreid != SSB_ANY_ID, coreid); 86562306a36Sopenharmony_ci ADD(alias, "rev", revision != SSB_ANY_REV, revision); 86662306a36Sopenharmony_ci add_wildcard(alias); 86762306a36Sopenharmony_ci return 1; 86862306a36Sopenharmony_ci} 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci/* Looks like: bcma:mNidNrevNclN. */ 87162306a36Sopenharmony_cistatic int do_bcma_entry(const char *filename, 87262306a36Sopenharmony_ci void *symval, char *alias) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci DEF_FIELD(symval, bcma_device_id, manuf); 87562306a36Sopenharmony_ci DEF_FIELD(symval, bcma_device_id, id); 87662306a36Sopenharmony_ci DEF_FIELD(symval, bcma_device_id, rev); 87762306a36Sopenharmony_ci DEF_FIELD(symval, bcma_device_id, class); 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci strcpy(alias, "bcma:"); 88062306a36Sopenharmony_ci ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf); 88162306a36Sopenharmony_ci ADD(alias, "id", id != BCMA_ANY_ID, id); 88262306a36Sopenharmony_ci ADD(alias, "rev", rev != BCMA_ANY_REV, rev); 88362306a36Sopenharmony_ci ADD(alias, "cl", class != BCMA_ANY_CLASS, class); 88462306a36Sopenharmony_ci add_wildcard(alias); 88562306a36Sopenharmony_ci return 1; 88662306a36Sopenharmony_ci} 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci/* Looks like: virtio:dNvN */ 88962306a36Sopenharmony_cistatic int do_virtio_entry(const char *filename, void *symval, 89062306a36Sopenharmony_ci char *alias) 89162306a36Sopenharmony_ci{ 89262306a36Sopenharmony_ci DEF_FIELD(symval, virtio_device_id, device); 89362306a36Sopenharmony_ci DEF_FIELD(symval, virtio_device_id, vendor); 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci strcpy(alias, "virtio:"); 89662306a36Sopenharmony_ci ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device); 89762306a36Sopenharmony_ci ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci add_wildcard(alias); 90062306a36Sopenharmony_ci return 1; 90162306a36Sopenharmony_ci} 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci/* 90462306a36Sopenharmony_ci * Looks like: vmbus:guid 90562306a36Sopenharmony_ci * Each byte of the guid will be represented by two hex characters 90662306a36Sopenharmony_ci * in the name. 90762306a36Sopenharmony_ci */ 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_cistatic int do_vmbus_entry(const char *filename, void *symval, 91062306a36Sopenharmony_ci char *alias) 91162306a36Sopenharmony_ci{ 91262306a36Sopenharmony_ci int i; 91362306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid); 91462306a36Sopenharmony_ci char guid_name[(sizeof(*guid) + 1) * 2]; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci for (i = 0; i < (sizeof(*guid) * 2); i += 2) 91762306a36Sopenharmony_ci sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2])); 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_ci strcpy(alias, "vmbus:"); 92062306a36Sopenharmony_ci strcat(alias, guid_name); 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci return 1; 92362306a36Sopenharmony_ci} 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci/* Looks like: rpmsg:S */ 92662306a36Sopenharmony_cistatic int do_rpmsg_entry(const char *filename, void *symval, 92762306a36Sopenharmony_ci char *alias) 92862306a36Sopenharmony_ci{ 92962306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, rpmsg_device_id, name); 93062306a36Sopenharmony_ci sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name); 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci return 1; 93362306a36Sopenharmony_ci} 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci/* Looks like: i2c:S */ 93662306a36Sopenharmony_cistatic int do_i2c_entry(const char *filename, void *symval, 93762306a36Sopenharmony_ci char *alias) 93862306a36Sopenharmony_ci{ 93962306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, i2c_device_id, name); 94062306a36Sopenharmony_ci sprintf(alias, I2C_MODULE_PREFIX "%s", *name); 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci return 1; 94362306a36Sopenharmony_ci} 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_cistatic int do_i3c_entry(const char *filename, void *symval, 94662306a36Sopenharmony_ci char *alias) 94762306a36Sopenharmony_ci{ 94862306a36Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, match_flags); 94962306a36Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, dcr); 95062306a36Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, manuf_id); 95162306a36Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, part_id); 95262306a36Sopenharmony_ci DEF_FIELD(symval, i3c_device_id, extra_info); 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci strcpy(alias, "i3c:"); 95562306a36Sopenharmony_ci ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr); 95662306a36Sopenharmony_ci ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id); 95762306a36Sopenharmony_ci ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id); 95862306a36Sopenharmony_ci ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci return 1; 96162306a36Sopenharmony_ci} 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci/* Looks like: spi:S */ 96462306a36Sopenharmony_cistatic int do_spi_entry(const char *filename, void *symval, 96562306a36Sopenharmony_ci char *alias) 96662306a36Sopenharmony_ci{ 96762306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, spi_device_id, name); 96862306a36Sopenharmony_ci sprintf(alias, SPI_MODULE_PREFIX "%s", *name); 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci return 1; 97162306a36Sopenharmony_ci} 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_cistatic const struct dmifield { 97462306a36Sopenharmony_ci const char *prefix; 97562306a36Sopenharmony_ci int field; 97662306a36Sopenharmony_ci} dmi_fields[] = { 97762306a36Sopenharmony_ci { "bvn", DMI_BIOS_VENDOR }, 97862306a36Sopenharmony_ci { "bvr", DMI_BIOS_VERSION }, 97962306a36Sopenharmony_ci { "bd", DMI_BIOS_DATE }, 98062306a36Sopenharmony_ci { "br", DMI_BIOS_RELEASE }, 98162306a36Sopenharmony_ci { "efr", DMI_EC_FIRMWARE_RELEASE }, 98262306a36Sopenharmony_ci { "svn", DMI_SYS_VENDOR }, 98362306a36Sopenharmony_ci { "pn", DMI_PRODUCT_NAME }, 98462306a36Sopenharmony_ci { "pvr", DMI_PRODUCT_VERSION }, 98562306a36Sopenharmony_ci { "rvn", DMI_BOARD_VENDOR }, 98662306a36Sopenharmony_ci { "rn", DMI_BOARD_NAME }, 98762306a36Sopenharmony_ci { "rvr", DMI_BOARD_VERSION }, 98862306a36Sopenharmony_ci { "cvn", DMI_CHASSIS_VENDOR }, 98962306a36Sopenharmony_ci { "ct", DMI_CHASSIS_TYPE }, 99062306a36Sopenharmony_ci { "cvr", DMI_CHASSIS_VERSION }, 99162306a36Sopenharmony_ci { NULL, DMI_NONE } 99262306a36Sopenharmony_ci}; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_cistatic void dmi_ascii_filter(char *d, const char *s) 99562306a36Sopenharmony_ci{ 99662306a36Sopenharmony_ci /* Filter out characters we don't want to see in the modalias string */ 99762306a36Sopenharmony_ci for (; *s; s++) 99862306a36Sopenharmony_ci if (*s > ' ' && *s < 127 && *s != ':') 99962306a36Sopenharmony_ci *(d++) = *s; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci *d = 0; 100262306a36Sopenharmony_ci} 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_cistatic int do_dmi_entry(const char *filename, void *symval, 100662306a36Sopenharmony_ci char *alias) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci int i, j; 100962306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, dmi_system_id, matches); 101062306a36Sopenharmony_ci sprintf(alias, "dmi*"); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) { 101362306a36Sopenharmony_ci for (j = 0; j < 4; j++) { 101462306a36Sopenharmony_ci if ((*matches)[j].slot && 101562306a36Sopenharmony_ci (*matches)[j].slot == dmi_fields[i].field) { 101662306a36Sopenharmony_ci sprintf(alias + strlen(alias), ":%s*", 101762306a36Sopenharmony_ci dmi_fields[i].prefix); 101862306a36Sopenharmony_ci dmi_ascii_filter(alias + strlen(alias), 101962306a36Sopenharmony_ci (*matches)[j].substr); 102062306a36Sopenharmony_ci strcat(alias, "*"); 102162306a36Sopenharmony_ci } 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci } 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci strcat(alias, ":"); 102662306a36Sopenharmony_ci return 1; 102762306a36Sopenharmony_ci} 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_cistatic int do_platform_entry(const char *filename, 103062306a36Sopenharmony_ci void *symval, char *alias) 103162306a36Sopenharmony_ci{ 103262306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, platform_device_id, name); 103362306a36Sopenharmony_ci sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name); 103462306a36Sopenharmony_ci return 1; 103562306a36Sopenharmony_ci} 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_cistatic int do_mdio_entry(const char *filename, 103862306a36Sopenharmony_ci void *symval, char *alias) 103962306a36Sopenharmony_ci{ 104062306a36Sopenharmony_ci int i; 104162306a36Sopenharmony_ci DEF_FIELD(symval, mdio_device_id, phy_id); 104262306a36Sopenharmony_ci DEF_FIELD(symval, mdio_device_id, phy_id_mask); 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci alias += sprintf(alias, MDIO_MODULE_PREFIX); 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci for (i = 0; i < 32; i++) { 104762306a36Sopenharmony_ci if (!((phy_id_mask >> (31-i)) & 1)) 104862306a36Sopenharmony_ci *(alias++) = '?'; 104962306a36Sopenharmony_ci else if ((phy_id >> (31-i)) & 1) 105062306a36Sopenharmony_ci *(alias++) = '1'; 105162306a36Sopenharmony_ci else 105262306a36Sopenharmony_ci *(alias++) = '0'; 105362306a36Sopenharmony_ci } 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci /* Terminate the string */ 105662306a36Sopenharmony_ci *alias = 0; 105762306a36Sopenharmony_ci 105862306a36Sopenharmony_ci return 1; 105962306a36Sopenharmony_ci} 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci/* Looks like: zorro:iN. */ 106262306a36Sopenharmony_cistatic int do_zorro_entry(const char *filename, void *symval, 106362306a36Sopenharmony_ci char *alias) 106462306a36Sopenharmony_ci{ 106562306a36Sopenharmony_ci DEF_FIELD(symval, zorro_device_id, id); 106662306a36Sopenharmony_ci strcpy(alias, "zorro:"); 106762306a36Sopenharmony_ci ADD(alias, "i", id != ZORRO_WILDCARD, id); 106862306a36Sopenharmony_ci return 1; 106962306a36Sopenharmony_ci} 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci/* looks like: "pnp:dD" */ 107262306a36Sopenharmony_cistatic int do_isapnp_entry(const char *filename, 107362306a36Sopenharmony_ci void *symval, char *alias) 107462306a36Sopenharmony_ci{ 107562306a36Sopenharmony_ci DEF_FIELD(symval, isapnp_device_id, vendor); 107662306a36Sopenharmony_ci DEF_FIELD(symval, isapnp_device_id, function); 107762306a36Sopenharmony_ci sprintf(alias, "pnp:d%c%c%c%x%x%x%x*", 107862306a36Sopenharmony_ci 'A' + ((vendor >> 2) & 0x3f) - 1, 107962306a36Sopenharmony_ci 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, 108062306a36Sopenharmony_ci 'A' + ((vendor >> 8) & 0x1f) - 1, 108162306a36Sopenharmony_ci (function >> 4) & 0x0f, function & 0x0f, 108262306a36Sopenharmony_ci (function >> 12) & 0x0f, (function >> 8) & 0x0f); 108362306a36Sopenharmony_ci return 1; 108462306a36Sopenharmony_ci} 108562306a36Sopenharmony_ci 108662306a36Sopenharmony_ci/* Looks like: "ipack:fNvNdN". */ 108762306a36Sopenharmony_cistatic int do_ipack_entry(const char *filename, 108862306a36Sopenharmony_ci void *symval, char *alias) 108962306a36Sopenharmony_ci{ 109062306a36Sopenharmony_ci DEF_FIELD(symval, ipack_device_id, format); 109162306a36Sopenharmony_ci DEF_FIELD(symval, ipack_device_id, vendor); 109262306a36Sopenharmony_ci DEF_FIELD(symval, ipack_device_id, device); 109362306a36Sopenharmony_ci strcpy(alias, "ipack:"); 109462306a36Sopenharmony_ci ADD(alias, "f", format != IPACK_ANY_FORMAT, format); 109562306a36Sopenharmony_ci ADD(alias, "v", vendor != IPACK_ANY_ID, vendor); 109662306a36Sopenharmony_ci ADD(alias, "d", device != IPACK_ANY_ID, device); 109762306a36Sopenharmony_ci add_wildcard(alias); 109862306a36Sopenharmony_ci return 1; 109962306a36Sopenharmony_ci} 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci/* 110262306a36Sopenharmony_ci * Append a match expression for a single masked hex digit. 110362306a36Sopenharmony_ci * outp points to a pointer to the character at which to append. 110462306a36Sopenharmony_ci * *outp is updated on return to point just after the appended text, 110562306a36Sopenharmony_ci * to facilitate further appending. 110662306a36Sopenharmony_ci */ 110762306a36Sopenharmony_cistatic void append_nibble_mask(char **outp, 110862306a36Sopenharmony_ci unsigned int nibble, unsigned int mask) 110962306a36Sopenharmony_ci{ 111062306a36Sopenharmony_ci char *p = *outp; 111162306a36Sopenharmony_ci unsigned int i; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci switch (mask) { 111462306a36Sopenharmony_ci case 0: 111562306a36Sopenharmony_ci *p++ = '?'; 111662306a36Sopenharmony_ci break; 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci case 0xf: 111962306a36Sopenharmony_ci p += sprintf(p, "%X", nibble); 112062306a36Sopenharmony_ci break; 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci default: 112362306a36Sopenharmony_ci /* 112462306a36Sopenharmony_ci * Dumbly emit a match pattern for all possible matching 112562306a36Sopenharmony_ci * digits. This could be improved in some cases using ranges, 112662306a36Sopenharmony_ci * but it has the advantage of being trivially correct, and is 112762306a36Sopenharmony_ci * often optimal. 112862306a36Sopenharmony_ci */ 112962306a36Sopenharmony_ci *p++ = '['; 113062306a36Sopenharmony_ci for (i = 0; i < 0x10; i++) 113162306a36Sopenharmony_ci if ((i & mask) == nibble) 113262306a36Sopenharmony_ci p += sprintf(p, "%X", i); 113362306a36Sopenharmony_ci *p++ = ']'; 113462306a36Sopenharmony_ci } 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci /* Ensure that the string remains NUL-terminated: */ 113762306a36Sopenharmony_ci *p = '\0'; 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_ci /* Advance the caller's end-of-string pointer: */ 114062306a36Sopenharmony_ci *outp = p; 114162306a36Sopenharmony_ci} 114262306a36Sopenharmony_ci 114362306a36Sopenharmony_ci/* 114462306a36Sopenharmony_ci * looks like: "amba:dN" 114562306a36Sopenharmony_ci * 114662306a36Sopenharmony_ci * N is exactly 8 digits, where each is an upper-case hex digit, or 114762306a36Sopenharmony_ci * a ? or [] pattern matching exactly one digit. 114862306a36Sopenharmony_ci */ 114962306a36Sopenharmony_cistatic int do_amba_entry(const char *filename, 115062306a36Sopenharmony_ci void *symval, char *alias) 115162306a36Sopenharmony_ci{ 115262306a36Sopenharmony_ci unsigned int digit; 115362306a36Sopenharmony_ci char *p = alias; 115462306a36Sopenharmony_ci DEF_FIELD(symval, amba_id, id); 115562306a36Sopenharmony_ci DEF_FIELD(symval, amba_id, mask); 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ci if ((id & mask) != id) 115862306a36Sopenharmony_ci fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: id=0x%08X, mask=0x%08X. Please fix this driver.\n", 115962306a36Sopenharmony_ci filename, id, mask); 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci p += sprintf(alias, "amba:d"); 116262306a36Sopenharmony_ci for (digit = 0; digit < 8; digit++) 116362306a36Sopenharmony_ci append_nibble_mask(&p, 116462306a36Sopenharmony_ci (id >> (4 * (7 - digit))) & 0xf, 116562306a36Sopenharmony_ci (mask >> (4 * (7 - digit))) & 0xf); 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci return 1; 116862306a36Sopenharmony_ci} 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci/* 117162306a36Sopenharmony_ci * looks like: "mipscdmm:tN" 117262306a36Sopenharmony_ci * 117362306a36Sopenharmony_ci * N is exactly 2 digits, where each is an upper-case hex digit, or 117462306a36Sopenharmony_ci * a ? or [] pattern matching exactly one digit. 117562306a36Sopenharmony_ci */ 117662306a36Sopenharmony_cistatic int do_mips_cdmm_entry(const char *filename, 117762306a36Sopenharmony_ci void *symval, char *alias) 117862306a36Sopenharmony_ci{ 117962306a36Sopenharmony_ci DEF_FIELD(symval, mips_cdmm_device_id, type); 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci sprintf(alias, "mipscdmm:t%02X*", type); 118262306a36Sopenharmony_ci return 1; 118362306a36Sopenharmony_ci} 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,* 118662306a36Sopenharmony_ci * All fields are numbers. It would be nicer to use strings for vendor 118762306a36Sopenharmony_ci * and feature, but getting those out of the build system here is too 118862306a36Sopenharmony_ci * complicated. 118962306a36Sopenharmony_ci */ 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_cistatic int do_x86cpu_entry(const char *filename, void *symval, 119262306a36Sopenharmony_ci char *alias) 119362306a36Sopenharmony_ci{ 119462306a36Sopenharmony_ci DEF_FIELD(symval, x86_cpu_id, feature); 119562306a36Sopenharmony_ci DEF_FIELD(symval, x86_cpu_id, family); 119662306a36Sopenharmony_ci DEF_FIELD(symval, x86_cpu_id, model); 119762306a36Sopenharmony_ci DEF_FIELD(symval, x86_cpu_id, vendor); 119862306a36Sopenharmony_ci 119962306a36Sopenharmony_ci strcpy(alias, "cpu:type:x86,"); 120062306a36Sopenharmony_ci ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor); 120162306a36Sopenharmony_ci ADD(alias, "fam", family != X86_FAMILY_ANY, family); 120262306a36Sopenharmony_ci ADD(alias, "mod", model != X86_MODEL_ANY, model); 120362306a36Sopenharmony_ci strcat(alias, ":feature:*"); 120462306a36Sopenharmony_ci if (feature != X86_FEATURE_ANY) 120562306a36Sopenharmony_ci sprintf(alias + strlen(alias), "%04X*", feature); 120662306a36Sopenharmony_ci return 1; 120762306a36Sopenharmony_ci} 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci/* LOOKS like cpu:type:*:feature:*FEAT* */ 121062306a36Sopenharmony_cistatic int do_cpu_entry(const char *filename, void *symval, char *alias) 121162306a36Sopenharmony_ci{ 121262306a36Sopenharmony_ci DEF_FIELD(symval, cpu_feature, feature); 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci sprintf(alias, "cpu:type:*:feature:*%04X*", feature); 121562306a36Sopenharmony_ci return 1; 121662306a36Sopenharmony_ci} 121762306a36Sopenharmony_ci 121862306a36Sopenharmony_ci/* Looks like: mei:S:uuid:N:* */ 121962306a36Sopenharmony_cistatic int do_mei_entry(const char *filename, void *symval, 122062306a36Sopenharmony_ci char *alias) 122162306a36Sopenharmony_ci{ 122262306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, mei_cl_device_id, name); 122362306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid); 122462306a36Sopenharmony_ci DEF_FIELD(symval, mei_cl_device_id, version); 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci sprintf(alias, MEI_CL_MODULE_PREFIX); 122762306a36Sopenharmony_ci sprintf(alias + strlen(alias), "%s:", (*name)[0] ? *name : "*"); 122862306a36Sopenharmony_ci add_uuid(alias, *uuid); 122962306a36Sopenharmony_ci ADD(alias, ":", version != MEI_CL_VERSION_ANY, version); 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci strcat(alias, ":*"); 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci return 1; 123462306a36Sopenharmony_ci} 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci/* Looks like: rapidio:vNdNavNadN */ 123762306a36Sopenharmony_cistatic int do_rio_entry(const char *filename, 123862306a36Sopenharmony_ci void *symval, char *alias) 123962306a36Sopenharmony_ci{ 124062306a36Sopenharmony_ci DEF_FIELD(symval, rio_device_id, did); 124162306a36Sopenharmony_ci DEF_FIELD(symval, rio_device_id, vid); 124262306a36Sopenharmony_ci DEF_FIELD(symval, rio_device_id, asm_did); 124362306a36Sopenharmony_ci DEF_FIELD(symval, rio_device_id, asm_vid); 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci strcpy(alias, "rapidio:"); 124662306a36Sopenharmony_ci ADD(alias, "v", vid != RIO_ANY_ID, vid); 124762306a36Sopenharmony_ci ADD(alias, "d", did != RIO_ANY_ID, did); 124862306a36Sopenharmony_ci ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid); 124962306a36Sopenharmony_ci ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci add_wildcard(alias); 125262306a36Sopenharmony_ci return 1; 125362306a36Sopenharmony_ci} 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci/* Looks like: ulpi:vNpN */ 125662306a36Sopenharmony_cistatic int do_ulpi_entry(const char *filename, void *symval, 125762306a36Sopenharmony_ci char *alias) 125862306a36Sopenharmony_ci{ 125962306a36Sopenharmony_ci DEF_FIELD(symval, ulpi_device_id, vendor); 126062306a36Sopenharmony_ci DEF_FIELD(symval, ulpi_device_id, product); 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci sprintf(alias, "ulpi:v%04xp%04x", vendor, product); 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci return 1; 126562306a36Sopenharmony_ci} 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci/* Looks like: hdaudio:vNrNaN */ 126862306a36Sopenharmony_cistatic int do_hda_entry(const char *filename, void *symval, char *alias) 126962306a36Sopenharmony_ci{ 127062306a36Sopenharmony_ci DEF_FIELD(symval, hda_device_id, vendor_id); 127162306a36Sopenharmony_ci DEF_FIELD(symval, hda_device_id, rev_id); 127262306a36Sopenharmony_ci DEF_FIELD(symval, hda_device_id, api_version); 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci strcpy(alias, "hdaudio:"); 127562306a36Sopenharmony_ci ADD(alias, "v", vendor_id != 0, vendor_id); 127662306a36Sopenharmony_ci ADD(alias, "r", rev_id != 0, rev_id); 127762306a36Sopenharmony_ci ADD(alias, "a", api_version != 0, api_version); 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci add_wildcard(alias); 128062306a36Sopenharmony_ci return 1; 128162306a36Sopenharmony_ci} 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci/* Looks like: sdw:mNpNvNcN */ 128462306a36Sopenharmony_cistatic int do_sdw_entry(const char *filename, void *symval, char *alias) 128562306a36Sopenharmony_ci{ 128662306a36Sopenharmony_ci DEF_FIELD(symval, sdw_device_id, mfg_id); 128762306a36Sopenharmony_ci DEF_FIELD(symval, sdw_device_id, part_id); 128862306a36Sopenharmony_ci DEF_FIELD(symval, sdw_device_id, sdw_version); 128962306a36Sopenharmony_ci DEF_FIELD(symval, sdw_device_id, class_id); 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci strcpy(alias, "sdw:"); 129262306a36Sopenharmony_ci ADD(alias, "m", mfg_id != 0, mfg_id); 129362306a36Sopenharmony_ci ADD(alias, "p", part_id != 0, part_id); 129462306a36Sopenharmony_ci ADD(alias, "v", sdw_version != 0, sdw_version); 129562306a36Sopenharmony_ci ADD(alias, "c", class_id != 0, class_id); 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci add_wildcard(alias); 129862306a36Sopenharmony_ci return 1; 129962306a36Sopenharmony_ci} 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci/* Looks like: fsl-mc:vNdN */ 130262306a36Sopenharmony_cistatic int do_fsl_mc_entry(const char *filename, void *symval, 130362306a36Sopenharmony_ci char *alias) 130462306a36Sopenharmony_ci{ 130562306a36Sopenharmony_ci DEF_FIELD(symval, fsl_mc_device_id, vendor); 130662306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type); 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type); 130962306a36Sopenharmony_ci return 1; 131062306a36Sopenharmony_ci} 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci/* Looks like: tbsvc:kSpNvNrN */ 131362306a36Sopenharmony_cistatic int do_tbsvc_entry(const char *filename, void *symval, char *alias) 131462306a36Sopenharmony_ci{ 131562306a36Sopenharmony_ci DEF_FIELD(symval, tb_service_id, match_flags); 131662306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, tb_service_id, protocol_key); 131762306a36Sopenharmony_ci DEF_FIELD(symval, tb_service_id, protocol_id); 131862306a36Sopenharmony_ci DEF_FIELD(symval, tb_service_id, protocol_version); 131962306a36Sopenharmony_ci DEF_FIELD(symval, tb_service_id, protocol_revision); 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci strcpy(alias, "tbsvc:"); 132262306a36Sopenharmony_ci if (match_flags & TBSVC_MATCH_PROTOCOL_KEY) 132362306a36Sopenharmony_ci sprintf(alias + strlen(alias), "k%s", *protocol_key); 132462306a36Sopenharmony_ci else 132562306a36Sopenharmony_ci strcat(alias + strlen(alias), "k*"); 132662306a36Sopenharmony_ci ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id); 132762306a36Sopenharmony_ci ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION, 132862306a36Sopenharmony_ci protocol_version); 132962306a36Sopenharmony_ci ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION, 133062306a36Sopenharmony_ci protocol_revision); 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci add_wildcard(alias); 133362306a36Sopenharmony_ci return 1; 133462306a36Sopenharmony_ci} 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci/* Looks like: typec:idNmN */ 133762306a36Sopenharmony_cistatic int do_typec_entry(const char *filename, void *symval, char *alias) 133862306a36Sopenharmony_ci{ 133962306a36Sopenharmony_ci DEF_FIELD(symval, typec_device_id, svid); 134062306a36Sopenharmony_ci DEF_FIELD(symval, typec_device_id, mode); 134162306a36Sopenharmony_ci 134262306a36Sopenharmony_ci sprintf(alias, "typec:id%04X", svid); 134362306a36Sopenharmony_ci ADD(alias, "m", mode != TYPEC_ANY_MODE, mode); 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci return 1; 134662306a36Sopenharmony_ci} 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci/* Looks like: tee:uuid */ 134962306a36Sopenharmony_cistatic int do_tee_entry(const char *filename, void *symval, char *alias) 135062306a36Sopenharmony_ci{ 135162306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, tee_client_device_id, uuid); 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ci sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 135462306a36Sopenharmony_ci uuid->b[0], uuid->b[1], uuid->b[2], uuid->b[3], uuid->b[4], 135562306a36Sopenharmony_ci uuid->b[5], uuid->b[6], uuid->b[7], uuid->b[8], uuid->b[9], 135662306a36Sopenharmony_ci uuid->b[10], uuid->b[11], uuid->b[12], uuid->b[13], uuid->b[14], 135762306a36Sopenharmony_ci uuid->b[15]); 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci add_wildcard(alias); 136062306a36Sopenharmony_ci return 1; 136162306a36Sopenharmony_ci} 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci/* Looks like: wmi:guid */ 136462306a36Sopenharmony_cistatic int do_wmi_entry(const char *filename, void *symval, char *alias) 136562306a36Sopenharmony_ci{ 136662306a36Sopenharmony_ci int len; 136762306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, wmi_device_id, guid_string); 136862306a36Sopenharmony_ci 136962306a36Sopenharmony_ci if (strlen(*guid_string) != UUID_STRING_LEN) { 137062306a36Sopenharmony_ci warn("Invalid WMI device id 'wmi:%s' in '%s'\n", 137162306a36Sopenharmony_ci *guid_string, filename); 137262306a36Sopenharmony_ci return 0; 137362306a36Sopenharmony_ci } 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string); 137662306a36Sopenharmony_ci if (len < 0 || len >= ALIAS_SIZE) { 137762306a36Sopenharmony_ci warn("Could not generate all MODULE_ALIAS's in '%s'\n", 137862306a36Sopenharmony_ci filename); 137962306a36Sopenharmony_ci return 0; 138062306a36Sopenharmony_ci } 138162306a36Sopenharmony_ci return 1; 138262306a36Sopenharmony_ci} 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci/* Looks like: mhi:S */ 138562306a36Sopenharmony_cistatic int do_mhi_entry(const char *filename, void *symval, char *alias) 138662306a36Sopenharmony_ci{ 138762306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, mhi_device_id, chan); 138862306a36Sopenharmony_ci sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan); 138962306a36Sopenharmony_ci return 1; 139062306a36Sopenharmony_ci} 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_ci/* Looks like: mhi_ep:S */ 139362306a36Sopenharmony_cistatic int do_mhi_ep_entry(const char *filename, void *symval, char *alias) 139462306a36Sopenharmony_ci{ 139562306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, mhi_device_id, chan); 139662306a36Sopenharmony_ci sprintf(alias, MHI_EP_DEVICE_MODALIAS_FMT, *chan); 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci return 1; 139962306a36Sopenharmony_ci} 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_ci/* Looks like: ishtp:{guid} */ 140262306a36Sopenharmony_cistatic int do_ishtp_entry(const char *filename, void *symval, char *alias) 140362306a36Sopenharmony_ci{ 140462306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, ishtp_device_id, guid); 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci strcpy(alias, ISHTP_MODULE_PREFIX "{"); 140762306a36Sopenharmony_ci add_guid(alias, *guid); 140862306a36Sopenharmony_ci strcat(alias, "}"); 140962306a36Sopenharmony_ci 141062306a36Sopenharmony_ci return 1; 141162306a36Sopenharmony_ci} 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_cistatic int do_auxiliary_entry(const char *filename, void *symval, char *alias) 141462306a36Sopenharmony_ci{ 141562306a36Sopenharmony_ci DEF_FIELD_ADDR(symval, auxiliary_device_id, name); 141662306a36Sopenharmony_ci sprintf(alias, AUXILIARY_MODULE_PREFIX "%s", *name); 141762306a36Sopenharmony_ci 141862306a36Sopenharmony_ci return 1; 141962306a36Sopenharmony_ci} 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci/* 142262306a36Sopenharmony_ci * Looks like: ssam:dNcNtNiNfN 142362306a36Sopenharmony_ci * 142462306a36Sopenharmony_ci * N is exactly 2 digits, where each is an upper-case hex digit. 142562306a36Sopenharmony_ci */ 142662306a36Sopenharmony_cistatic int do_ssam_entry(const char *filename, void *symval, char *alias) 142762306a36Sopenharmony_ci{ 142862306a36Sopenharmony_ci DEF_FIELD(symval, ssam_device_id, match_flags); 142962306a36Sopenharmony_ci DEF_FIELD(symval, ssam_device_id, domain); 143062306a36Sopenharmony_ci DEF_FIELD(symval, ssam_device_id, category); 143162306a36Sopenharmony_ci DEF_FIELD(symval, ssam_device_id, target); 143262306a36Sopenharmony_ci DEF_FIELD(symval, ssam_device_id, instance); 143362306a36Sopenharmony_ci DEF_FIELD(symval, ssam_device_id, function); 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci sprintf(alias, "ssam:d%02Xc%02X", domain, category); 143662306a36Sopenharmony_ci ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target); 143762306a36Sopenharmony_ci ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance); 143862306a36Sopenharmony_ci ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function); 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci return 1; 144162306a36Sopenharmony_ci} 144262306a36Sopenharmony_ci 144362306a36Sopenharmony_ci/* Looks like: dfl:tNfN */ 144462306a36Sopenharmony_cistatic int do_dfl_entry(const char *filename, void *symval, char *alias) 144562306a36Sopenharmony_ci{ 144662306a36Sopenharmony_ci DEF_FIELD(symval, dfl_device_id, type); 144762306a36Sopenharmony_ci DEF_FIELD(symval, dfl_device_id, feature_id); 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci sprintf(alias, "dfl:t%04Xf%04X", type, feature_id); 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci add_wildcard(alias); 145262306a36Sopenharmony_ci return 1; 145362306a36Sopenharmony_ci} 145462306a36Sopenharmony_ci 145562306a36Sopenharmony_ci/* Looks like: cdx:vNdN */ 145662306a36Sopenharmony_cistatic int do_cdx_entry(const char *filename, void *symval, 145762306a36Sopenharmony_ci char *alias) 145862306a36Sopenharmony_ci{ 145962306a36Sopenharmony_ci DEF_FIELD(symval, cdx_device_id, vendor); 146062306a36Sopenharmony_ci DEF_FIELD(symval, cdx_device_id, device); 146162306a36Sopenharmony_ci DEF_FIELD(symval, cdx_device_id, override_only); 146262306a36Sopenharmony_ci 146362306a36Sopenharmony_ci switch (override_only) { 146462306a36Sopenharmony_ci case 0: 146562306a36Sopenharmony_ci strcpy(alias, "cdx:"); 146662306a36Sopenharmony_ci break; 146762306a36Sopenharmony_ci case CDX_ID_F_VFIO_DRIVER_OVERRIDE: 146862306a36Sopenharmony_ci strcpy(alias, "vfio_cdx:"); 146962306a36Sopenharmony_ci break; 147062306a36Sopenharmony_ci default: 147162306a36Sopenharmony_ci warn("Unknown CDX driver_override alias %08X\n", 147262306a36Sopenharmony_ci override_only); 147362306a36Sopenharmony_ci return 0; 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci ADD(alias, "v", vendor != CDX_ANY_ID, vendor); 147762306a36Sopenharmony_ci ADD(alias, "d", device != CDX_ANY_ID, device); 147862306a36Sopenharmony_ci return 1; 147962306a36Sopenharmony_ci} 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci/* Does namelen bytes of name exactly match the symbol? */ 148262306a36Sopenharmony_cistatic bool sym_is(const char *name, unsigned namelen, const char *symbol) 148362306a36Sopenharmony_ci{ 148462306a36Sopenharmony_ci if (namelen != strlen(symbol)) 148562306a36Sopenharmony_ci return false; 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci return memcmp(name, symbol, namelen) == 0; 148862306a36Sopenharmony_ci} 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_cistatic void do_table(void *symval, unsigned long size, 149162306a36Sopenharmony_ci unsigned long id_size, 149262306a36Sopenharmony_ci const char *device_id, 149362306a36Sopenharmony_ci int (*do_entry)(const char *filename, void *symval, char *alias), 149462306a36Sopenharmony_ci struct module *mod) 149562306a36Sopenharmony_ci{ 149662306a36Sopenharmony_ci unsigned int i; 149762306a36Sopenharmony_ci char alias[ALIAS_SIZE]; 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci device_id_check(mod->name, device_id, size, id_size, symval); 150062306a36Sopenharmony_ci /* Leave last one: it's the terminator. */ 150162306a36Sopenharmony_ci size -= id_size; 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci for (i = 0; i < size; i += id_size) { 150462306a36Sopenharmony_ci if (do_entry(mod->name, symval+i, alias)) { 150562306a36Sopenharmony_ci buf_printf(&mod->dev_table_buf, 150662306a36Sopenharmony_ci "MODULE_ALIAS(\"%s\");\n", alias); 150762306a36Sopenharmony_ci } 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci} 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_cistatic const struct devtable devtable[] = { 151262306a36Sopenharmony_ci {"hid", SIZE_hid_device_id, do_hid_entry}, 151362306a36Sopenharmony_ci {"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry}, 151462306a36Sopenharmony_ci {"pci", SIZE_pci_device_id, do_pci_entry}, 151562306a36Sopenharmony_ci {"ccw", SIZE_ccw_device_id, do_ccw_entry}, 151662306a36Sopenharmony_ci {"ap", SIZE_ap_device_id, do_ap_entry}, 151762306a36Sopenharmony_ci {"css", SIZE_css_device_id, do_css_entry}, 151862306a36Sopenharmony_ci {"serio", SIZE_serio_device_id, do_serio_entry}, 151962306a36Sopenharmony_ci {"acpi", SIZE_acpi_device_id, do_acpi_entry}, 152062306a36Sopenharmony_ci {"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry}, 152162306a36Sopenharmony_ci {"vio", SIZE_vio_device_id, do_vio_entry}, 152262306a36Sopenharmony_ci {"input", SIZE_input_device_id, do_input_entry}, 152362306a36Sopenharmony_ci {"eisa", SIZE_eisa_device_id, do_eisa_entry}, 152462306a36Sopenharmony_ci {"parisc", SIZE_parisc_device_id, do_parisc_entry}, 152562306a36Sopenharmony_ci {"sdio", SIZE_sdio_device_id, do_sdio_entry}, 152662306a36Sopenharmony_ci {"ssb", SIZE_ssb_device_id, do_ssb_entry}, 152762306a36Sopenharmony_ci {"bcma", SIZE_bcma_device_id, do_bcma_entry}, 152862306a36Sopenharmony_ci {"virtio", SIZE_virtio_device_id, do_virtio_entry}, 152962306a36Sopenharmony_ci {"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry}, 153062306a36Sopenharmony_ci {"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry}, 153162306a36Sopenharmony_ci {"i2c", SIZE_i2c_device_id, do_i2c_entry}, 153262306a36Sopenharmony_ci {"i3c", SIZE_i3c_device_id, do_i3c_entry}, 153362306a36Sopenharmony_ci {"spi", SIZE_spi_device_id, do_spi_entry}, 153462306a36Sopenharmony_ci {"dmi", SIZE_dmi_system_id, do_dmi_entry}, 153562306a36Sopenharmony_ci {"platform", SIZE_platform_device_id, do_platform_entry}, 153662306a36Sopenharmony_ci {"mdio", SIZE_mdio_device_id, do_mdio_entry}, 153762306a36Sopenharmony_ci {"zorro", SIZE_zorro_device_id, do_zorro_entry}, 153862306a36Sopenharmony_ci {"isapnp", SIZE_isapnp_device_id, do_isapnp_entry}, 153962306a36Sopenharmony_ci {"ipack", SIZE_ipack_device_id, do_ipack_entry}, 154062306a36Sopenharmony_ci {"amba", SIZE_amba_id, do_amba_entry}, 154162306a36Sopenharmony_ci {"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry}, 154262306a36Sopenharmony_ci {"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry}, 154362306a36Sopenharmony_ci {"cpu", SIZE_cpu_feature, do_cpu_entry}, 154462306a36Sopenharmony_ci {"mei", SIZE_mei_cl_device_id, do_mei_entry}, 154562306a36Sopenharmony_ci {"rapidio", SIZE_rio_device_id, do_rio_entry}, 154662306a36Sopenharmony_ci {"ulpi", SIZE_ulpi_device_id, do_ulpi_entry}, 154762306a36Sopenharmony_ci {"hdaudio", SIZE_hda_device_id, do_hda_entry}, 154862306a36Sopenharmony_ci {"sdw", SIZE_sdw_device_id, do_sdw_entry}, 154962306a36Sopenharmony_ci {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry}, 155062306a36Sopenharmony_ci {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry}, 155162306a36Sopenharmony_ci {"typec", SIZE_typec_device_id, do_typec_entry}, 155262306a36Sopenharmony_ci {"tee", SIZE_tee_client_device_id, do_tee_entry}, 155362306a36Sopenharmony_ci {"wmi", SIZE_wmi_device_id, do_wmi_entry}, 155462306a36Sopenharmony_ci {"mhi", SIZE_mhi_device_id, do_mhi_entry}, 155562306a36Sopenharmony_ci {"mhi_ep", SIZE_mhi_device_id, do_mhi_ep_entry}, 155662306a36Sopenharmony_ci {"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry}, 155762306a36Sopenharmony_ci {"ssam", SIZE_ssam_device_id, do_ssam_entry}, 155862306a36Sopenharmony_ci {"dfl", SIZE_dfl_device_id, do_dfl_entry}, 155962306a36Sopenharmony_ci {"ishtp", SIZE_ishtp_device_id, do_ishtp_entry}, 156062306a36Sopenharmony_ci {"cdx", SIZE_cdx_device_id, do_cdx_entry}, 156162306a36Sopenharmony_ci}; 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci/* Create MODULE_ALIAS() statements. 156462306a36Sopenharmony_ci * At this time, we cannot write the actual output C source yet, 156562306a36Sopenharmony_ci * so we write into the mod->dev_table_buf buffer. */ 156662306a36Sopenharmony_civoid handle_moddevtable(struct module *mod, struct elf_info *info, 156762306a36Sopenharmony_ci Elf_Sym *sym, const char *symname) 156862306a36Sopenharmony_ci{ 156962306a36Sopenharmony_ci void *symval; 157062306a36Sopenharmony_ci char *zeros = NULL; 157162306a36Sopenharmony_ci const char *name, *identifier; 157262306a36Sopenharmony_ci unsigned int namelen; 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_ci /* We're looking for a section relative symbol */ 157562306a36Sopenharmony_ci if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) 157662306a36Sopenharmony_ci return; 157762306a36Sopenharmony_ci 157862306a36Sopenharmony_ci /* We're looking for an object */ 157962306a36Sopenharmony_ci if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) 158062306a36Sopenharmony_ci return; 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci /* All our symbols are of form __mod_<name>__<identifier>_device_table. */ 158362306a36Sopenharmony_ci if (strncmp(symname, "__mod_", strlen("__mod_"))) 158462306a36Sopenharmony_ci return; 158562306a36Sopenharmony_ci name = symname + strlen("__mod_"); 158662306a36Sopenharmony_ci namelen = strlen(name); 158762306a36Sopenharmony_ci if (namelen < strlen("_device_table")) 158862306a36Sopenharmony_ci return; 158962306a36Sopenharmony_ci if (strcmp(name + namelen - strlen("_device_table"), "_device_table")) 159062306a36Sopenharmony_ci return; 159162306a36Sopenharmony_ci identifier = strstr(name, "__"); 159262306a36Sopenharmony_ci if (!identifier) 159362306a36Sopenharmony_ci return; 159462306a36Sopenharmony_ci namelen = identifier - name; 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_ci /* Handle all-NULL symbols allocated into .bss */ 159762306a36Sopenharmony_ci if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { 159862306a36Sopenharmony_ci zeros = calloc(1, sym->st_size); 159962306a36Sopenharmony_ci symval = zeros; 160062306a36Sopenharmony_ci } else { 160162306a36Sopenharmony_ci symval = sym_get_data(info, sym); 160262306a36Sopenharmony_ci } 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci /* First handle the "special" cases */ 160562306a36Sopenharmony_ci if (sym_is(name, namelen, "usb")) 160662306a36Sopenharmony_ci do_usb_table(symval, sym->st_size, mod); 160762306a36Sopenharmony_ci else if (sym_is(name, namelen, "of")) 160862306a36Sopenharmony_ci do_of_table(symval, sym->st_size, mod); 160962306a36Sopenharmony_ci else if (sym_is(name, namelen, "pnp")) 161062306a36Sopenharmony_ci do_pnp_device_entry(symval, sym->st_size, mod); 161162306a36Sopenharmony_ci else if (sym_is(name, namelen, "pnp_card")) 161262306a36Sopenharmony_ci do_pnp_card_entries(symval, sym->st_size, mod); 161362306a36Sopenharmony_ci else { 161462306a36Sopenharmony_ci int i; 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(devtable); i++) { 161762306a36Sopenharmony_ci const struct devtable *p = &devtable[i]; 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci if (sym_is(name, namelen, p->device_id)) { 162062306a36Sopenharmony_ci do_table(symval, sym->st_size, p->id_size, 162162306a36Sopenharmony_ci p->device_id, p->do_entry, mod); 162262306a36Sopenharmony_ci break; 162362306a36Sopenharmony_ci } 162462306a36Sopenharmony_ci } 162562306a36Sopenharmony_ci } 162662306a36Sopenharmony_ci free(zeros); 162762306a36Sopenharmony_ci} 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci/* Now add out buffered information to the generated C source */ 163062306a36Sopenharmony_civoid add_moddevtable(struct buffer *buf, struct module *mod) 163162306a36Sopenharmony_ci{ 163262306a36Sopenharmony_ci buf_printf(buf, "\n"); 163362306a36Sopenharmony_ci buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos); 163462306a36Sopenharmony_ci free(mod->dev_table_buf.p); 163562306a36Sopenharmony_ci} 1636