2 * COPYRIGHT: GPL, see COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/base/kddll/kddll.c
5 * PURPOSE: Base functions for the kernel debugger.
6 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
11 /* GLOBALS ********************************************************************/
13 ULONG CurrentPacketId
= INITIAL_PACKET_ID
| SYNC_PACKET_ID
;
14 ULONG RemotePacketId
= INITIAL_PACKET_ID
;
17 /* PRIVATE FUNCTIONS **********************************************************/
19 /******************************************************************************
20 * \name KdpCalculateChecksum
21 * \brief Calculates the checksum for the packet data.
22 * \param Buffer Pointer to the packet data.
23 * \param Length Length of data in bytes.
24 * \return The calculated checksum.
25 * \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
33 PUCHAR ByteBuffer
= Buffer
;
38 Checksum
+= (ULONG
)*ByteBuffer
++;
47 IN ULONG PacketId OPTIONAL
)
51 Packet
.PacketLeader
= CONTROL_PACKET_LEADER
;
52 Packet
.PacketId
= PacketId
;
55 Packet
.PacketType
= PacketType
;
57 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
61 /* PUBLIC FUNCTIONS ***********************************************************/
63 /******************************************************************************
64 * \name KdReceivePacket
65 * \brief Receive a packet from the KD port.
66 * \param [in] PacketType Describes the type of the packet to receive.
67 * This can be one of the PACKET_TYPE_ constants.
68 * \param [out] MessageHeader Pointer to a STRING structure for the header.
69 * \param [out] MessageData Pointer to a STRING structure for the data.
70 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
71 * timed out, KdPacketNeedsResend to signal that the last packet needs
73 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
74 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
75 * packet byte is received.
76 * \sa http://www.nynaeve.net/?p=169
82 OUT PSTRING MessageHeader
,
83 OUT PSTRING MessageData
,
84 OUT PULONG DataLength
,
85 IN OUT PKD_CONTEXT KdContext
)
92 /* Special handling for breakin packet */
93 if (PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
95 return KdpPollBreakIn();
100 /* Step 1 - Read PacketLeader */
101 KdStatus
= KdpReceivePacketLeader(&Packet
.PacketLeader
);
102 if (KdStatus
!= KDP_PACKET_RECEIVED
)
104 /* Check if we got a breakin */
105 if (KdStatus
== KDP_PACKET_RESEND
)
107 KdContext
->KdpControlCPending
= TRUE
;
112 /* Step 2 - Read PacketType */
113 KdStatus
= KdpReceiveBuffer(&Packet
.PacketType
, sizeof(USHORT
));
114 if (KdStatus
!= KDP_PACKET_RECEIVED
)
116 /* Didn't receive a PacketType. */
120 /* Check if we got a resend packet */
121 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
&&
122 Packet
.PacketType
== PACKET_TYPE_KD_RESEND
)
124 return KDP_PACKET_RESEND
;
127 /* Step 3 - Read ByteCount */
128 KdStatus
= KdpReceiveBuffer(&Packet
.ByteCount
, sizeof(USHORT
));
129 if (KdStatus
!= KDP_PACKET_RECEIVED
)
131 /* Didn't receive ByteCount. */
135 /* Step 4 - Read PacketId */
136 KdStatus
= KdpReceiveBuffer(&Packet
.PacketId
, sizeof(ULONG
));
137 if (KdStatus
!= KDP_PACKET_RECEIVED
)
139 /* Didn't receive PacketId. */
144 if (Packet.PacketId != ExpectedPacketId)
151 /* Step 5 - Read Checksum */
152 KdStatus
= KdpReceiveBuffer(&Packet
.Checksum
, sizeof(ULONG
));
153 if (KdStatus
!= KDP_PACKET_RECEIVED
)
155 /* Didn't receive Checksum. */
159 /* Step 6 - Handle control packets */
160 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
)
162 switch (Packet
.PacketType
)
164 case PACKET_TYPE_KD_ACKNOWLEDGE
:
165 /* Are we waiting for an ACK packet? */
166 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
&&
167 Packet
.PacketId
== (CurrentPacketId
& ~SYNC_PACKET_ID
))
169 /* Remote acknowledges the last packet */
170 CurrentPacketId
^= 1;
171 return KDP_PACKET_RECEIVED
;
173 /* That's not what we were waiting for, start over */
176 case PACKET_TYPE_KD_RESET
:
177 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESET\n");
178 CurrentPacketId
= INITIAL_PACKET_ID
;
179 RemotePacketId
= INITIAL_PACKET_ID
;
180 KdpSendControlPacket(PACKET_TYPE_KD_RESET
, 0);
183 case PACKET_TYPE_KD_RESEND
:
184 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n");
185 /* Remote wants us to resend the last packet */
186 return KDP_PACKET_RESEND
;
189 KDDBGPRINT("KdReceivePacket - got unknown control packet\n");
190 /* We got an invalid packet, ignore it and start over */
195 /* Did we wait for an ack packet? */
196 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
198 /* We received something different */
199 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
200 CurrentPacketId
^= 1;
201 return KDP_PACKET_RECEIVED
;
204 /* Get size of the message header */
205 MessageHeader
->Length
= MessageHeader
->MaximumLength
;
207 /* Packet smaller than expected or too big? */
208 if (Packet
.ByteCount
< MessageHeader
->Length
||
209 Packet
.ByteCount
> PACKET_MAX_SIZE
)
211 KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n",
212 Packet
.ByteCount
, MessageHeader
->Length
);
213 MessageHeader
->Length
= Packet
.ByteCount
;
214 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
218 //KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
220 /* Receive the message header data */
221 KdStatus
= KdpReceiveBuffer(MessageHeader
->Buffer
,
222 MessageHeader
->Length
);
223 if (KdStatus
!= KDP_PACKET_RECEIVED
)
225 /* Didn't receive data. Packet needs to be resent. */
226 KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n");
227 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
231 //KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n");
233 /* Calculate checksum for the header data */
234 Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
235 MessageHeader
->Length
);
237 /* Calculate the length of the message data */
238 *DataLength
= Packet
.ByteCount
- MessageHeader
->Length
;
240 /* Shall we receive message data? */
243 /* Set the length of the message data */
244 MessageData
->Length
= (USHORT
)*DataLength
;
246 /* Do we have data? */
247 if (MessageData
->Length
)
249 KDDBGPRINT("KdReceivePacket - got data\n");
251 /* Receive the message data */
252 KdStatus
= KdpReceiveBuffer(MessageData
->Buffer
,
253 MessageData
->Length
);
254 if (KdStatus
!= KDP_PACKET_RECEIVED
)
256 /* Didn't receive data. Start over. */
257 KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n");
258 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
262 /* Add cheksum for message data */
263 Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
264 MessageData
->Length
);
268 /* We must receive a PACKET_TRAILING_BYTE now */
269 KdStatus
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
270 if (KdStatus
!= KDP_PACKET_RECEIVED
|| Byte
!= PACKET_TRAILING_BYTE
)
272 KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte
, KdStatus
);
273 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
277 /* Compare checksum */
278 if (Packet
.Checksum
!= Checksum
)
280 KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
281 Packet
.Checksum
, Checksum
);
282 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
286 /* Acknowledge the received packet */
287 KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE
, Packet
.PacketId
);
289 /* Check if the received PacketId is ok */
290 if (Packet
.PacketId
!= RemotePacketId
)
292 /* Continue with next packet */
296 /* Did we get the right packet type? */
297 if (PacketType
== Packet
.PacketType
)
299 /* Yes, return success */
300 //KDDBGPRINT("KdReceivePacket - all ok\n");
302 return KDP_PACKET_RECEIVED
;
305 /* We received something different, ignore it. */
306 KDDBGPRINT("KdReceivePacket - wrong PacketType\n");
309 return KDP_PACKET_RECEIVED
;
316 IN PSTRING MessageHeader
,
317 IN PSTRING MessageData
,
318 IN OUT PKD_CONTEXT KdContext
)
324 /* Initialize a KD_PACKET */
325 Packet
.PacketLeader
= PACKET_LEADER
;
326 Packet
.PacketType
= (USHORT
)PacketType
;
327 Packet
.ByteCount
= MessageHeader
->Length
;
328 Packet
.Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
329 MessageHeader
->Length
);
331 /* If we have message data, add it to the packet */
334 Packet
.ByteCount
+= MessageData
->Length
;
335 Packet
.Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
336 MessageData
->Length
);
339 Retries
= KdContext
->KdpDefaultRetries
;
343 /* Set the packet id */
344 Packet
.PacketId
= CurrentPacketId
;
346 /* Send the packet header to the KD port */
347 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
349 /* Send the message header */
350 KdpSendBuffer(MessageHeader
->Buffer
, MessageHeader
->Length
);
352 /* If we have message data, also send it */
355 KdpSendBuffer(MessageData
->Buffer
, MessageData
->Length
);
358 /* Finalize with a trailing byte */
359 KdpSendByte(PACKET_TRAILING_BYTE
);
361 /* Wait for acknowledge */
362 KdStatus
= KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE
,
368 /* Did we succeed? */
369 if (KdStatus
== KDP_PACKET_RECEIVED
)
371 /* Packet received, we can quit the loop */
372 CurrentPacketId
&= ~SYNC_PACKET_ID
;
373 Retries
= KdContext
->KdpDefaultRetries
;
376 else if (KdStatus
== KDP_PACKET_TIMEOUT
)
378 /* Timeout, decrement the retry count */
383 * If the retry count reaches zero, bail out
384 * for packet types allowed to timeout.
388 ULONG MessageId
= *(PULONG
)MessageHeader
->Buffer
;
391 case PACKET_TYPE_KD_DEBUG_IO
:
393 if (MessageId
!= DbgKdPrintStringApi
) continue;
397 case PACKET_TYPE_KD_STATE_CHANGE32
:
398 case PACKET_TYPE_KD_STATE_CHANGE64
:
400 if (MessageId
!= DbgKdLoadSymbolsStateChange
) continue;
404 case PACKET_TYPE_KD_FILE_IO
:
406 if (MessageId
!= DbgKdCreateFileApi
) continue;
411 /* Reset debugger state */
412 KD_DEBUGGER_NOT_PRESENT
= TRUE
;
413 SharedUserData
->KdDebuggerEnabled
&= ~0x00000002;
414 CurrentPacketId
= INITIAL_PACKET_ID
| SYNC_PACKET_ID
;
415 RemotePacketId
= INITIAL_PACKET_ID
;
420 // else (KdStatus == KDP_PACKET_RESEND) /* Resend the packet */
422 /* Packet timed out, send it again */
423 KDDBGPRINT("KdSendPacket got KdStatus 0x%x\n", KdStatus
);