mptable - prepare to raise WARNS
[dragonfly.git] / usr.sbin / mptable / mptable.c
1 /*
2  * Copyright (c) 1996, by Steve Passe
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. The name of the developer may NOT be used to endorse or promote products
11  *    derived from this software without specific prior written permission.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  *
25  * $FreeBSD: src/usr.sbin/mptable/mptable.c,v 1.12.2.3 2000/12/11 01:03:34 obrien Exp $
26  * $DragonFly: src/usr.sbin/mptable/mptable.c,v 1.4 2008/04/20 13:44:26 swildner Exp $
27  */
28
29 /*
30  * mptable.c
31  */
32
33 #define VMAJOR                  2
34 #define VMINOR                  0
35 #define VDELTA                  15
36
37 #define MP_SIG                  0x5f504d5f      /* _MP_ */
38 #define EXTENDED_PROCESSING_READY
39 #define OEM_PROCESSING_READY_NOT
40
41 #include <sys/types.h>
42 #include <err.h>
43 #include <fcntl.h>
44 #include <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 /*
389  * set PHYSICAL address of MP floating pointer structure
390  */
391 #define NEXT(X)         ((X) += sizeof(uint32_t))
392 static void
393 apic_probe( vm_offset_t* paddr, int* where )
394 {
395     /*
396      * c rewrite of apic_probe() by Jack F. Vogel
397      */
398
399     int         x;
400     uint16_t    segment;
401     vm_offset_t target;
402     uint32_t    buffer[ BIOS_SIZE / sizeof( uint32_t ) ];
403
404     if ( verbose )
405         printf( "\n" );
406
407     /* search Extended Bios Data Area, if present */
408     if ( verbose )
409         printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER );
410     seekEntry( (vm_offset_t)EBDA_POINTER );
411     readEntry( &segment, sizeof(segment) );
412     if ( segment ) {                /* search EBDA */
413         target = (vm_offset_t)segment << 4;
414         if ( verbose )
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;
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 );
430     readEntry( &segment, sizeof(segment) );
431     --segment;                                          /* less ONE_KBYTE */
432     target = segment * 1024;
433     if ( verbose )
434         printf( " searching CMOS 'top of mem' @ 0x%08lx (%dK)\n",
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 )
451             printf( " searching default 'top of mem' @ 0x%08lx (%ldK)\n",
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 )
497             printf( " groping memory @ 0x%08lx\n", target );
498
499         if ((x = findMpSig(target, GROPE_SIZE)) != -1) {
500             *where = 6;
501             *paddr = x;
502             return;
503         }
504
505         target = GROPE_AREA2;
506         if ( verbose )
507             printf( " groping memory @ 0x%08lx\n", target );
508
509         if ((x = findMpSig(target, GROPE_SIZE)) != -1) {
510             *where = 7;
511             *paddr = x;
512             return;
513         }
514     }
515
516     *where = 0;
517     *paddr = (vm_offset_t)0;
518 }
519
520
521 /*
522  * 
523  */
524 static void
525 MPFloatingPointer( 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     }
561     printf( "  physical address:\t\t0x%08lx\n", paddr );
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  */
593 static void
594 MPConfigDefault( 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  */
650 static void
651 MPConfigTableHeader( uint32_t pap )
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
814     if ( raw ) {
815         int             ofd;
816         u_char  dumpbuf[ 4096 ];
817
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     }
824 }
825
826
827 /*
828  * 
829  */
830 static int
831 readType( 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  */
848 static void
849 seekEntry( 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  */
859 static void
860 readEntry( void* entry, int size )
861 {
862     if ( read( pfd, entry, size ) != size )
863         err( 1, "readEntry" );
864 }
865
866
867 static void
868 processorEntry( 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  */
897 static int
898 lookupBusType( 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
910 static void
911 busEntry( 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
937 static void
938 ioApicEntry( 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
958 const char* intTypes[] = {
959     "INT", "NMI", "SMI", "ExtINT"
960 };
961
962 const char* polarityMode[] = {
963     "conforms", "active-hi", "reserved", "active-lo"
964 };
965 const char* triggerMode[] = {
966     "conforms", "edge", "reserved", "level"
967 };
968
969 static void
970 intEntry( 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
998 static void
999 sasEntry( 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
1024     printf( " address base: 0x%" PRIx64 "\n", entry.addressBase );
1025     printf( " address range: 0x%" PRIx64 "\n", entry.addressLength );
1026 }
1027
1028
1029 static void
1030 bhdEntry( 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
1044 static void
1045 cbasmEntry( 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  */
1063 static void
1064 doDmesg( 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  */
1077 static void
1078 pnstr( 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 }