ReactOS 0.4.16-dev-401-g45b008d
kddll.c
Go to the documentation of this file.
1/*
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)
7 */
8
9#include "kddll.h"
10
11/* GLOBALS ********************************************************************/
12
15
16
17/* PRIVATE FUNCTIONS **********************************************************/
18
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
26 */
32{
33 PUCHAR ByteBuffer = Buffer;
34 ULONG Checksum = 0;
35
36 while (Length-- > 0)
37 {
38 Checksum += (ULONG)*ByteBuffer++;
39 }
40 return Checksum;
41}
42
43VOID
46 IN USHORT PacketType,
47 IN ULONG PacketId OPTIONAL)
48{
50
51 Packet.PacketLeader = CONTROL_PACKET_LEADER;
52 Packet.PacketId = PacketId;
53 Packet.ByteCount = 0;
54 Packet.Checksum = 0;
55 Packet.PacketType = PacketType;
56
58}
59
60
61/* PUBLIC FUNCTIONS ***********************************************************/
62
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
72 * to be sent again.
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
77 */
81 IN ULONG PacketType,
82 OUT PSTRING MessageHeader,
83 OUT PSTRING MessageData,
85 IN OUT PKD_CONTEXT KdContext)
86{
87 UCHAR Byte = 0;
88 KDP_STATUS KdStatus;
90 ULONG Checksum;
91
92 /* Special handling for breakin packet */
93 if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN)
94 {
95 return KdpPollBreakIn();
96 }
97
98 for (;;)
99 {
100 /* Step 1 - Read PacketLeader */
101 KdStatus = KdpReceivePacketLeader(&Packet.PacketLeader);
102 if (KdStatus != KDP_PACKET_RECEIVED)
103 {
104 /* Check if we got a breakin */
105 if (KdStatus == KDP_PACKET_RESEND)
106 {
107 KdContext->KdpControlCPending = TRUE;
108 }
109 return KdStatus;
110 }
111
112 /* Step 2 - Read PacketType */
113 KdStatus = KdpReceiveBuffer(&Packet.PacketType, sizeof(USHORT));
114 if (KdStatus != KDP_PACKET_RECEIVED)
115 {
116 /* Didn't receive a PacketType. */
117 return KdStatus;
118 }
119
120 /* Check if we got a resend packet */
121 if (Packet.PacketLeader == CONTROL_PACKET_LEADER &&
122 Packet.PacketType == PACKET_TYPE_KD_RESEND)
123 {
124 return KDP_PACKET_RESEND;
125 }
126
127 /* Step 3 - Read ByteCount */
128 KdStatus = KdpReceiveBuffer(&Packet.ByteCount, sizeof(USHORT));
129 if (KdStatus != KDP_PACKET_RECEIVED)
130 {
131 /* Didn't receive ByteCount. */
132 return KdStatus;
133 }
134
135 /* Step 4 - Read PacketId */
136 KdStatus = KdpReceiveBuffer(&Packet.PacketId, sizeof(ULONG));
137 if (KdStatus != KDP_PACKET_RECEIVED)
138 {
139 /* Didn't receive PacketId. */
140 return KdStatus;
141 }
142
143/*
144 if (Packet.PacketId != ExpectedPacketId)
145 {
146 // Ask for a resend!
147 continue;
148 }
149*/
150
151 /* Step 5 - Read Checksum */
152 KdStatus = KdpReceiveBuffer(&Packet.Checksum, sizeof(ULONG));
153 if (KdStatus != KDP_PACKET_RECEIVED)
154 {
155 /* Didn't receive Checksum. */
156 return KdStatus;
157 }
158
159 /* Step 6 - Handle control packets */
160 if (Packet.PacketLeader == CONTROL_PACKET_LEADER)
161 {
162 switch (Packet.PacketType)
163 {
165 /* Are we waiting for an ACK packet? */
166 if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE &&
167 Packet.PacketId == (CurrentPacketId & ~SYNC_PACKET_ID))
168 {
169 /* Remote acknowledges the last packet */
170 CurrentPacketId ^= 1;
171 return KDP_PACKET_RECEIVED;
172 }
173 /* That's not what we were waiting for, start over */
174 continue;
175
177 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESET\n");
181 /* Fall through */
182
184 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n");
185 /* Remote wants us to resend the last packet */
186 return KDP_PACKET_RESEND;
187
188 default:
189 KDDBGPRINT("KdReceivePacket - got unknown control packet\n");
190 /* We got an invalid packet, ignore it and start over */
191 continue;
192 }
193 }
194
195 /* Did we wait for an ack packet? */
196 if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE)
197 {
198 /* We received something different */
200 CurrentPacketId ^= 1;
201 return KDP_PACKET_RECEIVED;
202 }
203
204 /* Get size of the message header */
205 MessageHeader->Length = MessageHeader->MaximumLength;
206
207 /* Packet smaller than expected or too big? */
208 if (Packet.ByteCount < MessageHeader->Length ||
209 Packet.ByteCount > PACKET_MAX_SIZE)
210 {
211 KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n",
212 Packet.ByteCount, MessageHeader->Length);
213 MessageHeader->Length = Packet.ByteCount;
215 continue;
216 }
217
218 //KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
219
220 /* Receive the message header data */
221 KdStatus = KdpReceiveBuffer(MessageHeader->Buffer,
222 MessageHeader->Length);
223 if (KdStatus != KDP_PACKET_RECEIVED)
224 {
225 /* Didn't receive data. Packet needs to be resent. */
226 KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n");
228 continue;
229 }
230
231 //KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n");
232
233 /* Calculate checksum for the header data */
234 Checksum = KdpCalculateChecksum(MessageHeader->Buffer,
235 MessageHeader->Length);
236
237 /* Calculate the length of the message data */
238 *DataLength = Packet.ByteCount - MessageHeader->Length;
239
240 /* Shall we receive message data? */
241 if (MessageData)
242 {
243 /* Set the length of the message data */
244 MessageData->Length = (USHORT)*DataLength;
245
246 /* Do we have data? */
247 if (MessageData->Length)
248 {
249 KDDBGPRINT("KdReceivePacket - got data\n");
250
251 /* Receive the message data */
252 KdStatus = KdpReceiveBuffer(MessageData->Buffer,
253 MessageData->Length);
254 if (KdStatus != KDP_PACKET_RECEIVED)
255 {
256 /* Didn't receive data. Start over. */
257 KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n");
259 continue;
260 }
261
262 /* Add cheksum for message data */
263 Checksum += KdpCalculateChecksum(MessageData->Buffer,
264 MessageData->Length);
265 }
266 }
267
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)
271 {
272 KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte, KdStatus);
274 continue;
275 }
276
277 /* Compare checksum */
278 if (Packet.Checksum != Checksum)
279 {
280 KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
281 Packet.Checksum, Checksum);
283 continue;
284 }
285
286 /* Acknowledge the received packet */
288
289 /* Check if the received PacketId is ok */
290 if (Packet.PacketId != RemotePacketId)
291 {
292 /* Continue with next packet */
293 continue;
294 }
295
296 /* Did we get the right packet type? */
297 if (PacketType == Packet.PacketType)
298 {
299 /* Yes, return success */
300 //KDDBGPRINT("KdReceivePacket - all ok\n");
301 RemotePacketId ^= 1;
302 return KDP_PACKET_RECEIVED;
303 }
304
305 /* We received something different, ignore it. */
306 KDDBGPRINT("KdReceivePacket - wrong PacketType\n");
307 }
308
309 return KDP_PACKET_RECEIVED;
310}
311
312VOID
313NTAPI
315 IN ULONG PacketType,
316 IN PSTRING MessageHeader,
317 IN PSTRING MessageData,
318 IN OUT PKD_CONTEXT KdContext)
319{
321 KDP_STATUS KdStatus;
322 ULONG Retries;
323
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);
330
331 /* If we have message data, add it to the packet */
332 if (MessageData)
333 {
334 Packet.ByteCount += MessageData->Length;
335 Packet.Checksum += KdpCalculateChecksum(MessageData->Buffer,
336 MessageData->Length);
337 }
338
339 Retries = KdContext->KdpDefaultRetries;
340
341 for (;;)
342 {
343 /* Set the packet id */
344 Packet.PacketId = CurrentPacketId;
345
346 /* Send the packet header to the KD port */
347 KdpSendBuffer(&Packet, sizeof(KD_PACKET));
348
349 /* Send the message header */
350 KdpSendBuffer(MessageHeader->Buffer, MessageHeader->Length);
351
352 /* If we have message data, also send it */
353 if (MessageData)
354 {
355 KdpSendBuffer(MessageData->Buffer, MessageData->Length);
356 }
357
358 /* Finalize with a trailing byte */
360
361 /* Wait for acknowledge */
363 NULL,
364 NULL,
365 NULL,
366 KdContext);
367
368 /* Did we succeed? */
369 if (KdStatus == KDP_PACKET_RECEIVED)
370 {
371 /* Packet received, we can quit the loop */
372 CurrentPacketId &= ~SYNC_PACKET_ID;
373 Retries = KdContext->KdpDefaultRetries;
374 break;
375 }
376 else if (KdStatus == KDP_PACKET_TIMEOUT)
377 {
378 /* Timeout, decrement the retry count */
379 if (Retries > 0)
380 Retries--;
381
382 /*
383 * If the retry count reaches zero, bail out
384 * for packet types allowed to timeout.
385 */
386 if (Retries == 0)
387 {
388 ULONG MessageId = *(PULONG)MessageHeader->Buffer;
389 switch (PacketType)
390 {
392 {
393 if (MessageId != DbgKdPrintStringApi) continue;
394 break;
395 }
396
399 {
400 if (MessageId != DbgKdLoadSymbolsStateChange) continue;
401 break;
402 }
403
405 {
406 if (MessageId != DbgKdCreateFileApi) continue;
407 break;
408 }
409 }
410
411 /* Reset debugger state */
413 SharedUserData->KdDebuggerEnabled &= ~0x00000002;
416
417 return;
418 }
419 }
420 // else (KdStatus == KDP_PACKET_RESEND) /* Resend the packet */
421
422 /* Packet timed out, send it again */
423 KDDBGPRINT("KdSendPacket got KdStatus 0x%x\n", KdStatus);
424 }
425}
426
427/* EOF */
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
unsigned char Byte
Definition: zlib.h:37
#define KDDBGPRINT(...)
Definition: kddll.h:19
VOID NTAPI KdpSendBuffer(IN PVOID Buffer, IN ULONG Size)
Definition: kdserial.c:21
KDP_STATUS NTAPI KdpReceiveBuffer(OUT PVOID Buffer, IN ULONG Size)
Definition: kdserial.c:43
KDP_STATUS
Definition: kddll.h:26
@ KDP_PACKET_TIMEOUT
Definition: kddll.h:28
@ KDP_PACKET_RESEND
Definition: kddll.h:29
@ KDP_PACKET_RECEIVED
Definition: kddll.h:27
KDP_STATUS NTAPI KdpReceivePacketLeader(OUT PULONG PacketLeader)
Definition: kdserial.c:75
switch(r->id)
Definition: btrfs.c:3046
VOID NTAPI KdpSendByte(IN UCHAR Byte)
Definition: kdcom.c:291
KDP_STATUS NTAPI KdpPollBreakIn(VOID)
Definition: kdcom.c:343
ULONG CurrentPacketId
Definition: kddll.c:13
ULONG NTAPI KdpCalculateChecksum(IN PVOID Buffer, IN ULONG Length)
Definition: kddll.c:29
VOID NTAPI KdSendPacket(IN ULONG PacketType, IN PSTRING MessageHeader, IN PSTRING MessageData, IN OUT PKD_CONTEXT KdContext)
Definition: kddll.c:314
ULONG RemotePacketId
Definition: kddll.c:14
KDP_STATUS NTAPI KdReceivePacket(IN ULONG PacketType, OUT PSTRING MessageHeader, OUT PSTRING MessageData, OUT PULONG DataLength, IN OUT PKD_CONTEXT KdContext)
Definition: kddll.c:80
VOID NTAPI KdpSendControlPacket(IN USHORT PacketType, IN ULONG PacketId OPTIONAL)
Definition: kddll.c:45
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
unsigned short USHORT
Definition: pedump.c:61
#define SharedUserData
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
uint32_t * PULONG
Definition: typedefs.h:59
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define DbgKdLoadSymbolsStateChange
Definition: windbgkd.h:60
#define DbgKdPrintStringApi
Definition: windbgkd.h:122
#define PACKET_TYPE_KD_FILE_IO
Definition: windbgkd.h:52
#define PACKET_TYPE_KD_STATE_CHANGE32
Definition: windbgkd.h:42
#define PACKET_MAX_SIZE
Definition: windbgkd.h:18
#define PACKET_TYPE_KD_ACKNOWLEDGE
Definition: windbgkd.h:45
#define PACKET_TRAILING_BYTE
Definition: windbgkd.h:36
#define PACKET_TYPE_KD_STATE_CHANGE64
Definition: windbgkd.h:48
#define CONTROL_PACKET_LEADER
Definition: windbgkd.h:34
#define PACKET_TYPE_KD_POLL_BREAKIN
Definition: windbgkd.h:49
#define DbgKdCreateFileApi
Definition: windbgkd.h:139
#define INITIAL_PACKET_ID
Definition: windbgkd.h:24
#define PACKET_TYPE_KD_RESET
Definition: windbgkd.h:47
#define PACKET_LEADER
Definition: windbgkd.h:32
#define SYNC_PACKET_ID
Definition: windbgkd.h:25
#define PACKET_TYPE_KD_RESEND
Definition: windbgkd.h:46
#define PACKET_TYPE_KD_DEBUG_IO
Definition: windbgkd.h:44
#define KD_DEBUGGER_NOT_PRESENT
Definition: kdfuncs.h:133
unsigned char UCHAR
Definition: xmlstorage.h:181