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