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@ewactos.org)
11 /* GLOBALS ********************************************************************/
13 PFNDBGPRNT KdpDbgPrint
= NULL
;
14 ULONG CurrentPacketId
= INITIAL_PACKET_ID
| SYNC_PACKET_ID
;
15 ULONG RemotePacketId
= INITIAL_PACKET_ID
;
18 /* PRIVATE FUNCTIONS **********************************************************/
20 /******************************************************************************
21 * \name KdpCalculateChecksum
22 * \brief Calculates the checksum for the packet data.
23 * \param Buffer Pointer to the packet data.
24 * \param Length Length of data in bytes.
25 * \return The calculated checksum.
26 * \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
34 ULONG i
, Checksum
= 0;
36 for (i
= 0; i
< Length
; i
++)
38 Checksum
+= ((PUCHAR
)Buffer
)[i
];
48 IN ULONG PacketId OPTIONAL
)
52 Packet
.PacketLeader
= CONTROL_PACKET_LEADER
;
53 Packet
.PacketId
= PacketId
;
56 Packet
.PacketType
= PacketType
;
58 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
62 /* PUBLIC FUNCTIONS ***********************************************************/
68 return STATUS_SUCCESS
;
75 return STATUS_SUCCESS
;
79 /******************************************************************************
80 * \name KdDebuggerInitialize1
81 * \brief Phase 1 initialization.
82 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
87 KdDebuggerInitialize1(
88 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
90 return STATUS_SUCCESS
;
94 /******************************************************************************
95 * \name KdReceivePacket
96 * \brief Receive a packet from the KD port.
97 * \param [in] PacketType Describes the type of the packet to receive.
98 * This can be one of the PACKET_TYPE_ constants.
99 * \param [out] MessageHeader Pointer to a STRING structure for the header.
100 * \param [out] MessageData Pointer to a STRING structure for the data.
101 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
102 * timed out, KdPacketNeedsResend to signal that the last packet needs
104 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
105 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
106 * packet byte is received.
107 * \sa http://www.nynaeve.net/?p=169
113 OUT PSTRING MessageHeader
,
114 OUT PSTRING MessageData
,
115 OUT PULONG DataLength
,
116 IN OUT PKD_CONTEXT KdContext
)
123 /* Special handling for breakin packet */
124 if(PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
126 return KdpPollBreakIn();
131 /* Step 1 - Read PacketLeader */
132 KdStatus
= KdpReceivePacketLeader(&Packet
.PacketLeader
);
133 if (KdStatus
!= KDP_PACKET_RECEIVED
)
135 /* Check if we got a breakin */
136 if (KdStatus
== KDP_PACKET_RESEND
)
138 KdContext
->KdpControlCPending
= TRUE
;
143 /* Step 2 - Read PacketType */
144 KdStatus
= KdpReceiveBuffer(&Packet
.PacketType
, sizeof(USHORT
));
145 if (KdStatus
!= KDP_PACKET_RECEIVED
)
147 /* Didn't receive a PacketType. */
151 /* Check if we got a resend packet */
152 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
&&
153 Packet
.PacketType
== PACKET_TYPE_KD_RESEND
)
155 return KDP_PACKET_RESEND
;
158 /* Step 3 - Read ByteCount */
159 KdStatus
= KdpReceiveBuffer(&Packet
.ByteCount
, sizeof(USHORT
));
160 if (KdStatus
!= KDP_PACKET_RECEIVED
)
162 /* Didn't receive ByteCount. */
166 /* Step 4 - Read PacketId */
167 KdStatus
= KdpReceiveBuffer(&Packet
.PacketId
, sizeof(ULONG
));
168 if (KdStatus
!= KDP_PACKET_RECEIVED
)
170 /* Didn't receive PacketId. */
175 if (Packet.PacketId != ExpectedPacketId)
182 /* Step 5 - Read Checksum */
183 KdStatus
= KdpReceiveBuffer(&Packet
.Checksum
, sizeof(ULONG
));
184 if (KdStatus
!= KDP_PACKET_RECEIVED
)
186 /* Didn't receive Checksum. */
190 /* Step 6 - Handle control packets */
191 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
)
193 switch (Packet
.PacketType
)
195 case PACKET_TYPE_KD_ACKNOWLEDGE
:
196 /* Are we waiting for an ACK packet? */
197 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
&&
198 Packet
.PacketId
== (CurrentPacketId
& ~SYNC_PACKET_ID
))
200 /* Remote acknowledges the last packet */
201 CurrentPacketId
^= 1;
202 return KDP_PACKET_RECEIVED
;
204 /* That's not what we were waiting for, start over. */
207 case PACKET_TYPE_KD_RESET
:
208 KDDBGPRINT("KdReceivePacket - got a reset packet\n");
209 KdpSendControlPacket(PACKET_TYPE_KD_RESET
, 0);
210 CurrentPacketId
= INITIAL_PACKET_ID
;
211 RemotePacketId
= INITIAL_PACKET_ID
;
214 case PACKET_TYPE_KD_RESEND
:
215 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n");
216 /* Remote wants us to resend the last packet */
217 return KDP_PACKET_RESEND
;
220 KDDBGPRINT("KdReceivePacket - got unknown control packet\n");
221 return KDP_PACKET_RESEND
;
225 /* Did we wait for an ack packet? */
226 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
228 /* We received something different */
229 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
230 CurrentPacketId
^= 1;
231 return KDP_PACKET_RECEIVED
;
234 /* Get size of the message header */
235 MessageHeader
->Length
= MessageHeader
->MaximumLength
;
237 /* Packet smaller than expected or too big? */
238 if (Packet
.ByteCount
< MessageHeader
->Length
||
239 Packet
.ByteCount
> PACKET_MAX_SIZE
)
241 KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n",
242 Packet
.ByteCount
, MessageHeader
->Length
);
243 MessageHeader
->Length
= Packet
.ByteCount
;
244 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
248 //KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
250 /* Receive the message header data */
251 KdStatus
= KdpReceiveBuffer(MessageHeader
->Buffer
,
252 MessageHeader
->Length
);
253 if (KdStatus
!= KDP_PACKET_RECEIVED
)
255 /* Didn't receive data. Packet needs to be resent. */
256 KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n");
257 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
261 //KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n");
263 /* Calculate checksum for the header data */
264 Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
265 MessageHeader
->Length
);
267 /* Calculate the length of the message data */
268 *DataLength
= Packet
.ByteCount
- MessageHeader
->Length
;
270 /* Shall we receive messsage data? */
273 /* Set the length of the message data */
274 MessageData
->Length
= (USHORT
)*DataLength
;
276 /* Do we have data? */
277 if (MessageData
->Length
)
279 KDDBGPRINT("KdReceivePacket - got data\n");
281 /* Receive the message data */
282 KdStatus
= KdpReceiveBuffer(MessageData
->Buffer
,
283 MessageData
->Length
);
284 if (KdStatus
!= KDP_PACKET_RECEIVED
)
286 /* Didn't receive data. Start over. */
287 KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n");
288 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
292 /* Add cheksum for message data */
293 Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
294 MessageData
->Length
);
298 /* We must receive a PACKET_TRAILING_BYTE now */
299 KdStatus
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
300 if (KdStatus
!= KDP_PACKET_RECEIVED
|| Byte
!= PACKET_TRAILING_BYTE
)
302 KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte
, KdStatus
);
303 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
307 /* Compare checksum */
308 if (Packet
.Checksum
!= Checksum
)
310 KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
311 Packet
.Checksum
, Checksum
);
312 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
316 /* Acknowledge the received packet */
317 KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE
, Packet
.PacketId
);
319 /* Check if the received PacketId is ok */
320 if (Packet
.PacketId
!= RemotePacketId
)
322 /* Continue with next packet */
326 /* Did we get the right packet type? */
327 if (PacketType
== Packet
.PacketType
)
329 /* Yes, return success */
330 //KDDBGPRINT("KdReceivePacket - all ok\n");
332 return KDP_PACKET_RECEIVED
;
335 /* We received something different, ignore it. */
336 KDDBGPRINT("KdReceivePacket - wrong PacketType\n");
339 return KDP_PACKET_RECEIVED
;
347 IN PSTRING MessageHeader
,
348 IN PSTRING MessageData
,
349 IN OUT PKD_CONTEXT KdContext
)
355 /* Initialize a KD_PACKET */
356 Packet
.PacketLeader
= PACKET_LEADER
;
357 Packet
.PacketType
= (USHORT
)PacketType
;
358 Packet
.ByteCount
= MessageHeader
->Length
;
359 Packet
.Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
360 MessageHeader
->Length
);
362 /* If we have message data, add it to the packet */
365 Packet
.ByteCount
+= MessageData
->Length
;
366 Packet
.Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
367 MessageData
->Length
);
370 Retries
= KdContext
->KdpDefaultRetries
;
376 /* PACKET_TYPE_KD_DEBUG_IO is allowed to instantly timeout */
377 if (PacketType
== PACKET_TYPE_KD_DEBUG_IO
)
379 /* No response, silently fail. */
384 /* Set the packet id */
385 Packet
.PacketId
= CurrentPacketId
;
387 /* Send the packet header to the KD port */
388 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
390 /* Send the message header */
391 KdpSendBuffer(MessageHeader
->Buffer
, MessageHeader
->Length
);
393 /* If we have meesage data, also send it */
394 if (MessageData
) KdpSendBuffer(MessageData
->Buffer
, MessageData
->Length
);
396 /* Finalize with a trailing byte */
397 KdpSendByte(PACKET_TRAILING_BYTE
);
399 /* Wait for acknowledge */
400 KdStatus
= KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE
,
405 if (KdStatus
== KDP_PACKET_TIMEOUT
)
407 if (Retries
> 0) Retries
--;
410 /* Packet timed out, send it again */
411 KDDBGPRINT("KdSendPacket got KdStatus 0x%x\n", KdStatus
);
413 } while (KdStatus
!= KDP_PACKET_RECEIVED
);
415 CurrentPacketId
&= ~SYNC_PACKET_ID
;