Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428/* * 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 (DEAD_LINK) */ULONGNTAPIKdpCalculateChecksum( IN PVOID Buffer, IN ULONG Length){ PUCHAR ByteBuffer = Buffer; ULONG Checksum = 0;
while (Length-- > 0) { Checksum += (ULONG)*ByteBuffer++; } return Checksum;}
VOIDNTAPIKdpSendControlPacket( 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_STATUSNTAPIKdReceivePacket( 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;}
VOIDNTAPIKdSendPacket( 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 */