ReactOS 0.4.16-dev-2491-g3dc6630
kdmain.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Kernel Debugger Initialization
5 * COPYRIGHT: Copyright 2005 Alex Ionescu <alex.ionescu@reactos.org>
6 * Copyright 2020 Hervé Poussineau <hpoussin@reactos.org>
7 * Copyright 2023 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
8 */
9
10#include <ntoskrnl.h>
11#include "kd.h"
12#include "kdterminal.h"
13#include <cportlib/uartinfo.h>
14
15#define NDEBUG
16#include <debug.h>
17
18#undef KdD0Transition
19#undef KdD3Transition
20#undef KdSave
21#undef KdRestore
22
23/* PUBLIC FUNCTIONS *********************************************************/
24
25#define CONST_STR_LEN(x) (sizeof(x)/sizeof(x[0]) - 1)
26
27static VOID
29 _In_ PCSTR p1)
30{
31 while (p1 && *p1)
32 {
33 /* Skip leading whitespace */
34 while (*p1 == ' ') ++p1;
35
36 if (!_strnicmp(p1, "KDSERIAL", CONST_STR_LEN("KDSERIAL")))
37 {
38 p1 += CONST_STR_LEN("KDSERIAL");
41 }
42 else if (!_strnicmp(p1, "KDNOECHO", CONST_STR_LEN("KDNOECHO")))
43 {
44 p1 += CONST_STR_LEN("KDNOECHO");
46 }
47
48 /* Move on to the next option */
49 p1 = strchr(p1, ' ');
50 }
51}
52
53static PSTR
55 _In_ PCSTR DebugPort)
56{
57 PCSTR p2 = DebugPort;
59
60 /* Check for Screen Debugging */
61 if (!_strnicmp(p2, "SCREEN", CONST_STR_LEN("SCREEN")))
62 {
63 /* Enable it */
64 p2 += CONST_STR_LEN("SCREEN");
66 }
67 /* Check for Serial Debugging */
68 else if (!_strnicmp(p2, "COM", CONST_STR_LEN("COM")))
69 {
70 /* Check for a valid serial port */
71 p2 += CONST_STR_LEN("COM");
72 if (*p2 != ':')
73 {
74 Value = (ULONG)atol(p2);
75 if (Value > 0 && Value <= MAX_COM_PORTS)
76 {
77 /* Valid port found, enable it and set the port to use */
80 }
81 }
82 else
83 {
84 Value = strtoul(p2 + 1, NULL, 0);
85 if (Value)
86 {
87 /* Valid port found, enable it and set its address */
91 }
92 }
93 }
94 /* Check for Debug Log Debugging */
95 else if (!_strnicmp(p2, "FILE", CONST_STR_LEN("FILE")))
96 {
97 /* Enable it */
98 p2 += CONST_STR_LEN("FILE");
100 if (*p2 == ':')
101 {
102 PCSTR p1 = ++p2;
103 while (*p2 && *p2 != ' ') ++p2;
106 }
107 }
108
109 return (PSTR)p2;
110}
111
113NTAPI
116{
117 PSTR CommandLine, Port = NULL, BaudRate = NULL;
118 ULONG i;
120
121 if (LoaderBlock)
122 {
123 /* Check if we have a command line */
124 CommandLine = LoaderBlock->LoadOptions;
125 if (CommandLine)
126 {
127 /* Upcase it */
128 _strupr(CommandLine);
129
130 /* Get terminal settings */
131 KdpGetTerminalSettings(CommandLine);
132
133 /* Get the port and baud rate */
134 Port = strstr(CommandLine, "DEBUGPORT");
135 BaudRate = strstr(CommandLine, "BAUDRATE");
136 }
137 }
138
139 /* Check if we got DEBUGPORT parameters */
140 while (Port)
141 {
142 /* Move past the actual string and any spaces */
143 Port += CONST_STR_LEN("DEBUGPORT");
144 while (*Port == ' ') ++Port;
145 /* Skip the equals sign */
146 if (*Port) ++Port;
147
148 /* Get the debug mode and wrapper */
150 Port = strstr(Port, "DEBUGPORT");
151 }
152
153 /* If no debug port was set, fall back to serial port debugging */
154 if (KdpDebugMode.Value == 0)
156
157 /* Check if we got a baud rate */
158 if (BaudRate)
159 {
160 /* Move past the actual string and any spaces */
161 BaudRate += CONST_STR_LEN("BAUDRATE");
162 while (*BaudRate == ' ') ++BaudRate;
163
164 /* Make sure we have a rate */
165 if (*BaudRate)
166 {
167 /* Read and set it */
168 ULONG Value = (ULONG)atol(BaudRate + 1);
170 }
171 }
172
173 /* Call the providers at Phase 0 */
174 for (i = 0; i < RTL_NUMBER_OF(DispatchTable); i++)
175 {
176 DispatchTable[i].InitStatus = InitRoutines[i](&DispatchTable[i], 0);
177 Success = (Success || NT_SUCCESS(DispatchTable[i].InitStatus));
178 }
179
180 /* Return success if at least one of the providers succeeded */
182}
183
184
192static VOID
193NTAPI
198{
199 PLIST_ENTRY CurrentEntry;
200 PKD_DISPATCH_TABLE CurrentTable;
201 PKDP_INIT_ROUTINE KdpInitRoutine;
202 ULONG BootPhase = (Count + 1); // Do BootPhase >= 2
203 BOOLEAN ScheduleReinit = FALSE;
204
206
207 DPRINT("*** KD %sREINITIALIZATION - Phase %d ***\n",
208 Context ? "" : "BOOT ", BootPhase);
209
210 /* Call the registered providers */
211 for (CurrentEntry = KdProviders.Flink;
212 CurrentEntry != &KdProviders; NOTHING)
213 {
214 /* Get the provider */
215 CurrentTable = CONTAINING_RECORD(CurrentEntry,
217 KdProvidersList);
218 /* Go to the next entry (the Init routine may unlink us) */
219 CurrentEntry = CurrentEntry->Flink;
220
221 /* Call it if it requires a reinitialization */
222 if (CurrentTable->KdpInitRoutine)
223 {
224 /* Get the initialization routine and reset it */
225 KdpInitRoutine = CurrentTable->KdpInitRoutine;
226 CurrentTable->KdpInitRoutine = NULL;
227 CurrentTable->InitStatus = KdpInitRoutine(CurrentTable, BootPhase);
228 DPRINT("KdpInitRoutine(%p) returned 0x%08lx\n",
229 CurrentTable, CurrentTable->InitStatus);
230
231 /* Check whether it needs to be reinitialized again */
232 ScheduleReinit = (ScheduleReinit || CurrentTable->KdpInitRoutine);
233 }
234 }
235
236 DPRINT("ScheduleReinit: %s\n", ScheduleReinit ? "TRUE" : "FALSE");
237 if (ScheduleReinit)
238 {
239 /*
240 * Determine when to reinitialize.
241 * If Context == NULL, we are doing a boot-driver reinitialization.
242 * It is initially done once (Count == 1), and is rescheduled once
243 * after all other boot drivers get loaded (Count == 2).
244 * If further reinitialization is needed, switch to system-driver
245 * reinitialization and do it again, not more than twice.
246 */
247 if (Count <= 1)
248 {
251 (PVOID)FALSE);
252 }
253 else if (Count <= 3)
254 {
257 (PVOID)TRUE);
258 }
259 else
260 {
261 /* Too late, no more reinitializations! */
262 DPRINT("Cannot reinitialize anymore!\n");
263 ScheduleReinit = FALSE;
264 }
265 }
266
267 if (!ScheduleReinit)
268 {
269 /* All the necessary reinitializations are done,
270 * the driver object is not needed anymore. */
273 }
274}
275
280static NTSTATUS
281NTAPI
285{
287
288 /* Register for reinitialization after the other drivers are loaded */
291 (PVOID)FALSE);
292
293 /* Set the driver as initialized */
295 return STATUS_SUCCESS;
296}
297
304
315static NTSTATUS
316NTAPI
318{
319 static BOOLEAN InitCalled = FALSE;
321 UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"\\Driver\\KdDriver");
322
324
325 /* Ensure we are not called more than once */
326 if (_InterlockedCompareExchange8((char*)&InitCalled, TRUE, FALSE) != FALSE)
327 return STATUS_SUCCESS;
328
329 /* Create the driver */
330 Status = IoCreateDriver(&DriverName, KdpDriverEntry);
331 if (!NT_SUCCESS(Status))
332 DPRINT1("IoCreateDriver failed: 0x%08lx\n", Status);
333 /* Ignore any failure from IoCreateDriver(). If it fails, no I/O-related
334 * initialization will happen (no file log debugging, etc.). */
335
336 /* Finally, restore and call the original HalInitPnpDriver() */
339}
340
342NTAPI
345{
346 PLIST_ENTRY CurrentEntry;
347 PKD_DISPATCH_TABLE CurrentTable;
348 PKDP_INIT_ROUTINE KdpInitRoutine;
350 BOOLEAN ReinitForPhase2 = FALSE;
351
352 /* Make space for the displayed providers' signons */
353 HalDisplayString("\r\n");
354
355 /* Call the registered providers */
356 for (CurrentEntry = KdProviders.Flink;
357 CurrentEntry != &KdProviders; NOTHING)
358 {
359 /* Get the provider */
360 CurrentTable = CONTAINING_RECORD(CurrentEntry,
362 KdProvidersList);
363 /* Go to the next entry (the Init routine may unlink us) */
364 CurrentEntry = CurrentEntry->Flink;
365
366 /* Get the initialization routine and reset it */
367 ASSERT(CurrentTable->KdpInitRoutine);
368 KdpInitRoutine = CurrentTable->KdpInitRoutine;
369 CurrentTable->KdpInitRoutine = NULL;
370
371 /* Call it */
372 CurrentTable->InitStatus = KdpInitRoutine(CurrentTable, 1);
373
374 /* Check whether it needs to be reinitialized for Phase 2 */
375 Success = (Success || NT_SUCCESS(CurrentTable->InitStatus));
376 ReinitForPhase2 = (ReinitForPhase2 || CurrentTable->KdpInitRoutine);
377 }
378
379 /* Make space for the displayed providers' signons */
380 HalDisplayString("\r\n");
381
383
384 /* If we don't need to reinitialize providers for Phase 2, we are done */
385 if (!ReinitForPhase2)
386 {
387 /* Return success if at least one of them succeeded */
389 }
390
466 return STATUS_SUCCESS;
467}
468
470NTAPI
472{
473 /* Nothing to do */
474 return STATUS_SUCCESS;
475}
476
478NTAPI
480{
481 /* Nothing to do */
482 return STATUS_SUCCESS;
483}
484
486NTAPI
488 _In_ BOOLEAN SleepTransition)
489{
490 /* Nothing to do */
491 return STATUS_SUCCESS;
492}
493
495NTAPI
497 _In_ BOOLEAN SleepTransition)
498{
499 /* Nothing to do */
500 return STATUS_SUCCESS;
501}
502
503/* EOF */
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
#define _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
_ACRTIMP __msvcrt_long __cdecl atol(const char *)
Definition: string.c:1782
_ACRTIMP __msvcrt_ulong __cdecl strtoul(const char *, char **, int)
Definition: string.c:1859
_ACRTIMP char *__cdecl strchr(const char *, int)
Definition: string.c:3286
_ACRTIMP char *__cdecl strstr(const char *, const char *)
Definition: string.c:3415
#define L(x)
Definition: resources.c:13
#define UlongToPtr(u)
Definition: config.h:106
#define InterlockedExchangePointer(Target, Value)
Definition: dshow.h:45
#define PASSIVE_LEVEL
Definition: env_spec_w32.h:693
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
@ Success
Definition: eventcreate.c:712
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
CPPORT Port[4]
Definition: headless.c:38
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
#define FLG_STOP_ON_EXCEPTION
Definition: pstypes.h:56
#define NOTHING
Definition: input_list.c:10
ULONG SerialPortNumber
Definition: kdio.c:40
LIST_ENTRY KdProviders
Definition: kdio.c:48
KDP_DEBUG_MODE KdpDebugMode
Definition: kdio.c:47
PKDP_INIT_ROUTINE InitRoutines[KdMax]
Definition: kdio.c:51
NTSTATUS(NTAPI * PKDP_INIT_ROUTINE)(_In_ struct _KD_DISPATCH_TABLE *DispatchTable, _In_ ULONG BootPhase)
Definition: kd.h:9
ANSI_STRING KdpLogFileName
Definition: kdio.c:37
CPPORT SerialPortInfo
Definition: kdio.c:41
NTSTATUS NTAPI KdD0Transition(VOID)
Definition: kdmain.c:471
NTSTATUS NTAPI KdD3Transition(VOID)
Definition: kdmain.c:479
NTSTATUS NTAPI KdDebuggerInitialize0(_In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: kdmain.c:114
static VOID NTAPI KdpDriverReinit(_In_ PDRIVER_OBJECT DriverObject, _In_opt_ PVOID Context, _In_ ULONG Count)
Reinitialization routine. DRIVER_REINITIALIZE.
Definition: kdmain.c:194
static VOID KdpGetTerminalSettings(_In_ PCSTR p1)
Definition: kdmain.c:28
#define CONST_STR_LEN(x)
Definition: kdmain.c:25
static NTSTATUS NTAPI KdpDriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
Entry point for the auxiliary driver. DRIVER_INITIALIZE.
Definition: kdmain.c:282
static PSTR KdpGetDebugMode(_In_ PCSTR DebugPort)
Definition: kdmain.c:54
NTSTATUS NTAPI KdRestore(_In_ BOOLEAN SleepTransition)
Definition: kdmain.c:496
static pHalInitPnpDriver orgHalInitPnpDriver
Hooked HalInitPnpDriver() callback. It is initially set by the HAL when HalInitSystem(0,...
Definition: kdmain.c:303
static NTSTATUS NTAPI KdpInitDriver(VOID)
HalInitPnpDriver() callback hook installed by KdDebuggerInitialize1().
Definition: kdmain.c:317
NTSTATUS NTAPI KdSave(_In_ BOOLEAN SleepTransition)
Definition: kdmain.c:487
NTSTATUS NTAPI KdDebuggerInitialize1(_In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: kdmain.c:343
ULONG KdbDebugState
Definition: kdterminal.c:32
@ KD_DEBUG_KDSERIAL
Definition: kdterminal.h:36
@ KD_DEBUG_KDNOECHO
Definition: kdterminal.h:37
#define MAX_COM_PORTS
Definition: machpc.c:29
#define ASSERT(a)
Definition: mode.c:44
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
int Count
Definition: noreturn.cpp:7
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
ULONG NtGlobalFlag
Definition: init.c:54
VOID NTAPI IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE ReinitRoutine, IN PVOID Context)
Definition: driver.c:1809
NTSTATUS NTAPI IoCreateDriver(_In_opt_ PUNICODE_STRING DriverName, _In_ PDRIVER_INITIALIZE InitializationFunction)
Definition: driver.c:1588
VOID NTAPI IoDeleteDriver(_In_ PDRIVER_OBJECT DriverObject)
Definition: driver.c:1768
VOID NTAPI IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE ReinitRoutine, IN PVOID Context)
Definition: driver.c:1780
VOID NTAPI ObMakeTemporaryObject(IN PVOID ObjectBody)
Definition: oblife.c:1449
_strupr
Definition: string.h:453
char _InterlockedCompareExchange8(_Interlocked_operand_ char volatile *_Destination, char _Exchange, char _Comparand)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
_In_ PVOID Context
Definition: storport.h:2269
USHORT MaximumLength
Definition: env_spec_w32.h:377
PUCHAR Address
Definition: cportlib.h:28
ULONG BaudRate
Definition: cportlib.h:29
UCHAR File
Definition: kd.h:100
UCHAR Screen
Definition: kd.h:98
UCHAR Serial
Definition: kd.h:99
ULONG Value
Definition: kd.h:104
PKDP_INIT_ROUTINE KdpInitRoutine
Definition: kd.h:112
NTSTATUS InitStatus
Definition: kd.h:114
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
char * PSTR
Definition: typedefs.h:51
#define NTAPI
Definition: typedefs.h:36
const char * PCSTR
Definition: typedefs.h:52
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_In_ PWDFDEVICE_INIT _In_ PWDF_PDO_EVENT_CALLBACKS DispatchTable
Definition: wdfpdo.h:248
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
NTSTATUS(NTAPI * pHalInitPnpDriver)(VOID)
Definition: haltypes.h:124
#define HalInitPnpDriver
Definition: haltypes.h:310
#define DRVO_INITIALIZED
Definition: iotypes.h:4473