2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/kd/kdio.c
5 * PURPOSE: NT Kernel Debugger Input/Output Functions
7 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES ******************************************************************/
15 /* GLOBALS *******************************************************************/
17 #define KdpBufferSize (1024 * 512)
18 BOOLEAN KdpLoggingEnabled
= FALSE
;
19 PCHAR KdpDebugBuffer
= NULL
;
20 volatile ULONG KdpCurrentPosition
= 0;
21 volatile ULONG KdpFreeBytes
= 0;
22 KSPIN_LOCK KdpDebugLogSpinLock
;
23 KEVENT KdpLoggerThreadEvent
;
24 HANDLE KdpLogFileHandle
;
26 KSPIN_LOCK KdpSerialSpinLock
;
27 KD_PORT_INFORMATION SerialPortInfo
= { DEFAULT_DEBUG_PORT
, DEFAULT_DEBUG_BAUD_RATE
, 0 };
29 /* Current Port in use. FIXME: Do we support more then one? */
32 /* DEBUG LOG FUNCTIONS *******************************************************/
36 KdpLoggerThread(PVOID Context
)
41 KdpLoggingEnabled
= TRUE
;
45 KeWaitForSingleObject(&KdpLoggerThreadEvent
, 0, KernelMode
, FALSE
, NULL
);
48 end
= KdpCurrentPosition
;
50 beg
= (end
+ num
) % KdpBufferSize
;
51 num
= KdpBufferSize
- num
;
59 NtWriteFile(KdpLogFileHandle
, NULL
, NULL
, NULL
, &Iosb
,
60 KdpDebugBuffer
+ beg
, num
, NULL
, NULL
);
64 NtWriteFile(KdpLogFileHandle
, NULL
, NULL
, NULL
, &Iosb
,
65 KdpDebugBuffer
+ beg
, KdpBufferSize
- beg
, NULL
, NULL
);
67 NtWriteFile(KdpLogFileHandle
, NULL
, NULL
, NULL
, &Iosb
,
68 KdpDebugBuffer
, end
, NULL
, NULL
);
71 (VOID
)InterlockedExchangeAddUL(&KdpFreeBytes
, num
);
77 KdpPrintToLogFile(PCH String
,
83 if (KdpDebugBuffer
== NULL
) return;
85 /* Acquire the printing spinlock without waiting at raised IRQL */
88 /* Wait when the spinlock becomes available */
89 while (!KeTestSpinLock(&KdpDebugLogSpinLock
));
91 /* Spinlock was free, raise IRQL */
92 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
94 /* Try to get the spinlock */
95 if (KeTryToAcquireSpinLockAtDpcLevel(&KdpDebugLogSpinLock
))
98 /* Someone else got the spinlock, lower IRQL back */
102 beg
= KdpCurrentPosition
;
104 if (StringLength
< num
)
109 end
= (beg
+ num
) % KdpBufferSize
;
110 KdpCurrentPosition
= end
;
115 RtlCopyMemory(KdpDebugBuffer
+ beg
, String
, num
);
119 RtlCopyMemory(KdpDebugBuffer
+ beg
, String
, KdpBufferSize
- beg
);
120 RtlCopyMemory(KdpDebugBuffer
, String
+ KdpBufferSize
- beg
, end
);
124 /* Release spinlock */
125 KiReleaseSpinLock(&KdpDebugLogSpinLock
);
128 KeLowerIrql(OldIrql
);
130 /* Signal the logger thread */
131 if (OldIrql
<= DISPATCH_LEVEL
&& KdpLoggingEnabled
)
132 KeSetEvent(&KdpLoggerThreadEvent
, 0, FALSE
);
137 KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable
,
141 UNICODE_STRING FileName
;
142 OBJECT_ATTRIBUTES ObjectAttributes
;
143 IO_STATUS_BLOCK Iosb
;
147 if (!KdpDebugMode
.File
) return;
151 KdComPortInUse
= NULL
;
153 /* Write out the functions that we support for now */
154 DispatchTable
->KdpInitRoutine
= KdpInitDebugLog
;
155 DispatchTable
->KdpPrintRoutine
= KdpPrintToLogFile
;
157 /* Register as a Provider */
158 InsertTailList(&KdProviders
, &DispatchTable
->KdProvidersList
);
161 else if (BootPhase
== 1)
163 /* Allocate a buffer for debug log */
164 KdpDebugBuffer
= ExAllocatePool(NonPagedPool
, KdpBufferSize
);
165 KdpFreeBytes
= KdpBufferSize
;
167 /* Initialize spinlock */
168 KeInitializeSpinLock(&KdpDebugLogSpinLock
);
170 /* Display separator + ReactOS version at start of the debug log */
171 DPRINT1("---------------------------------------------------------------\n");
172 DPRINT1("ReactOS "KERNEL_VERSION_STR
" (Build "KERNEL_VERSION_BUILD_STR
")\n");
174 else if (BootPhase
== 2)
176 HalDisplayString("\n File log debugging enabled\n\n");
178 else if (BootPhase
== 3)
180 /* Setup the log name */
181 RtlInitUnicodeString(&FileName
, L
"\\SystemRoot\\debug.log");
182 InitializeObjectAttributes(&ObjectAttributes
,
188 /* Create the log file */
189 Status
= NtCreateFile(&KdpLogFileHandle
,
190 FILE_APPEND_DATA
| SYNCHRONIZE
,
194 FILE_ATTRIBUTE_NORMAL
,
197 FILE_WRITE_THROUGH
| FILE_SYNCHRONOUS_IO_NONALERT
,
201 if (!NT_SUCCESS(Status
)) return;
203 KeInitializeEvent(&KdpLoggerThreadEvent
, SynchronizationEvent
, TRUE
);
205 /* Create the logger thread */
206 Status
= PsCreateSystemThread(&ThreadHandle
,
214 if (!NT_SUCCESS(Status
)) return;
217 NtSetInformationThread(ThreadHandle
,
224 /* SERIAL FUNCTIONS **********************************************************/
228 KdpSerialDebugPrint(LPSTR Message
,
232 PCHAR pch
= (PCHAR
) Message
;
234 /* Acquire the printing spinlock without waiting at raised IRQL */
237 /* Wait when the spinlock becomes available */
238 while (!KeTestSpinLock(&KdpSerialSpinLock
));
240 /* Spinlock was free, raise IRQL */
241 KeRaiseIrql(HIGH_LEVEL
, &OldIrql
);
243 /* Try to get the spinlock */
244 if (KeTryToAcquireSpinLockAtDpcLevel(&KdpSerialSpinLock
))
247 /* Someone else got the spinlock, lower IRQL back */
248 KeLowerIrql(OldIrql
);
251 /* Output the message */
256 KdPortPutByteEx(&SerialPortInfo
, '\r');
258 KdPortPutByteEx(&SerialPortInfo
, *pch
);
262 /* Release spinlock */
263 KiReleaseSpinLock(&KdpSerialSpinLock
);
266 KeLowerIrql(OldIrql
);
271 KdpSerialInit(PKD_DISPATCH_TABLE DispatchTable
,
274 if (!KdpDebugMode
.Serial
) return;
278 /* Write out the functions that we support for now */
279 DispatchTable
->KdpInitRoutine
= KdpSerialInit
;
280 DispatchTable
->KdpPrintRoutine
= KdpSerialDebugPrint
;
282 /* Initialize the Port */
283 if (!KdPortInitializeEx(&SerialPortInfo
, 0, 0))
285 KdpDebugMode
.Serial
= FALSE
;
288 KdComPortInUse
= (PUCHAR
)(ULONG_PTR
)SerialPortInfo
.BaseAddress
;
290 /* Initialize spinlock */
291 KeInitializeSpinLock(&KdpSerialSpinLock
);
293 /* Register as a Provider */
294 InsertTailList(&KdProviders
, &DispatchTable
->KdProvidersList
);
296 /* Display separator + ReactOS version at start of the debug log */
297 DPRINT1("-----------------------------------------------------\n");
298 DPRINT1("ReactOS "KERNEL_VERSION_STR
" (Build "KERNEL_VERSION_BUILD_STR
")\n");
299 DPRINT1("Command Line: %s\n", KeLoaderBlock
->LoadOptions
);
300 DPRINT1("ARC Paths: %s %s %s %s\n", KeLoaderBlock
->ArcBootDeviceName
,
301 KeLoaderBlock
->NtHalPathName
,
302 KeLoaderBlock
->ArcHalDeviceName
,
303 KeLoaderBlock
->NtBootPathName
);
305 else if (BootPhase
== 2)
307 HalDisplayString("\n Serial debugging enabled\n\n");
311 /* SCREEN FUNCTIONS **********************************************************/
315 KdpScreenPrint(LPSTR Message
,
319 HalDisplayString(Message
);
324 KdpScreenInit(PKD_DISPATCH_TABLE DispatchTable
,
327 if (!KdpDebugMode
.Screen
) return;
331 /* Write out the functions that we support for now */
332 DispatchTable
->KdpInitRoutine
= KdpScreenInit
;
333 DispatchTable
->KdpPrintRoutine
= KdpScreenPrint
;
335 /* Register as a Provider */
336 InsertTailList(&KdProviders
, &DispatchTable
->KdProvidersList
);
338 else if (BootPhase
== 2)
340 HalDisplayString("\n Screen debugging enabled\n\n");
344 /* GENERAL FUNCTIONS *********************************************************/
348 KdpPrintString(LPSTR String
,
351 PLIST_ENTRY CurrentEntry
;
352 PKD_DISPATCH_TABLE CurrentTable
;
354 if (!KdpDebugMode
.Value
) return 0;
356 /* Call the registered handlers */
357 CurrentEntry
= KdProviders
.Flink
;
358 while (CurrentEntry
!= &KdProviders
)
360 /* Get the current table */
361 CurrentTable
= CONTAINING_RECORD(CurrentEntry
,
366 CurrentTable
->KdpPrintRoutine(String
, Length
);
369 CurrentEntry
= CurrentEntry
->Flink
;
372 /* Call the Wrapper Routine */
373 if (WrapperTable
.KdpPrintRoutine
)
374 WrapperTable
.KdpPrintRoutine(String
, Length
);
376 /* Return the Length */