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