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