]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/mptable/mptable.c
MFV r315875:
[FreeBSD/FreeBSD.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
26 /*
27  * mptable.c
28  */
29
30 #ifndef lint
31 static const char rcsid[] =
32   "$FreeBSD$";
33 #endif /* not lint */
34
35 /*
36  * this will cause the raw mp table to be dumped to /tmp/mpdump
37  *
38 #define RAW_DUMP
39  */
40
41 #define MP_SIG                  0x5f504d5f      /* _MP_ */
42 #define EXTENDED_PROCESSING_READY
43 #define OEM_PROCESSING_READY_NOT
44
45 #include <sys/param.h>
46 #include <sys/mman.h>
47 #include <x86/mptable.h>
48 #include <err.h>
49 #include <fcntl.h>
50 #include <paths.h>
51 #include <stdint.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 MAXPNSTR                132
81
82 typedef struct BUSTYPENAME {
83     u_char      type;
84     char        name[ 7 ];
85 } busTypeName;
86
87 static const busTypeName busTypeTable[] =
88 {
89     { CBUS,             "CBUS"   },
90     { CBUSII,           "CBUSII" },
91     { EISA,             "EISA"   },
92     { UNKNOWN_BUSTYPE,  "---"    },
93     { UNKNOWN_BUSTYPE,  "---"    },
94     { ISA,              "ISA"    },
95     { UNKNOWN_BUSTYPE,  "---"    },
96     { UNKNOWN_BUSTYPE,  "---"    },
97     { UNKNOWN_BUSTYPE,  "---"    },
98     { UNKNOWN_BUSTYPE,  "---"    },
99     { UNKNOWN_BUSTYPE,  "---"    },
100     { UNKNOWN_BUSTYPE,  "---"    },
101     { PCI,              "PCI"    },
102     { UNKNOWN_BUSTYPE,  "---"    },
103     { UNKNOWN_BUSTYPE,  "---"    },
104     { UNKNOWN_BUSTYPE,  "---"    },
105     { UNKNOWN_BUSTYPE,  "---"    },
106     { UNKNOWN_BUSTYPE,  "---"    },
107     { UNKNOWN_BUSTYPE,  "---"    }
108 };
109
110 static const char *whereStrings[] = {
111     "Extended BIOS Data Area",
112     "BIOS top of memory",
113     "Default top of memory",
114     "BIOS",
115     "Extended BIOS",
116     "GROPE AREA #1",
117     "GROPE AREA #2"
118 };
119
120 static void apic_probe( u_int32_t* paddr, int* where );
121
122 static void MPConfigDefault( int featureByte );
123
124 static void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp );
125 static void MPConfigTableHeader( u_int32_t pap );
126
127 static void seekEntry( u_int32_t addr );
128 static void readEntry( void* entry, int size );
129 static void *mapEntry( u_int32_t addr, int size );
130
131 static void processorEntry( proc_entry_ptr entry );
132 static void busEntry( bus_entry_ptr entry );
133 static void ioApicEntry( io_apic_entry_ptr entry );
134 static void intEntry( int_entry_ptr entry );
135
136 static void sasEntry( sas_entry_ptr entry );
137 static void bhdEntry( bhd_entry_ptr entry );
138 static void cbasmEntry( cbasm_entry_ptr entry );
139
140 static void doDmesg( void );
141 static void pnstr( char* s, int c );
142
143 /* global data */
144 static int      pfd;            /* physical /dev/mem fd */
145
146 static int      busses[256];
147 static int      apics[256];
148
149 static int      ncpu;
150 static int      nbus;
151 static int      napic;
152 static int      nintr;
153
154 static int      dmesg;
155 static int      grope;
156 static int      verbose;
157
158 static void
159 usage( void )
160 {
161     fprintf( stderr, "usage: mptable [-dmesg] [-verbose] [-grope] [-help]\n" );
162     exit( 0 );
163 }
164
165 /*
166  * 
167  */
168 int
169 main( int argc, char *argv[] )
170 {
171     u_int32_t   paddr;
172     int         where;
173     mpfps_t     mpfps;
174     int         defaultConfig;
175
176     int         ch;
177
178     /* announce ourselves */
179     puts( SEP_LINE2 );
180
181     printf( "MPTable\n" );
182
183     while ((ch = getopt(argc, argv, "d:g:h:v:")) != -1) {
184         switch(ch) {
185         case 'd':
186             if ( strcmp( optarg, "mesg") == 0 )
187                 dmesg = 1;
188             else
189                 dmesg = 0;
190             break;
191         case 'h':
192             if ( strcmp( optarg, "elp") == 0 )
193                 usage();
194             break;
195         case 'g':
196             if ( strcmp( optarg, "rope") == 0 )
197                 grope = 1;
198             break;
199         case 'v':
200             if ( strcmp( optarg, "erbose") == 0 )
201                 verbose = 1;
202             break;
203         default:
204             usage();
205         }
206         argc -= optind;
207         argv += optind;
208         optreset = 1;
209         optind = 0;
210     }
211
212     /* open physical memory for access to MP structures */
213     if ( (pfd = open( _PATH_MEM, O_RDONLY )) < 0 )
214         err( 1, "mem open" );
215
216     /* probe for MP structures */
217     apic_probe( &paddr, &where );
218     if ( where <= 0 ) {
219         fprintf( stderr, "\n MP FPS NOT found,\n" );
220         if (!grope)
221             fprintf( stderr, " suggest trying -grope option!!!\n\n" );
222         return 1;
223     }
224
225     if ( verbose )
226         printf( "\n MP FPS found in %s @ physical addr: 0x%08x\n",
227               whereStrings[ where - 1 ], paddr );
228
229     puts( SEP_LINE );
230
231     /* analyze the MP Floating Pointer Structure */
232     MPFloatingPointer( paddr, where, &mpfps );
233
234     puts( SEP_LINE );
235
236     /* check whether an MP config table exists */
237     if ( (defaultConfig = mpfps->config_type) )
238         MPConfigDefault( defaultConfig );
239     else
240         MPConfigTableHeader( mpfps->pap );
241
242     /* do a dmesg output */
243     if ( dmesg )
244         doDmesg();
245
246     puts( SEP_LINE2 );
247
248     return 0;
249 }
250
251
252 /*
253  * set PHYSICAL address of MP floating pointer structure
254  */
255 #define NEXT(X)         ((X) += 4)
256 static void
257 apic_probe( u_int32_t* paddr, int* where )
258 {
259     /*
260      * c rewrite of apic_probe() by Jack F. Vogel
261      */
262
263     int         x;
264     u_short     segment;
265     u_int32_t   target;
266     u_int       buffer[ BIOS_SIZE / sizeof( int ) ];
267
268     if ( verbose )
269         printf( "\n" );
270
271     /* search Extended Bios Data Area, if present */
272     if ( verbose )
273         printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER );
274     seekEntry( (u_int32_t)EBDA_POINTER );
275     readEntry( &segment, 2 );
276     if ( segment ) {                /* search EBDA */
277         target = (u_int32_t)segment << 4;
278         if ( verbose )
279             printf( "found, searching EBDA @ 0x%08x\n", target );
280         seekEntry( target );
281         readEntry( buffer, ONE_KBYTE );
282
283         for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) {
284             if ( buffer[ x ] == MP_SIG ) {
285                 *where = 1;
286                 *paddr = (x * sizeof( unsigned int )) + target;
287                 return;
288             }
289         }
290     }
291     else {
292         if ( verbose )
293             printf( "NOT found\n" );
294     }
295
296     /* read CMOS for real top of mem */
297     seekEntry( (u_int32_t)TOPOFMEM_POINTER );
298     readEntry( &segment, 2 );
299     --segment;                                          /* less ONE_KBYTE */
300     target = segment * 1024;
301     if ( verbose )
302         printf( " searching CMOS 'top of mem' @ 0x%08x (%dK)\n",
303                 target, segment );
304     seekEntry( target );
305     readEntry( buffer, ONE_KBYTE );
306
307     for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) {
308         if ( buffer[ x ] == MP_SIG ) {
309             *where = 2;
310             *paddr = (x * sizeof( unsigned int )) + target;
311             return;
312         }
313     }
314
315     /* we don't necessarily believe CMOS, check base of the last 1K of 640K */
316     if ( target != (DEFAULT_TOPOFMEM - 1024)) {
317         target = (DEFAULT_TOPOFMEM - 1024);
318         if ( verbose )
319             printf( " searching default 'top of mem' @ 0x%08x (%dK)\n",
320                     target, (target / 1024) );
321         seekEntry( target );
322         readEntry( buffer, ONE_KBYTE );
323
324         for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) {
325             if ( buffer[ x ] == MP_SIG ) {
326                 *where = 3;
327                 *paddr = (x * sizeof( unsigned int )) + target;
328                 return;
329             }
330         }
331     }
332
333     /* search the BIOS */
334     if ( verbose )
335         printf( " searching BIOS @ 0x%08x\n", BIOS_BASE );
336     seekEntry( BIOS_BASE );
337     readEntry( buffer, BIOS_SIZE );
338
339     for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) {
340         if ( buffer[ x ] == MP_SIG ) {
341             *where = 4;
342             *paddr = (x * sizeof( unsigned int )) + BIOS_BASE;
343             return;
344         }
345     }
346
347     /* search the extended BIOS */
348     if ( verbose )
349         printf( " searching extended BIOS @ 0x%08x\n", BIOS_BASE2 );
350     seekEntry( BIOS_BASE2 );
351     readEntry( buffer, BIOS_SIZE );
352
353     for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) {
354         if ( buffer[ x ] == MP_SIG ) {
355             *where = 5;
356             *paddr = (x * sizeof( unsigned int )) + BIOS_BASE2;
357             return;
358         }
359     }
360
361     if ( grope ) {
362         /* search additional memory */
363         target = GROPE_AREA1;
364         if ( verbose )
365             printf( " groping memory @ 0x%08x\n", target );
366         seekEntry( target );
367         readEntry( buffer, GROPE_SIZE );
368
369         for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) {
370             if ( buffer[ x ] == MP_SIG ) {
371                 *where = 6;
372                 *paddr = (x * sizeof( unsigned int )) + GROPE_AREA1;
373                 return;
374             }
375         }
376
377         target = GROPE_AREA2;
378         if ( verbose )
379             printf( " groping memory @ 0x%08x\n", target );
380         seekEntry( target );
381         readEntry( buffer, GROPE_SIZE );
382
383         for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) {
384             if ( buffer[ x ] == MP_SIG ) {
385                 *where = 7;
386                 *paddr = (x * sizeof( unsigned int )) + GROPE_AREA2;
387                 return;
388             }
389         }
390     }
391
392     *where = 0;
393     *paddr = (u_int32_t)0;
394 }
395
396
397 /*
398  * 
399  */
400 static void
401 MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp )
402 {
403     mpfps_t mpfps;
404         
405     /* map in mpfps structure*/
406     *mpfpsp = mpfps = mapEntry( paddr, sizeof( *mpfps ) );
407
408     /* show its contents */
409     printf( "MP Floating Pointer Structure:\n\n" );
410
411     printf( "  location:\t\t\t" );
412     switch ( where )
413     {
414     case 1:
415         printf( "EBDA\n" );
416         break;
417     case 2:
418         printf( "BIOS base memory\n" );
419         break;
420     case 3:
421         printf( "DEFAULT base memory (639K)\n" );
422         break;
423     case 4:
424         printf( "BIOS\n" );
425         break;
426     case 5:
427         printf( "Extended BIOS\n" );
428         break;
429
430     case 0:
431         printf( "NOT found!\n" );
432         exit( 1 );
433     default:
434         printf( "BOGUS!\n" );
435         exit( 1 );
436     }
437     printf( "  physical address:\t\t0x%08x\n", paddr );
438
439     printf( "  signature:\t\t\t'" );
440     pnstr( mpfps->signature, 4 );
441     printf( "'\n" );
442
443     printf( "  length:\t\t\t%d bytes\n", mpfps->length * 16 );
444     printf( "  version:\t\t\t1.%1d\n", mpfps->spec_rev );
445     printf( "  checksum:\t\t\t0x%02x\n", mpfps->checksum );
446
447     /* bits 0:6 are RESERVED */
448     if ( mpfps->mpfb2 & 0x7f ) {
449         printf( " warning, MP feature byte 2: 0x%02x\n", mpfps->mpfb2 );
450     }
451
452     /* bit 7 is IMCRP */
453     printf( "  mode:\t\t\t\t%s\n", (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) ?
454             "PIC" : "Virtual Wire" );
455
456     /* MP feature bytes 3-5 are expected to be ZERO */
457     if ( mpfps->mpfb3 )
458         printf( " warning, MP feature byte 3 NONZERO!\n" );
459     if ( mpfps->mpfb4 )
460         printf( " warning, MP feature byte 4 NONZERO!\n" );
461     if ( mpfps->mpfb5 )
462         printf( " warning, MP feature byte 5 NONZERO!\n" );
463 }
464
465
466 /*
467  * 
468  */
469 static void
470 MPConfigDefault( int featureByte )
471 {
472     printf( "  MP default config type: %d\n\n", featureByte );
473     switch ( featureByte ) {
474     case 1:
475         printf( "   bus: ISA, APIC: 82489DX\n" );
476         break;
477     case 2:
478         printf( "   bus: EISA, APIC: 82489DX\n" );
479         break;
480     case 3:
481         printf( "   bus: EISA, APIC: 82489DX\n" );
482         break;
483     case 4:
484         printf( "   bus: MCA, APIC: 82489DX\n" );
485         break;
486     case 5:
487         printf( "   bus: ISA+PCI, APIC: Integrated\n" );
488         break;
489     case 6:
490         printf( "   bus: EISA+PCI, APIC: Integrated\n" );
491         break;
492     case 7:
493         printf( "   bus: MCA+PCI, APIC: Integrated\n" );
494         break;
495     default:
496         printf( "   future type\n" );
497         break;
498     }
499
500     switch ( featureByte ) {
501     case 1:
502     case 2:
503     case 3:
504     case 4:
505         nbus = 1;
506         break;
507     case 5:
508     case 6:
509     case 7:
510         nbus = 2;
511         break;
512     default:
513         printf( "   future type\n" );
514         break;
515     }
516
517     ncpu = 2;
518     napic = 1;
519     nintr = 16;
520 }
521
522
523 /*
524  * 
525  */
526 static void
527 MPConfigTableHeader( u_int32_t pap )
528 {
529     mpcth_t     cth;
530     int         x;
531     int         totalSize;
532     int         c;
533     int         oldtype, entrytype;
534     u_int8_t    *entry;
535
536     if ( pap == 0 ) {
537         printf( "MP Configuration Table Header MISSING!\n" );
538         exit( 1 );
539     }
540
541     /* map in cth structure */
542     cth = mapEntry( pap, sizeof( *cth ) );
543
544     printf( "MP Config Table Header:\n\n" );
545
546     printf( "  physical address:\t\t0x%08x\n", pap );
547
548     printf( "  signature:\t\t\t'" );
549     pnstr( cth->signature, 4 );
550     printf( "'\n" );
551
552     printf( "  base table length:\t\t%d\n", cth->base_table_length );
553
554     printf( "  version:\t\t\t1.%1d\n", cth->spec_rev );
555     printf( "  checksum:\t\t\t0x%02x\n", cth->checksum );
556
557     printf( "  OEM ID:\t\t\t'" );
558     pnstr( cth->oem_id, 8 );
559     printf( "'\n" );
560
561     printf( "  Product ID:\t\t\t'" );
562     pnstr( cth->product_id, 12 );
563     printf( "'\n" );
564
565     printf( "  OEM table pointer:\t\t0x%08x\n", cth->oem_table_pointer );
566     printf( "  OEM table size:\t\t%d\n", cth->oem_table_size );
567
568     printf( "  entry count:\t\t\t%d\n", cth->entry_count );
569
570     printf( "  local APIC address:\t\t0x%08x\n", cth->apic_address );
571
572     printf( "  extended table length:\t%d\n", cth->extended_table_length );
573     printf( "  extended table checksum:\t%d\n", cth->extended_table_checksum );
574
575     totalSize = cth->base_table_length - sizeof( struct MPCTH );
576
577     puts( SEP_LINE );
578
579     printf( "MP Config Base Table Entries:\n\n" );
580
581     /* initialize tables */
582     for (x = 0; x < (int)nitems(busses); x++)
583         busses[x] = 0xff;
584
585     for (x = 0; x < (int)nitems(apics); x++)
586         apics[x] = 0xff;
587
588     ncpu = 0;
589     nbus = 0;
590     napic = 0;
591     nintr = 0;
592
593     oldtype = -1;
594     entry = mapEntry(pap + sizeof(*cth), cth->base_table_length);
595     for (c = cth->entry_count; c; c--) {
596         entrytype = *entry;
597         if (entrytype != oldtype)
598             printf("--\n");
599         if (entrytype < oldtype)
600             printf("MPTABLE OUT OF ORDER!\n");
601         switch (entrytype) {
602         case MPCT_ENTRY_PROCESSOR:
603             if (oldtype != MPCT_ENTRY_PROCESSOR)
604                 printf( "Processors:\tAPIC ID\tVersion\tState"
605                         "\t\tFamily\tModel\tStep\tFlags\n" );
606             processorEntry((proc_entry_ptr)entry);
607             entry += sizeof(struct PROCENTRY);
608             break;
609
610         case MPCT_ENTRY_BUS:
611             if (oldtype != MPCT_ENTRY_BUS)
612                 printf( "Bus:\t\tBus ID\tType\n" );
613             busEntry((bus_entry_ptr)entry);
614             entry += sizeof(struct BUSENTRY);
615             break;
616
617         case MPCT_ENTRY_IOAPIC:
618             if (oldtype != MPCT_ENTRY_IOAPIC)
619                 printf( "I/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" );
620             ioApicEntry((io_apic_entry_ptr)entry);
621             entry += sizeof(struct IOAPICENTRY);
622             break;
623
624         case MPCT_ENTRY_INT:
625             if (oldtype != MPCT_ENTRY_INT)
626                 printf( "I/O Ints:\tType\tPolarity    Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" );
627             intEntry((int_entry_ptr)entry);
628             entry += sizeof(struct INTENTRY);
629             break;
630
631         case MPCT_ENTRY_LOCAL_INT:
632             if (oldtype != MPCT_ENTRY_LOCAL_INT)
633                 printf( "Local Ints:\tType\tPolarity    Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" );
634             intEntry((int_entry_ptr)entry);
635             entry += sizeof(struct INTENTRY);
636             break;
637
638         default:
639             printf("MPTABLE HOSED! record type = %d\n", entrytype);
640             exit(1);
641         }
642         oldtype = entrytype;
643     }
644
645
646 #if defined( EXTENDED_PROCESSING_READY )
647     /* process any extended data */
648     if ( cth->extended_table_length ) {
649         ext_entry_ptr ext_entry, end;
650
651         puts( SEP_LINE );
652
653         printf( "MP Config Extended Table Entries:\n\n" );
654
655         ext_entry = mapEntry(pap + cth->base_table_length,
656             cth->extended_table_length);
657         end = (ext_entry_ptr)((char *)ext_entry + cth->extended_table_length);
658         while (ext_entry < end) {
659             switch (ext_entry->type) {
660             case MPCT_EXTENTRY_SAS:
661                 sasEntry((sas_entry_ptr)ext_entry);
662                 break;
663             case MPCT_EXTENTRY_BHD:
664                 bhdEntry((bhd_entry_ptr)ext_entry);
665                 break;
666             case MPCT_EXTENTRY_CBASM:
667                 cbasmEntry((cbasm_entry_ptr)ext_entry);
668                 break;
669             default:
670                 printf( "Extended Table HOSED!\n" );
671                 exit( 1 );
672             }
673
674             ext_entry = (ext_entry_ptr)((char *)ext_entry + ext_entry->length);
675         }
676     }
677 #endif  /* EXTENDED_PROCESSING_READY */
678
679     /* process any OEM data */
680     if ( cth->oem_table_pointer && (cth->oem_table_size > 0) ) {
681 #if defined( OEM_PROCESSING_READY )
682 # error your on your own here!
683         /* map in oem table structure */
684         oemdata = mapEntry( cth->oem_table_pointer, cth->oem_table_size);
685
686         /** process it */
687 #else
688         printf( "\nyou need to modify the source to handle OEM data!\n\n" );
689 #endif  /* OEM_PROCESSING_READY */
690     }
691
692     fflush( stdout );
693
694 #if defined( RAW_DUMP )
695 {
696     int         ofd;
697     void        *dumpbuf;
698
699     ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR, 0666 );
700     
701     dumpbuf = mapEntry( paddr, 1024 );
702     write( ofd, dumpbuf, 1024 );
703     close( ofd );
704 }
705 #endif /* RAW_DUMP */
706 }
707
708
709 /*
710  * 
711  */
712 static void
713 seekEntry( u_int32_t addr )
714 {
715     if ( lseek( pfd, (off_t)addr, SEEK_SET ) < 0 )
716         err( 1, "%s seek", _PATH_MEM );
717 }
718
719
720 /*
721  * 
722  */
723 static void
724 readEntry( void* entry, int size )
725 {
726     if ( read( pfd, entry, size ) != size )
727         err( 1, "readEntry" );
728 }
729
730 static void *
731 mapEntry( u_int32_t addr, int size )
732 {
733     void        *p;
734
735     p = mmap( NULL, size, PROT_READ, MAP_SHARED, pfd, addr );
736     if (p == MAP_FAILED)
737         err( 1, "mapEntry" );
738     return (p);
739 }
740
741 static void
742 processorEntry( proc_entry_ptr entry )
743 {
744
745     /* count it */
746     ++ncpu;
747
748     printf( "\t\t%2d", entry->apic_id );
749     printf( "\t 0x%2x", entry->apic_version );
750
751     printf( "\t %s, %s",
752             (entry->cpu_flags & PROCENTRY_FLAG_BP) ? "BSP" : "AP",
753             (entry->cpu_flags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" );
754
755     printf( "\t %d\t %d\t %d",
756             (entry->cpu_signature >> 8) & 0x0f,
757             (entry->cpu_signature >> 4) & 0x0f,
758             entry->cpu_signature & 0x0f );
759
760     printf( "\t 0x%04x\n", entry->feature_flags );
761 }
762
763
764 /*
765  * 
766  */
767 static int
768 lookupBusType( char* name )
769 {
770     int x;
771
772     for ( x = 0; x < MAX_BUSTYPE; ++x )
773         if ( strcmp( busTypeTable[ x ].name, name ) == 0 )
774             return busTypeTable[ x ].type;
775
776     return UNKNOWN_BUSTYPE;
777 }
778
779
780 static void
781 busEntry( bus_entry_ptr entry )
782 {
783     int         x;
784     char        name[ 8 ];
785     char        c;
786
787     /* count it */
788     ++nbus;
789
790     printf( "\t\t%2d", entry->bus_id );
791     printf( "\t " ); pnstr( entry->bus_type, 6 ); printf( "\n" );
792
793     for ( x = 0; x < 6; ++x ) {
794         if ( (c = entry->bus_type[ x ]) == ' ' )
795             break;
796         name[ x ] = c;
797     }
798     name[ x ] = '\0';
799     busses[ entry->bus_id ] = lookupBusType( name );
800 }
801
802
803 static void
804 ioApicEntry( io_apic_entry_ptr entry )
805 {
806
807     /* count it */
808     ++napic;
809
810     printf( "\t\t%2d", entry->apic_id );
811     printf( "\t 0x%02x", entry->apic_version );
812     printf( "\t %s",
813             (entry->apic_flags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" );
814     printf( "\t\t 0x%x\n", entry->apic_address );
815
816     apics[ entry->apic_id ] = entry->apic_id;
817 }
818
819
820 static const char *intTypes[] = {
821     "INT", "NMI", "SMI", "ExtINT"
822 };
823
824 static const char *polarityMode[] = {
825     "conforms", "active-hi", "reserved", "active-lo"
826 };
827 static const char *triggerMode[] = {
828     "conforms", "edge", "reserved", "level"
829 };
830
831 static void
832 intEntry( int_entry_ptr entry )
833 {
834
835     /* count it */
836     if ( entry->type == MPCT_ENTRY_INT )
837         ++nintr;
838
839     printf( "\t\t%s", intTypes[ entry->int_type ] );
840
841     printf( "\t%9s", polarityMode[ entry->int_flags & INTENTRY_FLAGS_POLARITY ] );
842     printf( "%12s", triggerMode[ (entry->int_flags & INTENTRY_FLAGS_TRIGGER) >> 2 ] );
843
844     printf( "\t %5d", entry->src_bus_id );
845     if ( busses[ entry->src_bus_id ] == PCI )
846         printf( "\t%2d:%c", 
847                 (entry->src_bus_irq >> 2) & 0x1f,
848                 (entry->src_bus_irq & 0x03) + 'A' );
849     else
850         printf( "\t %3d", entry->src_bus_irq );
851     printf( "\t %6d", entry->dst_apic_id );
852     printf( "\t %3d\n", entry->dst_apic_int );
853 }
854
855
856 static void
857 sasEntry( sas_entry_ptr entry )
858 {
859
860     printf( "--\nSystem Address Space\n");
861     printf( " bus ID: %d", entry->bus_id );
862     printf( " address type: " );
863     switch ( entry->address_type ) {
864     case SASENTRY_TYPE_IO:
865         printf( "I/O address\n" );
866         break;
867     case SASENTRY_TYPE_MEMORY:
868         printf( "memory address\n" );
869         break;
870     case SASENTRY_TYPE_PREFETCH:
871         printf( "prefetch address\n" );
872         break;
873     default:
874         printf( "UNKNOWN type\n" );
875         break;
876     }
877
878     printf( " address base: 0x%jx\n", (uintmax_t)entry->address_base );
879     printf( " address range: 0x%jx\n", (uintmax_t)entry->address_length );
880 }
881
882
883 static void
884 bhdEntry( bhd_entry_ptr entry )
885 {
886
887     printf( "--\nBus Hierarchy\n" );
888     printf( " bus ID: %d", entry->bus_id );
889     printf( " bus info: 0x%02x", entry->bus_info );
890     printf( " parent bus ID: %d\n", entry->parent_bus );
891 }
892
893
894 static void
895 cbasmEntry( cbasm_entry_ptr entry )
896 {
897
898     printf( "--\nCompatibility Bus Address\n" );
899     printf( " bus ID: %d", entry->bus_id );
900     printf( " address modifier: %s\n",
901         (entry->address_mod & CBASMENTRY_ADDRESS_MOD_SUBTRACT) ?
902         "subtract" : "add" );
903     printf( " predefined range: 0x%08x\n", entry->predefined_range );
904 }
905
906
907 /*
908  * do a dmesg output
909  */
910 static void
911 doDmesg( void )
912 {
913     puts( SEP_LINE );
914
915     printf( "dmesg output:\n\n" );
916     fflush( stdout );
917     system( "dmesg" );
918 }
919
920
921 /*
922  * 
923  */
924 static void
925 pnstr( char* s, int c )
926 {
927     char string[ MAXPNSTR + 1 ];
928
929     if ( c > MAXPNSTR )
930         c = MAXPNSTR;
931     strncpy( string, s, c );
932     string[ c ] = '\0';
933     printf( "%s", string );
934 }