Mega KD64 revival patch:
[reactos.git] / reactos / ntoskrnl / kd64 / kdapi.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/kd64/kdapi.c
5 * PURPOSE: KD64 Public Routines and Internal Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* PRIVATE FUNCTIONS *********************************************************/
16
17 VOID
18 NTAPI
19 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,
20 IN PCONTEXT Context)
21 {
22 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;
23 STRING Header;
24 NTSTATUS Status = STATUS_SUCCESS;
25
26 /* Validate the address space */
27 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)
28 {
29 /* Check if this is process memory */
30 if ((PVOID)(LONG_PTR)Memory->Address < MmHighestUserAddress)
31 {
32 /* It is */
33 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
34 }
35 else
36 {
37 /* FIXME: Check if it's session space */
38 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
39 }
40
41 /* Set flags */
42 Memory->Flags = DBGKD_QUERY_MEMORY_READ |
43 DBGKD_QUERY_MEMORY_WRITE |
44 DBGKD_QUERY_MEMORY_EXECUTE;
45 }
46 else
47 {
48 /* Invalid */
49 Status = STATUS_INVALID_PARAMETER;
50 }
51
52 /* Return structure */
53 State->ReturnStatus = Status;
54 Memory->Reserved = 0;
55
56 /* Build header */
57 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
58 Header.Buffer = (PCHAR)State;
59
60 /* Send the packet */
61 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
62 &Header,
63 NULL,
64 &KdpContext);
65 }
66
67 VOID
68 NTAPI
69 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
70 IN PSTRING Data,
71 IN PCONTEXT Context)
72 {
73 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
74 STRING Header;
75
76 /* Build header */
77 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
78 Header.Buffer = (PCHAR)State;
79 ASSERT(Data->Length == 0);
80
81 /* Create the breakpoint */
82 Breakpoint->BreakPointHandle =
83 KdpAddBreakpoint((PVOID)(LONG_PTR)Breakpoint->BreakPointAddress);
84 if (!Breakpoint->BreakPointHandle)
85 {
86 /* We failed */
87 State->ReturnStatus = STATUS_UNSUCCESSFUL;
88 }
89 else
90 {
91 /* Success! */
92 State->ReturnStatus = STATUS_SUCCESS;
93 }
94
95 /* Send the packet */
96 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
97 &Header,
98 NULL,
99 &KdpContext);
100 }
101
102 VOID
103 NTAPI
104 DumpTraceData(IN PSTRING TraceData)
105 {
106 /* Update the buffer */
107 TraceDataBuffer[0] = TraceDataBufferPosition;
108
109 /* Setup the trace data */
110 TraceData->Length = TraceDataBufferPosition * sizeof(ULONG);
111 TraceData->Buffer = (PCHAR)TraceDataBuffer;
112
113 /* Reset the buffer location */
114 TraceDataBufferPosition = 1;
115 }
116
117 VOID
118 NTAPI
119 KdpGetStateChange(IN PDBGKD_MANIPULATE_STATE64 State,
120 IN PCONTEXT Context)
121 {
122 PKPRCB Prcb;
123 ULONG i;
124
125 /* Check for success */
126 if (NT_SUCCESS(State->u.Continue2.ContinueStatus))
127 {
128 /* Check if we're tracing */
129 if (State->u.Continue2.ControlSet.TraceFlag)
130 {
131 /* Enable TF */
132 Context->EFlags |= EFLAGS_TF;
133 }
134 else
135 {
136 /* Remove it */
137 Context->EFlags &= ~EFLAGS_TF;
138 }
139
140 /* Loop all processors */
141 for (i = 0; i < KeNumberProcessors; i++)
142 {
143 /* Get the PRCB and update DR7 and DR6 */
144 Prcb = KiProcessorBlock[i];
145 Prcb->ProcessorState.SpecialRegisters.KernelDr7 =
146 State->u.Continue2.ControlSet.Dr7;
147 Prcb->ProcessorState.SpecialRegisters.KernelDr6 = 0;
148 }
149
150 /* Check if we have new symbol information */
151 if (State->u.Continue2.ControlSet.CurrentSymbolStart != 1)
152 {
153 /* Update it */
154 KdpCurrentSymbolStart =
155 State->u.Continue2.ControlSet.CurrentSymbolStart;
156 KdpCurrentSymbolEnd= State->u.Continue2.ControlSet.CurrentSymbolEnd;
157 }
158 }
159 }
160
161 VOID
162 NTAPI
163 KdpSetCommonState(IN ULONG NewState,
164 IN PCONTEXT Context,
165 IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange)
166 {
167 USHORT InstructionCount;
168 BOOLEAN HadBreakpoints;
169
170 /* Setup common stuff available for all CPU architectures */
171 WaitStateChange->NewState = NewState;
172 WaitStateChange->ProcessorLevel = KeProcessorLevel;
173 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
174 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
175 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
176 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
177
178 /* Zero out the Control Report */
179 RtlZeroMemory(&WaitStateChange->ControlReport,
180 sizeof(DBGKD_CONTROL_REPORT));
181
182 /* Now copy the instruction stream and set the count */
183 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
184 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
185 DBGKD_MAXSTREAM);
186 InstructionCount = DBGKD_MAXSTREAM;
187 WaitStateChange->ControlReport.InstructionCount = InstructionCount;
188
189 /* Clear all the breakpoints in this region */
190 HadBreakpoints =
191 KdpDeleteBreakpointRange((PVOID)(LONG_PTR)WaitStateChange->ProgramCounter,
192 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
193 WaitStateChange->ControlReport.InstructionCount - 1));
194 if (HadBreakpoints)
195 {
196 /* Copy the instruction stream again, this time without breakpoints */
197 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
198 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
199 WaitStateChange->ControlReport.InstructionCount);
200 }
201 }
202
203 VOID
204 NTAPI
205 KdpSetContextState(IN PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange,
206 IN PCONTEXT Context)
207 {
208 PKPRCB Prcb = KeGetCurrentPrcb();
209
210 /* Copy i386 specific debug registers */
211 WaitStateChange->ControlReport.Dr6 = Prcb->ProcessorState.SpecialRegisters.
212 KernelDr6;
213 WaitStateChange->ControlReport.Dr7 = Prcb->ProcessorState.SpecialRegisters.
214 KernelDr7;
215
216 /* Copy i386 specific segments */
217 WaitStateChange->ControlReport.SegCs = (USHORT)Context->SegCs;
218 WaitStateChange->ControlReport.SegDs = (USHORT)Context->SegDs;
219 WaitStateChange->ControlReport.SegEs = (USHORT)Context->SegEs;
220 WaitStateChange->ControlReport.SegFs = (USHORT)Context->SegFs;
221
222 /* Copy EFlags */
223 WaitStateChange->ControlReport.EFlags = Context->EFlags;
224
225 /* Set Report Flags */
226 WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_SEGS;
227 if (WaitStateChange->ControlReport.SegCs == KGDT_R0_CODE)
228 {
229 WaitStateChange->ControlReport.ReportFlags = REPORT_INCLUDES_CS;
230 }
231 }
232
233 VOID
234 NTAPI
235 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version)
236 {
237 /* Copy the version block */
238 RtlCopyMemory(Version, &KdVersionBlock, sizeof(DBGKD_GET_VERSION64));
239 }
240
241 VOID
242 NTAPI
243 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
244 {
245 STRING Header;
246
247 /* Fill out the header */
248 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
249 Header.Buffer = (PCHAR)State;
250
251 /* Get the version block */
252 KdpSysGetVersion(&State->u.GetVersion64);
253
254 /* Fill out the state */
255 State->ApiNumber = DbgKdGetVersionApi;
256 State->ReturnStatus = STATUS_SUCCESS;
257
258 /* Send the packet */
259 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
260 &Header,
261 NULL,
262 &KdpContext);
263 }
264
265 VOID
266 NTAPI
267 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
268 IN PSTRING Data,
269 IN PCONTEXT Context)
270 {
271 STRING Header;
272 ULONG Length = State->u.ReadMemory.TransferCount;
273 NTSTATUS Status = STATUS_SUCCESS;
274
275 /* Validate length */
276 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
277 {
278 /* Overflow, set it to maximum possible */
279 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
280 }
281
282 #if 0
283 if (!MmIsAddressValid((PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress))
284 {
285 Ke386SetCr2(State->u.ReadMemory.TargetBaseAddress);
286 while (TRUE);
287 }
288 #endif
289
290 if (!State->u.ReadMemory.TargetBaseAddress)
291 {
292 Length = 0;
293 Status = STATUS_UNSUCCESSFUL;
294 }
295 else
296 {
297 RtlCopyMemory(Data->Buffer,
298 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress,
299 Length);
300 }
301
302 /* Fill out the header */
303 Data->Length = Length;
304 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
305 Header.Buffer = (PCHAR)State;
306
307 /* Fill out the state */
308 State->ReturnStatus = Status;
309 State->u.ReadMemory.ActualBytesRead = Length;
310
311 /* Send the packet */
312 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
313 &Header,
314 Data,
315 &KdpContext);
316 }
317
318 VOID
319 NTAPI
320 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
321 IN PSTRING Data,
322 IN PCONTEXT Context)
323 {
324 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
325 STRING Header;
326 ULONG Length, RealLength;
327 PVOID ControlStart;
328
329 /* Setup the header */
330 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
331 Header.Buffer = (PCHAR)State;
332 ASSERT(Data->Length == 0);
333
334 /* Check the length requested */
335 Length = ReadMemory->TransferCount;
336 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
337 {
338 /* Use maximum allowed */
339 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
340 }
341
342 /* Make sure that this is a valid request */
343 if (((ULONG)ReadMemory->TargetBaseAddress < sizeof(KPROCESSOR_STATE)) &&
344 (State->Processor < KeNumberProcessors))
345 {
346 /* Get the actual length */
347 RealLength = sizeof(KPROCESSOR_STATE) -
348 (ULONG_PTR)ReadMemory->TargetBaseAddress;
349 if (RealLength < Length) Length = RealLength;
350
351 /* Set the proper address */
352 ControlStart = (PVOID)((ULONG_PTR)ReadMemory->TargetBaseAddress +
353 (ULONG_PTR)&KiProcessorBlock[State->Processor]->
354 ProcessorState);
355
356 /* Copy the memory */
357 RtlCopyMemory(Data->Buffer, ControlStart, Length);
358 Data->Length = Length;
359
360 /* Finish up */
361 State->ReturnStatus = STATUS_SUCCESS;
362 ReadMemory->ActualBytesRead = Data->Length;
363 }
364 else
365 {
366 /* Invalid request */
367 Data->Length = 0;
368 State->ReturnStatus = STATUS_UNSUCCESSFUL;
369 ReadMemory->ActualBytesRead = 0;
370 }
371
372 /* Send the reply */
373 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
374 &Header,
375 Data,
376 &KdpContext);
377 }
378
379 VOID
380 NTAPI
381 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
382 IN PSTRING Data,
383 IN PCONTEXT Context)
384 {
385 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
386 STRING Header;
387 ULONG Length;
388 PVOID ControlStart;
389
390 /* Setup the header */
391 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
392 Header.Buffer = (PCHAR)State;
393
394 /* Make sure that this is a valid request */
395 Length = WriteMemory->TransferCount;
396 if ((((ULONG)WriteMemory->TargetBaseAddress + Length) <=
397 sizeof(KPROCESSOR_STATE)) &&
398 (State->Processor < KeNumberProcessors))
399 {
400 /* Set the proper address */
401 ControlStart = (PVOID)((ULONG_PTR)WriteMemory->TargetBaseAddress +
402 (ULONG_PTR)&KiProcessorBlock[State->Processor]->
403 ProcessorState);
404
405 /* Copy the memory */
406 RtlCopyMemory(ControlStart, Data->Buffer, Data->Length);
407 Length = Data->Length;
408
409 /* Finish up */
410 State->ReturnStatus = STATUS_SUCCESS;
411 WriteMemory->ActualBytesWritten = Length;
412 }
413 else
414 {
415 /* Invalid request */
416 Data->Length = 0;
417 State->ReturnStatus = STATUS_UNSUCCESSFUL;
418 WriteMemory->ActualBytesWritten = 0;
419 }
420
421 /* Send the reply */
422 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
423 &Header,
424 Data,
425 &KdpContext);
426 }
427
428 VOID
429 NTAPI
430 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
431 IN PSTRING Data,
432 IN PCONTEXT Context)
433 {
434 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
435 STRING Header;
436
437 /* Fill out the header */
438 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
439 Header.Buffer = (PCHAR)State;
440 ASSERT(Data->Length == 0);
441
442 /* Get the version block */
443 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
444 {
445 /* We're all good */
446 State->ReturnStatus = STATUS_SUCCESS;
447 }
448 else
449 {
450 /* We failed */
451 State->ReturnStatus = STATUS_UNSUCCESSFUL;
452 }
453
454 /* Send the packet */
455 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
456 &Header,
457 NULL,
458 &KdpContext);
459 }
460
461 VOID
462 NTAPI
463 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
464 IN PSTRING Data,
465 IN PCONTEXT Context)
466 {
467 STRING Header;
468 PVOID ControlStart;
469
470 /* Setup the header */
471 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
472 Header.Buffer = (PCHAR)State;
473 ASSERT(Data->Length == 0);
474
475 /* Make sure that this is a valid request */
476 if (State->Processor < KeNumberProcessors)
477 {
478 /* Check if the request is for this CPU */
479 if (State->Processor == KeGetCurrentPrcb()->Number)
480 {
481 /* We're just copying our own context */
482 ControlStart = Context;
483 }
484 else
485 {
486 /* SMP not yet handled */
487 ControlStart = NULL;
488 while (TRUE);
489 }
490
491 /* Copy the memory */
492 RtlCopyMemory(Data->Buffer, ControlStart, sizeof(CONTEXT));
493 Data->Length = sizeof(CONTEXT);
494
495 /* Finish up */
496 State->ReturnStatus = STATUS_SUCCESS;
497 }
498 else
499 {
500 /* Invalid request */
501 State->ReturnStatus = STATUS_UNSUCCESSFUL;
502 }
503
504 /* Send the reply */
505 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
506 &Header,
507 Data,
508 &KdpContext);
509 }
510
511 VOID
512 NTAPI
513 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
514 IN PSTRING Data,
515 IN PCONTEXT Context)
516 {
517 STRING Header;
518 PVOID ControlStart;
519
520 /* Setup the header */
521 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
522 Header.Buffer = (PCHAR)State;
523 ASSERT(Data->Length == sizeof(CONTEXT));
524
525 /* Make sure that this is a valid request */
526 if (State->Processor < KeNumberProcessors)
527 {
528 /* Check if the request is for this CPU */
529 if (State->Processor == KeGetCurrentPrcb()->Number)
530 {
531 /* We're just copying our own context */
532 ControlStart = Context;
533 }
534 else
535 {
536 /* SMP not yet handled */
537 ControlStart = NULL;
538 while (TRUE);
539 }
540
541 /* Copy the memory */
542 RtlCopyMemory(ControlStart, Data->Buffer, sizeof(CONTEXT));
543
544 /* Finish up */
545 State->ReturnStatus = STATUS_SUCCESS;
546 }
547 else
548 {
549 /* Invalid request */
550 State->ReturnStatus = STATUS_UNSUCCESSFUL;
551 }
552
553 /* Send the reply */
554 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
555 &Header,
556 Data,
557 &KdpContext);
558 }
559
560 VOID
561 NTAPI
562 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)
563 {
564 /* Crash with the special code */
565 KeBugCheck(MANUALLY_INITIATED_CRASH);
566 }
567
568 KCONTINUE_STATUS
569 NTAPI
570 KdpSendWaitContinue(IN ULONG PacketType,
571 IN PSTRING SendHeader,
572 IN PSTRING SendData OPTIONAL,
573 IN OUT PCONTEXT Context)
574 {
575 STRING Data, Header;
576 DBGKD_MANIPULATE_STATE64 ManipulateState;
577 ULONG Length;
578 KDSTATUS RecvCode;
579
580 /* Setup the Manipulate State structure */
581 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
582 Header.Buffer = (PCHAR)&ManipulateState;
583 Data.MaximumLength = sizeof(KdpMessageBuffer);
584 Data.Buffer = KdpMessageBuffer;
585 //KdpContextSent = FALSE;
586
587 SendPacket:
588 /* Send the Packet */
589 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
590
591 /* If the debugger isn't present anymore, just return success */
592 if (KdDebuggerNotPresent) return ContinueSuccess;
593
594 /* Main processing Loop */
595 for (;;)
596 {
597 /* Receive Loop */
598 do
599 {
600 /* Wait to get a reply to our packet */
601 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
602 &Header,
603 &Data,
604 &Length,
605 &KdpContext);
606
607 /* If we got a resend request, do it */
608 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
609 } while (RecvCode == KdPacketTimedOut);
610
611 /* Now check what API we got */
612 switch (ManipulateState.ApiNumber)
613 {
614 case DbgKdReadVirtualMemoryApi:
615
616 /* Read virtual memory */
617 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
618 break;
619
620 case DbgKdWriteVirtualMemoryApi:
621
622 /* FIXME: TODO */
623 Ke386SetCr2(DbgKdWriteVirtualMemoryApi);
624 while (TRUE);
625 break;
626
627 case DbgKdGetContextApi:
628
629 /* Get the current context */
630 KdpGetContext(&ManipulateState, &Data, Context);
631 break;
632
633 case DbgKdSetContextApi:
634
635 /* Set a new context */
636 KdpSetContext(&ManipulateState, &Data, Context);
637 break;
638
639 case DbgKdWriteBreakPointApi:
640
641 /* Write the breakpoint */
642 KdpWriteBreakpoint(&ManipulateState, &Data, Context);
643 break;
644
645 case DbgKdRestoreBreakPointApi:
646
647 /* Restore the breakpoint */
648 KdpRestoreBreakpoint(&ManipulateState, &Data, Context);
649 break;
650
651 case DbgKdContinueApi:
652
653 /* Simply continue */
654 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);
655
656 case DbgKdReadControlSpaceApi:
657
658 /* Read control space */
659 KdpReadControlSpace(&ManipulateState, &Data, Context);
660 break;
661
662 case DbgKdWriteControlSpaceApi:
663
664 /* Write control space */
665 KdpWriteControlSpace(&ManipulateState, &Data, Context);
666 break;
667
668 case DbgKdReadIoSpaceApi:
669
670 /* FIXME: TODO */
671 Ke386SetCr2(DbgKdReadIoSpaceApi);
672 while (TRUE);
673 break;
674
675 case DbgKdWriteIoSpaceApi:
676
677 /* FIXME: TODO */
678 Ke386SetCr2(DbgKdWriteIoSpaceApi);
679 while (TRUE);
680 break;
681
682 case DbgKdRebootApi:
683
684 /* Reboot the system */
685 HalReturnToFirmware(HalRebootRoutine);
686 break;
687
688 case DbgKdContinueApi2:
689
690 /* Check if caller reports success */
691 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))
692 {
693 /* Update the state */
694 KdpGetStateChange(&ManipulateState, Context);
695 return ContinueSuccess;
696 }
697 else
698 {
699 /* Return an error */
700 return ContinueError;
701 }
702 break;
703
704 case DbgKdReadPhysicalMemoryApi:
705
706 /* FIXME: TODO */
707 goto fail;
708 Ke386SetCr2(DbgKdReadPhysicalMemoryApi);
709 while (TRUE);
710 break;
711
712 case DbgKdWritePhysicalMemoryApi:
713
714 /* FIXME: TODO */
715 Ke386SetCr2(DbgKdWritePhysicalMemoryApi);
716 while (TRUE);
717 break;
718
719 case DbgKdQuerySpecialCallsApi:
720
721 /* FIXME: TODO */
722 Ke386SetCr2(DbgKdQuerySpecialCallsApi);
723 while (TRUE);
724 break;
725
726 case DbgKdSetSpecialCallApi:
727
728 /* FIXME: TODO */
729 Ke386SetCr2(DbgKdSetSpecialCallApi);
730 while (TRUE);
731 break;
732
733 case DbgKdClearSpecialCallsApi:
734
735 /* FIXME: TODO */
736 Ke386SetCr2(DbgKdClearSpecialCallsApi);
737 while (TRUE);
738 break;
739
740 case DbgKdSetInternalBreakPointApi:
741
742 /* FIXME: TODO */
743 Ke386SetCr2(DbgKdSetInternalBreakPointApi);
744 while (TRUE);
745 break;
746
747 case DbgKdGetInternalBreakPointApi:
748
749 /* FIXME: TODO */
750 Ke386SetCr2(DbgKdGetInternalBreakPointApi);
751 while (TRUE);
752 break;
753
754 case DbgKdReadIoSpaceExtendedApi:
755
756 /* FIXME: TODO */
757 Ke386SetCr2(DbgKdReadIoSpaceExtendedApi);
758 while (TRUE);
759 break;
760
761 case DbgKdWriteIoSpaceExtendedApi:
762
763 /* FIXME: TODO */
764 Ke386SetCr2(DbgKdWriteIoSpaceExtendedApi);
765 while (TRUE);
766 break;
767
768 case DbgKdGetVersionApi:
769
770 /* Get version data */
771 KdpGetVersion(&ManipulateState);
772 break;
773
774 case DbgKdWriteBreakPointExApi:
775
776 /* FIXME: TODO */
777 Ke386SetCr2(DbgKdWriteBreakPointExApi);
778 while (TRUE);
779 break;
780
781 case DbgKdRestoreBreakPointExApi:
782
783 /* FIXME: TODO */
784 Ke386SetCr2(DbgKdRestoreBreakPointExApi);
785 while (TRUE);
786 break;
787
788 case DbgKdCauseBugCheckApi:
789
790 /* Crash the system */
791 KdpCauseBugCheck(&ManipulateState);
792 break;
793
794 case DbgKdSwitchProcessor:
795
796 /* FIXME: TODO */
797 Ke386SetCr2(DbgKdSwitchProcessor);
798 while (TRUE);
799 break;
800
801 case DbgKdPageInApi:
802
803 /* FIXME: TODO */
804 Ke386SetCr2(DbgKdPageInApi);
805 while (TRUE);
806 break;
807
808 case DbgKdReadMachineSpecificRegister:
809
810 /* FIXME: TODO */
811 Ke386SetCr2(DbgKdReadMachineSpecificRegister);
812 while (TRUE);
813 break;
814
815 case DbgKdWriteMachineSpecificRegister:
816
817 /* FIXME: TODO */
818 Ke386SetCr2(DbgKdWriteMachineSpecificRegister);
819 while (TRUE);
820 break;
821
822 case OldVlm1:
823
824 /* FIXME: TODO */
825 Ke386SetCr2(OldVlm1);
826 while (TRUE);
827 break;
828
829 case OldVlm2:
830
831 /* FIXME: TODO */
832 Ke386SetCr2(OldVlm2);
833 while (TRUE);
834 break;
835
836 case DbgKdSearchMemoryApi:
837
838 /* FIXME: TODO */
839 Ke386SetCr2(DbgKdSearchMemoryApi);
840 while (TRUE);
841 break;
842
843 case DbgKdGetBusDataApi:
844
845 /* FIXME: TODO */
846 Ke386SetCr2(DbgKdGetBusDataApi);
847 while (TRUE);
848 break;
849
850 case DbgKdSetBusDataApi:
851
852 /* FIXME: TODO */
853 Ke386SetCr2(DbgKdSetBusDataApi);
854 while (TRUE);
855 break;
856
857 case DbgKdCheckLowMemoryApi:
858
859 /* FIXME: TODO */
860 Ke386SetCr2(DbgKdCheckLowMemoryApi);
861 while (TRUE);
862 break;
863
864 case DbgKdClearAllInternalBreakpointsApi:
865
866 /* Just clear the counter */
867 KdpNumInternalBreakpoints = 0;
868 break;
869
870 case DbgKdFillMemoryApi:
871
872 /* FIXME: TODO */
873 Ke386SetCr2(DbgKdFillMemoryApi);
874 while (TRUE);
875 break;
876
877 case DbgKdQueryMemoryApi:
878
879 /* Query memory */
880 KdpQueryMemory(&ManipulateState, Context);
881 break;
882
883 case DbgKdSwitchPartition:
884
885 /* FIXME: TODO */
886 Ke386SetCr2(DbgKdSwitchPartition);
887 while (TRUE);
888 break;
889
890 /* Unsupported Message */
891 default:
892
893 /* Setup an empty message, with failure */
894 while (TRUE);
895 fail:
896 Data.Length = 0;
897 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
898
899 /* Send it */
900 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
901 &Header,
902 &Data,
903 &KdpContext);
904 break;
905 }
906 }
907 }
908
909 BOOLEAN
910 NTAPI
911 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
912 IN PKD_SYMBOLS_INFO SymbolInfo,
913 IN BOOLEAN Unload,
914 IN OUT PCONTEXT Context)
915 {
916 PSTRING ExtraData;
917 STRING Data, Header;
918 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
919 KCONTINUE_STATUS Status;
920
921 /* Start wait loop */
922 do
923 {
924 /* Build the architecture common parts of the message */
925 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
926 Context,
927 &WaitStateChange);
928
929 /* Now finish creating the structure */
930 KdpSetContextState(&WaitStateChange, Context);
931
932 /* Fill out load data */
933 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
934 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONGLONG)(LONG_PTR)SymbolInfo->BaseOfDll;
935 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
936 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
937 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
938
939 /* Check if we have a symbol name */
940 if (PathName)
941 {
942 /* Setup the information */
943 WaitStateChange.u.LoadSymbols.PathNameLength = PathName->Length;
944 RtlCopyMemory(KdpPathBuffer, PathName->Buffer, PathName->Length);
945 Data.Buffer = KdpPathBuffer;
946 Data.Length = WaitStateChange.u.LoadSymbols.PathNameLength;
947 ExtraData = &Data;
948 }
949 else
950 {
951 /* No name */
952 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
953 ExtraData = NULL;
954 }
955
956 /* Setup the header */
957 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
958 Header.Buffer = (PCHAR)&WaitStateChange;
959
960 /* Send the packet */
961 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
962 &Header,
963 ExtraData,
964 Context);
965 } while (Status == ContinueProcessorReselected);
966
967 /* Return status */
968 return Status;
969 }
970
971 BOOLEAN
972 NTAPI
973 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
974 IN OUT PCONTEXT Context,
975 IN BOOLEAN SecondChanceException)
976 {
977 STRING Header, Data;
978 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
979 BOOLEAN Status;
980
981 /* Start report loop */
982 do
983 {
984 /* Build the architecture common parts of the message */
985 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
986
987 /* Convert the exception record to 64-bits and set First Chance flag */
988 ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
989 &WaitStateChange.u.Exception.ExceptionRecord);
990 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
991
992 /* Now finish creating the structure */
993 KdpSetContextState(&WaitStateChange, Context);
994
995 /* Setup the actual header to send to KD */
996 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
997 Header.Buffer = (PCHAR)&WaitStateChange;
998
999 /* Setup the trace data */
1000 DumpTraceData(&Data);
1001
1002 /* Send State Change packet and wait for a reply */
1003 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1004 &Header,
1005 &Data,
1006 Context);
1007 } while (Status == ContinueProcessorReselected);
1008
1009 /* Return */
1010 return Status;
1011 }
1012
1013 VOID
1014 NTAPI
1015 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1016 IN PVOID DeferredContext,
1017 IN PVOID SystemArgument1,
1018 IN PVOID SystemArgument2)
1019 {
1020 LONG OldSlip, NewSlip, PendingSlip;
1021
1022 /* Get the current pending slip */
1023 PendingSlip = KdpTimeSlipPending;
1024 do
1025 {
1026 /* Save the old value and either disable or enable it now. */
1027 OldSlip = PendingSlip;
1028 NewSlip = OldSlip > 1 ? 1 : 0;
1029
1030 /* Try to change the value */
1031 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1032 NewSlip,
1033 OldSlip) != OldSlip);
1034
1035 /* If the New Slip value is 1, then do the Time Slipping */
1036 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1037 }
1038
1039 VOID
1040 NTAPI
1041 KdpTimeSlipWork(IN PVOID Context)
1042 {
1043 KIRQL OldIrql;
1044 LARGE_INTEGER DueTime;
1045
1046 /* Update the System time from the CMOS */
1047 ExAcquireTimeRefreshLock(FALSE);
1048 ExUpdateSystemTimeFromCmos(FALSE, 0);
1049 ExReleaseTimeRefreshLock();
1050
1051 /* Check if we have a registered Time Slip Event and signal it */
1052 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1053 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1054 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1055
1056 /* Delay the DPC until it runs next time */
1057 DueTime.QuadPart = -1800000000;
1058 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1059 }
1060
1061 BOOLEAN
1062 NTAPI
1063 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
1064 IN OUT PCONTEXT ContextRecord,
1065 IN BOOLEAN SecondChanceException)
1066 {
1067 BOOLEAN Status;
1068
1069 /* Save the port data */
1070 KdSave(FALSE);
1071
1072 /* Report a state change */
1073 Status = KdpReportExceptionStateChange(ExceptionRecord,
1074 ContextRecord,
1075 SecondChanceException);
1076
1077 /* Restore the port data and return */
1078 KdRestore(FALSE);
1079 return Status;
1080 }
1081
1082 LARGE_INTEGER
1083 NTAPI
1084 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1085 {
1086 LARGE_INTEGER Null = {{0}};
1087
1088 /* Check if interrupts were disabled */
1089 if (!(TrapFrame->EFlags & EFLAGS_INTERRUPT_MASK))
1090 {
1091 /* Nothing to return */
1092 return Null;
1093 }
1094
1095 /* Otherwise, do the call */
1096 return KeQueryPerformanceCounter(NULL);
1097 }
1098
1099 BOOLEAN
1100 NTAPI
1101 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1102 IN PKEXCEPTION_FRAME ExceptionFrame)
1103 {
1104 BOOLEAN Entered;
1105
1106 /* Check if we have a trap frame */
1107 if (TrapFrame)
1108 {
1109 /* Calculate the time difference for the enter */
1110 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1111 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1112 KdTimerStart.QuadPart;
1113 }
1114 else
1115 {
1116 /* No trap frame, so can't calculate */
1117 KdTimerStop.QuadPart = 0;
1118 }
1119
1120 /* Save the current IRQL */
1121 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1122
1123 /* Freeze all CPUs */
1124 Entered = KeFreezeExecution(TrapFrame, ExceptionFrame);
1125
1126 /* Lock the port, save the state and set debugger entered */
1127 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1128 KdSave(FALSE);
1129 KdEnteredDebugger = TRUE;
1130
1131 /* Check freeze flag */
1132 if (KiFreezeFlag & 1)
1133 {
1134 /* Print out errror */
1135 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1136 }
1137
1138 /* Check processor state */
1139 if (KiFreezeFlag & 2)
1140 {
1141 /* Print out errror */
1142 KdpDprintf("Some processors not frozen in debugger!\n");
1143 }
1144
1145 /* Make sure we acquired the port */
1146 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n");
1147
1148 /* Return enter state */
1149 return Entered;
1150 }
1151
1152 VOID
1153 NTAPI
1154 KdExitDebugger(IN BOOLEAN Entered)
1155 {
1156 ULONG TimeSlip;
1157
1158 /* Restore the state and unlock the port */
1159 KdRestore(FALSE);
1160 if (KdpPortLocked) KdpPortUnlock();
1161
1162 /* Unfreeze the CPUs */
1163 KeThawExecution(Entered);
1164
1165 /* Compare time with the one from KdEnterDebugger */
1166 if (!KdTimerStop.QuadPart)
1167 {
1168 /* We didn't get a trap frame earlier in so never got the time */
1169 KdTimerStart = KdTimerStop;
1170 }
1171 else
1172 {
1173 /* Query the timer */
1174 KdTimerStart = KeQueryPerformanceCounter(NULL);
1175 }
1176
1177 /* Check if a Time Slip was on queue */
1178 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1179 if (TimeSlip == 1)
1180 {
1181 /* Queue a DPC for the time slip */
1182 InterlockedIncrement(&KdpTimeSlipPending);
1183 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
1184 }
1185 }
1186
1187 NTSTATUS
1188 NTAPI
1189 KdEnableDebuggerWithLock(BOOLEAN NeedLock)
1190 {
1191 KIRQL OldIrql = PASSIVE_LEVEL;
1192
1193 /* Check if we need to acquire the lock */
1194 if (NeedLock)
1195 {
1196 /* Lock the port */
1197 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1198 KdpPortLock();
1199 }
1200
1201 /* Check if we're not disabled */
1202 if (!KdDisableCount)
1203 {
1204 /* Check if we had locked the port before */
1205 if (NeedLock)
1206 {
1207 /* Do the unlock */
1208 KeLowerIrql(OldIrql);
1209 KdpPortUnlock();
1210 }
1211
1212 /* Fail: We're already enabled */
1213 return STATUS_INVALID_PARAMETER;
1214 }
1215
1216 /* Decrease the disable count */
1217 if (!(--KdDisableCount))
1218 {
1219 /* We're now enabled again! Were we enabled before, too? */
1220 if (KdPreviouslyEnabled)
1221 {
1222 /* Reinitialize the Debugger */
1223 KdInitSystem(0, NULL) ;
1224 KdpRestoreAllBreakpoints();
1225 }
1226 }
1227
1228 /* Check if we had locked the port before */
1229 if (NeedLock)
1230 {
1231 /* Yes, now unlock it */
1232 KeLowerIrql(OldIrql);
1233 KdpPortUnlock();
1234 }
1235
1236 /* We're done */
1237 return STATUS_SUCCESS;
1238 }
1239
1240 /* PUBLIC FUNCTIONS **********************************************************/
1241
1242 /*
1243 * @implemented
1244 */
1245 NTSTATUS
1246 NTAPI
1247 KdEnableDebugger(VOID)
1248 {
1249 /* Use the internal routine */
1250 while (TRUE);
1251 return KdEnableDebuggerWithLock(TRUE);
1252 }
1253
1254 /*
1255 * @unimplemented
1256 */
1257 NTSTATUS
1258 NTAPI
1259 KdSystemDebugControl(IN SYSDBG_COMMAND Command,
1260 IN PVOID InputBuffer,
1261 IN ULONG InputBufferLength,
1262 OUT PVOID OutputBuffer,
1263 IN ULONG OutputBufferLength,
1264 IN OUT PULONG ReturnLength,
1265 IN KPROCESSOR_MODE PreviousMode)
1266 {
1267 /* HACK */
1268 return STATUS_SUCCESS;
1269 }
1270
1271 /*
1272 * @unimplemented
1273 */
1274 NTSTATUS
1275 NTAPI
1276 KdChangeOption(IN KD_OPTION Option,
1277 IN ULONG InBufferBytes OPTIONAL,
1278 IN PVOID InBuffer,
1279 IN ULONG OutBufferBytes OPTIONAL,
1280 OUT PVOID OutBuffer,
1281 OUT PULONG OutBufferNeeded OPTIONAL)
1282 {
1283 /* HACK */
1284 return STATUS_SUCCESS;
1285 }
1286
1287 /*
1288 * @unimplemented
1289 */
1290 NTSTATUS
1291 NTAPI
1292 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
1293 {
1294 /* HACK */
1295 return STATUS_SUCCESS;
1296 }
1297
1298 /*
1299 * @unimplemented
1300 */
1301 NTSTATUS
1302 NTAPI
1303 KdDisableDebugger(VOID)
1304 {
1305 /* HACK */
1306 return STATUS_SUCCESS;
1307 }
1308
1309 /*
1310 * @unimplemented
1311 */
1312 BOOLEAN
1313 NTAPI
1314 KdRefreshDebuggerNotPresent(VOID)
1315 {
1316 /* HACK */
1317 return KdDebuggerNotPresent;
1318 }
1319
1320 NTSTATUS
1321 NTAPI
1322 NtQueryDebugFilterState(ULONG ComponentId,
1323 ULONG Level)
1324 {
1325 /* HACK */
1326 return STATUS_SUCCESS;
1327 }
1328
1329 NTSTATUS
1330 NTAPI
1331 NtSetDebugFilterState(ULONG ComponentId,
1332 ULONG Level,
1333 BOOLEAN State)
1334 {
1335 /* HACK */
1336 return STATUS_SUCCESS;
1337 }
1338