mirror of
https://github.com/reactos/reactos
synced 2025-10-06 08:22:58 +02:00
Compare commits
4 Commits
taskmgr_ac
...
freeldr_kd
Author | SHA1 | Date | |
---|---|---|---|
|
5fee9d2e41 | ||
|
db271c2228 | ||
|
c1c8f59eab | ||
|
73af453c73 |
@@ -33,7 +33,8 @@ list(APPEND FREELDR_BOOTLIB_SOURCE
|
||||
lib/cache/blocklist.c
|
||||
lib/cache/cache.c
|
||||
lib/comm/rs232.c
|
||||
## add KD support
|
||||
../../../drivers/base/kdnet/kdnet.c
|
||||
lib/kdstub.c
|
||||
lib/fs/btrfs.c
|
||||
lib/fs/ext2.c
|
||||
lib/fs/fat.c
|
||||
|
@@ -23,6 +23,6 @@
|
||||
|
||||
BOOLEAN Rs232PortInitialize(ULONG ComPort, ULONG BaudRate);
|
||||
BOOLEAN Rs232PortGetByte(PUCHAR ByteReceived);
|
||||
// BOOLEAN Rs232PortPollByte(PUCHAR ByteReceived);
|
||||
BOOLEAN Rs232PortPollByte(PUCHAR ByteReceived);
|
||||
VOID Rs232PortPutByte(UCHAR ByteToSend);
|
||||
BOOLEAN Rs232PortInUse(PUCHAR Base);
|
||||
|
@@ -65,6 +65,7 @@
|
||||
#include <disk.h>
|
||||
#include <fs.h>
|
||||
#include <inifile.h>
|
||||
#include <kd.h>
|
||||
#include <keycodes.h>
|
||||
#include <linux.h>
|
||||
#include <custom.h>
|
||||
|
15
boot/freeldr/freeldr/include/kd.h
Normal file
15
boot/freeldr/freeldr/include/kd.h
Normal file
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* PROJECT: FreeLoader
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Kernel debugger header file for the FreeLoader
|
||||
* COPYRIGHT: Copyright 2001-2003 Brian Palmer <brianp@sginet.com>
|
||||
* Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <windbgkd.h>
|
||||
#include <kddll.h>
|
||||
#include <kdnetextensibility.h>
|
||||
|
||||
VOID DebugPrintChar(UCHAR Character);
|
@@ -121,13 +121,11 @@ BOOLEAN Rs232PortGetByte(PUCHAR ByteReceived)
|
||||
return (CpGetByte(&Rs232ComPortInfo, ByteReceived, TRUE, FALSE) == CP_GET_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
BOOLEAN Rs232PortPollByte(PUCHAR ByteReceived)
|
||||
{
|
||||
if (Rs232ComPort == 0) return FALSE;
|
||||
return (CpGetByte(&Rs232ComPortInfo, ByteReceived, FALSE, FALSE) == CP_GET_SUCCESS);
|
||||
}
|
||||
*/
|
||||
|
||||
VOID Rs232PortPutByte(UCHAR ByteToSend)
|
||||
{
|
||||
|
@@ -194,6 +194,13 @@ Done:
|
||||
if (!Rs232PortInitialize(ComPort, BaudRate))
|
||||
DebugPort &= ~RS232;
|
||||
}
|
||||
|
||||
{
|
||||
LOADER_PARAMETER_BLOCK LoaderBlock = {0};
|
||||
LoaderBlock.LoadOptions = (PCHAR)CmdLineGetDebugString();
|
||||
KdDebuggerInitialize0(&LoaderBlock);
|
||||
KdDebuggerInitialize1(&LoaderBlock);
|
||||
}
|
||||
}
|
||||
|
||||
VOID DebugPrintChar(UCHAR Character)
|
||||
@@ -218,12 +225,32 @@ VOID DebugPrintChar(UCHAR Character)
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
DbgPrintString(
|
||||
_In_ PCHAR Buffer,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
DBGKD_DEBUG_IO DebugIo = {0};
|
||||
STRING MessageHeader;
|
||||
STRING MessageData;
|
||||
|
||||
/* Prepare packet to send to debugger */
|
||||
DebugIo.ApiNumber = DbgKdPrintStringApi;
|
||||
DebugIo.u.PrintString.LengthOfString = Length;
|
||||
MessageHeader.Buffer = (PCHAR)&DebugIo;
|
||||
MessageHeader.Length = sizeof(DebugIo);
|
||||
MessageData.Buffer = Buffer;
|
||||
MessageData.Length = Length;
|
||||
|
||||
/* Send packet to debugger */
|
||||
KdSendPacket(PACKET_TYPE_KD_DEBUG_IO, &MessageHeader, &MessageData, NULL);
|
||||
}
|
||||
|
||||
ULONG
|
||||
DbgPrint(const char *Format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int Length;
|
||||
char* ptr;
|
||||
CHAR Buffer[512];
|
||||
|
||||
va_start(ap, Format);
|
||||
@@ -240,9 +267,7 @@ DbgPrint(const char *Format, ...)
|
||||
Length = sizeof(Buffer);
|
||||
}
|
||||
|
||||
ptr = Buffer;
|
||||
while (Length--)
|
||||
DebugPrintChar(*ptr++);
|
||||
DbgPrintString(Buffer, Length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -252,7 +277,7 @@ DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, .
|
||||
{
|
||||
va_list ap;
|
||||
char Buffer[2096];
|
||||
char *ptr = Buffer;
|
||||
int Length;
|
||||
|
||||
/* Mask out unwanted debug messages */
|
||||
if (!(DbgChannels[Mask] & Level) && !(Level & DBG_DEFAULT_LEVELS))
|
||||
@@ -285,13 +310,10 @@ DbgPrint2(ULONG Mask, ULONG Level, const char *File, ULONG Line, char *Format, .
|
||||
}
|
||||
|
||||
va_start(ap, Format);
|
||||
vsprintf(Buffer, Format, ap);
|
||||
Length = vsprintf(Buffer, Format, ap);
|
||||
va_end(ap);
|
||||
|
||||
while (*ptr)
|
||||
{
|
||||
DebugPrintChar(*ptr++);
|
||||
}
|
||||
DbgPrintString(Buffer, Length);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
197
boot/freeldr/freeldr/lib/kdstub.c
Normal file
197
boot/freeldr/freeldr/lib/kdstub.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* PROJECT: FreeLoader
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: I/O functions for the freeldr debugger
|
||||
* COPYRIGHT: Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
|
||||
*/
|
||||
|
||||
#include <freeldr.h>
|
||||
|
||||
static UCHAR KdTxMessageBuffer[4096];
|
||||
static UCHAR KdRxMessageBuffer[4096];
|
||||
|
||||
static NTSTATUS
|
||||
NTAPI
|
||||
KdpGetRxPacketWinKD(
|
||||
_In_ PVOID Adapter,
|
||||
_Out_ PULONG Handle,
|
||||
_Out_ PVOID *Packet,
|
||||
_Out_ PULONG Length)
|
||||
{
|
||||
ULONG DataLength = 0;
|
||||
ULONG Retries;
|
||||
|
||||
do
|
||||
{
|
||||
for (Retries = 100; Retries > 0; Retries--)
|
||||
{
|
||||
if (Rs232PortPollByte(&KdRxMessageBuffer[DataLength]))
|
||||
{
|
||||
DataLength++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (Retries > 0);
|
||||
|
||||
if (DataLength == 0)
|
||||
return STATUS_IO_TIMEOUT;
|
||||
|
||||
*Handle = 1;
|
||||
*Packet = KdRxMessageBuffer;
|
||||
*Length = DataLength;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
NTAPI
|
||||
KdpGetRxPacketDirectOutput(
|
||||
_In_ PVOID Adapter,
|
||||
_Out_ PULONG Handle,
|
||||
_Out_ PVOID *Packet,
|
||||
_Out_ PULONG Length)
|
||||
{
|
||||
*(PULONG)(KdRxMessageBuffer + 0) = PACKET_LEADER;
|
||||
*(PUSHORT)(KdRxMessageBuffer + 4) = PACKET_TYPE_KD_ACKNOWLEDGE;
|
||||
*(PUSHORT)(KdRxMessageBuffer + 6) = 0; // ByteCount
|
||||
*(PULONG)(KdRxMessageBuffer + 8) = INITIAL_PACKET_ID; // PacketId
|
||||
*(PULONG)(KdRxMessageBuffer + 12) = 0; // CheckSum
|
||||
*(KdRxMessageBuffer + 16) = PACKET_TRAILING_BYTE;
|
||||
|
||||
*Handle = 1;
|
||||
*Packet = KdRxMessageBuffer;
|
||||
*Length = 17;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static VOID
|
||||
NTAPI
|
||||
KdpReleaseRxPacket(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle)
|
||||
{
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
NTAPI
|
||||
KdpGetTxPacket(
|
||||
_In_ PVOID Adapter,
|
||||
_Out_ PULONG Handle)
|
||||
{
|
||||
*Handle = 0;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
NTAPI
|
||||
KdpSendTxPacketWinKD(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
PUCHAR ByteBuffer = KdTxMessageBuffer;
|
||||
|
||||
while (Length-- > 0)
|
||||
{
|
||||
Rs232PortPutByte(*ByteBuffer++);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static NTSTATUS
|
||||
NTAPI
|
||||
KdpSendTxPacketDirectOutput(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle,
|
||||
_In_ ULONG Length)
|
||||
{
|
||||
PKD_PACKET Packet = (PKD_PACKET)KdTxMessageBuffer;
|
||||
PDBGKD_DEBUG_IO DebugIo;
|
||||
PCHAR Buffer;
|
||||
ULONG BufferLength, i;
|
||||
|
||||
if (Packet->PacketType != PACKET_TYPE_KD_DEBUG_IO)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
DebugIo = (PDBGKD_DEBUG_IO)(Packet + 1);
|
||||
if (DebugIo->ApiNumber != DbgKdPrintStringApi)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
BufferLength = Packet->ByteCount - sizeof(DBGKD_DEBUG_IO);
|
||||
Buffer = (PCHAR)(DebugIo + 1);
|
||||
for (i = 0; i < BufferLength; i++)
|
||||
DebugPrintChar(Buffer[i]);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static PVOID
|
||||
NTAPI
|
||||
KdpGetPacketAddress(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle)
|
||||
{
|
||||
if (Handle == 0)
|
||||
return KdTxMessageBuffer;
|
||||
else if (Handle == 1)
|
||||
return KdRxMessageBuffer;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ULONG
|
||||
NTAPI
|
||||
KdpGetPacketLength(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle)
|
||||
{
|
||||
if (Handle == 0)
|
||||
return sizeof(KdTxMessageBuffer);
|
||||
else if (Handle == 1)
|
||||
return sizeof(KdRxMessageBuffer);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static KDNET_EXTENSIBILITY_EXPORTS KdWinKDExports = {
|
||||
KDNET_EXT_EXPORTS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
KdpGetRxPacketWinKD,
|
||||
KdpReleaseRxPacket,
|
||||
KdpGetTxPacket,
|
||||
KdpSendTxPacketWinKD,
|
||||
KdpGetPacketAddress,
|
||||
KdpGetPacketLength,
|
||||
};
|
||||
|
||||
static KDNET_EXTENSIBILITY_EXPORTS KdDirectOutputExports = {
|
||||
KDNET_EXT_EXPORTS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
KdpGetRxPacketDirectOutput,
|
||||
KdpReleaseRxPacket,
|
||||
KdpGetTxPacket,
|
||||
KdpSendTxPacketDirectOutput,
|
||||
KdpGetPacketAddress,
|
||||
KdpGetPacketLength,
|
||||
};
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdInitializeLibrary(
|
||||
_In_ PKDNET_EXTENSIBILITY_IMPORTS ImportTable,
|
||||
_In_opt_ PCHAR LoaderOptions,
|
||||
_Inout_ PDEBUG_DEVICE_DESCRIPTOR Device)
|
||||
{
|
||||
#ifdef _WINKD_
|
||||
if (1)
|
||||
#else
|
||||
if (0)
|
||||
#endif
|
||||
ImportTable->Exports = &KdWinKDExports;
|
||||
else
|
||||
ImportTable->Exports = &KdDirectOutputExports;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
@@ -2,6 +2,8 @@
|
||||
add_subdirectory(beep)
|
||||
add_subdirectory(bootvid)
|
||||
add_subdirectory(condrv)
|
||||
add_subdirectory(kdnet)
|
||||
add_subdirectory(kdstub)
|
||||
|
||||
if(_WINKD_)
|
||||
if(GDB)
|
||||
|
16
drivers/base/kdnet/CMakeLists.txt
Normal file
16
drivers/base/kdnet/CMakeLists.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
spec2def(kdnet.dll kdnet.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
kdnet.c
|
||||
)
|
||||
|
||||
add_library(kdnet MODULE
|
||||
${SOURCE}
|
||||
kdnet.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/kdnet.def)
|
||||
|
||||
set_module_type(kdnet kerneldll ENTRYPOINT 0)
|
||||
set_subsystem(kdnet native)
|
||||
add_importlibs(kdnet ntoskrnl hal kdstub)
|
||||
add_dependencies(kdnet psdk bugcodes)
|
||||
add_cd_file(TARGET kdnet DESTINATION reactos/system32 NO_CAB FOR all)
|
570
drivers/base/kdnet/kdnet.c
Normal file
570
drivers/base/kdnet/kdnet.c
Normal file
@@ -0,0 +1,570 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Base functions for the kernel network debugger
|
||||
* COPYRIGHT: Copyright 2009-2016 Timo Kreuzer <timo.kreuzer@reactos.org>
|
||||
* Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
|
||||
*/
|
||||
|
||||
#define NOEXTAPI
|
||||
#include <ntifs.h>
|
||||
#include <windbgkd.h>
|
||||
#include <arc/arc.h>
|
||||
#include <kddll.h>
|
||||
#include <kdnetextensibility.h>
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
ULONG CurrentPacketId = INITIAL_PACKET_ID | SYNC_PACKET_ID;
|
||||
ULONG RemotePacketId = INITIAL_PACKET_ID;
|
||||
PKDNET_EXTENSIBILITY_EXPORTS KdNetExtensibilityExports = NULL;
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdpCalculateChecksum
|
||||
* \brief Calculates the checksum for the packet data.
|
||||
* \param Buffer Pointer to the packet data.
|
||||
* \param Length Length of data in bytes.
|
||||
* \return The calculated checksum.
|
||||
* \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
|
||||
*/
|
||||
ULONG
|
||||
NTAPI
|
||||
KdpCalculateChecksum(
|
||||
IN PVOID Buffer,
|
||||
IN ULONG Length)
|
||||
{
|
||||
PUCHAR ByteBuffer = Buffer;
|
||||
ULONG Checksum = 0;
|
||||
|
||||
while (Length-- > 0)
|
||||
{
|
||||
Checksum += (ULONG)*ByteBuffer++;
|
||||
}
|
||||
return Checksum;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdpSendControlPacket(
|
||||
IN USHORT PacketType,
|
||||
IN ULONG PacketId OPTIONAL)
|
||||
{
|
||||
PKD_PACKET Packet;
|
||||
NTSTATUS Status;
|
||||
ULONG TxHandle;
|
||||
|
||||
Status = KdGetTxPacket(NULL, &TxHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return;
|
||||
Packet = KdGetPacketAddress(NULL, TxHandle);
|
||||
if (!Packet)
|
||||
return;
|
||||
ASSERT(KdGetPacketLength(NULL, TxHandle) >= sizeof(KD_PACKET));
|
||||
|
||||
Packet->PacketLeader = CONTROL_PACKET_LEADER;
|
||||
Packet->PacketId = PacketId;
|
||||
Packet->ByteCount = 0;
|
||||
Packet->Checksum = 0;
|
||||
Packet->PacketType = PacketType;
|
||||
|
||||
KdSendTxPacket(NULL, TxHandle, sizeof(KD_PACKET));
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdpReceivePacketLeader
|
||||
* \brief Receives a packet leader from the KD port.
|
||||
* \param PacketLeader Pointer to an ULONG that receives the packet leader.
|
||||
* \return KdPacketReceived if successful.
|
||||
* KdPacketTimedOut if the receive timed out.
|
||||
* KdPacketNeedsResend if a breakin byte was detected.
|
||||
*/
|
||||
KDSTATUS
|
||||
NTAPI
|
||||
KdpReceivePacketLeader(
|
||||
OUT PULONG PacketLeader,
|
||||
IN PUCHAR *pRxPacket,
|
||||
IN PULONG pRxLength)
|
||||
{
|
||||
UCHAR Index = 0, Byte, Buffer[4];
|
||||
|
||||
/* Set first character to 0 */
|
||||
Buffer[0] = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (*pRxLength == 0)
|
||||
{
|
||||
/* End of RX packet. Check if we already got a breakin byte */
|
||||
if (Buffer[0] == BREAKIN_PACKET_BYTE)
|
||||
return KdPacketNeedsResend;
|
||||
|
||||
/* Report timeout */
|
||||
return KdPacketTimedOut;
|
||||
}
|
||||
|
||||
/* Receive a single byte */
|
||||
Byte = **pRxPacket;
|
||||
++(*pRxPacket);
|
||||
--(*pRxLength);
|
||||
|
||||
/* Check if this is a valid packet leader byte */
|
||||
if (Byte == PACKET_LEADER_BYTE ||
|
||||
Byte == CONTROL_PACKET_LEADER_BYTE)
|
||||
{
|
||||
/* Check if we match the first byte */
|
||||
if (Byte != Buffer[0])
|
||||
{
|
||||
/* No, this is the new byte 0! */
|
||||
Index = 0;
|
||||
}
|
||||
|
||||
/* Store the byte in the buffer */
|
||||
Buffer[Index] = Byte;
|
||||
|
||||
/* Continue with next byte */
|
||||
Index++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check for breakin byte */
|
||||
if (Byte == BREAKIN_PACKET_BYTE)
|
||||
{
|
||||
Index = 0;
|
||||
Buffer[0] = Byte;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Restart */
|
||||
Index = 0;
|
||||
Buffer[0] = 0;
|
||||
}
|
||||
while (Index < 4);
|
||||
|
||||
/* Return the received packet leader */
|
||||
*PacketLeader = *(PULONG)Buffer;
|
||||
|
||||
return KdPacketReceived;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdpReceiveBuffer
|
||||
* \brief Receives data from the KD port and fills a buffer.
|
||||
* \param Buffer Pointer to a buffer that receives the data.
|
||||
* \param Size Size of data to receive in bytes.
|
||||
* \return KdPacketReceived if successful.
|
||||
* KdPacketTimedOut if the receive timed out.
|
||||
*/
|
||||
KDSTATUS
|
||||
NTAPI
|
||||
KdpReceiveBuffer(
|
||||
OUT PVOID Buffer,
|
||||
IN ULONG Size,
|
||||
IN PUCHAR *pRxPacket,
|
||||
IN PULONG pRxLength)
|
||||
{
|
||||
if (*pRxLength < Size)
|
||||
{
|
||||
*pRxLength = 0;
|
||||
return KdPacketTimedOut;
|
||||
}
|
||||
|
||||
RtlCopyMemory(Buffer, *pRxPacket, Size);
|
||||
(*pRxPacket) += Size;
|
||||
(*pRxLength) -= Size;
|
||||
|
||||
return KdPacketReceived;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdD0Transition(VOID)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdD3Transition(VOID)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdDebuggerInitialize0(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdDebuggerInitialize1(IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL)
|
||||
{
|
||||
KDNET_EXTENSIBILITY_IMPORTS ImportTable = {0};
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = KdInitializeLibrary(&ImportTable, LoaderBlock ? LoaderBlock->LoadOptions : NULL, NULL);
|
||||
if (NT_SUCCESS(Status))
|
||||
KdNetExtensibilityExports = ImportTable.Exports;
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdRestore(IN BOOLEAN SleepTransition)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdSave(IN BOOLEAN SleepTransition)
|
||||
{
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdSetHiberRange(VOID)
|
||||
{
|
||||
}
|
||||
|
||||
KDSTATUS
|
||||
NTAPI
|
||||
KdReceivePacket(
|
||||
_In_ ULONG PacketType,
|
||||
_Out_ PSTRING MessageHeader,
|
||||
_Out_ PSTRING MessageData,
|
||||
_Out_ PULONG DataLength,
|
||||
_Inout_ PKD_CONTEXT Context)
|
||||
{
|
||||
UCHAR Byte = 0;
|
||||
KDSTATUS KdStatus;
|
||||
KD_PACKET Packet;
|
||||
ULONG Checksum, MessageDataLength;
|
||||
ULONG RxHandle, RxLength;
|
||||
PVOID RxPacket;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Special handling for breakin packet */
|
||||
if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Status = KdGetRxPacket(NULL, &RxHandle, &RxPacket, &RxLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
/* Report timeout */
|
||||
return KdPacketTimedOut;
|
||||
}
|
||||
|
||||
/* Step 1 - Read PacketLeader */
|
||||
KdStatus = KdpReceivePacketLeader(&Packet.PacketLeader, (PUCHAR*)&RxPacket, &RxLength);
|
||||
if (KdStatus != KdPacketReceived)
|
||||
{
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/* Step 2 - Read PacketType */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.PacketType, sizeof(USHORT), (PUCHAR*)&RxPacket, &RxLength);
|
||||
if (KdStatus != KdPacketReceived)
|
||||
{
|
||||
/* Didn't receive a PacketType. */
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/* Check if we got a resend packet */
|
||||
if (Packet.PacketLeader == CONTROL_PACKET_LEADER &&
|
||||
Packet.PacketType == PACKET_TYPE_KD_RESEND)
|
||||
{
|
||||
return KdPacketNeedsResend;
|
||||
}
|
||||
|
||||
/* Step 3 - Read ByteCount */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.ByteCount, sizeof(USHORT), (PUCHAR*)&RxPacket, &RxLength);
|
||||
if (KdStatus != KdPacketReceived)
|
||||
{
|
||||
/* Didn't receive ByteCount. */
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/* Step 4 - Read PacketId */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.PacketId, sizeof(ULONG), (PUCHAR*)&RxPacket, &RxLength);
|
||||
if (KdStatus != KdPacketReceived)
|
||||
{
|
||||
/* Didn't receive PacketId. */
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/* Step 5 - Read Checksum */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.Checksum, sizeof(ULONG), (PUCHAR*)&RxPacket, &RxLength);
|
||||
if (KdStatus != KdPacketReceived)
|
||||
{
|
||||
/* Didn't receive Checksum. */
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/* Step 6 - Handle control packets */
|
||||
if (Packet.PacketLeader == CONTROL_PACKET_LEADER)
|
||||
{
|
||||
switch (Packet.PacketType)
|
||||
{
|
||||
case PACKET_TYPE_KD_ACKNOWLEDGE:
|
||||
/* Are we waiting for an ACK packet? */
|
||||
if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE &&
|
||||
Packet.PacketId == (CurrentPacketId & ~SYNC_PACKET_ID))
|
||||
{
|
||||
/* Remote acknowledges the last packet */
|
||||
CurrentPacketId ^= 1;
|
||||
return KdPacketReceived;
|
||||
}
|
||||
/* That's not what we were waiting for, start over */
|
||||
continue;
|
||||
|
||||
case PACKET_TYPE_KD_RESET:
|
||||
CurrentPacketId = INITIAL_PACKET_ID;
|
||||
RemotePacketId = INITIAL_PACKET_ID;
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESET, 0);
|
||||
/* Fall through */
|
||||
|
||||
case PACKET_TYPE_KD_RESEND:
|
||||
/* Remote wants us to resend the last packet */
|
||||
return KdPacketNeedsResend;
|
||||
|
||||
default:
|
||||
/* We got an invalid packet, ignore it and start over */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Did we wait for an ack packet? */
|
||||
if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE)
|
||||
{
|
||||
/* We received something different */
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
CurrentPacketId ^= 1;
|
||||
return KdPacketReceived;
|
||||
}
|
||||
|
||||
/* Get size of the message header */
|
||||
MessageHeader->Length = MessageHeader->MaximumLength;
|
||||
|
||||
/* Packet smaller than expected or too big? */
|
||||
if (Packet.ByteCount < MessageHeader->Length ||
|
||||
Packet.ByteCount > PACKET_MAX_SIZE)
|
||||
{
|
||||
MessageHeader->Length = Packet.ByteCount;
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Receive the message header data */
|
||||
KdStatus = KdpReceiveBuffer(MessageHeader->Buffer,
|
||||
MessageHeader->Length,
|
||||
(PUCHAR*)&RxPacket, &RxLength);
|
||||
if (KdStatus != KdPacketReceived)
|
||||
{
|
||||
/* Didn't receive data. Packet needs to be resent. */
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Calculate checksum for the header data */
|
||||
Checksum = KdpCalculateChecksum(MessageHeader->Buffer,
|
||||
MessageHeader->Length);
|
||||
|
||||
/* Calculate the length of the message data */
|
||||
MessageDataLength = Packet.ByteCount - MessageHeader->Length;
|
||||
|
||||
/* Shall we receive message data? */
|
||||
if (MessageData)
|
||||
{
|
||||
/* Set the length of the message data */
|
||||
MessageData->Length = (USHORT)MessageDataLength;
|
||||
|
||||
/* Do we have data? */
|
||||
if (MessageData->Length)
|
||||
{
|
||||
/* Receive the message data */
|
||||
KdStatus = KdpReceiveBuffer(MessageData->Buffer,
|
||||
MessageData->Length,
|
||||
(PUCHAR*)&RxPacket, &RxLength);
|
||||
if (KdStatus != KdPacketReceived)
|
||||
{
|
||||
/* Didn't receive data. Start over. */
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Add cheksum for message data */
|
||||
Checksum += KdpCalculateChecksum(MessageData->Buffer,
|
||||
MessageData->Length);
|
||||
}
|
||||
}
|
||||
|
||||
/* We must receive a PACKET_TRAILING_BYTE now */
|
||||
KdStatus = KdpReceiveBuffer(&Byte, sizeof(UCHAR), (PUCHAR*)&RxPacket, &RxLength);
|
||||
if (KdStatus != KdPacketReceived || Byte != PACKET_TRAILING_BYTE)
|
||||
{
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Compare checksum */
|
||||
if (Packet.Checksum != Checksum)
|
||||
{
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Acknowledge the received packet */
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE, Packet.PacketId);
|
||||
|
||||
/* Check if the received PacketId is ok */
|
||||
if (Packet.PacketId != RemotePacketId)
|
||||
{
|
||||
/* Continue with next packet */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Did we get the right packet type? */
|
||||
if (PacketType == Packet.PacketType)
|
||||
{
|
||||
/* Yes, return success */
|
||||
RemotePacketId ^= 1;
|
||||
return KdPacketReceived;
|
||||
}
|
||||
|
||||
/* We received something different, ignore it. */
|
||||
}
|
||||
|
||||
return KdPacketReceived;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdSendPacket(
|
||||
_In_ ULONG PacketType,
|
||||
_In_ PSTRING MessageHeader,
|
||||
_In_ PSTRING MessageData,
|
||||
_Inout_ PKD_CONTEXT Context)
|
||||
{
|
||||
PKD_PACKET Packet;
|
||||
KDSTATUS KdStatus;
|
||||
ULONG Retries;
|
||||
ULONG TxHandle, DataLength;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = KdGetTxPacket(NULL, &TxHandle);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return;
|
||||
Packet = KdGetPacketAddress(NULL, TxHandle);
|
||||
ASSERT(Packet);
|
||||
ASSERT(KdGetPacketLength(NULL, TxHandle) >= sizeof(KD_PACKET));
|
||||
|
||||
/* Initialize a KD_PACKET */
|
||||
Packet->PacketLeader = PACKET_LEADER;
|
||||
Packet->PacketType = (USHORT)PacketType;
|
||||
Packet->ByteCount = MessageHeader->Length;
|
||||
Packet->Checksum = KdpCalculateChecksum(MessageHeader->Buffer,
|
||||
MessageHeader->Length);
|
||||
|
||||
/* If we have message data, add it to the packet */
|
||||
if (MessageData)
|
||||
{
|
||||
Packet->ByteCount += MessageData->Length;
|
||||
Packet->Checksum += KdpCalculateChecksum(MessageData->Buffer,
|
||||
MessageData->Length);
|
||||
}
|
||||
|
||||
if (KdGetPacketLength(NULL, TxHandle) < sizeof(KD_PACKET) + Packet->ByteCount + 1)
|
||||
{
|
||||
/* Release TX packet */
|
||||
KdSendTxPacket(NULL, TxHandle, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Copy message header and message data to packet */
|
||||
RtlCopyMemory(Packet + 1, MessageHeader->Buffer, MessageHeader->Length);
|
||||
if (MessageData)
|
||||
RtlCopyMemory((PUCHAR)(Packet + 1) + MessageHeader->Length, MessageData->Buffer, MessageData->Length);
|
||||
|
||||
/* Finalize with a trailing byte */
|
||||
((PUCHAR)(Packet + 1))[Packet->ByteCount] = PACKET_TRAILING_BYTE;
|
||||
|
||||
Retries = 3;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Set the packet id */
|
||||
Packet->PacketId = CurrentPacketId;
|
||||
|
||||
/* Send the packet to the KD port */
|
||||
KdSendTxPacket(NULL, TxHandle, sizeof(KD_PACKET) + Packet->ByteCount + 1);
|
||||
|
||||
/* Wait for acknowledge */
|
||||
KdStatus = KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE,
|
||||
NULL,
|
||||
NULL,
|
||||
&DataLength,
|
||||
NULL);
|
||||
|
||||
/* Did we succeed? */
|
||||
if (KdStatus == KdPacketReceived)
|
||||
{
|
||||
/* Packet received, we can quit the loop */
|
||||
CurrentPacketId &= ~SYNC_PACKET_ID;
|
||||
Retries = 3;
|
||||
break;
|
||||
}
|
||||
else if (KdStatus == KdPacketTimedOut)
|
||||
{
|
||||
/* Timeout, decrement the retry count */
|
||||
if (Retries > 0)
|
||||
Retries--;
|
||||
|
||||
/*
|
||||
* If the retry count reaches zero, bail out
|
||||
* for packet types allowed to timeout.
|
||||
*/
|
||||
if (Retries == 0)
|
||||
{
|
||||
ULONG MessageId = *(PULONG)MessageHeader->Buffer;
|
||||
switch (PacketType)
|
||||
{
|
||||
case PACKET_TYPE_KD_DEBUG_IO:
|
||||
{
|
||||
if (MessageId != DbgKdPrintStringApi) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_TYPE_KD_STATE_CHANGE32:
|
||||
case PACKET_TYPE_KD_STATE_CHANGE64:
|
||||
{
|
||||
if (MessageId != DbgKdLoadSymbolsStateChange) continue;
|
||||
break;
|
||||
}
|
||||
|
||||
case PACKET_TYPE_KD_FILE_IO:
|
||||
{
|
||||
if (MessageId != DbgKdCreateFileApi) continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset debugger state */
|
||||
CurrentPacketId = INITIAL_PACKET_ID | SYNC_PACKET_ID;
|
||||
RemotePacketId = INITIAL_PACKET_ID;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Packet timed out, send it again */
|
||||
}
|
||||
}
|
5
drivers/base/kdnet/kdnet.rc
Normal file
5
drivers/base/kdnet/kdnet.rc
Normal file
@@ -0,0 +1,5 @@
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Kernel Debugger Network Extension DLL"
|
||||
#define REACTOS_STR_INTERNAL_NAME "kdnet"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "kdnet.dll"
|
||||
#include <reactos/version.rc>
|
9
drivers/base/kdnet/kdnet.spec
Normal file
9
drivers/base/kdnet/kdnet.spec
Normal file
@@ -0,0 +1,9 @@
|
||||
@ 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)
|
||||
@ stdcall KdSetHiberRange()
|
13
drivers/base/kdstub/CMakeLists.txt
Normal file
13
drivers/base/kdstub/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
||||
spec2def(kdstub.dll kdstub.spec ADD_IMPORTLIB)
|
||||
|
||||
list(APPEND SOURCE
|
||||
kdstub.c)
|
||||
|
||||
add_library(kdstub MODULE
|
||||
${SOURCE}
|
||||
kdstub.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/kdstub.def)
|
||||
|
||||
set_module_type(kdstub kerneldll ENTRYPOINT 0)
|
||||
set_subsystem(kdstub native)
|
||||
add_cd_file(TARGET kdstub DESTINATION reactos/system32 NO_CAB FOR all)
|
21
drivers/base/kdstub/kdstub.c
Normal file
21
drivers/base/kdstub/kdstub.c
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* PROJECT: ReactOS Kernel
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Stubs for the kernel network debugger
|
||||
* COPYRIGHT: Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
|
||||
*/
|
||||
|
||||
#define NOEXTAPI
|
||||
#include <ntifs.h>
|
||||
#include <kdnetextensibility.h>
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdInitializeLibrary(
|
||||
_In_ PKDNET_EXTENSIBILITY_IMPORTS ImportTable,
|
||||
_In_opt_ PCHAR LoaderOptions,
|
||||
_Inout_ PDEBUG_DEVICE_DESCRIPTOR Device)
|
||||
{
|
||||
return STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
6
drivers/base/kdstub/kdstub.rc
Normal file
6
drivers/base/kdstub/kdstub.rc
Normal file
@@ -0,0 +1,6 @@
|
||||
#define REACTOS_VERSION_DLL
|
||||
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Kernel Debugger Stub Extension DLL"
|
||||
#define REACTOS_STR_INTERNAL_NAME "kdstub"
|
||||
#define REACTOS_STR_ORIGINAL_FILENAME "kdstub.dll"
|
||||
#include <reactos/version.rc>
|
||||
|
1
drivers/base/kdstub/kdstub.spec
Normal file
1
drivers/base/kdstub/kdstub.spec
Normal file
@@ -0,0 +1 @@
|
||||
@ stdcall KdInitializeLibrary(ptr ptr ptr)
|
81
sdk/include/reactos/kdnetextensibility.h
Normal file
81
sdk/include/reactos/kdnetextensibility.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
typedef NTSTATUS
|
||||
(NTAPI *KD_GET_RX_PACKET)(
|
||||
_In_ PVOID Adapter,
|
||||
_Out_ PULONG Handle,
|
||||
_Out_ PVOID *Packet,
|
||||
_Out_ PULONG Length);
|
||||
|
||||
typedef VOID
|
||||
(NTAPI *KD_RELEASE_RX_PACKET)(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle);
|
||||
|
||||
typedef NTSTATUS
|
||||
(NTAPI *KD_GET_TX_PACKET)(
|
||||
_In_ PVOID Adapter,
|
||||
_Out_ PULONG Handle);
|
||||
|
||||
typedef NTSTATUS
|
||||
(NTAPI *KD_SEND_TX_PACKET)(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle,
|
||||
_In_ ULONG Length);
|
||||
|
||||
typedef PVOID
|
||||
(NTAPI *KD_GET_PACKET_ADDRESS)(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle);
|
||||
|
||||
typedef ULONG
|
||||
(NTAPI *KD_GET_PACKET_LENGTH)(
|
||||
_In_ PVOID Adapter,
|
||||
_In_ ULONG Handle);
|
||||
|
||||
#define KDNET_EXT_EXPORTS 13
|
||||
|
||||
typedef struct _KDNET_EXTENSIBILITY_EXPORTS
|
||||
{
|
||||
ULONG FunctionCount;
|
||||
PVOID KdInitializeController;
|
||||
PVOID KdShutdownController;
|
||||
PVOID KdSetHibernateRange;
|
||||
KD_GET_RX_PACKET KdGetRxPacket;
|
||||
KD_RELEASE_RX_PACKET KdReleaseRxPacket;
|
||||
KD_GET_TX_PACKET KdGetTxPacket;
|
||||
KD_SEND_TX_PACKET KdSendTxPacket;
|
||||
KD_GET_PACKET_ADDRESS KdGetPacketAddress;
|
||||
KD_GET_PACKET_LENGTH KdGetPacketLength;
|
||||
PVOID KdGetHardwareContextSize;
|
||||
PVOID KdDeviceControl;
|
||||
PVOID KdReadSerialByte;
|
||||
PVOID KdWriteSerialByte;
|
||||
PVOID DebugSerialOutputInit;
|
||||
PVOID DebugSerialOutputByte;
|
||||
} KDNET_EXTENSIBILITY_EXPORTS, *PKDNET_EXTENSIBILITY_EXPORTS;
|
||||
|
||||
#define KDNET_EXT_IMPORTS 30
|
||||
|
||||
typedef struct _KDNET_EXTENSIBILITY_IMPORTS
|
||||
{
|
||||
ULONG FunctionCount;
|
||||
PKDNET_EXTENSIBILITY_EXPORTS Exports;
|
||||
PVOID Reserved[28];
|
||||
} KDNET_EXTENSIBILITY_IMPORTS, *PKDNET_EXTENSIBILITY_IMPORTS;
|
||||
|
||||
extern PKDNET_EXTENSIBILITY_EXPORTS KdNetExtensibilityExports;
|
||||
|
||||
#define KdGetRxPacket KdNetExtensibilityExports->KdGetRxPacket
|
||||
#define KdReleaseRxPacket KdNetExtensibilityExports->KdReleaseRxPacket
|
||||
#define KdGetTxPacket KdNetExtensibilityExports->KdGetTxPacket
|
||||
#define KdSendTxPacket KdNetExtensibilityExports->KdSendTxPacket
|
||||
#define KdGetPacketAddress KdNetExtensibilityExports->KdGetPacketAddress
|
||||
#define KdGetPacketLength KdNetExtensibilityExports->KdGetPacketLength
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
KdInitializeLibrary(
|
||||
_In_ PKDNET_EXTENSIBILITY_IMPORTS ImportTable,
|
||||
_In_opt_ PCHAR LoaderOptions,
|
||||
_Inout_ PDEBUG_DEVICE_DESCRIPTOR Device);
|
Reference in New Issue
Block a user