1 /* Simple code to turn various tables in an ELF file into alias definitions. 2 * This deals with kernel datastructures where they should be 3 * dealt with: in the kernel source. 4 * 5 * Copyright 2002-2003 Rusty Russell, IBM Corporation 6 * 2003 Kai Germaschewski 7 * 8 * 9 * This software may be used and distributed according to the terms 10 * of the GNU General Public License, incorporated herein by reference. 11 */ 12 13 #include "modpost.h" 14 #include "devicetable-offsets.h" 15 16 /* We use the ELF typedefs for kernel_ulong_t but bite the bullet and 17 * use either stdint.h or inttypes.h for the rest. */ 18 #if KERNEL_ELFCLASS == ELFCLASS32 19 typedef Elf32_Addr kernel_ulong_t; 20 #define BITS_PER_LONG 32 21 #else 22 typedef Elf64_Addr kernel_ulong_t; 23 #define BITS_PER_LONG 64 24 #endif 25 #ifdef __sun__ 26 #include <inttypes.h> 27 #else 28 #include <stdint.h> 29 #endif 30 31 #include <ctype.h> 32 #include <stdbool.h> 33 34 typedef uint32_t __u32; 35 typedef uint16_t __u16; 36 typedef unsigned char __u8; 37 typedef struct { 38 __u8 b[16]; 39 } uuid_le; 40 typedef struct { 41 __u8 b[16]; 42 } uuid_t; 43 #define UUID_STRING_LEN 36 44 45 /* Big exception to the "don't include kernel headers into userspace, which 46 * even potentially has different endianness and word sizes, since 47 * we handle those differences explicitly below */ 48 #include "../../include/linux/mod_devicetable.h" 49 50 /* This array collects all instances that use the generic do_table */ 51 struct devtable { 52 const char *device_id; /* name of table, __mod_<name>__*_device_table. */ 53 unsigned long id_size; 54 int (*do_entry)(const char *filename, void *symval, char *alias); 55 }; 56 57 /* Size of alias provided to do_entry functions */ 58 #define ALIAS_SIZE 500 59 60 /* Define a variable f that holds the value of field f of struct devid 61 * based at address m. 62 */ 63 #define DEF_FIELD(m, devid, f) \ 64 typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f)) 65 66 /* Define a variable v that holds the address of field f of struct devid 67 * based at address m. Due to the way typeof works, for a field of type 68 * T[N] the variable has type T(*)[N], _not_ T*. 69 */ 70 #define DEF_FIELD_ADDR_VAR(m, devid, f, v) \ 71 typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f) 72 73 /* Define a variable f that holds the address of field f of struct devid 74 * based at address m. Due to the way typeof works, for a field of type 75 * T[N] the variable has type T(*)[N], _not_ T*. 76 */ 77 #define DEF_FIELD_ADDR(m, devid, f) \ 78 DEF_FIELD_ADDR_VAR(m, devid, f, f) 79 80 #define ADD(str, sep, cond, field) \ 81 do { \ 82 strcat(str, sep); \ 83 if (cond) \ 84 sprintf(str + strlen(str), \ 85 sizeof(field) == 1 ? "%02X" : \ 86 sizeof(field) == 2 ? "%04X" : \ 87 sizeof(field) == 4 ? "%08X" : "", \ 88 field); \ 89 else \ 90 sprintf(str + strlen(str), "*"); \ 91 } while(0) 92 93 /* End in a wildcard, for future extension */ 94 static inline void add_wildcard(char *str) 95 { 96 int len = strlen(str); 97 98 if (str[len - 1] != '*') 99 strcat(str + len, "*"); 100 } 101 102 static inline void add_uuid(char *str, uuid_le uuid) 103 { 104 int len = strlen(str); 105 106 sprintf(str + len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 107 uuid.b[3], uuid.b[2], uuid.b[1], uuid.b[0], 108 uuid.b[5], uuid.b[4], uuid.b[7], uuid.b[6], 109 uuid.b[8], uuid.b[9], uuid.b[10], uuid.b[11], 110 uuid.b[12], uuid.b[13], uuid.b[14], uuid.b[15]); 111 } 112 113 /** 114 * Check that sizeof(device_id type) are consistent with size of section 115 * in .o file. If in-consistent then userspace and kernel does not agree 116 * on actual size which is a bug. 117 * Also verify that the final entry in the table is all zeros. 118 * Ignore both checks if build host differ from target host and size differs. 119 **/ 120 static void device_id_check(const char *modname, const char *device_id, 121 unsigned long size, unsigned long id_size, 122 void *symval) 123 { 124 int i; 125 126 if (size % id_size || size < id_size) { 127 fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo " 128 "of the size of " 129 "section __mod_%s__<identifier>_device_table=%lu.\n" 130 "Fix definition of struct %s_device_id " 131 "in mod_devicetable.h\n", 132 modname, device_id, id_size, device_id, size, device_id); 133 } 134 /* Verify last one is a terminator */ 135 for (i = 0; i < id_size; i++ ) { 136 if (*(uint8_t*)(symval+size-id_size+i)) { 137 fprintf(stderr,"%s: struct %s_device_id is %lu bytes. " 138 "The last of %lu is:\n", 139 modname, device_id, id_size, size / id_size); 140 for (i = 0; i < id_size; i++ ) 141 fprintf(stderr,"0x%02x ", 142 *(uint8_t*)(symval+size-id_size+i) ); 143 fprintf(stderr,"\n"); 144 fatal("%s: struct %s_device_id is not terminated " 145 "with a NULL entry!\n", modname, device_id); 146 } 147 } 148 } 149 150 /* USB is special because the bcdDevice can be matched against a numeric range */ 151 /* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */ 152 static void do_usb_entry(void *symval, 153 unsigned int bcdDevice_initial, int bcdDevice_initial_digits, 154 unsigned char range_lo, unsigned char range_hi, 155 unsigned char max, struct module *mod) 156 { 157 char alias[500]; 158 DEF_FIELD(symval, usb_device_id, match_flags); 159 DEF_FIELD(symval, usb_device_id, idVendor); 160 DEF_FIELD(symval, usb_device_id, idProduct); 161 DEF_FIELD(symval, usb_device_id, bcdDevice_lo); 162 DEF_FIELD(symval, usb_device_id, bDeviceClass); 163 DEF_FIELD(symval, usb_device_id, bDeviceSubClass); 164 DEF_FIELD(symval, usb_device_id, bDeviceProtocol); 165 DEF_FIELD(symval, usb_device_id, bInterfaceClass); 166 DEF_FIELD(symval, usb_device_id, bInterfaceSubClass); 167 DEF_FIELD(symval, usb_device_id, bInterfaceProtocol); 168 DEF_FIELD(symval, usb_device_id, bInterfaceNumber); 169 170 strcpy(alias, "usb:"); 171 ADD(alias, "v", match_flags&USB_DEVICE_ID_MATCH_VENDOR, 172 idVendor); 173 ADD(alias, "p", match_flags&USB_DEVICE_ID_MATCH_PRODUCT, 174 idProduct); 175 176 strcat(alias, "d"); 177 if (bcdDevice_initial_digits) 178 sprintf(alias + strlen(alias), "%0*X", 179 bcdDevice_initial_digits, bcdDevice_initial); 180 if (range_lo == range_hi) 181 sprintf(alias + strlen(alias), "%X", range_lo); 182 else if (range_lo > 0 || range_hi < max) { 183 if (range_lo > 0x9 || range_hi < 0xA) 184 sprintf(alias + strlen(alias), 185 "[%X-%X]", 186 range_lo, 187 range_hi); 188 else { 189 sprintf(alias + strlen(alias), 190 range_lo < 0x9 ? "[%X-9" : "[%X", 191 range_lo); 192 sprintf(alias + strlen(alias), 193 range_hi > 0xA ? "A-%X]" : "%X]", 194 range_hi); 195 } 196 } 197 if (bcdDevice_initial_digits < (sizeof(bcdDevice_lo) * 2 - 1)) 198 strcat(alias, "*"); 199 200 ADD(alias, "dc", match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS, 201 bDeviceClass); 202 ADD(alias, "dsc", match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS, 203 bDeviceSubClass); 204 ADD(alias, "dp", match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL, 205 bDeviceProtocol); 206 ADD(alias, "ic", match_flags&USB_DEVICE_ID_MATCH_INT_CLASS, 207 bInterfaceClass); 208 ADD(alias, "isc", match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS, 209 bInterfaceSubClass); 210 ADD(alias, "ip", match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL, 211 bInterfaceProtocol); 212 ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER, 213 bInterfaceNumber); 214 215 add_wildcard(alias); 216 buf_printf(&mod->dev_table_buf, 217 "MODULE_ALIAS(\"%s\");\n", alias); 218 } 219 220 /* Handles increment/decrement of BCD formatted integers */ 221 /* Returns the previous value, so it works like i++ or i-- */ 222 static unsigned int incbcd(unsigned int *bcd, 223 int inc, 224 unsigned char max, 225 size_t chars) 226 { 227 unsigned int init = *bcd, i, j; 228 unsigned long long c, dec = 0; 229 230 /* If bcd is not in BCD format, just increment */ 231 if (max > 0x9) { 232 *bcd += inc; 233 return init; 234 } 235 236 /* Convert BCD to Decimal */ 237 for (i=0 ; i < chars ; i++) { 238 c = (*bcd >> (i << 2)) & 0xf; 239 c = c > 9 ? 9 : c; /* force to bcd just in case */ 240 for (j=0 ; j < i ; j++) 241 c = c * 10; 242 dec += c; 243 } 244 245 /* Do our increment/decrement */ 246 dec += inc; 247 *bcd = 0; 248 249 /* Convert back to BCD */ 250 for (i=0 ; i < chars ; i++) { 251 for (c=1,j=0 ; j < i ; j++) 252 c = c * 10; 253 c = (dec / c) % 10; 254 *bcd += c << (i << 2); 255 } 256 return init; 257 } 258 259 static void do_usb_entry_multi(void *symval, struct module *mod) 260 { 261 unsigned int devlo, devhi; 262 unsigned char chi, clo, max; 263 int ndigits; 264 265 DEF_FIELD(symval, usb_device_id, match_flags); 266 DEF_FIELD(symval, usb_device_id, idVendor); 267 DEF_FIELD(symval, usb_device_id, idProduct); 268 DEF_FIELD(symval, usb_device_id, bcdDevice_lo); 269 DEF_FIELD(symval, usb_device_id, bcdDevice_hi); 270 DEF_FIELD(symval, usb_device_id, bDeviceClass); 271 DEF_FIELD(symval, usb_device_id, bInterfaceClass); 272 273 devlo = match_flags & USB_DEVICE_ID_MATCH_DEV_LO ? 274 bcdDevice_lo : 0x0U; 275 devhi = match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? 276 bcdDevice_hi : ~0x0U; 277 278 /* Figure out if this entry is in bcd or hex format */ 279 max = 0x9; /* Default to decimal format */ 280 for (ndigits = 0 ; ndigits < sizeof(bcdDevice_lo) * 2 ; ndigits++) { 281 clo = (devlo >> (ndigits << 2)) & 0xf; 282 chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf; 283 if (clo > max || chi > max) { 284 max = 0xf; 285 break; 286 } 287 } 288 289 /* 290 * Some modules (visor) have empty slots as placeholder for 291 * run-time specification that results in catch-all alias 292 */ 293 if (!(idVendor | idProduct | bDeviceClass | bInterfaceClass)) 294 return; 295 296 /* Convert numeric bcdDevice range into fnmatch-able pattern(s) */ 297 for (ndigits = sizeof(bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { 298 clo = devlo & 0xf; 299 chi = devhi & 0xf; 300 if (chi > max) /* If we are in bcd mode, truncate if necessary */ 301 chi = max; 302 devlo >>= 4; 303 devhi >>= 4; 304 305 if (devlo == devhi || !ndigits) { 306 do_usb_entry(symval, devlo, ndigits, clo, chi, max, mod); 307 break; 308 } 309 310 if (clo > 0x0) 311 do_usb_entry(symval, 312 incbcd(&devlo, 1, max, 313 sizeof(bcdDevice_lo) * 2), 314 ndigits, clo, max, max, mod); 315 316 if (chi < max) 317 do_usb_entry(symval, 318 incbcd(&devhi, -1, max, 319 sizeof(bcdDevice_lo) * 2), 320 ndigits, 0x0, chi, max, mod); 321 } 322 } 323 324 static void do_usb_table(void *symval, unsigned long size, 325 struct module *mod) 326 { 327 unsigned int i; 328 const unsigned long id_size = SIZE_usb_device_id; 329 330 device_id_check(mod->name, "usb", size, id_size, symval); 331 332 /* Leave last one: it's the terminator. */ 333 size -= id_size; 334 335 for (i = 0; i < size; i += id_size) 336 do_usb_entry_multi(symval + i, mod); 337 } 338 339 static void do_of_entry_multi(void *symval, struct module *mod) 340 { 341 char alias[500]; 342 int len; 343 char *tmp; 344 345 DEF_FIELD_ADDR(symval, of_device_id, name); 346 DEF_FIELD_ADDR(symval, of_device_id, type); 347 DEF_FIELD_ADDR(symval, of_device_id, compatible); 348 349 len = sprintf(alias, "of:N%sT%s", (*name)[0] ? *name : "*", 350 (*type)[0] ? *type : "*"); 351 352 if ((*compatible)[0]) 353 sprintf(&alias[len], "%sC%s", (*type)[0] ? "*" : "", 354 *compatible); 355 356 /* Replace all whitespace with underscores */ 357 for (tmp = alias; tmp && *tmp; tmp++) 358 if (isspace(*tmp)) 359 *tmp = '_'; 360 361 buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias); 362 strcat(alias, "C"); 363 add_wildcard(alias); 364 buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias); 365 } 366 367 static void do_of_table(void *symval, unsigned long size, 368 struct module *mod) 369 { 370 unsigned int i; 371 const unsigned long id_size = SIZE_of_device_id; 372 373 device_id_check(mod->name, "of", size, id_size, symval); 374 375 /* Leave last one: it's the terminator. */ 376 size -= id_size; 377 378 for (i = 0; i < size; i += id_size) 379 do_of_entry_multi(symval + i, mod); 380 } 381 382 /* Looks like: hid:bNvNpN */ 383 static int do_hid_entry(const char *filename, 384 void *symval, char *alias) 385 { 386 DEF_FIELD(symval, hid_device_id, bus); 387 DEF_FIELD(symval, hid_device_id, group); 388 DEF_FIELD(symval, hid_device_id, vendor); 389 DEF_FIELD(symval, hid_device_id, product); 390 391 sprintf(alias, "hid:"); 392 ADD(alias, "b", bus != HID_BUS_ANY, bus); 393 ADD(alias, "g", group != HID_GROUP_ANY, group); 394 ADD(alias, "v", vendor != HID_ANY_ID, vendor); 395 ADD(alias, "p", product != HID_ANY_ID, product); 396 397 return 1; 398 } 399 400 /* Looks like: ieee1394:venNmoNspNverN */ 401 static int do_ieee1394_entry(const char *filename, 402 void *symval, char *alias) 403 { 404 DEF_FIELD(symval, ieee1394_device_id, match_flags); 405 DEF_FIELD(symval, ieee1394_device_id, vendor_id); 406 DEF_FIELD(symval, ieee1394_device_id, model_id); 407 DEF_FIELD(symval, ieee1394_device_id, specifier_id); 408 DEF_FIELD(symval, ieee1394_device_id, version); 409 410 strcpy(alias, "ieee1394:"); 411 ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID, 412 vendor_id); 413 ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID, 414 model_id); 415 ADD(alias, "sp", match_flags & IEEE1394_MATCH_SPECIFIER_ID, 416 specifier_id); 417 ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION, 418 version); 419 420 add_wildcard(alias); 421 return 1; 422 } 423 424 /* Looks like: pci:vNdNsvNsdNbcNscNiN. */ 425 static int do_pci_entry(const char *filename, 426 void *symval, char *alias) 427 { 428 /* Class field can be divided into these three. */ 429 unsigned char baseclass, subclass, interface, 430 baseclass_mask, subclass_mask, interface_mask; 431 432 DEF_FIELD(symval, pci_device_id, vendor); 433 DEF_FIELD(symval, pci_device_id, device); 434 DEF_FIELD(symval, pci_device_id, subvendor); 435 DEF_FIELD(symval, pci_device_id, subdevice); 436 DEF_FIELD(symval, pci_device_id, class); 437 DEF_FIELD(symval, pci_device_id, class_mask); 438 439 strcpy(alias, "pci:"); 440 ADD(alias, "v", vendor != PCI_ANY_ID, vendor); 441 ADD(alias, "d", device != PCI_ANY_ID, device); 442 ADD(alias, "sv", subvendor != PCI_ANY_ID, subvendor); 443 ADD(alias, "sd", subdevice != PCI_ANY_ID, subdevice); 444 445 baseclass = (class) >> 16; 446 baseclass_mask = (class_mask) >> 16; 447 subclass = (class) >> 8; 448 subclass_mask = (class_mask) >> 8; 449 interface = class; 450 interface_mask = class_mask; 451 452 if ((baseclass_mask != 0 && baseclass_mask != 0xFF) 453 || (subclass_mask != 0 && subclass_mask != 0xFF) 454 || (interface_mask != 0 && interface_mask != 0xFF)) { 455 warn("Can't handle masks in %s:%04X\n", 456 filename, class_mask); 457 return 0; 458 } 459 460 ADD(alias, "bc", baseclass_mask == 0xFF, baseclass); 461 ADD(alias, "sc", subclass_mask == 0xFF, subclass); 462 ADD(alias, "i", interface_mask == 0xFF, interface); 463 add_wildcard(alias); 464 return 1; 465 } 466 467 /* looks like: "ccw:tNmNdtNdmN" */ 468 static int do_ccw_entry(const char *filename, 469 void *symval, char *alias) 470 { 471 DEF_FIELD(symval, ccw_device_id, match_flags); 472 DEF_FIELD(symval, ccw_device_id, cu_type); 473 DEF_FIELD(symval, ccw_device_id, cu_model); 474 DEF_FIELD(symval, ccw_device_id, dev_type); 475 DEF_FIELD(symval, ccw_device_id, dev_model); 476 477 strcpy(alias, "ccw:"); 478 ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE, 479 cu_type); 480 ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL, 481 cu_model); 482 ADD(alias, "dt", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_TYPE, 483 dev_type); 484 ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL, 485 dev_model); 486 add_wildcard(alias); 487 return 1; 488 } 489 490 /* looks like: "ap:tN" */ 491 static int do_ap_entry(const char *filename, 492 void *symval, char *alias) 493 { 494 DEF_FIELD(symval, ap_device_id, dev_type); 495 496 sprintf(alias, "ap:t%02X*", dev_type); 497 return 1; 498 } 499 500 /* looks like: "css:tN" */ 501 static int do_css_entry(const char *filename, 502 void *symval, char *alias) 503 { 504 DEF_FIELD(symval, css_device_id, type); 505 506 sprintf(alias, "css:t%01X", type); 507 return 1; 508 } 509 510 /* Looks like: "serio:tyNprNidNexN" */ 511 static int do_serio_entry(const char *filename, 512 void *symval, char *alias) 513 { 514 DEF_FIELD(symval, serio_device_id, type); 515 DEF_FIELD(symval, serio_device_id, proto); 516 DEF_FIELD(symval, serio_device_id, id); 517 DEF_FIELD(symval, serio_device_id, extra); 518 519 strcpy(alias, "serio:"); 520 ADD(alias, "ty", type != SERIO_ANY, type); 521 ADD(alias, "pr", proto != SERIO_ANY, proto); 522 ADD(alias, "id", id != SERIO_ANY, id); 523 ADD(alias, "ex", extra != SERIO_ANY, extra); 524 525 add_wildcard(alias); 526 return 1; 527 } 528 529 /* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or 530 * "acpi:bbsspp" (bb=base-class, ss=sub-class, pp=prog-if) 531 * 532 * NOTE: Each driver should use one of the following : _HID, _CIDs 533 * or _CLS. Also, bb, ss, and pp can be substituted with ?? 534 * as don't care byte. 535 */ 536 static int do_acpi_entry(const char *filename, 537 void *symval, char *alias) 538 { 539 DEF_FIELD_ADDR(symval, acpi_device_id, id); 540 DEF_FIELD_ADDR(symval, acpi_device_id, cls); 541 DEF_FIELD_ADDR(symval, acpi_device_id, cls_msk); 542 543 if (id && strlen((const char *)*id)) 544 sprintf(alias, "acpi*:%s:*", *id); 545 else if (cls) { 546 int i, byte_shift, cnt = 0; 547 unsigned int msk; 548 549 sprintf(&alias[cnt], "acpi*:"); 550 cnt = 6; 551 for (i = 1; i <= 3; i++) { 552 byte_shift = 8 * (3-i); 553 msk = (*cls_msk >> byte_shift) & 0xFF; 554 if (msk) 555 sprintf(&alias[cnt], "%02x", 556 (*cls >> byte_shift) & 0xFF); 557 else 558 sprintf(&alias[cnt], "??"); 559 cnt += 2; 560 } 561 sprintf(&alias[cnt], ":*"); 562 } 563 return 1; 564 } 565 566 /* looks like: "pnp:dD" */ 567 static void do_pnp_device_entry(void *symval, unsigned long size, 568 struct module *mod) 569 { 570 const unsigned long id_size = SIZE_pnp_device_id; 571 const unsigned int count = (size / id_size)-1; 572 unsigned int i; 573 574 device_id_check(mod->name, "pnp", size, id_size, symval); 575 576 for (i = 0; i < count; i++) { 577 DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id); 578 char acpi_id[sizeof(*id)]; 579 int j; 580 581 buf_printf(&mod->dev_table_buf, 582 "MODULE_ALIAS(\"pnp:d%s*\");\n", *id); 583 584 /* fix broken pnp bus lowercasing */ 585 for (j = 0; j < sizeof(acpi_id); j++) 586 acpi_id[j] = toupper((*id)[j]); 587 buf_printf(&mod->dev_table_buf, 588 "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id); 589 } 590 } 591 592 /* looks like: "pnp:dD" for every device of the card */ 593 static void do_pnp_card_entries(void *symval, unsigned long size, 594 struct module *mod) 595 { 596 const unsigned long id_size = SIZE_pnp_card_device_id; 597 const unsigned int count = (size / id_size)-1; 598 unsigned int i; 599 600 device_id_check(mod->name, "pnp", size, id_size, symval); 601 602 for (i = 0; i < count; i++) { 603 unsigned int j; 604 DEF_FIELD_ADDR(symval + i * id_size, pnp_card_device_id, devs); 605 606 for (j = 0; j < PNP_MAX_DEVICES; j++) { 607 const char *id = (char *)(*devs)[j].id; 608 int i2, j2; 609 int dup = 0; 610 611 if (!id[0]) 612 break; 613 614 /* find duplicate, already added value */ 615 for (i2 = 0; i2 < i && !dup; i2++) { 616 DEF_FIELD_ADDR_VAR(symval + i2 * id_size, 617 pnp_card_device_id, 618 devs, devs_dup); 619 620 for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) { 621 const char *id2 = 622 (char *)(*devs_dup)[j2].id; 623 624 if (!id2[0]) 625 break; 626 627 if (!strcmp(id, id2)) { 628 dup = 1; 629 break; 630 } 631 } 632 } 633 634 /* add an individual alias for every device entry */ 635 if (!dup) { 636 char acpi_id[PNP_ID_LEN]; 637 int k; 638 639 buf_printf(&mod->dev_table_buf, 640 "MODULE_ALIAS(\"pnp:d%s*\");\n", id); 641 642 /* fix broken pnp bus lowercasing */ 643 for (k = 0; k < sizeof(acpi_id); k++) 644 acpi_id[k] = toupper(id[k]); 645 buf_printf(&mod->dev_table_buf, 646 "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id); 647 } 648 } 649 } 650 } 651 652 /* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */ 653 static int do_pcmcia_entry(const char *filename, 654 void *symval, char *alias) 655 { 656 unsigned int i; 657 DEF_FIELD(symval, pcmcia_device_id, match_flags); 658 DEF_FIELD(symval, pcmcia_device_id, manf_id); 659 DEF_FIELD(symval, pcmcia_device_id, card_id); 660 DEF_FIELD(symval, pcmcia_device_id, func_id); 661 DEF_FIELD(symval, pcmcia_device_id, function); 662 DEF_FIELD(symval, pcmcia_device_id, device_no); 663 DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash); 664 665 for (i=0; i<4; i++) { 666 (*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]); 667 } 668 669 strcpy(alias, "pcmcia:"); 670 ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID, 671 manf_id); 672 ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID, 673 card_id); 674 ADD(alias, "f", match_flags & PCMCIA_DEV_ID_MATCH_FUNC_ID, 675 func_id); 676 ADD(alias, "fn", match_flags & PCMCIA_DEV_ID_MATCH_FUNCTION, 677 function); 678 ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO, 679 device_no); 680 ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]); 681 ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]); 682 ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]); 683 ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]); 684 685 add_wildcard(alias); 686 return 1; 687 } 688 689 static int do_vio_entry(const char *filename, void *symval, 690 char *alias) 691 { 692 char *tmp; 693 DEF_FIELD_ADDR(symval, vio_device_id, type); 694 DEF_FIELD_ADDR(symval, vio_device_id, compat); 695 696 sprintf(alias, "vio:T%sS%s", (*type)[0] ? *type : "*", 697 (*compat)[0] ? *compat : "*"); 698 699 /* Replace all whitespace with underscores */ 700 for (tmp = alias; tmp && *tmp; tmp++) 701 if (isspace (*tmp)) 702 *tmp = '_'; 703 704 add_wildcard(alias); 705 return 1; 706 } 707 708 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 709 710 static void do_input(char *alias, 711 kernel_ulong_t *arr, unsigned int min, unsigned int max) 712 { 713 unsigned int i; 714 715 for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++) 716 arr[i] = TO_NATIVE(arr[i]); 717 for (i = min; i < max; i++) 718 if (arr[i / BITS_PER_LONG] & (1L << (i%BITS_PER_LONG))) 719 sprintf(alias + strlen(alias), "%X,*", i); 720 } 721 722 /* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */ 723 static int do_input_entry(const char *filename, void *symval, 724 char *alias) 725 { 726 DEF_FIELD(symval, input_device_id, flags); 727 DEF_FIELD(symval, input_device_id, bustype); 728 DEF_FIELD(symval, input_device_id, vendor); 729 DEF_FIELD(symval, input_device_id, product); 730 DEF_FIELD(symval, input_device_id, version); 731 DEF_FIELD_ADDR(symval, input_device_id, evbit); 732 DEF_FIELD_ADDR(symval, input_device_id, keybit); 733 DEF_FIELD_ADDR(symval, input_device_id, relbit); 734 DEF_FIELD_ADDR(symval, input_device_id, absbit); 735 DEF_FIELD_ADDR(symval, input_device_id, mscbit); 736 DEF_FIELD_ADDR(symval, input_device_id, ledbit); 737 DEF_FIELD_ADDR(symval, input_device_id, sndbit); 738 DEF_FIELD_ADDR(symval, input_device_id, ffbit); 739 DEF_FIELD_ADDR(symval, input_device_id, swbit); 740 741 sprintf(alias, "input:"); 742 743 ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype); 744 ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor); 745 ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product); 746 ADD(alias, "e", flags & INPUT_DEVICE_ID_MATCH_VERSION, version); 747 748 sprintf(alias + strlen(alias), "-e*"); 749 if (flags & INPUT_DEVICE_ID_MATCH_EVBIT) 750 do_input(alias, *evbit, 0, INPUT_DEVICE_ID_EV_MAX); 751 sprintf(alias + strlen(alias), "k*"); 752 if (flags & INPUT_DEVICE_ID_MATCH_KEYBIT) 753 do_input(alias, *keybit, 754 INPUT_DEVICE_ID_KEY_MIN_INTERESTING, 755 INPUT_DEVICE_ID_KEY_MAX); 756 sprintf(alias + strlen(alias), "r*"); 757 if (flags & INPUT_DEVICE_ID_MATCH_RELBIT) 758 do_input(alias, *relbit, 0, INPUT_DEVICE_ID_REL_MAX); 759 sprintf(alias + strlen(alias), "a*"); 760 if (flags & INPUT_DEVICE_ID_MATCH_ABSBIT) 761 do_input(alias, *absbit, 0, INPUT_DEVICE_ID_ABS_MAX); 762 sprintf(alias + strlen(alias), "m*"); 763 if (flags & INPUT_DEVICE_ID_MATCH_MSCIT) 764 do_input(alias, *mscbit, 0, INPUT_DEVICE_ID_MSC_MAX); 765 sprintf(alias + strlen(alias), "l*"); 766 if (flags & INPUT_DEVICE_ID_MATCH_LEDBIT) 767 do_input(alias, *ledbit, 0, INPUT_DEVICE_ID_LED_MAX); 768 sprintf(alias + strlen(alias), "s*"); 769 if (flags & INPUT_DEVICE_ID_MATCH_SNDBIT) 770 do_input(alias, *sndbit, 0, INPUT_DEVICE_ID_SND_MAX); 771 sprintf(alias + strlen(alias), "f*"); 772 if (flags & INPUT_DEVICE_ID_MATCH_FFBIT) 773 do_input(alias, *ffbit, 0, INPUT_DEVICE_ID_FF_MAX); 774 sprintf(alias + strlen(alias), "w*"); 775 if (flags & INPUT_DEVICE_ID_MATCH_SWBIT) 776 do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX); 777 return 1; 778 } 779 780 static int do_eisa_entry(const char *filename, void *symval, 781 char *alias) 782 { 783 DEF_FIELD_ADDR(symval, eisa_device_id, sig); 784 if (sig[0]) 785 sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig); 786 else 787 strcat(alias, "*"); 788 return 1; 789 } 790 791 /* Looks like: parisc:tNhvNrevNsvN */ 792 static int do_parisc_entry(const char *filename, void *symval, 793 char *alias) 794 { 795 DEF_FIELD(symval, parisc_device_id, hw_type); 796 DEF_FIELD(symval, parisc_device_id, hversion); 797 DEF_FIELD(symval, parisc_device_id, hversion_rev); 798 DEF_FIELD(symval, parisc_device_id, sversion); 799 800 strcpy(alias, "parisc:"); 801 ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type); 802 ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion); 803 ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev); 804 ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion); 805 806 add_wildcard(alias); 807 return 1; 808 } 809 810 /* Looks like: sdio:cNvNdN. */ 811 static int do_sdio_entry(const char *filename, 812 void *symval, char *alias) 813 { 814 DEF_FIELD(symval, sdio_device_id, class); 815 DEF_FIELD(symval, sdio_device_id, vendor); 816 DEF_FIELD(symval, sdio_device_id, device); 817 818 strcpy(alias, "sdio:"); 819 ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class); 820 ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor); 821 ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device); 822 add_wildcard(alias); 823 return 1; 824 } 825 826 /* Looks like: ssb:vNidNrevN. */ 827 static int do_ssb_entry(const char *filename, 828 void *symval, char *alias) 829 { 830 DEF_FIELD(symval, ssb_device_id, vendor); 831 DEF_FIELD(symval, ssb_device_id, coreid); 832 DEF_FIELD(symval, ssb_device_id, revision); 833 834 strcpy(alias, "ssb:"); 835 ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor); 836 ADD(alias, "id", coreid != SSB_ANY_ID, coreid); 837 ADD(alias, "rev", revision != SSB_ANY_REV, revision); 838 add_wildcard(alias); 839 return 1; 840 } 841 842 /* Looks like: bcma:mNidNrevNclN. */ 843 static int do_bcma_entry(const char *filename, 844 void *symval, char *alias) 845 { 846 DEF_FIELD(symval, bcma_device_id, manuf); 847 DEF_FIELD(symval, bcma_device_id, id); 848 DEF_FIELD(symval, bcma_device_id, rev); 849 DEF_FIELD(symval, bcma_device_id, class); 850 851 strcpy(alias, "bcma:"); 852 ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf); 853 ADD(alias, "id", id != BCMA_ANY_ID, id); 854 ADD(alias, "rev", rev != BCMA_ANY_REV, rev); 855 ADD(alias, "cl", class != BCMA_ANY_CLASS, class); 856 add_wildcard(alias); 857 return 1; 858 } 859 860 /* Looks like: virtio:dNvN */ 861 static int do_virtio_entry(const char *filename, void *symval, 862 char *alias) 863 { 864 DEF_FIELD(symval, virtio_device_id, device); 865 DEF_FIELD(symval, virtio_device_id, vendor); 866 867 strcpy(alias, "virtio:"); 868 ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device); 869 ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor); 870 871 add_wildcard(alias); 872 return 1; 873 } 874 875 /* 876 * Looks like: vmbus:guid 877 * Each byte of the guid will be represented by two hex characters 878 * in the name. 879 */ 880 881 static int do_vmbus_entry(const char *filename, void *symval, 882 char *alias) 883 { 884 int i; 885 DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid); 886 char guid_name[(sizeof(*guid) + 1) * 2]; 887 888 for (i = 0; i < (sizeof(*guid) * 2); i += 2) 889 sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2])); 890 891 strcpy(alias, "vmbus:"); 892 strcat(alias, guid_name); 893 894 return 1; 895 } 896 897 /* Looks like: rpmsg:S */ 898 static int do_rpmsg_entry(const char *filename, void *symval, 899 char *alias) 900 { 901 DEF_FIELD_ADDR(symval, rpmsg_device_id, name); 902 sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name); 903 904 return 1; 905 } 906 907 /* Looks like: i2c:S */ 908 static int do_i2c_entry(const char *filename, void *symval, 909 char *alias) 910 { 911 DEF_FIELD_ADDR(symval, i2c_device_id, name); 912 sprintf(alias, I2C_MODULE_PREFIX "%s", *name); 913 914 return 1; 915 } 916 917 /* Looks like: spi:S */ 918 static int do_spi_entry(const char *filename, void *symval, 919 char *alias) 920 { 921 DEF_FIELD_ADDR(symval, spi_device_id, name); 922 sprintf(alias, SPI_MODULE_PREFIX "%s", *name); 923 924 return 1; 925 } 926 927 static const struct dmifield { 928 const char *prefix; 929 int field; 930 } dmi_fields[] = { 931 { "bvn", DMI_BIOS_VENDOR }, 932 { "bvr", DMI_BIOS_VERSION }, 933 { "bd", DMI_BIOS_DATE }, 934 { "svn", DMI_SYS_VENDOR }, 935 { "pn", DMI_PRODUCT_NAME }, 936 { "pvr", DMI_PRODUCT_VERSION }, 937 { "rvn", DMI_BOARD_VENDOR }, 938 { "rn", DMI_BOARD_NAME }, 939 { "rvr", DMI_BOARD_VERSION }, 940 { "cvn", DMI_CHASSIS_VENDOR }, 941 { "ct", DMI_CHASSIS_TYPE }, 942 { "cvr", DMI_CHASSIS_VERSION }, 943 { NULL, DMI_NONE } 944 }; 945 946 static void dmi_ascii_filter(char *d, const char *s) 947 { 948 /* Filter out characters we don't want to see in the modalias string */ 949 for (; *s; s++) 950 if (*s > ' ' && *s < 127 && *s != ':') 951 *(d++) = *s; 952 953 *d = 0; 954 } 955 956 957 static int do_dmi_entry(const char *filename, void *symval, 958 char *alias) 959 { 960 int i, j; 961 DEF_FIELD_ADDR(symval, dmi_system_id, matches); 962 sprintf(alias, "dmi*"); 963 964 for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) { 965 for (j = 0; j < 4; j++) { 966 if ((*matches)[j].slot && 967 (*matches)[j].slot == dmi_fields[i].field) { 968 sprintf(alias + strlen(alias), ":%s*", 969 dmi_fields[i].prefix); 970 dmi_ascii_filter(alias + strlen(alias), 971 (*matches)[j].substr); 972 strcat(alias, "*"); 973 } 974 } 975 } 976 977 strcat(alias, ":"); 978 return 1; 979 } 980 981 static int do_platform_entry(const char *filename, 982 void *symval, char *alias) 983 { 984 DEF_FIELD_ADDR(symval, platform_device_id, name); 985 sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name); 986 return 1; 987 } 988 989 static int do_mdio_entry(const char *filename, 990 void *symval, char *alias) 991 { 992 int i; 993 DEF_FIELD(symval, mdio_device_id, phy_id); 994 DEF_FIELD(symval, mdio_device_id, phy_id_mask); 995 996 alias += sprintf(alias, MDIO_MODULE_PREFIX); 997 998 for (i = 0; i < 32; i++) { 999 if (!((phy_id_mask >> (31-i)) & 1)) 1000 *(alias++) = '?'; 1001 else if ((phy_id >> (31-i)) & 1) 1002 *(alias++) = '1'; 1003 else 1004 *(alias++) = '0'; 1005 } 1006 1007 /* Terminate the string */ 1008 *alias = 0; 1009 1010 return 1; 1011 } 1012 1013 /* Looks like: zorro:iN. */ 1014 static int do_zorro_entry(const char *filename, void *symval, 1015 char *alias) 1016 { 1017 DEF_FIELD(symval, zorro_device_id, id); 1018 strcpy(alias, "zorro:"); 1019 ADD(alias, "i", id != ZORRO_WILDCARD, id); 1020 return 1; 1021 } 1022 1023 /* looks like: "pnp:dD" */ 1024 static int do_isapnp_entry(const char *filename, 1025 void *symval, char *alias) 1026 { 1027 DEF_FIELD(symval, isapnp_device_id, vendor); 1028 DEF_FIELD(symval, isapnp_device_id, function); 1029 sprintf(alias, "pnp:d%c%c%c%x%x%x%x*", 1030 'A' + ((vendor >> 2) & 0x3f) - 1, 1031 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1, 1032 'A' + ((vendor >> 8) & 0x1f) - 1, 1033 (function >> 4) & 0x0f, function & 0x0f, 1034 (function >> 12) & 0x0f, (function >> 8) & 0x0f); 1035 return 1; 1036 } 1037 1038 /* Looks like: "ipack:fNvNdN". */ 1039 static int do_ipack_entry(const char *filename, 1040 void *symval, char *alias) 1041 { 1042 DEF_FIELD(symval, ipack_device_id, format); 1043 DEF_FIELD(symval, ipack_device_id, vendor); 1044 DEF_FIELD(symval, ipack_device_id, device); 1045 strcpy(alias, "ipack:"); 1046 ADD(alias, "f", format != IPACK_ANY_FORMAT, format); 1047 ADD(alias, "v", vendor != IPACK_ANY_ID, vendor); 1048 ADD(alias, "d", device != IPACK_ANY_ID, device); 1049 add_wildcard(alias); 1050 return 1; 1051 } 1052 1053 /* 1054 * Append a match expression for a single masked hex digit. 1055 * outp points to a pointer to the character at which to append. 1056 * *outp is updated on return to point just after the appended text, 1057 * to facilitate further appending. 1058 */ 1059 static void append_nibble_mask(char **outp, 1060 unsigned int nibble, unsigned int mask) 1061 { 1062 char *p = *outp; 1063 unsigned int i; 1064 1065 switch (mask) { 1066 case 0: 1067 *p++ = '?'; 1068 break; 1069 1070 case 0xf: 1071 p += sprintf(p, "%X", nibble); 1072 break; 1073 1074 default: 1075 /* 1076 * Dumbly emit a match pattern for all possible matching 1077 * digits. This could be improved in some cases using ranges, 1078 * but it has the advantage of being trivially correct, and is 1079 * often optimal. 1080 */ 1081 *p++ = '['; 1082 for (i = 0; i < 0x10; i++) 1083 if ((i & mask) == nibble) 1084 p += sprintf(p, "%X", i); 1085 *p++ = ']'; 1086 } 1087 1088 /* Ensure that the string remains NUL-terminated: */ 1089 *p = '\0'; 1090 1091 /* Advance the caller's end-of-string pointer: */ 1092 *outp = p; 1093 } 1094 1095 /* 1096 * looks like: "amba:dN" 1097 * 1098 * N is exactly 8 digits, where each is an upper-case hex digit, or 1099 * a ? or [] pattern matching exactly one digit. 1100 */ 1101 static int do_amba_entry(const char *filename, 1102 void *symval, char *alias) 1103 { 1104 unsigned int digit; 1105 char *p = alias; 1106 DEF_FIELD(symval, amba_id, id); 1107 DEF_FIELD(symval, amba_id, mask); 1108 1109 if ((id & mask) != id) 1110 fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: " 1111 "id=0x%08X, mask=0x%08X. Please fix this driver.\n", 1112 filename, id, mask); 1113 1114 p += sprintf(alias, "amba:d"); 1115 for (digit = 0; digit < 8; digit++) 1116 append_nibble_mask(&p, 1117 (id >> (4 * (7 - digit))) & 0xf, 1118 (mask >> (4 * (7 - digit))) & 0xf); 1119 1120 return 1; 1121 } 1122 1123 /* 1124 * looks like: "mipscdmm:tN" 1125 * 1126 * N is exactly 2 digits, where each is an upper-case hex digit, or 1127 * a ? or [] pattern matching exactly one digit. 1128 */ 1129 static int do_mips_cdmm_entry(const char *filename, 1130 void *symval, char *alias) 1131 { 1132 DEF_FIELD(symval, mips_cdmm_device_id, type); 1133 1134 sprintf(alias, "mipscdmm:t%02X*", type); 1135 return 1; 1136 } 1137 1138 /* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,* 1139 * All fields are numbers. It would be nicer to use strings for vendor 1140 * and feature, but getting those out of the build system here is too 1141 * complicated. 1142 */ 1143 1144 static int do_x86cpu_entry(const char *filename, void *symval, 1145 char *alias) 1146 { 1147 DEF_FIELD(symval, x86_cpu_id, feature); 1148 DEF_FIELD(symval, x86_cpu_id, family); 1149 DEF_FIELD(symval, x86_cpu_id, model); 1150 DEF_FIELD(symval, x86_cpu_id, vendor); 1151 1152 strcpy(alias, "cpu:type:x86,"); 1153 ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor); 1154 ADD(alias, "fam", family != X86_FAMILY_ANY, family); 1155 ADD(alias, "mod", model != X86_MODEL_ANY, model); 1156 strcat(alias, ":feature:*"); 1157 if (feature != X86_FEATURE_ANY) 1158 sprintf(alias + strlen(alias), "%04X*", feature); 1159 return 1; 1160 } 1161 1162 /* LOOKS like cpu:type:*:feature:*FEAT* */ 1163 static int do_cpu_entry(const char *filename, void *symval, char *alias) 1164 { 1165 DEF_FIELD(symval, cpu_feature, feature); 1166 1167 sprintf(alias, "cpu:type:*:feature:*%04X*", feature); 1168 return 1; 1169 } 1170 1171 /* Looks like: mei:S:uuid:N:* */ 1172 static int do_mei_entry(const char *filename, void *symval, 1173 char *alias) 1174 { 1175 DEF_FIELD_ADDR(symval, mei_cl_device_id, name); 1176 DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid); 1177 DEF_FIELD(symval, mei_cl_device_id, version); 1178 1179 sprintf(alias, MEI_CL_MODULE_PREFIX); 1180 sprintf(alias + strlen(alias), "%s:", (*name)[0] ? *name : "*"); 1181 add_uuid(alias, *uuid); 1182 ADD(alias, ":", version != MEI_CL_VERSION_ANY, version); 1183 1184 strcat(alias, ":*"); 1185 1186 return 1; 1187 } 1188 1189 /* Looks like: rapidio:vNdNavNadN */ 1190 static int do_rio_entry(const char *filename, 1191 void *symval, char *alias) 1192 { 1193 DEF_FIELD(symval, rio_device_id, did); 1194 DEF_FIELD(symval, rio_device_id, vid); 1195 DEF_FIELD(symval, rio_device_id, asm_did); 1196 DEF_FIELD(symval, rio_device_id, asm_vid); 1197 1198 strcpy(alias, "rapidio:"); 1199 ADD(alias, "v", vid != RIO_ANY_ID, vid); 1200 ADD(alias, "d", did != RIO_ANY_ID, did); 1201 ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid); 1202 ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did); 1203 1204 add_wildcard(alias); 1205 return 1; 1206 } 1207 1208 /* Looks like: ulpi:vNpN */ 1209 static int do_ulpi_entry(const char *filename, void *symval, 1210 char *alias) 1211 { 1212 DEF_FIELD(symval, ulpi_device_id, vendor); 1213 DEF_FIELD(symval, ulpi_device_id, product); 1214 1215 sprintf(alias, "ulpi:v%04xp%04x", vendor, product); 1216 1217 return 1; 1218 } 1219 1220 /* Looks like: hdaudio:vNrNaN */ 1221 static int do_hda_entry(const char *filename, void *symval, char *alias) 1222 { 1223 DEF_FIELD(symval, hda_device_id, vendor_id); 1224 DEF_FIELD(symval, hda_device_id, rev_id); 1225 DEF_FIELD(symval, hda_device_id, api_version); 1226 1227 strcpy(alias, "hdaudio:"); 1228 ADD(alias, "v", vendor_id != 0, vendor_id); 1229 ADD(alias, "r", rev_id != 0, rev_id); 1230 ADD(alias, "a", api_version != 0, api_version); 1231 1232 add_wildcard(alias); 1233 return 1; 1234 } 1235 1236 /* Looks like: sdw:mNpN */ 1237 static int do_sdw_entry(const char *filename, void *symval, char *alias) 1238 { 1239 DEF_FIELD(symval, sdw_device_id, mfg_id); 1240 DEF_FIELD(symval, sdw_device_id, part_id); 1241 1242 strcpy(alias, "sdw:"); 1243 ADD(alias, "m", mfg_id != 0, mfg_id); 1244 ADD(alias, "p", part_id != 0, part_id); 1245 1246 add_wildcard(alias); 1247 return 1; 1248 } 1249 1250 /* Looks like: fsl-mc:vNdN */ 1251 static int do_fsl_mc_entry(const char *filename, void *symval, 1252 char *alias) 1253 { 1254 DEF_FIELD(symval, fsl_mc_device_id, vendor); 1255 DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type); 1256 1257 sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type); 1258 return 1; 1259 } 1260 1261 /* Looks like: tbsvc:kSpNvNrN */ 1262 static int do_tbsvc_entry(const char *filename, void *symval, char *alias) 1263 { 1264 DEF_FIELD(symval, tb_service_id, match_flags); 1265 DEF_FIELD_ADDR(symval, tb_service_id, protocol_key); 1266 DEF_FIELD(symval, tb_service_id, protocol_id); 1267 DEF_FIELD(symval, tb_service_id, protocol_version); 1268 DEF_FIELD(symval, tb_service_id, protocol_revision); 1269 1270 strcpy(alias, "tbsvc:"); 1271 if (match_flags & TBSVC_MATCH_PROTOCOL_KEY) 1272 sprintf(alias + strlen(alias), "k%s", *protocol_key); 1273 else 1274 strcat(alias + strlen(alias), "k*"); 1275 ADD(alias, "p", match_flags & TBSVC_MATCH_PROTOCOL_ID, protocol_id); 1276 ADD(alias, "v", match_flags & TBSVC_MATCH_PROTOCOL_VERSION, 1277 protocol_version); 1278 ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION, 1279 protocol_revision); 1280 1281 add_wildcard(alias); 1282 return 1; 1283 } 1284 1285 /* Looks like: typec:idNmN */ 1286 static int do_typec_entry(const char *filename, void *symval, char *alias) 1287 { 1288 DEF_FIELD(symval, typec_device_id, svid); 1289 DEF_FIELD(symval, typec_device_id, mode); 1290 1291 sprintf(alias, "typec:id%04X", svid); 1292 ADD(alias, "m", mode != TYPEC_ANY_MODE, mode); 1293 1294 return 1; 1295 } 1296 1297 /* Looks like: tee:uuid */ 1298 static int do_tee_entry(const char *filename, void *symval, char *alias) 1299 { 1300 DEF_FIELD(symval, tee_client_device_id, uuid); 1301 1302 sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 1303 uuid.b[0], uuid.b[1], uuid.b[2], uuid.b[3], uuid.b[4], 1304 uuid.b[5], uuid.b[6], uuid.b[7], uuid.b[8], uuid.b[9], 1305 uuid.b[10], uuid.b[11], uuid.b[12], uuid.b[13], uuid.b[14], 1306 uuid.b[15]); 1307 1308 add_wildcard(alias); 1309 return 1; 1310 } 1311 1312 /* Looks like: wmi:guid */ 1313 static int do_wmi_entry(const char *filename, void *symval, char *alias) 1314 { 1315 int len; 1316 DEF_FIELD_ADDR(symval, wmi_device_id, guid_string); 1317 1318 if (strlen(*guid_string) != UUID_STRING_LEN) { 1319 warn("Invalid WMI device id 'wmi:%s' in '%s'\n", 1320 *guid_string, filename); 1321 return 0; 1322 } 1323 1324 len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string); 1325 if (len < 0 || len >= ALIAS_SIZE) { 1326 warn("Could not generate all MODULE_ALIAS's in '%s'\n", 1327 filename); 1328 return 0; 1329 } 1330 return 1; 1331 } 1332 1333 /* Does namelen bytes of name exactly match the symbol? */ 1334 static bool sym_is(const char *name, unsigned namelen, const char *symbol) 1335 { 1336 if (namelen != strlen(symbol)) 1337 return false; 1338 1339 return memcmp(name, symbol, namelen) == 0; 1340 } 1341 1342 static void do_table(void *symval, unsigned long size, 1343 unsigned long id_size, 1344 const char *device_id, 1345 int (*do_entry)(const char *filename, void *symval, char *alias), 1346 struct module *mod) 1347 { 1348 unsigned int i; 1349 char alias[ALIAS_SIZE]; 1350 1351 device_id_check(mod->name, device_id, size, id_size, symval); 1352 /* Leave last one: it's the terminator. */ 1353 size -= id_size; 1354 1355 for (i = 0; i < size; i += id_size) { 1356 if (do_entry(mod->name, symval+i, alias)) { 1357 buf_printf(&mod->dev_table_buf, 1358 "MODULE_ALIAS(\"%s\");\n", alias); 1359 } 1360 } 1361 } 1362 1363 static const struct devtable devtable[] = { 1364 {"hid", SIZE_hid_device_id, do_hid_entry}, 1365 {"ieee1394", SIZE_ieee1394_device_id, do_ieee1394_entry}, 1366 {"pci", SIZE_pci_device_id, do_pci_entry}, 1367 {"ccw", SIZE_ccw_device_id, do_ccw_entry}, 1368 {"ap", SIZE_ap_device_id, do_ap_entry}, 1369 {"css", SIZE_css_device_id, do_css_entry}, 1370 {"serio", SIZE_serio_device_id, do_serio_entry}, 1371 {"acpi", SIZE_acpi_device_id, do_acpi_entry}, 1372 {"pcmcia", SIZE_pcmcia_device_id, do_pcmcia_entry}, 1373 {"vio", SIZE_vio_device_id, do_vio_entry}, 1374 {"input", SIZE_input_device_id, do_input_entry}, 1375 {"eisa", SIZE_eisa_device_id, do_eisa_entry}, 1376 {"parisc", SIZE_parisc_device_id, do_parisc_entry}, 1377 {"sdio", SIZE_sdio_device_id, do_sdio_entry}, 1378 {"ssb", SIZE_ssb_device_id, do_ssb_entry}, 1379 {"bcma", SIZE_bcma_device_id, do_bcma_entry}, 1380 {"virtio", SIZE_virtio_device_id, do_virtio_entry}, 1381 {"vmbus", SIZE_hv_vmbus_device_id, do_vmbus_entry}, 1382 {"rpmsg", SIZE_rpmsg_device_id, do_rpmsg_entry}, 1383 {"i2c", SIZE_i2c_device_id, do_i2c_entry}, 1384 {"spi", SIZE_spi_device_id, do_spi_entry}, 1385 {"dmi", SIZE_dmi_system_id, do_dmi_entry}, 1386 {"platform", SIZE_platform_device_id, do_platform_entry}, 1387 {"mdio", SIZE_mdio_device_id, do_mdio_entry}, 1388 {"zorro", SIZE_zorro_device_id, do_zorro_entry}, 1389 {"isapnp", SIZE_isapnp_device_id, do_isapnp_entry}, 1390 {"ipack", SIZE_ipack_device_id, do_ipack_entry}, 1391 {"amba", SIZE_amba_id, do_amba_entry}, 1392 {"mipscdmm", SIZE_mips_cdmm_device_id, do_mips_cdmm_entry}, 1393 {"x86cpu", SIZE_x86_cpu_id, do_x86cpu_entry}, 1394 {"cpu", SIZE_cpu_feature, do_cpu_entry}, 1395 {"mei", SIZE_mei_cl_device_id, do_mei_entry}, 1396 {"rapidio", SIZE_rio_device_id, do_rio_entry}, 1397 {"ulpi", SIZE_ulpi_device_id, do_ulpi_entry}, 1398 {"hdaudio", SIZE_hda_device_id, do_hda_entry}, 1399 {"sdw", SIZE_sdw_device_id, do_sdw_entry}, 1400 {"fslmc", SIZE_fsl_mc_device_id, do_fsl_mc_entry}, 1401 {"tbsvc", SIZE_tb_service_id, do_tbsvc_entry}, 1402 {"typec", SIZE_typec_device_id, do_typec_entry}, 1403 {"tee", SIZE_tee_client_device_id, do_tee_entry}, 1404 {"wmi", SIZE_wmi_device_id, do_wmi_entry}, 1405 }; 1406 1407 /* Create MODULE_ALIAS() statements. 1408 * At this time, we cannot write the actual output C source yet, 1409 * so we write into the mod->dev_table_buf buffer. */ 1410 void handle_moddevtable(struct module *mod, struct elf_info *info, 1411 Elf_Sym *sym, const char *symname) 1412 { 1413 void *symval; 1414 char *zeros = NULL; 1415 const char *name, *identifier; 1416 unsigned int namelen; 1417 1418 /* We're looking for a section relative symbol */ 1419 if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections) 1420 return; 1421 1422 /* We're looking for an object */ 1423 if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) 1424 return; 1425 1426 /* All our symbols are of form __mod_<name>__<identifier>_device_table. */ 1427 if (strncmp(symname, "__mod_", strlen("__mod_"))) 1428 return; 1429 name = symname + strlen("__mod_"); 1430 namelen = strlen(name); 1431 if (namelen < strlen("_device_table")) 1432 return; 1433 if (strcmp(name + namelen - strlen("_device_table"), "_device_table")) 1434 return; 1435 identifier = strstr(name, "__"); 1436 if (!identifier) 1437 return; 1438 namelen = identifier - name; 1439 1440 /* Handle all-NULL symbols allocated into .bss */ 1441 if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) { 1442 zeros = calloc(1, sym->st_size); 1443 symval = zeros; 1444 } else { 1445 symval = (void *)info->hdr 1446 + info->sechdrs[get_secindex(info, sym)].sh_offset 1447 + sym->st_value; 1448 } 1449 1450 /* First handle the "special" cases */ 1451 if (sym_is(name, namelen, "usb")) 1452 do_usb_table(symval, sym->st_size, mod); 1453 if (sym_is(name, namelen, "of")) 1454 do_of_table(symval, sym->st_size, mod); 1455 else if (sym_is(name, namelen, "pnp")) 1456 do_pnp_device_entry(symval, sym->st_size, mod); 1457 else if (sym_is(name, namelen, "pnp_card")) 1458 do_pnp_card_entries(symval, sym->st_size, mod); 1459 else { 1460 int i; 1461 1462 for (i = 0; i < ARRAY_SIZE(devtable); i++) { 1463 const struct devtable *p = &devtable[i]; 1464 1465 if (sym_is(name, namelen, p->device_id)) { 1466 do_table(symval, sym->st_size, p->id_size, 1467 p->device_id, p->do_entry, mod); 1468 break; 1469 } 1470 } 1471 } 1472 free(zeros); 1473 } 1474 1475 /* Now add out buffered information to the generated C source */ 1476 void add_moddevtable(struct buffer *buf, struct module *mod) 1477 { 1478 buf_printf(buf, "\n"); 1479 buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos); 1480 free(mod->dev_table_buf.p); 1481 } 1482