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