^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* Simple code to turn various tables in an ELF file into alias definitions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This deals with kernel datastructures where they should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * dealt with: in the kernel source.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2002-2003 Rusty Russell, IBM Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * 2003 Kai Germaschewski
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * This software may be used and distributed according to the terms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * of the GNU General Public License, incorporated herein by reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "modpost.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "devicetable-offsets.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * use either stdint.h or inttypes.h for the rest. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #if KERNEL_ELFCLASS == ELFCLASS32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) typedef Elf32_Addr kernel_ulong_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define BITS_PER_LONG 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) typedef Elf64_Addr kernel_ulong_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define BITS_PER_LONG 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #ifdef __sun__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <stdint.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <ctype.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <stdbool.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) typedef uint32_t __u32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) typedef uint16_t __u16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) typedef unsigned char __u8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) __u8 b[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) } guid_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /* backwards compatibility, don't use in new code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) __u8 b[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) } uuid_le;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) typedef struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) __u8 b[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) } uuid_t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define UUID_STRING_LEN 36
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* Big exception to the "don't include kernel headers into userspace, which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * even potentially has different endianness and word sizes, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * we handle those differences explicitly below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #include "../../include/linux/mod_devicetable.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) /* This array collects all instances that use the generic do_table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct devtable {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) const char *device_id; /* name of table, __mod_<name>__*_device_table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned long id_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int (*do_entry)(const char *filename, void *symval, char *alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Size of alias provided to do_entry functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define ALIAS_SIZE 500
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* Define a variable f that holds the value of field f of struct devid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * based at address m.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define DEF_FIELD(m, devid, f) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /* Define a variable v that holds the address of field f of struct devid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * based at address m. Due to the way typeof works, for a field of type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * T[N] the variable has type T(*)[N], _not_ T*.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define DEF_FIELD_ADDR_VAR(m, devid, f, v) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) /* Define a variable f that holds the address of field f of struct devid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * based at address m. Due to the way typeof works, for a field of type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * T[N] the variable has type T(*)[N], _not_ T*.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define DEF_FIELD_ADDR(m, devid, f) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) DEF_FIELD_ADDR_VAR(m, devid, f, f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define ADD(str, sep, cond, field) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) strcat(str, sep); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (cond) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) sprintf(str + strlen(str), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) sizeof(field) == 1 ? "%02X" : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) sizeof(field) == 2 ? "%04X" : \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) sizeof(field) == 4 ? "%08X" : "", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) field); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) else \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) sprintf(str + strlen(str), "*"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) } while(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* End in a wildcard, for future extension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static inline void add_wildcard(char *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) int len = strlen(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (str[len - 1] != '*')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) strcat(str + len, "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static inline void add_uuid(char *str, uuid_le uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int len = strlen(str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * Check that sizeof(device_id type) are consistent with size of section
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * in .o file. If in-consistent then userspace and kernel does not agree
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * on actual size which is a bug.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * Also verify that the final entry in the table is all zeros.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * Ignore both checks if build host differ from target host and size differs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) **/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) static void device_id_check(const char *modname, const char *device_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) unsigned long size, unsigned long id_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) void *symval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (size % id_size || size < id_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) "of the size of "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) "section __mod_%s__<identifier>_device_table=%lu.\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) "Fix definition of struct %s_device_id "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) "in mod_devicetable.h\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) modname, device_id, id_size, device_id, size, device_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* Verify last one is a terminator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) for (i = 0; i < id_size; i++ ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (*(uint8_t*)(symval+size-id_size+i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) fprintf(stderr,"%s: struct %s_device_id is %lu bytes. "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) "The last of %lu is:\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) modname, device_id, id_size, size / id_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) for (i = 0; i < id_size; i++ )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) fprintf(stderr,"0x%02x ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) *(uint8_t*)(symval+size-id_size+i) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) fprintf(stderr,"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) fatal("%s: struct %s_device_id is not terminated "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) "with a NULL entry!\n", modname, device_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) /* USB is special because the bcdDevice can be matched against a numeric range */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static void do_usb_entry(void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) unsigned char range_lo, unsigned char range_hi,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned char max, struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) char alias[500];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) DEF_FIELD(symval, usb_device_id, match_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) DEF_FIELD(symval, usb_device_id, idVendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) DEF_FIELD(symval, usb_device_id, idProduct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) DEF_FIELD(symval, usb_device_id, bDeviceClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) DEF_FIELD(symval, usb_device_id, bDeviceSubClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) DEF_FIELD(symval, usb_device_id, bDeviceProtocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) DEF_FIELD(symval, usb_device_id, bInterfaceClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) DEF_FIELD(symval, usb_device_id, bInterfaceSubClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) DEF_FIELD(symval, usb_device_id, bInterfaceProtocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) DEF_FIELD(symval, usb_device_id, bInterfaceNumber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) strcpy(alias, "usb:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) idVendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) idProduct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) strcat(alias, "d");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (bcdDevice_initial_digits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) sprintf(alias + strlen(alias), "%0*X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) bcdDevice_initial_digits, bcdDevice_initial);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (range_lo == range_hi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) sprintf(alias + strlen(alias), "%X", range_lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else if (range_lo > 0 || range_hi < max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (range_lo > 0x9 || range_hi < 0xA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) sprintf(alias + strlen(alias),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) "[%X-%X]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) range_lo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) range_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) sprintf(alias + strlen(alias),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) range_lo < 0x9 ? "[%X-9" : "[%X",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) range_lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) sprintf(alias + strlen(alias),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) range_hi > 0xA ? "A-%X]" : "%X]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) range_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) strcat(alias, "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) bDeviceClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) bDeviceSubClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) bDeviceProtocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) bInterfaceClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) bInterfaceSubClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) bInterfaceProtocol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) bInterfaceNumber);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) buf_printf(&mod->dev_table_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) "MODULE_ALIAS(\"%s\");\n", alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* Handles increment/decrement of BCD formatted integers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) /* Returns the previous value, so it works like i++ or i-- */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static unsigned int incbcd(unsigned int *bcd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) int inc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) unsigned char max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) size_t chars)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) unsigned int init = *bcd, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) unsigned long long c, dec = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* If bcd is not in BCD format, just increment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (max > 0x9) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) *bcd += inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) /* Convert BCD to Decimal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (i=0 ; i < chars ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) c = (*bcd >> (i << 2)) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) c = c > 9 ? 9 : c; /* force to bcd just in case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) for (j=0 ; j < i ; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) c = c * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) dec += c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* Do our increment/decrement */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) dec += inc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) *bcd = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /* Convert back to BCD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) for (i=0 ; i < chars ; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) for (c=1,j=0 ; j < i ; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) c = c * 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) c = (dec / c) % 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *bcd += c << (i << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static void do_usb_entry_multi(void *symval, struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned int devlo, devhi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) unsigned char chi, clo, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int ndigits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) DEF_FIELD(symval, usb_device_id, match_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) DEF_FIELD(symval, usb_device_id, idVendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) DEF_FIELD(symval, usb_device_id, idProduct);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) DEF_FIELD(symval, usb_device_id, bcdDevice_lo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) DEF_FIELD(symval, usb_device_id, bcdDevice_hi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) DEF_FIELD(symval, usb_device_id, bDeviceClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) DEF_FIELD(symval, usb_device_id, bInterfaceClass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) bcdDevice_lo : 0x0U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) bcdDevice_hi : ~0x0U;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* Figure out if this entry is in bcd or hex format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) max = 0x9; /* Default to decimal format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) clo = (devlo >> (ndigits << 2)) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (clo > max || chi > max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) max = 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * Some modules (visor) have empty slots as placeholder for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) * run-time specification that results in catch-all alias
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) clo = devlo & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) chi = devhi & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) if (chi > max) /* If we are in bcd mode, truncate if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) chi = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) devlo >>= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) devhi >>= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (devlo == devhi || !ndigits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (clo > 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) do_usb_entry(symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) incbcd(&devlo, 1, max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) sizeof(bcdDevice_lo) * 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) ndigits, clo, max, max, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (chi < max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) do_usb_entry(symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) incbcd(&devhi, -1, max,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) sizeof(bcdDevice_lo) * 2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) ndigits, 0x0, chi, max, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) static void do_usb_table(void *symval, unsigned long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) const unsigned long id_size = SIZE_usb_device_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) device_id_check(mod->name, "usb", size, id_size, symval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* Leave last one: it's the terminator. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) size -= id_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) for (i = 0; i < size; i += id_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) do_usb_entry_multi(symval + i, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static void do_of_entry_multi(void *symval, struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) char alias[500];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) char *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) DEF_FIELD_ADDR(symval, of_device_id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) DEF_FIELD_ADDR(symval, of_device_id, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) DEF_FIELD_ADDR(symval, of_device_id, compatible);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) (*type)[0] ? *type : "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if ((*compatible)[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) *compatible);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* Replace all whitespace with underscores */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) for (tmp = alias; tmp && *tmp; tmp++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (isspace(*tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *tmp = '_';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) strcat(alias, "C");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) static void do_of_table(void *symval, unsigned long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) const unsigned long id_size = SIZE_of_device_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) device_id_check(mod->name, "of", size, id_size, symval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* Leave last one: it's the terminator. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) size -= id_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) for (i = 0; i < size; i += id_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) do_of_entry_multi(symval + i, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) /* Looks like: hid:bNvNpN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static int do_hid_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) DEF_FIELD(symval, hid_device_id, bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) DEF_FIELD(symval, hid_device_id, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) DEF_FIELD(symval, hid_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) DEF_FIELD(symval, hid_device_id, product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) sprintf(alias, "hid:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) ADD(alias, "b", bus != HID_BUS_ANY, bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) ADD(alias, "g", group != HID_GROUP_ANY, group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) ADD(alias, "v", vendor != HID_ANY_ID, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) ADD(alias, "p", product != HID_ANY_ID, product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* Looks like: ieee1394:venNmoNspNverN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) static int do_ieee1394_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) DEF_FIELD(symval, ieee1394_device_id, match_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) DEF_FIELD(symval, ieee1394_device_id, vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) DEF_FIELD(symval, ieee1394_device_id, model_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) DEF_FIELD(symval, ieee1394_device_id, specifier_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) DEF_FIELD(symval, ieee1394_device_id, version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) strcpy(alias, "ieee1394:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) model_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) specifier_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* Looks like: pci:vNdNsvNsdNbcNscNiN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) static int do_pci_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) /* Class field can be divided into these three. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) unsigned char baseclass, subclass, interface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) baseclass_mask, subclass_mask, interface_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) DEF_FIELD(symval, pci_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) DEF_FIELD(symval, pci_device_id, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) DEF_FIELD(symval, pci_device_id, subvendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) DEF_FIELD(symval, pci_device_id, subdevice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) DEF_FIELD(symval, pci_device_id, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) DEF_FIELD(symval, pci_device_id, class_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) strcpy(alias, "pci:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) ADD(alias, "d", device != PCI_ANY_ID, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) baseclass = (class) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) baseclass_mask = (class_mask) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) subclass = (class) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) subclass_mask = (class_mask) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) interface = class;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) interface_mask = class_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) || (subclass_mask != 0 && subclass_mask != 0xFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) || (interface_mask != 0 && interface_mask != 0xFF)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) warn("Can't handle masks in %s:%04X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) filename, class_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) ADD(alias, "sc", subclass_mask == 0xFF, subclass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) ADD(alias, "i", interface_mask == 0xFF, interface);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) /* looks like: "ccw:tNmNdtNdmN" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) static int do_ccw_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) DEF_FIELD(symval, ccw_device_id, match_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) DEF_FIELD(symval, ccw_device_id, cu_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) DEF_FIELD(symval, ccw_device_id, cu_model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) DEF_FIELD(symval, ccw_device_id, dev_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) DEF_FIELD(symval, ccw_device_id, dev_model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) strcpy(alias, "ccw:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) cu_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) cu_model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) dev_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) dev_model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) /* looks like: "ap:tN" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) static int do_ap_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) DEF_FIELD(symval, ap_device_id, dev_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) sprintf(alias, "ap:t%02X*", dev_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* looks like: "css:tN" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static int do_css_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) DEF_FIELD(symval, css_device_id, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) sprintf(alias, "css:t%01X", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) /* Looks like: "serio:tyNprNidNexN" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int do_serio_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) DEF_FIELD(symval, serio_device_id, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) DEF_FIELD(symval, serio_device_id, proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) DEF_FIELD(symval, serio_device_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) DEF_FIELD(symval, serio_device_id, extra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) strcpy(alias, "serio:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) ADD(alias, "ty", type != SERIO_ANY, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) ADD(alias, "pr", proto != SERIO_ANY, proto);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) ADD(alias, "id", id != SERIO_ANY, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) ADD(alias, "ex", extra != SERIO_ANY, extra);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) * NOTE: Each driver should use one of the following : _HID, _CIDs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * or _CLS. Also, bb, ss, and pp can be substituted with ??
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * as don't care byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) static int do_acpi_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) DEF_FIELD_ADDR(symval, acpi_device_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) DEF_FIELD_ADDR(symval, acpi_device_id, cls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) DEF_FIELD_ADDR(symval, acpi_device_id, cls_msk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) if (id && strlen((const char *)*id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) sprintf(alias, "acpi*:%s:*", *id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) else if (cls) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) int i, byte_shift, cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) unsigned int msk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) sprintf(&alias[cnt], "acpi*:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) cnt = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) for (i = 1; i <= 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) byte_shift = 8 * (3-i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) msk = (*cls_msk >> byte_shift) & 0xFF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (msk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) sprintf(&alias[cnt], "%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) (*cls >> byte_shift) & 0xFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) sprintf(&alias[cnt], "??");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) cnt += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) sprintf(&alias[cnt], ":*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) /* looks like: "pnp:dD" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static void do_pnp_device_entry(void *symval, unsigned long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) const unsigned long id_size = SIZE_pnp_device_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) const unsigned int count = (size / id_size)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) device_id_check(mod->name, "pnp", size, id_size, symval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) char acpi_id[sizeof(*id)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) buf_printf(&mod->dev_table_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) "MODULE_ALIAS(\"pnp:d%s*\");\n", *id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) /* fix broken pnp bus lowercasing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) for (j = 0; j < sizeof(acpi_id); j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) acpi_id[j] = toupper((*id)[j]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) buf_printf(&mod->dev_table_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* looks like: "pnp:dD" for every device of the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) static void do_pnp_card_entries(void *symval, unsigned long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) const unsigned long id_size = SIZE_pnp_card_device_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) const unsigned int count = (size / id_size)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) device_id_check(mod->name, "pnp", size, id_size, symval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) for (i = 0; i < count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) unsigned int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) DEF_FIELD_ADDR(symval + i * id_size, pnp_card_device_id, devs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) for (j = 0; j < PNP_MAX_DEVICES; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) const char *id = (char *)(*devs)[j].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) int i2, j2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) int dup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) if (!id[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) /* find duplicate, already added value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) for (i2 = 0; i2 < i && !dup; i2++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) DEF_FIELD_ADDR_VAR(symval + i2 * id_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) pnp_card_device_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) devs, devs_dup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) const char *id2 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) (char *)(*devs_dup)[j2].id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (!id2[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) if (!strcmp(id, id2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) dup = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) /* add an individual alias for every device entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) if (!dup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) char acpi_id[PNP_ID_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) int k;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) buf_printf(&mod->dev_table_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* fix broken pnp bus lowercasing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) for (k = 0; k < sizeof(acpi_id); k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) acpi_id[k] = toupper(id[k]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) buf_printf(&mod->dev_table_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) static int do_pcmcia_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) DEF_FIELD(symval, pcmcia_device_id, match_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) DEF_FIELD(symval, pcmcia_device_id, manf_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) DEF_FIELD(symval, pcmcia_device_id, card_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) DEF_FIELD(symval, pcmcia_device_id, func_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) DEF_FIELD(symval, pcmcia_device_id, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) DEF_FIELD(symval, pcmcia_device_id, device_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) for (i=0; i<4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) (*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) strcpy(alias, "pcmcia:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) manf_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) card_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) func_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) device_no);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static int do_vio_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) char *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) DEF_FIELD_ADDR(symval, vio_device_id, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) DEF_FIELD_ADDR(symval, vio_device_id, compat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) (*compat)[0] ? *compat : "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) /* Replace all whitespace with underscores */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) for (tmp = alias; tmp && *tmp; tmp++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) if (isspace (*tmp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) *tmp = '_';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) static void do_input(char *alias,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) kernel_ulong_t *arr, unsigned int min, unsigned int max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) arr[i] = TO_NATIVE(arr[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) for (i = min; i < max; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) sprintf(alias + strlen(alias), "%X,*", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) static int do_input_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) DEF_FIELD(symval, input_device_id, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) DEF_FIELD(symval, input_device_id, bustype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) DEF_FIELD(symval, input_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) DEF_FIELD(symval, input_device_id, product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) DEF_FIELD(symval, input_device_id, version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) DEF_FIELD_ADDR(symval, input_device_id, evbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) DEF_FIELD_ADDR(symval, input_device_id, keybit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) DEF_FIELD_ADDR(symval, input_device_id, relbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) DEF_FIELD_ADDR(symval, input_device_id, absbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) DEF_FIELD_ADDR(symval, input_device_id, mscbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) DEF_FIELD_ADDR(symval, input_device_id, ledbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) DEF_FIELD_ADDR(symval, input_device_id, sndbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) DEF_FIELD_ADDR(symval, input_device_id, ffbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) DEF_FIELD_ADDR(symval, input_device_id, swbit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) sprintf(alias, "input:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) sprintf(alias + strlen(alias), "-e*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (flags & INPUT_DEVICE_ID_MATCH_EVBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) sprintf(alias + strlen(alias), "k*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) do_input(alias, *keybit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) INPUT_DEVICE_ID_KEY_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) sprintf(alias + strlen(alias), "r*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) if (flags & INPUT_DEVICE_ID_MATCH_RELBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) sprintf(alias + strlen(alias), "a*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) sprintf(alias + strlen(alias), "m*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (flags & INPUT_DEVICE_ID_MATCH_MSCIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) sprintf(alias + strlen(alias), "l*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) sprintf(alias + strlen(alias), "s*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) sprintf(alias + strlen(alias), "f*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (flags & INPUT_DEVICE_ID_MATCH_FFBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) sprintf(alias + strlen(alias), "w*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) static int do_eisa_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) DEF_FIELD_ADDR(symval, eisa_device_id, sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (sig[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) strcat(alias, "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* Looks like: parisc:tNhvNrevNsvN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) static int do_parisc_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) DEF_FIELD(symval, parisc_device_id, hw_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) DEF_FIELD(symval, parisc_device_id, hversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) DEF_FIELD(symval, parisc_device_id, hversion_rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) DEF_FIELD(symval, parisc_device_id, sversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) strcpy(alias, "parisc:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) /* Looks like: sdio:cNvNdN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) static int do_sdio_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) DEF_FIELD(symval, sdio_device_id, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) DEF_FIELD(symval, sdio_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) DEF_FIELD(symval, sdio_device_id, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) strcpy(alias, "sdio:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /* Looks like: ssb:vNidNrevN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) static int do_ssb_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) DEF_FIELD(symval, ssb_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) DEF_FIELD(symval, ssb_device_id, coreid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) DEF_FIELD(symval, ssb_device_id, revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) strcpy(alias, "ssb:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) ADD(alias, "rev", revision != SSB_ANY_REV, revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) /* Looks like: bcma:mNidNrevNclN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static int do_bcma_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) DEF_FIELD(symval, bcma_device_id, manuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) DEF_FIELD(symval, bcma_device_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) DEF_FIELD(symval, bcma_device_id, rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) DEF_FIELD(symval, bcma_device_id, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) strcpy(alias, "bcma:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) ADD(alias, "id", id != BCMA_ANY_ID, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) /* Looks like: virtio:dNvN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static int do_virtio_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) DEF_FIELD(symval, virtio_device_id, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) DEF_FIELD(symval, virtio_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) strcpy(alias, "virtio:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) * Looks like: vmbus:guid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) * Each byte of the guid will be represented by two hex characters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) * in the name.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static int do_vmbus_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) char guid_name[(sizeof(*guid) + 1) * 2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) for (i = 0; i < (sizeof(*guid) * 2); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) strcpy(alias, "vmbus:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) strcat(alias, guid_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) /* Looks like: rpmsg:S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) static int do_rpmsg_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) DEF_FIELD_ADDR(symval, rpmsg_device_id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) /* Looks like: i2c:S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) static int do_i2c_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) DEF_FIELD_ADDR(symval, i2c_device_id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) sprintf(alias, I2C_MODULE_PREFIX "%s", *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static int do_i3c_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) DEF_FIELD(symval, i3c_device_id, match_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) DEF_FIELD(symval, i3c_device_id, dcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) DEF_FIELD(symval, i3c_device_id, manuf_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) DEF_FIELD(symval, i3c_device_id, part_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) DEF_FIELD(symval, i3c_device_id, extra_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) strcpy(alias, "i3c:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) /* Looks like: spi:S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) static int do_spi_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) DEF_FIELD_ADDR(symval, spi_device_id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) sprintf(alias, SPI_MODULE_PREFIX "%s", *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) static const struct dmifield {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) const char *prefix;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int field;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) } dmi_fields[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) { "bvn", DMI_BIOS_VENDOR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) { "bvr", DMI_BIOS_VERSION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) { "bd", DMI_BIOS_DATE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) { "br", DMI_BIOS_RELEASE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) { "efr", DMI_EC_FIRMWARE_RELEASE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) { "svn", DMI_SYS_VENDOR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) { "pn", DMI_PRODUCT_NAME },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) { "pvr", DMI_PRODUCT_VERSION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) { "rvn", DMI_BOARD_VENDOR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) { "rn", DMI_BOARD_NAME },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) { "rvr", DMI_BOARD_VERSION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) { "cvn", DMI_CHASSIS_VENDOR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) { "ct", DMI_CHASSIS_TYPE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) { "cvr", DMI_CHASSIS_VERSION },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) { NULL, DMI_NONE }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) static void dmi_ascii_filter(char *d, const char *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) /* Filter out characters we don't want to see in the modalias string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) for (; *s; s++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (*s > ' ' && *s < 127 && *s != ':')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) *(d++) = *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) *d = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) static int do_dmi_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) int i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) DEF_FIELD_ADDR(symval, dmi_system_id, matches);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) sprintf(alias, "dmi*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) for (j = 0; j < 4; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if ((*matches)[j].slot &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) (*matches)[j].slot == dmi_fields[i].field) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) sprintf(alias + strlen(alias), ":%s*",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) dmi_fields[i].prefix);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) dmi_ascii_filter(alias + strlen(alias),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) (*matches)[j].substr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) strcat(alias, "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) strcat(alias, ":");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) static int do_platform_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) DEF_FIELD_ADDR(symval, platform_device_id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static int do_mdio_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) DEF_FIELD(symval, mdio_device_id, phy_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) DEF_FIELD(symval, mdio_device_id, phy_id_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) alias += sprintf(alias, MDIO_MODULE_PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) for (i = 0; i < 32; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) if (!((phy_id_mask >> (31-i)) & 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) *(alias++) = '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) else if ((phy_id >> (31-i)) & 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) *(alias++) = '1';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) *(alias++) = '0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) /* Terminate the string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) *alias = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) /* Looks like: zorro:iN. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) static int do_zorro_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) DEF_FIELD(symval, zorro_device_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) strcpy(alias, "zorro:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) ADD(alias, "i", id != ZORRO_WILDCARD, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) /* looks like: "pnp:dD" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) static int do_isapnp_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) DEF_FIELD(symval, isapnp_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) DEF_FIELD(symval, isapnp_device_id, function);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) sprintf(alias, "pnp:d%c%c%c%x%x%x%x*",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 'A' + ((vendor >> 2) & 0x3f) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) 'A' + ((vendor >> 8) & 0x1f) - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) (function >> 4) & 0x0f, function & 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) (function >> 12) & 0x0f, (function >> 8) & 0x0f);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) /* Looks like: "ipack:fNvNdN". */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) static int do_ipack_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) DEF_FIELD(symval, ipack_device_id, format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) DEF_FIELD(symval, ipack_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) DEF_FIELD(symval, ipack_device_id, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) strcpy(alias, "ipack:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ADD(alias, "f", format != IPACK_ANY_FORMAT, format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ADD(alias, "v", vendor != IPACK_ANY_ID, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) ADD(alias, "d", device != IPACK_ANY_ID, device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) * Append a match expression for a single masked hex digit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) * outp points to a pointer to the character at which to append.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) * *outp is updated on return to point just after the appended text,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) * to facilitate further appending.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) static void append_nibble_mask(char **outp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) unsigned int nibble, unsigned int mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) char *p = *outp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) *p++ = '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) case 0xf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) p += sprintf(p, "%X", nibble);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) * Dumbly emit a match pattern for all possible matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) * digits. This could be improved in some cases using ranges,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) * but it has the advantage of being trivially correct, and is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) * often optimal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) *p++ = '[';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) for (i = 0; i < 0x10; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) if ((i & mask) == nibble)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) p += sprintf(p, "%X", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) *p++ = ']';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) /* Ensure that the string remains NUL-terminated: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) *p = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /* Advance the caller's end-of-string pointer: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) *outp = p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * looks like: "amba:dN"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) * N is exactly 8 digits, where each is an upper-case hex digit, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) * a ? or [] pattern matching exactly one digit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) static int do_amba_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) unsigned int digit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) char *p = alias;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) DEF_FIELD(symval, amba_id, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) DEF_FIELD(symval, amba_id, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) if ((id & mask) != id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) "id=0x%08X, mask=0x%08X. Please fix this driver.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) filename, id, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) p += sprintf(alias, "amba:d");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) for (digit = 0; digit < 8; digit++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) append_nibble_mask(&p,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) (id >> (4 * (7 - digit))) & 0xf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) (mask >> (4 * (7 - digit))) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) * looks like: "mipscdmm:tN"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) * N is exactly 2 digits, where each is an upper-case hex digit, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) * a ? or [] pattern matching exactly one digit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static int do_mips_cdmm_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) DEF_FIELD(symval, mips_cdmm_device_id, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) sprintf(alias, "mipscdmm:t%02X*", type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) /* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) * All fields are numbers. It would be nicer to use strings for vendor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) * and feature, but getting those out of the build system here is too
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) * complicated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) static int do_x86cpu_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) DEF_FIELD(symval, x86_cpu_id, feature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) DEF_FIELD(symval, x86_cpu_id, family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) DEF_FIELD(symval, x86_cpu_id, model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) DEF_FIELD(symval, x86_cpu_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) strcpy(alias, "cpu:type:x86,");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) ADD(alias, "fam", family != X86_FAMILY_ANY, family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) ADD(alias, "mod", model != X86_MODEL_ANY, model);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) strcat(alias, ":feature:*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) if (feature != X86_FEATURE_ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) sprintf(alias + strlen(alias), "%04X*", feature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) /* LOOKS like cpu:type:*:feature:*FEAT* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) static int do_cpu_entry(const char *filename, void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) DEF_FIELD(symval, cpu_feature, feature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) /* Looks like: mei:S:uuid:N:* */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) static int do_mei_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) DEF_FIELD_ADDR(symval, mei_cl_device_id, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) DEF_FIELD(symval, mei_cl_device_id, version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) sprintf(alias, MEI_CL_MODULE_PREFIX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) sprintf(alias + strlen(alias), "%s:", (*name)[0] ? *name : "*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) add_uuid(alias, *uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) ADD(alias, ":", version != MEI_CL_VERSION_ANY, version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) strcat(alias, ":*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) /* Looks like: rapidio:vNdNavNadN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) static int do_rio_entry(const char *filename,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) DEF_FIELD(symval, rio_device_id, did);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) DEF_FIELD(symval, rio_device_id, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) DEF_FIELD(symval, rio_device_id, asm_did);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) DEF_FIELD(symval, rio_device_id, asm_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) strcpy(alias, "rapidio:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) ADD(alias, "v", vid != RIO_ANY_ID, vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) ADD(alias, "d", did != RIO_ANY_ID, did);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) /* Looks like: ulpi:vNpN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static int do_ulpi_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) DEF_FIELD(symval, ulpi_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) DEF_FIELD(symval, ulpi_device_id, product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) sprintf(alias, "ulpi:v%04xp%04x", vendor, product);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) /* Looks like: hdaudio:vNrNaN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) static int do_hda_entry(const char *filename, void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) DEF_FIELD(symval, hda_device_id, vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) DEF_FIELD(symval, hda_device_id, rev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) DEF_FIELD(symval, hda_device_id, api_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) strcpy(alias, "hdaudio:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) ADD(alias, "v", vendor_id != 0, vendor_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) ADD(alias, "r", rev_id != 0, rev_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) ADD(alias, "a", api_version != 0, api_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) /* Looks like: sdw:mNpNvNcN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) static int do_sdw_entry(const char *filename, void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) DEF_FIELD(symval, sdw_device_id, mfg_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) DEF_FIELD(symval, sdw_device_id, part_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) DEF_FIELD(symval, sdw_device_id, sdw_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) DEF_FIELD(symval, sdw_device_id, class_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) strcpy(alias, "sdw:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) ADD(alias, "m", mfg_id != 0, mfg_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) ADD(alias, "p", part_id != 0, part_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) ADD(alias, "v", sdw_version != 0, sdw_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) ADD(alias, "c", class_id != 0, class_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /* Looks like: fsl-mc:vNdN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) static int do_fsl_mc_entry(const char *filename, void *symval,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) DEF_FIELD(symval, fsl_mc_device_id, vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) /* Looks like: tbsvc:kSpNvNrN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) static int do_tbsvc_entry(const char *filename, void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) DEF_FIELD(symval, tb_service_id, match_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) DEF_FIELD_ADDR(symval, tb_service_id, protocol_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) DEF_FIELD(symval, tb_service_id, protocol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) DEF_FIELD(symval, tb_service_id, protocol_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) DEF_FIELD(symval, tb_service_id, protocol_revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) strcpy(alias, "tbsvc:");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (match_flags & TBSVC_MATCH_PROTOCOL_KEY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) sprintf(alias + strlen(alias), "k%s", *protocol_key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) strcat(alias + strlen(alias), "k*");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) protocol_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) protocol_revision);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) /* Looks like: typec:idNmN */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) static int do_typec_entry(const char *filename, void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) DEF_FIELD(symval, typec_device_id, svid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) DEF_FIELD(symval, typec_device_id, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) sprintf(alias, "typec:id%04X", svid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) ADD(alias, "m", mode != TYPEC_ANY_MODE, mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) /* Looks like: tee:uuid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) static int do_tee_entry(const char *filename, void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) DEF_FIELD(symval, tee_client_device_id, uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) uuid.b[15]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) add_wildcard(alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) /* Looks like: wmi:guid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) static int do_wmi_entry(const char *filename, void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) DEF_FIELD_ADDR(symval, wmi_device_id, guid_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if (strlen(*guid_string) != UUID_STRING_LEN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) warn("Invalid WMI device id 'wmi:%s' in '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) *guid_string, filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (len < 0 || len >= ALIAS_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) warn("Could not generate all MODULE_ALIAS's in '%s'\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) filename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) /* Looks like: mhi:S */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) static int do_mhi_entry(const char *filename, void *symval, char *alias)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) DEF_FIELD_ADDR(symval, mhi_device_id, chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) /* Does namelen bytes of name exactly match the symbol? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) static bool sym_is(const char *name, unsigned namelen, const char *symbol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) if (namelen != strlen(symbol))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) return memcmp(name, symbol, namelen) == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) static void do_table(void *symval, unsigned long size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) unsigned long id_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) const char *device_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) int (*do_entry)(const char *filename, void *symval, char *alias),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) char alias[ALIAS_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) device_id_check(mod->name, device_id, size, id_size, symval);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) /* Leave last one: it's the terminator. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) size -= id_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) for (i = 0; i < size; i += id_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) if (do_entry(mod->name, symval+i, alias)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) buf_printf(&mod->dev_table_buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) "MODULE_ALIAS(\"%s\");\n", alias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) static const struct devtable devtable[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) {"hid", SIZE_hid_device_id, do_hid_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) {"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) {"pci", SIZE_pci_device_id, do_pci_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) {"ccw", SIZE_ccw_device_id, do_ccw_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) {"ap", SIZE_ap_device_id, do_ap_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) {"css", SIZE_css_device_id, do_css_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) {"serio", SIZE_serio_device_id, do_serio_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) {"acpi", SIZE_acpi_device_id, do_acpi_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) {"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) {"vio", SIZE_vio_device_id, do_vio_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) {"input", SIZE_input_device_id, do_input_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) {"eisa", SIZE_eisa_device_id, do_eisa_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) {"parisc", SIZE_parisc_device_id, do_parisc_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) {"sdio", SIZE_sdio_device_id, do_sdio_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) {"ssb", SIZE_ssb_device_id, do_ssb_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) {"bcma", SIZE_bcma_device_id, do_bcma_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) {"virtio", SIZE_virtio_device_id, do_virtio_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) {"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) {"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) {"i2c", SIZE_i2c_device_id, do_i2c_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) {"i3c", SIZE_i3c_device_id, do_i3c_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) {"spi", SIZE_spi_device_id, do_spi_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) {"dmi", SIZE_dmi_system_id, do_dmi_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) {"platform", SIZE_platform_device_id, do_platform_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {"mdio", SIZE_mdio_device_id, do_mdio_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) {"zorro", SIZE_zorro_device_id, do_zorro_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) {"isapnp", SIZE_isapnp_device_id, do_isapnp_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) {"ipack", SIZE_ipack_device_id, do_ipack_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) {"amba", SIZE_amba_id, do_amba_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) {"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) {"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) {"cpu", SIZE_cpu_feature, do_cpu_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) {"mei", SIZE_mei_cl_device_id, do_mei_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) {"rapidio", SIZE_rio_device_id, do_rio_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) {"ulpi", SIZE_ulpi_device_id, do_ulpi_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) {"hdaudio", SIZE_hda_device_id, do_hda_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) {"sdw", SIZE_sdw_device_id, do_sdw_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) {"typec", SIZE_typec_device_id, do_typec_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) {"tee", SIZE_tee_client_device_id, do_tee_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) {"wmi", SIZE_wmi_device_id, do_wmi_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) {"mhi", SIZE_mhi_device_id, do_mhi_entry},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) /* Create MODULE_ALIAS() statements.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) * At this time, we cannot write the actual output C source yet,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) * so we write into the mod->dev_table_buf buffer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) void handle_moddevtable(struct module *mod, struct elf_info *info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) Elf_Sym *sym, const char *symname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) void *symval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) char *zeros = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) const char *name, *identifier;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) unsigned int namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) /* We're looking for a section relative symbol */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) /* We're looking for an object */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) /* All our symbols are of form __mod_<name>__<identifier>_device_table. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) if (strncmp(symname, "__mod_", strlen("__mod_")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) name = symname + strlen("__mod_");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) namelen = strlen(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) if (namelen < strlen("_device_table"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) if (strcmp(name + namelen - strlen("_device_table"), "_device_table"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) identifier = strstr(name, "__");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) if (!identifier)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) namelen = identifier - name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) /* Handle all-NULL symbols allocated into .bss */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) zeros = calloc(1, sym->st_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) symval = zeros;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) symval = (void *)info->hdr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) + info->sechdrs[get_secindex(info, sym)].sh_offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) + sym->st_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) /* First handle the "special" cases */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) if (sym_is(name, namelen, "usb"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) do_usb_table(symval, sym->st_size, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) if (sym_is(name, namelen, "of"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) do_of_table(symval, sym->st_size, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) else if (sym_is(name, namelen, "pnp"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) do_pnp_device_entry(symval, sym->st_size, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) else if (sym_is(name, namelen, "pnp_card"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) do_pnp_card_entries(symval, sym->st_size, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) for (i = 0; i < ARRAY_SIZE(devtable); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) const struct devtable *p = &devtable[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) if (sym_is(name, namelen, p->device_id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) do_table(symval, sym->st_size, p->id_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) p->device_id, p->do_entry, mod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) free(zeros);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) /* Now add out buffered information to the generated C source */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) void add_moddevtable(struct buffer *buf, struct module *mod)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) buf_printf(buf, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) free(mod->dev_table_buf.p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) }