KSPIN_LOCK BugCheckCallbackLock;
ULONG KeBugCheckActive, KeBugCheckOwner;
LONG KeBugCheckOwnerRecursionCount;
-PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
+PMESSAGE_RESOURCE_DATA KiBugCodeMessages;
ULONG KeBugCheckCount = 1;
ULONG KiHardwareTrigger;
PUNICODE_STRING KiBugCheckDriver;
ULONG_PTR KiBugCheckData[5];
+PKNMI_HANDLER_CALLBACK KiNmiCallbackListHead;
+KSPIN_LOCK KiNmiCallbackListLock;
/* Bugzilla Reporting */
UNICODE_STRING KeRosProcessorName, KeRosBiosDate, KeRosBiosVersion;
PVOID
NTAPI
-KiPcToFileHeader(IN PVOID Eip,
+KiPcToFileHeader(IN PVOID Pc,
OUT PLDR_DATA_TABLE_ENTRY *LdrEntry,
IN BOOLEAN DriversOnly,
OUT PBOOLEAN InKernel)
{
ULONG i = 0;
- PVOID ImageBase, EipBase = NULL;
+ PVOID ImageBase, PcBase = NULL;
PLDR_DATA_TABLE_ENTRY Entry;
PLIST_ENTRY ListHead, NextEntry;
ImageBase = Entry->DllBase;
/* Check if this is the right one */
- if (((ULONG_PTR)Eip >= (ULONG_PTR)Entry->DllBase) &&
- ((ULONG_PTR)Eip < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
+ if (((ULONG_PTR)Pc >= (ULONG_PTR)Entry->DllBase) &&
+ ((ULONG_PTR)Pc < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
{
/* Return this entry */
*LdrEntry = Entry;
- EipBase = ImageBase;
+ PcBase = ImageBase;
/* Check if this was a kernel or HAL entry */
if (i <= 2) *InKernel = TRUE;
}
/* Return the base address */
- return EipBase;
+ return PcBase;
}
BOOLEAN
PVOID
NTAPI
-KiRosPcToUserFileHeader(IN PVOID Eip,
+KiRosPcToUserFileHeader(IN PVOID Pc,
OUT PLDR_DATA_TABLE_ENTRY *LdrEntry)
{
- PVOID ImageBase, EipBase = NULL;
+ PVOID ImageBase, PcBase = NULL;
PLDR_DATA_TABLE_ENTRY Entry;
PLIST_ENTRY ListHead, NextEntry;
ImageBase = Entry->DllBase;
/* Check if this is the right one */
- if (((ULONG_PTR)Eip >= (ULONG_PTR)Entry->DllBase) &&
- ((ULONG_PTR)Eip < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
+ if (((ULONG_PTR)Pc >= (ULONG_PTR)Entry->DllBase) &&
+ ((ULONG_PTR)Pc < ((ULONG_PTR)Entry->DllBase + Entry->SizeOfImage)))
{
/* Return this entry */
*LdrEntry = Entry;
- EipBase = ImageBase;
+ PcBase = ImageBase;
break;
}
}
}
/* Return the base address */
- return EipBase;
+ return PcBase;
}
USHORT
return (USHORT)i;
}
-#ifndef _M_AMD64
+
VOID
FASTCALL
KeRosDumpStackFrameArray(IN PULONG Frames,
ULONG i, Addr;
BOOLEAN InSystem;
PVOID p;
- PLDR_DATA_TABLE_ENTRY LdrEntry;
+
+ /* GCC complaints that it may be used uninitialized */
+ PLDR_DATA_TABLE_ENTRY LdrEntry = NULL;
/* Loop them */
for (i = 0; i < FrameCount; i++)
}
}
}
-#endif
VOID
NTAPI
NTAPI
KiInitializeBugCheck(VOID)
{
- PRTL_MESSAGE_RESOURCE_DATA BugCheckData;
+ PMESSAGE_RESOURCE_DATA BugCheckData;
LDR_RESOURCE_INFO ResourceInfo;
PIMAGE_RESOURCE_DATA_ENTRY ResourceDataEntry;
NTSTATUS Status;
for (i = 0; i < IdOffset; i++)
{
/* Advance in the Entries */
- MessageEntry += ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->
+ MessageEntry += ((PMESSAGE_RESOURCE_ENTRY)MessageEntry)->
Length;
}
/* Get the final Code */
- BugCode = ((PRTL_MESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
+ BugCode = (PCHAR)((PMESSAGE_RESOURCE_ENTRY)MessageEntry)->Text;
i = strlen(BugCode);
/* Handle newlines */
NTAPI
KiBugCheckDebugBreak(IN ULONG StatusCode)
{
- /* If KDBG isn't connected, freeze the CPU, otherwise, break */
- if (KdDebuggerNotPresent) for (;;) KeArchHaltProcessor();
- DbgBreakPointWithStatus(StatusCode);
+ /*
+ * Wrap this in SEH so we don't crash if
+ * there is no debugger or if it disconnected
+ */
+DoBreak:
+ _SEH2_TRY
+ {
+ /* Breakpoint */
+ DbgBreakPointWithStatus(StatusCode);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ /* No debugger, halt the CPU */
+ HalHaltSystem();
+ }
+ _SEH2_END;
+
+ /* Break again if this wasn't first try */
+ if (StatusCode != DBG_STATUS_BUGCHECK_FIRST) goto DoBreak;
}
PCHAR
&InSystem);
if (!ImageBase)
{
- /* Driver wasn't found, check for unloaded driver */
- DriverName = NULL; // FIXME: ROS can't
- if (!DriverName) continue;
-
- /* Convert the driver name */
- ImageBase = (PVOID)Parameters[i];
- ConversionRoutine(DriverName, AnsiName, sizeof(AnsiName));
+ /* FIXME: Add code to check for unloaded drivers */
+ DPRINT1("Potentially unloaded driver!\n");
+ continue;
}
else
{
/* Show the technical Data */
sprintf(AnsiName,
- "\r\n\r\n*** STOP: 0x%p (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
- (PVOID)KiBugCheckData[0],
+ "\r\n\r\n*** STOP: 0x%08lX (0x%p,0x%p,0x%p,0x%p)\r\n\r\n",
+ KiBugCheckData[0],
(PVOID)KiBugCheckData[1],
(PVOID)KiBugCheckData[2],
(PVOID)KiBugCheckData[3],
CHAR AnsiName[128];
BOOLEAN IsSystem, IsHardError = FALSE, Reboot = FALSE;
PCHAR HardErrCaption = NULL, HardErrMessage = NULL;
- PVOID Eip = NULL, Memory;
+ PVOID Pc = NULL, Memory;
PVOID DriverBase;
PLDR_DATA_TABLE_ENTRY LdrEntry;
PULONG_PTR HardErrorParameters;
/* Check if this is a kernel-mode exception */
case KERNEL_MODE_EXCEPTION_NOT_HANDLED:
- //case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
+ case SYSTEM_THREAD_EXCEPTION_NOT_HANDLED:
case KMODE_EXCEPTION_NOT_HANDLED:
/* Use the generic text message */
if (BugCheckParameter3) TrapFrame = (PVOID)BugCheckParameter3;
}
- /* Check if we got one now and if we need to get EIP */
+ /* Check if we got one now and if we need to get the Program Counter */
if ((TrapFrame) &&
(BugCheckCode != KERNEL_MODE_EXCEPTION_NOT_HANDLED))
{
-#ifdef _M_IX86
- /* Get EIP */
- Eip = (PVOID)TrapFrame->Eip;
-#elif defined(_M_PPC)
- Eip = (PVOID)TrapFrame->Dr0; /* srr0 */
-#endif
+ /* Get the Program Counter */
+ Pc = (PVOID)KeGetTrapFramePc(TrapFrame);
}
break;
* and provide a more detailed analysis. For now, we don't.
*/
- /* Eip is in parameter 4 */
- Eip = (PVOID)BugCheckParameter4;
+ /* Program Counter is in parameter 4 */
+ Pc = (PVOID)BugCheckParameter4;
/* Get the driver base */
- DriverBase = KiPcToFileHeader(Eip, &LdrEntry, FALSE, &IsSystem);
+ DriverBase = KiPcToFileHeader(Pc,
+ &LdrEntry,
+ FALSE,
+ &IsSystem);
if (IsSystem)
{
/*
KiBugCheckData[0] = DRIVER_IRQL_NOT_LESS_OR_EQUAL;
}
- /* Clear EIP so we don't look it up later */
- Eip = NULL;
+ /* Clear Pc so we don't look it up later */
+ Pc = NULL;
break;
/* Hard error */
/* Check if we have a frame now */
if (TrapFrame)
{
-#ifdef _M_IX86
- /* Get EIP */
- Eip = (PVOID)TrapFrame->Eip;
- KiBugCheckData[3] = (ULONG)Eip;
-#elif defined(_M_PPC)
- Eip = (PVOID)TrapFrame->Dr0; /* srr0 */
- KiBugCheckData[3] = (ULONG)Eip;
-#endif
+ /* Get the Program Counter */
+ Pc = (PVOID)KeGetTrapFramePc(TrapFrame);
+ KiBugCheckData[3] = (ULONG_PTR)Pc;
/* Find out if was in the kernel or drivers */
- DriverBase = KiPcToFileHeader(Eip,
+ DriverBase = KiPcToFileHeader(Pc,
&LdrEntry,
FALSE,
&IsSystem);
/* Check if the driver forgot to unlock pages */
case DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS:
- /* EIP is in parameter 1 */
- Eip = (PVOID)BugCheckParameter1;
+ /* Program Counter is in parameter 1 */
+ Pc = (PVOID)BugCheckParameter1;
break;
/* Check if the driver consumed too many PTEs */
}
else
{
- /* Do we have an EIP? */
- if (Eip)
+ /* Do we have a Program Counter? */
+ if (Pc)
{
/* Dump image name */
KiDumpParameterImages(AnsiName,
- (PULONG_PTR)&Eip,
+ (PULONG_PTR)&Pc,
1,
KeBugCheckUnicodeToAnsi);
}
/* Check if we need to save the context for KD */
#ifdef _WINKD_
- if (!KdPitchDebugger) KdDebuggerDataBlock.SavedContext = (ULONG)&Context;
+ if (!KdPitchDebugger) KdDebuggerDataBlock.SavedContext = (ULONG_PTR)&Context;
#endif
/* Check if a debugger is connected */
if (i != (LONG)KeGetCurrentProcessorNumber())
{
/* Send the IPI and give them one second to catch up */
- KiIpiSendRequest(1 << i, IPI_FREEZE);
+ KiIpiSend(1 << i, IPI_FREEZE);
KeStallExecutionProcessor(1000000);
}
}
#endif
/* Display the BSOD */
- KeLowerIrql(APC_LEVEL); // This is a nastier hack than any ever before
KiDisplayBlueScreen(MessageId,
IsHardError,
HardErrCaption,
HardErrMessage,
AnsiName);
- KeRaiseIrql(HIGH_LEVEL, &OldIrql);
/* Check if the debugger is disabled but we can enable it */
if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
/* FIXME: Support Triage Dump */
- /* Write the crash dump */
- MmDumpToPagingFile(KiBugCheckData[4],
- KiBugCheckData[0],
- KiBugCheckData[1],
- KiBugCheckData[2],
- KiBugCheckData[3],
- TrapFrame);
+ /* FIXME: Write the crash dump */
}
else
{
}
else if (KeBugCheckOwnerRecursionCount > 2)
{
- /* Halt the CPU */
- for (;;) KeArchHaltProcessor();
+ /* Halt execution */
+ while (TRUE);
}
}
if (Reboot)
{
/* Unload symbols */
- DbgUnLoadImageSymbols(NULL, NtCurrentProcess(), 0);
+ DbgUnLoadImageSymbols(NULL, (PVOID)MAXULONG_PTR, 0);
HalReturnToFirmware(HalRebootRoutine);
}
/* Attempt to break in the debugger (otherwise halt CPU) */
KiBugCheckDebugBreak(DBG_STATUS_BUGCHECK_SECOND);
+
+ /* Shouldn't get here */
+ while (TRUE);
+}
+
+BOOLEAN
+NTAPI
+KiHandleNmi(VOID)
+{
+ BOOLEAN Handled = FALSE;
+ PKNMI_HANDLER_CALLBACK NmiData;
+
+ //
+ // Parse the list of callbacks
+ //
+ NmiData = KiNmiCallbackListHead;
+ while (NmiData)
+ {
+ //
+ // Save if this callback has handled it -- all it takes is one
+ //
+ Handled |= NmiData->Callback(NmiData->Context, Handled);
+ NmiData = NmiData->Next;
+ }
+
+ //
+ // Has anyone handled this?
+ //
+ return Handled;
}
/* PUBLIC FUNCTIONS **********************************************************/
return Status;
}
-/*
- * @unimplemented
- */
-NTSTATUS
-NTAPI
-KeDeregisterNmiCallback(PVOID Handle)
-{
- UNIMPLEMENTED;
- return STATUS_UNSUCCESSFUL;
-}
-
/*
* @implemented
*/
}
/*
- * @unimplemented
+ * @implemented
*/
PVOID
NTAPI
KeRegisterNmiCallback(IN PNMI_CALLBACK CallbackRoutine,
IN PVOID Context)
{
+ KIRQL OldIrql;
+ PKNMI_HANDLER_CALLBACK NmiData, Next;
+ ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
+
+ //
+ // Allocate NMI callback data
+ //
+ NmiData = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(KNMI_HANDLER_CALLBACK),
+ 'IMNK');
+ if (!NmiData) return NULL;
+
+ //
+ // Fill in the information
+ //
+ NmiData->Callback = CallbackRoutine;
+ NmiData->Context = Context;
+ NmiData->Handle = NmiData;
+
+ //
+ // Insert it into NMI callback list
+ //
+ KiAcquireNmiListLock(&OldIrql);
+ NmiData->Next = KiNmiCallbackListHead;
+ Next = InterlockedCompareExchangePointer(&KiNmiCallbackListHead,
+ NmiData,
+ NmiData->Next);
+ ASSERT(Next == NmiData->Next);
+ KiReleaseNmiListLock(OldIrql);
+
+ //
+ // Return the opaque "handle"
+ //
+ return NmiData->Handle;
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+KeDeregisterNmiCallback(PVOID Handle)
+{
UNIMPLEMENTED;
- return NULL;
+ return STATUS_UNSUCCESSFUL;
}
/*
}
}
- /* Bugcheck */
+ /* Break in the debugger */
KiBugCheckDebugBreak(DBG_STATUS_FATAL);
}