1 /* 2 * Copyright (c) 1996, by Steve Passe 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. The name of the developer may NOT be used to endorse or promote products 11 * derived from this software without specific prior written permission. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 /* 27 * mptable.c 28 */ 29 30 #ifndef lint 31 static const char rcsid[] = 32 "$FreeBSD$"; 33 #endif /* not lint */ 34 35 #define VMAJOR 2 36 #define VMINOR 0 37 #define VDELTA 15 38 39 /* 40 * this will cause the raw mp table to be dumped to /tmp/mpdump 41 * 42 #define RAW_DUMP 43 */ 44 45 #define MP_SIG 0x5f504d5f /* _MP_ */ 46 #define EXTENDED_PROCESSING_READY 47 #define OEM_PROCESSING_READY_NOT 48 49 #include <sys/types.h> 50 #include <err.h> 51 #include <fcntl.h> 52 #include <paths.h> 53 #include <stdio.h> 54 #include <stdlib.h> 55 #include <string.h> 56 #include <unistd.h> 57 58 #define SEP_LINE \ 59 "\n-------------------------------------------------------------------------------\n" 60 61 #define SEP_LINE2 \ 62 "\n===============================================================================\n" 63 64 /* EBDA is @ 40:0e in real-mode terms */ 65 #define EBDA_POINTER 0x040e /* location of EBDA pointer */ 66 67 /* CMOS 'top of mem' is @ 40:13 in real-mode terms */ 68 #define TOPOFMEM_POINTER 0x0413 /* BIOS: base memory size */ 69 70 #define DEFAULT_TOPOFMEM 0xa0000 71 72 #define BIOS_BASE 0xf0000 73 #define BIOS_BASE2 0xe0000 74 #define BIOS_SIZE 0x10000 75 #define ONE_KBYTE 1024 76 77 #define GROPE_AREA1 0x80000 78 #define GROPE_AREA2 0x90000 79 #define GROPE_SIZE 0x10000 80 81 #define PROCENTRY_FLAG_EN 0x01 82 #define PROCENTRY_FLAG_BP 0x02 83 #define IOAPICENTRY_FLAG_EN 0x01 84 85 #define MAXPNSTR 132 86 87 enum busTypes { 88 CBUS = 1, 89 CBUSII = 2, 90 EISA = 3, 91 ISA = 6, 92 PCI = 13, 93 XPRESS = 18, 94 MAX_BUSTYPE = 18, 95 UNKNOWN_BUSTYPE = 0xff 96 }; 97 98 typedef struct BUSTYPENAME { 99 u_char type; 100 char name[ 7 ]; 101 } busTypeName; 102 103 static busTypeName busTypeTable[] = 104 { 105 { CBUS, "CBUS" }, 106 { CBUSII, "CBUSII" }, 107 { EISA, "EISA" }, 108 { UNKNOWN_BUSTYPE, "---" }, 109 { UNKNOWN_BUSTYPE, "---" }, 110 { ISA, "ISA" }, 111 { UNKNOWN_BUSTYPE, "---" }, 112 { UNKNOWN_BUSTYPE, "---" }, 113 { UNKNOWN_BUSTYPE, "---" }, 114 { UNKNOWN_BUSTYPE, "---" }, 115 { UNKNOWN_BUSTYPE, "---" }, 116 { UNKNOWN_BUSTYPE, "---" }, 117 { PCI, "PCI" }, 118 { UNKNOWN_BUSTYPE, "---" }, 119 { UNKNOWN_BUSTYPE, "---" }, 120 { UNKNOWN_BUSTYPE, "---" }, 121 { UNKNOWN_BUSTYPE, "---" }, 122 { UNKNOWN_BUSTYPE, "---" }, 123 { UNKNOWN_BUSTYPE, "---" } 124 }; 125 126 char* whereStrings[] = { 127 "Extended BIOS Data Area", 128 "BIOS top of memory", 129 "Default top of memory", 130 "BIOS", 131 "Extended BIOS", 132 "GROPE AREA #1", 133 "GROPE AREA #2" 134 }; 135 136 typedef struct TABLE_ENTRY { 137 u_char type; 138 u_char length; 139 char name[ 32 ]; 140 } tableEntry; 141 142 tableEntry basetableEntryTypes[] = 143 { 144 { 0, 20, "Processor" }, 145 { 1, 8, "Bus" }, 146 { 2, 8, "I/O APIC" }, 147 { 3, 8, "I/O INT" }, 148 { 4, 8, "Local INT" } 149 }; 150 151 tableEntry extendedtableEntryTypes[] = 152 { 153 { 128, 20, "System Address Space" }, 154 { 129, 8, "Bus Heirarchy" }, 155 { 130, 8, "Compatibility Bus Address" } 156 }; 157 158 /* MP Floating Pointer Structure */ 159 typedef struct MPFPS { 160 char signature[ 4 ]; 161 void* pap; 162 u_char length; 163 u_char spec_rev; 164 u_char checksum; 165 u_char mpfb1; 166 u_char mpfb2; 167 u_char mpfb3; 168 u_char mpfb4; 169 u_char mpfb5; 170 } mpfps_t; 171 172 /* MP Configuration Table Header */ 173 typedef struct MPCTH { 174 char signature[ 4 ]; 175 u_short base_table_length; 176 u_char spec_rev; 177 u_char checksum; 178 u_char oem_id[ 8 ]; 179 u_char product_id[ 12 ]; 180 void* oem_table_pointer; 181 u_short oem_table_size; 182 u_short entry_count; 183 void* apic_address; 184 u_short extended_table_length; 185 u_char extended_table_checksum; 186 u_char reserved; 187 } mpcth_t; 188 189 190 typedef struct PROCENTRY { 191 u_char type; 192 u_char apicID; 193 u_char apicVersion; 194 u_char cpuFlags; 195 u_long cpuSignature; 196 u_long featureFlags; 197 u_long reserved1; 198 u_long reserved2; 199 } ProcEntry; 200 201 typedef struct BUSENTRY { 202 u_char type; 203 u_char busID; 204 char busType[ 6 ]; 205 } BusEntry; 206 207 typedef struct IOAPICENTRY { 208 u_char type; 209 u_char apicID; 210 u_char apicVersion; 211 u_char apicFlags; 212 void* apicAddress; 213 } IOApicEntry; 214 215 typedef struct INTENTRY { 216 u_char type; 217 u_char intType; 218 u_short intFlags; 219 u_char srcBusID; 220 u_char srcBusIRQ; 221 u_char dstApicID; 222 u_char dstApicINT; 223 } IntEntry; 224 225 226 /* 227 * extended entry type structures 228 */ 229 230 typedef struct SASENTRY { 231 u_char type; 232 u_char length; 233 u_char busID; 234 u_char addressType; 235 u_int64_t addressBase; 236 u_int64_t addressLength; 237 } SasEntry; 238 239 240 typedef struct BHDENTRY { 241 u_char type; 242 u_char length; 243 u_char busID; 244 u_char busInfo; 245 u_char busParent; 246 u_char reserved[ 3 ]; 247 } BhdEntry; 248 249 250 typedef struct CBASMENTRY { 251 u_char type; 252 u_char length; 253 u_char busID; 254 u_char addressMod; 255 u_int predefinedRange; 256 } CbasmEntry; 257 258 259 260 static void apic_probe( vm_offset_t* paddr, int* where ); 261 262 static void MPConfigDefault( int featureByte ); 263 264 static void MPFloatingPointer( vm_offset_t paddr, int where, mpfps_t* mpfps ); 265 static void MPConfigTableHeader( void* pap ); 266 267 static int readType( void ); 268 static void seekEntry( vm_offset_t addr ); 269 static void readEntry( void* entry, int size ); 270 271 static void processorEntry( void ); 272 static void busEntry( void ); 273 static void ioApicEntry( void ); 274 static void intEntry( void ); 275 276 static void sasEntry( void ); 277 static void bhdEntry( void ); 278 static void cbasmEntry( void ); 279 280 static void doDmesg( void ); 281 static void pnstr( char* s, int c ); 282 283 /* global data */ 284 int pfd; /* physical /dev/mem fd */ 285 286 int busses[ 16 ]; 287 int apics[ 16 ]; 288 289 int ncpu; 290 int nbus; 291 int napic; 292 int nintr; 293 294 int dmesg; 295 int grope; 296 int verbose; 297 298 static void 299 usage( void ) 300 { 301 fprintf( stderr, "usage: mptable [-dmesg] [-verbose] [-grope] [-help]\n" ); 302 exit( 0 ); 303 } 304 305 /* 306 * 307 */ 308 int 309 main( int argc, char *argv[] ) 310 { 311 vm_offset_t paddr; 312 int where; 313 mpfps_t mpfps; 314 int defaultConfig; 315 316 extern int optreset; 317 int ch; 318 319 /* announce ourselves */ 320 puts( SEP_LINE2 ); 321 322 printf( "MPTable, version %d.%d.%d\n", VMAJOR, VMINOR, VDELTA ); 323 324 while ((ch = getopt(argc, argv, "d:g:h:v:")) != -1) { 325 switch(ch) { 326 case 'd': 327 if ( strcmp( optarg, "mesg") == 0 ) 328 dmesg = 1; 329 else 330 dmesg = 0; 331 break; 332 case 'h': 333 if ( strcmp( optarg, "elp") == 0 ) 334 usage(); 335 break; 336 case 'g': 337 if ( strcmp( optarg, "rope") == 0 ) 338 grope = 1; 339 break; 340 case 'v': 341 if ( strcmp( optarg, "erbose") == 0 ) 342 verbose = 1; 343 break; 344 default: 345 usage(); 346 } 347 argc -= optind; 348 argv += optind; 349 optreset = 1; 350 optind = 0; 351 } 352 353 /* open physical memory for access to MP structures */ 354 if ( (pfd = open( _PATH_MEM, O_RDONLY )) < 0 ) 355 err( 1, "mem open" ); 356 357 /* probe for MP structures */ 358 apic_probe( &paddr, &where ); 359 if ( where <= 0 ) { 360 fprintf( stderr, "\n MP FPS NOT found,\n" ); 361 fprintf( stderr, " suggest trying -grope option!!!\n\n" ); 362 return 1; 363 } 364 365 if ( verbose ) 366 printf( "\n MP FPS found in %s @ physical addr: 0x%08x\n", 367 whereStrings[ where - 1 ], paddr ); 368 369 puts( SEP_LINE ); 370 371 /* analyze the MP Floating Pointer Structure */ 372 MPFloatingPointer( paddr, where, &mpfps ); 373 374 puts( SEP_LINE ); 375 376 /* check whether an MP config table exists */ 377 if ( (defaultConfig = mpfps.mpfb1) ) 378 MPConfigDefault( defaultConfig ); 379 else 380 MPConfigTableHeader( mpfps.pap ); 381 382 /* do a dmesg output */ 383 if ( dmesg ) 384 doDmesg(); 385 386 puts( SEP_LINE2 ); 387 388 return 0; 389 } 390 391 392 /* 393 * set PHYSICAL address of MP floating pointer structure 394 */ 395 #define NEXT(X) ((X) += 4) 396 static void 397 apic_probe( vm_offset_t* paddr, int* where ) 398 { 399 /* 400 * c rewrite of apic_probe() by Jack F. Vogel 401 */ 402 403 int x; 404 u_short segment; 405 vm_offset_t target; 406 u_int buffer[ BIOS_SIZE / sizeof( int ) ]; 407 408 if ( verbose ) 409 printf( "\n" ); 410 411 /* search Extended Bios Data Area, if present */ 412 if ( verbose ) 413 printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER ); 414 seekEntry( (vm_offset_t)EBDA_POINTER ); 415 readEntry( &segment, 2 ); 416 if ( segment ) { /* search EBDA */ 417 target = (vm_offset_t)segment << 4; 418 if ( verbose ) 419 printf( "found, searching EBDA @ 0x%08x\n", target ); 420 seekEntry( target ); 421 readEntry( buffer, ONE_KBYTE ); 422 423 for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) { 424 if ( buffer[ x ] == MP_SIG ) { 425 *where = 1; 426 *paddr = (x * sizeof( unsigned int )) + target; 427 return; 428 } 429 } 430 } 431 else { 432 if ( verbose ) 433 printf( "NOT found\n" ); 434 } 435 436 /* read CMOS for real top of mem */ 437 seekEntry( (vm_offset_t)TOPOFMEM_POINTER ); 438 readEntry( &segment, 2 ); 439 --segment; /* less ONE_KBYTE */ 440 target = segment * 1024; 441 if ( verbose ) 442 printf( " searching CMOS 'top of mem' @ 0x%08x (%dK)\n", 443 target, segment ); 444 seekEntry( target ); 445 readEntry( buffer, ONE_KBYTE ); 446 447 for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) { 448 if ( buffer[ x ] == MP_SIG ) { 449 *where = 2; 450 *paddr = (x * sizeof( unsigned int )) + target; 451 return; 452 } 453 } 454 455 /* we don't necessarily believe CMOS, check base of the last 1K of 640K */ 456 if ( target != (DEFAULT_TOPOFMEM - 1024)) { 457 target = (DEFAULT_TOPOFMEM - 1024); 458 if ( verbose ) 459 printf( " searching default 'top of mem' @ 0x%08x (%dK)\n", 460 target, (target / 1024) ); 461 seekEntry( target ); 462 readEntry( buffer, ONE_KBYTE ); 463 464 for ( x = 0; x < ONE_KBYTE / sizeof ( unsigned int ); NEXT(x) ) { 465 if ( buffer[ x ] == MP_SIG ) { 466 *where = 3; 467 *paddr = (x * sizeof( unsigned int )) + target; 468 return; 469 } 470 } 471 } 472 473 /* search the BIOS */ 474 if ( verbose ) 475 printf( " searching BIOS @ 0x%08x\n", BIOS_BASE ); 476 seekEntry( BIOS_BASE ); 477 readEntry( buffer, BIOS_SIZE ); 478 479 for ( x = 0; x < BIOS_SIZE / sizeof( unsigned int ); NEXT(x) ) { 480 if ( buffer[ x ] == MP_SIG ) { 481 *where = 4; 482 *paddr = (x * sizeof( unsigned int )) + BIOS_BASE; 483 return; 484 } 485 } 486 487 /* search the extended BIOS */ 488 if ( verbose ) 489 printf( " searching extended BIOS @ 0x%08x\n", BIOS_BASE2 ); 490 seekEntry( BIOS_BASE2 ); 491 readEntry( buffer, BIOS_SIZE ); 492 493 for ( x = 0; x < BIOS_SIZE / sizeof( unsigned int ); NEXT(x) ) { 494 if ( buffer[ x ] == MP_SIG ) { 495 *where = 5; 496 *paddr = (x * sizeof( unsigned int )) + BIOS_BASE2; 497 return; 498 } 499 } 500 501 if ( grope ) { 502 /* search additional memory */ 503 target = GROPE_AREA1; 504 if ( verbose ) 505 printf( " groping memory @ 0x%08x\n", target ); 506 seekEntry( target ); 507 readEntry( buffer, GROPE_SIZE ); 508 509 for ( x = 0; x < GROPE_SIZE / sizeof( unsigned int ); NEXT(x) ) { 510 if ( buffer[ x ] == MP_SIG ) { 511 *where = 6; 512 *paddr = (x * sizeof( unsigned int )) + GROPE_AREA1; 513 return; 514 } 515 } 516 517 target = GROPE_AREA2; 518 if ( verbose ) 519 printf( " groping memory @ 0x%08x\n", target ); 520 seekEntry( target ); 521 readEntry( buffer, GROPE_SIZE ); 522 523 for ( x = 0; x < GROPE_SIZE / sizeof( unsigned int ); NEXT(x) ) { 524 if ( buffer[ x ] == MP_SIG ) { 525 *where = 7; 526 *paddr = (x * sizeof( unsigned int )) + GROPE_AREA2; 527 return; 528 } 529 } 530 } 531 532 *where = 0; 533 *paddr = (vm_offset_t)0; 534 } 535 536 537 /* 538 * 539 */ 540 static void 541 MPFloatingPointer( vm_offset_t paddr, int where, mpfps_t* mpfps ) 542 { 543 544 /* read in mpfps structure*/ 545 seekEntry( paddr ); 546 readEntry( mpfps, sizeof( mpfps_t ) ); 547 548 /* show its contents */ 549 printf( "MP Floating Pointer Structure:\n\n" ); 550 551 printf( " location:\t\t\t" ); 552 switch ( where ) 553 { 554 case 1: 555 printf( "EBDA\n" ); 556 break; 557 case 2: 558 printf( "BIOS base memory\n" ); 559 break; 560 case 3: 561 printf( "DEFAULT base memory (639K)\n" ); 562 break; 563 case 4: 564 printf( "BIOS\n" ); 565 break; 566 case 5: 567 printf( "Extended BIOS\n" ); 568 break; 569 570 case 0: 571 printf( "NOT found!\n" ); 572 exit( 1 ); 573 default: 574 printf( "BOGUS!\n" ); 575 exit( 1 ); 576 } 577 printf( " physical address:\t\t0x%08x\n", paddr ); 578 579 printf( " signature:\t\t\t'" ); 580 pnstr( mpfps->signature, 4 ); 581 printf( "'\n" ); 582 583 printf( " length:\t\t\t%d bytes\n", mpfps->length * 16 ); 584 printf( " version:\t\t\t1.%1d\n", mpfps->spec_rev ); 585 printf( " checksum:\t\t\t0x%02x\n", mpfps->checksum ); 586 587 /* bits 0:6 are RESERVED */ 588 if ( mpfps->mpfb2 & 0x7f ) { 589 printf( " warning, MP feature byte 2: 0x%02x\n", mpfps->mpfb2 ); 590 } 591 592 /* bit 7 is IMCRP */ 593 printf( " mode:\t\t\t\t%s\n", (mpfps->mpfb2 & 0x80) ? 594 "PIC" : "Virtual Wire" ); 595 596 /* MP feature bytes 3-5 are expected to be ZERO */ 597 if ( mpfps->mpfb3 ) 598 printf( " warning, MP feature byte 3 NONZERO!\n" ); 599 if ( mpfps->mpfb4 ) 600 printf( " warning, MP feature byte 4 NONZERO!\n" ); 601 if ( mpfps->mpfb5 ) 602 printf( " warning, MP feature byte 5 NONZERO!\n" ); 603 } 604 605 606 /* 607 * 608 */ 609 static void 610 MPConfigDefault( int featureByte ) 611 { 612 printf( " MP default config type: %d\n\n", featureByte ); 613 switch ( featureByte ) { 614 case 1: 615 printf( " bus: ISA, APIC: 82489DX\n" ); 616 break; 617 case 2: 618 printf( " bus: EISA, APIC: 82489DX\n" ); 619 break; 620 case 3: 621 printf( " bus: EISA, APIC: 82489DX\n" ); 622 break; 623 case 4: 624 printf( " bus: MCA, APIC: 82489DX\n" ); 625 break; 626 case 5: 627 printf( " bus: ISA+PCI, APIC: Integrated\n" ); 628 break; 629 case 6: 630 printf( " bus: EISA+PCI, APIC: Integrated\n" ); 631 break; 632 case 7: 633 printf( " bus: MCA+PCI, APIC: Integrated\n" ); 634 break; 635 default: 636 printf( " future type\n" ); 637 break; 638 } 639 640 switch ( featureByte ) { 641 case 1: 642 case 2: 643 case 3: 644 case 4: 645 nbus = 1; 646 break; 647 case 5: 648 case 6: 649 case 7: 650 nbus = 2; 651 break; 652 default: 653 printf( " future type\n" ); 654 break; 655 } 656 657 ncpu = 2; 658 napic = 1; 659 nintr = 16; 660 } 661 662 663 /* 664 * 665 */ 666 static void 667 MPConfigTableHeader( void* pap ) 668 { 669 vm_offset_t paddr; 670 mpcth_t cth; 671 int x; 672 int totalSize; 673 int count, c; 674 int type; 675 int oldtype, entrytype; 676 677 if ( pap == 0 ) { 678 printf( "MP Configuration Table Header MISSING!\n" ); 679 exit( 1 ); 680 } 681 682 /* convert physical address to virtual address */ 683 paddr = (vm_offset_t)pap; 684 685 /* read in cth structure */ 686 seekEntry( paddr ); 687 readEntry( &cth, sizeof( cth ) ); 688 689 printf( "MP Config Table Header:\n\n" ); 690 691 printf( " physical address:\t\t0x%08x\n", pap ); 692 693 printf( " signature:\t\t\t'" ); 694 pnstr( cth.signature, 4 ); 695 printf( "'\n" ); 696 697 printf( " base table length:\t\t%d\n", cth.base_table_length ); 698 699 printf( " version:\t\t\t1.%1d\n", cth.spec_rev ); 700 printf( " checksum:\t\t\t0x%02x\n", cth.checksum ); 701 702 printf( " OEM ID:\t\t\t'" ); 703 pnstr( cth.oem_id, 8 ); 704 printf( "'\n" ); 705 706 printf( " Product ID:\t\t\t'" ); 707 pnstr( cth.product_id, 12 ); 708 printf( "'\n" ); 709 710 printf( " OEM table pointer:\t\t0x%08x\n", cth.oem_table_pointer ); 711 printf( " OEM table size:\t\t%d\n", cth.oem_table_size ); 712 713 printf( " entry count:\t\t\t%d\n", cth.entry_count ); 714 715 printf( " local APIC address:\t\t0x%08x\n", cth.apic_address ); 716 717 printf( " extended table length:\t%d\n", cth.extended_table_length ); 718 printf( " extended table checksum:\t%d\n", cth.extended_table_checksum ); 719 720 totalSize = cth.base_table_length - sizeof( struct MPCTH ); 721 count = cth.entry_count; 722 723 puts( SEP_LINE ); 724 725 printf( "MP Config Base Table Entries:\n\n" ); 726 727 /* initialze tables */ 728 for ( x = 0; x < 16; ++x ) { 729 busses[ x ] = apics[ x ] = 0xff; 730 } 731 732 ncpu = 0; 733 nbus = 0; 734 napic = 0; 735 nintr = 0; 736 737 oldtype = -1; 738 for (c = count; c; c--) { 739 entrytype = readType(); 740 if (entrytype != oldtype) 741 printf("--\n"); 742 if (entrytype < oldtype) 743 printf("MPTABLE OUT OF ORDER!\n"); 744 switch (entrytype) { 745 case 0: 746 if (oldtype != 0) 747 printf( "Processors:\tAPIC ID\tVersion\tState" 748 "\t\tFamily\tModel\tStep\tFlags\n" ); 749 oldtype = 0; 750 processorEntry(); 751 break; 752 753 case 1: 754 if (oldtype != 1) 755 printf( "Bus:\t\tBus ID\tType\n" ); 756 oldtype = 1; 757 busEntry(); 758 break; 759 760 case 2: 761 if (oldtype != 2) 762 printf( "I/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" ); 763 oldtype = 2; 764 ioApicEntry(); 765 break; 766 767 case 3: 768 if (oldtype != 3) 769 printf( "I/O Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); 770 oldtype = 3; 771 intEntry(); 772 break; 773 774 case 4: 775 if (oldtype != 4) 776 printf( "Local Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); 777 oldtype = 4; 778 intEntry(); 779 break; 780 781 default: 782 printf("MPTABLE HOSED! record type = %d\n", entrytype); 783 exit(1); 784 } 785 } 786 787 788 #if defined( EXTENDED_PROCESSING_READY ) 789 /* process any extended data */ 790 if ( (totalSize = cth.extended_table_length) ) { 791 puts( SEP_LINE ); 792 793 printf( "MP Config Extended Table Entries:\n\n" ); 794 795 while ( totalSize > 0 ) { 796 switch ( type = readType() ) { 797 case 128: 798 sasEntry(); 799 break; 800 case 129: 801 bhdEntry(); 802 break; 803 case 130: 804 cbasmEntry(); 805 break; 806 default: 807 printf( "Extended Table HOSED!\n" ); 808 exit( 1 ); 809 } 810 811 totalSize -= extendedtableEntryTypes[ type-128 ].length; 812 } 813 } 814 #endif /* EXTENDED_PROCESSING_READY */ 815 816 /* process any OEM data */ 817 if ( cth.oem_table_pointer && (cth.oem_table_size > 0) ) { 818 #if defined( OEM_PROCESSING_READY ) 819 # error your on your own here! 820 /* convert OEM table pointer to virtual address */ 821 poemtp = (vm_offset_t)cth.oem_table_pointer; 822 823 /* read in oem table structure */ 824 if ( (oemdata = (void*)malloc( cth.oem_table_size )) == NULL ) 825 err( 1, "oem malloc" ); 826 827 seekEntry( poemtp ); 828 readEntry( oemdata, cth.oem_table_size ); 829 830 /** process it */ 831 832 free( oemdata ); 833 #else 834 printf( "\nyou need to modify the source to handle OEM data!\n\n" ); 835 #endif /* OEM_PROCESSING_READY */ 836 } 837 838 fflush( stdout ); 839 840 #if defined( RAW_DUMP ) 841 { 842 int ofd; 843 u_char dumpbuf[ 4096 ]; 844 845 ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR ); 846 seekEntry( paddr ); 847 readEntry( dumpbuf, 1024 ); 848 write( ofd, dumpbuf, 1024 ); 849 close( ofd ); 850 } 851 #endif /* RAW_DUMP */ 852 } 853 854 855 /* 856 * 857 */ 858 static int 859 readType( void ) 860 { 861 u_char type; 862 863 if ( read( pfd, &type, sizeof( u_char ) ) != sizeof( u_char ) ) 864 err( 1, "type read; pfd: %d", pfd ); 865 866 if ( lseek( pfd, -1, SEEK_CUR ) < 0 ) 867 err( 1, "type seek" ); 868 869 return (int)type; 870 } 871 872 873 /* 874 * 875 */ 876 static void 877 seekEntry( vm_offset_t addr ) 878 { 879 if ( lseek( pfd, (off_t)addr, SEEK_SET ) < 0 ) 880 err( 1, "%s seek", _PATH_MEM ); 881 } 882 883 884 /* 885 * 886 */ 887 static void 888 readEntry( void* entry, int size ) 889 { 890 if ( read( pfd, entry, size ) != size ) 891 err( 1, "readEntry" ); 892 } 893 894 895 static void 896 processorEntry( void ) 897 { 898 ProcEntry entry; 899 900 /* read it into local memory */ 901 readEntry( &entry, sizeof( entry ) ); 902 903 /* count it */ 904 ++ncpu; 905 906 printf( "\t\t%2d", entry.apicID ); 907 printf( "\t 0x%2x", entry.apicVersion ); 908 909 printf( "\t %s, %s", 910 (entry.cpuFlags & PROCENTRY_FLAG_BP) ? "BSP" : "AP", 911 (entry.cpuFlags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" ); 912 913 printf( "\t %d\t %d\t %d", 914 (entry.cpuSignature >> 8) & 0x0f, 915 (entry.cpuSignature >> 4) & 0x0f, 916 entry.cpuSignature & 0x0f ); 917 918 printf( "\t 0x%04x\n", entry.featureFlags ); 919 } 920 921 922 /* 923 * 924 */ 925 static int 926 lookupBusType( char* name ) 927 { 928 int x; 929 930 for ( x = 0; x < MAX_BUSTYPE; ++x ) 931 if ( strcmp( busTypeTable[ x ].name, name ) == 0 ) 932 return busTypeTable[ x ].type; 933 934 return UNKNOWN_BUSTYPE; 935 } 936 937 938 static void 939 busEntry( void ) 940 { 941 int x; 942 char name[ 8 ]; 943 char c; 944 BusEntry entry; 945 946 /* read it into local memory */ 947 readEntry( &entry, sizeof( entry ) ); 948 949 /* count it */ 950 ++nbus; 951 952 printf( "\t\t%2d", entry.busID ); 953 printf( "\t " ); pnstr( entry.busType, 6 ); printf( "\n" ); 954 955 for ( x = 0; x < 6; ++x ) { 956 if ( (c = entry.busType[ x ]) == ' ' ) 957 break; 958 name[ x ] = c; 959 } 960 name[ x ] = '\0'; 961 busses[ entry.busID ] = lookupBusType( name ); 962 } 963 964 965 static void 966 ioApicEntry( void ) 967 { 968 IOApicEntry entry; 969 970 /* read it into local memory */ 971 readEntry( &entry, sizeof( entry ) ); 972 973 /* count it */ 974 ++napic; 975 976 printf( "\t\t%2d", entry.apicID ); 977 printf( "\t 0x%02x", entry.apicVersion ); 978 printf( "\t %s", 979 (entry.apicFlags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" ); 980 printf( "\t\t 0x%x\n", entry.apicAddress ); 981 982 apics[ entry.apicID ] = entry.apicID; 983 } 984 985 986 char* intTypes[] = { 987 "INT", "NMI", "SMI", "ExtINT" 988 }; 989 990 char* polarityMode[] = { 991 "conforms", "active-hi", "reserved", "active-lo" 992 }; 993 char* triggerMode[] = { 994 "conforms", "edge", "reserved", "level" 995 }; 996 997 static void 998 intEntry( void ) 999 { 1000 IntEntry entry; 1001 1002 /* read it into local memory */ 1003 readEntry( &entry, sizeof( entry ) ); 1004 1005 /* count it */ 1006 if ( (int)entry.type == 3 ) 1007 ++nintr; 1008 1009 printf( "\t\t%s", intTypes[ (int)entry.intType ] ); 1010 1011 printf( "\t%9s", polarityMode[ (int)entry.intFlags & 0x03 ] ); 1012 printf( "%12s", triggerMode[ ((int)entry.intFlags >> 2) & 0x03 ] ); 1013 1014 printf( "\t %5d", (int)entry.srcBusID ); 1015 if ( busses[ (int)entry.srcBusID ] == PCI ) 1016 printf( "\t%2d:%c", 1017 ((int)entry.srcBusIRQ >> 2) & 0x1f, 1018 ((int)entry.srcBusIRQ & 0x03) + 'A' ); 1019 else 1020 printf( "\t %3d", (int)entry.srcBusIRQ ); 1021 printf( "\t %6d", (int)entry.dstApicID ); 1022 printf( "\t %3d\n", (int)entry.dstApicINT ); 1023 } 1024 1025 1026 static void 1027 sasEntry( void ) 1028 { 1029 SasEntry entry; 1030 1031 /* read it into local memory */ 1032 readEntry( &entry, sizeof( entry ) ); 1033 1034 printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); 1035 printf( " bus ID: %d", entry.busID ); 1036 printf( " address type: " ); 1037 switch ( entry.addressType ) { 1038 case 0: 1039 printf( "I/O address\n" ); 1040 break; 1041 case 1: 1042 printf( "memory address\n" ); 1043 break; 1044 case 2: 1045 printf( "prefetch address\n" ); 1046 break; 1047 default: 1048 printf( "UNKNOWN type\n" ); 1049 break; 1050 } 1051 1052 printf( " address base: 0x%qx\n", entry.addressBase ); 1053 printf( " address range: 0x%qx\n", entry.addressLength ); 1054 } 1055 1056 1057 static void 1058 bhdEntry( void ) 1059 { 1060 BhdEntry entry; 1061 1062 /* read it into local memory */ 1063 readEntry( &entry, sizeof( entry ) ); 1064 1065 printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); 1066 printf( " bus ID: %d", entry.busID ); 1067 printf( " bus info: 0x%02x", entry.busInfo ); 1068 printf( " parent bus ID: %d\n", entry.busParent ); 1069 } 1070 1071 1072 static void 1073 cbasmEntry( void ) 1074 { 1075 CbasmEntry entry; 1076 1077 /* read it into local memory */ 1078 readEntry( &entry, sizeof( entry ) ); 1079 1080 printf( "--\n%s\n", extendedtableEntryTypes[entry.type - 128].name ); 1081 printf( " bus ID: %d", entry.busID ); 1082 printf( " address modifier: %s\n", (entry.addressMod & 0x01) ? 1083 "subtract" : "add" ); 1084 printf( " predefined range: 0x%08x\n", entry.predefinedRange ); 1085 } 1086 1087 1088 /* 1089 * do a dmesg output 1090 */ 1091 static void 1092 doDmesg( void ) 1093 { 1094 puts( SEP_LINE ); 1095 1096 printf( "dmesg output:\n\n" ); 1097 fflush( stdout ); 1098 system( "dmesg" ); 1099 } 1100 1101 1102 /* 1103 * 1104 */ 1105 static void 1106 pnstr( char* s, int c ) 1107 { 1108 char string[ MAXPNSTR + 1 ]; 1109 1110 if ( c > MAXPNSTR ) 1111 c = MAXPNSTR; 1112 strncpy( string, s, c ); 1113 string[ c ] = '\0'; 1114 printf( "%s", string ); 1115 } 1116