ReactOS PowerPC WIP. This will be edited and merged, and likely shrunk.
[reactos.git] / reactos / ntoskrnl / kd / kdmain.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel
4 * FILE: ntoskrnl/kd/kdinit.c
5 * PURPOSE: Kernel Debugger Initializtion
6 *
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
8 */
9
10 #include <ntoskrnl.h>
11 #define NDEBUG
12 #include <internal/debug.h>
13
14 /* VARIABLES ***************************************************************/
15
16 BOOLEAN KdDebuggerEnabled = FALSE;
17 BOOLEAN KdEnteredDebugger = FALSE;
18 BOOLEAN KdDebuggerNotPresent = TRUE;
19 BOOLEAN KiEnableTimerWatchdog = FALSE;
20 ULONG KiBugCheckData;
21 BOOLEAN KdpBreakPending;
22 VOID STDCALL PspDumpThreads(BOOLEAN SystemThreads);
23
24 typedef struct
25 {
26 ULONG ComponentId;
27 ULONG Level;
28 } KD_COMPONENT_DATA;
29 #define MAX_KD_COMPONENT_TABLE_ENTRIES 128
30 KD_COMPONENT_DATA KdComponentTable[MAX_KD_COMPONENT_TABLE_ENTRIES];
31 ULONG KdComponentTableEntries = 0;
32
33 /* PRIVATE FUNCTIONS *********************************************************/
34
35 ULONG
36 STDCALL
37 KdpServiceDispatcher(ULONG Service,
38 PVOID Buffer1,
39 ULONG Buffer1Length)
40 {
41 ULONG Result = 0;
42
43 switch (Service)
44 {
45 case BREAKPOINT_PRINT: /* DbgPrint */
46 Result = KdpPrintString(Buffer1, Buffer1Length);
47 break;
48
49 #ifdef DBG
50 case TAG('R', 'o', 's', ' '): /* ROS-INTERNAL */
51 {
52 switch ((ULONG)Buffer1)
53 {
54 case DumpNonPagedPool:
55 MiDebugDumpNonPagedPool(FALSE);
56 break;
57
58 case ManualBugCheck:
59 KEBUGCHECK(MANUALLY_INITIATED_CRASH);
60 break;
61
62 case DumpNonPagedPoolStats:
63 MiDebugDumpNonPagedPoolStats(FALSE);
64 break;
65
66 case DumpNewNonPagedPool:
67 MiDebugDumpNonPagedPool(TRUE);
68 break;
69
70 case DumpNewNonPagedPoolStats:
71 MiDebugDumpNonPagedPoolStats(TRUE);
72 break;
73
74 case DumpAllThreads:
75 PspDumpThreads(TRUE);
76 break;
77
78 case DumpUserThreads:
79 PspDumpThreads(FALSE);
80 break;
81
82 case EnterDebugger:
83 DbgBreakPoint();
84 break;
85
86 default:
87 break;
88 }
89 }
90 #endif
91 default:
92 HalDisplayString ("Invalid debug service call!\n");
93 break;
94 }
95
96 return Result;
97 }
98
99 KD_CONTINUE_TYPE
100 STDCALL
101 KdpEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
102 KPROCESSOR_MODE PreviousMode,
103 PCONTEXT Context,
104 PKTRAP_FRAME TrapFrame,
105 BOOLEAN FirstChance,
106 BOOLEAN Gdb)
107 {
108 /* Get out of here if the Debugger isn't enabled */
109 if (!KdDebuggerEnabled) return kdHandleException;
110
111 /* FIXME:
112 * Right now, the GDB wrapper seems to handle exceptions differntly
113 * from KDGB and both are called at different times, while the GDB
114 * one is only called once and that's it. I don't really have the knowledge
115 * to fix the GDB stub, so until then, we'll be using this hack
116 */
117 if (Gdb)
118 {
119 /* Call the registered wrapper */
120 if (WrapperInitRoutine) return WrapperTable.
121 KdpExceptionRoutine(ExceptionRecord,
122 Context,
123 TrapFrame);
124 }
125
126 /* Call KDBG if available */
127 return KdbEnterDebuggerException(ExceptionRecord,
128 PreviousMode,
129 Context,
130 TrapFrame,
131 FirstChance);
132 }
133
134 /* PUBLIC FUNCTIONS *********************************************************/
135
136 /*
137 * @implemented
138 */
139 VOID
140 STDCALL
141 KdDisableDebugger(VOID)
142 {
143 KIRQL OldIrql;
144
145 /* Raise IRQL */
146 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
147
148 /* TODO: Disable any breakpoints */
149
150 /* Disable the Debugger */
151 KdDebuggerEnabled = FALSE;
152
153 /* Lower the IRQL */
154 KeLowerIrql(OldIrql);
155 }
156
157 /*
158 * @implemented
159 */
160 VOID
161 STDCALL
162 KdEnableDebugger(VOID)
163 {
164 KIRQL OldIrql;
165
166 /* Raise IRQL */
167 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
168
169 /* TODO: Re-enable any breakpoints */
170
171 /* Enable the Debugger */
172 KdDebuggerEnabled = TRUE;
173
174 /* Lower the IRQL */
175 KeLowerIrql(OldIrql);
176 }
177
178 /*
179 * @implemented
180 */
181 BOOLEAN
182 STDCALL
183 KdPollBreakIn(VOID)
184 {
185 return KdpBreakPending;
186 }
187
188 /*
189 * @implemented
190 */
191 VOID
192 STDCALL
193 KeEnterKernelDebugger(VOID)
194 {
195 HalDisplayString("\n\n *** Entered kernel debugger ***\n");
196
197 /* Set the Variable */
198 KdEnteredDebugger = TRUE;
199
200 /* Halt the CPU */
201 #ifdef _M_IX86
202 for (;;) Ke386HaltProcessor();
203 #elif defined(_M_PPC)
204 for (;;);
205 #endif
206 }
207
208 /*
209 * @unimplemented
210 */
211 NTSTATUS
212 STDCALL
213 KdPowerTransition(ULONG PowerState)
214 {
215 UNIMPLEMENTED;
216 return STATUS_NOT_IMPLEMENTED;
217 }
218
219 NTSTATUS
220 STDCALL
221 NtQueryDebugFilterState(IN ULONG ComponentId,
222 IN ULONG Level)
223 {
224 unsigned int i;
225
226 /* convert Level to mask if it isn't already one */
227 if ( Level < 32 )
228 Level = 1 << Level;
229
230 for ( i = 0; i < KdComponentTableEntries; i++ )
231 {
232 if ( ComponentId == KdComponentTable[i].ComponentId )
233 {
234 if ( Level & KdComponentTable[i].Level )
235 return TRUE;
236 break;
237 }
238 }
239 return FALSE;
240 }
241
242 NTSTATUS
243 STDCALL
244 NtSetDebugFilterState(IN ULONG ComponentId,
245 IN ULONG Level,
246 IN BOOLEAN State)
247 {
248 unsigned int i;
249 for ( i = 0; i < KdComponentTableEntries; i++ )
250 {
251 if ( ComponentId == KdComponentTable[i].ComponentId )
252 break;
253 }
254 if ( i == KdComponentTableEntries )
255 {
256 if ( i == MAX_KD_COMPONENT_TABLE_ENTRIES )
257 return STATUS_INVALID_PARAMETER_1;
258 ++KdComponentTableEntries;
259 KdComponentTable[i].ComponentId = ComponentId;
260 KdComponentTable[i].Level = 0;
261 }
262 if ( State )
263 KdComponentTable[i].Level |= Level;
264 else
265 KdComponentTable[i].Level &= ~Level;
266 return STATUS_SUCCESS;
267 }
268
269 /* EOF */