Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

504 lines
14 KiB

  1. /*++
  2. Copyright (c) 1998-2001 Microsoft Corporation
  3. Module Name:
  4. kd1394io.c
  5. Abstract:
  6. 1394 Kernel Debugger DLL
  7. Author:
  8. George Chrysanthakopoulos (georgioc) Nov-1999
  9. Revision History:
  10. Date Who What
  11. ---------- --------- ------------------------------------------------------------
  12. 06/19/2001 pbinder cleanup
  13. --*/
  14. #define _KD1394IO_C
  15. #include "pch.h"
  16. #undef _KD1394IO_C
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(PAGEKD, KdpComputeChecksum)
  19. #pragma alloc_text(PAGEKD, KdpSendControlPacket)
  20. #pragma alloc_text(PAGEKD, KdReceivePacket)
  21. #pragma alloc_text(PAGEKD, KdSendPacket)
  22. #endif
  23. //
  24. // KdpRetryCount controls the number of retries before we give
  25. // up and assume kernel debugger is not present.
  26. // KdpNumberRetries is the number of retries left. Initially,
  27. // it is set to 5 such that booting NT without debugger won't be
  28. // delayed to long.
  29. //
  30. ULONG KdCompNumberRetries = 5;
  31. ULONG KdCompRetryCount = 5;
  32. ULONG KdPacketId = 0;
  33. ULONG
  34. KdpComputeChecksum(
  35. IN PUCHAR Buffer,
  36. IN ULONG Length
  37. )
  38. /*++
  39. Routine Description:
  40. This routine computes the checksum for the string passed in.
  41. Arguments:
  42. Buffer - Supplies a pointer to the string.
  43. Length - Supplies the length of the string.
  44. Return Value:
  45. A ULONG is return as the checksum for the input string.
  46. --*/
  47. {
  48. ULONG Checksum = 0;
  49. while (Length > 0) {
  50. Checksum = Checksum + (ULONG)*Buffer++;
  51. Length--;
  52. }
  53. return(Checksum);
  54. } // KdpComputeChecksum
  55. void
  56. KdpSendControlPacket(
  57. IN USHORT PacketType,
  58. IN ULONG PacketId OPTIONAL
  59. )
  60. /*++
  61. Routine Description:
  62. This routine sends a control packet to the host machine that is running the
  63. kernel debugger and waits for an ACK.
  64. Arguments:
  65. PacketType - Supplies the type of packet to send.
  66. PacketId - Supplies packet id, optionally.
  67. Return Value:
  68. None.
  69. --*/
  70. {
  71. KD_PACKET PacketHeader;
  72. //
  73. // Initialize and send the packet header.
  74. //
  75. PacketHeader.PacketLeader = CONTROL_PACKET_LEADER;
  76. if (ARGUMENT_PRESENT((PVOID)(ULONG_PTR)PacketId)) {
  77. PacketHeader.PacketId = PacketId;
  78. }
  79. PacketHeader.PacketId = 0;
  80. PacketHeader.ByteCount = 0;
  81. PacketHeader.Checksum = 0;
  82. PacketHeader.PacketType = PacketType;
  83. // setup our send packet
  84. RtlZeroMemory(&Kd1394Data->SendPacket, sizeof(DEBUG_1394_SEND_PACKET));
  85. Kd1394Data->SendPacket.Length = 0;
  86. RtlCopyMemory( &Kd1394Data->SendPacket.PacketHeader[0],
  87. &PacketHeader,
  88. sizeof(KD_PACKET)
  89. );
  90. Kd1394Data->SendPacket.TransferStatus = STATUS_PENDING;
  91. return;
  92. } // KdpSendControlPacket
  93. ULONG
  94. KdReceivePacket(
  95. IN ULONG PacketType,
  96. OUT PSTRING MessageHeader,
  97. OUT PSTRING MessageData,
  98. OUT PULONG DataLength,
  99. IN OUT PKD_CONTEXT KdContext
  100. )
  101. /*++
  102. Routine Description:
  103. This routine receives a packet from the host machine that is running
  104. the kernel debugger UI. This routine is ALWAYS called after packet being
  105. sent by caller. It first waits for ACK packet for the packet sent and
  106. then waits for the packet desired.
  107. N.B. If caller is KdPrintString, the parameter PacketType is
  108. PACKET_TYPE_KD_ACKNOWLEDGE. In this case, this routine will return
  109. right after the ack packet is received.
  110. Arguments:
  111. PacketType - Supplies the type of packet that is excepted.
  112. MessageHeader - Supplies a pointer to a string descriptor for the input
  113. message.
  114. MessageData - Supplies a pointer to a string descriptor for the input data.
  115. DataLength - Supplies pointer to ULONG to receive length of recv. data.
  116. KdContext - Supplies a pointer to the kernel debugger context.
  117. Return Value:
  118. KDP_PACKET_RESEND - if resend is required. = 2 = CP_GET_ERROR
  119. KDP_PACKET_TIMEOUT - if timeout. = 1 = CP_GET_NODATA
  120. KDP_PACKET_RECEIVED - if packet received. = 0 = CP_GET_SUCCESS
  121. --*/
  122. {
  123. UCHAR Input;
  124. ULONG MessageLength;
  125. KD_PACKET PacketHeader;
  126. ULONG ReturnCode;
  127. ULONG Checksum;
  128. ULONG Status;
  129. // this dispatch gets called with PacketType != PACKET_TYPE_KD_POLL_BREAKIN for
  130. // the number of times specified in KdCompNumberRetries (??). if we always timeout
  131. // then we'll get called with PacketType == PACKET_TYPE_KD_POLL_BREAKIN
  132. // make sure our link is enabled..
  133. Dbg1394_EnablePhysicalAccess(Kd1394Data);
  134. //
  135. // Just check for breakin packet and return
  136. //
  137. if (PacketType == PACKET_TYPE_KD_POLL_BREAKIN) {
  138. // let's peak into our receive packet and see if it's a breakin
  139. if ((Kd1394Data->ReceivePacket.TransferStatus == STATUS_PENDING) &&
  140. (Kd1394Data->ReceivePacket.Packet[0] == BREAKIN_PACKET_BYTE)) {
  141. *KdDebuggerNotPresent = FALSE;
  142. SharedUserData->KdDebuggerEnabled |= 0x00000002;
  143. // we have a breakin packet
  144. Kd1394Data->ReceivePacket.TransferStatus = STATUS_SUCCESS;
  145. return(KDP_PACKET_RECEIVED);
  146. }
  147. else {
  148. return(KDP_PACKET_TIMEOUT);
  149. }
  150. }
  151. WaitForPacketLeader:
  152. // read in our packet, if available...
  153. ReturnCode = Dbg1394_ReadPacket( Kd1394Data,
  154. &PacketHeader,
  155. MessageHeader,
  156. MessageData,
  157. TRUE
  158. );
  159. //
  160. // If we can successfully read packet leader, it has high possibility that
  161. // kernel debugger is alive. So reset count.
  162. //
  163. if (ReturnCode != KDP_PACKET_TIMEOUT) {
  164. KdCompNumberRetries = KdCompRetryCount;
  165. }
  166. if (ReturnCode != KDP_PACKET_RECEIVED) {
  167. // see if it's a breakin packet...
  168. if ((PacketHeader.PacketLeader & 0xFF) == BREAKIN_PACKET_BYTE) {
  169. KdContext->KdpControlCPending = TRUE;
  170. return(KDP_PACKET_RESEND);
  171. }
  172. return(ReturnCode);
  173. }
  174. //
  175. // if the packet we received is a resend request, we return true and
  176. // let caller resend the packet.
  177. //
  178. if (PacketHeader.PacketLeader == CONTROL_PACKET_LEADER &&
  179. PacketHeader.PacketType == PACKET_TYPE_KD_RESEND) {
  180. return(KDP_PACKET_RESEND);
  181. }
  182. //
  183. // Check ByteCount received is valid
  184. //
  185. MessageLength = MessageHeader->MaximumLength;
  186. if ((PacketHeader.ByteCount > (USHORT)PACKET_MAX_SIZE) ||
  187. (PacketHeader.ByteCount < (USHORT)MessageLength)) {
  188. goto SendResendPacket;
  189. }
  190. *DataLength = PacketHeader.ByteCount - MessageLength;
  191. MessageData->Length = (USHORT)*DataLength;
  192. MessageHeader->Length = (USHORT)MessageLength;
  193. //
  194. // Check PacketType is what we are waiting for.
  195. //
  196. if (PacketType != PacketHeader.PacketType) {
  197. goto SendResendPacket;
  198. }
  199. //
  200. // Check checksum is valid.
  201. //
  202. Checksum = KdpComputeChecksum(MessageHeader->Buffer, MessageHeader->Length);
  203. Checksum += KdpComputeChecksum(MessageData->Buffer, MessageData->Length);
  204. if (Checksum != PacketHeader.Checksum) {
  205. goto SendResendPacket;
  206. }
  207. return(KDP_PACKET_RECEIVED);
  208. SendResendPacket:
  209. KdpSendControlPacket(PACKET_TYPE_KD_RESEND, 0L);
  210. goto WaitForPacketLeader;
  211. } // KdReceivePacket
  212. void
  213. KdSendPacket(
  214. IN ULONG PacketType,
  215. IN PSTRING MessageHeader,
  216. IN PSTRING MessageData OPTIONAL,
  217. IN OUT PKD_CONTEXT KdContext
  218. )
  219. /*++
  220. Routine Description:
  221. This routine sends a packet to the host machine that is running the
  222. kernel debugger and waits for an ACK.
  223. Arguments:
  224. PacketType - Supplies the type of packet to send.
  225. MessageHeader - Supplies a pointer to a string descriptor that describes
  226. the message information.
  227. MessageData - Supplies a pointer to a string descriptor that describes
  228. the optional message data.
  229. KdContext - Supplies a pointer to the kernel debugger context.
  230. Return Value:
  231. None.
  232. --*/
  233. {
  234. KD_PACKET PacketHeader;
  235. ULONG MessageDataLength;
  236. ULONG ReturnCode;
  237. PDBGKD_DEBUG_IO DebugIo;
  238. PDBGKD_WAIT_STATE_CHANGE64 StateChange;
  239. PDBGKD_FILE_IO FileIo;
  240. BOOLEAN bException = FALSE;
  241. PacketHeader.Checksum = 0;
  242. if (ARGUMENT_PRESENT(MessageData)) {
  243. MessageDataLength = MessageData->Length;
  244. PacketHeader.Checksum = KdpComputeChecksum(MessageData->Buffer, MessageData->Length);
  245. }
  246. else {
  247. MessageDataLength = 0;
  248. PacketHeader.Checksum = 0;
  249. }
  250. PacketHeader.Checksum += KdpComputeChecksum(MessageHeader->Buffer, MessageHeader->Length);
  251. //
  252. // Initialize and send the packet header.
  253. //
  254. PacketHeader.PacketLeader = PACKET_LEADER;
  255. PacketHeader.ByteCount = (USHORT)(MessageHeader->Length + MessageDataLength);
  256. PacketHeader.PacketType = (USHORT)PacketType;
  257. PacketHeader.PacketId = KdPacketId;
  258. KdPacketId++;
  259. KdCompNumberRetries = KdCompRetryCount;
  260. // setup our send packet
  261. RtlZeroMemory(&Kd1394Data->SendPacket, sizeof(DEBUG_1394_SEND_PACKET));
  262. Kd1394Data->SendPacket.Length = 0;
  263. // copy our packet header...
  264. RtlCopyMemory( &Kd1394Data->SendPacket.PacketHeader[0],
  265. &PacketHeader,
  266. sizeof(KD_PACKET)
  267. );
  268. // setup our message header
  269. if (MessageHeader) {
  270. RtlCopyMemory( &Kd1394Data->SendPacket.Packet[0],
  271. MessageHeader->Buffer,
  272. MessageHeader->Length
  273. );
  274. Kd1394Data->SendPacket.Length += MessageHeader->Length;
  275. }
  276. // setup our message data
  277. if (ARGUMENT_PRESENT(MessageData)) {
  278. RtlCopyMemory( &Kd1394Data->SendPacket.Packet[Kd1394Data->SendPacket.Length],
  279. MessageData->Buffer,
  280. MessageData->Length
  281. );
  282. Kd1394Data->SendPacket.Length += MessageData->Length;
  283. }
  284. Kd1394Data->SendPacket.TransferStatus = STATUS_PENDING;
  285. do {
  286. // make sure our link is enabled..
  287. Dbg1394_EnablePhysicalAccess(Kd1394Data);
  288. if (KdCompNumberRetries == 0) {
  289. //
  290. // If the packet is not for reporting exception, we give up
  291. // and declare debugger not present.
  292. //
  293. if (PacketType == PACKET_TYPE_KD_DEBUG_IO) {
  294. DebugIo = (PDBGKD_DEBUG_IO)MessageHeader->Buffer;
  295. if (DebugIo->ApiNumber == DbgKdPrintStringApi) {
  296. *KdDebuggerNotPresent = TRUE;
  297. SharedUserData->KdDebuggerEnabled &= ~0x00000002;
  298. Kd1394Data->SendPacket.TransferStatus = STATUS_SUCCESS;
  299. return;
  300. }
  301. }
  302. else if (PacketType == PACKET_TYPE_KD_STATE_CHANGE64) {
  303. StateChange = (PDBGKD_WAIT_STATE_CHANGE64)MessageHeader->Buffer;
  304. if (StateChange->NewState == DbgKdLoadSymbolsStateChange) {
  305. *KdDebuggerNotPresent = TRUE;
  306. SharedUserData->KdDebuggerEnabled &= ~0x00000002;
  307. Kd1394Data->SendPacket.TransferStatus = STATUS_SUCCESS;
  308. return;
  309. }
  310. }
  311. else if (PacketType == PACKET_TYPE_KD_FILE_IO) {
  312. FileIo = (PDBGKD_FILE_IO)MessageHeader->Buffer;
  313. if (FileIo->ApiNumber == DbgKdCreateFileApi) {
  314. *KdDebuggerNotPresent = TRUE;
  315. SharedUserData->KdDebuggerEnabled &= ~0x00000002;
  316. Kd1394Data->SendPacket.TransferStatus = STATUS_SUCCESS;
  317. return;
  318. }
  319. }
  320. else {
  321. bException = TRUE;
  322. }
  323. }
  324. ReturnCode = KDP_PACKET_TIMEOUT;
  325. {
  326. ULONG count = 0;
  327. volatile NTSTATUS *pStatus;
  328. pStatus = &Kd1394Data->ReceivePacket.TransferStatus;
  329. //
  330. // now sit here and poll for a response from the target machine
  331. //
  332. do {
  333. // make sure our link is enabled..
  334. Dbg1394_EnablePhysicalAccess(Kd1394Data);
  335. //
  336. // while in this loop check if the host layed in a request.
  337. // If they did, mark it read and double buffer it
  338. //
  339. count++;
  340. if (Kd1394Data->SendPacket.TransferStatus != STATUS_PENDING) {
  341. ReturnCode = KDP_PACKET_RECEIVED;
  342. break;
  343. }
  344. if ((*pStatus == STATUS_PENDING) && (!bException)) {
  345. ReturnCode = KDP_PACKET_RECEIVED;
  346. break;
  347. }
  348. } while (count < TIMEOUT_COUNT);
  349. }
  350. if (ReturnCode == KDP_PACKET_TIMEOUT) {
  351. KdCompNumberRetries--;
  352. }
  353. } while (ReturnCode != KDP_PACKET_RECEIVED);
  354. //
  355. // Since we are able to talk to debugger, the retrycount is set to
  356. // maximum value.
  357. //
  358. KdCompRetryCount = KdContext->KdpDefaultRetries;
  359. return;
  360. } // KdSendPacket