home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / scripts / mod / file2alias.c < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-09  |  25.5 KB  |  849 lines

  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.  
  15. /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and
  16.  * use either stdint.h or inttypes.h for the rest. */
  17. #if KERNEL_ELFCLASS == ELFCLASS32
  18. typedef Elf32_Addr    kernel_ulong_t;
  19. #define BITS_PER_LONG 32
  20. #else
  21. typedef Elf64_Addr    kernel_ulong_t;
  22. #define BITS_PER_LONG 64
  23. #endif
  24. #ifdef __sun__
  25. #include <inttypes.h>
  26. #else
  27. #include <stdint.h>
  28. #endif
  29.  
  30. #include <ctype.h>
  31.  
  32. typedef uint32_t    __u32;
  33. typedef uint16_t    __u16;
  34. typedef unsigned char    __u8;
  35.  
  36. /* Big exception to the "don't include kernel headers into userspace, which
  37.  * even potentially has different endianness and word sizes, since
  38.  * we handle those differences explicitly below */
  39. #include "../../include/linux/mod_devicetable.h"
  40.  
  41. #define ADD(str, sep, cond, field)                              \
  42. do {                                                            \
  43.         strcat(str, sep);                                       \
  44.         if (cond)                                               \
  45.                 sprintf(str + strlen(str),                      \
  46.                         sizeof(field) == 1 ? "%02X" :           \
  47.                         sizeof(field) == 2 ? "%04X" :           \
  48.                         sizeof(field) == 4 ? "%08X" : "",       \
  49.                         field);                                 \
  50.         else                                                    \
  51.                 sprintf(str + strlen(str), "*");                \
  52. } while(0)
  53.  
  54. /* Always end in a wildcard, for future extension */
  55. static inline void add_wildcard(char *str)
  56. {
  57.     int len = strlen(str);
  58.  
  59.     if (str[len - 1] != '*')
  60.         strcat(str + len, "*");
  61. }
  62.  
  63. unsigned int cross_build = 0;
  64. /**
  65.  * Check that sizeof(device_id type) are consistent with size of section
  66.  * in .o file. If in-consistent then userspace and kernel does not agree
  67.  * on actual size which is a bug.
  68.  * Also verify that the final entry in the table is all zeros.
  69.  * Ignore both checks if build host differ from target host and size differs.
  70.  **/
  71. static void device_id_check(const char *modname, const char *device_id,
  72.                 unsigned long size, unsigned long id_size,
  73.                 void *symval)
  74. {
  75.     int i;
  76.  
  77.     if (size % id_size || size < id_size) {
  78.         if (cross_build != 0)
  79.             return;
  80.         fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo "
  81.               "of the size of section __mod_%s_device_table=%lu.\n"
  82.               "Fix definition of struct %s_device_id "
  83.               "in mod_devicetable.h\n",
  84.               modname, device_id, id_size, device_id, size, device_id);
  85.     }
  86.     /* Verify last one is a terminator */
  87.     for (i = 0; i < id_size; i++ ) {
  88.         if (*(uint8_t*)(symval+size-id_size+i)) {
  89.             fprintf(stderr,"%s: struct %s_device_id is %lu bytes.  "
  90.                 "The last of %lu is:\n",
  91.                 modname, device_id, id_size, size / id_size);
  92.             for (i = 0; i < id_size; i++ )
  93.                 fprintf(stderr,"0x%02x ",
  94.                     *(uint8_t*)(symval+size-id_size+i) );
  95.             fprintf(stderr,"\n");
  96.             fatal("%s: struct %s_device_id is not terminated "
  97.                 "with a NULL entry!\n", modname, device_id);
  98.         }
  99.     }
  100. }
  101.  
  102. /* USB is special because the bcdDevice can be matched against a numeric range */
  103. /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */
  104. static void do_usb_entry(struct usb_device_id *id,
  105.              unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
  106.              unsigned char range_lo, unsigned char range_hi,
  107.              struct module *mod)
  108. {
  109.     char alias[500];
  110.     strcpy(alias, "usb:");
  111.     ADD(alias, "v", id->match_flags&USB_DEVICE_ID_MATCH_VENDOR,
  112.         id->idVendor);
  113.     ADD(alias, "p", id->match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
  114.         id->idProduct);
  115.  
  116.     strcat(alias, "d");
  117.     if (bcdDevice_initial_digits)
  118.         sprintf(alias + strlen(alias), "%0*X",
  119.             bcdDevice_initial_digits, bcdDevice_initial);
  120.     if (range_lo == range_hi)
  121.         sprintf(alias + strlen(alias), "%u", range_lo);
  122.     else if (range_lo > 0 || range_hi < 9)
  123.         sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi);
  124.     if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
  125.         strcat(alias, "*");
  126.  
  127.     ADD(alias, "dc", id->match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
  128.         id->bDeviceClass);
  129.     ADD(alias, "dsc",
  130.         id->match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
  131.         id->bDeviceSubClass);
  132.     ADD(alias, "dp",
  133.         id->match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
  134.         id->bDeviceProtocol);
  135.     ADD(alias, "ic",
  136.         id->match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
  137.         id->bInterfaceClass);
  138.     ADD(alias, "isc",
  139.         id->match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
  140.         id->bInterfaceSubClass);
  141.     ADD(alias, "ip",
  142.         id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
  143.         id->bInterfaceProtocol);
  144.  
  145.     add_wildcard(alias);
  146.     buf_printf(&mod->dev_table_buf,
  147.            "MODULE_ALIAS(\"%s\");\n", alias);
  148. }
  149.  
  150. static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
  151. {
  152.     unsigned int devlo, devhi;
  153.     unsigned char chi, clo;
  154.     int ndigits;
  155.  
  156.     id->match_flags = TO_NATIVE(id->match_flags);
  157.     id->idVendor = TO_NATIVE(id->idVendor);
  158.     id->idProduct = TO_NATIVE(id->idProduct);
  159.  
  160.     devlo = id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO ?
  161.         TO_NATIVE(id->bcdDevice_lo) : 0x0U;
  162.     devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
  163.         TO_NATIVE(id->bcdDevice_hi) : ~0x0U;
  164.  
  165.     /*
  166.      * Some modules (visor) have empty slots as placeholder for
  167.      * run-time specification that results in catch-all alias
  168.      */
  169.     if (!(id->idVendor | id->idProduct | id->bDeviceClass | id->bInterfaceClass))
  170.         return;
  171.  
  172.     /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */
  173.     for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
  174.         clo = devlo & 0xf;
  175.         chi = devhi & 0xf;
  176.         if (chi > 9)    /* it's bcd not hex */
  177.             chi = 9;
  178.         devlo >>= 4;
  179.         devhi >>= 4;
  180.  
  181.         if (devlo == devhi || !ndigits) {
  182.             do_usb_entry(id, devlo, ndigits, clo, chi, mod);
  183.             break;
  184.         }
  185.  
  186.         if (clo > 0)
  187.             do_usb_entry(id, devlo++, ndigits, clo, 9, mod);
  188.  
  189.         if (chi < 9)
  190.             do_usb_entry(id, devhi--, ndigits, 0, chi, mod);
  191.     }
  192. }
  193.  
  194. static void do_usb_table(void *symval, unsigned long size,
  195.              struct module *mod)
  196. {
  197.     unsigned int i;
  198.     const unsigned long id_size = sizeof(struct usb_device_id);
  199.  
  200.     device_id_check(mod->name, "usb", size, id_size, symval);
  201.  
  202.     /* Leave last one: it's the terminator. */
  203.     size -= id_size;
  204.  
  205.     for (i = 0; i < size; i += id_size)
  206.         do_usb_entry_multi(symval + i, mod);
  207. }
  208.  
  209. /* Looks like: hid:bNvNpN */
  210. static int do_hid_entry(const char *filename,
  211.                  struct hid_device_id *id, char *alias)
  212. {
  213.     id->bus = TO_NATIVE(id->bus);
  214.     id->vendor = TO_NATIVE(id->vendor);
  215.     id->product = TO_NATIVE(id->product);
  216.  
  217.     sprintf(alias, "hid:b%04X", id->bus);
  218.     ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor);
  219.     ADD(alias, "p", id->product != HID_ANY_ID, id->product);
  220.  
  221.     return 1;
  222. }
  223.  
  224. /* Looks like: ieee1394:venNmoNspNverN */
  225. static int do_ieee1394_entry(const char *filename,
  226.                  struct ieee1394_device_id *id, char *alias)
  227. {
  228.     id->match_flags = TO_NATIVE(id->match_flags);
  229.     id->vendor_id = TO_NATIVE(id->vendor_id);
  230.     id->model_id = TO_NATIVE(id->model_id);
  231.     id->specifier_id = TO_NATIVE(id->specifier_id);
  232.     id->version = TO_NATIVE(id->version);
  233.  
  234.     strcpy(alias, "ieee1394:");
  235.     ADD(alias, "ven", id->match_flags & IEEE1394_MATCH_VENDOR_ID,
  236.         id->vendor_id);
  237.     ADD(alias, "mo", id->match_flags & IEEE1394_MATCH_MODEL_ID,
  238.         id->model_id);
  239.     ADD(alias, "sp", id->match_flags & IEEE1394_MATCH_SPECIFIER_ID,
  240.         id->specifier_id);
  241.     ADD(alias, "ver", id->match_flags & IEEE1394_MATCH_VERSION,
  242.         id->version);
  243.  
  244.     add_wildcard(alias);
  245.     return 1;
  246. }
  247.  
  248. /* Looks like: pci:vNdNsvNsdNbcNscNiN. */
  249. static int do_pci_entry(const char *filename,
  250.             struct pci_device_id *id, char *alias)
  251. {
  252.     /* Class field can be divided into these three. */
  253.     unsigned char baseclass, subclass, interface,
  254.         baseclass_mask, subclass_mask, interface_mask;
  255.  
  256.     id->vendor = TO_NATIVE(id->vendor);
  257.     id->device = TO_NATIVE(id->device);
  258.     id->subvendor = TO_NATIVE(id->subvendor);
  259.     id->subdevice = TO_NATIVE(id->subdevice);
  260.     id->class = TO_NATIVE(id->class);
  261.     id->class_mask = TO_NATIVE(id->class_mask);
  262.  
  263.     strcpy(alias, "pci:");
  264.     ADD(alias, "v", id->vendor != PCI_ANY_ID, id->vendor);
  265.     ADD(alias, "d", id->device != PCI_ANY_ID, id->device);
  266.     ADD(alias, "sv", id->subvendor != PCI_ANY_ID, id->subvendor);
  267.     ADD(alias, "sd", id->subdevice != PCI_ANY_ID, id->subdevice);
  268.  
  269.     baseclass = (id->class) >> 16;
  270.     baseclass_mask = (id->class_mask) >> 16;
  271.     subclass = (id->class) >> 8;
  272.     subclass_mask = (id->class_mask) >> 8;
  273.     interface = id->class;
  274.     interface_mask = id->class_mask;
  275.  
  276.     if ((baseclass_mask != 0 && baseclass_mask != 0xFF)
  277.         || (subclass_mask != 0 && subclass_mask != 0xFF)
  278.         || (interface_mask != 0 && interface_mask != 0xFF)) {
  279.         warn("Can't handle masks in %s:%04X\n",
  280.              filename, id->class_mask);
  281.         return 0;
  282.     }
  283.  
  284.     ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
  285.     ADD(alias, "sc", subclass_mask == 0xFF, subclass);
  286.     ADD(alias, "i", interface_mask == 0xFF, interface);
  287.     add_wildcard(alias);
  288.     return 1;
  289. }
  290.  
  291. /* looks like: "ccw:tNmNdtNdmN" */
  292. static int do_ccw_entry(const char *filename,
  293.             struct ccw_device_id *id, char *alias)
  294. {
  295.     id->match_flags = TO_NATIVE(id->match_flags);
  296.     id->cu_type = TO_NATIVE(id->cu_type);
  297.     id->cu_model = TO_NATIVE(id->cu_model);
  298.     id->dev_type = TO_NATIVE(id->dev_type);
  299.     id->dev_model = TO_NATIVE(id->dev_model);
  300.  
  301.     strcpy(alias, "ccw:");
  302.     ADD(alias, "t", id->match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
  303.         id->cu_type);
  304.     ADD(alias, "m", id->match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
  305.         id->cu_model);
  306.     ADD(alias, "dt", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE,
  307.         id->dev_type);
  308.     ADD(alias, "dm", id->match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
  309.         id->dev_model);
  310.     add_wildcard(alias);
  311.     return 1;
  312. }
  313.  
  314. /* looks like: "ap:tN" */
  315. static int do_ap_entry(const char *filename,
  316.                struct ap_device_id *id, char *alias)
  317. {
  318.     sprintf(alias, "ap:t%02X*", id->dev_type);
  319.     return 1;
  320. }
  321.  
  322. /* looks like: "css:tN" */
  323. static int do_css_entry(const char *filename,
  324.             struct css_device_id *id, char *alias)
  325. {
  326.     sprintf(alias, "css:t%01X", id->type);
  327.     return 1;
  328. }
  329.  
  330. /* Looks like: "serio:tyNprNidNexN" */
  331. static int do_serio_entry(const char *filename,
  332.               struct serio_device_id *id, char *alias)
  333. {
  334.     id->type = TO_NATIVE(id->type);
  335.     id->proto = TO_NATIVE(id->proto);
  336.     id->id = TO_NATIVE(id->id);
  337.     id->extra = TO_NATIVE(id->extra);
  338.  
  339.     strcpy(alias, "serio:");
  340.     ADD(alias, "ty", id->type != SERIO_ANY, id->type);
  341.     ADD(alias, "pr", id->proto != SERIO_ANY, id->proto);
  342.     ADD(alias, "id", id->id != SERIO_ANY, id->id);
  343.     ADD(alias, "ex", id->extra != SERIO_ANY, id->extra);
  344.  
  345.     add_wildcard(alias);
  346.     return 1;
  347. }
  348.  
  349. /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */
  350. static int do_acpi_entry(const char *filename,
  351.             struct acpi_device_id *id, char *alias)
  352. {
  353.     sprintf(alias, "acpi*:%s:*", id->id);
  354.     return 1;
  355. }
  356.  
  357. /* looks like: "pnp:dD" */
  358. static void do_pnp_device_entry(void *symval, unsigned long size,
  359.                 struct module *mod)
  360. {
  361.     const unsigned long id_size = sizeof(struct pnp_device_id);
  362.     const unsigned int count = (size / id_size)-1;
  363.     const struct pnp_device_id *devs = symval;
  364.     unsigned int i;
  365.  
  366.     device_id_check(mod->name, "pnp", size, id_size, symval);
  367.  
  368.     for (i = 0; i < count; i++) {
  369.         const char *id = (char *)devs[i].id;
  370.  
  371.         buf_printf(&mod->dev_table_buf,
  372.                "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
  373.         buf_printf(&mod->dev_table_buf,
  374.                "MODULE_ALIAS(\"acpi*:%s:*\");\n", id);
  375.     }
  376. }
  377.  
  378. /* looks like: "pnp:dD" for every device of the card */
  379. static void do_pnp_card_entries(void *symval, unsigned long size,
  380.                 struct module *mod)
  381. {
  382.     const unsigned long id_size = sizeof(struct pnp_card_device_id);
  383.     const unsigned int count = (size / id_size)-1;
  384.     const struct pnp_card_device_id *cards = symval;
  385.     unsigned int i;
  386.  
  387.     device_id_check(mod->name, "pnp", size, id_size, symval);
  388.  
  389.     for (i = 0; i < count; i++) {
  390.         unsigned int j;
  391.         const struct pnp_card_device_id *card = &cards[i];
  392.  
  393.         for (j = 0; j < PNP_MAX_DEVICES; j++) {
  394.             const char *id = (char *)card->devs[j].id;
  395.             int i2, j2;
  396.             int dup = 0;
  397.  
  398.             if (!id[0])
  399.                 break;
  400.  
  401.             /* find duplicate, already added value */
  402.             for (i2 = 0; i2 < i && !dup; i2++) {
  403.                 const struct pnp_card_device_id *card2 = &cards[i2];
  404.  
  405.                 for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
  406.                     const char *id2 = (char *)card2->devs[j2].id;
  407.  
  408.                     if (!id2[0])
  409.                         break;
  410.  
  411.                     if (!strcmp(id, id2)) {
  412.                         dup = 1;
  413.                         break;
  414.                     }
  415.                 }
  416.             }
  417.  
  418.             /* add an individual alias for every device entry */
  419.             if (!dup) {
  420.                 buf_printf(&mod->dev_table_buf,
  421.                        "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
  422.                 buf_printf(&mod->dev_table_buf,
  423.                        "MODULE_ALIAS(\"acpi*:%s:*\");\n", id);
  424.             }
  425.         }
  426.     }
  427. }
  428.  
  429. /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
  430. static int do_pcmcia_entry(const char *filename,
  431.                struct pcmcia_device_id *id, char *alias)
  432. {
  433.     unsigned int i;
  434.  
  435.     id->match_flags = TO_NATIVE(id->match_flags);
  436.     id->manf_id = TO_NATIVE(id->manf_id);
  437.     id->card_id = TO_NATIVE(id->card_id);
  438.     id->func_id = TO_NATIVE(id->func_id);
  439.     id->function = TO_NATIVE(id->function);
  440.     id->device_no = TO_NATIVE(id->device_no);
  441.  
  442.     for (i=0; i<4; i++) {
  443.         id->prod_id_hash[i] = TO_NATIVE(id->prod_id_hash[i]);
  444.        }
  445.  
  446.        strcpy(alias, "pcmcia:");
  447.        ADD(alias, "m", id->match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
  448.        id->manf_id);
  449.        ADD(alias, "c", id->match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
  450.        id->card_id);
  451.        ADD(alias, "f", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID,
  452.        id->func_id);
  453.        ADD(alias, "fn", id->match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION,
  454.        id->function);
  455.        ADD(alias, "pfn", id->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
  456.        id->device_no);
  457.        ADD(alias, "pa", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, id->prod_id_hash[0]);
  458.        ADD(alias, "pb", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, id->prod_id_hash[1]);
  459.        ADD(alias, "pc", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, id->prod_id_hash[2]);
  460.        ADD(alias, "pd", id->match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, id->prod_id_hash[3]);
  461.  
  462.     add_wildcard(alias);
  463.        return 1;
  464. }
  465.  
  466.  
  467.  
  468. static int do_of_entry (const char *filename, struct of_device_id *of, char *alias)
  469. {
  470.     int len;
  471.     char *tmp;
  472.     len = sprintf (alias, "of:N%sT%s",
  473.                     of->name[0] ? of->name : "*",
  474.                     of->type[0] ? of->type : "*");
  475.  
  476.     if (of->compatible[0])
  477.         sprintf (&alias[len], "%sC%s",
  478.                      of->type[0] ? "*" : "",
  479.                      of->compatible);
  480.  
  481.     /* Replace all whitespace with underscores */
  482.     for (tmp = alias; tmp && *tmp; tmp++)
  483.         if (isspace (*tmp))
  484.             *tmp = '_';
  485.  
  486.     add_wildcard(alias);
  487.     return 1;
  488. }
  489.  
  490. static int do_vio_entry(const char *filename, struct vio_device_id *vio,
  491.         char *alias)
  492. {
  493.     char *tmp;
  494.  
  495.     sprintf(alias, "vio:T%sS%s", vio->type[0] ? vio->type : "*",
  496.             vio->compat[0] ? vio->compat : "*");
  497.  
  498.     /* Replace all whitespace with underscores */
  499.     for (tmp = alias; tmp && *tmp; tmp++)
  500.         if (isspace (*tmp))
  501.             *tmp = '_';
  502.  
  503.     add_wildcard(alias);
  504.     return 1;
  505. }
  506.  
  507. #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
  508.  
  509. static void do_input(char *alias,
  510.              kernel_ulong_t *arr, unsigned int min, unsigned int max)
  511. {
  512.     unsigned int i;
  513.  
  514.     for (i = min; i < max; i++)
  515.         if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG)))
  516.             sprintf(alias + strlen(alias), "%X,*", i);
  517. }
  518.  
  519. /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
  520. static int do_input_entry(const char *filename, struct input_device_id *id,
  521.               char *alias)
  522. {
  523.     sprintf(alias, "input:");
  524.  
  525.     ADD(alias, "b", id->flags & INPUT_DEVICE_ID_MATCH_BUS, id->bustype);
  526.     ADD(alias, "v", id->flags & INPUT_DEVICE_ID_MATCH_VENDOR, id->vendor);
  527.     ADD(alias, "p", id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT, id->product);
  528.     ADD(alias, "e", id->flags & INPUT_DEVICE_ID_MATCH_VERSION, id->version);
  529.  
  530.     sprintf(alias + strlen(alias), "-e*");
  531.     if (id->flags & INPUT_DEVICE_ID_MATCH_EVBIT)
  532.         do_input(alias, id->evbit, 0, INPUT_DEVICE_ID_EV_MAX);
  533.     sprintf(alias + strlen(alias), "k*");
  534.     if (id->flags & INPUT_DEVICE_ID_MATCH_KEYBIT)
  535.         do_input(alias, id->keybit,
  536.              INPUT_DEVICE_ID_KEY_MIN_INTERESTING,
  537.              INPUT_DEVICE_ID_KEY_MAX);
  538.     sprintf(alias + strlen(alias), "r*");
  539.     if (id->flags & INPUT_DEVICE_ID_MATCH_RELBIT)
  540.         do_input(alias, id->relbit, 0, INPUT_DEVICE_ID_REL_MAX);
  541.     sprintf(alias + strlen(alias), "a*");
  542.     if (id->flags & INPUT_DEVICE_ID_MATCH_ABSBIT)
  543.         do_input(alias, id->absbit, 0, INPUT_DEVICE_ID_ABS_MAX);
  544.     sprintf(alias + strlen(alias), "m*");
  545.     if (id->flags & INPUT_DEVICE_ID_MATCH_MSCIT)
  546.         do_input(alias, id->mscbit, 0, INPUT_DEVICE_ID_MSC_MAX);
  547.     sprintf(alias + strlen(alias), "l*");
  548.     if (id->flags & INPUT_DEVICE_ID_MATCH_LEDBIT)
  549.         do_input(alias, id->ledbit, 0, INPUT_DEVICE_ID_LED_MAX);
  550.     sprintf(alias + strlen(alias), "s*");
  551.     if (id->flags & INPUT_DEVICE_ID_MATCH_SNDBIT)
  552.         do_input(alias, id->sndbit, 0, INPUT_DEVICE_ID_SND_MAX);
  553.     sprintf(alias + strlen(alias), "f*");
  554.     if (id->flags & INPUT_DEVICE_ID_MATCH_FFBIT)
  555.         do_input(alias, id->ffbit, 0, INPUT_DEVICE_ID_FF_MAX);
  556.     sprintf(alias + strlen(alias), "w*");
  557.     if (id->flags & INPUT_DEVICE_ID_MATCH_SWBIT)
  558.         do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX);
  559.     return 1;
  560. }
  561.  
  562. static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa,
  563.         char *alias)
  564. {
  565.     if (eisa->sig[0])
  566.         sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", eisa->sig);
  567.     else
  568.         strcat(alias, "*");
  569.     return 1;
  570. }
  571.  
  572. /* Looks like: parisc:tNhvNrevNsvN */
  573. static int do_parisc_entry(const char *filename, struct parisc_device_id *id,
  574.         char *alias)
  575. {
  576.     id->hw_type = TO_NATIVE(id->hw_type);
  577.     id->hversion = TO_NATIVE(id->hversion);
  578.     id->hversion_rev = TO_NATIVE(id->hversion_rev);
  579.     id->sversion = TO_NATIVE(id->sversion);
  580.  
  581.     strcpy(alias, "parisc:");
  582.     ADD(alias, "t", id->hw_type != PA_HWTYPE_ANY_ID, id->hw_type);
  583.     ADD(alias, "hv", id->hversion != PA_HVERSION_ANY_ID, id->hversion);
  584.     ADD(alias, "rev", id->hversion_rev != PA_HVERSION_REV_ANY_ID, id->hversion_rev);
  585.     ADD(alias, "sv", id->sversion != PA_SVERSION_ANY_ID, id->sversion);
  586.  
  587.     add_wildcard(alias);
  588.     return 1;
  589. }
  590.  
  591. /* Looks like: sdio:cNvNdN. */
  592. static int do_sdio_entry(const char *filename,
  593.             struct sdio_device_id *id, char *alias)
  594. {
  595.     id->class = TO_NATIVE(id->class);
  596.     id->vendor = TO_NATIVE(id->vendor);
  597.     id->device = TO_NATIVE(id->device);
  598.  
  599.     strcpy(alias, "sdio:");
  600.     ADD(alias, "c", id->class != (__u8)SDIO_ANY_ID, id->class);
  601.     ADD(alias, "v", id->vendor != (__u16)SDIO_ANY_ID, id->vendor);
  602.     ADD(alias, "d", id->device != (__u16)SDIO_ANY_ID, id->device);
  603.     add_wildcard(alias);
  604.     return 1;
  605. }
  606.  
  607. /* Looks like: ssb:vNidNrevN. */
  608. static int do_ssb_entry(const char *filename,
  609.             struct ssb_device_id *id, char *alias)
  610. {
  611.     id->vendor = TO_NATIVE(id->vendor);
  612.     id->coreid = TO_NATIVE(id->coreid);
  613.     id->revision = TO_NATIVE(id->revision);
  614.  
  615.     strcpy(alias, "ssb:");
  616.     ADD(alias, "v", id->vendor != SSB_ANY_VENDOR, id->vendor);
  617.     ADD(alias, "id", id->coreid != SSB_ANY_ID, id->coreid);
  618.     ADD(alias, "rev", id->revision != SSB_ANY_REV, id->revision);
  619.     add_wildcard(alias);
  620.     return 1;
  621. }
  622.  
  623. /* Looks like: virtio:dNvN */
  624. static int do_virtio_entry(const char *filename, struct virtio_device_id *id,
  625.                char *alias)
  626. {
  627.     id->device = TO_NATIVE(id->device);
  628.     id->vendor = TO_NATIVE(id->vendor);
  629.  
  630.     strcpy(alias, "virtio:");
  631.     ADD(alias, "d", 1, id->device);
  632.     ADD(alias, "v", id->vendor != VIRTIO_DEV_ANY_ID, id->vendor);
  633.  
  634.     add_wildcard(alias);
  635.     return 1;
  636. }
  637.  
  638. /* Looks like: i2c:S */
  639. static int do_i2c_entry(const char *filename, struct i2c_device_id *id,
  640.             char *alias)
  641. {
  642.     sprintf(alias, I2C_MODULE_PREFIX "%s", id->name);
  643.  
  644.     return 1;
  645. }
  646.  
  647. static const struct dmifield {
  648.     const char *prefix;
  649.     int field;
  650. } dmi_fields[] = {
  651.     { "bvn", DMI_BIOS_VENDOR },
  652.     { "bvr", DMI_BIOS_VERSION },
  653.     { "bd",  DMI_BIOS_DATE },
  654.     { "svn", DMI_SYS_VENDOR },
  655.     { "pn",  DMI_PRODUCT_NAME },
  656.     { "pvr", DMI_PRODUCT_VERSION },
  657.     { "rvn", DMI_BOARD_VENDOR },
  658.     { "rn",  DMI_BOARD_NAME },
  659.     { "rvr", DMI_BOARD_VERSION },
  660.     { "cvn", DMI_CHASSIS_VENDOR },
  661.     { "ct",  DMI_CHASSIS_TYPE },
  662.     { "cvr", DMI_CHASSIS_VERSION },
  663.     { NULL,  DMI_NONE }
  664. };
  665.  
  666. static void dmi_ascii_filter(char *d, const char *s)
  667. {
  668.     /* Filter out characters we don't want to see in the modalias string */
  669.     for (; *s; s++)
  670.         if (*s > ' ' && *s < 127 && *s != ':')
  671.             *(d++) = *s;
  672.  
  673.     *d = 0;
  674. }
  675.  
  676.  
  677. static int do_dmi_entry(const char *filename, struct dmi_system_id *id,
  678.             char *alias)
  679. {
  680.     int i, j;
  681.  
  682.     sprintf(alias, "dmi*");
  683.  
  684.     for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
  685.         for (j = 0; j < 4; j++) {
  686.             if (id->matches[j].slot &&
  687.                 id->matches[j].slot == dmi_fields[i].field) {
  688.                 sprintf(alias + strlen(alias), ":%s*",
  689.                     dmi_fields[i].prefix);
  690.                 dmi_ascii_filter(alias + strlen(alias),
  691.                          id->matches[j].substr);
  692.                 strcat(alias, "*");
  693.             }
  694.         }
  695.     }
  696.  
  697.     strcat(alias, ":");
  698.     return 1;
  699. }
  700. /* Ignore any prefix, eg. some architectures prepend _ */
  701. static inline int sym_is(const char *symbol, const char *name)
  702. {
  703.     const char *match;
  704.  
  705.     match = strstr(symbol, name);
  706.     if (!match)
  707.         return 0;
  708.     return match[strlen(symbol)] == '\0';
  709. }
  710.  
  711. static void do_table(void *symval, unsigned long size,
  712.              unsigned long id_size,
  713.              const char *device_id,
  714.              void *function,
  715.              struct module *mod)
  716. {
  717.     unsigned int i;
  718.     char alias[500];
  719.     int (*do_entry)(const char *, void *entry, char *alias) = function;
  720.  
  721.     device_id_check(mod->name, device_id, size, id_size, symval);
  722.     /* Leave last one: it's the terminator. */
  723.     size -= id_size;
  724.  
  725.     for (i = 0; i < size; i += id_size) {
  726.         if (do_entry(mod->name, symval+i, alias)) {
  727.             buf_printf(&mod->dev_table_buf,
  728.                    "MODULE_ALIAS(\"%s\");\n", alias);
  729.         }
  730.     }
  731. }
  732.  
  733. /* Create MODULE_ALIAS() statements.
  734.  * At this time, we cannot write the actual output C source yet,
  735.  * so we write into the mod->dev_table_buf buffer. */
  736. void handle_moddevtable(struct module *mod, struct elf_info *info,
  737.             Elf_Sym *sym, const char *symname)
  738. {
  739.     void *symval;
  740.     char *zeros = NULL;
  741.  
  742.     /* We're looking for a section relative symbol */
  743.     if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum)
  744.         return;
  745.  
  746.     /* Handle all-NULL symbols allocated into .bss */
  747.     if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) {
  748.         zeros = calloc(1, sym->st_size);
  749.         symval = zeros;
  750.     } else {
  751.         symval = (void *)info->hdr
  752.             + info->sechdrs[sym->st_shndx].sh_offset
  753.             + sym->st_value;
  754.     }
  755.  
  756.     if (sym_is(symname, "__mod_pci_device_table"))
  757.         do_table(symval, sym->st_size,
  758.              sizeof(struct pci_device_id), "pci",
  759.              do_pci_entry, mod);
  760.     else if (sym_is(symname, "__mod_usb_device_table"))
  761.         /* special case to handle bcdDevice ranges */
  762.         do_usb_table(symval, sym->st_size, mod);
  763.     else if (sym_is(symname, "__mod_hid_device_table"))
  764.         do_table(symval, sym->st_size,
  765.              sizeof(struct hid_device_id), "hid",
  766.              do_hid_entry, mod);
  767.     else if (sym_is(symname, "__mod_ieee1394_device_table"))
  768.         do_table(symval, sym->st_size,
  769.              sizeof(struct ieee1394_device_id), "ieee1394",
  770.              do_ieee1394_entry, mod);
  771.     else if (sym_is(symname, "__mod_ccw_device_table"))
  772.         do_table(symval, sym->st_size,
  773.              sizeof(struct ccw_device_id), "ccw",
  774.              do_ccw_entry, mod);
  775.     else if (sym_is(symname, "__mod_ap_device_table"))
  776.         do_table(symval, sym->st_size,
  777.              sizeof(struct ap_device_id), "ap",
  778.              do_ap_entry, mod);
  779.     else if (sym_is(symname, "__mod_css_device_table"))
  780.         do_table(symval, sym->st_size,
  781.              sizeof(struct css_device_id), "css",
  782.              do_css_entry, mod);
  783.     else if (sym_is(symname, "__mod_serio_device_table"))
  784.         do_table(symval, sym->st_size,
  785.              sizeof(struct serio_device_id), "serio",
  786.              do_serio_entry, mod);
  787.     else if (sym_is(symname, "__mod_acpi_device_table"))
  788.         do_table(symval, sym->st_size,
  789.              sizeof(struct acpi_device_id), "acpi",
  790.              do_acpi_entry, mod);
  791.     else if (sym_is(symname, "__mod_pnp_device_table"))
  792.         do_pnp_device_entry(symval, sym->st_size, mod);
  793.     else if (sym_is(symname, "__mod_pnp_card_device_table"))
  794.         do_pnp_card_entries(symval, sym->st_size, mod);
  795.     else if (sym_is(symname, "__mod_pcmcia_device_table"))
  796.         do_table(symval, sym->st_size,
  797.              sizeof(struct pcmcia_device_id), "pcmcia",
  798.              do_pcmcia_entry, mod);
  799.         else if (sym_is(symname, "__mod_of_device_table"))
  800.         do_table(symval, sym->st_size,
  801.              sizeof(struct of_device_id), "of",
  802.              do_of_entry, mod);
  803.         else if (sym_is(symname, "__mod_vio_device_table"))
  804.         do_table(symval, sym->st_size,
  805.              sizeof(struct vio_device_id), "vio",
  806.              do_vio_entry, mod);
  807.     else if (sym_is(symname, "__mod_input_device_table"))
  808.         do_table(symval, sym->st_size,
  809.              sizeof(struct input_device_id), "input",
  810.              do_input_entry, mod);
  811.     else if (sym_is(symname, "__mod_eisa_device_table"))
  812.         do_table(symval, sym->st_size,
  813.              sizeof(struct eisa_device_id), "eisa",
  814.              do_eisa_entry, mod);
  815.     else if (sym_is(symname, "__mod_parisc_device_table"))
  816.         do_table(symval, sym->st_size,
  817.              sizeof(struct parisc_device_id), "parisc",
  818.              do_parisc_entry, mod);
  819.     else if (sym_is(symname, "__mod_sdio_device_table"))
  820.         do_table(symval, sym->st_size,
  821.              sizeof(struct sdio_device_id), "sdio",
  822.              do_sdio_entry, mod);
  823.     else if (sym_is(symname, "__mod_ssb_device_table"))
  824.         do_table(symval, sym->st_size,
  825.              sizeof(struct ssb_device_id), "ssb",
  826.              do_ssb_entry, mod);
  827.     else if (sym_is(symname, "__mod_virtio_device_table"))
  828.         do_table(symval, sym->st_size,
  829.              sizeof(struct virtio_device_id), "virtio",
  830.              do_virtio_entry, mod);
  831.     else if (sym_is(symname, "__mod_i2c_device_table"))
  832.         do_table(symval, sym->st_size,
  833.              sizeof(struct i2c_device_id), "i2c",
  834.              do_i2c_entry, mod);
  835.     else if (sym_is(symname, "__mod_dmi_device_table"))
  836.         do_table(symval, sym->st_size,
  837.              sizeof(struct dmi_system_id), "dmi",
  838.              do_dmi_entry, mod);
  839.     free(zeros);
  840. }
  841.  
  842. /* Now add out buffered information to the generated C source */
  843. void add_moddevtable(struct buffer *buf, struct module *mod)
  844. {
  845.     buf_printf(buf, "\n");
  846.     buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
  847.     free(mod->dev_table_buf.p);
  848. }
  849.