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