file2alias.c 31 KB

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