file2alias.c 30 KB

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