Copy makefile
[reactos.git] / reactos / ntoskrnl / ke / bug.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/bug.c
6 * PURPOSE: Graceful system shutdown if a bug is detected
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 * Phillip Susi
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ntoskrnl.h>
15 #include <ntos/bootvid.h>
16 #include <internal/debug.h>
17 #include "../../hal/halx86/include/hal.h"
18
19 /* GLOBALS ******************************************************************/
20
21 static LIST_ENTRY BugcheckCallbackListHead = {NULL,NULL};
22 static ULONG InBugCheck;
23
24 /* FUNCTIONS *****************************************************************/
25
26 VOID INIT_FUNCTION
27 KeInitializeBugCheck(VOID)
28 {
29 InitializeListHead(&BugcheckCallbackListHead);
30 InBugCheck = 0;
31 }
32
33 /*
34 * @implemented
35 */
36 BOOLEAN STDCALL
37 KeDeregisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord)
38 {
39 /* Check the Current State */
40 if (CallbackRecord->State == BufferInserted) {
41 CallbackRecord->State = BufferEmpty;
42 RemoveEntryList(&CallbackRecord->Entry);
43 return TRUE;
44 }
45
46 /* The callback wasn't registered */
47 return FALSE;
48 }
49
50 /*
51 * @implemented
52 */
53 BOOLEAN STDCALL
54 KeRegisterBugCheckCallback(PKBUGCHECK_CALLBACK_RECORD CallbackRecord,
55 PKBUGCHECK_CALLBACK_ROUTINE CallbackRoutine,
56 PVOID Buffer,
57 ULONG Length,
58 PUCHAR Component)
59 {
60
61 /* Check the Current State first so we don't double-register */
62 if (CallbackRecord->State == BufferEmpty) {
63 CallbackRecord->Length = Length;
64 CallbackRecord->Buffer = Buffer;
65 CallbackRecord->Component = Component;
66 CallbackRecord->CallbackRoutine = CallbackRoutine;
67 CallbackRecord->State = BufferInserted;
68 InsertTailList(&BugcheckCallbackListHead, &CallbackRecord->Entry);
69
70 return TRUE;
71 }
72
73 /* The Callback was already registered */
74 return(FALSE);
75 }
76
77 VOID STDCALL
78 KeBugCheckWithTf(ULONG BugCheckCode,
79 ULONG BugCheckParameter1,
80 ULONG BugCheckParameter2,
81 ULONG BugCheckParameter3,
82 ULONG BugCheckParameter4,
83 PKTRAP_FRAME Tf)
84 {
85 PRTL_MESSAGE_RESOURCE_ENTRY Message;
86 NTSTATUS Status;
87 ULONG Mask;
88 KIRQL OldIrql;
89
90 /* Make sure we're switching back to the blue screen and print messages on it */
91 HalReleaseDisplayOwnership();
92 if (0 == (KdDebugState & KD_DEBUG_GDB))
93 {
94 KdDebugState |= KD_DEBUG_SCREEN;
95 }
96
97 Ke386DisableInterrupts();
98 DebugLogDumpMessages();
99
100 if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
101 {
102 MmUnlockAddressSpace(MmGetKernelAddressSpace());
103 }
104
105 if (KeGetCurrentIrql() < DISPATCH_LEVEL)
106 {
107 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
108 }
109 DbgPrint("Bug detected (code %x param %x %x %x %x)\n",
110 BugCheckCode,
111 BugCheckParameter1,
112 BugCheckParameter2,
113 BugCheckParameter3,
114 BugCheckParameter4);
115
116 Status = RtlFindMessage((PVOID)KERNEL_BASE, //0xC0000000,
117 11, //RT_MESSAGETABLE,
118 0x09, //0x409,
119 BugCheckCode,
120 &Message);
121 if (NT_SUCCESS(Status))
122 {
123 if (Message->Flags == 0)
124 DbgPrint(" %s\n", Message->Text);
125 else
126 DbgPrint(" %S\n", (PWSTR)Message->Text);
127 }
128 else
129 {
130 DbgPrint(" No message text found!\n\n");
131 }
132 Mask = 1 << KeGetCurrentProcessorNumber();
133 if (InBugCheck & Mask)
134 {
135 #ifdef MP
136 DbgPrint("Recursive bug check on CPU%d, halting now\n", KeGetCurrentProcessorNumber());
137 /*
138 * FIXME:
139 * Send an ipi to all other processors which halt them too.
140 */
141 #else
142 DbgPrint("Recursive bug check halting now\n");
143 #endif
144 Ke386HaltProcessor();
145 }
146 /*
147 * FIXME:
148 * Use InterlockedOr or InterlockedBitSet.
149 */
150 InBugCheck |= Mask;
151 if (Tf != NULL)
152 {
153 KiDumpTrapFrame(Tf, BugCheckParameter1, BugCheckParameter2);
154 }
155 else
156 {
157 #if defined(__GNUC__)
158 KeDumpStackFrames((PULONG)__builtin_frame_address(0));
159 #elif defined(_MSC_VER)
160 __asm push ebp
161 __asm call KeDumpStackFrames
162 __asm add esp, 4
163 #else
164 #error Unknown compiler for inline assembler
165 #endif
166 }
167 MmDumpToPagingFile(BugCheckCode, BugCheckParameter1,
168 BugCheckParameter2, BugCheckParameter3,
169 BugCheckParameter4, Tf);
170
171 if (KdDebuggerEnabled)
172 {
173 Ke386EnableInterrupts();
174 DbgBreakPointNoBugCheck();
175 Ke386DisableInterrupts();
176 }
177
178 for (;;)
179 {
180 /*
181 * FIXME:
182 * Send an ipi to all other processors which halt them too.
183 */
184 Ke386HaltProcessor();
185 }
186 }
187
188 /*
189 * @implemented
190 */
191 VOID STDCALL
192 KeBugCheckEx(ULONG BugCheckCode,
193 ULONG BugCheckParameter1,
194 ULONG BugCheckParameter2,
195 ULONG BugCheckParameter3,
196 ULONG BugCheckParameter4)
197 /*
198 * FUNCTION: Brings the system down in a controlled manner when an
199 * inconsistency that might otherwise cause corruption has been detected
200 * ARGUMENTS:
201 * BugCheckCode = Specifies the reason for the bug check
202 * BugCheckParameter[1-4] = Additional information about bug
203 * RETURNS: Doesn't
204 */
205 {
206 KeBugCheckWithTf(BugCheckCode, BugCheckParameter1, BugCheckParameter2,
207 BugCheckParameter3, BugCheckParameter4, NULL);
208 }
209
210 /*
211 * @implemented
212 */
213 VOID STDCALL
214 KeBugCheck(ULONG BugCheckCode)
215 /*
216 * FUNCTION: Brings the system down in a controlled manner when an
217 * inconsistency that might otherwise cause corruption has been detected
218 * ARGUMENTS:
219 * BugCheckCode = Specifies the reason for the bug check
220 * RETURNS: Doesn't
221 */
222 {
223 KeBugCheckEx(BugCheckCode, 0, 0, 0, 0);
224 }
225
226 /* EOF */