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