Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenkddll.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: GPL, see COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: drivers/base/kddll/kddll.c 00005 * PURPOSE: Base functions for the kernel debugger. 00006 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@ewactos.org) 00007 */ 00008 00009 #include "kddll.h" 00010 00011 /* GLOBALS ********************************************************************/ 00012 00013 PFNDBGPRNT KdpDbgPrint = NULL; 00014 ULONG CurrentPacketId = INITIAL_PACKET_ID | SYNC_PACKET_ID; 00015 ULONG RemotePacketId = 0; 00016 BOOLEAN KdpPhase1Complete = FALSE; 00017 ULONG KdpStallScaleFactor = 10000; 00018 00019 00020 /* PRIVATE FUNCTIONS **********************************************************/ 00021 00022 /****************************************************************************** 00023 * \name KdpCalculateChecksum 00024 * \brief Calculates the checksum for the packet data. 00025 * \param Buffer Pointer to the packet data. 00026 * \param Length Length of data in bytes. 00027 * \return The calculated checksum. 00028 * \sa http://www.vista-xp.co.uk/forums/technical-reference-library/2540-basics-debugging.html 00029 */ 00030 ULONG 00031 NTAPI 00032 KdpCalculateChecksum( 00033 IN PVOID Buffer, 00034 IN ULONG Length) 00035 { 00036 ULONG i, Checksum = 0; 00037 00038 for (i = 0; i < Length; i++) 00039 { 00040 Checksum += ((PUCHAR)Buffer)[i]; 00041 } 00042 00043 return Checksum; 00044 } 00045 00046 VOID 00047 NTAPI 00048 KdpSendControlPacket( 00049 IN USHORT PacketType, 00050 IN ULONG PacketId OPTIONAL) 00051 { 00052 KD_PACKET Packet; 00053 00054 Packet.PacketLeader = CONTROL_PACKET_LEADER; 00055 Packet.PacketId = PacketId; 00056 Packet.ByteCount = 0; 00057 Packet.Checksum = 0; 00058 Packet.PacketType = PacketType; 00059 00060 KdpSendBuffer(&Packet, sizeof(KD_PACKET)); 00061 } 00062 00063 00064 /* PUBLIC FUNCTIONS ***********************************************************/ 00065 00066 NTSTATUS 00067 NTAPI 00068 KdD0Transition(VOID) 00069 { 00070 return STATUS_SUCCESS; 00071 } 00072 00073 NTSTATUS 00074 NTAPI 00075 KdD3Transition(VOID) 00076 { 00077 return STATUS_SUCCESS; 00078 } 00079 00080 00081 /****************************************************************************** 00082 * \name KdDebuggerInitialize1 00083 * \brief Phase 1 initialization. 00084 * \param [opt] LoaderBlock Pointer to the Loader parameter block. Can be NULL. 00085 * \return Status 00086 */ 00087 NTSTATUS 00088 NTAPI 00089 KdDebuggerInitialize1( 00090 IN PLOADER_PARAMETER_BLOCK LoaderBlock OPTIONAL) 00091 { 00092 KdpStallScaleFactor = KeGetPcr()->StallScaleFactor * 100; 00093 KdpPhase1Complete = TRUE; 00094 00095 return STATUS_SUCCESS; 00096 } 00097 00098 00099 /****************************************************************************** 00100 * \name KdReceivePacket 00101 * \brief Receive a packet from the KD port. 00102 * \param [in] PacketType Describes the type of the packet to receive. 00103 * This can be one of the PACKET_TYPE_ constants. 00104 * \param [out] MessageHeader Pointer to a STRING structure for the header. 00105 * \param [out] MessageData Pointer to a STRING structure for the data. 00106 * \return KdPacketReceived if successful, KdPacketTimedOut if the receive 00107 * timed out, KdPacketNeedsResend to signal that the last packet needs 00108 * to be sent again. 00109 * \note If PacketType is PACKET_TYPE_KD_POLL_BREAKIN, the function doesn't 00110 * wait for any data, but returns KdPacketTimedOut instantly if no breakin 00111 * packet byte is received. 00112 * \sa http://www.nynaeve.net/?p=169 00113 */ 00114 KDP_STATUS 00115 NTAPI 00116 KdReceivePacket( 00117 IN ULONG PacketType, 00118 OUT PSTRING MessageHeader, 00119 OUT PSTRING MessageData, 00120 OUT PULONG DataLength, 00121 IN OUT PKD_CONTEXT KdContext) 00122 { 00123 UCHAR Byte = 0; 00124 KDP_STATUS KdStatus; 00125 KD_PACKET Packet; 00126 ULONG Checksum; 00127 00128 /* Special handling for breakin packet */ 00129 if(PacketType == PACKET_TYPE_KD_POLL_BREAKIN) 00130 { 00131 return KdpPollBreakIn(); 00132 } 00133 00134 for (;;) 00135 { 00136 /* Step 1 - Read PacketLeader */ 00137 KdStatus = KdpReceivePacketLeader(&Packet.PacketLeader); 00138 if (KdStatus != KDP_PACKET_RECEIVED) 00139 { 00140 /* Check if we got a breakin */ 00141 if (KdStatus == KDP_PACKET_RESEND) 00142 { 00143 KdContext->KdpControlCPending = TRUE; 00144 } 00145 return KdStatus; 00146 } 00147 00148 /* Step 2 - Read PacketType */ 00149 KdStatus = KdpReceiveBuffer(&Packet.PacketType, sizeof(USHORT)); 00150 if (KdStatus != KDP_PACKET_RECEIVED) 00151 { 00152 /* Didn't receive a PacketType. */ 00153 return KdStatus; 00154 } 00155 00156 /* Check if we got a resend packet */ 00157 if (Packet.PacketLeader == CONTROL_PACKET_LEADER && 00158 Packet.PacketType == PACKET_TYPE_KD_RESEND) 00159 { 00160 return KDP_PACKET_RESEND; 00161 } 00162 00163 /* Step 3 - Read ByteCount */ 00164 KdStatus = KdpReceiveBuffer(&Packet.ByteCount, sizeof(USHORT)); 00165 if (KdStatus != KDP_PACKET_RECEIVED) 00166 { 00167 /* Didn't receive ByteCount. */ 00168 return KdStatus; 00169 } 00170 00171 /* Step 4 - Read PacketId */ 00172 KdStatus = KdpReceiveBuffer(&Packet.PacketId, sizeof(ULONG)); 00173 if (KdStatus != KDP_PACKET_RECEIVED) 00174 { 00175 /* Didn't receive PacketId. */ 00176 return KdStatus; 00177 } 00178 00179 /* 00180 if (Packet.PacketId != ExpectedPacketId) 00181 { 00182 // Ask for a resend! 00183 continue; 00184 } 00185 */ 00186 00187 /* Step 5 - Read Checksum */ 00188 KdStatus = KdpReceiveBuffer(&Packet.Checksum, sizeof(ULONG)); 00189 if (KdStatus != KDP_PACKET_RECEIVED) 00190 { 00191 /* Didn't receive Checksum. */ 00192 return KdStatus; 00193 } 00194 00195 /* Step 6 - Handle control packets */ 00196 if (Packet.PacketLeader == CONTROL_PACKET_LEADER) 00197 { 00198 switch (Packet.PacketType) 00199 { 00200 case PACKET_TYPE_KD_ACKNOWLEDGE: 00201 /* Are we waiting for an ACK packet? */ 00202 if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE && 00203 Packet.PacketId == (CurrentPacketId & ~SYNC_PACKET_ID)) 00204 { 00205 /* Remote acknowledges the last packet */ 00206 CurrentPacketId ^= 1; 00207 return KDP_PACKET_RECEIVED; 00208 } 00209 /* That's not what we were waiting for, start over. */ 00210 continue; 00211 00212 case PACKET_TYPE_KD_RESET: 00213 KDDBGPRINT("KdReceivePacket - got a reset packet\n"); 00214 KdpSendControlPacket(PACKET_TYPE_KD_RESET, 0); 00215 CurrentPacketId = INITIAL_PACKET_ID; 00216 RemotePacketId = INITIAL_PACKET_ID; 00217 /* Fall through */ 00218 00219 case PACKET_TYPE_KD_RESEND: 00220 KDDBGPRINT("KdReceivePacket - got PACKET_TYPE_KD_RESEND\n"); 00221 /* Remote wants us to resend the last packet */ 00222 return KDP_PACKET_RESEND; 00223 00224 default: 00225 KDDBGPRINT("KdReceivePacket - got unknown control packet\n"); 00226 return KDP_PACKET_RESEND; 00227 } 00228 } 00229 00230 /* Did we wait for an ack packet? */ 00231 if (PacketType == PACKET_TYPE_KD_ACKNOWLEDGE) 00232 { 00233 /* We received something different */ 00234 KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0); 00235 CurrentPacketId ^= 1; 00236 return KDP_PACKET_RECEIVED; 00237 } 00238 00239 /* Get size of the message header */ 00240 MessageHeader->Length = MessageHeader->MaximumLength; 00241 00242 /* Packet smaller than expected or too big? */ 00243 if (Packet.ByteCount < MessageHeader->Length || 00244 Packet.ByteCount > PACKET_MAX_SIZE) 00245 { 00246 KDDBGPRINT("KdReceivePacket - too few data (%d) for type %d\n", 00247 Packet.ByteCount, MessageHeader->Length); 00248 MessageHeader->Length = Packet.ByteCount; 00249 KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0); 00250 continue; 00251 } 00252 00253 //KDDBGPRINT("KdReceivePacket - got normal PacketType, Buffer = %p\n", MessageHeader->Buffer); 00254 00255 /* Receive the message header data */ 00256 KdStatus = KdpReceiveBuffer(MessageHeader->Buffer, 00257 MessageHeader->Length); 00258 if (KdStatus != KDP_PACKET_RECEIVED) 00259 { 00260 /* Didn't receive data. Packet needs to be resent. */ 00261 KDDBGPRINT("KdReceivePacket - Didn't receive message header data.\n"); 00262 KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0); 00263 continue; 00264 } 00265 00266 //KDDBGPRINT("KdReceivePacket - got normal PacketType 3\n"); 00267 00268 /* Calculate checksum for the header data */ 00269 Checksum = KdpCalculateChecksum(MessageHeader->Buffer, 00270 MessageHeader->Length); 00271 00272 /* Calculate the length of the message data */ 00273 *DataLength = Packet.ByteCount - MessageHeader->Length; 00274 00275 /* Shall we receive messsage data? */ 00276 if (MessageData) 00277 { 00278 /* Set the length of the message data */ 00279 MessageData->Length = (USHORT)*DataLength; 00280 00281 /* Do we have data? */ 00282 if (MessageData->Length) 00283 { 00284 KDDBGPRINT("KdReceivePacket - got data\n"); 00285 00286 /* Receive the message data */ 00287 KdStatus = KdpReceiveBuffer(MessageData->Buffer, 00288 MessageData->Length); 00289 if (KdStatus != KDP_PACKET_RECEIVED) 00290 { 00291 /* Didn't receive data. Start over. */ 00292 KDDBGPRINT("KdReceivePacket - Didn't receive message data.\n"); 00293 KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0); 00294 continue; 00295 } 00296 00297 /* Add cheksum for message data */ 00298 Checksum += KdpCalculateChecksum(MessageData->Buffer, 00299 MessageData->Length); 00300 } 00301 } 00302 00303 /* We must receive a PACKET_TRAILING_BYTE now */ 00304 KdStatus = KdpReceiveBuffer(&Byte, sizeof(UCHAR)); 00305 if (KdStatus != KDP_PACKET_RECEIVED || Byte != PACKET_TRAILING_BYTE) 00306 { 00307 KDDBGPRINT("KdReceivePacket - wrong trailing byte (0x%x), status 0x%x\n", Byte, KdStatus); 00308 KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0); 00309 continue; 00310 } 00311 00312 /* Compare checksum */ 00313 if (Packet.Checksum != Checksum) 00314 { 00315 KDDBGPRINT("KdReceivePacket - wrong cheksum, got %x, calculated %x\n", 00316 Packet.Checksum, Checksum); 00317 KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0); 00318 continue; 00319 } 00320 00321 /* Acknowledge the received packet */ 00322 KdpSendControlPacket(PACKET_TYPE_KD_ACKNOWLEDGE, Packet.PacketId); 00323 00324 /* Check if the received PacketId is ok */ 00325 if (Packet.PacketId != RemotePacketId) 00326 { 00327 /* Continue with next packet */ 00328 continue; 00329 } 00330 00331 /* Did we get the right packet type? */ 00332 if (PacketType == Packet.PacketType) 00333 { 00334 /* Yes, return success */ 00335 //KDDBGPRINT("KdReceivePacket - all ok\n"); 00336 RemotePacketId ^= 1; 00337 return KDP_PACKET_RECEIVED; 00338 } 00339 00340 /* We received something different, ignore it. */ 00341 KDDBGPRINT("KdReceivePacket - wrong PacketType\n"); 00342 } 00343 00344 return KDP_PACKET_RECEIVED; 00345 } 00346 00347 00348 VOID 00349 NTAPI 00350 KdSendPacket( 00351 IN ULONG PacketType, 00352 IN PSTRING MessageHeader, 00353 IN PSTRING MessageData, 00354 IN OUT PKD_CONTEXT KdContext) 00355 { 00356 KD_PACKET Packet; 00357 KDP_STATUS KdStatus; 00358 ULONG Retries; 00359 00360 /* Initialize a KD_PACKET */ 00361 Packet.PacketLeader = PACKET_LEADER; 00362 Packet.PacketType = (USHORT)PacketType; 00363 Packet.ByteCount = MessageHeader->Length; 00364 Packet.Checksum = KdpCalculateChecksum(MessageHeader->Buffer, 00365 MessageHeader->Length); 00366 00367 /* If we have message data, add it to the packet */ 00368 if (MessageData) 00369 { 00370 Packet.ByteCount += MessageData->Length; 00371 Packet.Checksum += KdpCalculateChecksum(MessageData->Buffer, 00372 MessageData->Length); 00373 } 00374 00375 Retries = KdContext->KdpDefaultRetries; 00376 00377 do 00378 { 00379 /* Set the packet id */ 00380 Packet.PacketId = CurrentPacketId; 00381 00382 /* Send the packet header to the KD port */ 00383 KdpSendBuffer(&Packet, sizeof(KD_PACKET)); 00384 00385 /* Send the message header */ 00386 KdpSendBuffer(MessageHeader->Buffer, MessageHeader->Length); 00387 00388 /* If we have meesage data, also send it */ 00389 if (MessageData) 00390 { 00391 KdpSendBuffer(MessageData->Buffer, MessageData->Length); 00392 } 00393 00394 /* Finalize with a trailing byte */ 00395 KdpSendByte(PACKET_TRAILING_BYTE); 00396 00397 /* Wait for acknowledge */ 00398 KdStatus = KdReceivePacket(PACKET_TYPE_KD_ACKNOWLEDGE, 00399 NULL, 00400 NULL, 00401 0, 00402 KdContext); 00403 00404 /* Did we succeed? */ 00405 if (KdStatus == KDP_PACKET_RECEIVED) 00406 { 00407 CurrentPacketId &= ~SYNC_PACKET_ID; 00408 break; 00409 } 00410 00411 /* PACKET_TYPE_KD_DEBUG_IO is allowed to instantly timeout */ 00412 if (PacketType == PACKET_TYPE_KD_DEBUG_IO) 00413 { 00414 /* No response, silently fail. */ 00415 return; 00416 } 00417 00418 if (KdStatus == KDP_PACKET_TIMEOUT) 00419 { 00420 Retries--; 00421 } 00422 00423 /* Packet timed out, send it again */ 00424 KDDBGPRINT("KdSendPacket got KdStatus 0x%x\n", KdStatus); 00425 } 00426 while (Retries > 0); 00427 } 00428 Generated on Sat May 26 2012 04:25:42 for ReactOS by
1.7.6.1
|