diff --git a/ntoskrnl/kd/kdinit.c b/ntoskrnl/kd/kdinit.c index 21e21162416..a2ed88ca6ee 100644 --- a/ntoskrnl/kd/kdinit.c +++ b/ntoskrnl/kd/kdinit.c @@ -39,76 +39,11 @@ extern ANSI_STRING KdpLogFileName; /* PRIVATE FUNCTIONS *********************************************************/ -CODE_SEG("INIT") -PCHAR +BOOLEAN NTAPI -KdpGetDebugMode(PCHAR Currentp2) -{ - PCHAR p1, p2 = Currentp2; - ULONG Value; - - /* Check for Screen Debugging */ - if (!_strnicmp(p2, "SCREEN", 6)) - { - /* Enable It */ - p2 += 6; - KdpDebugMode.Screen = TRUE; - } - /* Check for Serial Debugging */ - else if (!_strnicmp(p2, "COM", 3)) - { - /* Gheck for a valid Serial Port */ - p2 += 3; - if (*p2 != ':') - { - Value = (ULONG)atol(p2); - if (Value > 0 && Value < 5) - { - /* Valid port found, enable Serial Debugging */ - KdpDebugMode.Serial = TRUE; - - /* Set the port to use */ - SerialPortNumber = Value; - KdpPort = Value; - } - } - else - { - Value = strtoul(p2 + 1, NULL, 0); - if (Value) - { - KdpDebugMode.Serial = TRUE; - SerialPortInfo.Address = UlongToPtr(Value); - SerialPortNumber = 0; - KdpPort = 0; - } - } - } - /* Check for Debug Log Debugging */ - else if (!_strnicmp(p2, "FILE", 4)) - { - /* Enable It */ - p2 += 4; - KdpDebugMode.File = TRUE; - if (*p2 == ':') - { - p2++; - p1 = p2; - while (*p2 != '\0' && *p2 != ' ') p2++; - KdpLogFileName.MaximumLength = KdpLogFileName.Length = p2 - p1; - KdpLogFileName.Buffer = p1; - } - } - /* Check for BOCHS Debugging */ - else if (!_strnicmp(p2, "BOCHS", 5)) - { - /* Enable It */ - p2 += 5; - KdpDebugMode.Bochs = TRUE; - } - - return p2; -} +KdRegisterDebuggerDataBlock(IN ULONG Tag, + IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader, + IN ULONG Size); CODE_SEG("INIT") VOID @@ -141,133 +76,172 @@ KdpCallInitRoutine(ULONG BootPhase) BOOLEAN NTAPI -KdInitSystem(ULONG BootPhase, - PLOADER_PARAMETER_BLOCK LoaderBlock) +KdInitSystem(IN ULONG BootPhase, + IN PLOADER_PARAMETER_BLOCK LoaderBlock) { - ULONG Value; + BOOLEAN EnableKd; + LPSTR DebugLine; + PLDR_DATA_TABLE_ENTRY LdrEntry; ULONG i; - PCHAR CommandLine, Port = NULL, BaudRate = NULL, Irq = NULL; + PCHAR CommandLine; - /* Set Default Port Options */ - if (BootPhase == 0) + /* Check if this is Phase 1 */ + if (BootPhase) { - /* Check if we have a loader block */ - if (LoaderBlock) - { - /* Check if we have a command line */ - CommandLine = LoaderBlock->LoadOptions; - if (CommandLine) - { - /* Upcase it */ - _strupr(CommandLine); + /* Call the Initialization Routines of the Registered Providers */ + KdpCallInitRoutine(BootPhase); + return TRUE; + } - /* XXX Check for settings that we support */ - if (strstr(CommandLine, "NODEBUG")) KdDebuggerEnabled = FALSE; - else if (strstr(CommandLine, "CRASHDEBUG")) KdDebuggerEnabled = FALSE; - else if (strstr(CommandLine, "DEBUG")) - { - /* Enable the kernel debugger */ - KdDebuggerNotPresent = FALSE; - KdDebuggerEnabled = TRUE; -#ifdef KDBG - /* Get the KDBG Settings */ - KdbpGetCommandLineSettings(LoaderBlock->LoadOptions); + /* Check if we already initialized once */ + if (KdDebuggerEnabled) return TRUE; + + /* 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)((DBGKD_MAJOR_NT << 8) | (NtBuildNumber >> 28)); + KdVersionBlock.MinorVersion = (USHORT)(NtBuildNumber & 0xFFFF); + +#ifdef CONFIG_SMP + /* This is an MP Build */ + KdVersionBlock.Flags |= DBGKD_VERS_FLAG_MP; #endif - } - /* Get the port and baud rate */ - Port = strstr(CommandLine, "DEBUGPORT"); - BaudRate = strstr(CommandLine, "BAUDRATE"); - Irq = strstr(CommandLine, "IRQ"); - } - else + /* 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, NODEBUG and just DEBUG */ + if (strstr(CommandLine, "CRASHDEBUG")) { - /* No command line options? Disable debugger by default */ - KdDebuggerEnabled = FALSE; + /* Don't enable KD now, but allow it to be enabled later */ + KdPitchDebugger = FALSE; + } + else if (strstr(CommandLine, "NODEBUG")) + { + /* Don't enable KD and don't let it be enabled later */ + KdPitchDebugger = TRUE; + } + else if ((DebugLine = strstr(CommandLine, "DEBUG")) != NULL) + { + /* Enable KD */ + EnableKd = TRUE; + KdDebuggerNotPresent = FALSE; +#ifdef KDBG + /* Get the KDBG Settings */ + KdbpGetCommandLineSettings(LoaderBlock->LoadOptions); +#endif } } else { - /* Called from a bugcheck or a re-enable. Unconditionally enable KD. */ - KdDebuggerEnabled = TRUE; + /* No command line options? Disable debugger by default */ + KdPitchDebugger = TRUE; + EnableKd = FALSE; } - - /* Let user-mode know our state */ - SharedUserData->KdDebuggerEnabled = KdDebuggerEnabled; - - /* Check if we got the /DEBUGPORT parameter(s) */ - while (Port) - { - /* Move past the actual string, to reach the port*/ - Port += sizeof("DEBUGPORT") - 1; - - /* Now get past any spaces and skip the equal sign */ - while (*Port == ' ') Port++; - Port++; - - /* Get the debug mode and wrapper */ - Port = KdpGetDebugMode(Port); - Port = strstr(Port, "DEBUGPORT"); - } - - /* Use serial port then */ - if (KdDebuggerEnabled && KdpDebugMode.Value == 0) - KdpDebugMode.Serial = TRUE; - - /* Check if we got a baud rate */ - if (BaudRate) - { - /* Move past the actual string, to reach the rate */ - BaudRate += sizeof("BAUDRATE") - 1; - - /* Now get past any spaces */ - while (*BaudRate == ' ') BaudRate++; - - /* And make sure we have a rate */ - if (*BaudRate) - { - /* Read and set it */ - Value = atol(BaudRate + 1); - if (Value) PortInfo.BaudRate = SerialPortInfo.BaudRate = Value; - } - } - - /* Check Serial Port Settings [IRQ] */ - if (Irq) - { - /* Move past the actual string, to reach the rate */ - Irq += sizeof("IRQ") - 1; - - /* Now get past any spaces */ - while (*Irq == ' ') Irq++; - - /* And make sure we have an IRQ */ - if (*Irq) - { - /* Read and set it */ - Value = atol(Irq + 1); - if (Value) KdpPortIrq = Value; - } - } - - /* Call Providers at Phase 0 */ - for (i = 0; i < KdMax; i++) - { - InitRoutines[i](&DispatchTable[i], 0); - } - - /* Call Wrapper at Phase 0 */ - if (WrapperInitRoutine) WrapperInitRoutine(&WrapperTable, 0); - return TRUE; } - else /* BootPhase > 0 */ + else { + /* Called from a bugcheck or a re-enable. Save the Kernel Base. */ + KdVersionBlock.KernBase = (ULONG64)(LONG_PTR)PsNtosImageBase; + + /* Unconditionally enable KD */ + EnableKd = TRUE; } - /* Call the Initialization Routines of the Registered Providers */ - KdpCallInitRoutine(BootPhase); + /* Set the Kernel Base in the Data Block */ + KdDebuggerDataBlock.KernBase = (ULONG_PTR)KdVersionBlock.KernBase; - /* Return success */ + /* Initialize the debugger if requested */ + if (EnableKd && (NT_SUCCESS(KdDebuggerInitialize0(LoaderBlock)))) + { + /* Check if we've already initialized our structures */ + if (!KdpDebuggerStructuresInitialized) + { + /* Set the Debug Switch Routine and Retries */ + KdpContext.KdpDefaultRetries = 20; + KiDebugSwitchRoutine = KdpSwitchProcessor; + + /* Initialize breakpoints owed flag and table */ + KdpOweBreakpoint = FALSE; + for (i = 0; i < KD_BREAKPOINT_MAX; i++) + { + KdpBreakpointTable[i].Flags = 0; + KdpBreakpointTable[i].DirectoryTableBase = 0; + KdpBreakpointTable[i].Address = NULL; + } + + /* 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 */ + SharedUserData->KdDebuggerEnabled = TRUE; + } + else + { + /* Disable debugger */ + KdDebuggerNotPresent = TRUE; + } + + /* Return initialized */ return TRUE; } diff --git a/ntoskrnl/kd/kdmain.c b/ntoskrnl/kd/kdmain.c index 92a47a9cc91..5cf6e00bd57 100644 --- a/ntoskrnl/kd/kdmain.c +++ b/ntoskrnl/kd/kdmain.c @@ -58,6 +58,9 @@ VOID NTAPI PspDumpThreads(BOOLEAN SystemThreads); ULONG Kd_DEFAULT_MASK = 1 << DPFLTR_ERROR_LEVEL; #endif +extern CPPORT PortInfo; +extern ANSI_STRING KdpLogFileName; + /* PRIVATE FUNCTIONS *********************************************************/ ULONG @@ -413,12 +416,164 @@ KdSystemDebugControl(IN SYSDBG_COMMAND Command, PKDEBUG_ROUTINE KiDebugRoutine = KdpEnterDebuggerException; +CODE_SEG("INIT") +PCHAR +NTAPI +KdpGetDebugMode(PCHAR Currentp2) +{ + PCHAR p1, p2 = Currentp2; + ULONG Value; + + /* Check for Screen Debugging */ + if (!_strnicmp(p2, "SCREEN", 6)) + { + /* Enable It */ + p2 += 6; + KdpDebugMode.Screen = TRUE; + } + /* Check for Serial Debugging */ + else if (!_strnicmp(p2, "COM", 3)) + { + /* Gheck for a valid Serial Port */ + p2 += 3; + if (*p2 != ':') + { + Value = (ULONG)atol(p2); + if (Value > 0 && Value < 5) + { + /* Valid port found, enable Serial Debugging */ + KdpDebugMode.Serial = TRUE; + + /* Set the port to use */ + SerialPortNumber = Value; + KdpPort = Value; + } + } + else + { + Value = strtoul(p2 + 1, NULL, 0); + if (Value) + { + KdpDebugMode.Serial = TRUE; + SerialPortInfo.Address = UlongToPtr(Value); + SerialPortNumber = 0; + KdpPort = 0; + } + } + } + /* Check for Debug Log Debugging */ + else if (!_strnicmp(p2, "FILE", 4)) + { + /* Enable It */ + p2 += 4; + KdpDebugMode.File = TRUE; + if (*p2 == ':') + { + p2++; + p1 = p2; + while (*p2 != '\0' && *p2 != ' ') p2++; + KdpLogFileName.MaximumLength = KdpLogFileName.Length = p2 - p1; + KdpLogFileName.Buffer = p1; + } + } + /* Check for BOCHS Debugging */ + else if (!_strnicmp(p2, "BOCHS", 5)) + { + /* Enable It */ + p2 += 5; + KdpDebugMode.Bochs = TRUE; + } + + return p2; +} + NTSTATUS NTAPI KdDebuggerInitialize0( IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL) { - return STATUS_NOT_IMPLEMENTED; + ULONG Value; + ULONG i; + PCHAR CommandLine, Port = NULL, BaudRate = NULL, Irq = NULL; + + if (LoaderBlock) + { + /* Check if we have a command line */ + CommandLine = LoaderBlock->LoadOptions; + if (CommandLine) + { + /* Upcase it */ + _strupr(CommandLine); + + /* Get the port and baud rate */ + Port = strstr(CommandLine, "DEBUGPORT"); + BaudRate = strstr(CommandLine, "BAUDRATE"); + Irq = strstr(CommandLine, "IRQ"); + } + } + + /* Check if we got the /DEBUGPORT parameter(s) */ + while (Port) + { + /* Move past the actual string, to reach the port*/ + Port += sizeof("DEBUGPORT") - 1; + + /* Now get past any spaces and skip the equal sign */ + while (*Port == ' ') Port++; + Port++; + + /* Get the debug mode and wrapper */ + Port = KdpGetDebugMode(Port); + Port = strstr(Port, "DEBUGPORT"); + } + + /* Use serial port then */ + if (KdpDebugMode.Value == 0) + KdpDebugMode.Serial = TRUE; + + /* Check if we got a baud rate */ + if (BaudRate) + { + /* Move past the actual string, to reach the rate */ + BaudRate += sizeof("BAUDRATE") - 1; + + /* Now get past any spaces */ + while (*BaudRate == ' ') BaudRate++; + + /* And make sure we have a rate */ + if (*BaudRate) + { + /* Read and set it */ + Value = atol(BaudRate + 1); + if (Value) PortInfo.BaudRate = SerialPortInfo.BaudRate = Value; + } + } + + /* Check Serial Port Settings [IRQ] */ + if (Irq) + { + /* Move past the actual string, to reach the rate */ + Irq += sizeof("IRQ") - 1; + + /* Now get past any spaces */ + while (*Irq == ' ') Irq++; + + /* And make sure we have an IRQ */ + if (*Irq) + { + /* Read and set it */ + Value = atol(Irq + 1); + if (Value) KdpPortIrq = Value; + } + } + + /* Call Providers at Phase 0 */ + for (i = 0; i < KdMax; i++) + { + InitRoutines[i](&DispatchTable[i], 0); + } + + return STATUS_SUCCESS; } NTSTATUS diff --git a/ntoskrnl/kd64/kdapi.c b/ntoskrnl/kd64/kdapi.c index f9205be480f..69fae2c450c 100644 --- a/ntoskrnl/kd64/kdapi.c +++ b/ntoskrnl/kd64/kdapi.c @@ -1726,6 +1726,7 @@ KdpReportCommandStringStateChange(IN PSTRING NameString, Context); } while (Status == ContinueProcessorReselected); } +#endif BOOLEAN NTAPI @@ -1733,6 +1734,7 @@ KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord, IN OUT PCONTEXT Context, IN BOOLEAN SecondChanceException) { +#ifdef _WINKD_ STRING Header, Data; DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange; KCONTINUE_STATUS Status; @@ -1780,6 +1782,10 @@ KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord, /* Return */ return Status; +#else + UNIMPLEMENTED; + return FALSE; +#endif } VOID @@ -1851,6 +1857,7 @@ KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord, return Status; } +#ifdef _WINKD_ LARGE_INTEGER NTAPI KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame) diff --git a/ntoskrnl/kd64/kddata.c b/ntoskrnl/kd64/kddata.c index d0acd10a2af..b11ea0fa98e 100644 --- a/ntoskrnl/kd64/kddata.c +++ b/ntoskrnl/kd64/kddata.c @@ -73,8 +73,8 @@ BOOLEAN KdpContextSent; // #ifdef _WINKD_ PKDEBUG_ROUTINE KiDebugRoutine = KdpStub; -PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine; #endif +PKDEBUG_SWITCH_ROUTINE KiDebugSwitchRoutine; // // Debugger Configuration Settings