//------------------------------------------------------------------- // smlayout.cpp // // This program tries to discover the current SMBASE register- // value for each processor by using services of our 'smram.c' // device-driver kernel-module to search this station's System // Management Memory for an expected pattern we associate with // the CR0 register's contents and then computing the location // for the SMBASE field within the Intel SMRAM Save-State Map. // // This forensic technique succeeded in identifying the SMBASE // addresses on our classroom workstations, which was required // for loading our own 'System Management Interrupt' handlers. // // compile using: $ smlayout.cpp -o smlayout // execute using: $ ./smlayout /dev/smram // // Reference: "SMRAM Save State Map for Intel 64 Architecture" // (from Intel 64 and IA-32 Architectures Software Developer's // Manual, Volume 3B). // // NOTE: This application is useful only on Intel64 platforms. // // ---------- // // Research question: does the processor always set the TS-bit // in its SMRAM Save-State field for Control Register CR0 upon // entering System Management Mode? We did not find this item // discussed in the Intel Software Developer's Manuals. Logic // would argue that, since the floating point registers do not // get saved, yet could be modified while in System Management // Mode, the TS-flag ought to be set to guard against a task's // using 'stale' FPU register-values when it resumes following // the System Management Interrupt. But it is unclear whether // Intel's documentation regards this type of 'context-switch' // as constituting a 'task-switch', since the task remains the // same. Our software tools, created for exploring SMIs, will // allow us to investigate such questions through experiments. // // ---------- // // programmer: ALLAN CRUSE // written on: 08 DEC 2008 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for read() #include // for strncpy() char filename[ 64 ] = "/dev/smram"; // name of input-file unsigned long long patt = 0x8005003BLL; // expected CR0 value int main( int argc, char **argv ) { // allow user to override the default input-file if ( argc > 1 ) strncpy( filename, argv[1], 63 ); // open the specified input-file int fd = open( filename, O_RDONLY ); if ( fd < 0 ) { perror( filename ); exit(1); } // obtain the size of this station's System Management Memory int filesize = lseek( fd, 0, SEEK_END ); printf( "\n \'%s\' (filesize = 0x%08X) \n\n", filename, filesize ); // loop to search the station's System Management Memory int where = 0; while ( where < filesize ) { unsigned long long pair[ 2 ] = { 0 }; lseek( fd, where, SEEK_SET ); if ( read( fd, pair, sizeof( pair ) ) < 0 ) break; if ( pair[1] == patt ) { printf( " %016llX ", pair[1] ); printf( "where=%08X ", where ); unsigned int smbase; int plant = where - 0x7FF0; lseek( fd, plant + 0x7EF8, SEEK_SET ); read( fd, &smbase, sizeof( smbase ) ); printf( " smbase=%08X ", smbase ); printf( " plant=%08X ", plant ); printf( "\n" ); } where += 16; } printf( "\n" ); }