mirror of
https://github.com/reactos/reactos.git
synced 2025-04-05 21:21:33 +00:00
[KDVBOX]
Implement a virtualkd compatible kernel debugger transport DLL. I started this, because I didn't manage to get the original one working, but it turned out, the original one works, you only need to use the correct virtualkd version. Anyway, it's there now. A virtualkd version that works with VBox 4.3.16+ can be found here: http://forum.sysprogs.com/viewtopic.php?f=4&t=3370 or here: http://public.avast.com/~hnanicek/VirtualKd.zip The folder is called kdvm, since I thought about adding support for VMWare as well, but here the original one probably works as well. Also fix my email address in some files. svn path=/trunk/; revision=65813
This commit is contained in:
parent
a9305dd7bb
commit
69512e2d9b
14 changed files with 836 additions and 5 deletions
|
@ -477,7 +477,13 @@ CreateFreeLoaderIniForReactos(
|
|||
L"ReactOS_Debug", L"\"ReactOS (Debug)\"",
|
||||
L"Windows2003", ArcPath,
|
||||
L"/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200 /SOS");
|
||||
|
||||
#ifdef _WINKD_
|
||||
/* ReactOS_VBoxDebug */
|
||||
CreateFreeLoaderEntry(IniCache, IniSection,
|
||||
L"ReactOS_VBoxDebug", L"\"ReactOS (VBoxDebug)\"",
|
||||
L"Windows2003", ArcPath,
|
||||
L"/DEBUG /DEBUGPORT=VBOX /SOS");
|
||||
#endif
|
||||
#if DBG
|
||||
#ifndef _WINKD_
|
||||
/* ReactOS_KdSerial */
|
||||
|
|
|
@ -30,6 +30,7 @@ cdrom.sys=,,,,,,x,,,,,,4
|
|||
class2.sys=,,,,,,x,,,,,,4
|
||||
isapnp.sys=,,,,,,,,,,,,4
|
||||
kdcom.dll=,,,,,,,,,,,,2
|
||||
kdvbox.dll=,,,,,,,,,,,,2
|
||||
disk.sys=,,,,,,x,,,,,,4
|
||||
floppy.sys=,,,,,,x,,,,,,4
|
||||
i8042prt.sys=,,,,,,,,,,,,4
|
||||
|
|
|
@ -8,6 +8,7 @@ if(_WINKD_)
|
|||
add_subdirectory(kdgdb)
|
||||
else()
|
||||
add_subdirectory(kdcom)
|
||||
add_subdirectory(kdvm)
|
||||
endif()
|
||||
else()
|
||||
add_subdirectory(kdrosdbg)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kdcom.c
|
||||
* PURPOSE: COM port functions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#include "kddll.h"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kddll.c
|
||||
* PURPOSE: Base functions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#include "kddll.h"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kddll.h
|
||||
* PURPOSE: Base definitions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#ifndef _KDDLL_H_
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kdserial.c
|
||||
* PURPOSE: Serial communication functions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org)
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#include "kddll.h"
|
||||
|
|
15
reactos/drivers/base/kdvm/CMakeLists.txt
Normal file
15
reactos/drivers/base/kdvm/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
spec2def(kdvbox.dll kdvm.spec)
|
||||
|
||||
add_library(kdvbox SHARED
|
||||
kdvm.c
|
||||
kdvbox.c
|
||||
kdvbox_asm.S
|
||||
kdvm.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/kdvbox.def)
|
||||
|
||||
set_module_type(kdvbox module IMAGEBASE 0x00010000)
|
||||
set_subsystem(kdvbox native)
|
||||
add_importlibs(kdvbox ntoskrnl hal)
|
||||
add_dependencies(kdvbox psdk bugcodes)
|
||||
add_cd_file(TARGET kdvbox DESTINATION reactos/system32 NO_CAB FOR all)
|
60
reactos/drivers/base/kdvm/kdvbox.c
Normal file
60
reactos/drivers/base/kdvm/kdvbox.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kdvm/kdvbox.c
|
||||
* PURPOSE: VBOX data exchange function for kdvbox
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#include "kdvm.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG SendSize;
|
||||
ULONG BufferSize;
|
||||
} KDVBOX_SEND_HEADER, *PKDVBOX_SEND_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG ReceivedDataSize;
|
||||
} KDVBOX_RECEIVE_HEADER, *PKDVBOX_RECEIVE_HEADER;
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdVmPrepareBuffer(VOID)
|
||||
{
|
||||
KdVmBufferPos = sizeof(KDVBOX_SEND_HEADER);
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdVmKdVmExchangeData(
|
||||
_Out_ PVOID* ReceiveData,
|
||||
_Out_ PULONG ReceiveDataSize)
|
||||
{
|
||||
PKDVBOX_SEND_HEADER SendHeader;
|
||||
PKDVBOX_RECEIVE_HEADER ReceiveHeader;
|
||||
|
||||
/* Setup the send-header */
|
||||
SendHeader = (PKDVBOX_SEND_HEADER)KdVmDataBuffer;
|
||||
SendHeader->SendSize = KdVmBufferPos - sizeof(KDVBOX_SEND_HEADER);
|
||||
SendHeader->BufferSize = KDVM_BUFFER_SIZE;
|
||||
|
||||
//KdpDbgPrint("Sending buffer:\n");
|
||||
//KdVmDbgDumpBuffer(KdVmDataBuffer, KdVmBufferPos);
|
||||
|
||||
/* Do the data exchange */
|
||||
KdVmExchange((ULONG_PTR)KdVmBufferPhysicalAddress.QuadPart, 0);
|
||||
|
||||
/* Reset the buffer position */
|
||||
KdVmBufferPos = sizeof(KDVBOX_SEND_HEADER);
|
||||
|
||||
/* Get the receive-header and return information about the received data */
|
||||
ReceiveHeader = (PKDVBOX_RECEIVE_HEADER)KdVmDataBuffer;
|
||||
*ReceiveData = KdVmDataBuffer + sizeof(KDVBOX_RECEIVE_HEADER);
|
||||
*ReceiveDataSize = ReceiveHeader->ReceivedDataSize;
|
||||
|
||||
//KdpDbgPrint("got data:\n");
|
||||
//KdVmDbgDumpBuffer(KdVmDataBuffer, *ReceiveDataSize + sizeof(*ReceiveHeader));
|
||||
|
||||
}
|
24
reactos/drivers/base/kdvm/kdvbox_asm.S
Normal file
24
reactos/drivers/base/kdvm/kdvbox_asm.S
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
#include <asm.inc>
|
||||
|
||||
.code
|
||||
|
||||
#ifdef _M_IX86
|
||||
PUBLIC @KdVmExchange@8
|
||||
FUNC @KdVmExchange@8
|
||||
xchg eax, ecx
|
||||
mov edx, HEX(5659)
|
||||
out dx, eax
|
||||
ret
|
||||
ENDFUNC
|
||||
#else
|
||||
PUBLIC KdVmExchange
|
||||
FUNC KdVmExchange
|
||||
xchg rax, rcx
|
||||
mov edx, HEX(5659)
|
||||
out dx, rax
|
||||
ret
|
||||
ENDFUNC
|
||||
#endif
|
||||
|
||||
END
|
561
reactos/drivers/base/kdvm/kdvm.c
Normal file
561
reactos/drivers/base/kdvm/kdvm.c
Normal file
|
@ -0,0 +1,561 @@
|
|||
/*
|
||||
* 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 **********************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
KdVmDbgDumpRow(
|
||||
_In_ PUCHAR Buffer,
|
||||
_In_ ULONG Size)
|
||||
{
|
||||
ULONG i;
|
||||
for (i = 0;i < Size; i++)
|
||||
{
|
||||
KdpDbgPrint("%02x ", Buffer[i]);
|
||||
}
|
||||
KdpDbgPrint("\n");
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdVmDbgDumpBuffer(
|
||||
_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));
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
KdVmAddToBuffer(
|
||||
_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;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
KdVmAddCommandToBuffer(
|
||||
_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;
|
||||
}
|
||||
|
||||
static
|
||||
PVOID
|
||||
KdVmSendReceive(
|
||||
_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);
|
||||
}
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
KdVmNegotiateProtocolVersions(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;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
TestConnectionOnChannel(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;
|
||||
}
|
||||
|
||||
static
|
||||
BOOLEAN
|
||||
KdVmTestConnectionWithHost(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 ***********************************************************/
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdD0Transition(VOID)
|
||||
{
|
||||
/* Nothing to do */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdD3Transition(VOID)
|
||||
{
|
||||
/* Nothing to do */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdSave(
|
||||
_In_ BOOLEAN SleepTransition)
|
||||
{
|
||||
/* Nothing to do */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdRestore(
|
||||
_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
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdDebuggerInitialize0(
|
||||
_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", 3) != 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
|
||||
*/
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdDebuggerInitialize1(
|
||||
_In_opt_ PLOADER_PARAMETER_BLOCK LoaderBlock)
|
||||
{
|
||||
/* Nothing to do */
|
||||
KDDBGPRINT("KdDebuggerInitialize1()\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdSendPacket(
|
||||
_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_STATUS
|
||||
NTAPI
|
||||
KdReceivePacket(
|
||||
_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;
|
||||
}
|
||||
|
150
reactos/drivers/base/kdvm/kdvm.h
Normal file
150
reactos/drivers/base/kdvm/kdvm.h
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kdvm/kdvm.h
|
||||
* PURPOSE: Base definitions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#ifndef _KDDLL_H_
|
||||
#define _KDDLL_H_
|
||||
|
||||
#define NOEXTAPI
|
||||
#include <ntifs.h>
|
||||
#include <windbgkd.h>
|
||||
#include <arc/arc.h>
|
||||
|
||||
#undef RtlEqualMemory
|
||||
#define RtlEqualMemory(a, b, c) (RtlCompareMemory(a, b, c) != c)
|
||||
|
||||
//#define KDDEBUG /* uncomment to enable debugging this dll */
|
||||
|
||||
typedef ULONG (*PFNDBGPRNT)(const char *Format, ...);
|
||||
extern PFNDBGPRNT KdpDbgPrint;
|
||||
|
||||
#ifndef KDDEBUG
|
||||
#define KDDBGPRINT(...)
|
||||
#else
|
||||
#define KDDBGPRINT KdpDbgPrint
|
||||
#endif
|
||||
|
||||
#define KDRPC_PROTOCOL_VERSION 0x101
|
||||
#define CONNECTION_TEST_ROUNDS 2 /*100*/
|
||||
#define KDVM_BUFFER_SIZE (131072 + 1024)
|
||||
#define KDRPC_TEST_BUFFER_SIZE 512
|
||||
|
||||
extern UCHAR KdVmDataBuffer[KDVM_BUFFER_SIZE];
|
||||
extern PHYSICAL_ADDRESS KdVmBufferPhysicalAddress;
|
||||
extern ULONG KdVmBufferPos;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KDP_PACKET_RECEIVED = 0,
|
||||
KDP_PACKET_TIMEOUT = 1,
|
||||
KDP_PACKET_RESEND = 2
|
||||
} KDP_STATUS;
|
||||
|
||||
typedef struct _KDVM_MARSHAL_STRING
|
||||
{
|
||||
USHORT Length;
|
||||
USHORT MaximumLength;
|
||||
} KDVM_MARSHAL_STRING;
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct
|
||||
{
|
||||
CHAR Magic[8];
|
||||
UCHAR Command;
|
||||
} KDVM_CMD_HEADER;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
USHORT Id;
|
||||
CHAR Magic[9];
|
||||
} KDVM_RECEIVE_HEADER, *PKDVM_RECEIVE_HEADER;
|
||||
|
||||
typedef struct _KDVM_CONTEXT
|
||||
{
|
||||
ULONG RetryCount;
|
||||
BOOLEAN BreakInRequested;
|
||||
UCHAR align;
|
||||
} KDVM_CONTEXT, *PKDVM_CONTEXT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
UCHAR KdDebuggerNotPresent : 1;
|
||||
UCHAR RetryKdSendPacket : 1;
|
||||
UCHAR KdDebuggerEnabledAvailable : 1;
|
||||
};
|
||||
BOOLEAN KdDebuggerEnabled;
|
||||
USHORT Unused;
|
||||
} KDVM_SENDPACKET_INFO;
|
||||
|
||||
typedef struct _KDVM_SEND_PKT_REQUEST
|
||||
{
|
||||
KDVM_MARSHAL_STRING MessageHeader;
|
||||
KDVM_MARSHAL_STRING MessageData;
|
||||
KDVM_CONTEXT KdContext;
|
||||
ULONG PacketType;
|
||||
ULONG HeaderSize;
|
||||
ULONG DataSize;
|
||||
KDVM_SENDPACKET_INFO Info;
|
||||
} KDVM_SEND_PKT_REQUEST, *PKDVM_SEND_PKT_REQUEST;
|
||||
|
||||
typedef struct _KDVM_SEND_PKT_RESULT
|
||||
{
|
||||
UCHAR CommandType;
|
||||
KDVM_CONTEXT KdContext;
|
||||
KDVM_SENDPACKET_INFO Info;
|
||||
} KDVM_SEND_PKT_RESULT, *PKDVM_SEND_PKT_RESULT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ULONG PacketType;
|
||||
KDVM_SENDPACKET_INFO Info;
|
||||
KDVM_MARSHAL_STRING MessageHeader;
|
||||
KDVM_MARSHAL_STRING MessageData;
|
||||
KDVM_CONTEXT KdContext;
|
||||
} KDVM_RECV_PKT_REQUEST;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UCHAR CommandType;
|
||||
KDVM_MARSHAL_STRING MessageHeader;
|
||||
KDVM_MARSHAL_STRING MessageData;
|
||||
KDVM_CONTEXT KdContext;
|
||||
KDP_STATUS KdStatus;
|
||||
ULONG FullSize;
|
||||
ULONG HeaderSize;
|
||||
ULONG DataSize;
|
||||
KDVM_SENDPACKET_INFO Info;
|
||||
} KDVM_RECV_PKT_RESULT, *PKDVM_RECV_PKT_RESULT;
|
||||
#pragma pack(pop)
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdVmDbgDumpBuffer(
|
||||
_In_ PVOID Buffer,
|
||||
_In_ ULONG Size);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
KdVmExchange(
|
||||
_In_ ULONG_PTR PhysicalAddress,
|
||||
_In_ SIZE_T BufferSize);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdVmPrepareBuffer(
|
||||
VOID);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdVmKdVmExchangeData(
|
||||
_Out_ PVOID* ReceiveData,
|
||||
_Out_ PULONG ReceiveDataSize);
|
||||
|
||||
|
||||
#endif /* _KDDLL_H_ */
|
5
reactos/drivers/base/kdvm/kdvm.rc
Normal file
5
reactos/drivers/base/kdvm/kdvm.rc
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Kernel Debugger COM Extension DLL"
|
||||
#define REACTOS_STR_INTERNAL_NAME "kdcom"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "kdcom.dll"
|
||||
#include <reactos/version.rc>
|
8
reactos/drivers/base/kdvm/kdvm.spec
Normal file
8
reactos/drivers/base/kdvm/kdvm.spec
Normal file
|
@ -0,0 +1,8 @@
|
|||
@ stdcall KdD0Transition()
|
||||
@ stdcall KdD3Transition()
|
||||
@ stdcall KdDebuggerInitialize0(ptr)
|
||||
@ stdcall KdDebuggerInitialize1(ptr)
|
||||
@ stdcall KdReceivePacket(long ptr ptr ptr ptr)
|
||||
@ stdcall KdRestore(long)
|
||||
@ stdcall KdSave(long)
|
||||
@ stdcall KdSendPacket(long ptr ptr ptr)
|
Loading…
Reference in a new issue