-/*\r
- * PROJECT: ReactOS Kernel\r
- * LICENSE: GPL - See COPYING in the top level directory\r
- * FILE: ntoskrnl/kd64/kdinit.c\r
- * PURPOSE: KD64 Initialization Code\r
- * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)\r
- */\r
-\r
-/* INCLUDES ******************************************************************/\r
-\r
-#include <ntoskrnl.h>\r
-#define NDEBUG\r
-#include <debug.h>\r
-\r
-/* FUNCTIONS *****************************************************************/\r
-\r
-BOOLEAN\r
-NTAPI\r
-KdRegisterDebuggerDataBlock(IN ULONG Tag,\r
- IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader,\r
- IN ULONG Size)\r
-{\r
- KIRQL OldIrql;\r
- PLIST_ENTRY NextEntry;\r
- PDBGKD_DEBUG_DATA_HEADER64 CurrentHeader;\r
-\r
- /* Acquire the Data Lock */\r
- KeAcquireSpinLock(&KdpDataSpinLock, &OldIrql);\r
-\r
- /* Loop the debugger data list */\r
- NextEntry = KdpDebuggerDataListHead.Flink;\r
- while (NextEntry != &KdpDebuggerDataListHead)\r
- {\r
- /* Get the header for this entry */\r
- CurrentHeader = CONTAINING_RECORD(NextEntry,\r
- DBGKD_DEBUG_DATA_HEADER64,\r
- List);\r
-\r
- /* Move to the next one */\r
- NextEntry = NextEntry->Flink;\r
-\r
- /* Check if we already have this data block */\r
- if ((CurrentHeader == DataHeader) || (CurrentHeader->OwnerTag == Tag))\r
- {\r
- /* Release the lock and fail */\r
- KeReleaseSpinLock(&KdpDataSpinLock, OldIrql);\r
- return FALSE;\r
- }\r
- }\r
-\r
- /* Setup the header */\r
- DataHeader->OwnerTag = Tag;\r
- DataHeader->Size = Size;\r
-\r
- /* Insert it into the list and release the lock */\r
- InsertTailList(&KdpDebuggerDataListHead, (PLIST_ENTRY)&DataHeader->List);\r
- KeReleaseSpinLock(&KdpDataSpinLock, OldIrql);\r
- return TRUE;\r
-}\r
-\r
-BOOLEAN\r
-NTAPI\r
-KdInitSystem(IN ULONG BootPhase,\r
- IN PLOADER_PARAMETER_BLOCK LoaderBlock)\r
-{\r
- BOOLEAN EnableKd;\r
- LPSTR CommandLine, DebugLine;\r
- ANSI_STRING ImageName;\r
- PLDR_DATA_TABLE_ENTRY LdrEntry;\r
- PLIST_ENTRY NextEntry;\r
- ULONG i, j, Length;\r
- CHAR NameBuffer[256];\r
- PWCHAR Name;\r
-\r
- /* Check if this is Phase 1 */\r
- if (BootPhase)\r
- {\r
- /* Just query the performance counter */\r
- KeQueryPerformanceCounter(&KdPerformanceCounterRate);\r
- return TRUE;\r
- }\r
-\r
- /* Check if we already initialized once */\r
- if (KdDebuggerEnabled) return TRUE;\r
-\r
- /* Set the Debug Routine as the Stub for now */\r
- KiDebugRoutine = KdpStub;\r
-\r
- /* Disable break after symbol load for now */\r
- KdBreakAfterSymbolLoad = FALSE;\r
-\r
- /* Check if the Debugger Data Block was already initialized */\r
- if (!KdpDebuggerDataListHead.Flink)\r
- {\r
- /* It wasn't...Initialize the KD Data Listhead */\r
- InitializeListHead(&KdpDebuggerDataListHead);\r
-\r
- /* Register the Debugger Data Block */\r
- KdRegisterDebuggerDataBlock(KDBG_TAG,\r
- &KdDebuggerDataBlock.Header,\r
- sizeof(KdDebuggerDataBlock));\r
-\r
- /* Fill out the KD Version Block */\r
- KdVersionBlock.MajorVersion = (USHORT)(NtBuildNumber >> 28);\r
- KdVersionBlock.MinorVersion = (USHORT)(NtBuildNumber & 0xFFFF);\r
-\r
-#ifdef CONFIG_SMP\r
- /* This is an MP Build */\r
- KdVersionBlock.Flags |= DBGKD_VERS_FLAG_MP;\r
-#endif\r
-\r
- /* Save Pointers to Loaded Module List and Debugger Data */\r
- KdVersionBlock.PsLoadedModuleList = (ULONGLONG)(LONG_PTR)&PsLoadedModuleList;\r
- KdVersionBlock.DebuggerDataList = (ULONGLONG)(LONG_PTR)&KdpDebuggerDataListHead;\r
-\r
- /* Set protocol limits */\r
- KdVersionBlock.MaxStateChange = DbgKdMaximumStateChange -\r
- DbgKdMinimumStateChange;\r
- KdVersionBlock.MaxManipulate = DbgKdMaximumManipulate -\r
- DbgKdMinimumManipulate;\r
- KdVersionBlock.Unused[0] = 0;\r
-\r
- /* Link us in the KPCR */\r
- KeGetPcr()->KdVersionBlock = &KdVersionBlock;\r
- }\r
-\r
- /* Check if we have a loader block */\r
- if (LoaderBlock)\r
- {\r
- /* Get the image entry */\r
- LdrEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,\r
- LDR_DATA_TABLE_ENTRY,\r
- InLoadOrderLinks);\r
-\r
- /* Save the Kernel Base */\r
- PsNtosImageBase = (ULONG)LdrEntry->DllBase;\r
- KdVersionBlock.KernBase = (ULONGLONG)(LONG_PTR)LdrEntry->DllBase;\r
-\r
- /* Check if we have a command line */\r
- CommandLine = LoaderBlock->LoadOptions;\r
- if (CommandLine)\r
- {\r
- /* Upcase it */\r
- _strupr(CommandLine);\r
-\r
- /* Assume we'll disable KD */\r
- EnableKd = FALSE;\r
-\r
- /* Check for CRASHDEBUG and NODEBUG */\r
- if (strstr(CommandLine, "CRASHDEBUG")) KdPitchDebugger = FALSE;\r
- if (strstr(CommandLine, "NODEBUG")) KdPitchDebugger = TRUE;\r
-\r
- /* Check if DEBUG was on */\r
- DebugLine = strstr(CommandLine, "DEBUG");\r
- if (DebugLine)\r
- {\r
- /* Enable KD */\r
- EnableKd = TRUE;\r
-\r
- /* Check if there was additional data */\r
- if (DebugLine[5] == '=')\r
- {\r
- /* FIXME: Check for NOUMEX, DISABLE, AUTOENABLE */\r
- }\r
- }\r
- }\r
- else\r
- {\r
- /* No command line options? Disable debugger by default */\r
- KdPitchDebugger = TRUE;\r
- EnableKd = FALSE;\r
- }\r
- }\r
- else\r
- {\r
- /* Called from a bugcheck...Save the Kernel Base */\r
- KdVersionBlock.KernBase = (ULONGLONG)(LONG_PTR)PsNtosImageBase;\r
-\r
- /* Unconditionally enable KD */\r
- EnableKd = TRUE;\r
- }\r
-\r
- /* Set the Kernel Base in the Data Block */\r
- KdDebuggerDataBlock.KernBase = (ULONGLONG)(LONG_PTR)KdVersionBlock.KernBase;\r
-\r
- /* Initialize the debugger if requested */\r
- if ((EnableKd) && (NT_SUCCESS(KdDebuggerInitialize0(LoaderBlock))))\r
- {\r
- /* Now set our real KD routine */\r
- KiDebugRoutine = KdpTrap;\r
-\r
- /* Check if we've already initialized our structures */\r
- if (!KdpDebuggerStructuresInitialized)\r
- {\r
- /* Set the Debug Switch Routine and Retries*/\r
- KdpContext.KdpDefaultRetries = 20;\r
- KiDebugSwitchRoutine = KdpSwitchProcessor;\r
-\r
- /* Initialize the Time Slip DPC */\r
- KeInitializeDpc(&KdpTimeSlipDpc, KdpTimeSlipDpcRoutine, NULL);\r
- KeInitializeTimer(&KdpTimeSlipTimer);\r
- ExInitializeWorkItem(&KdpTimeSlipWorkItem, KdpTimeSlipWork, NULL);\r
-\r
- /* First-time initialization done! */\r
- KdpDebuggerStructuresInitialized = TRUE;\r
- }\r
-\r
- /* Initialize the timer */\r
- KdTimerStart.QuadPart = 0;\r
-\r
- /* Officially enable KD */\r
- KdPitchDebugger = FALSE;\r
- KdDebuggerEnabled = TRUE;\r
-\r
- /* Let user-mode know that it's enabled as well */\r
-#undef KdDebuggerEnabled\r
- SharedUserData->KdDebuggerEnabled = TRUE;\r
-#define KdDebuggerEnabled _KdDebuggerEnabled\r
-\r
- /* Check if we have a loader block */\r
- if (LoaderBlock)\r
- {\r
- /* Loop boot images */\r
- NextEntry = LoaderBlock->LoadOrderListHead.Flink;\r
- i = 0;\r
- while ((NextEntry != &LoaderBlock->LoadOrderListHead) && (i < 2))\r
- {\r
- /* Get the image entry */\r
- LdrEntry = CONTAINING_RECORD(NextEntry,\r
- LDR_DATA_TABLE_ENTRY,\r
- InLoadOrderLinks);\r
-\r
- /* Generate the image name */\r
- Name = LdrEntry->FullDllName.Buffer;\r
- Length = LdrEntry->FullDllName.Length / sizeof(WCHAR);\r
- j = 0;\r
- do\r
- {\r
- /* Do cheap Unicode to ANSI conversion */\r
- NameBuffer[j++] = (CHAR)*Name++;\r
- } while (j < Length);\r
-\r
- /* Null-terminate */\r
- NameBuffer[j] = ANSI_NULL;\r
-\r
- /* Load symbols for image */\r
- RtlInitAnsiString(&ImageName, NameBuffer);\r
- DbgLoadImageSymbols(&ImageName, LdrEntry->DllBase, -1);\r
-\r
- /* Go to the next entry */\r
- NextEntry = NextEntry->Flink;\r
- i++;\r
- }\r
- }\r
-\r
- /* Check for incoming breakin and break on symbol load if we have it*/\r
- KdBreakAfterSymbolLoad = KdPollBreakIn();\r
- }\r
- else\r
- {\r
- /* Disable debugger */\r
- KdDebuggerNotPresent = TRUE;\r
- }\r
-\r
- /* Return initialized */\r
- return TRUE;\r
-}\r
+/*
+ * PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
+ * FILE: ntoskrnl/kd64/kdinit.c
+ * PURPOSE: KD64 Initialization Code
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
+ */
+
+/* INCLUDES ******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* FUNCTIONS *****************************************************************/
+
+VOID
+NTAPI
+KdUpdateDataBlock(VOID)
+{
+ /* Update the KeUserCallbackDispatcher pointer */
+ KdDebuggerDataBlock.KeUserCallbackDispatcher =
+ (ULONG_PTR)KeUserCallbackDispatcher;
+}
+
+BOOLEAN
+NTAPI
+KdRegisterDebuggerDataBlock(IN ULONG Tag,
+ IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader,
+ IN ULONG Size)
+{
+ KIRQL OldIrql;
+ PLIST_ENTRY NextEntry;
+ PDBGKD_DEBUG_DATA_HEADER64 CurrentHeader;
+
+ /* Acquire the Data Lock */
+ KeAcquireSpinLock(&KdpDataSpinLock, &OldIrql);
+
+ /* Loop the debugger data list */
+ NextEntry = KdpDebuggerDataListHead.Flink;
+ while (NextEntry != &KdpDebuggerDataListHead)
+ {
+ /* Get the header for this entry */
+ CurrentHeader = CONTAINING_RECORD(NextEntry,
+ DBGKD_DEBUG_DATA_HEADER64,
+ List);
+
+ /* Move to the next one */
+ NextEntry = NextEntry->Flink;
+
+ /* Check if we already have this data block */
+ if ((CurrentHeader == DataHeader) || (CurrentHeader->OwnerTag == Tag))
+ {
+ /* Release the lock and fail */
+ KeReleaseSpinLock(&KdpDataSpinLock, OldIrql);
+ return FALSE;
+ }
+ }
+
+ /* Setup the header */
+ DataHeader->OwnerTag = Tag;
+ DataHeader->Size = Size;
+
+ /* Insert it into the list and release the lock */
+ InsertTailList(&KdpDebuggerDataListHead, (PLIST_ENTRY)&DataHeader->List);
+ KeReleaseSpinLock(&KdpDataSpinLock, OldIrql);
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+KdInitSystem(IN ULONG BootPhase,
+ IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ BOOLEAN EnableKd, DisableKdAfterInit = FALSE, BlockEnable;
+ LPSTR CommandLine, DebugLine, DebugOptionStart, DebugOptionEnd;
+ ANSI_STRING ImageName;
+ PLDR_DATA_TABLE_ENTRY LdrEntry;
+ PLIST_ENTRY NextEntry;
+ ULONG i, j, Length, DebugOptionLength;
+ CHAR NameBuffer[256];
+ PWCHAR Name;
+
+#if defined(__GNUC__)
+ /* Make gcc happy */
+ BlockEnable = FALSE;
+#endif
+
+ /* Check if this is Phase 1 */
+ if (BootPhase)
+ {
+ /* Just query the performance counter */
+ KeQueryPerformanceCounter(&KdPerformanceCounterRate);
+ return TRUE;
+ }
+
+ /* Check if we already initialized once */
+ if (KdDebuggerEnabled) return TRUE;
+
+ /* Set the Debug Routine as the Stub for now */
+ KiDebugRoutine = KdpStub;
+
+ /* Disable break after symbol load for now */
+ KdBreakAfterSymbolLoad = FALSE;
+
+ /* Check if the Debugger Data Block was already initialized */
+ if (!KdpDebuggerDataListHead.Flink)
+ {
+ /* It wasn't...Initialize the KD Data Listhead */
+ InitializeListHead(&KdpDebuggerDataListHead);
+
+ /* Register the Debugger Data Block */
+ KdRegisterDebuggerDataBlock(KDBG_TAG,
+ &KdDebuggerDataBlock.Header,
+ sizeof(KdDebuggerDataBlock));
+
+ /* Fill out the KD Version Block */
+ KdVersionBlock.MajorVersion = (USHORT)(NtBuildNumber >> 28);
+ KdVersionBlock.MinorVersion = (USHORT)(NtBuildNumber & 0xFFFF);
+
+#ifdef CONFIG_SMP
+ /* This is an MP Build */
+ KdVersionBlock.Flags |= DBGKD_VERS_FLAG_MP;
+#endif
+
+ /* Save Pointers to Loaded Module List and Debugger Data */
+ KdVersionBlock.PsLoadedModuleList = (ULONG64)(LONG_PTR)&PsLoadedModuleList;
+ KdVersionBlock.DebuggerDataList = (ULONG64)(LONG_PTR)&KdpDebuggerDataListHead;
+
+ /* Set protocol limits */
+ KdVersionBlock.MaxStateChange = DbgKdMaximumStateChange -
+ DbgKdMinimumStateChange;
+ KdVersionBlock.MaxManipulate = DbgKdMaximumManipulate -
+ DbgKdMinimumManipulate;
+ KdVersionBlock.Unused[0] = 0;
+
+ /* Link us in the KPCR */
+ KeGetPcr()->KdVersionBlock = &KdVersionBlock;
+ }
+
+ /* Check if we have a loader block */
+ if (LoaderBlock)
+ {
+ /* Get the image entry */
+ LdrEntry = CONTAINING_RECORD(LoaderBlock->LoadOrderListHead.Flink,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ /* Save the Kernel Base */
+ PsNtosImageBase = (ULONG_PTR)LdrEntry->DllBase;
+ KdVersionBlock.KernBase = (ULONG64)(LONG_PTR)LdrEntry->DllBase;
+
+ /* Check if we have a command line */
+ CommandLine = LoaderBlock->LoadOptions;
+ if (CommandLine)
+ {
+ /* Upcase it */
+ _strupr(CommandLine);
+
+ /* Assume we'll disable KD */
+ EnableKd = FALSE;
+
+ /* Check for CRASHDEBUG and NODEBUG */
+ if (strstr(CommandLine, "CRASHDEBUG")) KdPitchDebugger = FALSE;
+ if (strstr(CommandLine, "NODEBUG")) KdPitchDebugger = TRUE;
+
+ /* Check if DEBUG was on */
+ DebugLine = strstr(CommandLine, "DEBUG");
+ if (DebugLine)
+ {
+ /* Enable KD */
+ EnableKd = TRUE;
+
+ /* Check if there are any options */
+ if (DebugLine[5] == '=')
+ {
+ /* Save pointers */
+ DebugOptionStart = DebugOptionEnd = &DebugLine[6];
+
+ /* Scan the string for debug options */
+ for (;;)
+ {
+ /* Loop until we reach the end of the string */
+ while (*DebugOptionEnd != ANSI_NULL)
+ {
+ /* Check if this is a comma, a space or a tab */
+ if ((*DebugOptionEnd == ',') ||
+ (*DebugOptionEnd == ' ') ||
+ (*DebugOptionEnd == ' '))
+ {
+ /*
+ * We reached the end of the option or
+ * the end of the string, break out
+ */
+ break;
+ }
+ else
+ {
+ /* Move on to the next character */
+ DebugOptionEnd++;
+ }
+ }
+
+ /* Calculate the length of the current option */
+ DebugOptionLength = ((ULONG_PTR)DebugOptionEnd -
+ (ULONG_PTR)DebugOptionStart);
+
+ /*
+ * Break out if we reached the last option
+ * or if there were no options at all
+ */
+ if (!DebugOptionLength) break;
+
+ /* Now check which option this is */
+ if ((DebugOptionLength == 10) &&
+ !(strncmp(DebugOptionStart, "AUTOENABLE", 10)))
+ {
+ /*
+ * Disable the debugger, but
+ * allow it to be reenabled
+ */
+ DisableKdAfterInit = TRUE;
+ BlockEnable = FALSE;
+ KdAutoEnableOnEvent = TRUE;
+ }
+ else if ((DebugOptionLength == 7) &&
+ !(strncmp(DebugOptionStart, "DISABLE", 7)))
+ {
+ /* Disable the debugger */
+ DisableKdAfterInit = TRUE;
+ BlockEnable = TRUE;
+ KdAutoEnableOnEvent = FALSE;
+ }
+ else if ((DebugOptionLength == 6) &&
+ !(strncmp(DebugOptionStart, "NOUMEX", 6)))
+ {
+ /* Ignore user mode exceptions */
+ KdIgnoreUmExceptions = TRUE;
+ }
+
+ /*
+ * If there are more options then
+ * the next character should be a comma
+ */
+ if (*DebugOptionEnd != ',')
+ {
+ /* It isn't, break out */
+ break;
+ }
+
+ /* Move on to the next option */
+ DebugOptionEnd++;
+ DebugOptionStart = DebugOptionEnd;
+ }
+ }
+ }
+ }
+ else
+ {
+ /* No command line options? Disable debugger by default */
+ KdPitchDebugger = TRUE;
+ EnableKd = FALSE;
+ }
+ }
+ else
+ {
+ /* Called from a bugcheck or a re-enable. Save the Kernel Base */
+ KdVersionBlock.KernBase = (ULONG64)(LONG_PTR)PsNtosImageBase;
+
+ /* Unconditionally enable KD */
+ EnableKd = TRUE;
+ }
+
+ /* Set the Kernel Base in the Data Block */
+ KdDebuggerDataBlock.KernBase = (ULONG_PTR)KdVersionBlock.KernBase;
+
+ /* Initialize the debugger if requested */
+ if ((EnableKd) && (NT_SUCCESS(KdDebuggerInitialize0(LoaderBlock))))
+ {
+ /* Now set our real KD routine */
+ KiDebugRoutine = KdpTrap;
+
+ /* Check if we've already initialized our structures */
+ if (!KdpDebuggerStructuresInitialized)
+ {
+ /* Set the Debug Switch Routine and Retries*/
+ KdpContext.KdpDefaultRetries = 20;
+ KiDebugSwitchRoutine = KdpSwitchProcessor;
+
+ /* Initialize the Time Slip DPC */
+ KeInitializeDpc(&KdpTimeSlipDpc, KdpTimeSlipDpcRoutine, NULL);
+ KeInitializeTimer(&KdpTimeSlipTimer);
+ ExInitializeWorkItem(&KdpTimeSlipWorkItem, KdpTimeSlipWork, NULL);
+
+ /* First-time initialization done! */
+ KdpDebuggerStructuresInitialized = TRUE;
+ }
+
+ /* Initialize the timer */
+ KdTimerStart.QuadPart = 0;
+
+ /* Officially enable KD */
+ KdPitchDebugger = FALSE;
+ KdDebuggerEnabled = TRUE;
+
+ /* Let user-mode know that it's enabled as well */
+#undef KdDebuggerEnabled
+ SharedUserData->KdDebuggerEnabled = TRUE;
+#define KdDebuggerEnabled _KdDebuggerEnabled
+
+ /* Check if the debugger should be disabled initially */
+ if (DisableKdAfterInit)
+ {
+ /* Disable it */
+ KdDisableDebuggerWithLock(FALSE);
+
+ /*
+ * Save the enable block state and return initialized
+ * (the debugger is active but disabled).
+ */
+ KdBlockEnable = BlockEnable;
+ return TRUE;
+ }
+
+ /* Check if we have a loader block */
+ if (LoaderBlock)
+ {
+ /* Loop boot images */
+ NextEntry = LoaderBlock->LoadOrderListHead.Flink;
+ i = 0;
+ while ((NextEntry != &LoaderBlock->LoadOrderListHead) && (i < 2))
+ {
+ /* Get the image entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ /* Generate the image name */
+ Name = LdrEntry->FullDllName.Buffer;
+ Length = LdrEntry->FullDllName.Length / sizeof(WCHAR);
+ j = 0;
+ do
+ {
+ /* Do cheap Unicode to ANSI conversion */
+ NameBuffer[j++] = (CHAR)*Name++;
+ } while (j < Length);
+
+ /* Null-terminate */
+ NameBuffer[j] = ANSI_NULL;
+
+ /* Load symbols for image */
+ RtlInitAnsiString(&ImageName, NameBuffer);
+ DbgLoadImageSymbols(&ImageName, LdrEntry->DllBase, -1);
+
+ /* Go to the next entry */
+ NextEntry = NextEntry->Flink;
+ i++;
+ }
+ }
+
+ /* Check for incoming breakin and break on symbol load if we have it*/
+ KdBreakAfterSymbolLoad = KdPollBreakIn();
+ }
+ else
+ {
+ /* Disable debugger */
+ KdDebuggerNotPresent = TRUE;
+ }
+
+ /* Return initialized */
+ return TRUE;
+}