|
|
1.1 root 1: #include "givit.h"
2:
3:
4: extern HANDLE PipeRead; // see DbgKdpKbdPollThread
5: extern HANDLE PipeWrite;
6: extern ULONG NumberProcessors;
7: static USHORT LastProcessorToPrint = -1;
8:
9: UCHAR DbgKdpPacketLeader[4] = {
10: PACKET_LEADER_BYTE,
11: PACKET_LEADER_BYTE,
12: PACKET_LEADER_BYTE,
13: PACKET_LEADER_BYTE
14: };
15:
16: //
17: // DbgKdpCmdCanceled indicates the fact that the current kd command has
18: // been canceled by user (using ctrl-C.) With the Packet Id controlling
19: // the packet exchange, the Ctrl-C has to be handled in controlled manner.
20: // At each end of DbgKdpXXXX routine, we will check for this flag. If the
21: // command has been canceled, a longjmp will be performed to transfer control
22: // back to kd prompt.
23: //
24:
25: BOOLEAN DbgKdpCmdCanceled = FALSE;
26:
27: #ifdef DBG
28: BOOLEAN KdDebug = FALSE;
29: #endif
30:
31: BOOLEAN KdResync = FALSE;
32: UCHAR PrintBuf[PACKET_MAX_SIZE];
33:
34: #define CONTROL_B 2
35: #define CONTROL_D 4
36: #define CONTROL_R 18
37: #define CONTROL_V 22
38:
39: ULONG DbgKdpPacketExpected; // ID for expected incoming packet
40: ULONG DbgKdpNextPacketToSend; // ID for Next packet to send
41: extern VOID DbgKdpSynchronizeTarget ( VOID );
42:
43: //++
44: //
45: // VOID
46: // DbgKdpWaitPacketForever (
47: // IN ULONG PacketType,
48: // IN PVOID Buffer
49: // )
50: //
51: // Routine Description:
52: //
53: // This macro is invoked to wait for specifi type of message without
54: // timeout.
55: //
56: // Arguments:
57: //
58: // PacketType - Type of the message we are expecting.
59: //
60: // Buffer - Buffer to store the message.
61: //
62: // Return Value:
63: //
64: // None.
65: //
66: //--
67:
68: #define DbgKdpWaitPacketForever( PacketType, Buffer) { \
69: BOOLEAN rc; \
70: do { \
71: rc = DbgKdpWaitForPacket( \
72: PacketType, \
73: Buffer \
74: ); \
75: } while ( rc == FALSE); \
76: }
77:
78: DWORD
79: DbgKdConnectAndInitialize(
80: )
81: {
82:
83: DWORD BytesWritten;
84: BOOL rc;
85: USHORT Length;
86:
87: //
88: // Initialize comport, packet queue and start the packet receiving
89: // thread.
90: //
91:
92: DbgKdpInitComPort(0L);
93: DbgKdpPacketExpected = INITIAL_PACKET_ID;
94: DbgKdpNextPacketToSend = INITIAL_PACKET_ID;
95:
96: DbgKdpStartThreads();
97:
98: return ERROR_SUCCESS;
99: }
100:
101: VOID
102: DbgKdpHandlePromptString(
103: IN PDBGKD_DEBUG_IO IoMessage
104: )
105: {
106: PUCHAR IoData;
107: DWORD i;
108: DWORD j;
109: BOOL rc;
110: UCHAR c;
111: PUCHAR d;
112:
113: IoData = (PUCHAR)(IoMessage+1);
114:
115: DbgKdpPrint(IoMessage->Processor,
116: IoData,
117: (USHORT)IoMessage->u.GetString.LengthOfPromptString
118: );
119:
120: //
121: // read the prompt data
122: //
123:
124: j = 0;
125: d = IoData;
126: rc = DbgKdpGetConsoleByte(&c, 1, &i);
127:
128: while ( rc == TRUE &&
129: i == 1 &&
130: j < (USHORT)IoMessage->u.GetString.LengthOfStringRead) {
131:
132: if ( c == '\r' ) {
133: *d++ = '\0';
134: j++;
135: } else if ( c == '\n' ) {
136: *d++ = '\0';
137: j++;
138: break;
139: } else {
140: *d++ = c;
141: j++;
142: }
143: rc = DbgKdpGetConsoleByte(&c, 1, &i);
144: }
145:
146: LastProcessorToPrint = -1;
147: if ( j < (USHORT)IoMessage->u.GetString.LengthOfStringRead ) {
148: IoMessage->u.GetString.LengthOfStringRead = j;
149: }
150:
151: //
152: // Send data to the debugger-target
153: //
154:
155: DbgKdpWritePacket(
156: IoMessage,
157: sizeof(*IoMessage),
158: PACKET_TYPE_KD_DEBUG_IO,
159: IoData,
160: (USHORT)IoMessage->u.GetString.LengthOfStringRead
161: );
162: }
163:
164: VOID
165: DbgKdpPrint(
166: IN USHORT Processor,
167: IN PUCHAR String,
168: IN USHORT StringLength
169: )
170: {
171: DWORD i;
172: DWORD j;
173: UCHAR c;
174: PUCHAR d;
175: static USHORT LastProcessor = -1;
176:
177: assert(StringLength < PACKET_MAX_SIZE - 2);
178:
179: d = PrintBuf;
180: if (NumberProcessors > 1 && Processor != LastProcessorToPrint) {
181: assert(Processor < 8);
182: LastProcessorToPrint = Processor;
183: *d++ = (UCHAR)((UCHAR)Processor + '0');
184: *d++ = ':';
185: j = 2;
186: } else {
187: j = 0;
188: }
189: for(i=0;i<StringLength;i++) {
190: c = *(String+i);
191: if ( c == '\n' ) {
192: LastProcessorToPrint = -1;
193: *d++ = '\n';
194: *d++ = '\r';
195: j += 2;
196: } else {
197: if ( c ) {
198: *d++ = c;
199: j++;
200: }
201: }
202: }
203:
204: //
205: // print the string. someday this should probably
206: // be a callout.
207:
208: WriteFile(ConsoleOutputHandle,PrintBuf,j,&i,NULL);
209: }
210:
211: DWORD
212: DbgKdWaitStateChange(
213: OUT PDBGKD_WAIT_STATE_CHANGE StateChange,
214: OUT PVOID Buffer,
215: IN ULONG BufferLength
216: )
217:
218: /*++
219:
220: Routine Description:
221:
222: This function causes the calling user interface to wait for a state
223: change to occur in the system being debugged. Once a state change
224: occurs, the user interface can either continue the system using
225: DbgKdContinue, or it can manipulate system state using anyone of the
226: DbgKd state manipulation APIs.
227:
228: Arguments:
229:
230: StateChange - Supplies the address of state change record that
231: will contain the state change information.
232:
233: Buffer - Supplies the address of a buffer that returns additional
234: information.
235:
236: BufferLength - Supplies the length of Buffer.
237:
238: Return Value:
239:
240: ERROR_SUCCESS - A state change occured. Valid state change information
241: was returned.
242:
243: --*/
244:
245: {
246:
247: PDBGKD_WAIT_STATE_CHANGE LocalStateChange;
248: DWORD st;
249: UCHAR *pt;
250:
251: st = ERROR_INVALID_FUNCTION;
252: while ( st != ERROR_SUCCESS ) {
253:
254: //
255: // Waiting for a state change message. Copy the message to the callers
256: // buffer, and then free the packet entry.
257: //
258:
259: DbgKdpWaitPacketForever(
260: PACKET_TYPE_KD_STATE_CHANGE,
261: &LocalStateChange
262: );
263: LocalStateChange = (PDBGKD_WAIT_STATE_CHANGE)DbgKdpPacket;
264: st = ERROR_SUCCESS;
265: assert(StateChange);
266: *StateChange = *LocalStateChange;
267:
268: switch ( (USHORT) StateChange->NewState ) {
269: case DbgKdExceptionStateChange:
270: break;
271: case DbgKdLoadSymbolsStateChange:
272: if ( BufferLength < LocalStateChange->u.LoadSymbols.PathNameLength ) {
273: st = ERROR_MORE_DATA;
274: } else {
275: pt = ((UCHAR *) LocalStateChange) + PacketHeader.ByteCount -
276: (int)LocalStateChange->u.LoadSymbols.PathNameLength;
277: memcpy(Buffer, pt,
278: (int)LocalStateChange->u.LoadSymbols.PathNameLength);
279: }
280: break;
281: default:
282: assert(FALSE);
283: }
284: return st;
285: }
286: }
287:
288: DWORD
289: DbgKdContinue (
290: IN DWORD ContinueStatus
291: )
292:
293: /*++
294:
295: Routine Description:
296:
297: Continuing a system that previously reported a state change causes
298: the system to continue executiontion using the context in effect at
299: the time the state change was reported (of course this context could
300: have been modified using the DbgKd state manipulation APIs).
301:
302: Arguments:
303:
304: ContinueStatus - Supplies the continuation status to the thread
305: being continued. Valid values for this are
306: DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED
307: or DBG_CONTINUE.
308:
309: Return Value:
310:
311: ERROR_SUCCESS - Successful call to DbgUiContinue
312:
313: ERROR_INVALID_PARAMETER - An invalid continue status or was
314: specified.
315:
316: --*/
317:
318: {
319: DBGKD_MANIPULATE_STATE m;
320: PDBGKD_CONTINUE a = &m.u.Continue;
321: DWORD st;
322:
323: if ( ContinueStatus == DBG_EXCEPTION_HANDLED ||
324: ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
325: ContinueStatus == DBG_CONTINUE ) {
326:
327: m.ApiNumber = DbgKdContinueApi;
328: m.ReturnStatus = ContinueStatus;
329:
330: a->ContinueStatus = ContinueStatus;
331: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
332: st = ERROR_SUCCESS;
333: }
334: else {
335: st = ERROR_INVALID_PARAMETER;
336: }
337:
338: return st;
339: }
340:
341:
342: DWORD
343: DbgKdContinue2 (
344: IN DWORD ContinueStatus,
345: IN DBGKD_CONTROL_SET ControlSet
346: )
347:
348: /*++
349:
350: Routine Description:
351:
352: Continuing a system that previously reported a state change causes
353: the system to continue executiontion using the context in effect at
354: the time the state change was reported, modified by the values set
355: in the ControlSet structure. (And, of course, the context could have
356: been modified by used the DbgKd state manipulation APIs.)
357:
358: Arguments:
359:
360: ContinueStatus - Supplies the continuation status to the thread
361: being continued. Valid values for this are
362: DBG_EXCEPTION_HANDLED, DBG_EXCEPTION_NOT_HANDLED
363: or DBG_CONTINUE.
364:
365: ControlSet - Supplies a pointer to a structure containing the machine
366: specific control data to set. For the x86 this is the TraceFlag
367: and Dr7.
368:
369: Return Value:
370:
371: ERROR_SUCCESS - Successful call to DbgUiContinue
372:
373: ERROR_INVALID_PARAMETER - An invalid continue status or was
374: specified.
375:
376: --*/
377:
378: {
379: DBGKD_MANIPULATE_STATE m;
380: DWORD st;
381:
382: if ( ContinueStatus == DBG_EXCEPTION_HANDLED ||
383: ContinueStatus == DBG_EXCEPTION_NOT_HANDLED ||
384: ContinueStatus == DBG_CONTINUE ) {
385:
386: m.ApiNumber = DbgKdContinueApi2;
387: m.ReturnStatus = ContinueStatus;
388:
389: m.u.Continue2.ContinueStatus = ContinueStatus;
390: m.u.Continue2.ControlSet = ControlSet;
391:
392: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
393: st = ERROR_SUCCESS;
394:
395: } else {
396: st = ERROR_INVALID_PARAMETER;
397: }
398:
399: return st;
400: }
401:
402: DWORD
403: DbgKdReadVirtualMemory(
404: IN PVOID TargetBaseAddress,
405: OUT PVOID UserInterfaceBuffer,
406: IN ULONG TransferCount,
407: OUT PULONG ActualBytesRead OPTIONAL
408: )
409:
410: /*++
411:
412: Routine Description:
413:
414: This function reads the specified data from the system being debugged
415: using the current mapping of the processor.
416:
417: Arguments:
418:
419: TargetBaseAddress - Supplies the base address of the memory to read
420: from the system being debugged. The virtual address is in terms
421: of the current mapping for the processor that reported the last
422: state change. Until we figure out how to do this differently,
423: the virtual address must refer to a valid page (although it does
424: not necesserily have to be in the TB).
425:
426: UserInterfaceBuffer - Supplies the address of the buffer in the user
427: interface that data read is to be placed.
428:
429: TransferCount - Specifies the number of bytes to read.
430:
431: ActualBytesRead - An optional parameter that if supplied, returns
432: the number of bytes actually read.
433:
434: Return Value:
435:
436: ERROR_SUCCESS - The specified read occured.
437:
438: ERROR_MORE_DATA - A read that is to large was specified.
439:
440: ERROR_NO_ACCESS - The TargetBaseAddress/TransferCount
441: parameters refers to invalid virtual memory.
442:
443: !ERROR_SUCCESS - TBD
444:
445: --*/
446:
447: {
448: DBGKD_MANIPULATE_STATE m;
449: PDBGKD_MANIPULATE_STATE Reply;
450: PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
451: DWORD st;
452: BOOLEAN rc;
453:
454: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
455: return ERROR_MORE_DATA;
456: }
457:
458: //
459: // Format state manipulate message
460: //
461:
462: m.ApiNumber = DbgKdReadVirtualMemoryApi;
463: m.ReturnStatus = STATUS_PENDING;
464: a->TargetBaseAddress = TargetBaseAddress;
465: a->TransferCount = TransferCount;
466: a->ActualBytesRead = 0L;
467:
468: //
469: // Send the message and then wait for reply
470: //
471:
472: do {
473: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
474:
475: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
476: &Reply
477: );
478: } while (rc == FALSE);
479:
480: //
481: // If this is not a ReadMemory response than protocol is screwed up.
482: // assert that protocol is ok.
483: //
484:
485: st = Reply->ReturnStatus;
486: assert(Reply->ApiNumber == DbgKdReadVirtualMemoryApi);
487:
488: //
489: // Reset message address to reply.
490: //
491:
492: a = &Reply->u.ReadMemory;
493: assert(a->ActualBytesRead <= TransferCount);
494:
495: //
496: // Return actual bytes read, and then transfer the bytes
497: //
498:
499: if (ActualBytesRead) {
500: *ActualBytesRead = a->ActualBytesRead;
501: }
502: st = Reply->ReturnStatus;
503:
504: //
505: // Since read response data follows message, Reply+1 should point
506: // at the data
507: //
508:
509: memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead);
510:
511: return st;
512: }
513:
514:
515:
516: DWORD
517: DbgKdWriteVirtualMemory(
518: IN PVOID TargetBaseAddress,
519: OUT PVOID UserInterfaceBuffer,
520: IN ULONG TransferCount,
521: OUT PULONG ActualBytesWritten OPTIONAL
522: )
523:
524: /*++
525:
526: Routine Description:
527:
528: This function writes the specified data to the system being debugged
529: using the current mapping of the processor.
530:
531: Arguments:
532:
533: TargetBaseAddress - Supplies the base address of the memory to be written
534: into the system being debugged. The virtual address is in terms
535: of the current mapping for the processor that reported the last
536: state change. Until we figure out how to do this differently,
537: the virtual address must refer to a valid page (although it does
538: not necesserily have to be in the TB).
539:
540: UserInterfaceBuffer - Supplies the address of the buffer in the user
541: interface that contains the data to be written.
542:
543: TransferCount - Specifies the number of bytes to write.
544:
545: ActualBytesWritten - An optional parameter that if supplied, returns
546: the number of bytes actually written.
547:
548: Return Value:
549:
550: ERROR_SUCCESS - The specified read occured.
551:
552: ERROR_MORE_DATA - A read that is to large was specified.
553:
554: ERROR_NO_ACCESS - The TargetBaseAddress/TransferCount
555: parameters refers to invalid virtual memory.
556:
557: !ERROR_SUCCESS - TBD
558:
559: --*/
560:
561: {
562: DBGKD_MANIPULATE_STATE m;
563: PDBGKD_MANIPULATE_STATE Reply;
564: PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
565: DWORD st;
566: BOOLEAN rc;
567:
568: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
569: return ERROR_MORE_DATA;
570: }
571:
572: //
573: // Format state manipulate message
574: //
575:
576: m.ApiNumber = DbgKdWriteVirtualMemoryApi;
577: m.ReturnStatus = STATUS_PENDING;
578: a->TargetBaseAddress = TargetBaseAddress;
579: a->TransferCount = TransferCount;
580: a->ActualBytesWritten = 0L;
581:
582: //
583: // Send the message and data to write and then wait for reply
584: //
585:
586: do {
587: DbgKdpWritePacket(
588: &m,
589: sizeof(m),
590: PACKET_TYPE_KD_STATE_MANIPULATE,
591: UserInterfaceBuffer,
592: (USHORT)TransferCount
593: );
594: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
595: &Reply
596: );
597: } while (rc == FALSE);
598:
599: //
600: // If this is not a WriteMemory response than protocol is screwed up.
601: // assert that protocol is ok.
602: //
603:
604: st = Reply->ReturnStatus;
605: assert(Reply->ApiNumber == DbgKdWriteVirtualMemoryApi);
606:
607: //
608: // Reset message address to reply.
609: //
610:
611: a = &Reply->u.WriteMemory;
612: assert(a->ActualBytesWritten <= TransferCount);
613:
614: //
615: // Return actual bytes written
616: //
617:
618: if (ActualBytesWritten) {
619: *ActualBytesWritten = a->ActualBytesWritten;
620: }
621: st = Reply->ReturnStatus;
622:
623: return st;
624: }
625:
626: DWORD
627: DbgKdReadControlSpace(
628: IN USHORT Processor,
629: IN PVOID TargetBaseAddress,
630: OUT PVOID UserInterfaceBuffer,
631: IN ULONG TransferCount,
632: OUT PULONG ActualBytesRead OPTIONAL
633: )
634:
635: /*++
636:
637: Routine Description:
638:
639: This function reads the specified data from the control space of
640: the system being debugged.
641:
642: Control space is processor dependent. TargetBaseAddress is mapped
643: to control space in a processor/implementation defined manner.
644:
645: Arguments:
646:
647: Processor - Supplies the processor whoes control space is desired.
648:
649: TargetBaseAddress - Supplies the base address in control space to
650: read. This address is interpreted in an implementation defined
651: manner.
652:
653:
654: On x86, control space is a per-processor area which contains:
655:
656: Current Context (CONTEXT)
657: Special Registers (KSPECIAL_REGISTERS)
658:
659: This means that to read the special registers:
660:
661: DbgKdReadControlSpace(
662: NtsdCurrentProcessor,
663: (PVOID)sizeof(CONTEXT),
664: (PVOID)&SpecialRegContext,
665: sizeof(KSPECIAL_REGISTERS),
666: &cBytesRead
667: );
668:
669: The above will read the special registers of the current processor
670: since the control space address is sizeof(CONTEXT)
671:
672: On MIPS, control space addresses are used to address the translation
673: buffer.
674:
675: UserInterfaceBuffer - Supplies the address of the buffer in the user
676: interface that data read is to be placed.
677:
678: TransferCount - Specifies the number of bytes to read.
679:
680: ActualBytesRead - An optional parameter that if supplied, returns
681: the number of bytes actually read.
682:
683: Return Value:
684:
685: ERROR_SUCCESS - The specified read occured.
686:
687: ERROR_MORE_DATA - A read that is to large was specified.
688:
689: !ERROR_SUCCESS - TBD
690:
691: --*/
692:
693: {
694: DBGKD_MANIPULATE_STATE m;
695: PDBGKD_MANIPULATE_STATE Reply;
696: PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
697: DWORD st;
698: BOOLEAN rc;
699:
700: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
701: return ERROR_MORE_DATA;
702: }
703:
704: //
705: // Format state manipulate message
706: //
707:
708: m.ApiNumber = DbgKdReadControlSpaceApi;
709: m.ReturnStatus = STATUS_PENDING;
710: m.Processor = Processor;
711: a->TargetBaseAddress = TargetBaseAddress;
712: a->TransferCount = TransferCount;
713: a->ActualBytesRead = 0L;
714:
715: //
716: // Send the message and then wait for reply
717: //
718:
719: do {
720: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
721:
722: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
723:
724: } while (rc == FALSE);
725:
726: //
727: // If this is not a ReadControl response than protocol is screwed up.
728: // assert that protocol is ok.
729: //
730:
731: st = Reply->ReturnStatus;
732: assert(Reply->ApiNumber == DbgKdReadControlSpaceApi);
733:
734: //
735: // Reset message address to reply.
736: //
737:
738: a = &Reply->u.ReadMemory;
739: assert(a->ActualBytesRead <= TransferCount);
740:
741: //
742: // Return actual bytes read, and then transfer the bytes
743: //
744:
745: if (ActualBytesRead) {
746: *ActualBytesRead = a->ActualBytesRead;
747: }
748: st = Reply->ReturnStatus;
749:
750: //
751: // Since read response data follows message, Reply+1 should point
752: // at the data
753: //
754:
755: memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead);
756:
757: return st;
758: }
759:
760:
761:
762: DWORD
763: DbgKdWriteControlSpace(
764: IN USHORT Processor,
765: IN PVOID TargetBaseAddress,
766: OUT PVOID UserInterfaceBuffer,
767: IN ULONG TransferCount,
768: OUT PULONG ActualBytesWritten OPTIONAL
769: )
770:
771: /*++
772:
773: Routine Description:
774:
775: This function writes the specified data to control space on the system
776: being debugged.
777:
778: Control space is processor dependent. TargetBaseAddress is mapped
779: to control space in a processor/implementation defined manner.
780:
781: Arguments:
782:
783: Processor - Supplies the processor whoes control space is desired.
784:
785: TargetBaseAddress - Supplies the base address in control space to be
786: written.
787:
788: UserInterfaceBuffer - Supplies the address of the buffer in the user
789: interface that contains the data to be written.
790:
791: TransferCount - Specifies the number of bytes to write.
792:
793: ActualBytesWritten - An optional parameter that if supplied, returns
794: the number of bytes actually written.
795:
796: Return Value:
797:
798: ERROR_SUCCESS - The specified read occured.
799:
800: ERROR_MORE_DATA - A read that is to large was specified.
801:
802: !ERROR_SUCCESS - TBD
803:
804: --*/
805:
806: {
807: DBGKD_MANIPULATE_STATE m;
808: PDBGKD_MANIPULATE_STATE Reply;
809: PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
810: DWORD st;
811: BOOLEAN rc;
812:
813: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
814: return ERROR_MORE_DATA;
815: }
816:
817: //
818: // Format state manipulate message
819: //
820:
821: m.ApiNumber = DbgKdWriteControlSpaceApi;
822: m.ReturnStatus = STATUS_PENDING;
823: m.Processor = Processor;
824: a->TargetBaseAddress = TargetBaseAddress;
825: a->TransferCount = TransferCount;
826: a->ActualBytesWritten = 0L;
827:
828: //
829: // Send the message and data to write and then wait for reply
830: //
831:
832: do {
833: DbgKdpWritePacket(
834: &m,
835: sizeof(m),
836: PACKET_TYPE_KD_STATE_MANIPULATE,
837: UserInterfaceBuffer,
838: (USHORT)TransferCount
839: );
840:
841: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
842: } while (rc == FALSE);
843:
844: //
845: // If this is not a WriteControl response than protocol is screwed up.
846: // assert that protocol is ok.
847: //
848:
849: st = Reply->ReturnStatus;
850: assert(Reply->ApiNumber == DbgKdWriteControlSpaceApi);
851:
852: //
853: // Reset message address to reply.
854: //
855:
856: a = &Reply->u.WriteMemory;
857: assert(a->ActualBytesWritten <= TransferCount);
858:
859: //
860: // Return actual bytes written
861: //
862:
863: *ActualBytesWritten = a->ActualBytesWritten;
864: st = Reply->ReturnStatus;
865:
866: return st;
867: }
868:
869:
870: DWORD
871: DbgKdGetContext(
872: IN USHORT Processor,
873: IN OUT PCONTEXT Context
874: )
875:
876: /*++
877:
878: Routine Description:
879:
880: This function reads the context from the system being debugged.
881: The ContextFlags field determines how much context is read.
882:
883: Arguments:
884:
885: Processor - Supplies a processor number to get context from.
886:
887: Context - On input, the ContextFlags field controls what portions of
888: the context record the caller as interested in reading. On
889: output, the context record returns the current context for the
890: processor that reported the last state change.
891:
892: Return Value:
893:
894: ERROR_SUCCESS - The specified get context occured.
895:
896: !ERROR_SUCCESS - TBD
897:
898: --*/
899:
900: {
901: DBGKD_MANIPULATE_STATE m;
902: PDBGKD_MANIPULATE_STATE Reply;
903: PDBGKD_GET_CONTEXT a = &m.u.GetContext;
904: DWORD st;
905: BOOLEAN rc;
906:
907: //
908: // Format state manipulate message
909: //
910:
911: m.ApiNumber = DbgKdGetContextApi;
912: m.ReturnStatus = STATUS_PENDING;
913: m.Processor = Processor;
914: a->ContextFlags = Context->ContextFlags;
915:
916: //
917: // Send the message and then wait for reply
918: //
919:
920: do {
921: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
922: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
923: } while (rc == FALSE);
924:
925: //
926: // If this is not a GetContext response than protocol is screwed up.
927: // assert that protocol is ok.
928: //
929:
930: st = Reply->ReturnStatus;
931: assert(Reply->ApiNumber == DbgKdGetContextApi);
932:
933: //
934: // Reset message address to reply.
935: //
936:
937: a = &Reply->u.GetContext;
938: st = Reply->ReturnStatus;
939:
940: //
941: // Since get context response data follows message, Reply+1 should point
942: // at the data
943: //
944:
945: memcpy(Context, Reply+1, sizeof(*Context));
946:
947: return st;
948: }
949:
950:
951:
952: DWORD
953: DbgKdSetContext(
954: IN USHORT Processor,
955: IN PCONTEXT Context
956: )
957:
958: /*++
959:
960: Routine Description:
961:
962: This function writes the specified context to the system being debugged.
963:
964: Arguments:
965:
966: Processor - Supplies a processor number to set the context to.
967:
968: Context - Supplies a context record used to set the context for the
969: processor that reported the last state change. Only the
970: portions of the context indicated by the ContextFlags field are
971: actually written.
972:
973:
974: Return Value:
975:
976: ERROR_SUCCESS - The specified set context occured.
977:
978: !ERROR_SUCCESS - TBD
979:
980: --*/
981:
982: {
983: DBGKD_MANIPULATE_STATE m;
984: PDBGKD_MANIPULATE_STATE Reply;
985: PDBGKD_SET_CONTEXT a = &m.u.SetContext;
986: DWORD st;
987: BOOLEAN rc;
988:
989: //
990: // Format state manipulate message
991: //
992:
993: m.ApiNumber = DbgKdSetContextApi;
994: m.ReturnStatus = STATUS_PENDING;
995: m.Processor = Processor;
996: a->ContextFlags = Context->ContextFlags;
997:
998: //
999: // Send the message and context and then wait for reply
1000: //
1001:
1002: do {
1003: DbgKdpWritePacket(
1004: &m,
1005: sizeof(m),
1006: PACKET_TYPE_KD_STATE_MANIPULATE,
1007: Context,
1008: sizeof(*Context)
1009: );
1010: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
1011: } while (rc == FALSE);
1012:
1013: //
1014: // If this is not a SetContext response than protocol is screwed up.
1015: // assert that protocol is ok.
1016: //
1017:
1018: st = Reply->ReturnStatus;
1019: assert(Reply->ApiNumber == DbgKdSetContextApi);
1020:
1021: //
1022: // Reset message address to reply.
1023: //
1024:
1025: a = &Reply->u.SetContext;
1026: st = Reply->ReturnStatus;
1027:
1028: return st;
1029: }
1030:
1031: DWORD
1032: DbgKdWriteBreakPoint(
1033: IN PVOID BreakPointAddress,
1034: OUT PULONG BreakPointHandle
1035: )
1036:
1037: /*++
1038:
1039: Routine Description:
1040:
1041: This function is used to write a breakpoint at the address specified.
1042:
1043:
1044: Arguments:
1045:
1046: BreakPointAddress - Supplies the address that a breakpoint
1047: instruction is to be written. This address is interpreted using
1048: the current mapping on the processor reporting the previous
1049: state change. If the address refers to a page that is not
1050: valid, the the breakpoint is remembered by the system. As each
1051: page is made valid, the system will check for pending
1052: breakpoints and install breakpoints as necessary.
1053:
1054: BreakPointHandle - Returns a handle to a breakpoint. This handle
1055: may be used in a subsequent call to DbgKdRestoreBreakPoint.
1056:
1057: Return Value:
1058:
1059: ERROR_SUCCESS - The specified breakpoint write occured.
1060:
1061: !ERROR_SUCCESS - TBD
1062:
1063:
1064: --*/
1065:
1066: {
1067:
1068: DBGKD_MANIPULATE_STATE m;
1069: PDBGKD_MANIPULATE_STATE Reply;
1070: PDBGKD_WRITE_BREAKPOINT a = &m.u.WriteBreakPoint;
1071: DWORD st;
1072: BOOLEAN rc;
1073:
1074: //
1075: // Format state manipulate message
1076: //
1077:
1078: m.ApiNumber = DbgKdWriteBreakPointApi;
1079: m.ReturnStatus = STATUS_PENDING;
1080: a->BreakPointAddress = BreakPointAddress;
1081:
1082: //
1083: // Send the message and context and then wait for reply
1084: //
1085:
1086: do {
1087: DbgKdpWritePacket(
1088: &m,
1089: sizeof(m),
1090: PACKET_TYPE_KD_STATE_MANIPULATE,
1091: NULL,
1092: 0
1093: );
1094:
1095: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
1096: } while (rc == FALSE);
1097:
1098: //
1099: // If this is not a WriteBreakPoint response than protocol is screwed up.
1100: // assert that protocol is ok.
1101: //
1102:
1103: st = Reply->ReturnStatus;
1104: assert(Reply->ApiNumber == DbgKdWriteBreakPointApi);
1105:
1106: //
1107: // Reset message address to reply.
1108: //
1109:
1110: a = &Reply->u.WriteBreakPoint;
1111: st = Reply->ReturnStatus;
1112: *BreakPointHandle = a->BreakPointHandle;
1113:
1114: return st;
1115: }
1116:
1117: DWORD
1118: DbgKdRestoreBreakPoint(
1119: IN ULONG BreakPointHandle
1120: )
1121:
1122: /*++
1123:
1124: Routine Description:
1125:
1126: This function is used to restore a breakpoint to its original
1127: value.
1128:
1129: Arguments:
1130:
1131: BreakPointHandle - Supplies a handle returned by
1132: DbgKdWriteBreakPoint. This handle must refer to a valid
1133: address. The contents of the address must also be a breakpoint
1134: instruction. If both of these are true, then the original value
1135: at the breakpoint address is restored.
1136:
1137: Return Value:
1138:
1139: ERROR_SUCCESS - The specified breakpoint restore occured.
1140:
1141: !ERROR_SUCCESS - TBD
1142:
1143: --*/
1144:
1145: {
1146:
1147: DBGKD_MANIPULATE_STATE m;
1148: PDBGKD_MANIPULATE_STATE Reply;
1149: PDBGKD_RESTORE_BREAKPOINT a = &m.u.RestoreBreakPoint;
1150: DWORD st;
1151: BOOLEAN rc;
1152:
1153: //
1154: // Format state manipulate message
1155: //
1156:
1157: m.ApiNumber = DbgKdRestoreBreakPointApi;
1158: m.ReturnStatus = STATUS_PENDING;
1159: a->BreakPointHandle = BreakPointHandle;
1160:
1161: //
1162: // Send the message and context and then wait for reply
1163: //
1164:
1165: do {
1166: DbgKdpWritePacket(
1167: &m,
1168: sizeof(m),
1169: PACKET_TYPE_KD_STATE_MANIPULATE,
1170: NULL,
1171: 0
1172: );
1173:
1174: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
1175: } while (rc == FALSE);
1176:
1177: //
1178: // If this is not a RestoreBreakPoint response than protocol is screwed up.
1179: // assert that protocol is ok.
1180: //
1181:
1182: st = Reply->ReturnStatus;
1183: assert(Reply->ApiNumber == DbgKdRestoreBreakPointApi);
1184:
1185: //
1186: // Reset message address to reply.
1187: //
1188:
1189: a = &Reply->u.RestoreBreakPoint;
1190: st = Reply->ReturnStatus;
1191:
1192: //
1193: // free the packet
1194: //
1195:
1196: return st;
1197: }
1198:
1199: DWORD
1200: DbgKdReadIoSpace(
1201: IN PVOID IoAddress,
1202: OUT PVOID ReturnedData,
1203: IN ULONG DataSize
1204: )
1205:
1206: /*++
1207:
1208: Routine Description:
1209:
1210: This function is used read a byte, short, or long (1,2,4 bytes) from
1211: the specified I/O address.
1212:
1213: Arguments:
1214:
1215: IoAddress - Supplies the Io address to read from.
1216:
1217: ReturnedData - Supplies the value read from the I/O address.
1218:
1219: DataSize - Supplies the size in bytes to read. Values of 1, 2, or
1220: 4 are accepted.
1221:
1222: Return Value:
1223:
1224: ERROR_SUCCESS - Data was successfully read from the I/O
1225: address.
1226:
1227: ERROR_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
1228: specified.
1229:
1230: !ERROR_SUCCESS - TBD
1231:
1232: --*/
1233:
1234: {
1235:
1236: DBGKD_MANIPULATE_STATE m;
1237: PDBGKD_MANIPULATE_STATE Reply;
1238: PDBGKD_READ_WRITE_IO a = &m.u.ReadWriteIo;
1239: DWORD st;
1240: BOOLEAN rc;
1241:
1242: switch ( DataSize ) {
1243: case 1:
1244: case 2:
1245: case 4:
1246: break;
1247: default:
1248: return ERROR_INVALID_PARAMETER;
1249: }
1250:
1251: //
1252: // Format state manipulate message
1253: //
1254:
1255: m.ApiNumber = DbgKdReadIoSpaceApi;
1256: m.ReturnStatus = STATUS_PENDING;
1257:
1258: a->DataSize = DataSize;
1259: a->IoAddress = IoAddress;
1260:
1261: //
1262: // Send the message and then wait for reply
1263: //
1264:
1265: do {
1266: DbgKdpWritePacket(
1267: &m,
1268: sizeof(m),
1269: PACKET_TYPE_KD_STATE_MANIPULATE,
1270: NULL,
1271: 0
1272: );
1273:
1274: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
1275: } while (rc == FALSE);
1276:
1277: //
1278: // If this is not a ReadIo response than protocol is screwed up.
1279: // assert that protocol is ok.
1280: //
1281:
1282: st = Reply->ReturnStatus;
1283: assert(Reply->ApiNumber == DbgKdReadIoSpaceApi);
1284:
1285: //
1286: // Reset message address to reply.
1287: //
1288:
1289: a = &Reply->u.ReadWriteIo;
1290: st = Reply->ReturnStatus;
1291:
1292: switch ( DataSize ) {
1293: case 1:
1294: *(PUCHAR)ReturnedData = (UCHAR)a->DataValue;
1295: break;
1296: case 2:
1297: *(PUSHORT)ReturnedData = (USHORT)a->DataValue;
1298: break;
1299: case 4:
1300: *(PULONG)ReturnedData = a->DataValue;
1301: break;
1302: }
1303:
1304: return st;
1305: }
1306:
1307: DWORD
1308: DbgKdWriteIoSpace(
1309: IN PVOID IoAddress,
1310: IN ULONG DataValue,
1311: IN ULONG DataSize
1312: )
1313:
1314: /*++
1315:
1316: Routine Description:
1317:
1318: This function is used write a byte, short, or long (1,2,4 bytes) to
1319: the specified I/O address.
1320:
1321: Arguments:
1322:
1323: IoAddress - Supplies the Io address to write to.
1324:
1325: DataValue - Supplies the value to write to the I/O address.
1326:
1327: DataSize - Supplies the size in bytes to write. Values of 1, 2, or
1328: 4 are accepted.
1329:
1330: Return Value:
1331:
1332: ERROR_SUCCESS - Data was successfully written to the I/O
1333: address.
1334:
1335: ERROR_INVALID_PARAMETER - A DataSize value other than 1,2, or 4 was
1336: specified.
1337:
1338: !ERROR_SUCCESS - TBD
1339:
1340: --*/
1341:
1342: {
1343:
1344: DBGKD_MANIPULATE_STATE m;
1345: PDBGKD_MANIPULATE_STATE Reply;
1346: PDBGKD_READ_WRITE_IO a = &m.u.ReadWriteIo;
1347: DWORD st;
1348: BOOLEAN rc;
1349:
1350: switch ( DataSize ) {
1351: case 1:
1352: case 2:
1353: case 4:
1354: break;
1355: default:
1356: return ERROR_INVALID_PARAMETER;
1357: }
1358:
1359: //
1360: // Format state manipulate message
1361: //
1362:
1363: m.ApiNumber = DbgKdWriteIoSpaceApi;
1364: m.ReturnStatus = STATUS_PENDING;
1365:
1366: a->DataSize = DataSize;
1367: a->IoAddress = IoAddress;
1368: a->DataValue = DataValue;
1369:
1370: //
1371: // Send the message and then wait for reply
1372: //
1373:
1374: do {
1375: DbgKdpWritePacket(
1376: &m,
1377: sizeof(m),
1378: PACKET_TYPE_KD_STATE_MANIPULATE,
1379: NULL,
1380: 0
1381: );
1382:
1383: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
1384: } while (rc == FALSE);
1385:
1386: //
1387: // If this is not a WriteIo response than protocol is screwed up.
1388: // assert that protocol is ok.
1389: //
1390:
1391: st = Reply->ReturnStatus;
1392: assert(Reply->ApiNumber == DbgKdWriteIoSpaceApi);
1393:
1394: //
1395: // Reset message address to reply.
1396: //
1397:
1398: a = &Reply->u.ReadWriteIo;
1399: st = Reply->ReturnStatus;
1400:
1401: //
1402: // free the packet
1403: //
1404:
1405: return st;
1406: }
1407:
1408:
1409: VOID far
1410: DbgKdpKbdPollThread(VOID)
1411: {
1412: HANDLE StandardInputHandle;
1413: DWORD i;
1414: BOOLEAN rc;
1415: UCHAR c;
1416:
1417: //
1418: // Capture all typed input immediately so that control-c,
1419: // control-break, etc, get processed in a timely fashion.
1420: // Stuff the characters into an anonymous pipe, from which
1421: // DbgKdpGetConsole byte will read them.
1422: //
1423: // (WHAT??? A PIPE??? Very very simple way to get data flow
1424: // between two threads correctly synchronized, folks.)
1425: //
1426:
1427: StandardInputHandle = GetStdHandle(STD_INPUT_HANDLE);
1428:
1429: while (TRUE) {
1430: rc = ReadFile(StandardInputHandle,&c,1,&i,NULL);
1431: if ((rc != TRUE) || (i != 1)) {
1432: continue;
1433: }
1434: if (c == CONTROL_B) {
1435: exit(0);
1436: } else if (c == CONTROL_D) {
1437: chLastCommand[0] = '\0';
1438: if (KdDebug) {
1439: KdDebug = FALSE;
1440: } else {
1441: KdDebug = TRUE;
1442: }
1443: continue;
1444: } else if (c == CONTROL_R) {
1445: KdResync = TRUE;
1446: chLastCommand[0] = '\0';
1447: continue;
1448: }
1449: rc = WriteFile(PipeWrite, &c, 1, &i, NULL);
1450: if ((rc != TRUE) || (i != 1)) {
1451: continue;
1452: }
1453: // FlushFileBuffers(PipeWrite);
1454: }
1455: }
1456:
1457: BOOL
1458: DbgKdpGetConsoleByte(
1459: PVOID pBuf,
1460: DWORD cbBuf,
1461: LPDWORD pcbBytesRead
1462: )
1463: {
1464: return ReadFile(PipeRead,pBuf,cbBuf,pcbBytesRead,NULL);
1465: }
1466:
1467: PUCHAR
1468: DbgKdGets(
1469: PUCHAR Buffer,
1470: USHORT Length
1471: )
1472: {
1473: DWORD i;
1474: BOOLEAN rc;
1475: USHORT j;
1476: UCHAR c;
1477:
1478: for (j = 0; (j+1) < Length; j++) {
1479:
1480: rc = DbgKdpGetConsoleByte(&c, 1, &i);
1481:
1482: if ((rc != TRUE) || (i != 1)) {
1483: }
1484:
1485: if (c == '\n') {
1486: Buffer[j] = '\n';
1487: Buffer[j+1] = '\0';
1488: return Buffer;
1489: }
1490:
1491: Buffer[j] = c;
1492:
1493: }
1494: Buffer[j-1] = '\0';
1495: return Buffer;
1496: }
1497:
1498:
1499:
1500: DWORD
1501: DbgKdReboot(
1502: VOID
1503: )
1504:
1505: /*++
1506:
1507: Routine Description:
1508:
1509: This function reboots being debugged.
1510:
1511: Arguments:
1512:
1513: None.
1514:
1515: Return Value:
1516:
1517: None.
1518:
1519: --*/
1520:
1521: {
1522: DBGKD_MANIPULATE_STATE m;
1523:
1524: //
1525: // Format state manipulate message
1526: //
1527:
1528: m.ApiNumber = DbgKdRebootApi;
1529: m.ReturnStatus = STATUS_PENDING;
1530:
1531: //
1532: // Send the message.
1533: //
1534:
1535: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
1536:
1537: return ERROR_SUCCESS;
1538: }
1539:
1540:
1541: DWORD
1542: DbgKdReadPhysicalMemory(
1543: IN PHYSICAL_ADDRESS TargetBaseAddress,
1544: OUT PVOID UserInterfaceBuffer,
1545: IN ULONG TransferCount,
1546: OUT PULONG ActualBytesRead OPTIONAL
1547: )
1548:
1549: /*++
1550:
1551: Routine Description:
1552:
1553: This function reads the specified data from the physical memory of
1554: the system being debugged.
1555:
1556: Arguments:
1557:
1558: TargetBaseAddress - Supplies the physical address of the memory to read
1559: from the system being debugged.
1560:
1561: UserInterfaceBuffer - Supplies the address of the buffer in the user
1562: interface that data read is to be placed.
1563:
1564: TransferCount - Specifies the number of bytes to read.
1565:
1566: ActualBytesRead - An optional parameter that if supplied, returns
1567: the number of bytes actually read.
1568:
1569: Return Value:
1570:
1571: ERROR_SUCCESS - The specified read occured.
1572:
1573: ERROR_MORE_DATA - A read that is too large was specified.
1574:
1575: ERROR_NO_ACCESS - TBD // Can you even HAVE an access
1576: // violation with a physical
1577: // memory access??
1578:
1579: !ERROR_SUCCESS - TBD
1580:
1581: --*/
1582:
1583: {
1584: DBGKD_MANIPULATE_STATE m;
1585: PDBGKD_MANIPULATE_STATE Reply;
1586: PDBGKD_READ_MEMORY a = &m.u.ReadMemory;
1587: DWORD st;
1588: BOOLEAN rc;
1589:
1590: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
1591: return ERROR_MORE_DATA;
1592: }
1593:
1594: //
1595: // Format state manipulate message
1596: //
1597:
1598: m.ApiNumber = DbgKdReadPhysicalMemoryApi;
1599: m.ReturnStatus = STATUS_PENDING;
1600: //
1601: // BUGBUG TargetBaseAddress should be >32 bits
1602: //
1603: a->TargetBaseAddress = (PVOID)TargetBaseAddress.LowPart;
1604: a->TransferCount = TransferCount;
1605: a->ActualBytesRead = 0L;
1606:
1607: //
1608: // Send the message and then wait for reply
1609: //
1610:
1611: do {
1612: DbgKdpWritePacket(&m,sizeof(m),PACKET_TYPE_KD_STATE_MANIPULATE,NULL,0);
1613:
1614: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
1615: } while (rc == FALSE);
1616:
1617: //
1618: // If this is not a ReadMemory response then protocol is screwed up.
1619: // assert that protocol is ok.
1620: //
1621:
1622: st = Reply->ReturnStatus;
1623: assert(Reply->ApiNumber == DbgKdReadPhysicalMemoryApi);
1624:
1625: //
1626: // Reset message address to reply.
1627: //
1628:
1629: a = &Reply->u.ReadMemory;
1630: assert(a->ActualBytesRead <= TransferCount);
1631:
1632: //
1633: // Return actual bytes read, and then transfer the bytes
1634: //
1635:
1636: if (ActualBytesRead) {
1637: *ActualBytesRead = a->ActualBytesRead;
1638: }
1639: st = Reply->ReturnStatus;
1640:
1641: //
1642: // Since read response data follows message, Reply+1 should point
1643: // at the data
1644: //
1645:
1646: memcpy(UserInterfaceBuffer, Reply+1, (int)a->ActualBytesRead);
1647:
1648: return st;
1649: }
1650:
1651:
1652: DWORD
1653: DbgKdWritePhysicalMemory(
1654: IN PHYSICAL_ADDRESS TargetBaseAddress,
1655: OUT PVOID UserInterfaceBuffer,
1656: IN ULONG TransferCount,
1657: OUT PULONG ActualBytesWritten OPTIONAL
1658: )
1659:
1660: /*++
1661:
1662: Routine Description:
1663:
1664: This function writes the specified data to the physical memory of the
1665: system being debugged.
1666:
1667: Arguments:
1668:
1669: TargetBaseAddress - Supplies the physical address of the memory to write
1670: to the system being debugged.
1671:
1672: UserInterfaceBuffer - Supplies the address of the buffer in the user
1673: interface that contains the data to be written.
1674:
1675: TransferCount - Specifies the number of bytes to write.
1676:
1677: ActualBytesWritten - An optional parameter that if supplied, returns
1678: the number of bytes actually written.
1679:
1680: Return Value:
1681:
1682: ERROR_SUCCESS - The specified read occured.
1683:
1684: ERROR_MORE_DATA - A read that is to large was specified.
1685:
1686: ERROR_NO_ACCESS - TBD // Can you even HAVE an access
1687: // violation with a physical
1688: // memory access??
1689:
1690: !ERROR_SUCCESS - TBD
1691:
1692: --*/
1693:
1694: {
1695: DBGKD_MANIPULATE_STATE m;
1696: PDBGKD_MANIPULATE_STATE Reply;
1697: PDBGKD_WRITE_MEMORY a = &m.u.WriteMemory;
1698: DWORD st;
1699: BOOLEAN rc;
1700:
1701: if ( TransferCount + sizeof(m) > PACKET_MAX_SIZE ) {
1702: return ERROR_MORE_DATA;
1703: }
1704:
1705: //
1706: // Format state manipulate message
1707: //
1708:
1709: m.ApiNumber = DbgKdWritePhysicalMemoryApi;
1710: m.ReturnStatus = STATUS_PENDING;
1711: //
1712: // BUGBUG TargetBaseAddress should be >32 bits
1713: //
1714: a->TargetBaseAddress = (PVOID)TargetBaseAddress.LowPart;
1715: a->TransferCount = TransferCount;
1716: a->ActualBytesWritten = 0L;
1717:
1718: //
1719: // Send the message and data to write and then wait for reply
1720: //
1721:
1722: do {
1723: DbgKdpWritePacket(
1724: &m,
1725: sizeof(m),
1726: PACKET_TYPE_KD_STATE_MANIPULATE,
1727: UserInterfaceBuffer,
1728: (USHORT)TransferCount
1729: );
1730:
1731: rc = DbgKdpWaitForPacket(PACKET_TYPE_KD_STATE_MANIPULATE, &Reply);
1732: } while (rc == FALSE);
1733:
1734: //
1735: // If this is not a WriteMemory response than protocol is screwed up.
1736: // assert that protocol is ok.
1737: //
1738:
1739: st = Reply->ReturnStatus;
1740: assert(Reply->ApiNumber == DbgKdWritePhysicalMemoryApi);
1741:
1742: //
1743: // Reset message address to reply.
1744: //
1745:
1746: a = &Reply->u.WriteMemory;
1747: assert(a->ActualBytesWritten <= TransferCount);
1748:
1749: //
1750: // Return actual bytes written
1751: //
1752:
1753: if (ActualBytesWritten) {
1754: *ActualBytesWritten = a->ActualBytesWritten;
1755: }
1756: st = Reply->ReturnStatus;
1757:
1758: return st;
1759: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.