diff options
Diffstat (limited to 'scripts/mod/file2alias.c')
-rw-r--r-- | scripts/mod/file2alias.c | 173 |
1 files changed, 156 insertions, 17 deletions
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 40e0045876ee..88f3f07205f8 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -104,7 +104,7 @@ static void device_id_check(const char *modname, const char *device_id, | |||
104 | static void do_usb_entry(struct usb_device_id *id, | 104 | static void do_usb_entry(struct usb_device_id *id, |
105 | unsigned int bcdDevice_initial, int bcdDevice_initial_digits, | 105 | unsigned int bcdDevice_initial, int bcdDevice_initial_digits, |
106 | unsigned char range_lo, unsigned char range_hi, | 106 | unsigned char range_lo, unsigned char range_hi, |
107 | struct module *mod) | 107 | unsigned char max, struct module *mod) |
108 | { | 108 | { |
109 | char alias[500]; | 109 | char alias[500]; |
110 | strcpy(alias, "usb:"); | 110 | strcpy(alias, "usb:"); |
@@ -118,9 +118,22 @@ static void do_usb_entry(struct usb_device_id *id, | |||
118 | sprintf(alias + strlen(alias), "%0*X", | 118 | sprintf(alias + strlen(alias), "%0*X", |
119 | bcdDevice_initial_digits, bcdDevice_initial); | 119 | bcdDevice_initial_digits, bcdDevice_initial); |
120 | if (range_lo == range_hi) | 120 | if (range_lo == range_hi) |
121 | sprintf(alias + strlen(alias), "%u", range_lo); | 121 | sprintf(alias + strlen(alias), "%X", range_lo); |
122 | else if (range_lo > 0 || range_hi < 9) | 122 | else if (range_lo > 0 || range_hi < max) { |
123 | sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi); | 123 | if (range_lo > 0x9 || range_hi < 0xA) |
124 | sprintf(alias + strlen(alias), | ||
125 | "[%X-%X]", | ||
126 | range_lo, | ||
127 | range_hi); | ||
128 | else { | ||
129 | sprintf(alias + strlen(alias), | ||
130 | range_lo < 0x9 ? "[%X-9" : "[%X", | ||
131 | range_lo); | ||
132 | sprintf(alias + strlen(alias), | ||
133 | range_hi > 0xA ? "a-%X]" : "%X]", | ||
134 | range_lo); | ||
135 | } | ||
136 | } | ||
124 | if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1)) | 137 | if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1)) |
125 | strcat(alias, "*"); | 138 | strcat(alias, "*"); |
126 | 139 | ||
@@ -147,10 +160,49 @@ static void do_usb_entry(struct usb_device_id *id, | |||
147 | "MODULE_ALIAS(\"%s\");\n", alias); | 160 | "MODULE_ALIAS(\"%s\");\n", alias); |
148 | } | 161 | } |
149 | 162 | ||
163 | /* Handles increment/decrement of BCD formatted integers */ | ||
164 | /* Returns the previous value, so it works like i++ or i-- */ | ||
165 | static unsigned int incbcd(unsigned int *bcd, | ||
166 | int inc, | ||
167 | unsigned char max, | ||
168 | size_t chars) | ||
169 | { | ||
170 | unsigned int init = *bcd, i, j; | ||
171 | unsigned long long c, dec = 0; | ||
172 | |||
173 | /* If bcd is not in BCD format, just increment */ | ||
174 | if (max > 0x9) { | ||
175 | *bcd += inc; | ||
176 | return init; | ||
177 | } | ||
178 | |||
179 | /* Convert BCD to Decimal */ | ||
180 | for (i=0 ; i < chars ; i++) { | ||
181 | c = (*bcd >> (i << 2)) & 0xf; | ||
182 | c = c > 9 ? 9 : c; /* force to bcd just in case */ | ||
183 | for (j=0 ; j < i ; j++) | ||
184 | c = c * 10; | ||
185 | dec += c; | ||
186 | } | ||
187 | |||
188 | /* Do our increment/decrement */ | ||
189 | dec += inc; | ||
190 | *bcd = 0; | ||
191 | |||
192 | /* Convert back to BCD */ | ||
193 | for (i=0 ; i < chars ; i++) { | ||
194 | for (c=1,j=0 ; j < i ; j++) | ||
195 | c = c * 10; | ||
196 | c = (dec / c) % 10; | ||
197 | *bcd += c << (i << 2); | ||
198 | } | ||
199 | return init; | ||
200 | } | ||
201 | |||
150 | static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) | 202 | static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) |
151 | { | 203 | { |
152 | unsigned int devlo, devhi; | 204 | unsigned int devlo, devhi; |
153 | unsigned char chi, clo; | 205 | unsigned char chi, clo, max; |
154 | int ndigits; | 206 | int ndigits; |
155 | 207 | ||
156 | id->match_flags = TO_NATIVE(id->match_flags); | 208 | id->match_flags = TO_NATIVE(id->match_flags); |
@@ -162,6 +214,17 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) | |||
162 | devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? | 214 | devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? |
163 | TO_NATIVE(id->bcdDevice_hi) : ~0x0U; | 215 | TO_NATIVE(id->bcdDevice_hi) : ~0x0U; |
164 | 216 | ||
217 | /* Figure out if this entry is in bcd or hex format */ | ||
218 | max = 0x9; /* Default to decimal format */ | ||
219 | for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) { | ||
220 | clo = (devlo >> (ndigits << 2)) & 0xf; | ||
221 | chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf; | ||
222 | if (clo > max || chi > max) { | ||
223 | max = 0xf; | ||
224 | break; | ||
225 | } | ||
226 | } | ||
227 | |||
165 | /* | 228 | /* |
166 | * Some modules (visor) have empty slots as placeholder for | 229 | * Some modules (visor) have empty slots as placeholder for |
167 | * run-time specification that results in catch-all alias | 230 | * run-time specification that results in catch-all alias |
@@ -173,21 +236,27 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) | |||
173 | for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { | 236 | for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { |
174 | clo = devlo & 0xf; | 237 | clo = devlo & 0xf; |
175 | chi = devhi & 0xf; | 238 | chi = devhi & 0xf; |
176 | if (chi > 9) /* it's bcd not hex */ | 239 | if (chi > max) /* If we are in bcd mode, truncate if necessary */ |
177 | chi = 9; | 240 | chi = max; |
178 | devlo >>= 4; | 241 | devlo >>= 4; |
179 | devhi >>= 4; | 242 | devhi >>= 4; |
180 | 243 | ||
181 | if (devlo == devhi || !ndigits) { | 244 | if (devlo == devhi || !ndigits) { |
182 | do_usb_entry(id, devlo, ndigits, clo, chi, mod); | 245 | do_usb_entry(id, devlo, ndigits, clo, chi, max, mod); |
183 | break; | 246 | break; |
184 | } | 247 | } |
185 | 248 | ||
186 | if (clo > 0) | 249 | if (clo > 0x0) |
187 | do_usb_entry(id, devlo++, ndigits, clo, 9, mod); | 250 | do_usb_entry(id, |
188 | 251 | incbcd(&devlo, 1, max, | |
189 | if (chi < 9) | 252 | sizeof(id->bcdDevice_lo) * 2), |
190 | do_usb_entry(id, devhi--, ndigits, 0, chi, mod); | 253 | ndigits, clo, max, max, mod); |
254 | |||
255 | if (chi < max) | ||
256 | do_usb_entry(id, | ||
257 | incbcd(&devhi, -1, max, | ||
258 | sizeof(id->bcdDevice_lo) * 2), | ||
259 | ndigits, 0x0, chi, max, mod); | ||
191 | } | 260 | } |
192 | } | 261 | } |
193 | 262 | ||
@@ -657,6 +726,15 @@ static int do_i2c_entry(const char *filename, struct i2c_device_id *id, | |||
657 | return 1; | 726 | return 1; |
658 | } | 727 | } |
659 | 728 | ||
729 | /* Looks like: spi:S */ | ||
730 | static int do_spi_entry(const char *filename, struct spi_device_id *id, | ||
731 | char *alias) | ||
732 | { | ||
733 | sprintf(alias, SPI_MODULE_PREFIX "%s", id->name); | ||
734 | |||
735 | return 1; | ||
736 | } | ||
737 | |||
660 | static const struct dmifield { | 738 | static const struct dmifield { |
661 | const char *prefix; | 739 | const char *prefix; |
662 | int field; | 740 | int field; |
@@ -718,6 +796,51 @@ static int do_platform_entry(const char *filename, | |||
718 | return 1; | 796 | return 1; |
719 | } | 797 | } |
720 | 798 | ||
799 | static int do_mdio_entry(const char *filename, | ||
800 | struct mdio_device_id *id, char *alias) | ||
801 | { | ||
802 | int i; | ||
803 | |||
804 | alias += sprintf(alias, MDIO_MODULE_PREFIX); | ||
805 | |||
806 | for (i = 0; i < 32; i++) { | ||
807 | if (!((id->phy_id_mask >> (31-i)) & 1)) | ||
808 | *(alias++) = '?'; | ||
809 | else if ((id->phy_id >> (31-i)) & 1) | ||
810 | *(alias++) = '1'; | ||
811 | else | ||
812 | *(alias++) = '0'; | ||
813 | } | ||
814 | |||
815 | /* Terminate the string */ | ||
816 | *alias = 0; | ||
817 | |||
818 | return 1; | ||
819 | } | ||
820 | |||
821 | /* Looks like: zorro:iN. */ | ||
822 | static int do_zorro_entry(const char *filename, struct zorro_device_id *id, | ||
823 | char *alias) | ||
824 | { | ||
825 | id->id = TO_NATIVE(id->id); | ||
826 | strcpy(alias, "zorro:"); | ||
827 | ADD(alias, "i", id->id != ZORRO_WILDCARD, id->id); | ||
828 | return 1; | ||
829 | } | ||
830 | |||
831 | /* looks like: "pnp:dD" */ | ||
832 | static int do_isapnp_entry(const char *filename, | ||
833 | struct isapnp_device_id *id, char *alias) | ||
834 | { | ||
835 | sprintf(alias, "pnp:d%c%c%c%x%x%x%x*", | ||
836 | 'A' + ((id->vendor >> 2) & 0x3f) - 1, | ||
837 | 'A' + (((id->vendor & 3) << 3) | ((id->vendor >> 13) & 7)) - 1, | ||
838 | 'A' + ((id->vendor >> 8) & 0x1f) - 1, | ||
839 | (id->function >> 4) & 0x0f, id->function & 0x0f, | ||
840 | (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f); | ||
841 | return 1; | ||
842 | } | ||
843 | |||
721 | /* Ignore any prefix, eg. some architectures prepend _ */ | 844 | /* Ignore any prefix, eg. some architectures prepend _ */ |
722 | static inline int sym_is(const char *symbol, const char *name) | 845 | static inline int sym_is(const char *symbol, const char *name) |
723 | { | 846 | { |
@@ -726,7 +849,7 @@ static inline int sym_is(const char *symbol, const char *name) | |||
726 | match = strstr(symbol, name); | 849 | match = strstr(symbol, name); |
727 | if (!match) | 850 | if (!match) |
728 | return 0; | 851 | return 0; |
729 | return match[strlen(symbol)] == '\0'; | 852 | return match[strlen(name)] == '\0'; |
730 | } | 853 | } |
731 | 854 | ||
732 | static void do_table(void *symval, unsigned long size, | 855 | static void do_table(void *symval, unsigned long size, |
@@ -761,16 +884,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
761 | char *zeros = NULL; | 884 | char *zeros = NULL; |
762 | 885 | ||
763 | /* We're looking for a section relative symbol */ | 886 | /* We're looking for a section relative symbol */ |
764 | if (!sym->st_shndx || sym->st_shndx >= info->hdr->e_shnum) | 887 | if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) |
765 | return; | 888 | return; |
766 | 889 | ||
767 | /* Handle all-NULL symbols allocated into .bss */ | 890 | /* Handle all-NULL symbols allocated into .bss */ |
768 | if (info->sechdrs[sym->st_shndx].sh_type & SHT_NOBITS) { | 891 | if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { |
769 | zeros = calloc(1, sym->st_size); | 892 | zeros = calloc(1, sym->st_size); |
770 | symval = zeros; | 893 | symval = zeros; |
771 | } else { | 894 | } else { |
772 | symval = (void *)info->hdr | 895 | symval = (void *)info->hdr |
773 | + info->sechdrs[sym->st_shndx].sh_offset | 896 | + info->sechdrs[get_secindex(info, sym)].sh_offset |
774 | + sym->st_value; | 897 | + sym->st_value; |
775 | } | 898 | } |
776 | 899 | ||
@@ -853,6 +976,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
853 | do_table(symval, sym->st_size, | 976 | do_table(symval, sym->st_size, |
854 | sizeof(struct i2c_device_id), "i2c", | 977 | sizeof(struct i2c_device_id), "i2c", |
855 | do_i2c_entry, mod); | 978 | do_i2c_entry, mod); |
979 | else if (sym_is(symname, "__mod_spi_device_table")) | ||
980 | do_table(symval, sym->st_size, | ||
981 | sizeof(struct spi_device_id), "spi", | ||
982 | do_spi_entry, mod); | ||
856 | else if (sym_is(symname, "__mod_dmi_device_table")) | 983 | else if (sym_is(symname, "__mod_dmi_device_table")) |
857 | do_table(symval, sym->st_size, | 984 | do_table(symval, sym->st_size, |
858 | sizeof(struct dmi_system_id), "dmi", | 985 | sizeof(struct dmi_system_id), "dmi", |
@@ -861,6 +988,18 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
861 | do_table(symval, sym->st_size, | 988 | do_table(symval, sym->st_size, |
862 | sizeof(struct platform_device_id), "platform", | 989 | sizeof(struct platform_device_id), "platform", |
863 | do_platform_entry, mod); | 990 | do_platform_entry, mod); |
991 | else if (sym_is(symname, "__mod_mdio_device_table")) | ||
992 | do_table(symval, sym->st_size, | ||
993 | sizeof(struct mdio_device_id), "mdio", | ||
994 | do_mdio_entry, mod); | ||
995 | else if (sym_is(symname, "__mod_zorro_device_table")) | ||
996 | do_table(symval, sym->st_size, | ||
997 | sizeof(struct zorro_device_id), "zorro", | ||
998 | do_zorro_entry, mod); | ||
999 | else if (sym_is(symname, "__mod_isapnp_device_table")) | ||
1000 | do_table(symval, sym->st_size, | ||
1001 | sizeof(struct isapnp_device_id), "isa", | ||
1002 | do_isapnp_entry, mod); | ||
864 | free(zeros); | 1003 | free(zeros); |
865 | } | 1004 | } |
866 | 1005 | ||