Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

kdinit.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990-1999 Microsoft Corporation 00004 00005 Module Name: 00006 00007 kdinit.c 00008 00009 Abstract: 00010 00011 This module implements the initialization for the portable kernel debgger. 00012 00013 Author: 00014 00015 David N. Cutler 27-July-1990 00016 00017 Revision History: 00018 00019 --*/ 00020 00021 #include "kdp.h" 00022 00023 // 00024 // Miscellaneous data from all over the kernel 00025 // 00026 00027 #define BAUD_OPTION "BAUDRATE" 00028 #define PORT_OPTION "DEBUGPORT" 00029 00030 00031 #ifdef ALLOC_PRAGMA 00032 #pragma alloc_text(PAGEKD, KdInitSystem) 00033 #pragma alloc_text(PAGEKD, KdUpdateDataBlock) 00034 #endif 00035 00036 00037 VOID 00038 KdUpdateDataBlock( 00039 VOID 00040 ) 00041 /*++ 00042 00043 Routine Description: 00044 00045 We have to update this variable seperately since it is initialized at a 00046 later time by PS. PS will call us to update the data block. 00047 00048 --*/ 00049 { 00050 KdDebuggerDataBlock.KeUserCallbackDispatcher = (ULONG_PTR) KeUserCallbackDispatcher; 00051 } 00052 00053 00054 ULONG_PTR 00055 KdGetDataBlock( 00056 VOID 00057 ) 00058 /*++ 00059 00060 Routine Description: 00061 00062 We have to update this variable seperately since it is initialized at a 00063 later time by PS. PS will call us to update the data block. 00064 00065 --*/ 00066 { 00067 return (ULONG_PTR)(&KdDebuggerDataBlock); 00068 } 00069 00070 00071 BOOLEAN 00072 KdInitSystem( 00073 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL, 00074 BOOLEAN StopInDebugger 00075 ) 00076 00077 /*++ 00078 00079 Routine Description: 00080 00081 This routine initializes the portable kernel debugger. 00082 00083 Arguments: 00084 00085 LoaderBlock - Supplies a pointer to the LOADER_PARAMETER_BLOCK passed 00086 in from the OS Loader. 00087 00088 StopInDebugger - Supplies a boolean value that determines whether a 00089 debug message and breakpoint are generated. 00090 00091 Return Value: 00092 00093 None. 00094 00095 --*/ 00096 00097 { 00098 00099 ULONG Index; 00100 BOOLEAN Initialize; 00101 PCHAR Options; 00102 PCHAR BaudOption; 00103 PCHAR PortOption; 00104 00105 // 00106 // If kernel debugger is already initialized, then return. 00107 // 00108 00109 if (KdDebuggerEnabled != FALSE) { 00110 return TRUE; 00111 } 00112 00113 KiDebugRoutine = KdpStub; 00114 00115 // 00116 // Determine whether or not the debugger should be enabled. 00117 // 00118 // Note that if LoaderBlock == NULL, then KdInitSystem was called 00119 // from BugCheck code. For this case the debugger is always enabled 00120 // to report the bugcheck if possible. 00121 // 00122 00123 if (LoaderBlock != NULL) { 00124 00125 KdpNtosImageBase = CONTAINING_RECORD( 00126 (LoaderBlock->LoadOrderListHead.Flink), 00127 LDR_DATA_TABLE_ENTRY, 00128 InLoadOrderLinks)->DllBase; 00129 00130 // 00131 // Initialize the debugger data block list when called at startup time. 00132 // 00133 00134 InitializeListHead(&KdpDebuggerDataListHead); 00135 00136 // 00137 // Fill in and register the debugger's debugger data block. 00138 // Most fields are already initialized, some fields will not be 00139 // filled in until later. 00140 // 00141 00142 KdDebuggerDataBlock.KernBase = (ULONG_PTR) KdpNtosImageBase; 00143 00144 KdRegisterDebuggerDataBlock(KDBG_TAG, 00145 &KdDebuggerDataBlock.Header, 00146 sizeof(KdDebuggerDataBlock)); 00147 00148 if (LoaderBlock->LoadOptions != NULL) { 00149 Options = LoaderBlock->LoadOptions; 00150 _strupr(Options); 00151 00152 // 00153 // If any of the port option, baud option, or debug is specified, 00154 // then enable the debugger unless it is explictly disabled. 00155 // 00156 00157 Initialize = TRUE; 00158 PortOption = strstr(Options, PORT_OPTION); 00159 BaudOption = strstr(Options, BAUD_OPTION); 00160 if ((PortOption == NULL) && (BaudOption == NULL)) { 00161 if (strstr(Options, "DEBUG") == NULL) { 00162 Initialize = FALSE; 00163 } 00164 00165 } else { 00166 if (PortOption) { 00167 PortOption = strstr(PortOption, "COM"); 00168 if (PortOption) { 00169 KdDebugParameters.CommunicationPort = 00170 atol(PortOption + 3); 00171 } 00172 } 00173 00174 if (BaudOption) { 00175 BaudOption += strlen(BAUD_OPTION); 00176 while (*BaudOption == ' ') { 00177 BaudOption++; 00178 } 00179 00180 if (*BaudOption != '\0') { 00181 KdDebugParameters.BaudRate = atol(BaudOption + 1); 00182 } 00183 } 00184 } 00185 00186 // 00187 // If the debugger is explicitly disabled, then set to NODEBUG. 00188 // 00189 00190 if (strstr(Options, "NODEBUG")) { 00191 Initialize = FALSE; 00192 KdPitchDebugger = TRUE; 00193 } 00194 00195 if (strstr(Options, "CRASHDEBUG")) { 00196 Initialize = FALSE; 00197 KdPitchDebugger = FALSE; 00198 } 00199 00200 } else { 00201 00202 // 00203 // If the load options are not specified, then set to NODEBUG. 00204 // 00205 00206 KdPitchDebugger = TRUE; 00207 Initialize = FALSE; 00208 } 00209 00210 } else { 00211 Initialize = TRUE; 00212 } 00213 00214 if ((KdPortInitialize(&KdDebugParameters, LoaderBlock, Initialize) == FALSE) || 00215 (Initialize == FALSE)) { 00216 return(TRUE); 00217 } 00218 00219 // 00220 // Set address of kernel debugger trap routine. 00221 // 00222 00223 KiDebugRoutine = KdpTrap; 00224 00225 if (!KdpDebuggerStructuresInitialized) { 00226 00227 KiDebugSwitchRoutine = KdpSwitchProcessor; 00228 KdpBreakpointInstruction = KDP_BREAKPOINT_VALUE; 00229 KdpOweBreakpoint = FALSE; 00230 00231 // 00232 // Initialize the breakpoint table. 00233 // 00234 00235 for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) { 00236 KdpBreakpointTable[Index].Flags = 0; 00237 KdpBreakpointTable[Index].Address = NULL; 00238 KdpBreakpointTable[Index].DirectoryTableBase = 0L; 00239 } 00240 00241 // 00242 // Initialize TimeSlip 00243 // 00244 KeInitializeDpc(&KdpTimeSlipDpc, KdpTimeSlipDpcRoutine, NULL); 00245 KeInitializeTimer(&KdpTimeSlipTimer); 00246 ExInitializeWorkItem(&KdpTimeSlipWorkItem, KdpTimeSlipWork, NULL); 00247 00248 KdpDebuggerStructuresInitialized = TRUE ; 00249 } 00250 00251 // 00252 // Initialize timer facility - HACKHACK 00253 // 00254 00255 KeQueryPerformanceCounter(&KdPerformanceCounterRate); 00256 KdTimerStart.HighPart = 0L; 00257 KdTimerStart.LowPart = 0L; 00258 00259 // 00260 // Initialize ID for NEXT packet to send and Expect ID of next incoming 00261 // packet. 00262 // 00263 00264 KdpNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID; 00265 KdpPacketIdExpected = INITIAL_PACKET_ID; 00266 00267 // 00268 // Mark debugger enabled. 00269 // 00270 KdPitchDebugger = FALSE; 00271 KdDebuggerEnabled = TRUE; 00272 SharedUserData->KdDebuggerEnabled = 0x00000001; 00273 00274 // 00275 // If requested, stop in the kernel debugger. 00276 // 00277 00278 if (StopInDebugger) { 00279 DbgBreakPoint(); 00280 } 00281 00282 return TRUE; 00283 } 00284 00285 00286 BOOLEAN 00287 KdRegisterDebuggerDataBlock( 00288 IN ULONG Tag, 00289 IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader, 00290 IN ULONG Size 00291 ) 00292 /*++ 00293 00294 Routine Description: 00295 00296 This routine is called by a component or driver to register a 00297 debugger data block. The data block is made accessible to the 00298 kernel debugger, thus providing a reliable method of exposing 00299 random data to debugger extensions. 00300 00301 Arguments: 00302 00303 Tag - Supplies a unique 4 byte tag which is used to identify the 00304 data block. 00305 00306 DataHeader - Supplies the address of the debugger data block header. 00307 The OwnerTag field must contain a unique value, and the Size 00308 field must contain the size of the data block, including the 00309 header. If this block is already present, or there is 00310 already a block with the same value for OwnerTag, this one 00311 will not be inserted. If Size is incorrect, this code will 00312 not notice, but the usermode side of the debugger might not 00313 function correctly. 00314 00315 Size - Supplies the size of the data block, including the header. 00316 00317 Return Value: 00318 00319 TRUE if the block was added to the list, FALSE if not. 00320 00321 --*/ 00322 { 00323 KIRQL OldIrql; 00324 PLIST_ENTRY List; 00325 PDBGKD_DEBUG_DATA_HEADER64 Header; 00326 00327 KeAcquireSpinLock(&KdpDataSpinLock, &OldIrql); 00328 00329 // 00330 // Look for a record with the same tag or address 00331 // 00332 00333 List = KdpDebuggerDataListHead.Flink; 00334 00335 while (List != &KdpDebuggerDataListHead) { 00336 00337 Header = CONTAINING_RECORD(List, DBGKD_DEBUG_DATA_HEADER64, List); 00338 00339 List = List->Flink; 00340 00341 if ((Header == DataHeader) || (Header->OwnerTag == Tag)) { 00342 KeReleaseSpinLock(&KdpDataSpinLock, OldIrql); 00343 return FALSE; 00344 } 00345 } 00346 00347 // 00348 // It wasn't already there, so add it. 00349 // 00350 00351 DataHeader->OwnerTag = Tag; 00352 DataHeader->Size = Size; 00353 00354 InsertTailList(&KdpDebuggerDataListHead, (PLIST_ENTRY)(&DataHeader->List)); 00355 00356 KeReleaseSpinLock(&KdpDataSpinLock, OldIrql); 00357 00358 return TRUE; 00359 } 00360 00361 00362 VOID 00363 KdDeregisterDebuggerDataBlock( 00364 IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader 00365 ) 00366 /*++ 00367 00368 Routine Description: 00369 00370 This routine is called to deregister a data block previously 00371 registered with KdRegisterDebuggerDataBlock. If the block is 00372 found in the list, it is removed. 00373 00374 Arguments: 00375 00376 DataHeader - Supplies the address of the data block which is 00377 to be removed from the list. 00378 00379 Return Value: 00380 00381 None 00382 00383 --*/ 00384 00385 { 00386 KIRQL OldIrql; 00387 PLIST_ENTRY List; 00388 PDBGKD_DEBUG_DATA_HEADER64 Header; 00389 00390 KeAcquireSpinLock(&KdpDataSpinLock, &OldIrql); 00391 00392 // 00393 // Make sure the data block is on our list before removing it. 00394 // 00395 00396 List = KdpDebuggerDataListHead.Flink; 00397 00398 while (List != &KdpDebuggerDataListHead) { 00399 00400 Header = CONTAINING_RECORD(List, DBGKD_DEBUG_DATA_HEADER64, List); 00401 List = List->Flink; 00402 00403 if (DataHeader == Header) { 00404 RemoveEntryList((PLIST_ENTRY)(&DataHeader->List)); 00405 break; 00406 } 00407 } 00408 00409 KeReleaseSpinLock(&KdpDataSpinLock, OldIrql); 00410 } 00411 00412 00413 VOID 00414 KdLogDbgPrint( 00415 IN PSTRING String 00416 ) 00417 { 00418 KIRQL OldIrql; 00419 ULONG Length; 00420 ULONG LengthCopied; 00421 00422 for (; ;) { 00423 if (KeTestSpinLock (&KdpPrintSpinLock)) { 00424 KeRaiseIrql (HIGH_LEVEL, &OldIrql); 00425 if (KiTryToAcquireSpinLock(&KdpPrintSpinLock)) { 00426 break; // got the lock 00427 } 00428 KeLowerIrql(OldIrql); 00429 } 00430 } 00431 00432 if (KdPrintCircularBuffer) { 00433 Length = String->Length; 00434 // 00435 // truncate ridiculous strings 00436 // 00437 if (Length > KDPRINTBUFFERSIZE) { 00438 Length = KDPRINTBUFFERSIZE; 00439 } 00440 00441 if (KdPrintWritePointer + Length <= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) { 00442 LengthCopied = KdpMoveMemory(KdPrintWritePointer, String->Buffer, Length); 00443 KdPrintWritePointer += LengthCopied; 00444 if (KdPrintWritePointer >= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) { 00445 KdPrintWritePointer = KdPrintCircularBuffer; 00446 KdPrintRolloverCount++; 00447 } 00448 } else { 00449 ULONG First = (ULONG)(KdPrintCircularBuffer + KDPRINTBUFFERSIZE - KdPrintWritePointer); 00450 LengthCopied = KdpMoveMemory(KdPrintWritePointer, 00451 String->Buffer, 00452 First); 00453 if (LengthCopied == First) { 00454 LengthCopied += KdpMoveMemory(KdPrintCircularBuffer, 00455 String->Buffer + First, 00456 Length - First); 00457 } 00458 if (LengthCopied > First) { 00459 KdPrintWritePointer = KdPrintCircularBuffer + LengthCopied - First; 00460 KdPrintRolloverCount++; 00461 } else { 00462 KdPrintWritePointer += LengthCopied; 00463 if (KdPrintWritePointer >= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) { 00464 KdPrintWritePointer = KdPrintCircularBuffer; 00465 KdPrintRolloverCount++; 00466 } 00467 } 00468 } 00469 } 00470 00471 KiReleaseSpinLock(&KdpPrintSpinLock); 00472 KeLowerIrql(OldIrql); 00473 }

Generated on Sat May 15 19:40:34 2004 for test by doxygen 1.3.7