📄 kdcomio.c
字号:
}
}
//
// if the packet we received is a resend request, we return true and
// let caller resend the packet.
//
if ( PacketHeader.PacketLeader == CONTROL_PACKET_LEADER &&
PacketHeader.PacketType == PACKET_TYPE_KD_RESEND ) {
DBGPRT("Got Packet Resend");
return KDP_PACKET_RESEND;
}
//
// Read data length.
//
ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.ByteCount,
sizeof(PacketHeader.ByteCount));
if (ReturnCode == CP_GET_NODATA) {
DBGPRT("Did not receive data length");
return KDP_PACKET_TIMEOUT;
} else if (ReturnCode == CP_GET_ERROR) {
KdClearCommError();
if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
goto WaitForPacketLeader;
} else {
DBGPRT("Failed to get ByteCount");
goto SendResendPacket;
}
}
//
// Read Packet Id.
//
ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.PacketId,
sizeof(PacketHeader.PacketId));
if (ReturnCode == CP_GET_NODATA) {
DBGPRT("Did not receive packet ID");
return KDP_PACKET_TIMEOUT;
} else if (ReturnCode == CP_GET_ERROR) {
KdClearCommError();
if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
goto WaitForPacketLeader;
} else {
DBGPRT("Failed to get PacketId");
goto SendResendPacket;
}
}
//
// Read packet checksum.
//
ReturnCode = KdpReceiveString((PCHAR)&PacketHeader.Checksum,
sizeof(PacketHeader.Checksum));
if (ReturnCode == CP_GET_NODATA) {
DBGPRT("Did not receive packet checksum");
return KDP_PACKET_TIMEOUT;
} else if (ReturnCode == CP_GET_ERROR) {
KdClearCommError();
if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER) {
goto WaitForPacketLeader;
} else {
DBGPRT("Failed to get Checksum");
goto SendResendPacket;
}
}
//
// A complete packet header is received. Check its validity and
// perform appropriate action depending on packet type.
//
if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER ) {
if (PacketHeader.PacketType == PACKET_TYPE_KD_ACKNOWLEDGE ) {
//
// If we received an expected ACK packet and we are not
// waiting for any new packet, update outgoing packet id
// and return. If we are NOT waiting for ACK packet
// we will keep on waiting. If the ACK packet
// is not for the packet we send, ignore it and keep on waiting.
//
if (PacketHeader.PacketId !=
(KdpNextPacketIdToSend & ~SYNC_PACKET_ID)) {
goto WaitForPacketLeader;
} else if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
KdpNextPacketIdToSend ^= 1;
return KDP_PACKET_RECEIVED;
} else {
goto WaitForPacketLeader;
}
} else if (PacketHeader.PacketType == PACKET_TYPE_KD_RESET) {
DBGPRT("Got reset packet");
//
// if we received Reset packet, reset the packet control variables
// and resend earlier packet.
//
KdpNextPacketIdToSend = INITIAL_PACKET_ID;
KdpPacketIdExpected = INITIAL_PACKET_ID;
KdpSendControlPacket(PACKET_TYPE_KD_RESET, 0L);
return KDP_PACKET_RESEND;
} else if (PacketHeader.PacketType == PACKET_TYPE_KD_RESEND) {
DBGPRT("Got packet Resend 2");
return KDP_PACKET_RESEND;
} else {
//
// Invalid packet header, ignore it.
//
goto WaitForPacketLeader;
}
//
// The packet header is for data packet (not control packet).
//
} else if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) {
//
// if we are waiting for ACK packet ONLY
// and we receive a data packet header, check if the packet id
// is what we expected. If yes, assume the acknowledge is lost (but
// sent), ask sender to resend and return with PACKET_RECEIVED.
//
if (PacketHeader.PacketId == KdpPacketIdExpected) {
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0L);
KdpNextPacketIdToSend ^= 1;
return KDP_PACKET_RECEIVED;
} else {
KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
PacketHeader.PacketId
);
goto WaitForPacketLeader;
}
}
//
// we are waiting for data packet and we received the packet header
// for data packet. Perform the following checkings to make sure
// it is the packet we are waiting for.
//
//
// Check ByteCount received is valid
//
MessageLength = MessageHeader->MaximumLength;
if ((PacketHeader.ByteCount > (USHORT)PACKET_MAX_SIZE) ||
(PacketHeader.ByteCount < (USHORT)MessageLength)) {
DBGPRT("Invalid ByteCount");
goto SendResendPacket;
}
*DataLength = PacketHeader.ByteCount - MessageLength;
//
// Read the message header.
//
ReturnCode = KdpReceiveString(MessageHeader->Buffer, MessageLength);
if (ReturnCode != CP_GET_SUCCESS) {
DBGPRT("Invalid MessageLength");
goto SendResendPacket;
}
MessageHeader->Length = (USHORT)MessageLength;
//
// Read the message data.
//
ReturnCode = KdpReceiveString(MessageData->Buffer, *DataLength);
if (ReturnCode != CP_GET_SUCCESS) {
goto SendResendPacket;
}
MessageData->Length = (USHORT)*DataLength;
//
// Read packet trailing byte
//
ReturnCode = KdPortGetByte(&Input);
if (ReturnCode != CP_GET_SUCCESS || Input != PACKET_TRAILING_BYTE) {
DBGPRT("Invalid Trailing Byte");
goto SendResendPacket;
}
//
// Check PacketType is what we are waiting for.
//
if (PacketType != PacketHeader.PacketType) {
if (!KdpUseTCPSockets) {
KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
PacketHeader.PacketId
);
}
goto WaitForPacketLeader;
}
//
// Check PacketId is valid.
//
if (PacketHeader.PacketId == INITIAL_PACKET_ID ||
PacketHeader.PacketId == (INITIAL_PACKET_ID ^ 1)) {
if (PacketHeader.PacketId != KdpPacketIdExpected) {
if (!KdpUseTCPSockets) {
KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
PacketHeader.PacketId
);
}
goto WaitForPacketLeader;
}
} else {
DBGPRT("Invalid Packet ID");
goto SendResendPacket;
}
//
// Check checksum is valid.
//
Checksum = KdpComputeChecksum(
MessageHeader->Buffer,
MessageHeader->Length
);
Checksum += KdpComputeChecksum(
MessageData->Buffer,
MessageData->Length
);
if (Checksum != PacketHeader.Checksum) {
DBGPRT("Invalid CheckSum");
goto SendResendPacket;
}
if (!KdpUseTCPSockets) {
//
// Send Acknowledge byte and the Id of the packet received.
// Then, update the ExpectId for next incoming packet.
//
KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE,
PacketHeader.PacketId
);
}
//
// We have successfully received the packet so update the
// packet control variables and return sucess.
//
KdpPacketIdExpected ^= 1;
return KDP_PACKET_RECEIVED;
SendResendPacket:
KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0L);
goto WaitForPacketLeader;
}
VOID KdpSendPacket(IN ULONG PacketType, IN PSTRING MessageHeader,
IN PSTRING MessageData OPTIONAL)
/*++
Routine Description:
This routine sends a packet to the host machine that is running the
kernel debugger and waits for an ACK.
Arguments:
PacketType - Supplies the type of packet to send.
MessageHeader - Supplies a pointer to a string descriptor that describes
the message information.
MessageData - Supplies a pointer to a string descriptor that describes
the optional message data.
Return Value:
None.
--*/
{
KD_PACKET PacketHeader;
ULONG MessageDataLength;
USHORT ReturnCode;
PDBGKD_DEBUG_IO DebugIo;
PDBGKD_WAIT_STATE_CHANGE StateChange;
if ( ARGUMENT_PRESENT(MessageData) ) {
MessageDataLength = MessageData->Length;
PacketHeader.Checksum = KdpComputeChecksum(
MessageData->Buffer,
MessageData->Length
);
} else {
MessageDataLength = 0;
PacketHeader.Checksum = 0;
}
PacketHeader.Checksum += KdpComputeChecksum (
MessageHeader->Buffer,
MessageHeader->Length
);
//
// Initialize and send the packet header.
//
PacketHeader.PacketLeader = PACKET_LEADER;
PacketHeader.ByteCount = (USHORT)(MessageHeader->Length + MessageDataLength);
PacketHeader.PacketType = (USHORT)PacketType;
KdpNumberRetries = KdpRetryCount;
do {
if (KdpNumberRetries == 0) {
//
// If the packet is not for reporting exception, we give up
// and declare debugger not present.
//
if (PacketType == PACKET_TYPE_KD_DEBUG_IO) {
DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer;
if (DebugIo->ApiNumber == DbgKdPrintStringApi) {
KdDebuggerNotPresent = TRUE;
KdpNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID;
KdpPacketIdExpected = INITIAL_PACKET_ID;
return;
}
} else if (PacketType == PACKET_TYPE_KD_STATE_CHANGE) {
StateChange = (PDBGKD_WAIT_STATE_CHANGE)MessageHeader->Buffer;
if (StateChange->NewState == DbgKdLoadSymbolsStateChange) {
KdDebuggerNotPresent = TRUE;
KdpNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID;
KdpPacketIdExpected = INITIAL_PACKET_ID;
return;
}
}
}
//
// Setting PacketId has to be in the do loop in case Packet Id was
// reset.
//
PacketHeader.PacketId = KdpNextPacketIdToSend;
KdpSendString((PCHAR)&PacketHeader, sizeof(KD_PACKET));
//
// Output message header.
//
KdpSendString(MessageHeader->Buffer, MessageHeader->Length);
//
// Output message data.
//
if ( MessageDataLength ) {
KdpSendString(MessageData->Buffer, MessageData->Length);
}
//
// Output a packet trailing byte
//
KdPortPutByte(PACKET_TRAILING_BYTE);
// If we're using EDBG services, flush write buffer to net
if (KdpUseEdbg)
WriteEdbgBuffer();
// Don't need acks over reliable transports
if (!KdpUseTCPSockets) {
//
// Wait for the Ack Packet.
//
ReturnCode = KdpReceivePacket(
PACKET_TYPE_KD_ACKNOWLEDGE,
NULL,
NULL,
NULL
);
if (ReturnCode == KDP_PACKET_TIMEOUT) {
KdpNumberRetries--;
}
}
else {
// Since we don't wait for an ack with TCP, toggle the send id
// here.
KdpNextPacketIdToSend ^= 1;
ReturnCode = KDP_PACKET_RECEIVED;
}
} while (ReturnCode != KDP_PACKET_RECEIVED);
//
// Reset Sync bit in packet id. The packet we sent may have Sync bit set
//
KdpNextPacketIdToSend &= ~SYNC_PACKET_ID;
//
// Since we are able to talk to debugger, the retrycount is set to
// maximum value.
//
KdpRetryCount = MAXIMUM_RETRIES;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -