mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 14:43:22 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
427
drivers/base/kdcom/kddll.c
Normal file
427
drivers/base/kdcom/kddll.c
Normal file
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
* COPYRIGHT: GPL, see COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: drivers/base/kddll/kddll.c
|
||||
* PURPOSE: Base functions for the kernel debugger.
|
||||
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
||||
*/
|
||||
|
||||
#include "kddll.h"
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
|
||||
ULONG CurrentPacketId = INITIAL_PACKET_ID | SYNC_PACKET_ID;
|
||||
ULONG RemotePacketId = INITIAL_PACKET_ID;
|
||||
|
||||
|
||||
/* PRIVATE FUNCTIONS **********************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* \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)
|
||||
{
|
||||
KD_PACKET Packet;
|
||||
|
||||
Packet.PacketLeader = CONTROL_PACKET_LEADER;
|
||||
Packet.PacketId = PacketId;
|
||||
Packet.ByteCount = 0;
|
||||
Packet.Checksum = 0;
|
||||
Packet.PacketType = PacketType;
|
||||
|
||||
KdpSendBuffer(&Packet, sizeof(KD_PACKET));
|
||||
}
|
||||
|
||||
|
||||
/* PUBLIC FUNCTIONS ***********************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* \name KdReceivePacket
|
||||
* \brief Receive a packet from the KD port.
|
||||
* \param [in] PacketType Describes the type of the packet to receive.
|
||||
* This can be one of the PACKET_TYPE_ constants.
|
||||
* \param [out] MessageHeader Pointer to a STRING structure for the header.
|
||||
* \param [out] MessageData Pointer to a STRING structure for the data.
|
||||
* \return KdPacketReceived if successful, KdPacketTimedOut if the receive
|
||||
* timed out, KdPacketNeedsResend to signal that the last packet needs
|
||||
* to be sent again.
|
||||
* \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
|
||||
* wait for any data, but returns KdPacketTimedOut instantly if no breakin
|
||||
* packet byte is received.
|
||||
* \sa http://www.nynaeve.net/?p=169
|
||||
*/
|
||||
KDP_STATUS
|
||||
NTAPI
|
||||
KdReceivePacket(
|
||||
IN ULONG PacketType,
|
||||
OUT PSTRING MessageHeader,
|
||||
OUT PSTRING MessageData,
|
||||
OUT PULONG DataLength,
|
||||
IN OUT PKD_CONTEXT KdContext)
|
||||
{
|
||||
UCHAR Byte = 0;
|
||||
KDP_STATUS KdStatus;
|
||||
KD_PACKET Packet;
|
||||
ULONG Checksum;
|
||||
|
||||
/* Special handling for breakin packet */
|
||||
if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
|
||||
{
|
||||
return KdpPollBreakIn();
|
||||
}
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Step 1 - Read PacketLeader */
|
||||
KdStatus = KdpReceivePacketLeader(&Packet.PacketLeader);
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Check if we got a breakin */
|
||||
if (KdStatus == KDP_PACKET_RESEND)
|
||||
{
|
||||
KdContext->KdpControlCPending = TRUE;
|
||||
}
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/* Step 2 - Read PacketType */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.PacketType, sizeof(USHORT));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* 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 KDP_PACKET_RESEND;
|
||||
}
|
||||
|
||||
/* Step 3 - Read ByteCount */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.ByteCount, sizeof(USHORT));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive ByteCount. */
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/* Step 4 - Read PacketId */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.PacketId, sizeof(ULONG));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive PacketId. */
|
||||
return KdStatus;
|
||||
}
|
||||
|
||||
/*
|
||||
if (Packet.PacketId != ExpectedPacketId)
|
||||
{
|
||||
// Ask for a resend!
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Step 5 - Read Checksum */
|
||||
KdStatus = KdpReceiveBuffer(&Packet.Checksum, sizeof(ULONG));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* 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 KDP_PACKET_RECEIVED;
|
||||
}
|
||||
/* That's not what we were waiting for, start over */
|
||||
continue;
|
||||
|
||||
case PACKET_TYPE_KD_RESET:
|
||||
KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESET\n");
|
||||
CurrentPacketId = INITIAL_PACKET_ID;
|
||||
RemotePacketId = INITIAL_PACKET_ID;
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESET, 0);
|
||||
/* Fall through */
|
||||
|
||||
case PACKET_TYPE_KD_RESEND:
|
||||
KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n");
|
||||
/* Remote wants us to resend the last packet */
|
||||
return KDP_PACKET_RESEND;
|
||||
|
||||
default:
|
||||
KDDBGPRINT("KdReceivePacket - got unknown control packet\n");
|
||||
/* 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 KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n",
|
||||
Packet.ByteCount, MessageHeader->Length);
|
||||
MessageHeader->Length = Packet.ByteCount;
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
//KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
|
||||
|
||||
/* Receive the message header data */
|
||||
KdStatus = KdpReceiveBuffer(MessageHeader->Buffer,
|
||||
MessageHeader->Length);
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive data. Packet needs to be resent. */
|
||||
KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n");
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
//KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n");
|
||||
|
||||
/* Calculate checksum for the header data */
|
||||
Checksum = KdpCalculateChecksum(MessageHeader->Buffer,
|
||||
MessageHeader->Length);
|
||||
|
||||
/* Calculate the length of the message data */
|
||||
*DataLength = Packet.ByteCount - MessageHeader->Length;
|
||||
|
||||
/* Shall we receive message data? */
|
||||
if (MessageData)
|
||||
{
|
||||
/* Set the length of the message data */
|
||||
MessageData->Length = (USHORT)*DataLength;
|
||||
|
||||
/* Do we have data? */
|
||||
if (MessageData->Length)
|
||||
{
|
||||
KDDBGPRINT("KdReceivePacket - got data\n");
|
||||
|
||||
/* Receive the message data */
|
||||
KdStatus = KdpReceiveBuffer(MessageData->Buffer,
|
||||
MessageData->Length);
|
||||
if (KdStatus != KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Didn't receive data. Start over. */
|
||||
KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n");
|
||||
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));
|
||||
if (KdStatus != KDP_PACKET_RECEIVED || Byte != PACKET_TRAILING_BYTE)
|
||||
{
|
||||
KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte, KdStatus);
|
||||
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Compare checksum */
|
||||
if (Packet.Checksum != Checksum)
|
||||
{
|
||||
KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
|
||||
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 */
|
||||
//KDDBGPRINT("KdReceivePacket - all ok\n");
|
||||
RemotePacketId ^= 1;
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
/* We received something different, ignore it. */
|
||||
KDDBGPRINT("KdReceivePacket - wrong PacketType\n");
|
||||
}
|
||||
|
||||
return KDP_PACKET_RECEIVED;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KdSendPacket(
|
||||
IN ULONG PacketType,
|
||||
IN PSTRING MessageHeader,
|
||||
IN PSTRING MessageData,
|
||||
IN OUT PKD_CONTEXT KdContext)
|
||||
{
|
||||
KD_PACKET Packet;
|
||||
KDP_STATUS KdStatus;
|
||||
ULONG Retries;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
Retries = KdContext->KdpDefaultRetries;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* Set the packet id */
|
||||
Packet.PacketId = CurrentPacketId;
|
||||
|
||||
/* Send the packet header to the KD port */
|
||||
KdpSendBuffer(&Packet, sizeof(KD_PACKET));
|
||||
|
||||
/* Send the message header */
|
||||
KdpSendBuffer(MessageHeader->Buffer, MessageHeader->Length);
|
||||
|
||||
/* If we have message data, also send it */
|
||||
if (MessageData)
|
||||
{
|
||||
KdpSendBuffer(MessageData->Buffer, MessageData->Length);
|
||||
}
|
||||
|
||||
/* Finalize with a trailing byte */
|
||||
KdpSendByte(PACKET_TRAILING_BYTE);
|
||||
|
||||
/* Wait for acknowledge */
|
||||
KdStatus = KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
KdContext);
|
||||
|
||||
/* Did we succeed? */
|
||||
if (KdStatus == KDP_PACKET_RECEIVED)
|
||||
{
|
||||
/* Packet received, we can quit the loop */
|
||||
CurrentPacketId &= ~SYNC_PACKET_ID;
|
||||
Retries = KdContext->KdpDefaultRetries;
|
||||
break;
|
||||
}
|
||||
else if (KdStatus == KDP_PACKET_TIMEOUT)
|
||||
{
|
||||
/* 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 */
|
||||
KD_DEBUGGER_NOT_PRESENT = TRUE;
|
||||
SharedUserData->KdDebuggerEnabled &= ~0x00000002;
|
||||
CurrentPacketId = INITIAL_PACKET_ID | SYNC_PACKET_ID;
|
||||
RemotePacketId = INITIAL_PACKET_ID;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
// else (KdStatus == KDP_PACKET_RESEND) /* Resend the packet */
|
||||
|
||||
/* Packet timed out, send it again */
|
||||
KDDBGPRINT("KdSendPacket got KdStatus 0x%x\n", KdStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
Loading…
Add table
Add a link
Reference in a new issue