test: kdinit.c Source File

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 }