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