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