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)
9 //#define KDDEBUG /* uncomment to enable debugging this dll */
12 /* GLOBALS ********************************************************************/
14 PFNDBGPRNT KdpDbgPrint
= NULL
;
15 ULONG CurrentPacketId
= INITIAL_PACKET_ID
| SYNC_PACKET_ID
;
16 ULONG RemotePacketId
= 0;
19 /* PRIVATE FUNCTIONS **********************************************************/
21 /******************************************************************************
22 * \name KdpCalculateChecksum
23 * \brief Calculates the checksum for the packet data.
24 * \param Buffer Pointer to the packet data.
25 * \param Length Length of data in bytes.
26 * \return The calculated checksum.
27 * \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html
35 ULONG i
, Checksum
= 0;
37 for (i
= 0; i
< Length
; i
++)
39 Checksum
+= ((PUCHAR
)Buffer
)[i
];
49 IN ULONG PacketId OPTIONAL
)
53 Packet
.PacketLeader
= CONTROL_PACKET_LEADER
;
54 Packet
.PacketId
= PacketId
;
57 Packet
.PacketType
= PacketType
;
59 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
63 /* PUBLIC FUNCTIONS ***********************************************************/
69 return STATUS_SUCCESS
;
76 return STATUS_SUCCESS
;
80 /******************************************************************************
81 * \name KdDebuggerInitialize1
82 * \brief Phase 1 initialization.
83 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL.
88 KdDebuggerInitialize1(
89 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL
)
91 // HACK: misuse this function to get a pointer to FrLdrDbgPrint
92 KdpDbgPrint
= (PVOID
)LoaderBlock
;
93 KDDBGPRINT("KdDebuggerInitialize1\n");
95 return STATUS_NOT_IMPLEMENTED
;
99 /******************************************************************************
100 * \name KdReceivePacket
101 * \brief Receive a packet from the KD port.
102 * \param [in] PacketType Describes the type of the packet to receive.
103 * This can be one of the PACKET_TYPE_ constants.
104 * \param [out] MessageHeader Pointer to a STRING structure for the header.
105 * \param [out] MessageData Pointer to a STRING structure for the data.
106 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive
107 * timed out, KdPacketNeedsResend to signal that the last packet needs
109 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't
110 * wait for any data, but returns KdPacketTimedOut instantly if no breakin
111 * packet byte is received.
112 * \sa http://www.nynaeve.net/?p=169
118 OUT PSTRING MessageHeader
,
119 OUT PSTRING MessageData
,
120 OUT PULONG DataLength
,
121 IN OUT PKD_CONTEXT KdContext
)
128 /* Special handling for breakin packet */
129 if(PacketType
== PACKET_TYPE_KD_POLL_BREAKIN
)
131 return KdpPollBreakIn();
136 /* Step 1 - Read PacketLeader */
137 KdStatus
= KdpReceivePacketLeader(&Packet
.PacketLeader
);
138 if (KdStatus
!= KDP_PACKET_RECEIVED
)
140 /* Check if we got a breakin */
141 if (KdStatus
== KDP_PACKET_RESEND
)
143 KdContext
->KdpControlCPending
= TRUE
;
148 /* Step 2 - Read PacketType */
149 KdStatus
= KdpReceiveBuffer(&Packet
.PacketType
, sizeof(USHORT
));
150 if (KdStatus
!= KDP_PACKET_RECEIVED
)
152 /* Didn't receive a PacketType. */
156 /* Check if we got a resend packet */
157 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
&&
158 Packet
.PacketType
== PACKET_TYPE_KD_RESEND
)
160 return KDP_PACKET_RESEND
;
163 /* Step 3 - Read ByteCount */
164 KdStatus
= KdpReceiveBuffer(&Packet
.ByteCount
, sizeof(USHORT
));
165 if (KdStatus
!= KDP_PACKET_RECEIVED
)
167 /* Didn't receive ByteCount. */
171 /* Step 4 - Read PacketId */
172 KdStatus
= KdpReceiveBuffer(&Packet
.PacketId
, sizeof(ULONG
));
173 if (KdStatus
!= KDP_PACKET_RECEIVED
)
175 /* Didn't receive PacketId. */
180 if (Packet.PacketId != ExpectedPacketId)
187 /* Step 5 - Read Checksum */
188 KdStatus
= KdpReceiveBuffer(&Packet
.Checksum
, sizeof(ULONG
));
189 if (KdStatus
!= KDP_PACKET_RECEIVED
)
191 /* Didn't receive Checksum. */
195 /* Step 6 - Handle control packets */
196 if (Packet
.PacketLeader
== CONTROL_PACKET_LEADER
)
198 switch (Packet
.PacketType
)
200 case PACKET_TYPE_KD_ACKNOWLEDGE
:
201 /* Are we waiting for an ACK packet? */
202 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
&&
203 Packet
.PacketId
== (CurrentPacketId
& ~SYNC_PACKET_ID
))
205 /* Remote acknowledges the last packet */
206 CurrentPacketId
^= 1;
207 return KDP_PACKET_RECEIVED
;
209 /* That's not what we were waiting for, start over. */
212 case PACKET_TYPE_KD_RESET
:
213 KDDBGPRINT("KdReceivePacket - got a reset packet\n");
214 KdpSendControlPacket(PACKET_TYPE_KD_RESET
, 0);
215 CurrentPacketId
= INITIAL_PACKET_ID
;
216 RemotePacketId
= INITIAL_PACKET_ID
;
219 case PACKET_TYPE_KD_RESEND
:
220 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n");
221 /* Remote wants us to resend the last packet */
222 return KDP_PACKET_RESEND
;
225 KDDBGPRINT("KdReceivePacket - got unknown control packet\n");
226 return KDP_PACKET_RESEND
;
230 /* Did we wait for an ack packet? */
231 if (PacketType
== PACKET_TYPE_KD_ACKNOWLEDGE
)
233 /* We received something different */
234 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
235 CurrentPacketId
^= 1;
236 return KDP_PACKET_RECEIVED
;
239 /* Get size of the message header */
240 MessageHeader
->Length
= MessageHeader
->MaximumLength
;
242 /* Packet smaller than expected or too big? */
243 if (Packet
.ByteCount
< MessageHeader
->Length
||
244 Packet
.ByteCount
> PACKET_MAX_SIZE
)
246 KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n",
247 Packet
.ByteCount
, MessageHeader
->Length
);
248 MessageHeader
->Length
= Packet
.ByteCount
;
249 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
253 //KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer);
255 /* Receive the message header data */
256 KdStatus
= KdpReceiveBuffer(MessageHeader
->Buffer
,
257 MessageHeader
->Length
);
258 if (KdStatus
!= KDP_PACKET_RECEIVED
)
260 /* Didn't receive data. Packet needs to be resent. */
261 KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n");
262 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
266 //KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n");
268 /* Calculate checksum for the header data */
269 Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
270 MessageHeader
->Length
);
272 /* Calculate the length of the message data */
273 *DataLength
= Packet
.ByteCount
- MessageHeader
->Length
;
275 /* Shall we receive messsage data? */
278 /* Set the length of the message data */
279 MessageData
->Length
= *DataLength
;
281 /* Do we have data? */
282 if (MessageData
->Length
)
284 KDDBGPRINT("KdReceivePacket - got data\n");
286 /* Receive the message data */
287 KdStatus
= KdpReceiveBuffer(MessageData
->Buffer
,
288 MessageData
->Length
);
289 if (KdStatus
!= KDP_PACKET_RECEIVED
)
291 /* Didn't receive data. Start over. */
292 KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n");
293 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
297 /* Add cheksum for message data */
298 Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
299 MessageData
->Length
);
303 /* We must receive a PACKET_TRAILING_BYTE now */
304 KdStatus
= KdpReceiveBuffer(&Byte
, sizeof(UCHAR
));
305 if (KdStatus
!= KDP_PACKET_RECEIVED
|| Byte
!= PACKET_TRAILING_BYTE
)
307 KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte
, KdStatus
);
308 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
312 /* Compare checksum */
313 if (Packet
.Checksum
!= Checksum
)
315 KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n",
316 Packet
.Checksum
, Checksum
);
317 KdpSendControlPacket(PACKET_TYPE_KD_RESEND
, 0);
321 /* Acknowledge the received packet */
322 KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE
, Packet
.PacketId
);
324 /* Check if the received PacketId is ok */
325 if (Packet
.PacketId
!= RemotePacketId
)
327 /* Continue with next packet */
331 /* Did we get the right packet type? */
332 if (PacketType
== Packet
.PacketType
)
334 /* Yes, return success */
335 //KDDBGPRINT("KdReceivePacket - all ok\n");
337 return KDP_PACKET_RECEIVED
;
340 /* We received something different, ignore it. */
341 KDDBGPRINT("KdReceivePacket - wrong PacketType\n");
344 return KDP_PACKET_RECEIVED
;
352 IN PSTRING MessageHeader
,
353 IN PSTRING MessageData
,
354 IN OUT PKD_CONTEXT KdContext
)
360 /* Initialize a KD_PACKET */
361 Packet
.PacketLeader
= PACKET_LEADER
;
362 Packet
.PacketType
= PacketType
;
363 Packet
.ByteCount
= MessageHeader
->Length
;
364 Packet
.Checksum
= KdpCalculateChecksum(MessageHeader
->Buffer
,
365 MessageHeader
->Length
);
367 /* If we have message data, add it to the packet */
370 Packet
.ByteCount
+= MessageData
->Length
;
371 Packet
.Checksum
+= KdpCalculateChecksum(MessageData
->Buffer
,
372 MessageData
->Length
);
375 Retries
= KdContext
->KdpDefaultRetries
;
379 /* Set the packet id */
380 Packet
.PacketId
= CurrentPacketId
;
382 /* Send the packet header to the KD port */
383 KdpSendBuffer(&Packet
, sizeof(KD_PACKET
));
385 /* Send the message header */
386 KdpSendBuffer(MessageHeader
->Buffer
, MessageHeader
->Length
);
388 /* If we have meesage data, also send it */
391 KdpSendBuffer(MessageData
->Buffer
, MessageData
->Length
);
394 /* Finalize with a trailing byte */
395 KdpSendByte(PACKET_TRAILING_BYTE
);
397 /* Wait for acknowledge */
398 KdStatus
= KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE
,
404 /* Did we succeed? */
405 if (KdStatus
== KDP_PACKET_RECEIVED
)
407 CurrentPacketId
&= ~SYNC_PACKET_ID
;
411 /* PACKET_TYPE_KD_DEBUG_IO is allowed to instantly timeout */
412 if (PacketType
== PACKET_TYPE_KD_DEBUG_IO
)
414 /* No response, silently fail. */
418 if (KdStatus
== KDP_PACKET_TIMEOUT
)
423 /* Packet timed out, send it again */
424 KDDBGPRINT("KdSendPacket got KdStatus 0x%x\n", KdStatus
);