1330449Seadler/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 425265Sfsmp * Copyright (c) 1996, by Steve Passe 525265Sfsmp * All rights reserved. 625265Sfsmp * 725265Sfsmp * Redistribution and use in source and binary forms, with or without 825265Sfsmp * modification, are permitted provided that the following conditions 925265Sfsmp * are met: 1025265Sfsmp * 1. Redistributions of source code must retain the above copyright 1125265Sfsmp * notice, this list of conditions and the following disclaimer. 1225265Sfsmp * 2. The name of the developer may NOT be used to endorse or promote products 1325265Sfsmp * derived from this software without specific prior written permission. 1425265Sfsmp * 1525265Sfsmp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1625265Sfsmp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1725265Sfsmp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1825265Sfsmp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1925265Sfsmp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2025265Sfsmp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2125265Sfsmp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2225265Sfsmp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2325265Sfsmp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2425265Sfsmp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2525265Sfsmp * SUCH DAMAGE. 2625265Sfsmp */ 2725265Sfsmp 2825265Sfsmp/* 2925265Sfsmp * mptable.c 3025265Sfsmp */ 3125265Sfsmp 3229850Scharnier#ifndef lint 3329850Scharnierstatic const char rcsid[] = 3450479Speter "$FreeBSD: stable/11/usr.sbin/mptable/mptable.c 330449 2018-03-05 07:26:05Z eadler $"; 3529850Scharnier#endif /* not lint */ 3629850Scharnier 3725265Sfsmp/* 3825265Sfsmp * this will cause the raw mp table to be dumped to /tmp/mpdump 3925265Sfsmp * 4025265Sfsmp#define RAW_DUMP 4125265Sfsmp */ 4225265Sfsmp 4325265Sfsmp#define MP_SIG 0x5f504d5f /* _MP_ */ 4425265Sfsmp#define EXTENDED_PROCESSING_READY 4525265Sfsmp#define OEM_PROCESSING_READY_NOT 4625265Sfsmp 47244530Sneel#include <sys/param.h> 48259229Sjhb#include <sys/mman.h> 49259229Sjhb#include <x86/mptable.h> 5029850Scharnier#include <err.h> 5129850Scharnier#include <fcntl.h> 5269793Sobrien#include <paths.h> 53259229Sjhb#include <stdint.h> 5425265Sfsmp#include <stdio.h> 5529850Scharnier#include <stdlib.h> 5629850Scharnier#include <string.h> 5725265Sfsmp#include <unistd.h> 5825265Sfsmp 5925265Sfsmp#define SEP_LINE \ 6025265Sfsmp"\n-------------------------------------------------------------------------------\n" 6125265Sfsmp 6225265Sfsmp#define SEP_LINE2 \ 6325265Sfsmp"\n===============================================================================\n" 6425265Sfsmp 6525265Sfsmp/* EBDA is @ 40:0e in real-mode terms */ 6625265Sfsmp#define EBDA_POINTER 0x040e /* location of EBDA pointer */ 6725265Sfsmp 6825265Sfsmp/* CMOS 'top of mem' is @ 40:13 in real-mode terms */ 6925265Sfsmp#define TOPOFMEM_POINTER 0x0413 /* BIOS: base memory size */ 7025265Sfsmp 7125265Sfsmp#define DEFAULT_TOPOFMEM 0xa0000 7225265Sfsmp 7325265Sfsmp#define BIOS_BASE 0xf0000 7425265Sfsmp#define BIOS_BASE2 0xe0000 7525265Sfsmp#define BIOS_SIZE 0x10000 7625265Sfsmp#define ONE_KBYTE 1024 7725265Sfsmp 7825265Sfsmp#define GROPE_AREA1 0x80000 7925265Sfsmp#define GROPE_AREA2 0x90000 8025265Sfsmp#define GROPE_SIZE 0x10000 8125265Sfsmp 8225265Sfsmp#define MAXPNSTR 132 8325265Sfsmp 8425265Sfsmptypedef struct BUSTYPENAME { 8525265Sfsmp u_char type; 8625265Sfsmp char name[ 7 ]; 8725265Sfsmp} busTypeName; 8825265Sfsmp 89227224Sedstatic const busTypeName busTypeTable[] = 9025265Sfsmp{ 9125265Sfsmp { CBUS, "CBUS" }, 9225265Sfsmp { CBUSII, "CBUSII" }, 9325265Sfsmp { EISA, "EISA" }, 9425265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 9525265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 9625265Sfsmp { ISA, "ISA" }, 9725265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 9825265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 9925265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10025265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10125265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10225265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10325265Sfsmp { PCI, "PCI" }, 10425265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10525265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10625265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10725265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10825265Sfsmp { UNKNOWN_BUSTYPE, "---" }, 10925265Sfsmp { UNKNOWN_BUSTYPE, "---" } 11025265Sfsmp}; 11125265Sfsmp 112227224Sedstatic const char *whereStrings[] = { 11325265Sfsmp "Extended BIOS Data Area", 11425265Sfsmp "BIOS top of memory", 11525265Sfsmp "Default top of memory", 11625265Sfsmp "BIOS", 11725265Sfsmp "Extended BIOS", 11825265Sfsmp "GROPE AREA #1", 11925265Sfsmp "GROPE AREA #2" 12025265Sfsmp}; 12125265Sfsmp 122120590Speterstatic void apic_probe( u_int32_t* paddr, int* where ); 12325265Sfsmp 12425265Sfsmpstatic void MPConfigDefault( int featureByte ); 12525265Sfsmp 126259229Sjhbstatic void MPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp ); 127120590Speterstatic void MPConfigTableHeader( u_int32_t pap ); 12825265Sfsmp 129120590Speterstatic void seekEntry( u_int32_t addr ); 13025265Sfsmpstatic void readEntry( void* entry, int size ); 131259229Sjhbstatic void *mapEntry( u_int32_t addr, int size ); 13225265Sfsmp 133259229Sjhbstatic void processorEntry( proc_entry_ptr entry ); 134259229Sjhbstatic void busEntry( bus_entry_ptr entry ); 135259229Sjhbstatic void ioApicEntry( io_apic_entry_ptr entry ); 136259229Sjhbstatic void intEntry( int_entry_ptr entry ); 13725265Sfsmp 138259229Sjhbstatic void sasEntry( sas_entry_ptr entry ); 139259229Sjhbstatic void bhdEntry( bhd_entry_ptr entry ); 140259229Sjhbstatic void cbasmEntry( cbasm_entry_ptr entry ); 14125265Sfsmp 14225265Sfsmpstatic void doDmesg( void ); 14325265Sfsmpstatic void pnstr( char* s, int c ); 14425265Sfsmp 14525265Sfsmp/* global data */ 146227224Sedstatic int pfd; /* physical /dev/mem fd */ 14725265Sfsmp 148244526Sneelstatic int busses[256]; 149244526Sneelstatic int apics[256]; 15025265Sfsmp 151227224Sedstatic int ncpu; 152227224Sedstatic int nbus; 153227224Sedstatic int napic; 154227224Sedstatic int nintr; 15525265Sfsmp 156227224Sedstatic int dmesg; 157227224Sedstatic int grope; 158227224Sedstatic int verbose; 15925265Sfsmp 16025265Sfsmpstatic void 16125265Sfsmpusage( void ) 16225265Sfsmp{ 16329850Scharnier fprintf( stderr, "usage: mptable [-dmesg] [-verbose] [-grope] [-help]\n" ); 16425265Sfsmp exit( 0 ); 16525265Sfsmp} 16625265Sfsmp 16725265Sfsmp/* 16825265Sfsmp * 16925265Sfsmp */ 17025265Sfsmpint 17125265Sfsmpmain( int argc, char *argv[] ) 17225265Sfsmp{ 173120590Speter u_int32_t paddr; 17425265Sfsmp int where; 17525265Sfsmp mpfps_t mpfps; 17625265Sfsmp int defaultConfig; 17725265Sfsmp 17825265Sfsmp int ch; 17925265Sfsmp 18025265Sfsmp /* announce ourselves */ 18125265Sfsmp puts( SEP_LINE2 ); 18225265Sfsmp 183141385Sobrien printf( "MPTable\n" ); 18425265Sfsmp 18547442Simp while ((ch = getopt(argc, argv, "d:g:h:v:")) != -1) { 18625265Sfsmp switch(ch) { 18725265Sfsmp case 'd': 18825265Sfsmp if ( strcmp( optarg, "mesg") == 0 ) 18925265Sfsmp dmesg = 1; 19025265Sfsmp else 19125265Sfsmp dmesg = 0; 19225265Sfsmp break; 19325265Sfsmp case 'h': 19425265Sfsmp if ( strcmp( optarg, "elp") == 0 ) 19525265Sfsmp usage(); 19625265Sfsmp break; 19725265Sfsmp case 'g': 19825326Sfsmp if ( strcmp( optarg, "rope") == 0 ) 19925265Sfsmp grope = 1; 20025265Sfsmp break; 20125265Sfsmp case 'v': 20225265Sfsmp if ( strcmp( optarg, "erbose") == 0 ) 20325265Sfsmp verbose = 1; 20425265Sfsmp break; 20525265Sfsmp default: 20625265Sfsmp usage(); 20725265Sfsmp } 20825265Sfsmp argc -= optind; 20925265Sfsmp argv += optind; 21025265Sfsmp optreset = 1; 21125265Sfsmp optind = 0; 21225265Sfsmp } 21325265Sfsmp 21425265Sfsmp /* open physical memory for access to MP structures */ 21569793Sobrien if ( (pfd = open( _PATH_MEM, O_RDONLY )) < 0 ) 21629850Scharnier err( 1, "mem open" ); 21725265Sfsmp 21825265Sfsmp /* probe for MP structures */ 21925265Sfsmp apic_probe( &paddr, &where ); 22025265Sfsmp if ( where <= 0 ) { 22125265Sfsmp fprintf( stderr, "\n MP FPS NOT found,\n" ); 222289767Sbapt if (!grope) 223289767Sbapt fprintf( stderr, " suggest trying -grope option!!!\n\n" ); 22425265Sfsmp return 1; 22525265Sfsmp } 22625265Sfsmp 22725265Sfsmp if ( verbose ) 22825265Sfsmp printf( "\n MP FPS found in %s @ physical addr: 0x%08x\n", 22925265Sfsmp whereStrings[ where - 1 ], paddr ); 23025265Sfsmp 23125265Sfsmp puts( SEP_LINE ); 23225265Sfsmp 23325265Sfsmp /* analyze the MP Floating Pointer Structure */ 23425265Sfsmp MPFloatingPointer( paddr, where, &mpfps ); 23525265Sfsmp 23625265Sfsmp puts( SEP_LINE ); 23725265Sfsmp 23825265Sfsmp /* check whether an MP config table exists */ 239259229Sjhb if ( (defaultConfig = mpfps->config_type) ) 24025265Sfsmp MPConfigDefault( defaultConfig ); 24125265Sfsmp else 242259229Sjhb MPConfigTableHeader( mpfps->pap ); 24325265Sfsmp 24425265Sfsmp /* do a dmesg output */ 24525265Sfsmp if ( dmesg ) 24625265Sfsmp doDmesg(); 24725265Sfsmp 24825265Sfsmp puts( SEP_LINE2 ); 24925265Sfsmp 25025265Sfsmp return 0; 25125265Sfsmp} 25225265Sfsmp 25325265Sfsmp 25425265Sfsmp/* 25525265Sfsmp * set PHYSICAL address of MP floating pointer structure 25625265Sfsmp */ 25725265Sfsmp#define NEXT(X) ((X) += 4) 25825265Sfsmpstatic void 259120590Speterapic_probe( u_int32_t* paddr, int* where ) 26025265Sfsmp{ 26125265Sfsmp /* 26225265Sfsmp * c rewrite of apic_probe() by Jack F. Vogel 26325265Sfsmp */ 26425265Sfsmp 26525265Sfsmp int x; 26625265Sfsmp u_short segment; 267120590Speter u_int32_t target; 26825265Sfsmp u_int buffer[ BIOS_SIZE / sizeof( int ) ]; 26925265Sfsmp 27025265Sfsmp if ( verbose ) 27125265Sfsmp printf( "\n" ); 27225265Sfsmp 27325265Sfsmp /* search Extended Bios Data Area, if present */ 27425265Sfsmp if ( verbose ) 27525265Sfsmp printf( " looking for EBDA pointer @ 0x%04x, ", EBDA_POINTER ); 276120590Speter seekEntry( (u_int32_t)EBDA_POINTER ); 27725265Sfsmp readEntry( &segment, 2 ); 27825265Sfsmp if ( segment ) { /* search EBDA */ 279120590Speter target = (u_int32_t)segment << 4; 28025265Sfsmp if ( verbose ) 28125265Sfsmp printf( "found, searching EBDA @ 0x%08x\n", target ); 28225265Sfsmp seekEntry( target ); 28325265Sfsmp readEntry( buffer, ONE_KBYTE ); 28425265Sfsmp 285120590Speter for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 28625265Sfsmp if ( buffer[ x ] == MP_SIG ) { 28725265Sfsmp *where = 1; 28825265Sfsmp *paddr = (x * sizeof( unsigned int )) + target; 28925265Sfsmp return; 29025265Sfsmp } 29125265Sfsmp } 29225265Sfsmp } 29325265Sfsmp else { 29425265Sfsmp if ( verbose ) 29525265Sfsmp printf( "NOT found\n" ); 29625265Sfsmp } 29725265Sfsmp 29825265Sfsmp /* read CMOS for real top of mem */ 299120590Speter seekEntry( (u_int32_t)TOPOFMEM_POINTER ); 30025265Sfsmp readEntry( &segment, 2 ); 30125265Sfsmp --segment; /* less ONE_KBYTE */ 30225265Sfsmp target = segment * 1024; 30325265Sfsmp if ( verbose ) 30425265Sfsmp printf( " searching CMOS 'top of mem' @ 0x%08x (%dK)\n", 30525265Sfsmp target, segment ); 30625265Sfsmp seekEntry( target ); 30725265Sfsmp readEntry( buffer, ONE_KBYTE ); 30825265Sfsmp 309120590Speter for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 31025265Sfsmp if ( buffer[ x ] == MP_SIG ) { 31125265Sfsmp *where = 2; 31225265Sfsmp *paddr = (x * sizeof( unsigned int )) + target; 31325265Sfsmp return; 31425265Sfsmp } 31525265Sfsmp } 31625265Sfsmp 31725265Sfsmp /* we don't necessarily believe CMOS, check base of the last 1K of 640K */ 31825265Sfsmp if ( target != (DEFAULT_TOPOFMEM - 1024)) { 31925265Sfsmp target = (DEFAULT_TOPOFMEM - 1024); 32025265Sfsmp if ( verbose ) 32125265Sfsmp printf( " searching default 'top of mem' @ 0x%08x (%dK)\n", 32225265Sfsmp target, (target / 1024) ); 32325265Sfsmp seekEntry( target ); 32425265Sfsmp readEntry( buffer, ONE_KBYTE ); 32525265Sfsmp 326120590Speter for ( x = 0; x < ONE_KBYTE / (int)sizeof ( unsigned int ); NEXT(x) ) { 32725265Sfsmp if ( buffer[ x ] == MP_SIG ) { 32825265Sfsmp *where = 3; 32925265Sfsmp *paddr = (x * sizeof( unsigned int )) + target; 33025265Sfsmp return; 33125265Sfsmp } 33225265Sfsmp } 33325265Sfsmp } 33425265Sfsmp 33525265Sfsmp /* search the BIOS */ 33625265Sfsmp if ( verbose ) 33725265Sfsmp printf( " searching BIOS @ 0x%08x\n", BIOS_BASE ); 33825265Sfsmp seekEntry( BIOS_BASE ); 33925265Sfsmp readEntry( buffer, BIOS_SIZE ); 34025265Sfsmp 341120590Speter for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 34225265Sfsmp if ( buffer[ x ] == MP_SIG ) { 34325265Sfsmp *where = 4; 34425265Sfsmp *paddr = (x * sizeof( unsigned int )) + BIOS_BASE; 34525265Sfsmp return; 34625265Sfsmp } 34725265Sfsmp } 34825265Sfsmp 34925265Sfsmp /* search the extended BIOS */ 35025265Sfsmp if ( verbose ) 35125265Sfsmp printf( " searching extended BIOS @ 0x%08x\n", BIOS_BASE2 ); 35225265Sfsmp seekEntry( BIOS_BASE2 ); 35325265Sfsmp readEntry( buffer, BIOS_SIZE ); 35425265Sfsmp 355120590Speter for ( x = 0; x < BIOS_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 35625265Sfsmp if ( buffer[ x ] == MP_SIG ) { 35725265Sfsmp *where = 5; 35825265Sfsmp *paddr = (x * sizeof( unsigned int )) + BIOS_BASE2; 35925265Sfsmp return; 36025265Sfsmp } 36125265Sfsmp } 36225265Sfsmp 36325265Sfsmp if ( grope ) { 36425265Sfsmp /* search additional memory */ 36525265Sfsmp target = GROPE_AREA1; 36625265Sfsmp if ( verbose ) 36725265Sfsmp printf( " groping memory @ 0x%08x\n", target ); 36825265Sfsmp seekEntry( target ); 36925265Sfsmp readEntry( buffer, GROPE_SIZE ); 37025265Sfsmp 371120590Speter for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 37225265Sfsmp if ( buffer[ x ] == MP_SIG ) { 37325265Sfsmp *where = 6; 37425265Sfsmp *paddr = (x * sizeof( unsigned int )) + GROPE_AREA1; 37525265Sfsmp return; 37625265Sfsmp } 37725265Sfsmp } 37825265Sfsmp 37925265Sfsmp target = GROPE_AREA2; 38025265Sfsmp if ( verbose ) 38125265Sfsmp printf( " groping memory @ 0x%08x\n", target ); 38225265Sfsmp seekEntry( target ); 38325265Sfsmp readEntry( buffer, GROPE_SIZE ); 38425265Sfsmp 385120590Speter for ( x = 0; x < GROPE_SIZE / (int)sizeof( unsigned int ); NEXT(x) ) { 38625265Sfsmp if ( buffer[ x ] == MP_SIG ) { 38725265Sfsmp *where = 7; 38825265Sfsmp *paddr = (x * sizeof( unsigned int )) + GROPE_AREA2; 38925265Sfsmp return; 39025265Sfsmp } 39125265Sfsmp } 39225265Sfsmp } 39325265Sfsmp 39425265Sfsmp *where = 0; 395120590Speter *paddr = (u_int32_t)0; 39625265Sfsmp} 39725265Sfsmp 39825265Sfsmp 39925265Sfsmp/* 40025265Sfsmp * 40125265Sfsmp */ 40229850Scharnierstatic void 403259229SjhbMPFloatingPointer( u_int32_t paddr, int where, mpfps_t* mpfpsp ) 40425265Sfsmp{ 405259229Sjhb mpfps_t mpfps; 406259229Sjhb 407259229Sjhb /* map in mpfps structure*/ 408262978Sjhb *mpfpsp = mpfps = mapEntry( paddr, sizeof( *mpfps ) ); 40925265Sfsmp 41025265Sfsmp /* show its contents */ 41125265Sfsmp printf( "MP Floating Pointer Structure:\n\n" ); 41225265Sfsmp 41329850Scharnier printf( " location:\t\t\t" ); 41425265Sfsmp switch ( where ) 41525265Sfsmp { 41625265Sfsmp case 1: 41725265Sfsmp printf( "EBDA\n" ); 41825265Sfsmp break; 41925265Sfsmp case 2: 42025265Sfsmp printf( "BIOS base memory\n" ); 42125265Sfsmp break; 42225265Sfsmp case 3: 42325265Sfsmp printf( "DEFAULT base memory (639K)\n" ); 42425265Sfsmp break; 42525265Sfsmp case 4: 42625265Sfsmp printf( "BIOS\n" ); 42725265Sfsmp break; 42825265Sfsmp case 5: 42925265Sfsmp printf( "Extended BIOS\n" ); 43025265Sfsmp break; 43125265Sfsmp 43225265Sfsmp case 0: 43325265Sfsmp printf( "NOT found!\n" ); 43425265Sfsmp exit( 1 ); 43525265Sfsmp default: 43625265Sfsmp printf( "BOGUS!\n" ); 43725265Sfsmp exit( 1 ); 43825265Sfsmp } 43925265Sfsmp printf( " physical address:\t\t0x%08x\n", paddr ); 44025265Sfsmp 44125265Sfsmp printf( " signature:\t\t\t'" ); 44225265Sfsmp pnstr( mpfps->signature, 4 ); 44325265Sfsmp printf( "'\n" ); 44425265Sfsmp 44525265Sfsmp printf( " length:\t\t\t%d bytes\n", mpfps->length * 16 ); 44625265Sfsmp printf( " version:\t\t\t1.%1d\n", mpfps->spec_rev ); 44725265Sfsmp printf( " checksum:\t\t\t0x%02x\n", mpfps->checksum ); 44825265Sfsmp 44925265Sfsmp /* bits 0:6 are RESERVED */ 45025265Sfsmp if ( mpfps->mpfb2 & 0x7f ) { 45129850Scharnier printf( " warning, MP feature byte 2: 0x%02x\n", mpfps->mpfb2 ); 45225265Sfsmp } 45325265Sfsmp 45425265Sfsmp /* bit 7 is IMCRP */ 455259229Sjhb printf( " mode:\t\t\t\t%s\n", (mpfps->mpfb2 & MPFB2_IMCR_PRESENT) ? 45625265Sfsmp "PIC" : "Virtual Wire" ); 45725265Sfsmp 45825265Sfsmp /* MP feature bytes 3-5 are expected to be ZERO */ 45925265Sfsmp if ( mpfps->mpfb3 ) 46025265Sfsmp printf( " warning, MP feature byte 3 NONZERO!\n" ); 46125265Sfsmp if ( mpfps->mpfb4 ) 46225265Sfsmp printf( " warning, MP feature byte 4 NONZERO!\n" ); 46325265Sfsmp if ( mpfps->mpfb5 ) 46425265Sfsmp printf( " warning, MP feature byte 5 NONZERO!\n" ); 46525265Sfsmp} 46625265Sfsmp 46725265Sfsmp 46825265Sfsmp/* 46925265Sfsmp * 47025265Sfsmp */ 47125265Sfsmpstatic void 47225265SfsmpMPConfigDefault( int featureByte ) 47325265Sfsmp{ 47425265Sfsmp printf( " MP default config type: %d\n\n", featureByte ); 47525265Sfsmp switch ( featureByte ) { 47625265Sfsmp case 1: 47725265Sfsmp printf( " bus: ISA, APIC: 82489DX\n" ); 47825265Sfsmp break; 47925265Sfsmp case 2: 48025265Sfsmp printf( " bus: EISA, APIC: 82489DX\n" ); 48125265Sfsmp break; 48225265Sfsmp case 3: 48325265Sfsmp printf( " bus: EISA, APIC: 82489DX\n" ); 48425265Sfsmp break; 48525265Sfsmp case 4: 48625265Sfsmp printf( " bus: MCA, APIC: 82489DX\n" ); 48725265Sfsmp break; 48825265Sfsmp case 5: 48925265Sfsmp printf( " bus: ISA+PCI, APIC: Integrated\n" ); 49025265Sfsmp break; 49125265Sfsmp case 6: 49225265Sfsmp printf( " bus: EISA+PCI, APIC: Integrated\n" ); 49325265Sfsmp break; 49425265Sfsmp case 7: 49525265Sfsmp printf( " bus: MCA+PCI, APIC: Integrated\n" ); 49625265Sfsmp break; 49725265Sfsmp default: 49825265Sfsmp printf( " future type\n" ); 49925265Sfsmp break; 50025265Sfsmp } 50125265Sfsmp 50225265Sfsmp switch ( featureByte ) { 50325265Sfsmp case 1: 50425265Sfsmp case 2: 50525265Sfsmp case 3: 50625265Sfsmp case 4: 50725265Sfsmp nbus = 1; 50825265Sfsmp break; 50925265Sfsmp case 5: 51025265Sfsmp case 6: 51125265Sfsmp case 7: 51225265Sfsmp nbus = 2; 51325265Sfsmp break; 51425265Sfsmp default: 51525265Sfsmp printf( " future type\n" ); 51625265Sfsmp break; 51725265Sfsmp } 51825265Sfsmp 51925265Sfsmp ncpu = 2; 52025265Sfsmp napic = 1; 52125265Sfsmp nintr = 16; 52225265Sfsmp} 52325265Sfsmp 52425265Sfsmp 52525265Sfsmp/* 52625265Sfsmp * 52725265Sfsmp */ 52825265Sfsmpstatic void 529120590SpeterMPConfigTableHeader( u_int32_t pap ) 53025265Sfsmp{ 53125265Sfsmp mpcth_t cth; 53229850Scharnier int x; 53371209Speter int totalSize; 534259229Sjhb int c; 53571209Speter int oldtype, entrytype; 536259229Sjhb u_int8_t *entry; 53725265Sfsmp 53825265Sfsmp if ( pap == 0 ) { 53925265Sfsmp printf( "MP Configuration Table Header MISSING!\n" ); 54025265Sfsmp exit( 1 ); 54125265Sfsmp } 54225265Sfsmp 543259229Sjhb /* map in cth structure */ 544259229Sjhb cth = mapEntry( pap, sizeof( *cth ) ); 54525265Sfsmp 54625265Sfsmp printf( "MP Config Table Header:\n\n" ); 54725265Sfsmp 54825265Sfsmp printf( " physical address:\t\t0x%08x\n", pap ); 54925265Sfsmp 55025265Sfsmp printf( " signature:\t\t\t'" ); 551259229Sjhb pnstr( cth->signature, 4 ); 55225265Sfsmp printf( "'\n" ); 55325265Sfsmp 554259229Sjhb printf( " base table length:\t\t%d\n", cth->base_table_length ); 55525265Sfsmp 556259229Sjhb printf( " version:\t\t\t1.%1d\n", cth->spec_rev ); 557259229Sjhb printf( " checksum:\t\t\t0x%02x\n", cth->checksum ); 55825265Sfsmp 55925265Sfsmp printf( " OEM ID:\t\t\t'" ); 560259229Sjhb pnstr( cth->oem_id, 8 ); 56125265Sfsmp printf( "'\n" ); 56225265Sfsmp 56325265Sfsmp printf( " Product ID:\t\t\t'" ); 564259229Sjhb pnstr( cth->product_id, 12 ); 56525265Sfsmp printf( "'\n" ); 56625265Sfsmp 567259229Sjhb printf( " OEM table pointer:\t\t0x%08x\n", cth->oem_table_pointer ); 568259229Sjhb printf( " OEM table size:\t\t%d\n", cth->oem_table_size ); 56925265Sfsmp 570259229Sjhb printf( " entry count:\t\t\t%d\n", cth->entry_count ); 57125265Sfsmp 572259229Sjhb printf( " local APIC address:\t\t0x%08x\n", cth->apic_address ); 57325265Sfsmp 574259229Sjhb printf( " extended table length:\t%d\n", cth->extended_table_length ); 575259229Sjhb printf( " extended table checksum:\t%d\n", cth->extended_table_checksum ); 57625265Sfsmp 577259229Sjhb totalSize = cth->base_table_length - sizeof( struct MPCTH ); 57825265Sfsmp 57925265Sfsmp puts( SEP_LINE ); 58025265Sfsmp 58125265Sfsmp printf( "MP Config Base Table Entries:\n\n" ); 58225265Sfsmp 583244530Sneel /* initialize tables */ 584244530Sneel for (x = 0; x < (int)nitems(busses); x++) 585244530Sneel busses[x] = 0xff; 58625265Sfsmp 587244530Sneel for (x = 0; x < (int)nitems(apics); x++) 588244530Sneel apics[x] = 0xff; 589244530Sneel 59025265Sfsmp ncpu = 0; 59125265Sfsmp nbus = 0; 59225265Sfsmp napic = 0; 59325265Sfsmp nintr = 0; 59425265Sfsmp 59571209Speter oldtype = -1; 596259229Sjhb entry = mapEntry(pap + sizeof(*cth), cth->base_table_length); 597259229Sjhb for (c = cth->entry_count; c; c--) { 598259229Sjhb entrytype = *entry; 59971209Speter if (entrytype != oldtype) 60071209Speter printf("--\n"); 60171209Speter if (entrytype < oldtype) 60271209Speter printf("MPTABLE OUT OF ORDER!\n"); 60371209Speter switch (entrytype) { 604259229Sjhb case MPCT_ENTRY_PROCESSOR: 605259229Sjhb if (oldtype != MPCT_ENTRY_PROCESSOR) 60671209Speter printf( "Processors:\tAPIC ID\tVersion\tState" 60771209Speter "\t\tFamily\tModel\tStep\tFlags\n" ); 608259229Sjhb processorEntry((proc_entry_ptr)entry); 609259229Sjhb entry += sizeof(struct PROCENTRY); 61071209Speter break; 61125265Sfsmp 612259229Sjhb case MPCT_ENTRY_BUS: 613259229Sjhb if (oldtype != MPCT_ENTRY_BUS) 61471209Speter printf( "Bus:\t\tBus ID\tType\n" ); 615259229Sjhb busEntry((bus_entry_ptr)entry); 616259229Sjhb entry += sizeof(struct BUSENTRY); 61771209Speter break; 61825265Sfsmp 619259229Sjhb case MPCT_ENTRY_IOAPIC: 620259229Sjhb if (oldtype != MPCT_ENTRY_IOAPIC) 62171209Speter printf( "I/O APICs:\tAPIC ID\tVersion\tState\t\tAddress\n" ); 622259229Sjhb ioApicEntry((io_apic_entry_ptr)entry); 623259229Sjhb entry += sizeof(struct IOAPICENTRY); 62471209Speter break; 62525265Sfsmp 626259229Sjhb case MPCT_ENTRY_INT: 627259229Sjhb if (oldtype != MPCT_ENTRY_INT) 62871209Speter printf( "I/O Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); 629259229Sjhb intEntry((int_entry_ptr)entry); 630259229Sjhb entry += sizeof(struct INTENTRY); 63171209Speter break; 63225265Sfsmp 633259229Sjhb case MPCT_ENTRY_LOCAL_INT: 634259229Sjhb if (oldtype != MPCT_ENTRY_LOCAL_INT) 63571209Speter printf( "Local Ints:\tType\tPolarity Trigger\tBus ID\t IRQ\tAPIC ID\tPIN#\n" ); 636259229Sjhb intEntry((int_entry_ptr)entry); 637259229Sjhb entry += sizeof(struct INTENTRY); 63871209Speter break; 63971209Speter 64071209Speter default: 64171209Speter printf("MPTABLE HOSED! record type = %d\n", entrytype); 64271209Speter exit(1); 64371209Speter } 644259229Sjhb oldtype = entrytype; 64525265Sfsmp } 64625265Sfsmp 64725265Sfsmp 64825265Sfsmp#if defined( EXTENDED_PROCESSING_READY ) 64925265Sfsmp /* process any extended data */ 650259229Sjhb if ( cth->extended_table_length ) { 651259229Sjhb ext_entry_ptr ext_entry, end; 652259229Sjhb 65325265Sfsmp puts( SEP_LINE ); 65425265Sfsmp 65525265Sfsmp printf( "MP Config Extended Table Entries:\n\n" ); 65625265Sfsmp 657259229Sjhb ext_entry = mapEntry(pap + cth->base_table_length, 658259229Sjhb cth->extended_table_length); 659259229Sjhb end = (ext_entry_ptr)((char *)ext_entry + cth->extended_table_length); 660259229Sjhb while (ext_entry < end) { 661259229Sjhb switch (ext_entry->type) { 662259229Sjhb case MPCT_EXTENTRY_SAS: 663259229Sjhb sasEntry((sas_entry_ptr)ext_entry); 66425265Sfsmp break; 665259229Sjhb case MPCT_EXTENTRY_BHD: 666259229Sjhb bhdEntry((bhd_entry_ptr)ext_entry); 66725265Sfsmp break; 668259229Sjhb case MPCT_EXTENTRY_CBASM: 669259229Sjhb cbasmEntry((cbasm_entry_ptr)ext_entry); 67025265Sfsmp break; 67125265Sfsmp default: 67225265Sfsmp printf( "Extended Table HOSED!\n" ); 67325265Sfsmp exit( 1 ); 67425265Sfsmp } 67525265Sfsmp 676259229Sjhb ext_entry = (ext_entry_ptr)((char *)ext_entry + ext_entry->length); 67725265Sfsmp } 67825265Sfsmp } 67925265Sfsmp#endif /* EXTENDED_PROCESSING_READY */ 68025265Sfsmp 68125265Sfsmp /* process any OEM data */ 682259229Sjhb if ( cth->oem_table_pointer && (cth->oem_table_size > 0) ) { 68325265Sfsmp#if defined( OEM_PROCESSING_READY ) 68425265Sfsmp# error your on your own here! 685259229Sjhb /* map in oem table structure */ 686259229Sjhb oemdata = mapEntry( cth->oem_table_pointer, cth->oem_table_size); 68725265Sfsmp 68825265Sfsmp /** process it */ 68925265Sfsmp#else 69025265Sfsmp printf( "\nyou need to modify the source to handle OEM data!\n\n" ); 69125265Sfsmp#endif /* OEM_PROCESSING_READY */ 69225265Sfsmp } 69325265Sfsmp 69425265Sfsmp fflush( stdout ); 69525265Sfsmp 69625265Sfsmp#if defined( RAW_DUMP ) 69725265Sfsmp{ 69825265Sfsmp int ofd; 699259229Sjhb void *dumpbuf; 70025265Sfsmp 701229466Spjd ofd = open( "/tmp/mpdump", O_CREAT | O_RDWR, 0666 ); 702259229Sjhb 703259229Sjhb dumpbuf = mapEntry( paddr, 1024 ); 70425265Sfsmp write( ofd, dumpbuf, 1024 ); 70525265Sfsmp close( ofd ); 70625265Sfsmp} 70725265Sfsmp#endif /* RAW_DUMP */ 70825265Sfsmp} 70925265Sfsmp 71025265Sfsmp 71125265Sfsmp/* 71225265Sfsmp * 71325265Sfsmp */ 71425265Sfsmpstatic void 715120590SpeterseekEntry( u_int32_t addr ) 71625265Sfsmp{ 71729850Scharnier if ( lseek( pfd, (off_t)addr, SEEK_SET ) < 0 ) 71869793Sobrien err( 1, "%s seek", _PATH_MEM ); 71925265Sfsmp} 72025265Sfsmp 72125265Sfsmp 72225265Sfsmp/* 72325265Sfsmp * 72425265Sfsmp */ 72525265Sfsmpstatic void 72625265SfsmpreadEntry( void* entry, int size ) 72725265Sfsmp{ 72829850Scharnier if ( read( pfd, entry, size ) != size ) 72929850Scharnier err( 1, "readEntry" ); 73025265Sfsmp} 73125265Sfsmp 732259229Sjhbstatic void * 733259229SjhbmapEntry( u_int32_t addr, int size ) 734259229Sjhb{ 735259229Sjhb void *p; 73625265Sfsmp 737259229Sjhb p = mmap( NULL, size, PROT_READ, MAP_SHARED, pfd, addr ); 738259229Sjhb if (p == MAP_FAILED) 739259229Sjhb err( 1, "mapEntry" ); 740259229Sjhb return (p); 741259229Sjhb} 742259229Sjhb 74325265Sfsmpstatic void 744259229SjhbprocessorEntry( proc_entry_ptr entry ) 74525265Sfsmp{ 74625265Sfsmp 74725265Sfsmp /* count it */ 74825265Sfsmp ++ncpu; 74925265Sfsmp 750259229Sjhb printf( "\t\t%2d", entry->apic_id ); 751259229Sjhb printf( "\t 0x%2x", entry->apic_version ); 75225265Sfsmp 75325265Sfsmp printf( "\t %s, %s", 754259229Sjhb (entry->cpu_flags & PROCENTRY_FLAG_BP) ? "BSP" : "AP", 755259229Sjhb (entry->cpu_flags & PROCENTRY_FLAG_EN) ? "usable" : "unusable" ); 75625265Sfsmp 75725265Sfsmp printf( "\t %d\t %d\t %d", 758259229Sjhb (entry->cpu_signature >> 8) & 0x0f, 759259229Sjhb (entry->cpu_signature >> 4) & 0x0f, 760259229Sjhb entry->cpu_signature & 0x0f ); 76125265Sfsmp 762259229Sjhb printf( "\t 0x%04x\n", entry->feature_flags ); 76325265Sfsmp} 76425265Sfsmp 76525265Sfsmp 76625265Sfsmp/* 76725265Sfsmp * 76825265Sfsmp */ 76925265Sfsmpstatic int 77025265SfsmplookupBusType( char* name ) 77125265Sfsmp{ 77225265Sfsmp int x; 77325265Sfsmp 77425265Sfsmp for ( x = 0; x < MAX_BUSTYPE; ++x ) 77525265Sfsmp if ( strcmp( busTypeTable[ x ].name, name ) == 0 ) 77625265Sfsmp return busTypeTable[ x ].type; 77725265Sfsmp 77825265Sfsmp return UNKNOWN_BUSTYPE; 77925265Sfsmp} 78025265Sfsmp 78125265Sfsmp 78225265Sfsmpstatic void 783259229SjhbbusEntry( bus_entry_ptr entry ) 78425265Sfsmp{ 78525265Sfsmp int x; 78625265Sfsmp char name[ 8 ]; 78725265Sfsmp char c; 78825265Sfsmp 78925265Sfsmp /* count it */ 79025265Sfsmp ++nbus; 79125265Sfsmp 792259229Sjhb printf( "\t\t%2d", entry->bus_id ); 793259229Sjhb printf( "\t " ); pnstr( entry->bus_type, 6 ); printf( "\n" ); 79425265Sfsmp 79525265Sfsmp for ( x = 0; x < 6; ++x ) { 796259229Sjhb if ( (c = entry->bus_type[ x ]) == ' ' ) 79725265Sfsmp break; 79825265Sfsmp name[ x ] = c; 79925265Sfsmp } 80025265Sfsmp name[ x ] = '\0'; 801259229Sjhb busses[ entry->bus_id ] = lookupBusType( name ); 80225265Sfsmp} 80325265Sfsmp 80425265Sfsmp 80525265Sfsmpstatic void 806259229SjhbioApicEntry( io_apic_entry_ptr entry ) 80725265Sfsmp{ 80825265Sfsmp 80925265Sfsmp /* count it */ 81025265Sfsmp ++napic; 81125265Sfsmp 812259229Sjhb printf( "\t\t%2d", entry->apic_id ); 813259229Sjhb printf( "\t 0x%02x", entry->apic_version ); 81425265Sfsmp printf( "\t %s", 815259229Sjhb (entry->apic_flags & IOAPICENTRY_FLAG_EN) ? "usable" : "unusable" ); 816259229Sjhb printf( "\t\t 0x%x\n", entry->apic_address ); 81725265Sfsmp 818259229Sjhb apics[ entry->apic_id ] = entry->apic_id; 81925265Sfsmp} 82025265Sfsmp 82125265Sfsmp 822227224Sedstatic const char *intTypes[] = { 82325265Sfsmp "INT", "NMI", "SMI", "ExtINT" 82425265Sfsmp}; 82525265Sfsmp 826227224Sedstatic const char *polarityMode[] = { 82725265Sfsmp "conforms", "active-hi", "reserved", "active-lo" 82825265Sfsmp}; 829227224Sedstatic const char *triggerMode[] = { 83025265Sfsmp "conforms", "edge", "reserved", "level" 83125265Sfsmp}; 83225265Sfsmp 83325265Sfsmpstatic void 834259229SjhbintEntry( int_entry_ptr entry ) 83525265Sfsmp{ 83625265Sfsmp 83725265Sfsmp /* count it */ 838259229Sjhb if ( entry->type == MPCT_ENTRY_INT ) 83925265Sfsmp ++nintr; 84025265Sfsmp 841259229Sjhb printf( "\t\t%s", intTypes[ entry->int_type ] ); 84225265Sfsmp 843259229Sjhb printf( "\t%9s", polarityMode[ entry->int_flags & INTENTRY_FLAGS_POLARITY ] ); 844259229Sjhb printf( "%12s", triggerMode[ (entry->int_flags & INTENTRY_FLAGS_TRIGGER) >> 2 ] ); 84525265Sfsmp 846259229Sjhb printf( "\t %5d", entry->src_bus_id ); 847259229Sjhb if ( busses[ entry->src_bus_id ] == PCI ) 84825265Sfsmp printf( "\t%2d:%c", 849259229Sjhb (entry->src_bus_irq >> 2) & 0x1f, 850259229Sjhb (entry->src_bus_irq & 0x03) + 'A' ); 85125265Sfsmp else 852259229Sjhb printf( "\t %3d", entry->src_bus_irq ); 853259229Sjhb printf( "\t %6d", entry->dst_apic_id ); 854259229Sjhb printf( "\t %3d\n", entry->dst_apic_int ); 85525265Sfsmp} 85625265Sfsmp 85725265Sfsmp 85825265Sfsmpstatic void 859259229SjhbsasEntry( sas_entry_ptr entry ) 86025265Sfsmp{ 86125265Sfsmp 862259229Sjhb printf( "--\nSystem Address Space\n"); 863259229Sjhb printf( " bus ID: %d", entry->bus_id ); 86425265Sfsmp printf( " address type: " ); 865259229Sjhb switch ( entry->address_type ) { 866259229Sjhb case SASENTRY_TYPE_IO: 86725265Sfsmp printf( "I/O address\n" ); 86825265Sfsmp break; 869259229Sjhb case SASENTRY_TYPE_MEMORY: 87025265Sfsmp printf( "memory address\n" ); 87125265Sfsmp break; 872259229Sjhb case SASENTRY_TYPE_PREFETCH: 87325265Sfsmp printf( "prefetch address\n" ); 87425265Sfsmp break; 87525265Sfsmp default: 87625265Sfsmp printf( "UNKNOWN type\n" ); 87725265Sfsmp break; 87825265Sfsmp } 87925265Sfsmp 880259229Sjhb printf( " address base: 0x%jx\n", (uintmax_t)entry->address_base ); 881259229Sjhb printf( " address range: 0x%jx\n", (uintmax_t)entry->address_length ); 88225265Sfsmp} 88325265Sfsmp 88425265Sfsmp 88525265Sfsmpstatic void 886259229SjhbbhdEntry( bhd_entry_ptr entry ) 88725265Sfsmp{ 88825265Sfsmp 889259229Sjhb printf( "--\nBus Hierarchy\n" ); 890259229Sjhb printf( " bus ID: %d", entry->bus_id ); 891259229Sjhb printf( " bus info: 0x%02x", entry->bus_info ); 892259229Sjhb printf( " parent bus ID: %d\n", entry->parent_bus ); 89325265Sfsmp} 89425265Sfsmp 89525265Sfsmp 89625265Sfsmpstatic void 897259229SjhbcbasmEntry( cbasm_entry_ptr entry ) 89825265Sfsmp{ 89925265Sfsmp 900259229Sjhb printf( "--\nCompatibility Bus Address\n" ); 901259229Sjhb printf( " bus ID: %d", entry->bus_id ); 902259229Sjhb printf( " address modifier: %s\n", 903259229Sjhb (entry->address_mod & CBASMENTRY_ADDRESS_MOD_SUBTRACT) ? 904259229Sjhb "subtract" : "add" ); 905259229Sjhb printf( " predefined range: 0x%08x\n", entry->predefined_range ); 90625265Sfsmp} 90725265Sfsmp 90825265Sfsmp 90925265Sfsmp/* 91025265Sfsmp * do a dmesg output 91125265Sfsmp */ 91225265Sfsmpstatic void 91325265SfsmpdoDmesg( void ) 91425265Sfsmp{ 91525265Sfsmp puts( SEP_LINE ); 91625265Sfsmp 91725265Sfsmp printf( "dmesg output:\n\n" ); 91825265Sfsmp fflush( stdout ); 91925265Sfsmp system( "dmesg" ); 92025265Sfsmp} 92125265Sfsmp 92225265Sfsmp 92325265Sfsmp/* 92425265Sfsmp * 92525265Sfsmp */ 92625265Sfsmpstatic void 92725265Sfsmppnstr( char* s, int c ) 92825265Sfsmp{ 92925265Sfsmp char string[ MAXPNSTR + 1 ]; 93025265Sfsmp 93125265Sfsmp if ( c > MAXPNSTR ) 93225265Sfsmp c = MAXPNSTR; 93325265Sfsmp strncpy( string, s, c ); 93425265Sfsmp string[ c ] = '\0'; 93525265Sfsmp printf( "%s", string ); 93625265Sfsmp} 937