diff options
Diffstat (limited to 'scripts/mod/file2alias.c')
-rw-r--r-- | scripts/mod/file2alias.c | 374 |
1 files changed, 115 insertions, 259 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index df4fc23dd83..e26e2fb462d 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -28,7 +28,6 @@ typedef Elf64_Addr kernel_ulong_t; | |||
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | #include <ctype.h> | 30 | #include <ctype.h> |
31 | #include <stdbool.h> | ||
32 | 31 | ||
33 | typedef uint32_t __u32; | 32 | typedef uint32_t __u32; |
34 | typedef uint16_t __u16; | 33 | typedef uint16_t __u16; |
@@ -39,61 +38,6 @@ typedef unsigned char __u8; | |||
39 | * we handle those differences explicitly below */ | 38 | * we handle those differences explicitly below */ |
40 | #include "../../include/linux/mod_devicetable.h" | 39 | #include "../../include/linux/mod_devicetable.h" |
41 | 40 | ||
42 | /* This array collects all instances that use the generic do_table */ | ||
43 | struct devtable { | ||
44 | const char *device_id; /* name of table, __mod_<name>_device_table. */ | ||
45 | unsigned long id_size; | ||
46 | void *function; | ||
47 | }; | ||
48 | |||
49 | #define ___cat(a,b) a ## b | ||
50 | #define __cat(a,b) ___cat(a,b) | ||
51 | |||
52 | /* we need some special handling for this host tool running eventually on | ||
53 | * Darwin. The Mach-O section handling is a bit different than ELF section | ||
54 | * handling. The differnces in detail are: | ||
55 | * a) we have segments which have sections | ||
56 | * b) we need a API call to get the respective section symbols */ | ||
57 | #if defined(__MACH__) | ||
58 | #include <mach-o/getsect.h> | ||
59 | |||
60 | #define INIT_SECTION(name) do { \ | ||
61 | unsigned long name ## _len; \ | ||
62 | char *__cat(pstart_,name) = getsectdata("__TEXT", \ | ||
63 | #name, &__cat(name,_len)); \ | ||
64 | char *__cat(pstop_,name) = __cat(pstart_,name) + \ | ||
65 | __cat(name, _len); \ | ||
66 | __cat(__start_,name) = (void *)__cat(pstart_,name); \ | ||
67 | __cat(__stop_,name) = (void *)__cat(pstop_,name); \ | ||
68 | } while (0) | ||
69 | #define SECTION(name) __attribute__((section("__TEXT, " #name))) | ||
70 | |||
71 | struct devtable **__start___devtable, **__stop___devtable; | ||
72 | #else | ||
73 | #define INIT_SECTION(name) /* no-op for ELF */ | ||
74 | #define SECTION(name) __attribute__((section(#name))) | ||
75 | |||
76 | /* We construct a table of pointers in an ELF section (pointers generally | ||
77 | * go unpadded by gcc). ld creates boundary syms for us. */ | ||
78 | extern struct devtable *__start___devtable[], *__stop___devtable[]; | ||
79 | #endif /* __MACH__ */ | ||
80 | |||
81 | #if __GNUC__ == 3 && __GNUC_MINOR__ < 3 | ||
82 | # define __used __attribute__((__unused__)) | ||
83 | #else | ||
84 | # define __used __attribute__((__used__)) | ||
85 | #endif | ||
86 | |||
87 | /* Add a table entry. We test function type matches while we're here. */ | ||
88 | #define ADD_TO_DEVTABLE(device_id, type, function) \ | ||
89 | static struct devtable __cat(devtable,__LINE__) = { \ | ||
90 | device_id + 0*sizeof((function)((const char *)NULL, \ | ||
91 | (type *)NULL, \ | ||
92 | (char *)NULL)), \ | ||
93 | sizeof(type), (function) }; \ | ||
94 | static struct devtable *SECTION(__devtable) __used \ | ||
95 | __cat(devtable_ptr,__LINE__) = &__cat(devtable,__LINE__) | ||
96 | |||
97 | #define ADD(str, sep, cond, field) \ | 41 | #define ADD(str, sep, cond, field) \ |
98 | do { \ | 42 | do { \ |
99 | strcat(str, sep); \ | 43 | strcat(str, sep); \ |
@@ -156,7 +100,7 @@ static void device_id_check(const char *modname, const char *device_id, | |||
156 | } | 100 | } |
157 | 101 | ||
158 | /* USB is special because the bcdDevice can be matched against a numeric range */ | 102 | /* USB is special because the bcdDevice can be matched against a numeric range */ |
159 | /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */ | 103 | /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipN" */ |
160 | static void do_usb_entry(struct usb_device_id *id, | 104 | static void do_usb_entry(struct usb_device_id *id, |
161 | unsigned int bcdDevice_initial, int bcdDevice_initial_digits, | 105 | unsigned int bcdDevice_initial, int bcdDevice_initial_digits, |
162 | unsigned char range_lo, unsigned char range_hi, | 106 | unsigned char range_lo, unsigned char range_hi, |
@@ -210,9 +154,6 @@ static void do_usb_entry(struct usb_device_id *id, | |||
210 | ADD(alias, "ip", | 154 | ADD(alias, "ip", |
211 | id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, | 155 | id->match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, |
212 | id->bInterfaceProtocol); | 156 | id->bInterfaceProtocol); |
213 | ADD(alias, "in", | ||
214 | id->match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER, | ||
215 | id->bInterfaceNumber); | ||
216 | 157 | ||
217 | add_wildcard(alias); | 158 | add_wildcard(alias); |
218 | buf_printf(&mod->dev_table_buf, | 159 | buf_printf(&mod->dev_table_buf, |
@@ -339,19 +280,15 @@ static int do_hid_entry(const char *filename, | |||
339 | struct hid_device_id *id, char *alias) | 280 | struct hid_device_id *id, char *alias) |
340 | { | 281 | { |
341 | id->bus = TO_NATIVE(id->bus); | 282 | id->bus = TO_NATIVE(id->bus); |
342 | id->group = TO_NATIVE(id->group); | ||
343 | id->vendor = TO_NATIVE(id->vendor); | 283 | id->vendor = TO_NATIVE(id->vendor); |
344 | id->product = TO_NATIVE(id->product); | 284 | id->product = TO_NATIVE(id->product); |
345 | 285 | ||
346 | sprintf(alias, "hid:"); | 286 | sprintf(alias, "hid:b%04X", id->bus); |
347 | ADD(alias, "b", id->bus != HID_BUS_ANY, id->bus); | ||
348 | ADD(alias, "g", id->group != HID_GROUP_ANY, id->group); | ||
349 | ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor); | 287 | ADD(alias, "v", id->vendor != HID_ANY_ID, id->vendor); |
350 | ADD(alias, "p", id->product != HID_ANY_ID, id->product); | 288 | ADD(alias, "p", id->product != HID_ANY_ID, id->product); |
351 | 289 | ||
352 | return 1; | 290 | return 1; |
353 | } | 291 | } |
354 | ADD_TO_DEVTABLE("hid", struct hid_device_id, do_hid_entry); | ||
355 | 292 | ||
356 | /* Looks like: ieee1394:venNmoNspNverN */ | 293 | /* Looks like: ieee1394:venNmoNspNverN */ |
357 | static int do_ieee1394_entry(const char *filename, | 294 | static int do_ieee1394_entry(const char *filename, |
@@ -376,7 +313,6 @@ static int do_ieee1394_entry(const char *filename, | |||
376 | add_wildcard(alias); | 313 | add_wildcard(alias); |
377 | return 1; | 314 | return 1; |
378 | } | 315 | } |
379 | ADD_TO_DEVTABLE("ieee1394", struct ieee1394_device_id, do_ieee1394_entry); | ||
380 | 316 | ||
381 | /* Looks like: pci:vNdNsvNsdNbcNscNiN. */ | 317 | /* Looks like: pci:vNdNsvNsdNbcNscNiN. */ |
382 | static int do_pci_entry(const char *filename, | 318 | static int do_pci_entry(const char *filename, |
@@ -420,7 +356,6 @@ static int do_pci_entry(const char *filename, | |||
420 | add_wildcard(alias); | 356 | add_wildcard(alias); |
421 | return 1; | 357 | return 1; |
422 | } | 358 | } |
423 | ADD_TO_DEVTABLE("pci", struct pci_device_id, do_pci_entry); | ||
424 | 359 | ||
425 | /* looks like: "ccw:tNmNdtNdmN" */ | 360 | /* looks like: "ccw:tNmNdtNdmN" */ |
426 | static int do_ccw_entry(const char *filename, | 361 | static int do_ccw_entry(const char *filename, |
@@ -444,7 +379,6 @@ static int do_ccw_entry(const char *filename, | |||
444 | add_wildcard(alias); | 379 | add_wildcard(alias); |
445 | return 1; | 380 | return 1; |
446 | } | 381 | } |
447 | ADD_TO_DEVTABLE("ccw", struct ccw_device_id, do_ccw_entry); | ||
448 | 382 | ||
449 | /* looks like: "ap:tN" */ | 383 | /* looks like: "ap:tN" */ |
450 | static int do_ap_entry(const char *filename, | 384 | static int do_ap_entry(const char *filename, |
@@ -453,7 +387,6 @@ static int do_ap_entry(const char *filename, | |||
453 | sprintf(alias, "ap:t%02X*", id->dev_type); | 387 | sprintf(alias, "ap:t%02X*", id->dev_type); |
454 | return 1; | 388 | return 1; |
455 | } | 389 | } |
456 | ADD_TO_DEVTABLE("ap", struct ap_device_id, do_ap_entry); | ||
457 | 390 | ||
458 | /* looks like: "css:tN" */ | 391 | /* looks like: "css:tN" */ |
459 | static int do_css_entry(const char *filename, | 392 | static int do_css_entry(const char *filename, |
@@ -462,7 +395,6 @@ static int do_css_entry(const char *filename, | |||
462 | sprintf(alias, "css:t%01X", id->type); | 395 | sprintf(alias, "css:t%01X", id->type); |
463 | return 1; | 396 | return 1; |
464 | } | 397 | } |
465 | ADD_TO_DEVTABLE("css", struct css_device_id, do_css_entry); | ||
466 | 398 | ||
467 | /* Looks like: "serio:tyNprNidNexN" */ | 399 | /* Looks like: "serio:tyNprNidNexN" */ |
468 | static int do_serio_entry(const char *filename, | 400 | static int do_serio_entry(const char *filename, |
@@ -482,7 +414,6 @@ static int do_serio_entry(const char *filename, | |||
482 | add_wildcard(alias); | 414 | add_wildcard(alias); |
483 | return 1; | 415 | return 1; |
484 | } | 416 | } |
485 | ADD_TO_DEVTABLE("serio", struct serio_device_id, do_serio_entry); | ||
486 | 417 | ||
487 | /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */ | 418 | /* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" or "acpi:LNXVIDEO" */ |
488 | static int do_acpi_entry(const char *filename, | 419 | static int do_acpi_entry(const char *filename, |
@@ -491,7 +422,6 @@ static int do_acpi_entry(const char *filename, | |||
491 | sprintf(alias, "acpi*:%s:*", id->id); | 422 | sprintf(alias, "acpi*:%s:*", id->id); |
492 | return 1; | 423 | return 1; |
493 | } | 424 | } |
494 | ADD_TO_DEVTABLE("acpi", struct acpi_device_id, do_acpi_entry); | ||
495 | 425 | ||
496 | /* looks like: "pnp:dD" */ | 426 | /* looks like: "pnp:dD" */ |
497 | static void do_pnp_device_entry(void *symval, unsigned long size, | 427 | static void do_pnp_device_entry(void *symval, unsigned long size, |
@@ -614,7 +544,8 @@ static int do_pcmcia_entry(const char *filename, | |||
614 | add_wildcard(alias); | 544 | add_wildcard(alias); |
615 | return 1; | 545 | return 1; |
616 | } | 546 | } |
617 | ADD_TO_DEVTABLE("pcmcia", struct pcmcia_device_id, do_pcmcia_entry); | 547 | |
548 | |||
618 | 549 | ||
619 | static int do_of_entry (const char *filename, struct of_device_id *of, char *alias) | 550 | static int do_of_entry (const char *filename, struct of_device_id *of, char *alias) |
620 | { | 551 | { |
@@ -637,7 +568,6 @@ static int do_of_entry (const char *filename, struct of_device_id *of, char *ali | |||
637 | add_wildcard(alias); | 568 | add_wildcard(alias); |
638 | return 1; | 569 | return 1; |
639 | } | 570 | } |
640 | ADD_TO_DEVTABLE("of", struct of_device_id, do_of_entry); | ||
641 | 571 | ||
642 | static int do_vio_entry(const char *filename, struct vio_device_id *vio, | 572 | static int do_vio_entry(const char *filename, struct vio_device_id *vio, |
643 | char *alias) | 573 | char *alias) |
@@ -655,7 +585,6 @@ static int do_vio_entry(const char *filename, struct vio_device_id *vio, | |||
655 | add_wildcard(alias); | 585 | add_wildcard(alias); |
656 | return 1; | 586 | return 1; |
657 | } | 587 | } |
658 | ADD_TO_DEVTABLE("vio", struct vio_device_id, do_vio_entry); | ||
659 | 588 | ||
660 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) | 589 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
661 | 590 | ||
@@ -711,7 +640,6 @@ static int do_input_entry(const char *filename, struct input_device_id *id, | |||
711 | do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX); | 640 | do_input(alias, id->swbit, 0, INPUT_DEVICE_ID_SW_MAX); |
712 | return 1; | 641 | return 1; |
713 | } | 642 | } |
714 | ADD_TO_DEVTABLE("input", struct input_device_id, do_input_entry); | ||
715 | 643 | ||
716 | static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa, | 644 | static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa, |
717 | char *alias) | 645 | char *alias) |
@@ -722,7 +650,6 @@ static int do_eisa_entry(const char *filename, struct eisa_device_id *eisa, | |||
722 | strcat(alias, "*"); | 650 | strcat(alias, "*"); |
723 | return 1; | 651 | return 1; |
724 | } | 652 | } |
725 | ADD_TO_DEVTABLE("eisa", struct eisa_device_id, do_eisa_entry); | ||
726 | 653 | ||
727 | /* Looks like: parisc:tNhvNrevNsvN */ | 654 | /* Looks like: parisc:tNhvNrevNsvN */ |
728 | static int do_parisc_entry(const char *filename, struct parisc_device_id *id, | 655 | static int do_parisc_entry(const char *filename, struct parisc_device_id *id, |
@@ -742,7 +669,6 @@ static int do_parisc_entry(const char *filename, struct parisc_device_id *id, | |||
742 | add_wildcard(alias); | 669 | add_wildcard(alias); |
743 | return 1; | 670 | return 1; |
744 | } | 671 | } |
745 | ADD_TO_DEVTABLE("parisc", struct parisc_device_id, do_parisc_entry); | ||
746 | 672 | ||
747 | /* Looks like: sdio:cNvNdN. */ | 673 | /* Looks like: sdio:cNvNdN. */ |
748 | static int do_sdio_entry(const char *filename, | 674 | static int do_sdio_entry(const char *filename, |
@@ -759,7 +685,6 @@ static int do_sdio_entry(const char *filename, | |||
759 | add_wildcard(alias); | 685 | add_wildcard(alias); |
760 | return 1; | 686 | return 1; |
761 | } | 687 | } |
762 | ADD_TO_DEVTABLE("sdio", struct sdio_device_id, do_sdio_entry); | ||
763 | 688 | ||
764 | /* Looks like: ssb:vNidNrevN. */ | 689 | /* Looks like: ssb:vNidNrevN. */ |
765 | static int do_ssb_entry(const char *filename, | 690 | static int do_ssb_entry(const char *filename, |
@@ -776,7 +701,6 @@ static int do_ssb_entry(const char *filename, | |||
776 | add_wildcard(alias); | 701 | add_wildcard(alias); |
777 | return 1; | 702 | return 1; |
778 | } | 703 | } |
779 | ADD_TO_DEVTABLE("ssb", struct ssb_device_id, do_ssb_entry); | ||
780 | 704 | ||
781 | /* Looks like: bcma:mNidNrevNclN. */ | 705 | /* Looks like: bcma:mNidNrevNclN. */ |
782 | static int do_bcma_entry(const char *filename, | 706 | static int do_bcma_entry(const char *filename, |
@@ -795,7 +719,6 @@ static int do_bcma_entry(const char *filename, | |||
795 | add_wildcard(alias); | 719 | add_wildcard(alias); |
796 | return 1; | 720 | return 1; |
797 | } | 721 | } |
798 | ADD_TO_DEVTABLE("bcma", struct bcma_device_id, do_bcma_entry); | ||
799 | 722 | ||
800 | /* Looks like: virtio:dNvN */ | 723 | /* Looks like: virtio:dNvN */ |
801 | static int do_virtio_entry(const char *filename, struct virtio_device_id *id, | 724 | static int do_virtio_entry(const char *filename, struct virtio_device_id *id, |
@@ -811,29 +734,6 @@ static int do_virtio_entry(const char *filename, struct virtio_device_id *id, | |||
811 | add_wildcard(alias); | 734 | add_wildcard(alias); |
812 | return 1; | 735 | return 1; |
813 | } | 736 | } |
814 | ADD_TO_DEVTABLE("virtio", struct virtio_device_id, do_virtio_entry); | ||
815 | |||
816 | /* | ||
817 | * Looks like: vmbus:guid | ||
818 | * Each byte of the guid will be represented by two hex characters | ||
819 | * in the name. | ||
820 | */ | ||
821 | |||
822 | static int do_vmbus_entry(const char *filename, struct hv_vmbus_device_id *id, | ||
823 | char *alias) | ||
824 | { | ||
825 | int i; | ||
826 | char guid_name[((sizeof(id->guid) + 1)) * 2]; | ||
827 | |||
828 | for (i = 0; i < (sizeof(id->guid) * 2); i += 2) | ||
829 | sprintf(&guid_name[i], "%02x", id->guid[i/2]); | ||
830 | |||
831 | strcpy(alias, "vmbus:"); | ||
832 | strcat(alias, guid_name); | ||
833 | |||
834 | return 1; | ||
835 | } | ||
836 | ADD_TO_DEVTABLE("vmbus", struct hv_vmbus_device_id, do_vmbus_entry); | ||
837 | 737 | ||
838 | /* Looks like: i2c:S */ | 738 | /* Looks like: i2c:S */ |
839 | static int do_i2c_entry(const char *filename, struct i2c_device_id *id, | 739 | static int do_i2c_entry(const char *filename, struct i2c_device_id *id, |
@@ -843,7 +743,6 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id, | |||
843 | 743 | ||
844 | return 1; | 744 | return 1; |
845 | } | 745 | } |
846 | ADD_TO_DEVTABLE("i2c", struct i2c_device_id, do_i2c_entry); | ||
847 | 746 | ||
848 | /* Looks like: spi:S */ | 747 | /* Looks like: spi:S */ |
849 | static int do_spi_entry(const char *filename, struct spi_device_id *id, | 748 | static int do_spi_entry(const char *filename, struct spi_device_id *id, |
@@ -853,7 +752,6 @@ static int do_spi_entry(const char *filename, struct spi_device_id *id, | |||
853 | 752 | ||
854 | return 1; | 753 | return 1; |
855 | } | 754 | } |
856 | ADD_TO_DEVTABLE("spi", struct spi_device_id, do_spi_entry); | ||
857 | 755 | ||
858 | static const struct dmifield { | 756 | static const struct dmifield { |
859 | const char *prefix; | 757 | const char *prefix; |
@@ -908,7 +806,6 @@ static int do_dmi_entry(const char *filename, struct dmi_system_id *id, | |||
908 | strcat(alias, ":"); | 806 | strcat(alias, ":"); |
909 | return 1; | 807 | return 1; |
910 | } | 808 | } |
911 | ADD_TO_DEVTABLE("dmi", struct dmi_system_id, do_dmi_entry); | ||
912 | 809 | ||
913 | static int do_platform_entry(const char *filename, | 810 | static int do_platform_entry(const char *filename, |
914 | struct platform_device_id *id, char *alias) | 811 | struct platform_device_id *id, char *alias) |
@@ -916,7 +813,6 @@ static int do_platform_entry(const char *filename, | |||
916 | sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name); | 813 | sprintf(alias, PLATFORM_MODULE_PREFIX "%s", id->name); |
917 | return 1; | 814 | return 1; |
918 | } | 815 | } |
919 | ADD_TO_DEVTABLE("platform", struct platform_device_id, do_platform_entry); | ||
920 | 816 | ||
921 | static int do_mdio_entry(const char *filename, | 817 | static int do_mdio_entry(const char *filename, |
922 | struct mdio_device_id *id, char *alias) | 818 | struct mdio_device_id *id, char *alias) |
@@ -939,7 +835,6 @@ static int do_mdio_entry(const char *filename, | |||
939 | 835 | ||
940 | return 1; | 836 | return 1; |
941 | } | 837 | } |
942 | ADD_TO_DEVTABLE("mdio", struct mdio_device_id, do_mdio_entry); | ||
943 | 838 | ||
944 | /* Looks like: zorro:iN. */ | 839 | /* Looks like: zorro:iN. */ |
945 | static int do_zorro_entry(const char *filename, struct zorro_device_id *id, | 840 | static int do_zorro_entry(const char *filename, struct zorro_device_id *id, |
@@ -950,7 +845,6 @@ static int do_zorro_entry(const char *filename, struct zorro_device_id *id, | |||
950 | ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id); | 845 | ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id); |
951 | return 1; | 846 | return 1; |
952 | } | 847 | } |
953 | ADD_TO_DEVTABLE("zorro", struct zorro_device_id, do_zorro_entry); | ||
954 | 848 | ||
955 | /* looks like: "pnp:dD" */ | 849 | /* looks like: "pnp:dD" */ |
956 | static int do_isapnp_entry(const char *filename, | 850 | static int do_isapnp_entry(const char *filename, |
@@ -964,124 +858,16 @@ static int do_isapnp_entry(const char *filename, | |||
964 | (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f); | 858 | (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f); |
965 | return 1; | 859 | return 1; |
966 | } | 860 | } |
967 | ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry); | ||
968 | 861 | ||
969 | /* Looks like: "ipack:fNvNdN". */ | 862 | /* Ignore any prefix, eg. some architectures prepend _ */ |
970 | static int do_ipack_entry(const char *filename, | 863 | static inline int sym_is(const char *symbol, const char *name) |
971 | struct ipack_device_id *id, char *alias) | ||
972 | { | 864 | { |
973 | id->vendor = TO_NATIVE(id->vendor); | 865 | const char *match; |
974 | id->device = TO_NATIVE(id->device); | ||
975 | strcpy(alias, "ipack:"); | ||
976 | ADD(alias, "f", id->format != IPACK_ANY_FORMAT, id->format); | ||
977 | ADD(alias, "v", id->vendor != IPACK_ANY_ID, id->vendor); | ||
978 | ADD(alias, "d", id->device != IPACK_ANY_ID, id->device); | ||
979 | add_wildcard(alias); | ||
980 | return 1; | ||
981 | } | ||
982 | ADD_TO_DEVTABLE("ipack", struct ipack_device_id, do_ipack_entry); | ||
983 | |||
984 | /* | ||
985 | * Append a match expression for a single masked hex digit. | ||
986 | * outp points to a pointer to the character at which to append. | ||
987 | * *outp is updated on return to point just after the appended text, | ||
988 | * to facilitate further appending. | ||
989 | */ | ||
990 | static void append_nibble_mask(char **outp, | ||
991 | unsigned int nibble, unsigned int mask) | ||
992 | { | ||
993 | char *p = *outp; | ||
994 | unsigned int i; | ||
995 | |||
996 | switch (mask) { | ||
997 | case 0: | ||
998 | *p++ = '?'; | ||
999 | break; | ||
1000 | |||
1001 | case 0xf: | ||
1002 | p += sprintf(p, "%X", nibble); | ||
1003 | break; | ||
1004 | |||
1005 | default: | ||
1006 | /* | ||
1007 | * Dumbly emit a match pattern for all possible matching | ||
1008 | * digits. This could be improved in some cases using ranges, | ||
1009 | * but it has the advantage of being trivially correct, and is | ||
1010 | * often optimal. | ||
1011 | */ | ||
1012 | *p++ = '['; | ||
1013 | for (i = 0; i < 0x10; i++) | ||
1014 | if ((i & mask) == nibble) | ||
1015 | p += sprintf(p, "%X", i); | ||
1016 | *p++ = ']'; | ||
1017 | } | ||
1018 | |||
1019 | /* Ensure that the string remains NUL-terminated: */ | ||
1020 | *p = '\0'; | ||
1021 | 866 | ||
1022 | /* Advance the caller's end-of-string pointer: */ | 867 | match = strstr(symbol, name); |
1023 | *outp = p; | 868 | if (!match) |
1024 | } | 869 | return 0; |
1025 | 870 | return match[strlen(name)] == '\0'; | |
1026 | /* | ||
1027 | * looks like: "amba:dN" | ||
1028 | * | ||
1029 | * N is exactly 8 digits, where each is an upper-case hex digit, or | ||
1030 | * a ? or [] pattern matching exactly one digit. | ||
1031 | */ | ||
1032 | static int do_amba_entry(const char *filename, | ||
1033 | struct amba_id *id, char *alias) | ||
1034 | { | ||
1035 | unsigned int digit; | ||
1036 | char *p = alias; | ||
1037 | |||
1038 | if ((id->id & id->mask) != id->id) | ||
1039 | fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: " | ||
1040 | "id=0x%08X, mask=0x%08X. Please fix this driver.\n", | ||
1041 | filename, id->id, id->mask); | ||
1042 | |||
1043 | p += sprintf(alias, "amba:d"); | ||
1044 | for (digit = 0; digit < 8; digit++) | ||
1045 | append_nibble_mask(&p, | ||
1046 | (id->id >> (4 * (7 - digit))) & 0xf, | ||
1047 | (id->mask >> (4 * (7 - digit))) & 0xf); | ||
1048 | |||
1049 | return 1; | ||
1050 | } | ||
1051 | ADD_TO_DEVTABLE("amba", struct amba_id, do_amba_entry); | ||
1052 | |||
1053 | /* LOOKS like x86cpu:vendor:VVVV:family:FFFF:model:MMMM:feature:*,FEAT,* | ||
1054 | * All fields are numbers. It would be nicer to use strings for vendor | ||
1055 | * and feature, but getting those out of the build system here is too | ||
1056 | * complicated. | ||
1057 | */ | ||
1058 | |||
1059 | static int do_x86cpu_entry(const char *filename, struct x86_cpu_id *id, | ||
1060 | char *alias) | ||
1061 | { | ||
1062 | id->feature = TO_NATIVE(id->feature); | ||
1063 | id->family = TO_NATIVE(id->family); | ||
1064 | id->model = TO_NATIVE(id->model); | ||
1065 | id->vendor = TO_NATIVE(id->vendor); | ||
1066 | |||
1067 | strcpy(alias, "x86cpu:"); | ||
1068 | ADD(alias, "vendor:", id->vendor != X86_VENDOR_ANY, id->vendor); | ||
1069 | ADD(alias, ":family:", id->family != X86_FAMILY_ANY, id->family); | ||
1070 | ADD(alias, ":model:", id->model != X86_MODEL_ANY, id->model); | ||
1071 | strcat(alias, ":feature:*"); | ||
1072 | if (id->feature != X86_FEATURE_ANY) | ||
1073 | sprintf(alias + strlen(alias), "%04X*", id->feature); | ||
1074 | return 1; | ||
1075 | } | ||
1076 | ADD_TO_DEVTABLE("x86cpu", struct x86_cpu_id, do_x86cpu_entry); | ||
1077 | |||
1078 | /* Does namelen bytes of name exactly match the symbol? */ | ||
1079 | static bool sym_is(const char *name, unsigned namelen, const char *symbol) | ||
1080 | { | ||
1081 | if (namelen != strlen(symbol)) | ||
1082 | return false; | ||
1083 | |||
1084 | return memcmp(name, symbol, namelen) == 0; | ||
1085 | } | 871 | } |
1086 | 872 | ||
1087 | static void do_table(void *symval, unsigned long size, | 873 | static void do_table(void *symval, unsigned long size, |
@@ -1114,29 +900,11 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
1114 | { | 900 | { |
1115 | void *symval; | 901 | void *symval; |
1116 | char *zeros = NULL; | 902 | char *zeros = NULL; |
1117 | const char *name; | ||
1118 | unsigned int namelen; | ||
1119 | 903 | ||
1120 | /* We're looking for a section relative symbol */ | 904 | /* We're looking for a section relative symbol */ |
1121 | if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) | 905 | if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) |
1122 | return; | 906 | return; |
1123 | 907 | ||
1124 | /* We're looking for an object */ | ||
1125 | if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) | ||
1126 | return; | ||
1127 | |||
1128 | /* All our symbols are of form <prefix>__mod_XXX_device_table. */ | ||
1129 | name = strstr(symname, "__mod_"); | ||
1130 | if (!name) | ||
1131 | return; | ||
1132 | name += strlen("__mod_"); | ||
1133 | namelen = strlen(name); | ||
1134 | if (namelen < strlen("_device_table")) | ||
1135 | return; | ||
1136 | if (strcmp(name + namelen - strlen("_device_table"), "_device_table")) | ||
1137 | return; | ||
1138 | namelen -= strlen("_device_table"); | ||
1139 | |||
1140 | /* Handle all-NULL symbols allocated into .bss */ | 908 | /* Handle all-NULL symbols allocated into .bss */ |
1141 | if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { | 909 | if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { |
1142 | zeros = calloc(1, sym->st_size); | 910 | zeros = calloc(1, sym->st_size); |
@@ -1147,25 +915,113 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
1147 | + sym->st_value; | 915 | + sym->st_value; |
1148 | } | 916 | } |
1149 | 917 | ||
1150 | /* First handle the "special" cases */ | 918 | if (sym_is(symname, "__mod_pci_device_table")) |
1151 | if (sym_is(name, namelen, "usb")) | 919 | do_table(symval, sym->st_size, |
920 | sizeof(struct pci_device_id), "pci", | ||
921 | do_pci_entry, mod); | ||
922 | else if (sym_is(symname, "__mod_usb_device_table")) | ||
923 | /* special case to handle bcdDevice ranges */ | ||
1152 | do_usb_table(symval, sym->st_size, mod); | 924 | do_usb_table(symval, sym->st_size, mod); |
1153 | else if (sym_is(name, namelen, "pnp")) | 925 | else if (sym_is(symname, "__mod_hid_device_table")) |
926 | do_table(symval, sym->st_size, | ||
927 | sizeof(struct hid_device_id), "hid", | ||
928 | do_hid_entry, mod); | ||
929 | else if (sym_is(symname, "__mod_ieee1394_device_table")) | ||
930 | do_table(symval, sym->st_size, | ||
931 | sizeof(struct ieee1394_device_id), "ieee1394", | ||
932 | do_ieee1394_entry, mod); | ||
933 | else if (sym_is(symname, "__mod_ccw_device_table")) | ||
934 | do_table(symval, sym->st_size, | ||
935 | sizeof(struct ccw_device_id), "ccw", | ||
936 | do_ccw_entry, mod); | ||
937 | else if (sym_is(symname, "__mod_ap_device_table")) | ||
938 | do_table(symval, sym->st_size, | ||
939 | sizeof(struct ap_device_id), "ap", | ||
940 | do_ap_entry, mod); | ||
941 | else if (sym_is(symname, "__mod_css_device_table")) | ||
942 | do_table(symval, sym->st_size, | ||
943 | sizeof(struct css_device_id), "css", | ||
944 | do_css_entry, mod); | ||
945 | else if (sym_is(symname, "__mod_serio_device_table")) | ||
946 | do_table(symval, sym->st_size, | ||
947 | sizeof(struct serio_device_id), "serio", | ||
948 | do_serio_entry, mod); | ||
949 | else if (sym_is(symname, "__mod_acpi_device_table")) | ||
950 | do_table(symval, sym->st_size, | ||
951 | sizeof(struct acpi_device_id), "acpi", | ||
952 | do_acpi_entry, mod); | ||
953 | else if (sym_is(symname, "__mod_pnp_device_table")) | ||
1154 | do_pnp_device_entry(symval, sym->st_size, mod); | 954 | do_pnp_device_entry(symval, sym->st_size, mod); |
1155 | else if (sym_is(name, namelen, "pnp_card")) | 955 | else if (sym_is(symname, "__mod_pnp_card_device_table")) |
1156 | do_pnp_card_entries(symval, sym->st_size, mod); | 956 | do_pnp_card_entries(symval, sym->st_size, mod); |
1157 | else { | 957 | else if (sym_is(symname, "__mod_pcmcia_device_table")) |
1158 | struct devtable **p; | 958 | do_table(symval, sym->st_size, |
1159 | INIT_SECTION(__devtable); | 959 | sizeof(struct pcmcia_device_id), "pcmcia", |
1160 | 960 | do_pcmcia_entry, mod); | |
1161 | for (p = __start___devtable; p < __stop___devtable; p++) { | 961 | else if (sym_is(symname, "__mod_of_device_table")) |
1162 | if (sym_is(name, namelen, (*p)->device_id)) { | 962 | do_table(symval, sym->st_size, |
1163 | do_table(symval, sym->st_size, (*p)->id_size, | 963 | sizeof(struct of_device_id), "of", |
1164 | (*p)->device_id, (*p)->function, mod); | 964 | do_of_entry, mod); |
1165 | break; | 965 | else if (sym_is(symname, "__mod_vio_device_table")) |
1166 | } | 966 | do_table(symval, sym->st_size, |
1167 | } | 967 | sizeof(struct vio_device_id), "vio", |
1168 | } | 968 | do_vio_entry, mod); |
969 | else if (sym_is(symname, "__mod_input_device_table")) | ||
970 | do_table(symval, sym->st_size, | ||
971 | sizeof(struct input_device_id), "input", | ||
972 | do_input_entry, mod); | ||
973 | else if (sym_is(symname, "__mod_eisa_device_table")) | ||
974 | do_table(symval, sym->st_size, | ||
975 | sizeof(struct eisa_device_id), "eisa", | ||
976 | do_eisa_entry, mod); | ||
977 | else if (sym_is(symname, "__mod_parisc_device_table")) | ||
978 | do_table(symval, sym->st_size, | ||
979 | sizeof(struct parisc_device_id), "parisc", | ||
980 | do_parisc_entry, mod); | ||
981 | else if (sym_is(symname, "__mod_sdio_device_table")) | ||
982 | do_table(symval, sym->st_size, | ||
983 | sizeof(struct sdio_device_id), "sdio", | ||
984 | do_sdio_entry, mod); | ||
985 | else if (sym_is(symname, "__mod_ssb_device_table")) | ||
986 | do_table(symval, sym->st_size, | ||
987 | sizeof(struct ssb_device_id), "ssb", | ||
988 | do_ssb_entry, mod); | ||
989 | else if (sym_is(symname, "__mod_bcma_device_table")) | ||
990 | do_table(symval, sym->st_size, | ||
991 | sizeof(struct bcma_device_id), "bcma", | ||
992 | do_bcma_entry, mod); | ||
993 | else if (sym_is(symname, "__mod_virtio_device_table")) | ||
994 | do_table(symval, sym->st_size, | ||
995 | sizeof(struct virtio_device_id), "virtio", | ||
996 | do_virtio_entry, mod); | ||
997 | else if (sym_is(symname, "__mod_i2c_device_table")) | ||
998 | do_table(symval, sym->st_size, | ||
999 | sizeof(struct i2c_device_id), "i2c", | ||
1000 | do_i2c_entry, mod); | ||
1001 | else if (sym_is(symname, "__mod_spi_device_table")) | ||
1002 | do_table(symval, sym->st_size, | ||
1003 | sizeof(struct spi_device_id), "spi", | ||
1004 | do_spi_entry, mod); | ||
1005 | else if (sym_is(symname, "__mod_dmi_device_table")) | ||
1006 | do_table(symval, sym->st_size, | ||
1007 | sizeof(struct dmi_system_id), "dmi", | ||
1008 | do_dmi_entry, mod); | ||
1009 | else if (sym_is(symname, "__mod_platform_device_table")) | ||
1010 | do_table(symval, sym->st_size, | ||
1011 | sizeof(struct platform_device_id), "platform", | ||
1012 | do_platform_entry, mod); | ||
1013 | else if (sym_is(symname, "__mod_mdio_device_table")) | ||
1014 | do_table(symval, sym->st_size, | ||
1015 | sizeof(struct mdio_device_id), "mdio", | ||
1016 | do_mdio_entry, mod); | ||
1017 | else if (sym_is(symname, "__mod_zorro_device_table")) | ||
1018 | do_table(symval, sym->st_size, | ||
1019 | sizeof(struct zorro_device_id), "zorro", | ||
1020 | do_zorro_entry, mod); | ||
1021 | else if (sym_is(symname, "__mod_isapnp_device_table")) | ||
1022 | do_table(symval, sym->st_size, | ||
1023 | sizeof(struct isapnp_device_id), "isa", | ||
1024 | do_isapnp_entry, mod); | ||
1169 | free(zeros); | 1025 | free(zeros); |
1170 | } | 1026 | } |
1171 | 1027 | ||