/*++ Copyright (c) 1990-2001 Microsoft Corporation Module Name: kddbgio.c Abstract: This module implements kernel debugger based Dbg I/O. This is the foundation for DbgPrint and DbgPrompt. Author: Mark Lucovsky (markl) 31-Aug-1990 Revision History: --*/ #include "kdp.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGEKD, KdpPrintString) #pragma alloc_text(PAGEKD, KdpPromptString) #pragma alloc_text(PAGEKD, KdpAcquireBreakpoint) #endif BOOLEAN KdpPrintString ( IN PSTRING Output ) /*++ Routine Description: This routine prints a string. Arguments: Output - Supplies a pointer to a string descriptor for the output string. Return Value: TRUE if Control-C present in input buffer after print is done. FALSE otherwise. --*/ { ULONG Length; STRING MessageData; STRING MessageHeader; DBGKD_DEBUG_IO DebugIo; // // Move the output string to the message buffer. // KdpCopyFromPtr(KdpMessageBuffer, Output->Buffer, Output->Length, &Length); // // If the total message length is greater than the maximum packet size, // then truncate the output string. // if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE) { Length = PACKET_MAX_SIZE - sizeof(DBGKD_DEBUG_IO); } // // Construct the print string message and message descriptor. // DebugIo.ApiNumber = DbgKdPrintStringApi; DebugIo.ProcessorLevel = KeProcessorLevel; DebugIo.Processor = (USHORT)KeGetCurrentPrcb()->Number; DebugIo.u.PrintString.LengthOfString = Length; MessageHeader.Length = sizeof(DBGKD_DEBUG_IO); MessageHeader.Buffer = (PCHAR)&DebugIo; // // Construct the print string data and data descriptor. // MessageData.Length = (USHORT)Length; MessageData.Buffer = KdpMessageBuffer; // // Send packet to the kernel debugger on the host machine. // KdSendPacket( PACKET_TYPE_KD_DEBUG_IO, &MessageHeader, &MessageData, &KdpContext ); return KdpPollBreakInWithPortLock(); } BOOLEAN KdpPromptString ( IN PSTRING Output, IN OUT PSTRING Input ) /*++ Routine Description: This routine prints a string, then reads a reply string. Arguments: Output - Supplies a pointer to a string descriptor for the output string. Input - Supplies a pointer to a string descriptor for the input string. (Length stored/returned in Input->Length) Return Value: TRUE - A Breakin sequence was seen, caller should breakpoint and retry FALSE - No Breakin seen. --*/ { ULONG Length; STRING MessageData; STRING MessageHeader; DBGKD_DEBUG_IO DebugIo; ULONG ReturnCode; // // Move the output string to the message buffer. // KdpCopyFromPtr(KdpMessageBuffer, Output->Buffer, Output->Length, &Length); // // If the total message length is greater than the maximum packet size, // then truncate the output string. // if ((sizeof(DBGKD_DEBUG_IO) + Length) > PACKET_MAX_SIZE) { Length = PACKET_MAX_SIZE - sizeof(DBGKD_DEBUG_IO); } // // Construct the prompt string message and message descriptor. // DebugIo.ApiNumber = DbgKdGetStringApi; DebugIo.ProcessorLevel = KeProcessorLevel; DebugIo.Processor = (USHORT)KeGetCurrentPrcb()->Number; DebugIo.u.GetString.LengthOfPromptString = Length; DebugIo.u.GetString.LengthOfStringRead = Input->MaximumLength; MessageHeader.Length = sizeof(DBGKD_DEBUG_IO); MessageHeader.Buffer = (PCHAR)&DebugIo; // // Construct the prompt string data and data descriptor. // MessageData.Length = (USHORT)Length; MessageData.Buffer = KdpMessageBuffer; // // Send packet to the kernel debugger on the host machine. // KdSendPacket( PACKET_TYPE_KD_DEBUG_IO, &MessageHeader, &MessageData, &KdpContext ); // // Receive packet from the kernel debugger on the host machine. // MessageHeader.MaximumLength = sizeof(DBGKD_DEBUG_IO); MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE; do { ReturnCode = KdReceivePacket( PACKET_TYPE_KD_DEBUG_IO, &MessageHeader, &MessageData, &Length, &KdpContext ); if (ReturnCode == KDP_PACKET_RESEND) { return TRUE; } } while (ReturnCode != KDP_PACKET_RECEIVED); if (Length > Input->MaximumLength) { Length = Input->MaximumLength; } KdpCopyToPtr(Input->Buffer, KdpMessageBuffer, Length, &Length); Input->Length = (USHORT)Length; return FALSE; } BOOLEAN KdpAcquireBreakpoint( IN ULONG Number ) /*++ Routine Description: This routine prints a string, then reads a reply string. Arguments: Number - breakpoint register number being requested. Return Value: TRUE - Breakpoint now reserved for kernel use. FALSE - breakpoint not available. --*/ { ULONG Length; STRING MessageData; STRING MessageHeader; DBGKD_CONTROL_REQUEST ControlRequest; ULONG ReturnCode; // // Construct the prompt string message and message descriptor. // ControlRequest.ApiNumber = DbgKdRequestHardwareBp; ControlRequest.u.RequestBreakpoint.HardwareBreakPointNumber = Number; ControlRequest.u.RequestBreakpoint.Available = FALSE; MessageHeader.Length = sizeof(ControlRequest); MessageHeader.Buffer = (PCHAR)&ControlRequest; // // Send packet to the kernel debugger on the host machine. // KdSendPacket(PACKET_TYPE_KD_CONTROL_REQUEST, &MessageHeader, NULL, &KdpContext); // // Receive packet from the kernel debugger on the host machine. // MessageHeader.MaximumLength = sizeof(PACKET_TYPE_KD_CONTROL_REQUEST); MessageData.Buffer = KdpMessageBuffer; MessageData.Length = 0; MessageData.MaximumLength = KDP_MESSAGE_BUFFER_SIZE; do { ReturnCode = KdReceivePacket(PACKET_TYPE_KD_CONTROL_REQUEST, &MessageHeader, &MessageData, &Length, &KdpContext); if (ReturnCode == KDP_PACKET_RESEND) { return FALSE; } } while (ReturnCode != KDP_PACKET_RECEIVED); return (ControlRequest.u.RequestBreakpoint.Available == 1); }