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