Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562/* * COPYRIGHT: GPL, see COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: drivers/base/kdvm/kdvm.c * PURPOSE: VM independent function for kdvbox/kd * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) */
#include "kdvm.h"
static CHAR KdVmCmdMagic[] = "~kdVMvA ";static CHAR KdVmReplyMagic[] = "++kdVMvA ";static const UCHAR KDVM_CMD_TestConnection = 't';static const UCHAR KDVM_CMD_ReceivePacket = 'r';static const UCHAR KDVM_CMD_SendPacket = 's';static const UCHAR KDVM_CMD_VersionReport = 'v';
UCHAR KdVmDataBuffer[KDVM_BUFFER_SIZE];PHYSICAL_ADDRESS KdVmBufferPhysicalAddress;ULONG KdVmBufferPos;
PFNDBGPRNT KdpDbgPrint;
/* PRIVATE FUNCTIONS **********************************************************/
staticVOIDKdVmDbgDumpRow( _In_ PUCHAR Buffer, _In_ ULONG Size){ ULONG i; for (i = 0;i < Size; i++) { KdpDbgPrint("%02x ", Buffer[i]); } KdpDbgPrint("\n");}
VOIDNTAPIKdVmDbgDumpBuffer( _In_ PVOID Buffer, _In_ ULONG Size){ PUCHAR CurrentRow; ULONG i;
CurrentRow = Buffer; for (i = 0; i < (Size / 16); i++) { KdVmDbgDumpRow(CurrentRow, 16); CurrentRow += 16; } KdVmDbgDumpRow(CurrentRow, (Size % 16));}
staticBOOLEANKdVmAddToBuffer( _In_ PVOID Data, _In_ ULONG DataSize){ if (((KdVmBufferPos + DataSize) > KDVM_BUFFER_SIZE) || ((KdVmBufferPos + DataSize) < KdVmBufferPos)) { KDDBGPRINT("KdVmAddToBuffer: Buffer overflow! Need %lu, remaining: %lu\n", DataSize, KDVM_BUFFER_SIZE - KdVmBufferPos); return FALSE; }
RtlCopyMemory(&KdVmDataBuffer[KdVmBufferPos], Data, DataSize); KdVmBufferPos += DataSize; return TRUE;}
staticBOOLEANKdVmAddCommandToBuffer( _In_ UCHAR Command, _In_ PVOID Buffer, _In_ SIZE_T BufferSize){ KDVM_CMD_HEADER Header;
RtlCopyMemory(&Header.Magic, KdVmCmdMagic, sizeof(Header.Magic)); Header.Command = Command;
if (!KdVmAddToBuffer(&Header, sizeof(Header))) return FALSE;
if (!KdVmAddToBuffer(Buffer, BufferSize)) return FALSE;
return TRUE;}
staticPVOIDKdVmSendReceive( _Out_ PULONG ReceiveDataSize){ PVOID ReceiveData; PKDVM_RECEIVE_HEADER ReceiveHeader;
KdVmKdVmExchangeData(&ReceiveData, ReceiveDataSize); ReceiveHeader = ReceiveData;
if (*ReceiveDataSize < sizeof(*ReceiveHeader)) { KDDBGPRINT("KdVmSendReceive: received data too small: 0x%x\n", *ReceiveDataSize); *ReceiveDataSize = 0; return NULL; }
if (ReceiveHeader->Id != 0x2031 /* '01' */) { KDDBGPRINT("KdVmSendReceive: got invalid Id: 0x%x\n", ReceiveHeader->Id); *ReceiveDataSize = 0; return NULL; }
if (!RtlEqualMemory(ReceiveHeader->Magic, KdVmReplyMagic, 9)) { KDDBGPRINT("KdVmSendReceive: got invalid Magic: '%*s'\n", sizeof(KdVmReplyMagic), ReceiveHeader->Magic); *ReceiveDataSize = 0; return NULL; }
*ReceiveDataSize -= sizeof(*ReceiveHeader); return (PVOID)(ReceiveHeader + 1);}
staticNTSTATUSKdVmNegotiateProtocolVersions(VOID){ ULONG Version = KDRPC_PROTOCOL_VERSION; ULONG ReceivedSize; PULONG ReceivedVersion; KDDBGPRINT("KdVmNegotiateProtocolVersions()\n");
/* Prepare the buffer */ KdVmPrepareBuffer();
if (!KdVmAddCommandToBuffer(KDVM_CMD_VersionReport, &Version, sizeof(Version))) { KDDBGPRINT("Failed to do VersionReport\n"); return STATUS_CONNECTION_REFUSED; }
ReceivedVersion = KdVmSendReceive(&ReceivedSize); if (ReceivedSize != sizeof(ULONG)) { KDDBGPRINT("Invalid size for VersionReport: %lx\n", ReceivedSize); return STATUS_CONNECTION_REFUSED; }
if (*ReceivedVersion != KDRPC_PROTOCOL_VERSION) { KDDBGPRINT("Invalid Version: %lx\n", *ReceivedVersion); return STATUS_CONNECTION_REFUSED; //STATUS_PROTOCOL_NOT_SUPPORTED; }
return STATUS_SUCCESS;}
staticBOOLEANTestConnectionOnChannel(VOID){ UCHAR TestBuffer[KDRPC_TEST_BUFFER_SIZE]; PUCHAR ReceivedBuffer; ULONG i, ReceivedSize;
/* Prepare the buffer */ KdVmPrepareBuffer();
for (i = 0; i < sizeof(TestBuffer); i++) TestBuffer[i] = (UCHAR)i;
if (!KdVmAddCommandToBuffer(KDVM_CMD_TestConnection, TestBuffer, sizeof(TestBuffer))) { KDDBGPRINT("Failed to do TestConnection\n"); return FALSE; }
ReceivedBuffer = KdVmSendReceive(&ReceivedSize); if (ReceivedSize != sizeof(TestBuffer)) { KDDBGPRINT("Invalid size for TestConnection: %lx\n", ReceivedSize); return FALSE; }
for (i = 0; i < sizeof(TestBuffer); i++) { if (ReceivedBuffer[i] != (UCHAR)(i ^ 0x55)) { KDDBGPRINT("Wrong test data @ %lx, expected %x, got %x\n", i, (UCHAR)(i ^ 0x55), TestBuffer[i]); return FALSE; } }
KDDBGPRINT("TestConnectionOnChannel: success\n"); return TRUE;}
staticBOOLEANKdVmTestConnectionWithHost(VOID){ ULONG i, j; KDDBGPRINT("KdVmTestConnectionWithHost()\n");
for (j = 0; j < 2; j++) { //VMWareRPC::OpenChannel for (i = 0; i < CONNECTION_TEST_ROUNDS / 2; i++) { if (!TestConnectionOnChannel()) { return FALSE; } } }
return TRUE;}
/* PUBLIC FUNCTIONS ***********************************************************/
NTSTATUSNTAPIKdD0Transition(VOID){ /* Nothing to do */ return STATUS_SUCCESS;}
NTSTATUSNTAPIKdD3Transition(VOID){ /* Nothing to do */ return STATUS_SUCCESS;}
NTSTATUSNTAPIKdSave( _In_ BOOLEAN SleepTransition){ /* Nothing to do */ return STATUS_SUCCESS;}
NTSTATUSNTAPIKdRestore( _In_ BOOLEAN SleepTransition){ /* Nothing to do */ return STATUS_SUCCESS;}
/****************************************************************************** * \name KdDebuggerInitialize0 * \brief Phase 0 initialization. * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL. * \return Status */NTSTATUSNTAPIKdDebuggerInitialize0( _In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock){ PCHAR CommandLine, PortString; NTSTATUS Status;
/* Check if we have a LoaderBlock */ if (LoaderBlock != NULL) { /* HACK */ KdpDbgPrint = LoaderBlock->u.I386.CommonDataArea; KDDBGPRINT("KdDebuggerInitialize0\n");
/* Get the Command Line */ CommandLine = LoaderBlock->LoadOptions;
/* Upcase it */ _strupr(CommandLine);
/* Check if we got the /DEBUGPORT parameter */ PortString = strstr(CommandLine, "DEBUGPORT"); if (PortString) { /* Move past the actual string, to reach the port*/ PortString += strlen("DEBUGPORT");
/* Now get past any spaces and skip the equal sign */ while (*PortString == ' ') PortString++; PortString++;
/* Do we have a serial port? */ if (strncmp(PortString, "VBOX", 4) != 0) { KDDBGPRINT("Invalid debugport: '%s'\n", CommandLine); return STATUS_INVALID_PARAMETER; } } }
/* Get the physical address of the data buffer */ KdVmBufferPhysicalAddress = MmGetPhysicalAddress(KdVmDataBuffer); KDDBGPRINT("KdVmBufferPhysicalAddress = %llx\n", KdVmBufferPhysicalAddress.QuadPart);
Status = KdVmNegotiateProtocolVersions(); if (!NT_SUCCESS(Status)) return Status;
if (!KdVmTestConnectionWithHost()) return STATUS_CONNECTION_REFUSED;
return STATUS_SUCCESS;}
/****************************************************************************** * \name KdDebuggerInitialize1 * \brief Phase 1 initialization. * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL. * \return Status */NTSTATUSNTAPIKdDebuggerInitialize1( _In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock){ /* Nothing to do */ KDDBGPRINT("KdDebuggerInitialize1()\n"); return STATUS_SUCCESS;}
VOIDNTAPIKdSendPacket( _In_ ULONG PacketType, _In_ PSTRING MessageHeader, _In_ PSTRING MessageData, _Inout_ PKD_CONTEXT KdContext){ KDVM_SEND_PKT_REQUEST SendPktRequest; PKDVM_SEND_PKT_RESULT SendPktResult; ULONG ReceivedSize; KDDBGPRINT("KdSendPacket(0x%lx, ...)\n", PacketType);
do {
RtlZeroMemory(&SendPktRequest, sizeof(SendPktRequest));
SendPktRequest.PacketType = PacketType; SendPktRequest.Info.KdDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT; SendPktRequest.Info.KdDebuggerEnabledAvailable = 1; SendPktRequest.Info.KdDebuggerEnabled = SharedUserData->KdDebuggerEnabled;
if (MessageHeader != NULL) { SendPktRequest.MessageHeader.Length = MessageHeader->Length; SendPktRequest.MessageHeader.MaximumLength = MessageHeader->MaximumLength; SendPktRequest.HeaderSize = MessageHeader->Length; }
if (MessageData != NULL) { SendPktRequest.MessageData.Length = MessageData->Length; SendPktRequest.MessageData.MaximumLength = MessageData->MaximumLength; SendPktRequest.DataSize = MessageData->Length; }
if (KdContext != NULL) { RtlCopyMemory(&SendPktRequest.KdContext, KdContext, sizeof(SendPktRequest.KdContext)); }
/* Prepare the buffer */ KdVmPrepareBuffer();
if (!KdVmAddCommandToBuffer(KDVM_CMD_SendPacket, &SendPktRequest, sizeof(SendPktRequest))) { KDDBGPRINT("KdSendPacket: Failed to add SendPacket command\n"); return; }
if (MessageHeader != NULL) { if (!KdVmAddToBuffer(MessageHeader->Buffer, MessageHeader->Length)) { KDDBGPRINT("KdSendPacket: Failed to add MessageHeader\n"); return; } }
if (MessageData != NULL) { if (!KdVmAddToBuffer(MessageData->Buffer, MessageData->Length)) { KDDBGPRINT("KdSendPacket: Failed to add MessageData\n"); return; } }
SendPktResult = KdVmSendReceive(&ReceivedSize); if (ReceivedSize != sizeof(*SendPktResult)) { KDDBGPRINT("KdSendPacket: Invalid size for SendPktResult: %lx\n", ReceivedSize); return; }
if (KdContext != NULL) { RtlCopyMemory(KdContext, &SendPktResult->KdContext, sizeof(SendPktResult->KdContext)); }
KD_DEBUGGER_NOT_PRESENT = SendPktResult->Info.KdDebuggerNotPresent; if (SendPktResult->Info.KdDebuggerEnabledAvailable) SharedUserData->KdDebuggerEnabled = SendPktResult->Info.KdDebuggerEnabled != 0;
if (SendPktResult->Info.RetryKdSendPacket) { KDDBGPRINT("KdSendPacket: RetryKdSendPacket!\n"); }
} while (SendPktResult->Info.RetryKdSendPacket);
KDDBGPRINT("KdSendPacket: Success!\n");}
KDP_STATUSNTAPIKdReceivePacket( _In_ ULONG PacketType, _Out_ PSTRING MessageHeader, _Out_ PSTRING MessageData, _Out_ PULONG DataLength, _Inout_opt_ PKD_CONTEXT KdContext){ KDVM_RECV_PKT_REQUEST RecvPktRequest; PKDVM_RECV_PKT_RESULT RecvPktResult; ULONG ReceivedSize, ExpectedSize; PUCHAR Buffer; KDDBGPRINT("KdReceivePacket(0x%lx, ...)\n", PacketType);
/* Prepare the buffer */ KdVmPrepareBuffer();
RtlZeroMemory(&RecvPktRequest, sizeof(RecvPktRequest));
RecvPktRequest.PacketType = PacketType; RecvPktRequest.Info.KdDebuggerNotPresent = KD_DEBUGGER_NOT_PRESENT; RecvPktRequest.Info.KdDebuggerEnabledAvailable = 1; RecvPktRequest.Info.KdDebuggerEnabled = SharedUserData->KdDebuggerEnabled;
if (MessageHeader != NULL) { RecvPktRequest.MessageHeader.Length = MessageHeader->Length; RecvPktRequest.MessageHeader.MaximumLength = MessageHeader->MaximumLength; }
if (MessageData != NULL) { RecvPktRequest.MessageData.Length = MessageData->Length; RecvPktRequest.MessageData.MaximumLength = MessageData->MaximumLength; }
if (KdContext != NULL) { RtlCopyMemory(&RecvPktRequest.KdContext, KdContext, sizeof(RecvPktRequest.KdContext)); }
if (!KdVmAddCommandToBuffer(KDVM_CMD_ReceivePacket, &RecvPktRequest, sizeof(RecvPktRequest))) { KDDBGPRINT("KdReceivePacket: Failed to add SendPacket command\n"); return KDP_PACKET_RESEND; }
RecvPktResult = KdVmSendReceive(&ReceivedSize); if (ReceivedSize < sizeof(*RecvPktResult)) { KDDBGPRINT("KdReceivePacket: Invalid size for RecvPktResult: %lx\n", ReceivedSize); return KDP_PACKET_RESEND; }
ExpectedSize = sizeof(*RecvPktResult) + RecvPktResult->HeaderSize + RecvPktResult->DataSize; if (ReceivedSize != ExpectedSize) { KDDBGPRINT("KdReceivePacket: Invalid size for RecvPktResult: %lu, expected %lu\n", ReceivedSize, ExpectedSize); return KDP_PACKET_RESEND; }
if (KdContext != NULL) { RtlCopyMemory(KdContext, &RecvPktResult->KdContext, sizeof(RecvPktResult->KdContext)); }
Buffer = (PUCHAR)(RecvPktResult + 1); if (MessageHeader != NULL) { MessageHeader->Length = RecvPktResult->MessageHeader.Length; if ((MessageHeader->Buffer != NULL) && (MessageHeader->MaximumLength >= RecvPktResult->HeaderSize)) { RtlCopyMemory(MessageHeader->Buffer, Buffer, RecvPktResult->HeaderSize); } else { KDDBGPRINT("MessageHeader not good\n"); } }
Buffer += RecvPktResult->HeaderSize; if (MessageData != NULL) { MessageData->Length = RecvPktResult->MessageData.Length; if ((MessageData->Buffer != NULL) && (MessageData->MaximumLength >= RecvPktResult->DataSize)) { RtlCopyMemory(MessageData->Buffer, Buffer, RecvPktResult->DataSize); } else { KDDBGPRINT("MessageData not good\n"); } }
if (DataLength != NULL) *DataLength = RecvPktResult->FullSize;
KDDBGPRINT("KdReceivePacket: returning status %u\n", RecvPktResult->KdStatus); return RecvPktResult->KdStatus;}