2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdinit.c
5 * PURPOSE: KD64 Initialization Code
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ******************************************************************/
15 /* FUNCTIONS *****************************************************************/
19 KdRegisterDebuggerDataBlock(IN ULONG Tag
,
20 IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader
,
24 PLIST_ENTRY NextEntry
;
25 PDBGKD_DEBUG_DATA_HEADER64 CurrentHeader
;
27 /* Acquire the Data Lock */
28 KeAcquireSpinLock(&KdpDataSpinLock
, &OldIrql
);
30 /* Loop the debugger data list */
31 NextEntry
= KdpDebuggerDataListHead
.Flink
;
32 while (NextEntry
!= &KdpDebuggerDataListHead
)
34 /* Get the header for this entry */
35 CurrentHeader
= CONTAINING_RECORD(NextEntry
,
36 DBGKD_DEBUG_DATA_HEADER64
,
39 /* Move to the next one */
40 NextEntry
= NextEntry
->Flink
;
42 /* Check if we already have this data block */
43 if ((CurrentHeader
== DataHeader
) || (CurrentHeader
->OwnerTag
== Tag
))
45 /* Release the lock and fail */
46 KeReleaseSpinLock(&KdpDataSpinLock
, OldIrql
);
51 /* Setup the header */
52 DataHeader
->OwnerTag
= Tag
;
53 DataHeader
->Size
= Size
;
55 /* Insert it into the list and release the lock */
56 InsertTailList(&KdpDebuggerDataListHead
, (PLIST_ENTRY
)&DataHeader
->List
);
57 KeReleaseSpinLock(&KdpDataSpinLock
, OldIrql
);
63 KdInitSystem(IN ULONG BootPhase
,
64 IN PLOADER_PARAMETER_BLOCK LoaderBlock
)
67 LPSTR CommandLine
, DebugLine
;
68 ANSI_STRING ImageName
;
69 PLDR_DATA_TABLE_ENTRY LdrEntry
;
70 PLIST_ENTRY NextEntry
;
74 /* Check if this is Phase 1 */
77 /* Just query the performance counter */
78 KeQueryPerformanceCounter(&KdPerformanceCounterRate
);
82 /* Check if we already initialized once */
83 if (KdDebuggerEnabled
) return TRUE
;
85 /* Set the Debug Routine as the Stub for now */
86 KiDebugRoutine
= KdpStub
;
88 /* Disable break after symbol load for now */
89 KdBreakAfterSymbolLoad
= FALSE
;
91 /* Check if the Debugger Data Block was already initialized */
92 if (!KdpDebuggerDataListHead
.Flink
)
94 /* It wasn't...Initialize the KD Data Listhead */
95 InitializeListHead(&KdpDebuggerDataListHead
);
97 /* Register the Debugger Data Block */
98 KdRegisterDebuggerDataBlock(KDBG_TAG
,
99 &KdDebuggerDataBlock
.Header
,
100 sizeof(KdDebuggerDataBlock
));
102 /* Fill out the KD Version Block */
103 KdVersionBlock
.MajorVersion
= (USHORT
)(NtBuildNumber
>> 28);
104 KdVersionBlock
.MinorVersion
= (USHORT
)(NtBuildNumber
& 0xFFFF);
107 /* This is an MP Build */
108 KdVersionBlock
.Flags
|= DBGKD_VERS_FLAG_MP
;
111 /* Save Pointers to Loaded Module List and Debugger Data */
112 KdVersionBlock
.PsLoadedModuleList
= (ULONG64
)&PsLoadedModuleList
;
113 KdVersionBlock
.DebuggerDataList
= (ULONG64
)&KdpDebuggerDataListHead
;
115 /* Set protocol limits */
116 KdVersionBlock
.MaxStateChange
= DbgKdMaximumStateChange
-
117 DbgKdMinimumStateChange
;
118 KdVersionBlock
.MaxManipulate
= DbgKdMaximumManipulate
-
119 DbgKdMinimumManipulate
;
120 KdVersionBlock
.Unused
[0] = 0;
122 /* Link us in the KPCR */
123 KeGetPcr()->KdVersionBlock
= &KdVersionBlock
;
126 /* Check if we have a loader block */
129 /* Save the Kernel Base */
130 KdVersionBlock
.KernBase
= (ULONG64
)LoaderBlock
->KernelStack
;
132 /* Check if we have a command line */
133 CommandLine
= LoaderBlock
->LoadOptions
;
137 _strupr(CommandLine
);
139 /* Assume we'll disable KD */
142 /* Check for CRASHDEBUG and NODEBUG */
143 if (strstr(CommandLine
, "CRASHDEBUG")) KdPitchDebugger
= FALSE
;
144 if (strstr(CommandLine
, "NODEBUG")) KdPitchDebugger
= TRUE
;
146 /* Check if DEBUG was on */
147 DebugLine
= strstr(CommandLine
, "DEBUG");
153 /* Check if there was additional data */
154 if (DebugLine
[5] == '=')
156 /* FIXME: Check for NOUMEX, DISABLE, AUTOENABLE */
162 /* No command line options? Disable debugger by default */
163 KdPitchDebugger
= TRUE
;
169 /* Called from a bugcheck...Save the Kernel Base */
170 KdVersionBlock
.KernBase
= PsNtosImageBase
;
172 /* Unconditionally enable KD */
176 /* Set the Kernel Base in the Data Block */
177 KdDebuggerDataBlock
.KernBase
= KdVersionBlock
.KernBase
;
179 /* Initialize the debugger if requested */
180 if ((EnableKd
) && (NT_SUCCESS(KdDebuggerInitialize0(LoaderBlock
))))
182 /* Now set our real KD routine */
183 KiDebugRoutine
= KdpTrap
;
185 /* Check if we've already initialized our structures */
186 if (!KdpDebuggerStructuresInitialized
)
188 /* Set the Debug Switch Routine and Retries*/
189 KdpContext
.KdpDefaultRetries
= 20;
190 KiDebugSwitchRoutine
= KdpSwitchProcessor
;
192 /* Initialize the Time Slip DPC */
193 KeInitializeDpc(&KdpTimeSlipDpc
, KdpTimeSlipDpcRoutine
, NULL
);
194 KeInitializeTimer(&KdpTimeSlipTimer
);
195 ExInitializeWorkItem(&KdpTimeSlipWorkItem
, KdpTimeSlipWork
, NULL
);
197 /* First-time initialization done! */
198 KdpDebuggerStructuresInitialized
= TRUE
;
201 /* Initialize the timer */
202 KdTimerStart
.QuadPart
= 0;
204 /* Officially enable KD */
205 KdPitchDebugger
= FALSE
;
206 KdDebuggerEnabled
= TRUE
;
208 /* Let user-mode know that it's enabled as well */
209 //#undef KdDebuggerEnabled
210 //SharedUserData->KdDebuggerEnabled = TRUE;
211 //#define KdDebuggerEnabled _KdDebuggerEnabled
213 /* Check if we have a loader block */
216 /* Loop boot images */
217 NextEntry
= LoaderBlock
->LoadOrderListHead
.Flink
;
219 while ((NextEntry
!= &LoaderBlock
->LoadOrderListHead
) && (i
< 2))
221 /* Get the image entry */
222 LdrEntry
= CONTAINING_RECORD(NextEntry
,
223 LDR_DATA_TABLE_ENTRY
,
226 /* Generate the image name */
228 /* Load symbols for image */
229 RtlInitAnsiString(&ImageName
, NameBuffer
);
230 DbgLoadImageSymbols(&ImageName
, LdrEntry
->DllBase
, -1);
232 /* Go to the next entry */
233 NextEntry
= NextEntry
->Flink
;
238 /* Check for incoming breakin and break on symbol load if we have it*/
239 KdBreakAfterSymbolLoad
= KdPollBreakIn();
243 /* Disable debugger */
244 KdDebuggerNotPresent
= TRUE
;
247 /* Return initialized */