Add back some stuff that got lost in syncing
[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)(ULONG_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 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,
70 IN PSTRING Data,
71 IN PCONTEXT Context)
72 {
73 /* FIXME: STUB */
74 KdpDprintf("KdpSearchMemory called\n");
75 while (TRUE);
76 }
77
78 VOID
79 NTAPI
80 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,
81 IN PSTRING Data,
82 IN PCONTEXT Context)
83 {
84 /* FIXME: STUB */
85 KdpDprintf("KdpFillMemory called\n");
86 while (TRUE);
87 }
88
89 VOID
90 NTAPI
91 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
92 IN PSTRING Data,
93 IN PCONTEXT Context)
94 {
95 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
96 STRING Header;
97
98 /* Build header */
99 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
100 Header.Buffer = (PCHAR)State;
101 ASSERT(Data->Length == 0);
102
103 /* Create the breakpoint */
104 Breakpoint->BreakPointHandle =
105 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress);
106 if (!Breakpoint->BreakPointHandle)
107 {
108 /* We failed */
109 State->ReturnStatus = STATUS_UNSUCCESSFUL;
110 }
111 else
112 {
113 /* Success! */
114 State->ReturnStatus = STATUS_SUCCESS;
115 }
116
117 /* Send the packet */
118 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
119 &Header,
120 NULL,
121 &KdpContext);
122 }
123
124 VOID
125 NTAPI
126 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
127 IN PSTRING Data,
128 IN PCONTEXT Context)
129 {
130 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
131 STRING Header;
132
133 /* Fill out the header */
134 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
135 Header.Buffer = (PCHAR)State;
136 ASSERT(Data->Length == 0);
137
138 /* Get the version block */
139 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
140 {
141 /* We're all good */
142 State->ReturnStatus = STATUS_SUCCESS;
143 }
144 else
145 {
146 /* We failed */
147 State->ReturnStatus = STATUS_UNSUCCESSFUL;
148 }
149
150 /* Send the packet */
151 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
152 &Header,
153 NULL,
154 &KdpContext);
155 }
156
157 NTSTATUS
158 NTAPI
159 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
160 IN PSTRING Data,
161 IN PCONTEXT Context)
162 {
163 /* FIXME: STUB */
164 KdpDprintf("KdpWriteBreakPointEx called\n");
165 while (TRUE);
166 return STATUS_UNSUCCESSFUL;
167 }
168
169 VOID
170 NTAPI
171 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
172 IN PSTRING Data,
173 IN PCONTEXT Context)
174 {
175 /* FIXME: STUB */
176 KdpDprintf("KdpRestoreBreakPointEx called\n");
177 while (TRUE);
178 }
179
180 VOID
181 NTAPI
182 DumpTraceData(OUT PSTRING TraceData)
183 {
184 /* Update the buffer */
185 TraceDataBuffer[0] = TraceDataBufferPosition;
186
187 /* Setup the trace data */
188 TraceData->Length = TraceDataBufferPosition * sizeof(ULONG);
189 TraceData->Buffer = (PCHAR)TraceDataBuffer;
190
191 /* Reset the buffer location */
192 TraceDataBufferPosition = 1;
193 }
194
195 VOID
196 NTAPI
197 KdpSetCommonState(IN ULONG NewState,
198 IN PCONTEXT Context,
199 OUT PDBGKD_WAIT_STATE_CHANGE64 WaitStateChange)
200 {
201 USHORT InstructionCount;
202 BOOLEAN HadBreakpoints;
203
204 /* Setup common stuff available for all CPU architectures */
205 WaitStateChange->NewState = NewState;
206 WaitStateChange->ProcessorLevel = KeProcessorLevel;
207 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
208 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
209 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
210 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
211
212 /* Zero out the Control Report */
213 RtlZeroMemory(&WaitStateChange->ControlReport,
214 sizeof(DBGKD_CONTROL_REPORT));
215
216 /* Now copy the instruction stream and set the count */
217 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
218 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
219 DBGKD_MAXSTREAM);
220 InstructionCount = DBGKD_MAXSTREAM;
221 WaitStateChange->ControlReport.InstructionCount = InstructionCount;
222
223 /* Clear all the breakpoints in this region */
224 HadBreakpoints =
225 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
226 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
227 WaitStateChange->ControlReport.InstructionCount - 1));
228 if (HadBreakpoints)
229 {
230 /* Copy the instruction stream again, this time without breakpoints */
231 RtlCopyMemory(&WaitStateChange->ControlReport.InstructionStream[0],
232 (PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
233 WaitStateChange->ControlReport.InstructionCount);
234 }
235 }
236
237 VOID
238 NTAPI
239 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
240 {
241 STRING Header;
242
243 /* Fill out the header */
244 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
245 Header.Buffer = (PCHAR)State;
246
247 /* Get the version block */
248 KdpSysGetVersion(&State->u.GetVersion64);
249
250 /* Fill out the state */
251 State->ApiNumber = DbgKdGetVersionApi;
252 State->ReturnStatus = STATUS_SUCCESS;
253
254 /* Send the packet */
255 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
256 &Header,
257 NULL,
258 &KdpContext);
259 }
260
261 VOID
262 NTAPI
263 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
264 IN PSTRING Data,
265 IN PCONTEXT Context)
266 {
267 STRING Header;
268 ULONG Length = State->u.ReadMemory.TransferCount;
269 NTSTATUS Status = STATUS_SUCCESS;
270 ULONG64 TargetBaseAddress = State->u.ReadMemory.TargetBaseAddress;
271
272 /* Validate length */
273 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
274 {
275 /* Overflow, set it to maximum possible */
276 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
277 }
278
279 #if 0
280 if (!MmIsAddressValid((PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress))
281 {
282 KdpDprintf("Tried to read invalid address %p\n",
283 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress);
284 while (TRUE);
285 }
286 #endif
287
288 // HACK for x64, until KD stops sending bogus addresses to WinDbg
289 if (TargetBaseAddress < (ULONG_PTR)MM_LOWEST_SYSTEM_ADDRESS)
290 {
291 FrLdrDbgPrint("Trying to read memory at 0x%p\n", TargetBaseAddress);
292 // DPRINT1("Trying to read memory at 0x%p\n", TargetBaseAddress);
293 TargetBaseAddress = 0;
294 }
295
296 if (!TargetBaseAddress)
297 {
298 Length = 0;
299 Status = STATUS_UNSUCCESSFUL;
300 }
301 else
302 {
303 RtlCopyMemory(Data->Buffer,
304 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress,
305 Length);
306 }
307
308 /* Fill out the header */
309 Data->Length = Length;
310 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
311 Header.Buffer = (PCHAR)State;
312
313 /* Fill out the state */
314 State->ReturnStatus = Status;
315 State->u.ReadMemory.ActualBytesRead = Length;
316
317 /* Send the packet */
318 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
319 &Header,
320 Data,
321 &KdpContext);
322 }
323
324 VOID
325 NTAPI
326 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
327 IN PSTRING Data,
328 IN PCONTEXT Context)
329 {
330 /* FIXME: STUB */
331 KdpDprintf("KdpWriteVirtualMemory called for Address: %p Length %x\n",
332 (PVOID)(ULONG_PTR)State->u.ReadMemory.TargetBaseAddress,
333 State->u.ReadMemory.TransferCount);
334 while (TRUE);
335 }
336
337 VOID
338 NTAPI
339 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State,
340 IN PSTRING Data,
341 IN PCONTEXT Context)
342 {
343 STRING Header;
344
345 /* FIXME: STUB */
346 KdpDprintf("KdpWritePhysicalMemory called for Address %I64x Length: %x\n",
347 State->u.ReadMemory.TargetBaseAddress,
348 State->u.ReadMemory.TransferCount);
349
350 /* Setup an empty message, with failure */
351 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
352 Header.Buffer = (PCHAR)State;
353 Data->Length = 0;
354 State->ReturnStatus = STATUS_UNSUCCESSFUL;
355
356 /* Send it */
357 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
358 &Header,
359 Data,
360 &KdpContext);
361 }
362
363 VOID
364 NTAPI
365 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State,
366 IN PSTRING Data,
367 IN PCONTEXT Context)
368 {
369 STRING Header;
370
371 /* FIXME: STUB */
372 KdpDprintf("KdpWritePhysicalMemory called for Address %I64x Length: %x\n",
373 State->u.ReadMemory.TargetBaseAddress,
374 State->u.ReadMemory.TransferCount);
375
376 /* Setup an empty message, with failure */
377 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
378 Header.Buffer = (PCHAR)State;
379 Data->Length = 0;
380 State->ReturnStatus = STATUS_UNSUCCESSFUL;
381
382 /* Send it */
383 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
384 &Header,
385 Data,
386 &KdpContext);
387 }
388
389 VOID
390 NTAPI
391 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
392 IN PSTRING Data,
393 IN PCONTEXT Context)
394 {
395 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
396 STRING Header;
397 ULONG Length;
398
399 /* Setup the header */
400 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
401 Header.Buffer = (PCHAR)State;
402 ASSERT(Data->Length == 0);
403
404 /* Check the length requested */
405 Length = ReadMemory->TransferCount;
406 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
407 {
408 /* Use maximum allowed */
409 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
410 }
411
412 /* Call the internal routine */
413 State->ReturnStatus = KdpSysReadControlSpace(State->Processor,
414 ReadMemory->TargetBaseAddress,
415 Data->Buffer,
416 Length,
417 &Length);
418
419 /* Return the actual length read */
420 Data->Length = ReadMemory->ActualBytesRead = Length;
421
422 /* Send the reply */
423 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
424 &Header,
425 Data,
426 &KdpContext);
427 }
428
429 VOID
430 NTAPI
431 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
432 IN PSTRING Data,
433 IN PCONTEXT Context)
434 {
435 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
436 STRING Header;
437 ULONG Length;
438
439 /* Setup the header */
440 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
441 Header.Buffer = (PCHAR)State;
442
443 /* Call the internal routine */
444 State->ReturnStatus = KdpSysWriteControlSpace(State->Processor,
445 WriteMemory->TargetBaseAddress,
446 Data->Buffer,
447 Data->Length,
448 &Length);
449
450 /* Return the length written */
451 WriteMemory->ActualBytesWritten = Length;
452
453 /* Send the reply */
454 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
455 &Header,
456 Data,
457 &KdpContext);
458 }
459
460 VOID
461 NTAPI
462 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
463 IN PSTRING Data,
464 IN PCONTEXT Context)
465 {
466 STRING Header;
467 PVOID ControlStart;
468
469 /* Setup the header */
470 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
471 Header.Buffer = (PCHAR)State;
472 ASSERT(Data->Length == 0);
473
474 /* Make sure that this is a valid request */
475 if (State->Processor < KeNumberProcessors)
476 {
477 /* Check if the request is for this CPU */
478 if (State->Processor == KeGetCurrentPrcb()->Number)
479 {
480 /* We're just copying our own context */
481 ControlStart = Context;
482 }
483 else
484 {
485 /* SMP not yet handled */
486 KdpDprintf("SMP UNHANDLED\n");
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 KdpDprintf("SMP UNHANDLED\n");
538 ControlStart = NULL;
539 while (TRUE);
540 }
541
542 /* Copy the memory */
543 RtlCopyMemory(ControlStart, Data->Buffer, sizeof(CONTEXT));
544
545 /* Finish up */
546 State->ReturnStatus = STATUS_SUCCESS;
547 }
548 else
549 {
550 /* Invalid request */
551 State->ReturnStatus = STATUS_UNSUCCESSFUL;
552 }
553
554 /* Send the reply */
555 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
556 &Header,
557 Data,
558 &KdpContext);
559 }
560
561 VOID
562 NTAPI
563 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)
564 {
565 /* Crash with the special code */
566 KeBugCheck(MANUALLY_INITIATED_CRASH);
567 }
568
569 VOID
570 NTAPI
571 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
572 IN PSTRING Data,
573 IN PCONTEXT Context)
574 {
575 STRING Header;
576 PDBGKD_READ_WRITE_MSR ReadMsr = &State->u.ReadWriteMsr;
577 LARGE_INTEGER MsrValue;
578
579 /* Setup the header */
580 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
581 Header.Buffer = (PCHAR)State;
582 ASSERT(Data->Length == 0);
583
584 /* Call the internal routine */
585 State->ReturnStatus = KdpSysReadMsr(ReadMsr->Msr,
586 &MsrValue);
587
588 /* Return the data */
589 ReadMsr->DataValueLow = MsrValue.LowPart;
590 ReadMsr->DataValueHigh = MsrValue.HighPart;
591
592 /* Send the reply */
593 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
594 &Header,
595 NULL,
596 &KdpContext);
597 }
598
599 VOID
600 NTAPI
601 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
602 IN PSTRING Data,
603 IN PCONTEXT Context)
604 {
605 STRING Header;
606 PDBGKD_READ_WRITE_MSR WriteMsr = &State->u.ReadWriteMsr;
607 LARGE_INTEGER MsrValue;
608
609 /* Setup the header */
610 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
611 Header.Buffer = (PCHAR)State;
612 ASSERT(Data->Length == 0);
613
614 /* Call the internal routine */
615 MsrValue.LowPart = WriteMsr->DataValueLow;
616 MsrValue.HighPart = WriteMsr->DataValueHigh;
617 State->ReturnStatus = KdpSysWriteMsr(WriteMsr->Msr,
618 &MsrValue);
619
620 /* Send the reply */
621 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
622 &Header,
623 NULL,
624 &KdpContext);
625 }
626
627 VOID
628 NTAPI
629 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
630 IN PSTRING Data,
631 IN PCONTEXT Context)
632 {
633 STRING Header;
634 PDBGKD_GET_SET_BUS_DATA GetBusData = &State->u.GetSetBusData;
635 ULONG Length;
636
637 /* Setup the header */
638 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
639 Header.Buffer = (PCHAR)State;
640 ASSERT(Data->Length == 0);
641
642 /* Check the length requested */
643 Length = GetBusData->Length;
644 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
645 {
646 /* Use maximum allowed */
647 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
648 }
649
650 /* Call the internal routine */
651 State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType,
652 GetBusData->BusNumber,
653 GetBusData->SlotNumber,
654 Data->Buffer,
655 GetBusData->Offset,
656 Length,
657 &Length);
658
659 /* Return the actual length read */
660 Data->Length = GetBusData->Length = Length;
661
662 /* Send the reply */
663 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
664 &Header,
665 Data,
666 &KdpContext);
667 }
668
669 VOID
670 NTAPI
671 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
672 IN PSTRING Data,
673 IN PCONTEXT Context)
674 {
675 STRING Header;
676 PDBGKD_GET_SET_BUS_DATA SetBusData = &State->u.GetSetBusData;
677 ULONG Length;
678
679 /* Setup the header */
680 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
681 Header.Buffer = (PCHAR)State;
682
683 /* Call the internal routine */
684 State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType,
685 SetBusData->BusNumber,
686 SetBusData->SlotNumber,
687 Data->Buffer,
688 SetBusData->Offset,
689 SetBusData->Length,
690 &Length);
691
692 /* Return the actual length written */
693 SetBusData->Length = Length;
694
695 /* Send the reply */
696 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
697 &Header,
698 Data,
699 &KdpContext);
700 }
701
702 VOID
703 NTAPI
704 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
705 IN PSTRING Data,
706 IN PCONTEXT Context)
707 {
708 STRING Header;
709 PDBGKD_READ_WRITE_IO64 ReadIo = &State->u.ReadWriteIo;
710
711 /* Setup the header */
712 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
713 Header.Buffer = (PCHAR)State;
714 ASSERT(Data->Length == 0);
715
716 /*
717 * Clear the value so 1 or 2 byte reads
718 * don't leave the higher bits unmodified
719 */
720 ReadIo->DataValue = 0;
721
722 /* Call the internal routine */
723 State->ReturnStatus = KdpSysReadIoSpace(Isa,
724 0,
725 1,
726 ReadIo->IoAddress,
727 &ReadIo->DataValue,
728 ReadIo->DataSize,
729 &ReadIo->DataSize);
730
731 /* Send the reply */
732 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
733 &Header,
734 NULL,
735 &KdpContext);
736 }
737
738 VOID
739 NTAPI
740 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
741 IN PSTRING Data,
742 IN PCONTEXT Context)
743 {
744 STRING Header;
745 PDBGKD_READ_WRITE_IO64 WriteIo = &State->u.ReadWriteIo;
746
747 /* Setup the header */
748 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
749 Header.Buffer = (PCHAR)State;
750 ASSERT(Data->Length == 0);
751
752 /* Call the internal routine */
753 State->ReturnStatus = KdpSysWriteIoSpace(Isa,
754 0,
755 1,
756 WriteIo->IoAddress,
757 &WriteIo->DataValue,
758 WriteIo->DataSize,
759 &WriteIo->DataSize);
760
761 /* Send the reply */
762 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
763 &Header,
764 NULL,
765 &KdpContext);
766 }
767
768 VOID
769 NTAPI
770 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
771 IN PSTRING Data,
772 IN PCONTEXT Context)
773 {
774 STRING Header;
775 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended = &State->u.
776 ReadWriteIoExtended;
777
778 /* Setup the header */
779 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
780 Header.Buffer = (PCHAR)State;
781 ASSERT(Data->Length == 0);
782
783 /*
784 * Clear the value so 1 or 2 byte reads
785 * don't leave the higher bits unmodified
786 */
787 ReadIoExtended->DataValue = 0;
788
789 /* Call the internal routine */
790 State->ReturnStatus = KdpSysReadIoSpace(ReadIoExtended->InterfaceType,
791 ReadIoExtended->BusNumber,
792 ReadIoExtended->AddressSpace,
793 ReadIoExtended->IoAddress,
794 &ReadIoExtended->DataValue,
795 ReadIoExtended->DataSize,
796 &ReadIoExtended->DataSize);
797
798 /* Send the reply */
799 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
800 &Header,
801 NULL,
802 &KdpContext);
803 }
804
805 VOID
806 NTAPI
807 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
808 IN PSTRING Data,
809 IN PCONTEXT Context)
810 {
811 STRING Header;
812 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended = &State->u.
813 ReadWriteIoExtended;
814
815 /* Setup the header */
816 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
817 Header.Buffer = (PCHAR)State;
818 ASSERT(Data->Length == 0);
819
820 /* Call the internal routine */
821 State->ReturnStatus = KdpSysReadIoSpace(WriteIoExtended->InterfaceType,
822 WriteIoExtended->BusNumber,
823 WriteIoExtended->AddressSpace,
824 WriteIoExtended->IoAddress,
825 &WriteIoExtended->DataValue,
826 WriteIoExtended->DataSize,
827 &WriteIoExtended->DataSize);
828
829 /* Send the reply */
830 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
831 &Header,
832 NULL,
833 &KdpContext);
834 }
835
836 VOID
837 NTAPI
838 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State)
839 {
840 STRING Header;
841
842 /* Setup the header */
843 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
844 Header.Buffer = (PCHAR)State;
845
846 /* Call the internal routine */
847 State->ReturnStatus = KdpSysCheckLowMemory(0x4);
848
849 /* Send the reply */
850 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
851 &Header,
852 NULL,
853 &KdpContext);
854 }
855
856 KCONTINUE_STATUS
857 NTAPI
858 KdpSendWaitContinue(IN ULONG PacketType,
859 IN PSTRING SendHeader,
860 IN PSTRING SendData OPTIONAL,
861 IN OUT PCONTEXT Context)
862 {
863 STRING Data, Header;
864 DBGKD_MANIPULATE_STATE64 ManipulateState;
865 ULONG Length;
866 KDSTATUS RecvCode;
867
868 /* Setup the Manipulate State structure */
869 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
870 Header.Buffer = (PCHAR)&ManipulateState;
871 Data.MaximumLength = sizeof(KdpMessageBuffer);
872 Data.Buffer = KdpMessageBuffer;
873 //KdpContextSent = FALSE;
874
875 SendPacket:
876 /* Send the Packet */
877 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
878
879 /* If the debugger isn't present anymore, just return success */
880 if (KdDebuggerNotPresent) return ContinueSuccess;
881
882 /* Main processing Loop */
883 for (;;)
884 {
885 /* Receive Loop */
886 do
887 {
888 /* Wait to get a reply to our packet */
889 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
890 &Header,
891 &Data,
892 &Length,
893 &KdpContext);
894
895 /* If we got a resend request, do it */
896 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
897 } while (RecvCode == KdPacketTimedOut);
898
899 /* Now check what API we got */
900 switch (ManipulateState.ApiNumber)
901 {
902 case DbgKdReadVirtualMemoryApi:
903
904 /* Read virtual memory */
905 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
906 break;
907
908 case DbgKdWriteVirtualMemoryApi:
909
910 /* Write virtual memory */
911 KdpWriteVirtualMemory(&ManipulateState, &Data, Context);
912 break;
913
914 case DbgKdGetContextApi:
915
916 /* Get the current context */
917 KdpGetContext(&ManipulateState, &Data, Context);
918 break;
919
920 case DbgKdSetContextApi:
921
922 /* Set a new context */
923 KdpSetContext(&ManipulateState, &Data, Context);
924 break;
925
926 case DbgKdWriteBreakPointApi:
927
928 /* Write the breakpoint */
929 KdpWriteBreakpoint(&ManipulateState, &Data, Context);
930 break;
931
932 case DbgKdRestoreBreakPointApi:
933
934 /* Restore the breakpoint */
935 KdpRestoreBreakpoint(&ManipulateState, &Data, Context);
936 break;
937
938 case DbgKdContinueApi:
939
940 /* Simply continue */
941 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);
942
943 case DbgKdReadControlSpaceApi:
944
945 /* Read control space */
946 KdpReadControlSpace(&ManipulateState, &Data, Context);
947 break;
948
949 case DbgKdWriteControlSpaceApi:
950
951 /* Write control space */
952 KdpWriteControlSpace(&ManipulateState, &Data, Context);
953 break;
954
955 case DbgKdReadIoSpaceApi:
956
957 /* Read I/O Space */
958 KdpReadIoSpace(&ManipulateState, &Data, Context);
959 break;
960
961 case DbgKdWriteIoSpaceApi:
962
963 /* Write I/O Space */
964 KdpWriteIoSpace(&ManipulateState, &Data, Context);
965 break;
966
967 case DbgKdRebootApi:
968
969 /* Reboot the system */
970 HalReturnToFirmware(HalRebootRoutine);
971 break;
972
973 case DbgKdContinueApi2:
974
975 /* Check if caller reports success */
976 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))
977 {
978 /* Update the state */
979 KdpGetStateChange(&ManipulateState, Context);
980 return ContinueSuccess;
981 }
982 else
983 {
984 /* Return an error */
985 return ContinueError;
986 }
987
988 case DbgKdReadPhysicalMemoryApi:
989
990 /* Read physical memory */
991 KdpReadPhysicalmemory(&ManipulateState, &Data, Context);
992 break;
993
994 case DbgKdWritePhysicalMemoryApi:
995
996 /* Write physical memory */
997 KdpWritePhysicalmemory(&ManipulateState, &Data, Context);
998 break;
999
1000 case DbgKdQuerySpecialCallsApi:
1001
1002 /* FIXME: TODO */
1003 KdpDprintf("DbgKdQuerySpecialCallsApi called\n");
1004 while (TRUE);
1005 break;
1006
1007 case DbgKdSetSpecialCallApi:
1008
1009 /* FIXME: TODO */
1010 KdpDprintf("DbgKdSetSpecialCallApi called\n");
1011 while (TRUE);
1012 break;
1013
1014 case DbgKdClearSpecialCallsApi:
1015
1016 /* FIXME: TODO */
1017 KdpDprintf("DbgKdClearSpecialCallsApi called\n");
1018 while (TRUE);
1019 break;
1020
1021 case DbgKdSetInternalBreakPointApi:
1022
1023 /* FIXME: TODO */
1024 KdpDprintf("DbgKdSetInternalBreakPointApi called\n");
1025 while (TRUE);
1026 break;
1027
1028 case DbgKdGetInternalBreakPointApi:
1029
1030 /* FIXME: TODO */
1031 KdpDprintf("DbgKdGetInternalBreakPointApi called\n");
1032 while (TRUE);
1033 break;
1034
1035 case DbgKdReadIoSpaceExtendedApi:
1036
1037 /* Read I/O Space */
1038 KdpReadIoSpaceExtended(&ManipulateState, &Data, Context);
1039 break;
1040
1041 case DbgKdWriteIoSpaceExtendedApi:
1042
1043 /* Write I/O Space */
1044 KdpWriteIoSpaceExtended(&ManipulateState, &Data, Context);
1045 break;
1046
1047 case DbgKdGetVersionApi:
1048
1049 /* Get version data */
1050 KdpGetVersion(&ManipulateState);
1051 break;
1052
1053 case DbgKdWriteBreakPointExApi:
1054
1055 /* Write the breakpoint and check if it failed */
1056 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState,
1057 &Data,
1058 Context)))
1059 {
1060 /* Return an error */
1061 return ContinueError;
1062 }
1063 break;
1064
1065 case DbgKdRestoreBreakPointExApi:
1066
1067 /* Restore the breakpoint */
1068 KdpRestoreBreakPointEx(&ManipulateState, &Data, Context);
1069 break;
1070
1071 case DbgKdCauseBugCheckApi:
1072
1073 /* Crash the system */
1074 KdpCauseBugCheck(&ManipulateState);
1075 break;
1076
1077 case DbgKdSwitchProcessor:
1078
1079 /* FIXME: TODO */
1080 KdpDprintf("DbgKdSwitchProcessor called\n");
1081 while (TRUE);
1082 break;
1083
1084 case DbgKdPageInApi:
1085
1086 /* FIXME: TODO */
1087 KdpDprintf("DbgKdPageInApi called\n");
1088 while (TRUE);
1089 break;
1090
1091 case DbgKdReadMachineSpecificRegister:
1092
1093 /* Read from the specified MSR */
1094 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context);
1095 break;
1096
1097 case DbgKdWriteMachineSpecificRegister:
1098
1099 /* Write to the specified MSR */
1100 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context);
1101 break;
1102
1103 case DbgKdSearchMemoryApi:
1104
1105 /* Search memory */
1106 KdpSearchMemory(&ManipulateState, &Data, Context);
1107 break;
1108
1109 case DbgKdGetBusDataApi:
1110
1111 /* Read from the bus */
1112 KdpGetBusData(&ManipulateState, &Data, Context);
1113 break;
1114
1115 case DbgKdSetBusDataApi:
1116
1117 /* Write to the bus */
1118 KdpSetBusData(&ManipulateState, &Data, Context);
1119 break;
1120
1121 case DbgKdCheckLowMemoryApi:
1122
1123 /* Check for memory corruption in the lower 4 GB */
1124 KdpCheckLowMemory(&ManipulateState);
1125 break;
1126
1127 case DbgKdClearAllInternalBreakpointsApi:
1128
1129 /* Just clear the counter */
1130 KdpNumInternalBreakpoints = 0;
1131 break;
1132
1133 case DbgKdFillMemoryApi:
1134
1135 /* Fill memory */
1136 KdpFillMemory(&ManipulateState, &Data, Context);
1137 break;
1138
1139 case DbgKdQueryMemoryApi:
1140
1141 /* Query memory */
1142 KdpQueryMemory(&ManipulateState, Context);
1143 break;
1144
1145 case DbgKdSwitchPartition:
1146
1147 /* FIXME: TODO */
1148 KdpDprintf("DbgKdSwitchPartition called\n");
1149 while (TRUE);
1150 break;
1151
1152 /* Unsupported Message */
1153 default:
1154
1155 /* Setup an empty message, with failure */
1156 KdpDprintf("Received Unhandled API %lx\n", ManipulateState.ApiNumber);
1157 Data.Length = 0;
1158 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
1159
1160 /* Send it */
1161 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1162 &Header,
1163 &Data,
1164 &KdpContext);
1165 break;
1166 }
1167 }
1168 }
1169
1170 BOOLEAN
1171 NTAPI
1172 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
1173 IN PKD_SYMBOLS_INFO SymbolInfo,
1174 IN BOOLEAN Unload,
1175 IN OUT PCONTEXT Context)
1176 {
1177 PSTRING ExtraData;
1178 STRING Data, Header;
1179 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
1180 KCONTINUE_STATUS Status;
1181
1182 /* Start wait loop */
1183 do
1184 {
1185 /* Build the architecture common parts of the message */
1186 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
1187 Context,
1188 &WaitStateChange);
1189
1190 /* Now finish creating the structure */
1191 KdpSetContextState(&WaitStateChange, Context);
1192
1193 /* Fill out load data */
1194 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
1195 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll;
1196 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
1197 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
1198 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
1199
1200 /* Check if we have a symbol name */
1201 if (PathName)
1202 {
1203 /* Setup the information */
1204 WaitStateChange.u.LoadSymbols.PathNameLength = PathName->Length;
1205 RtlCopyMemory(KdpPathBuffer, PathName->Buffer, PathName->Length);
1206 Data.Buffer = KdpPathBuffer;
1207 Data.Length = WaitStateChange.u.LoadSymbols.PathNameLength;
1208 ExtraData = &Data;
1209 }
1210 else
1211 {
1212 /* No name */
1213 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
1214 ExtraData = NULL;
1215 }
1216
1217 /* Setup the header */
1218 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64);
1219 Header.Buffer = (PCHAR)&WaitStateChange;
1220
1221 /* Send the packet */
1222 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1223 &Header,
1224 ExtraData,
1225 Context);
1226 } while (Status == ContinueProcessorReselected);
1227
1228 /* Return status */
1229 return Status;
1230 }
1231
1232 BOOLEAN
1233 NTAPI
1234 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
1235 IN OUT PCONTEXT Context,
1236 IN BOOLEAN SecondChanceException)
1237 {
1238 STRING Header, Data;
1239 DBGKD_WAIT_STATE_CHANGE64 WaitStateChange;
1240 KCONTINUE_STATUS Status;
1241
1242 /* Start report loop */
1243 do
1244 {
1245 /* Build the architecture common parts of the message */
1246 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
1247
1248 /* Copy the Exception Record and set First Chance flag */
1249 CopyExceptionRecord(ExceptionRecord,
1250 &WaitStateChange.u.Exception.ExceptionRecord);
1251 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
1252
1253 /* Now finish creating the structure */
1254 KdpSetContextState(&WaitStateChange, Context);
1255
1256 /* Setup the actual header to send to KD */
1257 Header.Length = sizeof(DBGKD_WAIT_STATE_CHANGE64) - sizeof(CONTEXT);
1258 Header.Buffer = (PCHAR)&WaitStateChange;
1259
1260 /* Setup the trace data */
1261 DumpTraceData(&Data);
1262
1263 /* Send State Change packet and wait for a reply */
1264 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1265 &Header,
1266 &Data,
1267 Context);
1268 } while (Status == ContinueProcessorReselected);
1269
1270 /* Return */
1271 return Status;
1272 }
1273
1274 VOID
1275 NTAPI
1276 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1277 IN PVOID DeferredContext,
1278 IN PVOID SystemArgument1,
1279 IN PVOID SystemArgument2)
1280 {
1281 LONG OldSlip, NewSlip, PendingSlip;
1282
1283 /* Get the current pending slip */
1284 PendingSlip = KdpTimeSlipPending;
1285 do
1286 {
1287 /* Save the old value and either disable or enable it now. */
1288 OldSlip = PendingSlip;
1289 NewSlip = OldSlip > 1 ? 1 : 0;
1290
1291 /* Try to change the value */
1292 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1293 NewSlip,
1294 OldSlip) != OldSlip);
1295
1296 /* If the New Slip value is 1, then do the Time Slipping */
1297 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1298 }
1299
1300 VOID
1301 NTAPI
1302 KdpTimeSlipWork(IN PVOID Context)
1303 {
1304 KIRQL OldIrql;
1305 LARGE_INTEGER DueTime;
1306
1307 /* Update the System time from the CMOS */
1308 ExAcquireTimeRefreshLock(FALSE);
1309 ExUpdateSystemTimeFromCmos(FALSE, 0);
1310 ExReleaseTimeRefreshLock();
1311
1312 /* Check if we have a registered Time Slip Event and signal it */
1313 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1314 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1315 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1316
1317 /* Delay the DPC until it runs next time */
1318 DueTime.QuadPart = -1800000000;
1319 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1320 }
1321
1322 BOOLEAN
1323 NTAPI
1324 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
1325 IN OUT PCONTEXT ContextRecord,
1326 IN BOOLEAN SecondChanceException)
1327 {
1328 BOOLEAN Status;
1329
1330 /* Save the port data */
1331 KdSave(FALSE);
1332
1333 /* Report a state change */
1334 Status = KdpReportExceptionStateChange(ExceptionRecord,
1335 ContextRecord,
1336 SecondChanceException);
1337
1338 /* Restore the port data and return */
1339 KdRestore(FALSE);
1340 return Status;
1341 }
1342
1343 LARGE_INTEGER
1344 NTAPI
1345 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1346 {
1347 LARGE_INTEGER Null = {{0}};
1348
1349 /* Check if interrupts were disabled */
1350 if (!KeGetTrapFrameInterruptState(TrapFrame))
1351 {
1352 /* Nothing to return */
1353 return Null;
1354 }
1355
1356 /* Otherwise, do the call */
1357 return KeQueryPerformanceCounter(NULL);
1358 }
1359
1360 BOOLEAN
1361 NTAPI
1362 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1363 IN PKEXCEPTION_FRAME ExceptionFrame)
1364 {
1365 BOOLEAN Entered;
1366
1367 /* Check if we have a trap frame */
1368 if (TrapFrame)
1369 {
1370 /* Calculate the time difference for the enter */
1371 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1372 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1373 KdTimerStart.QuadPart;
1374 }
1375 else
1376 {
1377 /* No trap frame, so can't calculate */
1378 KdTimerStop.QuadPart = 0;
1379 }
1380
1381 /* Save the current IRQL */
1382 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1383
1384 /* Freeze all CPUs */
1385 Entered = KeFreezeExecution(TrapFrame, ExceptionFrame);
1386
1387 /* Lock the port, save the state and set debugger entered */
1388 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1389 KdSave(FALSE);
1390 KdEnteredDebugger = TRUE;
1391
1392 /* Check freeze flag */
1393 if (KiFreezeFlag & 1)
1394 {
1395 /* Print out errror */
1396 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1397 }
1398
1399 /* Check processor state */
1400 if (KiFreezeFlag & 2)
1401 {
1402 /* Print out errror */
1403 KdpDprintf("Some processors not frozen in debugger!\n");
1404 }
1405
1406 /* Make sure we acquired the port */
1407 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n");
1408
1409 /* Return enter state */
1410 return Entered;
1411 }
1412
1413 VOID
1414 NTAPI
1415 KdExitDebugger(IN BOOLEAN Entered)
1416 {
1417 ULONG TimeSlip;
1418
1419 /* Restore the state and unlock the port */
1420 KdRestore(FALSE);
1421 if (KdpPortLocked) KdpPortUnlock();
1422
1423 /* Unfreeze the CPUs */
1424 KeThawExecution(Entered);
1425
1426 /* Compare time with the one from KdEnterDebugger */
1427 if (!KdTimerStop.QuadPart)
1428 {
1429 /* We didn't get a trap frame earlier in so never got the time */
1430 KdTimerStart = KdTimerStop;
1431 }
1432 else
1433 {
1434 /* Query the timer */
1435 KdTimerStart = KeQueryPerformanceCounter(NULL);
1436 }
1437
1438 /* Check if a Time Slip was on queue */
1439 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1440 if (TimeSlip == 1)
1441 {
1442 /* Queue a DPC for the time slip */
1443 InterlockedIncrement(&KdpTimeSlipPending);
1444 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL);
1445 }
1446 }
1447
1448 NTSTATUS
1449 NTAPI
1450 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)
1451 {
1452 KIRQL OldIrql;
1453
1454 #if defined(__GNUC__)
1455 /* Make gcc happy */
1456 OldIrql = PASSIVE_LEVEL;
1457 #endif
1458
1459 /* Check if we need to acquire the lock */
1460 if (NeedLock)
1461 {
1462 /* Lock the port */
1463 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1464 KdpPortLock();
1465 }
1466
1467 /* Check if we're not disabled */
1468 if (!KdDisableCount)
1469 {
1470 /* Check if we had locked the port before */
1471 if (NeedLock)
1472 {
1473 /* Do the unlock */
1474 KeLowerIrql(OldIrql);
1475 KdpPortUnlock();
1476 }
1477
1478 /* Fail: We're already enabled */
1479 return STATUS_INVALID_PARAMETER;
1480 }
1481
1482 /* Decrease the disable count */
1483 if (!(--KdDisableCount))
1484 {
1485 /* We're now enabled again! Were we enabled before, too? */
1486 if (KdPreviouslyEnabled)
1487 {
1488 /* Reinitialize the Debugger */
1489 KdInitSystem(0, NULL) ;
1490 KdpRestoreAllBreakpoints();
1491 }
1492 }
1493
1494 /* Check if we had locked the port before */
1495 if (NeedLock)
1496 {
1497 /* Yes, now unlock it */
1498 KeLowerIrql(OldIrql);
1499 KdpPortUnlock();
1500 }
1501
1502 /* We're done */
1503 return STATUS_SUCCESS;
1504 }
1505
1506 /* PUBLIC FUNCTIONS **********************************************************/
1507
1508 /*
1509 * @implemented
1510 */
1511 NTSTATUS
1512 NTAPI
1513 KdEnableDebugger(VOID)
1514 {
1515 /* Use the internal routine */
1516 KdpDprintf("KdEnableDebugger called\n");
1517 while (TRUE);
1518 return KdEnableDebuggerWithLock(TRUE);
1519 }
1520
1521 /*
1522 * @unimplemented
1523 */
1524 NTSTATUS
1525 NTAPI
1526 KdSystemDebugControl(IN SYSDBG_COMMAND Command,
1527 IN PVOID InputBuffer,
1528 IN ULONG InputBufferLength,
1529 OUT PVOID OutputBuffer,
1530 IN ULONG OutputBufferLength,
1531 IN OUT PULONG ReturnLength,
1532 IN KPROCESSOR_MODE PreviousMode)
1533 {
1534 /* HACK */
1535 return STATUS_SUCCESS;
1536 }
1537
1538 /*
1539 * @unimplemented
1540 */
1541 NTSTATUS
1542 NTAPI
1543 KdChangeOption(IN KD_OPTION Option,
1544 IN ULONG InBufferBytes OPTIONAL,
1545 IN PVOID InBuffer,
1546 IN ULONG OutBufferBytes OPTIONAL,
1547 OUT PVOID OutBuffer,
1548 OUT PULONG OutBufferNeeded OPTIONAL)
1549 {
1550 /* HACK */
1551 return STATUS_SUCCESS;
1552 }
1553
1554 /*
1555 * @unimplemented
1556 */
1557 NTSTATUS
1558 NTAPI
1559 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
1560 {
1561 /* HACK */
1562 return STATUS_SUCCESS;
1563 }
1564
1565 /*
1566 * @unimplemented
1567 */
1568 NTSTATUS
1569 NTAPI
1570 KdDisableDebugger(VOID)
1571 {
1572 /* HACK */
1573 return STATUS_SUCCESS;
1574 }
1575
1576 /*
1577 * @unimplemented
1578 */
1579 BOOLEAN
1580 NTAPI
1581 KdRefreshDebuggerNotPresent(VOID)
1582 {
1583 /* HACK */
1584 return KdDebuggerNotPresent;
1585 }
1586
1587 NTSTATUS
1588 NTAPI
1589 NtQueryDebugFilterState(ULONG ComponentId,
1590 ULONG Level)
1591 {
1592 /* HACK */
1593 return STATUS_SUCCESS;
1594 }
1595
1596 NTSTATUS
1597 NTAPI
1598 NtSetDebugFilterState(ULONG ComponentId,
1599 ULONG Level,
1600 BOOLEAN State)
1601 {
1602 /* HACK */
1603 return STATUS_SUCCESS;
1604 }
1605