ReactOS 0.4.16-dev-122-g325d74c
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
14#define NDEBUG
15#include <debug.h>
16
17#undef KdD0Transition
18#undef KdD3Transition
19#undef KdSave
20#undef KdRestore
21
22/* PUBLIC FUNCTIONS *********************************************************/
23
24static VOID
26 _In_ PCSTR p1)
27{
28#define CONST_STR_LEN(x) (sizeof(x)/sizeof(x[0]) - 1)
29
30 while (p1 && *p1)
31 {
32 /* Skip leading whitespace */
33 while (*p1 == ' ') ++p1;
34
35 if (!_strnicmp(p1, "KDSERIAL", CONST_STR_LEN("KDSERIAL")))
36 {
37 p1 += CONST_STR_LEN("KDSERIAL");
40 }
41 else if (!_strnicmp(p1, "KDNOECHO", CONST_STR_LEN("KDNOECHO")))
42 {
43 p1 += CONST_STR_LEN("KDNOECHO");
45 }
46
47 /* Move on to the next option */
48 p1 = strchr(p1, ' ');
49 }
50}
51
52static PCHAR
54 _In_ PCHAR Currentp2)
55{
56 PCHAR p1, p2 = Currentp2;
58
59 /* Check for Screen Debugging */
60 if (!_strnicmp(p2, "SCREEN", 6))
61 {
62 /* Enable It */
63 p2 += 6;
65 }
66 /* Check for Serial Debugging */
67 else if (!_strnicmp(p2, "COM", 3))
68 {
69 /* Check for a valid Serial Port */
70 p2 += 3;
71 if (*p2 != ':')
72 {
73 Value = (ULONG)atol(p2);
74 if (Value > 0 && Value < 5)
75 {
76 /* Valid port found, enable Serial Debugging */
78
79 /* Set the port to use */
81 }
82 }
83 else
84 {
85 Value = strtoul(p2 + 1, NULL, 0);
86 if (Value)
87 {
91 }
92 }
93 }
94 /* Check for Debug Log Debugging */
95 else if (!_strnicmp(p2, "FILE", 4))
96 {
97 /* Enable It */
98 p2 += 4;
100 if (*p2 == ':')
101 {
102 p2++;
103 p1 = p2;
104 while (*p2 != '\0' && *p2 != ' ') p2++;
107 }
108 }
109
110 return p2;
111}
112
114NTAPI
117{
118 PCHAR CommandLine, Port = NULL;
119 ULONG i;
121
122 if (LoaderBlock)
123 {
124 /* Check if we have a command line */
125 CommandLine = LoaderBlock->LoadOptions;
126 if (CommandLine)
127 {
128 /* Upcase it */
129 _strupr(CommandLine);
130
131 /* Get terminal settings */
132 KdpGetTerminalSettings(CommandLine);
133
134 /* Get the port */
135 Port = strstr(CommandLine, "DEBUGPORT");
136 }
137 }
138
139 /* Check if we got the /DEBUGPORT parameter(s) */
140 while (Port)
141 {
142 /* Move past the actual string, to reach the port*/
143 Port += sizeof("DEBUGPORT") - 1;
144
145 /* Now get past any spaces and skip the equal sign */
146 while (*Port == ' ') Port++;
147 Port++;
148
149 /* Get the debug mode and wrapper */
151 Port = strstr(Port, "DEBUGPORT");
152 }
153
154 /* Use serial port then */
155 if (KdpDebugMode.Value == 0)
157
158 /* Call the providers at Phase 0 */
159 for (i = 0; i < RTL_NUMBER_OF(DispatchTable); i++)
160 {
161 DispatchTable[i].InitStatus = InitRoutines[i](&DispatchTable[i], 0);
162 Success = (Success || NT_SUCCESS(DispatchTable[i].InitStatus));
163 }
164
165 /* Return success if at least one of the providers succeeded */
167}
168
169
177static VOID
178NTAPI
183{
184 PLIST_ENTRY CurrentEntry;
185 PKD_DISPATCH_TABLE CurrentTable;
186 PKDP_INIT_ROUTINE KdpInitRoutine;
187 ULONG BootPhase = (Count + 1); // Do BootPhase >= 2
188 BOOLEAN ScheduleReinit = FALSE;
189
191
192 DPRINT("*** KD %sREINITIALIZATION - Phase %d ***\n",
193 Context ? "" : "BOOT ", BootPhase);
194
195 /* Call the registered providers */
196 for (CurrentEntry = KdProviders.Flink;
197 CurrentEntry != &KdProviders; NOTHING)
198 {
199 /* Get the provider */
200 CurrentTable = CONTAINING_RECORD(CurrentEntry,
202 KdProvidersList);
203 /* Go to the next entry (the Init routine may unlink us) */
204 CurrentEntry = CurrentEntry->Flink;
205
206 /* Call it if it requires a reinitialization */
207 if (CurrentTable->KdpInitRoutine)
208 {
209 /* Get the initialization routine and reset it */
210 KdpInitRoutine = CurrentTable->KdpInitRoutine;
211 CurrentTable->KdpInitRoutine = NULL;
212 CurrentTable->InitStatus = KdpInitRoutine(CurrentTable, BootPhase);
213 DPRINT("KdpInitRoutine(%p) returned 0x%08lx\n",
214 CurrentTable, CurrentTable->InitStatus);
215
216 /* Check whether it needs to be reinitialized again */
217 ScheduleReinit = (ScheduleReinit || CurrentTable->KdpInitRoutine);
218 }
219 }
220
221 DPRINT("ScheduleReinit: %s\n", ScheduleReinit ? "TRUE" : "FALSE");
222 if (ScheduleReinit)
223 {
224 /*
225 * Determine when to reinitialize.
226 * If Context == NULL, we are doing a boot-driver reinitialization.
227 * It is initially done once (Count == 1), and is rescheduled once
228 * after all other boot drivers get loaded (Count == 2).
229 * If further reinitialization is needed, switch to system-driver
230 * reinitialization and do it again, not more than twice.
231 */
232 if (Count <= 1)
233 {
236 (PVOID)FALSE);
237 }
238 else if (Count <= 3)
239 {
242 (PVOID)TRUE);
243 }
244 else
245 {
246 /* Too late, no more reinitializations! */
247 DPRINT("Cannot reinitialize anymore!\n");
248 ScheduleReinit = FALSE;
249 }
250 }
251
252 if (!ScheduleReinit)
253 {
254 /* All the necessary reinitializations are done,
255 * the driver object is not needed anymore. */
258 }
259}
260
265static NTSTATUS
266NTAPI
270{
272
273 /* Register for reinitialization after the other drivers are loaded */
276 (PVOID)FALSE);
277
278 /* Set the driver as initialized */
280 return STATUS_SUCCESS;
281}
282
289
300static NTSTATUS
301NTAPI
303{
304 static BOOLEAN InitCalled = FALSE;
306 UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"\\Driver\\KdDriver");
307
309
310 /* Ensure we are not called more than once */
311 if (_InterlockedCompareExchange8((char*)&InitCalled, TRUE, FALSE) != FALSE)
312 return STATUS_SUCCESS;
313
314 /* Create the driver */
315 Status = IoCreateDriver(&DriverName, KdpDriverEntry);
316 if (!NT_SUCCESS(Status))
317 DPRINT1("IoCreateDriver failed: 0x%08lx\n", Status);
318 /* Ignore any failure from IoCreateDriver(). If it fails, no I/O-related
319 * initialization will happen (no file log debugging, etc.). */
320
321 /* Finally, restore and call the original HalInitPnpDriver() */
324}
325
327NTAPI
330{
331 PLIST_ENTRY CurrentEntry;
332 PKD_DISPATCH_TABLE CurrentTable;
333 PKDP_INIT_ROUTINE KdpInitRoutine;
335 BOOLEAN ReinitForPhase2 = FALSE;
336
337 /* Make space for the displayed providers' signons */
338 HalDisplayString("\r\n");
339
340 /* Call the registered providers */
341 for (CurrentEntry = KdProviders.Flink;
342 CurrentEntry != &KdProviders; NOTHING)
343 {
344 /* Get the provider */
345 CurrentTable = CONTAINING_RECORD(CurrentEntry,
347 KdProvidersList);
348 /* Go to the next entry (the Init routine may unlink us) */
349 CurrentEntry = CurrentEntry->Flink;
350
351 /* Get the initialization routine and reset it */
352 ASSERT(CurrentTable->KdpInitRoutine);
353 KdpInitRoutine = CurrentTable->KdpInitRoutine;
354 CurrentTable->KdpInitRoutine = NULL;
355
356 /* Call it */
357 CurrentTable->InitStatus = KdpInitRoutine(CurrentTable, 1);
358
359 /* Check whether it needs to be reinitialized for Phase 2 */
360 Success = (Success || NT_SUCCESS(CurrentTable->InitStatus));
361 ReinitForPhase2 = (ReinitForPhase2 || CurrentTable->KdpInitRoutine);
362 }
363
364 /* Make space for the displayed providers' signons */
365 HalDisplayString("\r\n");
366
368
369 /* If we don't need to reinitialize providers for Phase 2, we are done */
370 if (!ReinitForPhase2)
371 {
372 /* Return success if at least one of them succeeded */
374 }
375
451 return STATUS_SUCCESS;
452}
453
455NTAPI
457{
458 /* Nothing to do */
459 return STATUS_SUCCESS;
460}
461
463NTAPI
465{
466 /* Nothing to do */
467 return STATUS_SUCCESS;
468}
469
471NTAPI
473 _In_ BOOLEAN SleepTransition)
474{
475 /* Nothing to do */
476 return STATUS_SUCCESS;
477}
478
480NTAPI
482 _In_ BOOLEAN SleepTransition)
483{
484 /* Nothing to do */
485 return STATUS_SUCCESS;
486}
487
488/* EOF */
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
char * strstr(char *String1, char *String2)
Definition: utclib.c:653
UINT32 strtoul(const char *String, char **Terminator, UINT32 Base)
Definition: utclib.c:696
char * strchr(const char *String, int ch)
Definition: utclib.c:501
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 _strnicmp(_String1, _String2, _MaxCount)
Definition: compat.h:23
#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:35
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
_Check_return_ long __cdecl atol(_In_z_ const char *_Str)
#define FLG_STOP_ON_EXCEPTION
Definition: pstypes.h:56
#define NOTHING
Definition: input_list.c:10
char _InterlockedCompareExchange8(_Interlocked_operand_ char volatile *_Destination, char _Exchange, char _Comparand)
ULONG SerialPortNumber
Definition: kdio.c:39
LIST_ENTRY KdProviders
Definition: kdio.c:47
KDP_DEBUG_MODE KdpDebugMode
Definition: kdio.c:46
PKDP_INIT_ROUTINE InitRoutines[KdMax]
Definition: kdio.c:50
NTSTATUS(NTAPI * PKDP_INIT_ROUTINE)(_In_ struct _KD_DISPATCH_TABLE *DispatchTable, _In_ ULONG BootPhase)
Definition: kd.h:9
ANSI_STRING KdpLogFileName
Definition: kdio.c:36
CPPORT SerialPortInfo
Definition: kdio.c:40
static PCHAR KdpGetDebugMode(_In_ PCHAR Currentp2)
Definition: kdmain.c:53
NTSTATUS NTAPI KdD0Transition(VOID)
Definition: kdmain.c:456
NTSTATUS NTAPI KdD3Transition(VOID)
Definition: kdmain.c:464
NTSTATUS NTAPI KdDebuggerInitialize0(_In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: kdmain.c:115
static VOID NTAPI KdpDriverReinit(_In_ PDRIVER_OBJECT DriverObject, _In_opt_ PVOID Context, _In_ ULONG Count)
Reinitialization routine. DRIVER_REINITIALIZE.
Definition: kdmain.c:179
static VOID KdpGetTerminalSettings(_In_ PCSTR p1)
Definition: kdmain.c:25
#define CONST_STR_LEN(x)
static NTSTATUS NTAPI KdpDriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
Entry point for the auxiliary driver. DRIVER_INITIALIZE.
Definition: kdmain.c:267
NTSTATUS NTAPI KdRestore(_In_ BOOLEAN SleepTransition)
Definition: kdmain.c:481
static pHalInitPnpDriver orgHalInitPnpDriver
Hooked HalInitPnpDriver() callback. It is initially set by the HAL when HalInitSystem(0,...
Definition: kdmain.c:288
static NTSTATUS NTAPI KdpInitDriver(VOID)
HalInitPnpDriver() callback hook installed by KdDebuggerInitialize1().
Definition: kdmain.c:302
NTSTATUS NTAPI KdSave(_In_ BOOLEAN SleepTransition)
Definition: kdmain.c:472
NTSTATUS NTAPI KdDebuggerInitialize1(_In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: kdmain.c:328
ULONG KdbDebugState
Definition: kdterminal.c:32
@ KD_DEBUG_KDSERIAL
Definition: kdterminal.h:36
@ KD_DEBUG_KDNOECHO
Definition: kdterminal.h:37
#define ASSERT(a)
Definition: mode.c:44
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
int Count
Definition: noreturn.cpp:7
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
ULONG NtGlobalFlag
Definition: init.c:54
VOID NTAPI IoRegisterDriverReinitialization(IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE ReinitRoutine, IN PVOID Context)
Definition: driver.c:1797
NTSTATUS NTAPI IoCreateDriver(_In_opt_ PUNICODE_STRING DriverName, _In_ PDRIVER_INITIALIZE InitializationFunction)
Definition: driver.c:1576
VOID NTAPI IoDeleteDriver(_In_ PDRIVER_OBJECT DriverObject)
Definition: driver.c:1756
VOID NTAPI IoRegisterBootDriverReinitialization(IN PDRIVER_OBJECT DriverObject, IN PDRIVER_REINITIALIZE ReinitRoutine, IN PVOID Context)
Definition: driver.c:1768
#define L(x)
Definition: ntvdm.h:50
VOID NTAPI ObMakeTemporaryObject(IN PVOID ObjectBody)
Definition: oblife.c:1449
_CRTIMP char *__cdecl _strupr(_Inout_z_ char *_String)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
USHORT MaximumLength
Definition: env_spec_w32.h:377
PUCHAR Address
Definition: cportlib.h:29
UCHAR File
Definition: kd.h:102
UCHAR Screen
Definition: kd.h:100
UCHAR Serial
Definition: kd.h:101
ULONG Value
Definition: kd.h:106
PKDP_INIT_ROUTINE KdpInitRoutine
Definition: kd.h:114
NTSTATUS InitStatus
Definition: kd.h:116
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
#define RTL_CONSTANT_STRING(s)
Definition: tunneltest.c:14
#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
char * PCHAR
Definition: typedefs.h:51
#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:114
#define HalInitPnpDriver
Definition: haltypes.h:300
#define DRVO_INITIALIZED
Definition: iotypes.h:4470