ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

kddll.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.