ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

kdio.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS kernel
00004  * FILE:            ntoskrnl/kd/kdio.c
00005  * PURPOSE:         NT Kernel Debugger Input/Output Functions
00006  *
00007  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00008  */
00009 
00010 /* INCLUDES ******************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #include <reactos/buildno.h>
00014 #include <debug.h>
00015 
00016 /* GLOBALS *******************************************************************/
00017 
00018 #define KdpBufferSize  (1024 * 512)
00019 BOOLEAN KdpLoggingEnabled = FALSE;
00020 PCHAR KdpDebugBuffer = NULL;
00021 volatile ULONG KdpCurrentPosition = 0;
00022 volatile ULONG KdpFreeBytes = 0;
00023 KSPIN_LOCK KdpDebugLogSpinLock;
00024 KEVENT KdpLoggerThreadEvent;
00025 HANDLE KdpLogFileHandle;
00026 ANSI_STRING KdpLogFileName = RTL_CONSTANT_STRING("\\SystemRoot\\debug.log");
00027 
00028 KSPIN_LOCK KdpSerialSpinLock;
00029 KD_PORT_INFORMATION SerialPortInfo = { DEFAULT_DEBUG_PORT, DEFAULT_DEBUG_BAUD_RATE, 0 };
00030 
00031 /* Current Port in use. FIXME: Do we support more then one? */
00032 ULONG KdpPort;
00033 
00034 #define KdpScreenLineLenght 80
00035 CHAR KdpScreenLineBuffer[KdpScreenLineLenght + 1] = "";
00036 ULONG KdpScreenLineBufferPos = 0, KdpScreenLineLength = 0;
00037 
00038 const ULONG KdpDmesgBufferSize = 128 * 1024; // 512*1024; // 5*1024*1024;
00039 PCHAR KdpDmesgBuffer = NULL;
00040 volatile ULONG KdpDmesgCurrentPosition = 0;
00041 volatile ULONG KdpDmesgFreeBytes = 0;
00042 volatile ULONG KdbDmesgTotalWritten = 0;
00043 KSPIN_LOCK KdpDmesgLogSpinLock;
00044 volatile BOOLEAN KdbpIsInDmesgMode = FALSE;
00045 
00046 /* FILE DEBUG LOG FUNCTIONS **************************************************/
00047 
00048 VOID
00049 NTAPI
00050 KdpLoggerThread(PVOID Context)
00051 {
00052     ULONG beg, end, num;
00053     IO_STATUS_BLOCK Iosb;
00054 
00055     KdpLoggingEnabled = TRUE;
00056 
00057     while (TRUE)
00058     {
00059         KeWaitForSingleObject(&KdpLoggerThreadEvent, 0, KernelMode, FALSE, NULL);
00060 
00061         /* Bug */
00062         /* Keep KdpCurrentPosition and KdpFreeBytes values in local
00063          * variables to avoid their possible change from Producer part,
00064          * KdpPrintToLogFile function
00065          */
00066         end = KdpCurrentPosition;
00067         num = KdpFreeBytes;
00068 
00069         /* Now securely calculate values, based on local variables */
00070         beg = (end + num) % KdpBufferSize;
00071         num = KdpBufferSize - num;
00072 
00073         /* Nothing to do? */
00074         if (num == 0)
00075             continue;
00076 
00077         if (end > beg)
00078         {
00079             NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
00080                         KdpDebugBuffer + beg, num, NULL, NULL);
00081         }
00082         else
00083         {
00084             NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
00085                         KdpDebugBuffer + beg, KdpBufferSize - beg, NULL, NULL);
00086 
00087             NtWriteFile(KdpLogFileHandle, NULL, NULL, NULL, &Iosb,
00088                         KdpDebugBuffer, end, NULL, NULL);
00089         }
00090 
00091         (VOID)InterlockedExchangeAddUL(&KdpFreeBytes, num);
00092     }
00093 }
00094 
00095 VOID
00096 NTAPI
00097 KdpPrintToLogFile(PCH String,
00098                   ULONG StringLength)
00099 {
00100     ULONG beg, end, num;
00101     KIRQL OldIrql;
00102 
00103     if (KdpDebugBuffer == NULL) return;
00104 
00105     /* Acquire the printing spinlock without waiting at raised IRQL */
00106     while (TRUE)
00107     {
00108         /* Wait when the spinlock becomes available */
00109         while (!KeTestSpinLock(&KdpDebugLogSpinLock));
00110 
00111         /* Spinlock was free, raise IRQL */
00112         KeRaiseIrql(HIGH_LEVEL, &OldIrql);
00113 
00114         /* Try to get the spinlock */
00115         if (KeTryToAcquireSpinLockAtDpcLevel(&KdpDebugLogSpinLock))
00116             break;
00117 
00118         /* Someone else got the spinlock, lower IRQL back */
00119         KeLowerIrql(OldIrql);
00120     }
00121 
00122     beg = KdpCurrentPosition;
00123     num = KdpFreeBytes;
00124     if (StringLength < num)
00125         num = StringLength;
00126 
00127     if (num != 0)
00128     {
00129         end = (beg + num) % KdpBufferSize;
00130         KdpCurrentPosition = end;
00131         KdpFreeBytes -= num;
00132 
00133         if (end > beg)
00134         {
00135             RtlCopyMemory(KdpDebugBuffer + beg, String, num);
00136         }
00137         else
00138         {
00139             RtlCopyMemory(KdpDebugBuffer + beg, String, KdpBufferSize - beg);
00140             RtlCopyMemory(KdpDebugBuffer, String + KdpBufferSize - beg, end);
00141         }
00142     }
00143 
00144     /* Release spinlock */
00145     KiReleaseSpinLock(&KdpDebugLogSpinLock);
00146 
00147     /* Lower IRQL */
00148     KeLowerIrql(OldIrql);
00149 
00150     /* Signal the logger thread */
00151     if (OldIrql <= DISPATCH_LEVEL && KdpLoggingEnabled)
00152         KeSetEvent(&KdpLoggerThreadEvent, 0, FALSE);
00153 }
00154 
00155 VOID
00156 NTAPI
00157 INIT_FUNCTION
00158 KdpInitDebugLog(PKD_DISPATCH_TABLE DispatchTable,
00159                 ULONG BootPhase)
00160 {
00161     NTSTATUS Status;
00162     UNICODE_STRING FileName;
00163     OBJECT_ATTRIBUTES ObjectAttributes;
00164     IO_STATUS_BLOCK Iosb;
00165     HANDLE ThreadHandle;
00166     KPRIORITY Priority;
00167     SIZE_T MemSizeMBs;
00168 
00169     if (!KdpDebugMode.File) return;
00170 
00171     if (BootPhase == 0)
00172     {
00173         KdComPortInUse = NULL;
00174 
00175         /* Write out the functions that we support for now */
00176         DispatchTable->KdpInitRoutine = KdpInitDebugLog;
00177         DispatchTable->KdpPrintRoutine = KdpPrintToLogFile;
00178 
00179         /* Register as a Provider */
00180         InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
00181 
00182     }
00183     else if (BootPhase == 1)
00184     {
00185         /* Allocate a buffer for debug log */
00186         KdpDebugBuffer = ExAllocatePool(NonPagedPool, KdpBufferSize);
00187         KdpFreeBytes = KdpBufferSize;
00188 
00189         /* Initialize spinlock */
00190         KeInitializeSpinLock(&KdpDebugLogSpinLock);
00191 
00192         /* Display separator + ReactOS version at start of the debug log */
00193         DPRINT1("---------------------------------------------------------------\n");
00194         DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n");
00195         MemSizeMBs = MmNumberOfPhysicalPages * PAGE_SIZE / 1024 / 1024;
00196         DPRINT1("%u System Processor [%u MB Memory]\n", KeNumberProcessors, MemSizeMBs);
00197     }
00198     else if (BootPhase == 2)
00199     {
00200         HalDisplayString("\n   File log debugging enabled\n\n");
00201     }
00202     else if (BootPhase == 3)
00203     {
00204         /* Setup the log name */
00205         Status = RtlAnsiStringToUnicodeString(&FileName, &KdpLogFileName, TRUE);
00206         if (!NT_SUCCESS(Status)) return;
00207 
00208         InitializeObjectAttributes(&ObjectAttributes,
00209                                    &FileName,
00210                                    0,
00211                                    NULL,
00212                                    NULL);
00213 
00214         /* Create the log file */
00215         Status = NtCreateFile(&KdpLogFileHandle,
00216                               FILE_APPEND_DATA | SYNCHRONIZE,
00217                               &ObjectAttributes,
00218                               &Iosb,
00219                               NULL,
00220                               FILE_ATTRIBUTE_NORMAL,
00221                               FILE_SHARE_READ,
00222                               FILE_SUPERSEDE,
00223                               FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT,
00224                               NULL,
00225                               0);
00226 
00227         RtlFreeUnicodeString(&FileName);
00228 
00229         if (!NT_SUCCESS(Status)) return;
00230 
00231         KeInitializeEvent(&KdpLoggerThreadEvent, SynchronizationEvent, TRUE);
00232 
00233         /* Create the logger thread */
00234         Status = PsCreateSystemThread(&ThreadHandle,
00235                                       THREAD_ALL_ACCESS,
00236                                       NULL,
00237                                       NULL,
00238                                       NULL,
00239                                       KdpLoggerThread,
00240                                       NULL);
00241 
00242         if (!NT_SUCCESS(Status)) return;
00243 
00244         Priority = 7;
00245         NtSetInformationThread(ThreadHandle,
00246                                ThreadPriority,
00247                                &Priority,
00248                                sizeof(Priority));
00249     }
00250 }
00251 
00252 /* SERIAL FUNCTIONS **********************************************************/
00253 
00254 VOID
00255 NTAPI
00256 KdpSerialDebugPrint(LPSTR Message,
00257                     ULONG Length)
00258 {
00259     KIRQL OldIrql;
00260     PCHAR pch = (PCHAR) Message;
00261 
00262     /* Acquire the printing spinlock without waiting at raised IRQL */
00263     while (TRUE)
00264     {
00265         /* Wait when the spinlock becomes available */
00266         while (!KeTestSpinLock(&KdpSerialSpinLock));
00267 
00268         /* Spinlock was free, raise IRQL */
00269         KeRaiseIrql(HIGH_LEVEL, &OldIrql);
00270 
00271         /* Try to get the spinlock */
00272         if (KeTryToAcquireSpinLockAtDpcLevel(&KdpSerialSpinLock))
00273             break;
00274 
00275         /* Someone else got the spinlock, lower IRQL back */
00276         KeLowerIrql(OldIrql);
00277     }
00278 
00279     /* Output the message */
00280     while (*pch != 0)
00281     {
00282         if (*pch == '\n')
00283         {
00284             KdPortPutByteEx(&SerialPortInfo, '\r');
00285         }
00286         KdPortPutByteEx(&SerialPortInfo, *pch);
00287         pch++;
00288     }
00289 
00290     /* Release spinlock */
00291     KiReleaseSpinLock(&KdpSerialSpinLock);
00292 
00293     /* Lower IRQL */
00294     KeLowerIrql(OldIrql);
00295 }
00296 
00297 VOID
00298 NTAPI
00299 KdpSerialInit(PKD_DISPATCH_TABLE DispatchTable,
00300               ULONG BootPhase)
00301 {
00302     SIZE_T MemSizeMBs;
00303     if (!KdpDebugMode.Serial) return;
00304 
00305     if (BootPhase == 0)
00306     {
00307         /* Write out the functions that we support for now */
00308         DispatchTable->KdpInitRoutine = KdpSerialInit;
00309         DispatchTable->KdpPrintRoutine = KdpSerialDebugPrint;
00310 
00311         /* Initialize the Port */
00312         if (!KdPortInitializeEx(&SerialPortInfo, 0, 0))
00313         {
00314             KdpDebugMode.Serial = FALSE;
00315             return;
00316         }
00317         KdComPortInUse = (PUCHAR)(ULONG_PTR)SerialPortInfo.BaseAddress;
00318 
00319         /* Initialize spinlock */
00320         KeInitializeSpinLock(&KdpSerialSpinLock);
00321 
00322         /* Register as a Provider */
00323         InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
00324 
00325         /* Display separator + ReactOS version at start of the debug log */
00326         DPRINT1("-----------------------------------------------------\n");
00327         DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n");
00328         MemSizeMBs = MmNumberOfPhysicalPages * PAGE_SIZE / 1024 / 1024;
00329         DPRINT1("%u System Processor [%u MB Memory]\n", KeNumberProcessors, MemSizeMBs);
00330         DPRINT1("Command Line: %s\n", KeLoaderBlock->LoadOptions);
00331         DPRINT1("ARC Paths: %s %s %s %s\n", KeLoaderBlock->ArcBootDeviceName,
00332                                             KeLoaderBlock->NtHalPathName,
00333                                             KeLoaderBlock->ArcHalDeviceName,
00334                                             KeLoaderBlock->NtBootPathName);
00335     }
00336     else if (BootPhase == 2)
00337     {
00338         HalDisplayString("\n   Serial debugging enabled\n\n");
00339     }
00340 }
00341 
00342 /* SCREEN FUNCTIONS **********************************************************/
00343 
00344 /*
00345  * Screen debug logger function KdpScreenPrint() writes text messages into
00346  * KdpDmesgBuffer, using it as a circular buffer. KdpDmesgBuffer contents could
00347  * be later (re)viewed using dmesg command of kdbg. KdpScreenPrint() protects
00348  * KdpDmesgBuffer from simultaneous writes by use of KdpDmesgLogSpinLock.
00349  */
00350 VOID
00351 NTAPI
00352 KdpScreenPrint(LPSTR Message,
00353                ULONG Length)
00354 {
00355     ULONG beg, end, num;
00356     KIRQL OldIrql;
00357     PCHAR pch = (PCHAR) Message;
00358 
00359     while (*pch)
00360     {
00361         if(*pch == '\b')
00362         {
00363             /* HalDisplayString does not support '\b'. Workaround it and use '\r' */
00364             if(KdpScreenLineLength > 0)
00365             {
00366                 /* Remove last character from buffer */
00367                 KdpScreenLineBuffer[--KdpScreenLineLength] = '\0';
00368                 KdpScreenLineBufferPos = KdpScreenLineLength;
00369 
00370                 /* Clear row and print line again */
00371                 HalDisplayString("\r");
00372                 HalDisplayString(KdpScreenLineBuffer);
00373             }
00374         }
00375         else
00376         {
00377             KdpScreenLineBuffer[KdpScreenLineLength++] = *pch;
00378             KdpScreenLineBuffer[KdpScreenLineLength] = '\0';
00379         }
00380 
00381         if(*pch == '\n' || KdpScreenLineLength == KdpScreenLineLenght)
00382         {
00383             /* Print buffered characters */
00384             if(KdpScreenLineBufferPos != KdpScreenLineLength)
00385                 HalDisplayString(KdpScreenLineBuffer + KdpScreenLineBufferPos);
00386 
00387             /* Clear line buffer */
00388             KdpScreenLineBuffer[0] = '\0';
00389             KdpScreenLineLength = KdpScreenLineBufferPos = 0;
00390         }
00391 
00392         ++pch;
00393     }
00394 
00395     /* Print buffered characters */
00396     if(KdpScreenLineBufferPos != KdpScreenLineLength)
00397     {
00398         HalDisplayString(KdpScreenLineBuffer + KdpScreenLineBufferPos);
00399         KdpScreenLineBufferPos = KdpScreenLineLength;
00400     }
00401 
00402     /* Dmesg: store Message in the buffer to show it later */
00403     if (KdbpIsInDmesgMode)
00404        return;
00405 
00406     if (KdpDmesgBuffer == NULL)
00407       return;
00408 
00409     /* Acquire the printing spinlock without waiting at raised IRQL */
00410     while (TRUE)
00411     {
00412         /* Wait when the spinlock becomes available */
00413         while (!KeTestSpinLock(&KdpDmesgLogSpinLock));
00414 
00415         /* Spinlock was free, raise IRQL */
00416         KeRaiseIrql(HIGH_LEVEL, &OldIrql);
00417 
00418         /* Try to get the spinlock */
00419         if (KeTryToAcquireSpinLockAtDpcLevel(&KdpDmesgLogSpinLock))
00420             break;
00421 
00422         /* Someone else got the spinlock, lower IRQL back */
00423         KeLowerIrql(OldIrql);
00424     }
00425 
00426     /* Invariant: always_true(KdpDmesgFreeBytes == KdpDmesgBufferSize);
00427      * set num to min(KdpDmesgFreeBytes, Length).
00428      */
00429     num = (Length < KdpDmesgFreeBytes) ? Length : KdpDmesgFreeBytes; 
00430     beg = KdpDmesgCurrentPosition;
00431     if (num != 0)
00432     {
00433         end = (beg + num) % KdpDmesgBufferSize;
00434         if (end > beg)
00435         {
00436             RtlCopyMemory(KdpDmesgBuffer + beg, Message, Length);
00437         }
00438         else
00439         {
00440             RtlCopyMemory(KdpDmesgBuffer + beg, Message, KdpDmesgBufferSize - beg);
00441             RtlCopyMemory(KdpDmesgBuffer, Message + (KdpDmesgBufferSize - beg), end);
00442         }
00443         KdpDmesgCurrentPosition = end;
00444 
00445         /* Counting the total bytes written */
00446         KdbDmesgTotalWritten += num;
00447     }
00448 
00449     /* Release spinlock */
00450     KiReleaseSpinLock(&KdpDmesgLogSpinLock);
00451 
00452     /* Lower IRQL */
00453     KeLowerIrql(OldIrql);
00454 
00455     /* Optional step(?): find out a way to notify about buffer exhaustion,
00456      * and possibly fall into kbd to use dmesg command: user will read
00457      * debug messages before they will be wiped over by next writes.
00458      */
00459 }
00460 
00461 VOID
00462 NTAPI
00463 KdpScreenInit(PKD_DISPATCH_TABLE DispatchTable,
00464               ULONG BootPhase)
00465 {
00466     SIZE_T MemSizeMBs;
00467     if (!KdpDebugMode.Screen) return;
00468 
00469     if (BootPhase == 0)
00470     {
00471         /* Write out the functions that we support for now */
00472         DispatchTable->KdpInitRoutine = KdpScreenInit;
00473         DispatchTable->KdpPrintRoutine = KdpScreenPrint;
00474 
00475         /* Register as a Provider */
00476         InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
00477     }
00478     else if (BootPhase == 1)
00479     {
00480       /* Allocate a buffer for dmesg log buffer. +1 for terminating null,
00481        * see kdbp_cli.c:KdbpCmdDmesg()/2
00482        */
00483       KdpDmesgBuffer = ExAllocatePool(NonPagedPool, KdpDmesgBufferSize + 1);
00484       RtlZeroMemory(KdpDmesgBuffer, KdpDmesgBufferSize + 1);
00485       KdpDmesgFreeBytes = KdpDmesgBufferSize;
00486       KdbDmesgTotalWritten = 0;
00487 
00488       /* Take control of the display */
00489       InbvAcquireDisplayOwnership();
00490       InbvResetDisplay();
00491       InbvSolidColorFill(0, 0, 639, 479, 0);
00492       InbvSetTextColor(15);
00493       InbvSetScrollRegion(0, 0, 639, 479);
00494       InbvInstallDisplayStringFilter(NULL);
00495       InbvEnableDisplayString(TRUE);
00496 
00497       /* Initialize spinlock */
00498       KeInitializeSpinLock(&KdpDmesgLogSpinLock);
00499 
00500       /* Display separator + ReactOS version at start of the debug log */
00501       DPRINT1("-----------------------------------------------------\n");
00502       DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build "KERNEL_VERSION_BUILD_STR")\n");
00503       MemSizeMBs = MmNumberOfPhysicalPages * PAGE_SIZE / 1024 / 1024;
00504       DPRINT1("%u System Processor [%u MB Memory]\n", KeNumberProcessors, MemSizeMBs);
00505       DPRINT1("Command Line: %s\n", KeLoaderBlock->LoadOptions);
00506       DPRINT1("ARC Paths: %s %s %s %s\n", KeLoaderBlock->ArcBootDeviceName,
00507                                           KeLoaderBlock->NtHalPathName,
00508                                           KeLoaderBlock->ArcHalDeviceName,
00509                                           KeLoaderBlock->NtBootPathName);
00510     }
00511     else if (BootPhase == 2)
00512     {
00513         HalDisplayString("\n   Screen debugging enabled\n\n");
00514     }
00515 }
00516 
00517 /* GENERAL FUNCTIONS *********************************************************/
00518 
00519 ULONG
00520 NTAPI
00521 KdpPrintString(LPSTR String,
00522                ULONG Length)
00523 {
00524     PLIST_ENTRY CurrentEntry;
00525     PKD_DISPATCH_TABLE CurrentTable;
00526 
00527     if (!KdpDebugMode.Value) return 0;
00528 
00529     /* Call the registered handlers */
00530     CurrentEntry = KdProviders.Flink;
00531     while (CurrentEntry != &KdProviders)
00532     {
00533         /* Get the current table */
00534         CurrentTable = CONTAINING_RECORD(CurrentEntry,
00535                                          KD_DISPATCH_TABLE,
00536                                          KdProvidersList);
00537 
00538         /* Call it */
00539         CurrentTable->KdpPrintRoutine(String, Length);
00540 
00541         /* Next Table */
00542         CurrentEntry = CurrentEntry->Flink;
00543     }
00544 
00545     /* Call the Wrapper Routine */
00546     if (WrapperTable.KdpPrintRoutine)
00547         WrapperTable.KdpPrintRoutine(String, Length);
00548 
00549     /* Return the Length */
00550     return Length;
00551 }
00552 
00553 /* EOF */

Generated on Sun May 27 2012 04:37:19 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.