VOID KeEnterKernelDebugger ( VOID ) /*++ Routine Description: This function crashes the system in a controlled manner attempting to invoke the kernel debugger. Arguments: None. Return Value: None. --*/ { #if !defined(i386) KIRQL OldIrql; #endif // // Freeze execution of the system by disabling interrupts and looping. // KiHardwareTrigger = 1; KiDisableInterrupts(); #if !defined(i386) KeRaiseIrql(HIGH_LEVEL, &OldIrql); #endif if (InterlockedDecrement (&KeBugCheckCount) == 0) { if (KdDebuggerEnabled == FALSE) { if ( KdPitchDebugger == FALSE ) { KdInitSystem(NULL, FALSE); } } } KiBugCheckDebugBreak (DBG_STATUS_FATAL); }
/* * @implemented */ VOID NTAPI KeEnterKernelDebugger(VOID) { /* Disable interrupts */ KiHardwareTrigger = 1; _disable(); /* Check the bugcheck count */ if (!InterlockedDecrement((PLONG)&KeBugCheckCount)) { /* There was only one, is the debugger disabled? */ if (!(KdDebuggerEnabled) && !(KdPitchDebugger)) { /* Enable the debugger */ KdInitSystem(0, NULL); } } /* Break in the debugger */ KiBugCheckDebugBreak(DBG_STATUS_FATAL); }
VOID KeDumpMachineState ( IN PKPROCESSOR_STATE ProcessorState, IN PCHAR Buffer, IN PULONG BugCheckParameters, IN ULONG NumberOfParameters, IN PKE_BUGCHECK_UNICODE_TO_ANSI UnicodeToAnsiRoutine ) /*++ Routine Description: This function formats and displays the machine state at the time of the to bug check. Arguments: ProcessorState - Supplies a pointer to a processor state record. Buffer - Supplies a pointer to a buffer to be used to output machine state information. BugCheckParameters - Supplies a pointer to an array of additional bug check information. NumberOfParameters - Suppiles the size of the bug check parameters array. UnicodeToAnsiRoutine - Supplies a pointer to a routine to convert Unicode strings to Ansi strings without touching paged translation tables. Return Value: None. --*/ { PCONTEXT ContextRecord; ULONG ControlPc; PLDR_DATA_TABLE_ENTRY DataTableEntry; ULONG DisplayColumn; ULONG DisplayHeight; ULONG DisplayRow; ULONG DisplayWidth; UNICODE_STRING DllName; ULONG EstablisherFrame; PRUNTIME_FUNCTION FunctionEntry; PVOID ImageBase; ULONG Index; BOOLEAN InFunction; ULONG LastStack; PLIST_ENTRY ModuleListHead; PLIST_ENTRY NextEntry; ULONG NextPc; ULONG StackLimit; UCHAR AnsiBuffer[ 32 ]; ULONG DateStamp; // // Call the HAL to force all external interrupts to be disabled // at the interrupt controller. PowerPC optimization does not // do this when raising to high level. // for (Index = 0; Index < MAXIMUM_VECTOR; Index++) { HalDisableSystemInterrupt(Index, HIGH_LEVEL); } // // Query display parameters. // HalQueryDisplayParameters(&DisplayWidth, &DisplayHeight, &DisplayColumn, &DisplayRow); // // Display any addresses that fall within the range of any module in // the loaded module list. // for (Index = 0; Index < NumberOfParameters; Index += 1) { ImageBase = KiPcToFileHeader((PVOID)*BugCheckParameters, &ImageBase, &DataTableEntry); if (ImageBase != NULL) { sprintf(Buffer, "*** %08lX has base at %08lX - %s\n", *BugCheckParameters, ImageBase, (*UnicodeToAnsiRoutine)( &DataTableEntry->BaseDllName, AnsiBuffer, sizeof( AnsiBuffer ))); HalDisplayString(Buffer); } BugCheckParameters += 1; } // // Virtually unwind to the caller of bug check. // ContextRecord = &ProcessorState->ContextFrame; LastStack = ContextRecord->Gpr1; ControlPc = ContextRecord->Lr - 4; NextPc = ControlPc; FunctionEntry = KiLookupFunctionEntry(ControlPc); if (FunctionEntry != NULL) { NextPc = RtlVirtualUnwind(ControlPc, FunctionEntry, ContextRecord, &InFunction, &EstablisherFrame, NULL, 0, 0xffffffff); } // // At this point the context record contains the machine state at the // call to bug check. // // Put out the machine state at the time of the bugcheck. // sprintf(Buffer, "\n Machine State at Call to Bug Check IAR:%08lX MSR:%08lX\n", ContextRecord->Lr, ContextRecord->Msr); HalDisplayString(Buffer); // // Format and output the integer registers. // sprintf(Buffer, " R0:%8lX R1:%8lX R2:%8lX R3:%8lX R4:%8lX R5:%8lX\n", ContextRecord->Gpr0, ContextRecord->Gpr1, ContextRecord->Gpr2, ContextRecord->Gpr3, ContextRecord->Gpr4, ContextRecord->Gpr5); HalDisplayString(Buffer); sprintf(Buffer, " R6:%8lX R7:%8lX R8:%8lX R9:%8lX R10:%8lX R11:%8lX\n", ContextRecord->Gpr6, ContextRecord->Gpr7, ContextRecord->Gpr8, ContextRecord->Gpr9, ContextRecord->Gpr10, ContextRecord->Gpr11); HalDisplayString(Buffer); sprintf(Buffer, "R12:%8lX R13:%8lX R14:%8lX R15:%8lX R16:%8lX R17:%8lX\n", ContextRecord->Gpr12, ContextRecord->Gpr13, ContextRecord->Gpr14, ContextRecord->Gpr15, ContextRecord->Gpr16, ContextRecord->Gpr17); HalDisplayString(Buffer); sprintf(Buffer, "R18:%8lX R19:%8lX R20:%8lX R21:%8lX R22:%8lX R23:%8lX\n", ContextRecord->Gpr18, ContextRecord->Gpr19, ContextRecord->Gpr20, ContextRecord->Gpr21, ContextRecord->Gpr22, ContextRecord->Gpr23); HalDisplayString(Buffer); sprintf(Buffer, "R24:%8lX R25:%8lX R26:%8lX R27:%8lX R28:%8lX R29:%8lX\n", ContextRecord->Gpr24, ContextRecord->Gpr25, ContextRecord->Gpr26, ContextRecord->Gpr27, ContextRecord->Gpr28, ContextRecord->Gpr29); HalDisplayString(Buffer); sprintf(Buffer, "R30:%8lX R31:%8lX CR:%8lX CTR:%8lX XER:%8lX\n", ContextRecord->Gpr30, ContextRecord->Gpr31, ContextRecord->Cr, ContextRecord->Ctr, ContextRecord->Xer); HalDisplayString(Buffer); #if 0 // // I'd much rather see a longer stack trace and skip the floating // point stuff when the system crashes. plj // // // Format and output the floating registers. // DumpFloat = (PULONG)(&ContextRecord->Fpr0); sprintf(Buffer, " F0- F3:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr4); sprintf(Buffer, " F4- F7:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr8); sprintf(Buffer, " F8-F11:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr12); sprintf(Buffer, "F12-F15:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr16); sprintf(Buffer, "F16-F19:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr20); sprintf(Buffer, "F20-F23:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr24); sprintf(Buffer, "F24-F27:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpr28); sprintf(Buffer, "F28-F31:%08lX%08lX %08lX%08lX %08lX%08lX %08lX%08lX\n", *(DumpFloat+1), *DumpFloat, *(DumpFloat+3), *(DumpFloat+2), *(DumpFloat+5), *(DumpFloat+4), *(DumpFloat+7), *(DumpFloat+6)); HalDisplayString(Buffer); DumpFloat = (PULONG)(&ContextRecord->Fpscr); sprintf(Buffer, " FPSCR:%08lX%08lX\n", *(DumpFloat+1), *DumpFloat); HalDisplayString(Buffer); #define STAKWALK 4 #else #define STAKWALK 8 #endif // // Output short stack back trace with base address. // DllName.Length = 0; DllName.Buffer = L""; if (FunctionEntry != NULL) { StackLimit = (ULONG)KeGetCurrentThread()->KernelStack; HalDisplayString("Callee-Sp Return-Ra Dll Base - Name\n"); for (Index = 0; Index < STAKWALK; Index += 1) { ImageBase = KiPcToFileHeader((PVOID)ControlPc, &ImageBase, &DataTableEntry); sprintf(Buffer, " %08lX %08lX : %08lX - %s\n", ContextRecord->Gpr1, NextPc + 4, ImageBase, (*UnicodeToAnsiRoutine)( (ImageBase != NULL) ? &DataTableEntry->BaseDllName : &DllName, AnsiBuffer, sizeof( AnsiBuffer ))); HalDisplayString(Buffer); if ((NextPc != ControlPc) || (ContextRecord->Gpr1 != LastStack)) { ControlPc = NextPc; LastStack = ContextRecord->Gpr1; FunctionEntry = KiLookupFunctionEntry(ControlPc); if ((FunctionEntry != NULL) && (LastStack < StackLimit)) { NextPc = RtlVirtualUnwind(ControlPc, FunctionEntry, ContextRecord, &InFunction, &EstablisherFrame, NULL, 0, 0xffffffff); } else { NextPc = ContextRecord->Lr; } } else { break; } } } // // Output the build number and other useful information. // sprintf(Buffer, "\nIRQL : %d, DPC Active : %s, SYSVER 0x%08x\n", KeGetCurrentIrql(), KeIsExecutingDpc() ? "TRUE" : "FALSE", NtBuildNumber); HalDisplayString(Buffer); // // Output the processor id and the primary cache sizes. // sprintf(Buffer, "Processor Id: %d.%d, Icache: %d, Dcache: %d", PCR->ProcessorVersion, PCR->ProcessorRevision, PCR->FirstLevelIcacheSize, PCR->FirstLevelDcacheSize); HalDisplayString(Buffer); // // If the display width is greater than 80 + 24 (the size of a DLL // name and base address), then display all the modules loaded in // the system. // HalQueryDisplayParameters(&DisplayWidth, &DisplayHeight, &DisplayColumn, &DisplayRow); if (DisplayWidth > (80 + 24)) { HalDisplayString("\n"); if (KeLoaderBlock != NULL) { ModuleListHead = &KeLoaderBlock->LoadOrderListHead; } else { ModuleListHead = &PsLoadedModuleList; } // // Output display headers. // Index = 1; KiDisplayString(80, Index, "Dll Base DateStmp - Name"); NextEntry = ModuleListHead->Flink; if (NextEntry != NULL) { // // Scan the list of loaded modules and display their base // address and name. // while (NextEntry != ModuleListHead) { Index += 1; DataTableEntry = CONTAINING_RECORD(NextEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (MmDbgReadCheck(DataTableEntry->DllBase) != NULL) { PIMAGE_NT_HEADERS NtHeaders; NtHeaders = RtlImageNtHeader(DataTableEntry->DllBase); DateStamp = NtHeaders->FileHeader.TimeDateStamp; } else { DateStamp = 0; } sprintf(Buffer, "%08lX %08lx - %s", DataTableEntry->DllBase, DateStamp, (*UnicodeToAnsiRoutine)( &DataTableEntry->BaseDllName, AnsiBuffer, sizeof( AnsiBuffer ))); KiDisplayString(80, Index, Buffer); NextEntry = NextEntry->Flink; if (Index > DisplayHeight) { break; } } } } // // Reset the current display position. // HalSetDisplayParameters(DisplayColumn, DisplayRow); // // The system has crashed, if we are running without the Kernel // debugger attached, attach it now. // KdInitSystem(NULL, FALSE); return; }
VOID KeBugCheckEx ( IN ULONG BugCheckCode, IN ULONG_PTR BugCheckParameter1, IN ULONG_PTR BugCheckParameter2, IN ULONG_PTR BugCheckParameter3, IN ULONG_PTR BugCheckParameter4 ) /*++ Routine Description: This function crashes the system in a controlled manner. Arguments: BugCheckCode - Supplies the reason for the bug check. BugCheckParameter1-4 - Supplies additional bug check information Return Value: None. --*/ { UCHAR Buffer[100]; ULONG_PTR BugCheckParameters[4]; CONTEXT ContextSave; ULONG PssMessage; PCHAR HardErrorCaption; PCHAR HardErrorMessage; KIRQL OldIrql; PKTRAP_FRAME TrapInformation; PVOID ExecutionAddress; PVOID ImageBase; PVOID VirtualAddress; PLDR_DATA_TABLE_ENTRY DataTableEntry; UCHAR AnsiBuffer[32]; PKTHREAD Thread; BOOLEAN InKernelOrHal; BOOLEAN DontCare; #if !defined(NT_UP) ULONG TargetSet; #endif BOOLEAN hardErrorCalled; // // Try to simulate a power failure for Cluster testing // if (BugCheckCode == POWER_FAILURE_SIMULATE) { KiScanBugCheckCallbackList(); HalReturnToFirmware(HalRebootRoutine); } // // Capture the callers context as closely as possible into the debugger's // processor state area of the Prcb. // // N.B. There may be some prologue code that shuffles registers such that // they get destroyed. // #if defined(i386) KiSetHardwareTrigger(); #else KiHardwareTrigger = 1; #endif RtlCaptureContext(&KeGetCurrentPrcb()->ProcessorState.ContextFrame); KiSaveProcessorControlState(&KeGetCurrentPrcb()->ProcessorState); // // This is necessary on machines where the virtual unwind that happens // during KeDumpMachineState() destroys the context record. // ContextSave = KeGetCurrentPrcb()->ProcessorState.ContextFrame; // // If we are called by hard error then we don't want to dump the // processor state on the machine. // // We know that we are called by hard error because the bug check // code will be FATAL_UNHANDLED_HARD_ERROR. If this is so then the // error status passed to harderr is the first parameter, and a pointer // to the parameter array from hard error is passed as the second // argument. // // The third argument is the OemCaption to be printed. // The last argument is the OemMessage to be printed. // if (BugCheckCode == FATAL_UNHANDLED_HARD_ERROR) { PULONG_PTR parameterArray; hardErrorCalled = TRUE; HardErrorCaption = (PCHAR)BugCheckParameter3; HardErrorMessage = (PCHAR)BugCheckParameter4; parameterArray = (PULONG_PTR)BugCheckParameter2; BugCheckCode = (ULONG)BugCheckParameter1; BugCheckParameter1 = parameterArray[0]; BugCheckParameter2 = parameterArray[1]; BugCheckParameter3 = parameterArray[2]; BugCheckParameter4 = parameterArray[3]; } else { hardErrorCalled = FALSE; switch (BugCheckCode) { case IRQL_NOT_LESS_OR_EQUAL: ExecutionAddress = (PVOID)BugCheckParameter4; if (ExecutionAddress >= ExPoolCodeStart && ExecutionAddress < ExPoolCodeEnd) { BugCheckCode = DRIVER_CORRUPTED_EXPOOL; } else if (ExecutionAddress >= MmPoolCodeStart && ExecutionAddress < MmPoolCodeEnd) { BugCheckCode = DRIVER_CORRUPTED_MMPOOL; } else if (ExecutionAddress >= MmPteCodeStart && ExecutionAddress < MmPteCodeEnd) { BugCheckCode = DRIVER_CORRUPTED_SYSPTES; } else { ImageBase = KiPcToFileHeader (ExecutionAddress, &DataTableEntry, FALSE, &InKernelOrHal); if (InKernelOrHal == TRUE) { // // The kernel faulted at raised IRQL. Quite often this // is a driver that has unloaded without deleting its // lookaside lists or other resources. Or its resources // are marked pagable and shouldn't be. Detect both // cases here and identify the offending driver // whenever possible. // VirtualAddress = (PVOID)BugCheckParameter1; ImageBase = KiPcToFileHeader (VirtualAddress, &DataTableEntry, TRUE, &InKernelOrHal); if (ImageBase != NULL) { KiBugCheckDriver = &DataTableEntry->BaseDllName; BugCheckCode = DRIVER_PORTION_MUST_BE_NONPAGED; } else { KiBugCheckDriver = MmLocateUnloadedDriver (VirtualAddress); if (KiBugCheckDriver != NULL) { BugCheckCode = SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD; } } } else { BugCheckCode = DRIVER_IRQL_NOT_LESS_OR_EQUAL; } } break; case ATTEMPTED_WRITE_TO_READONLY_MEMORY: KiBugCheckDriver = NULL; TrapInformation = (PKTRAP_FRAME)BugCheckParameter3; // // Extract the execution address from the trap frame to // identify the component. // if (TrapInformation != NULL) { ExecutionAddress = (PVOID)PROGRAM_COUNTER (TrapInformation); ImageBase = KiPcToFileHeader (ExecutionAddress, &DataTableEntry, TRUE, &InKernelOrHal); if (ImageBase != NULL) { KiBugCheckDriver = &DataTableEntry->BaseDllName; } } break; case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS: ExecutionAddress = (PVOID)BugCheckParameter1; ImageBase = KiPcToFileHeader (ExecutionAddress, &DataTableEntry, TRUE, &InKernelOrHal); if (ImageBase != NULL) { KiBugCheckDriver = &DataTableEntry->BaseDllName; } else { KiBugCheckDriver = MmLocateUnloadedDriver (ExecutionAddress); } BugCheckParameter4 = (ULONG_PTR)KiBugCheckDriver; break; case DRIVER_USED_EXCESSIVE_PTES: DataTableEntry = (PLDR_DATA_TABLE_ENTRY)BugCheckParameter1; KiBugCheckDriver = &DataTableEntry->BaseDllName; break; case PAGE_FAULT_IN_NONPAGED_AREA: ExecutionAddress = NULL; KiBugCheckDriver = NULL; VirtualAddress = (PVOID)BugCheckParameter1; TrapInformation = (PKTRAP_FRAME)BugCheckParameter3; // // Extract the execution address from the trap frame to // identify the component. // if (TrapInformation != NULL) { ExecutionAddress = (PVOID)PROGRAM_COUNTER (TrapInformation); BugCheckParameter3 = (ULONG_PTR)ExecutionAddress; KiPcToFileHeader (ExecutionAddress, &DataTableEntry, FALSE, &InKernelOrHal); ImageBase = KiPcToFileHeader (ExecutionAddress, &DataTableEntry, TRUE, &DontCare); if (ImageBase != NULL) { KiBugCheckDriver = &DataTableEntry->BaseDllName; } } else { // // No trap frame, so no execution address either. // BugCheckParameter3 = 0; } Thread = KeGetCurrentThread(); if ((VirtualAddress >= MmSpecialPoolStart) && (VirtualAddress < MmSpecialPoolEnd)) { // // Update the bugcheck number so the administrator gets // useful feedback that enabling special pool has enabled // the system to locate the corruptor. // if (MmIsSpecialPoolAddressFree (VirtualAddress) == TRUE) { if (InKernelOrHal == TRUE) { BugCheckCode = PAGE_FAULT_IN_FREED_SPECIAL_POOL; } else { BugCheckCode = DRIVER_PAGE_FAULT_IN_FREED_SPECIAL_POOL; } } else { if (InKernelOrHal == TRUE) { BugCheckCode = PAGE_FAULT_BEYOND_END_OF_ALLOCATION; } else { BugCheckCode = DRIVER_PAGE_FAULT_BEYOND_END_OF_ALLOCATION; } } } else if ((ExecutionAddress == VirtualAddress) && (MmIsHydraAddress (VirtualAddress) == TRUE) && ((Thread->Teb == NULL) || (IS_SYSTEM_ADDRESS(Thread->Teb)))) { // // This is a driver reference to session space from a // worker thread. Since the system process has no session // space this is illegal and the driver must be fixed. // BugCheckCode = TERMINAL_SERVER_DRIVER_MADE_INCORRECT_MEMORY_REFERENCE; } else { KiBugCheckDriver = MmLocateUnloadedDriver (VirtualAddress); if (KiBugCheckDriver != NULL) { BugCheckCode = DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS; } } break; default: break; } } if (KiBugCheckDriver != NULL) { KeBugCheckUnicodeToAnsi (KiBugCheckDriver, AnsiBuffer, sizeof (AnsiBuffer)); } KiBugCheckData[0] = BugCheckCode; KiBugCheckData[1] = BugCheckParameter1; KiBugCheckData[2] = BugCheckParameter2; KiBugCheckData[3] = BugCheckParameter3; KiBugCheckData[4] = BugCheckParameter4; BugCheckParameters[0] = BugCheckParameter1; BugCheckParameters[1] = BugCheckParameter2; BugCheckParameters[2] = BugCheckParameter3; BugCheckParameters[3] = BugCheckParameter4; if (KdPitchDebugger == FALSE ) { KdDebuggerDataBlock.SavedContext = (ULONG_PTR) &ContextSave; } // // If the user manually crashed the machine, skips the DbgPrints and // go to the crashdump. // Trying to do DbgPrint causes us to reeeter the debugger which causes // some problems. // // Otherwise, if the debugger is enabled, print out the information and // stop. // if ((BugCheckCode != MANUALLY_INITIATED_CRASH) && (KdDebuggerEnabled)) { DbgPrint("\n*** Fatal System Error: 0x%08lx\n" " (0x%p,0x%p,0x%p,0x%p)\n\n", BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4); // // If the debugger is not actually connected, or the user manually // crashed the machine by typing .crash in the debugger, proceed to // "blue screen" the system. // // The call to DbgPrint above will have set the state of // KdDebuggerNotPresent if the debugger has become disconnected // since the system was booted. // if (KdDebuggerNotPresent == FALSE) { if (KiBugCheckDriver != NULL) { DbgPrint("The %s driver may be at fault.\n", AnsiBuffer); } if (hardErrorCalled != FALSE) { if (HardErrorCaption) { DbgPrint(HardErrorCaption); } if (HardErrorMessage) { DbgPrint(HardErrorMessage); } } KiBugCheckDebugBreak (DBG_STATUS_BUGCHECK_FIRST); } } // // Freeze execution of the system by disabling interrupts and looping. // KiDisableInterrupts(); KeRaiseIrql(HIGH_LEVEL, &OldIrql); // // Don't attempt to display message more than once. // if (InterlockedDecrement (&KeBugCheckCount) == 0) { #if !defined(NT_UP) // // Attempt to get the other processors frozen now, but don't wait // for them to freeze (in case someone is stuck). // TargetSet = KeActiveProcessors & ~KeGetCurrentPrcb()->SetMember; if (TargetSet != 0) { KiIpiSend((KAFFINITY) TargetSet, IPI_FREEZE); // // Give the other processors one second to flush their data caches. // // N.B. This cannot be synchronized since the reason for the bug // may be one of the other processors failed. // KeStallExecutionProcessor(1000 * 1000); } #endif // // Enable InbvDisplayString calls to make it through to bootvid driver. // if (InbvIsBootDriverInstalled()) { InbvAcquireDisplayOwnership(); InbvResetDisplay(); InbvSolidColorFill(0,0,639,479,4); // make the screen blue InbvSetTextColor(15); InbvInstallDisplayStringFilter((INBV_DISPLAY_STRING_FILTER)NULL); InbvEnableDisplayString(TRUE); // enable display string InbvSetScrollRegion(0,0,639,479); // set to use entire screen } if (!hardErrorCalled) { sprintf((char *)Buffer, "\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\n", BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4 ); InbvDisplayString((char *)Buffer); KeGetBugMessageText(BugCheckCode, NULL); InbvDisplayString("\n"); if (KiBugCheckDriver != NULL) { // // Output the driver name. // KeGetBugMessageText(BUGCODE_ID_DRIVER, NULL); InbvDisplayString(AnsiBuffer); InbvDisplayString("\n"); } } else { if (HardErrorCaption) { InbvDisplayString(HardErrorCaption); } if (HardErrorMessage) { InbvDisplayString(HardErrorMessage); } } // // Process the bug check callback list. // KiScanBugCheckCallbackList(); // // If the debugger is not enabled, then dump the machine state and // attempt to enable the debugger. // if (!hardErrorCalled) { KiDumpParameterImages( (char *)Buffer, BugCheckParameters, 4, KeBugCheckUnicodeToAnsi); } if (KdDebuggerEnabled == FALSE && KdPitchDebugger == FALSE ) { KdInitSystem(NULL, FALSE); } else { InbvDisplayString("\n"); } // // Write a crash dump and optionally reboot if the system has been // so configured. // KeGetCurrentPrcb()->ProcessorState.ContextFrame = ContextSave; if (!IoWriteCrashDump(BugCheckCode, BugCheckParameter1, BugCheckParameter2, BugCheckParameter3, BugCheckParameter4, &ContextSave )) { // // If no crashdump take, display the PSS message. // switch ( BugCheckCode ) { case IRQL_NOT_LESS_OR_EQUAL: case DRIVER_IRQL_NOT_LESS_OR_EQUAL: case DRIVER_CORRUPTED_EXPOOL: case DRIVER_CORRUPTED_MMPOOL: case DRIVER_PORTION_MUST_BE_NONPAGED: case SYSTEM_SCAN_AT_RAISED_IRQL_CAUGHT_IMPROPER_DRIVER_UNLOAD: PssMessage = BUGCODE_PSS_MESSAGE_A; break; case KMODE_EXCEPTION_NOT_HANDLED: PssMessage = BUGCODE_PSS_MESSAGE_1E; break; case FAT_FILE_SYSTEM: case NTFS_FILE_SYSTEM: PssMessage = BUGCODE_PSS_MESSAGE_23; break; case DATA_BUS_ERROR: PssMessage = BUGCODE_PSS_MESSAGE_2E; break; case NO_MORE_SYSTEM_PTES: PssMessage = BUGCODE_PSS_MESSAGE_3F; break; case INACCESSIBLE_BOOT_DEVICE: PssMessage = BUGCODE_PSS_MESSAGE_7B; break; case UNEXPECTED_KERNEL_MODE_TRAP: PssMessage = BUGCODE_PSS_MESSAGE_7F; break; case STATUS_SYSTEM_IMAGE_BAD_SIGNATURE: PssMessage = BUGCODE_PSS_MESSAGE_SIGNATURE; break; case ACPI_BIOS_ERROR: PssMessage = BUGCODE_PSS_MESSAGE_A5; break; case ACPI_BIOS_FATAL_ERROR: PssMessage = ACPI_BIOS_FATAL_ERROR; break; default: PssMessage = BUGCODE_PSS_MESSAGE; break; } KeGetBugMessageText(PssMessage, NULL); } } // // Attempt to enter the kernel debugger. // KiBugCheckDebugBreak (DBG_STATUS_BUGCHECK_SECOND); return; }
VOID NTAPI KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { CCHAR Cpu; PKTHREAD InitialThread; ULONG64 InitialStack; PKIPCR Pcr; /* HACK */ FrLdrDbgPrint = LoaderBlock->u.I386.CommonDataArea; //FrLdrDbgPrint("Hello from KiSystemStartup!!!\n"); /* Save the loader block */ KeLoaderBlock = LoaderBlock; /* Get the current CPU number */ Cpu = KeNumberProcessors++; // FIXME /* LoaderBlock initialization for Cpu 0 */ if (Cpu == 0) { /* Set the initial stack, idle thread and process */ LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack; LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread; LoaderBlock->Process = (ULONG_PTR)&KiInitialProcess.Pcb; LoaderBlock->Prcb = (ULONG_PTR)&KiInitialPcr.Prcb; } /* Get Pcr from loader block */ Pcr = CONTAINING_RECORD(LoaderBlock->Prcb, KIPCR, Prcb); /* Set the PRCB for this Processor */ KiProcessorBlock[Cpu] = &Pcr->Prcb; /* Align stack to 16 bytes */ LoaderBlock->KernelStack &= ~(16 - 1); /* Save the initial thread and stack */ InitialStack = LoaderBlock->KernelStack; // Checkme InitialThread = (PKTHREAD)LoaderBlock->Thread; /* Set us as the current process */ InitialThread->ApcState.Process = (PVOID)LoaderBlock->Process; /* Initialize the PCR */ KiInitializePcr(Pcr, Cpu, InitialThread, (PVOID)KiDoubleFaultStack); /* Initialize the CPU features */ KiInitializeCpu(Pcr); /* Initial setup for the boot CPU */ if (Cpu == 0) { /* Initialize the module list (ntos, hal, kdcom) */ KiInitModuleList(LoaderBlock); /* Setup the TSS descriptors and entries */ KiInitializeTss(Pcr->TssBase, InitialStack); /* Setup the IDT */ KeInitExceptions(); /* Initialize debugging system */ KdInitSystem(0, KeLoaderBlock); /* Check for break-in */ if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); } DPRINT1("Pcr = %p, Gdt = %p, Idt = %p, Tss = %p\n", Pcr, Pcr->GdtBase, Pcr->IdtBase, Pcr->TssBase); /* Acquire lock */ while (InterlockedBitTestAndSet64((PLONG64)&KiFreezeExecutionLock, 0)) { /* Loop until lock is free */ while ((*(volatile KSPIN_LOCK*)&KiFreezeExecutionLock) & 1); } /* Initialize the Processor with HAL */ HalInitializeProcessor(Cpu, KeLoaderBlock); /* Set processor as active */ KeActiveProcessors |= 1ULL << Cpu; /* Release lock */ InterlockedAnd64((PLONG64)&KiFreezeExecutionLock, 0); /* Raise to HIGH_LEVEL */ KfRaiseIrql(HIGH_LEVEL); /* Machine specific kernel initialization */ if (Cpu == 0) KiInitializeKernelMachineDependent(&Pcr->Prcb, LoaderBlock); /* Switch to new kernel stack and start kernel bootstrapping */ KiSwitchToBootStack(InitialStack & ~3); }
BOOLEAN INIT_FUNCTION NTAPI IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { LARGE_INTEGER ExpireTime; NTSTATUS Status; CHAR Buffer[256]; ANSI_STRING NtBootPath, RootString; /* Initialize empty NT Boot Path */ RtlInitEmptyAnsiString(&NtBootPath, Buffer, sizeof(Buffer)); /* Initialize the lookaside lists */ IopInitLookasideLists(); /* Initialize all locks and lists */ ExInitializeResource(&IopDatabaseResource); ExInitializeResource(&IopSecurityResource); KeInitializeGuardedMutex(&PnpNotifyListLock); InitializeListHead(&IopDiskFileSystemQueueHead); InitializeListHead(&IopCdRomFileSystemQueueHead); InitializeListHead(&IopTapeFileSystemQueueHead); InitializeListHead(&IopNetworkFileSystemQueueHead); InitializeListHead(&DriverBootReinitListHead); InitializeListHead(&DriverReinitListHead); InitializeListHead(&PnpNotifyListHead); InitializeListHead(&ShutdownListHead); InitializeListHead(&LastChanceShutdownListHead); InitializeListHead(&IopFsNotifyChangeQueueHead); InitializeListHead(&IopErrorLogListHead); KeInitializeSpinLock(&IoStatisticsLock); KeInitializeSpinLock(&DriverReinitListLock); KeInitializeSpinLock(&DriverBootReinitListLock); KeInitializeSpinLock(&ShutdownListLock); KeInitializeSpinLock(&IopLogListLock); /* Initialize Timer List Lock */ KeInitializeSpinLock(&IopTimerLock); /* Initialize Timer List */ InitializeListHead(&IopTimerQueueHead); /* Initialize the DPC/Timer which will call the other Timer Routines */ ExpireTime.QuadPart = -10000000; KeInitializeDpc(&IopTimerDpc, IopTimerDispatch, NULL); KeInitializeTimerEx(&IopTimer, SynchronizationTimer); KeSetTimerEx(&IopTimer, ExpireTime, 1000, &IopTimerDpc); /* Create Object Types */ if (!IopCreateObjectTypes()) { DPRINT1("IopCreateObjectTypes failed!\n"); return FALSE; } /* Create Object Directories */ if (!IopCreateRootDirectories()) { DPRINT1("IopCreateRootDirectories failed!\n"); return FALSE; } /* Initialize PnP manager */ IopInitializePlugPlayServices(); /* Initialize HAL Root Bus Driver */ HalInitPnpDriver(); /* Make loader block available for the whole kernel */ IopLoaderBlock = LoaderBlock; /* Load boot start drivers */ IopInitializeBootDrivers(); /* Call back drivers that asked for */ IopReinitializeBootDrivers(); /* Check if this was a ramdisk boot */ if (!_strnicmp(LoaderBlock->ArcBootDeviceName, "ramdisk(0)", 10)) { /* Initialize the ramdisk driver */ IopStartRamdisk(LoaderBlock); } /* No one should need loader block any longer */ IopLoaderBlock = NULL; /* Create ARC names for boot devices */ Status = IopCreateArcNames(LoaderBlock); if (!NT_SUCCESS(Status)) { DPRINT1("IopCreateArcNames failed: %lx\n", Status); return FALSE; } /* Mark the system boot partition */ if (!IopMarkBootPartition(LoaderBlock)) { DPRINT1("IopMarkBootPartition failed!\n"); return FALSE; } /* Initialize PnP root relations */ IopEnumerateDevice(IopRootDeviceNode->PhysicalDeviceObject); #ifndef _WINKD_ /* Read KDB Data */ KdbInit(); /* I/O is now setup for disk access, so phase 3 */ KdInitSystem(3, LoaderBlock); #endif /* Load services for devices found by PnP manager */ IopInitializePnpServices(IopRootDeviceNode); /* Load system start drivers */ IopInitializeSystemDrivers(); PnpSystemInit = TRUE; /* Reinitialize drivers that requested it */ IopReinitializeDrivers(); /* Convert SystemRoot from ARC to NT path */ Status = IopReassignSystemRoot(LoaderBlock, &NtBootPath); if (!NT_SUCCESS(Status)) { DPRINT1("IopReassignSystemRoot failed: %lx\n", Status); return FALSE; } /* Set the ANSI_STRING for the root path */ RootString.MaximumLength = NtSystemRoot.MaximumLength / sizeof(WCHAR); RootString.Length = 0; RootString.Buffer = ExAllocatePoolWithTag(PagedPool, RootString.MaximumLength, TAG_IO); /* Convert the path into the ANSI_STRING */ Status = RtlUnicodeStringToAnsiString(&RootString, &NtSystemRoot, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("RtlUnicodeStringToAnsiString failed: %lx\n", Status); return FALSE; } /* Assign drive letters */ IoAssignDriveLetters(LoaderBlock, &NtBootPath, (PUCHAR)RootString.Buffer, &RootString); /* Update system root */ Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &RootString, FALSE); if (!NT_SUCCESS(Status)) { DPRINT1("RtlAnsiStringToUnicodeString failed: %lx\n", Status); return FALSE; } /* Load the System DLL and its Entrypoints */ Status = PsLocateSystemDll(); if (!NT_SUCCESS(Status)) { DPRINT1("PsLocateSystemDll failed: %lx\n", Status); return FALSE; } /* Return success */ return TRUE; }
VOID NTAPI INIT_FUNCTION KiSystemStartup(IN PLOADER_PARAMETER_BLOCK LoaderBlock) { ULONG Cpu; PKTHREAD InitialThread; ULONG InitialStack; PKGDTENTRY Gdt; PKIDTENTRY Idt; KIDTENTRY NmiEntry, DoubleFaultEntry; PKTSS Tss; PKIPCR Pcr; /* Boot cycles timestamp */ BootCycles = __rdtsc(); /* Save the loader block and get the current CPU */ KeLoaderBlock = LoaderBlock; Cpu = KeNumberProcessors; if (!Cpu) { /* If this is the boot CPU, set FS and the CPU Number*/ Ke386SetFs(KGDT_R0_PCR); __writefsdword(KPCR_PROCESSOR_NUMBER, Cpu); /* Set the initial stack and idle thread as well */ LoaderBlock->KernelStack = (ULONG_PTR)P0BootStack; LoaderBlock->Thread = (ULONG_PTR)&KiInitialThread; } /* Save the initial thread and stack */ InitialStack = LoaderBlock->KernelStack; InitialThread = (PKTHREAD)LoaderBlock->Thread; /* Clean the APC List Head */ InitializeListHead(&InitialThread->ApcState.ApcListHead[KernelMode]); /* Initialize the machine type */ KiInitializeMachineType(); /* Skip initial setup if this isn't the Boot CPU */ if (Cpu) goto AppCpuInit; /* Get GDT, IDT, PCR and TSS pointers */ KiGetMachineBootPointers(&Gdt, &Idt, &Pcr, &Tss); /* Setup the TSS descriptors and entries */ Ki386InitializeTss(Tss, Idt, Gdt); /* Initialize the PCR */ RtlZeroMemory(Pcr, PAGE_SIZE); KiInitializePcr(Cpu, Pcr, Idt, Gdt, Tss, InitialThread, (PVOID)KiDoubleFaultStack); /* Set us as the current process */ InitialThread->ApcState.Process = &KiInitialProcess.Pcb; /* Clear DR6/7 to cleanup bootloader debugging */ __writefsdword(KPCR_TEB, 0); __writefsdword(KPCR_DR6, 0); __writefsdword(KPCR_DR7, 0); /* Setup the IDT */ KeInitExceptions(); /* Load Ring 3 selectors for DS/ES */ Ke386SetDs(KGDT_R3_DATA | RPL_MASK); Ke386SetEs(KGDT_R3_DATA | RPL_MASK); /* Save NMI and double fault traps */ RtlCopyMemory(&NmiEntry, &Idt[2], sizeof(KIDTENTRY)); RtlCopyMemory(&DoubleFaultEntry, &Idt[8], sizeof(KIDTENTRY)); /* Copy kernel's trap handlers */ RtlCopyMemory(Idt, (PVOID)KiIdtDescriptor.Base, KiIdtDescriptor.Limit + 1); /* Restore NMI and double fault */ RtlCopyMemory(&Idt[2], &NmiEntry, sizeof(KIDTENTRY)); RtlCopyMemory(&Idt[8], &DoubleFaultEntry, sizeof(KIDTENTRY)); AppCpuInit: /* Loop until we can release the freeze lock */ do { /* Loop until execution can continue */ while (*(volatile PKSPIN_LOCK*)&KiFreezeExecutionLock == (PVOID)1); } while(InterlockedBitTestAndSet((PLONG)&KiFreezeExecutionLock, 0)); /* Setup CPU-related fields */ __writefsdword(KPCR_NUMBER, Cpu); __writefsdword(KPCR_SET_MEMBER, 1 << Cpu); __writefsdword(KPCR_SET_MEMBER_COPY, 1 << Cpu); __writefsdword(KPCR_PRCB_SET_MEMBER, 1 << Cpu); /* Initialize the Processor with HAL */ HalInitializeProcessor(Cpu, KeLoaderBlock); /* Set active processors */ KeActiveProcessors |= __readfsdword(KPCR_SET_MEMBER); KeNumberProcessors++; /* Check if this is the boot CPU */ if (!Cpu) { /* Initialize debugging system */ KdInitSystem(0, KeLoaderBlock); /* Check for break-in */ if (KdPollBreakIn()) DbgBreakPointWithStatus(DBG_STATUS_CONTROL_C); } /* Raise to HIGH_LEVEL */ KfRaiseIrql(HIGH_LEVEL); /* Switch to new kernel stack and start kernel bootstrapping */ KiSwitchToBootStack(InitialStack & ~3); }