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