/*++ Copyright (c) 2000 Microsoft Corporation Module Name: vfsettings.c Abstract: This module contains code that tracks whether various verifier tests are enabled. It also keeps track of various values. Author: Adrian J. Oney (adriao) 31-May-2000 Environment: Kernel mode Revision History: --*/ #include "vfdef.h" #include "visettings.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGEVRFY, VfSettingsInit) #pragma alloc_text(PAGEVRFY, VfSettingsCreateSnapshot) #pragma alloc_text(PAGEVRFY, VfSettingsGetSnapshotSize) #pragma alloc_text(PAGEVRFY, VfSettingsIsOptionEnabled) #pragma alloc_text(PAGEVRFY, VfSettingsSetOption) #pragma alloc_text(PAGEVRFY, VfSettingsGetValue) #pragma alloc_text(PAGEVRFY, VfSettingsSetValue) #endif #define POOL_TAG_VERIFIER_SETTINGS 'oGfV' // // This points to the global list of verifier settings. // PVERIFIER_SETTINGS_SNAPSHOT VfSettingsGlobal = NULL; VOID FASTCALL VfSettingsInit( IN ULONG MmFlags ) /*++ Description: This routine is called to initialize the current set of verifier settings. Arguments: MmFlags - A mask of flags (DRIVER_VERIFIER_xxx) indicating which verifier settings should be enabled. Return Value: None. --*/ { // // As this is system startup code, it is one of the very few places where // it's ok to use MustSucceed. // VfSettingsGlobal = (PVERIFIER_SETTINGS_SNAPSHOT) ExAllocatePoolWithTag( NonPagedPoolMustSucceed, VfSettingsGetSnapshotSize(), POOL_TAG_VERIFIER_SETTINGS ); RtlZeroMemory(VfSettingsGlobal, VfSettingsGetSnapshotSize()); // // Set IRP deferral time to 300 us. // VfSettingsSetValue(NULL, VERIFIER_VALUE_IRP_DEFERRAL_TIME, 10 * 300); // // Set the IRPs-to-log-per-devobj to 20 // VfSettingsSetValue(NULL, VERIFIER_VALUE_IRPLOG_COUNT, 20); if (MmFlags & DRIVER_VERIFIER_IO_CHECKING) { VfSettingsSetOption(NULL, VERIFIER_OPTION_EXAMINE_RELATION_PDOS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_TRACK_IRPS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_MONITOR_IRP_ALLOCS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_POLICE_IRPS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_MONITOR_MAJORS, TRUE); if (MmFlags & DRIVER_VERIFIER_ENHANCED_IO_CHECKING) { #if 0 // // These are untested options: // VfSettingsSetOption(NULL, VERIFIER_OPTION_BUFFER_DIRECT_IO, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_DEFER_COMPLETION, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_COMPLETE_AT_PASSIVE, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_FORCE_PENDING, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_COMPLETE_AT_DISPATCH, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_DETECT_DEADLOCKS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_VERIFY_DO_FLAGS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_SMASH_SRBS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_SURROGATE_IRPS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_SCRAMBLE_RELATIONS, TRUE); #endif VfSettingsSetOption(NULL, VERIFIER_OPTION_INSERT_WDM_FILTERS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_MONITOR_PENDING_IO, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_SEEDSTACK, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_ROTATE_STATUS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_CONSUME_ALWAYS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_MONITOR_REMOVES, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_SEND_BOGUS_WMI_IRPS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_SEND_BOGUS_POWER_IRPS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_RELATION_IGNORANCE_TEST, TRUE); } } if (MmFlags & DRIVER_VERIFIER_EXPOSE_IRP_HISTORY) { VfSettingsSetOption(NULL, VERIFIER_OPTION_TRACK_IRPS, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_EXPOSE_IRP_HISTORY, TRUE); } if (MmFlags & DRIVER_VERIFIER_DMA_VERIFIER) { VfSettingsSetOption(NULL, VERIFIER_OPTION_VERIFY_DMA, TRUE); VfSettingsSetOption(NULL, VERIFIER_OPTION_DOUBLE_BUFFER_DMA, TRUE); } if (MmFlags & DRIVER_VERIFIER_HARDWARE_VERIFICATION) { VfSettingsSetOption(NULL, VERIFIER_OPTION_HARDWARE_VERIFICATION, TRUE); } if (MmFlags & DRIVER_VERIFIER_SYSTEM_BIOS_VERIFICATION) { VfSettingsSetOption(NULL, VERIFIER_OPTION_SYSTEM_BIOS_VERIFICATION, TRUE); } } VOID FASTCALL VfSettingsCreateSnapshot( IN OUT PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot ) /*++ Description: This routine creates a snapshot of the current global verifier settings. Arguments: VerifierSettingsSnapshot - Pointer to an uninitialized block of memory, the size of which is determined by calling VfSettingsGetSnapshotSize. Return Value: Size of snapshot data in bytes. --*/ { RtlCopyMemory( VerifierSettingsSnapshot, VfSettingsGlobal, VfSettingsGetSnapshotSize() ); } ULONG FASTCALL VfSettingsGetSnapshotSize( VOID ) /*++ Description: This routine returns the size of a snapshot. It allows callers to create an appropriate sized buffer for storing verifier settings. Arguments: None. Return Value: Size of snapshot data in bytes. --*/ { return (OPTION_SIZE + sizeof(ULONG) * VERIFIER_VALUE_MAX); } BOOLEAN FASTCALL VfSettingsIsOptionEnabled( IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot OPTIONAL, IN VERIFIER_OPTION VerifierOption ) /*++ Description: This routine determines whether a given verifier option is enabled. Arguments: VerifierSettingsSnapshot - A snapshot of verifier settings. If NULL the current system-wide verifier setting are used. VerifierOption - Option to examine Return Value: TRUE if option is currently enabled, FALSE otherwise. --*/ { ULONG verifierIndex, verifierMask; PULONG verifierData; // // Bounds check. // if ((VerifierOption >= VERIFIER_OPTION_MAX) || (VerifierOption == 0)) { ASSERT(0); return FALSE; } // // Extract appropriate bit. // verifierIndex = (ULONG) VerifierOption; verifierMask = 1 << (verifierIndex % 32); verifierIndex /= 32; if (VerifierSettingsSnapshot) { verifierData = (PULONG) VerifierSettingsSnapshot; } else { verifierData = (PULONG) VfSettingsGlobal; } // // And now the test. // return (BOOLEAN)((verifierData[verifierIndex]&verifierMask) != 0); } VOID FASTCALL VfSettingsSetOption( IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot OPTIONAL, IN VERIFIER_OPTION VerifierOption, IN BOOLEAN Setting ) /*++ Description: This routine sets the state of a given verifier option. Arguments: VerifierSettingsSnapshot - A snapshot of verifier settings. If NULL the current system-wide verifier setting are used. VerifierOption - Option to set Setting - TRUE if option should be enabled, FALSE otherwise. Return Value: None. --*/ { ULONG verifierIndex, verifierMask, oldValue, newValue, lastValue; PULONG verifierData; // // Bounds check. // if ((VerifierOption >= VERIFIER_OPTION_MAX) || (VerifierOption == 0)) { ASSERT(0); return; } // // Extract appropriate bit. // verifierIndex = (ULONG) VerifierOption; verifierMask = 1 << (verifierIndex % 32); verifierIndex /= 32; if (VerifierSettingsSnapshot) { verifierData = (PULONG) VerifierSettingsSnapshot; } else { verifierData = (PULONG) VfSettingsGlobal; } // // And now to set the value as atomically as possible. // do { oldValue = verifierData[verifierIndex]; if (Setting) { newValue = oldValue | verifierMask; } else { newValue = oldValue &= ~verifierMask; } lastValue = InterlockedExchange((PLONG)(verifierData + verifierIndex), newValue); } while ( lastValue != newValue ); } VOID FASTCALL VfSettingsGetValue( IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot OPTIONAL, IN VERIFIER_VALUE VerifierValue, OUT ULONG *Value ) /*++ Description: This routine retrieves a given verifier value. Arguments: VerifierSettingsSnapshot - A snapshot of verifier settings. If NULL the current system-wide verifier setting are used. VerifierValue - Value to retrieve. Value - Receives verifier value (0 if bad VerifierValue was specified.) Return Value: None. --*/ { PULONG valueArray; // // Sanity check values // if ((VerifierValue == 0) || (VerifierValue >= VERIFIER_VALUE_MAX)) { *Value = 0; return; } // // Get appropriate array // if (VerifierSettingsSnapshot) { valueArray = (PULONG) (((PUCHAR) VerifierSettingsSnapshot) + OPTION_SIZE); } else { valueArray = (PULONG) (((PUCHAR) VfSettingsGlobal) + OPTION_SIZE); } // // Read out the value. // *Value = valueArray[VerifierValue]; } VOID FASTCALL VfSettingsSetValue( IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot OPTIONAL, IN VERIFIER_VALUE VerifierValue, IN ULONG Value ) /*++ Description: This routine sets the state of a given verifier value. Arguments: VerifierSettingsSnapshot - A snapshot of verifier settings. If NULL the current system-wide verifier setting are used. VerifierValue - Value to set. Value - ULONG to store. Return Value: None. --*/ { PULONG valueArray; // // Sanity check values // if ((VerifierValue == 0) || (VerifierValue >= VERIFIER_VALUE_MAX)) { return; } // // Get appropriate array // if (VerifierSettingsSnapshot) { valueArray = (PULONG) (((PUCHAR) VerifierSettingsSnapshot) + OPTION_SIZE); } else { valueArray = (PULONG) (((PUCHAR) VfSettingsGlobal) + OPTION_SIZE); } // // Set the value. // valueArray[VerifierValue] = Value; }