[DRWTSN32] Print some extra exception info
[reactos.git] / 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 * Stefan Ginsberg (stefan.ginsberg@reactos.org)
8 */
9
10 /* INCLUDES ******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* PRIVATE FUNCTIONS *********************************************************/
17
18 VOID
19 NTAPI
20 KdpMoveMemory(IN PVOID Destination,
21 IN PVOID Source,
22 IN SIZE_T Length)
23 {
24 PCHAR DestinationBytes, SourceBytes;
25
26 /* Copy the buffers 1 byte at a time */
27 DestinationBytes = Destination;
28 SourceBytes = Source;
29 while (Length--) *DestinationBytes++ = *SourceBytes++;
30 }
31
32 VOID
33 NTAPI
34 KdpZeroMemory(IN PVOID Destination,
35 IN SIZE_T Length)
36 {
37 PCHAR DestinationBytes;
38
39 /* Zero the buffer 1 byte at a time */
40 DestinationBytes = Destination;
41 while (Length--) *DestinationBytes++ = 0;
42 }
43
44 NTSTATUS
45 NTAPI
46 KdpCopyMemoryChunks(IN ULONG64 Address,
47 IN PVOID Buffer,
48 IN ULONG TotalSize,
49 IN ULONG ChunkSize,
50 IN ULONG Flags,
51 OUT PULONG ActualSize OPTIONAL)
52 {
53 NTSTATUS Status;
54 ULONG RemainingLength, CopyChunk;
55
56 /* Check if we didn't get a chunk size or if it is too big */
57 if (ChunkSize == 0)
58 {
59 /* Default to 4 byte chunks */
60 ChunkSize = 4;
61 }
62 else if (ChunkSize > MMDBG_COPY_MAX_SIZE)
63 {
64 /* Normalize to maximum size */
65 ChunkSize = MMDBG_COPY_MAX_SIZE;
66 }
67
68 /* Copy the whole range in aligned chunks */
69 RemainingLength = TotalSize;
70 CopyChunk = 1;
71 while (RemainingLength > 0)
72 {
73 /*
74 * Determine the best chunk size for this round.
75 * The ideal size is aligned, isn't larger than the
76 * the remaining length and respects the chunk limit.
77 */
78 while (((CopyChunk * 2) <= RemainingLength) &&
79 (CopyChunk < ChunkSize) &&
80 ((Address & ((CopyChunk * 2) - 1)) == 0))
81 {
82 /* Increase it */
83 CopyChunk *= 2;
84 }
85
86 /*
87 * The chunk size can be larger than the remaining size if this isn't
88 * the first round, so check if we need to shrink it back
89 */
90 while (CopyChunk > RemainingLength)
91 {
92 /* Shrink it */
93 CopyChunk /= 2;
94 }
95
96 /* Do the copy */
97 Status = MmDbgCopyMemory(Address,
98 Buffer,
99 CopyChunk,
100 Flags);
101 if (!NT_SUCCESS(Status))
102 {
103 /* Copy failed, break out */
104 break;
105 }
106
107 /* Update pointers and length for the next run */
108 Address = Address + CopyChunk;
109 Buffer = (PVOID)((ULONG_PTR)Buffer + CopyChunk);
110 RemainingLength = RemainingLength - CopyChunk;
111 }
112
113 /*
114 * We may have modified executable code, flush the instruction cache
115 */
116 KeSweepICache((PVOID)(ULONG_PTR)Address, TotalSize);
117
118 /*
119 * Return the size we managed to copy
120 * and return success if we could copy the whole range
121 */
122 if (ActualSize) *ActualSize = TotalSize - RemainingLength;
123 return RemainingLength == 0 ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
124 }
125
126 VOID
127 NTAPI
128 KdpQueryMemory(IN PDBGKD_MANIPULATE_STATE64 State,
129 IN PCONTEXT Context)
130 {
131 PDBGKD_QUERY_MEMORY Memory = &State->u.QueryMemory;
132 STRING Header;
133 NTSTATUS Status = STATUS_SUCCESS;
134
135 /* Validate the address space */
136 if (Memory->AddressSpace == DBGKD_QUERY_MEMORY_VIRTUAL)
137 {
138 /* Check if this is process memory */
139 if ((PVOID)(ULONG_PTR)Memory->Address < MmHighestUserAddress)
140 {
141 /* It is */
142 Memory->AddressSpace = DBGKD_QUERY_MEMORY_PROCESS;
143 }
144 else
145 {
146 /* Check if it's session space */
147 if (MmIsSessionAddress((PVOID)(ULONG_PTR)Memory->Address))
148 {
149 /* It is */
150 Memory->AddressSpace = DBGKD_QUERY_MEMORY_SESSION;
151 }
152 else
153 {
154 /* Not session space but some other kernel memory */
155 Memory->AddressSpace = DBGKD_QUERY_MEMORY_KERNEL;
156 }
157 }
158
159 /* Set flags */
160 Memory->Flags = DBGKD_QUERY_MEMORY_READ |
161 DBGKD_QUERY_MEMORY_WRITE |
162 DBGKD_QUERY_MEMORY_EXECUTE;
163 }
164 else
165 {
166 /* Invalid */
167 Status = STATUS_INVALID_PARAMETER;
168 }
169
170 /* Return structure */
171 State->ReturnStatus = Status;
172 Memory->Reserved = 0;
173
174 /* Build header */
175 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
176 Header.Buffer = (PCHAR)State;
177
178 /* Send the packet */
179 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
180 &Header,
181 NULL,
182 &KdpContext);
183 }
184
185 VOID
186 NTAPI
187 KdpSearchMemory(IN PDBGKD_MANIPULATE_STATE64 State,
188 IN PSTRING Data,
189 IN PCONTEXT Context)
190 {
191 //PDBGKD_SEARCH_MEMORY SearchMemory = &State->u.SearchMemory;
192 STRING Header;
193
194 /* TODO */
195 KdpDprintf("Memory Search support is unimplemented!\n");
196
197 /* Send a failure packet */
198 State->ReturnStatus = STATUS_UNSUCCESSFUL;
199 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
200 Header.Buffer = (PCHAR)State;
201 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
202 &Header,
203 NULL,
204 &KdpContext);
205 }
206
207 VOID
208 NTAPI
209 KdpFillMemory(IN PDBGKD_MANIPULATE_STATE64 State,
210 IN PSTRING Data,
211 IN PCONTEXT Context)
212 {
213 //PDBGKD_FILL_MEMORY FillMemory = &State->u.FillMemory;
214 STRING Header;
215
216 /* TODO */
217 KdpDprintf("Memory Fill support is unimplemented!\n");
218
219 /* Send a failure packet */
220 State->ReturnStatus = STATUS_UNSUCCESSFUL;
221 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
222 Header.Buffer = (PCHAR)State;
223 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
224 &Header,
225 NULL,
226 &KdpContext);
227 }
228
229 VOID
230 NTAPI
231 KdpWriteBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
232 IN PSTRING Data,
233 IN PCONTEXT Context)
234 {
235 PDBGKD_WRITE_BREAKPOINT64 Breakpoint = &State->u.WriteBreakPoint;
236 STRING Header;
237
238 /* Build header */
239 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
240 Header.Buffer = (PCHAR)State;
241 ASSERT(Data->Length == 0);
242
243 /* Create the breakpoint */
244 Breakpoint->BreakPointHandle =
245 KdpAddBreakpoint((PVOID)(ULONG_PTR)Breakpoint->BreakPointAddress);
246 if (!Breakpoint->BreakPointHandle)
247 {
248 /* We failed */
249 State->ReturnStatus = STATUS_UNSUCCESSFUL;
250 }
251 else
252 {
253 /* Success! */
254 State->ReturnStatus = STATUS_SUCCESS;
255 }
256
257 /* Send the packet */
258 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
259 &Header,
260 NULL,
261 &KdpContext);
262 }
263
264 VOID
265 NTAPI
266 KdpRestoreBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
267 IN PSTRING Data,
268 IN PCONTEXT Context)
269 {
270 PDBGKD_RESTORE_BREAKPOINT RestoreBp = &State->u.RestoreBreakPoint;
271 STRING Header;
272
273 /* Fill out the header */
274 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
275 Header.Buffer = (PCHAR)State;
276 ASSERT(Data->Length == 0);
277
278 /* Get the version block */
279 if (KdpDeleteBreakpoint(RestoreBp->BreakPointHandle))
280 {
281 /* We're all good */
282 State->ReturnStatus = STATUS_SUCCESS;
283 }
284 else
285 {
286 /* We failed */
287 State->ReturnStatus = STATUS_UNSUCCESSFUL;
288 }
289
290 /* Send the packet */
291 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
292 &Header,
293 NULL,
294 &KdpContext);
295 }
296
297 NTSTATUS
298 NTAPI
299 KdpWriteBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
300 IN PSTRING Data,
301 IN PCONTEXT Context)
302 {
303 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
304 STRING Header;
305
306 /* TODO */
307 KdpDprintf("Extended Breakpoint Write support is unimplemented!\n");
308
309 /* Send a failure packet */
310 State->ReturnStatus = STATUS_UNSUCCESSFUL;
311 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
312 Header.Buffer = (PCHAR)State;
313 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
314 &Header,
315 Data,
316 &KdpContext);
317 return STATUS_UNSUCCESSFUL;
318 }
319
320 VOID
321 NTAPI
322 KdpRestoreBreakPointEx(IN PDBGKD_MANIPULATE_STATE64 State,
323 IN PSTRING Data,
324 IN PCONTEXT Context)
325 {
326 //PDBGKD_BREAKPOINTEX = &State->u.BreakPointEx;
327 STRING Header;
328
329 /* TODO */
330 KdpDprintf("Extended Breakpoint Restore support is unimplemented!\n");
331
332 /* Send a failure packet */
333 State->ReturnStatus = STATUS_UNSUCCESSFUL;
334 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
335 Header.Buffer = (PCHAR)State;
336 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
337 &Header,
338 Data,
339 &KdpContext);
340 }
341
342 VOID
343 NTAPI
344 KdpWriteCustomBreakpoint(IN PDBGKD_MANIPULATE_STATE64 State,
345 IN PSTRING Data,
346 IN PCONTEXT Context)
347 {
348 //PDBGKD_WRITE_CUSTOM_BREAKPOINT = &State->u.WriteCustomBreakpoint;
349 STRING Header;
350
351 /* Not supported */
352 KdpDprintf("Custom Breakpoint Write is unimplemented\n");
353
354 /* Send a failure packet */
355 State->ReturnStatus = STATUS_UNSUCCESSFUL;
356 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
357 Header.Buffer = (PCHAR)State;
358 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
359 &Header,
360 NULL,
361 &KdpContext);
362 }
363
364 VOID
365 NTAPI
366 DumpTraceData(IN PSTRING TraceData)
367 {
368 /* Update the buffer */
369 TraceDataBuffer[0] = TraceDataBufferPosition;
370
371 /* Setup the trace data */
372 TraceData->Length = (USHORT)(TraceDataBufferPosition * sizeof(ULONG));
373 TraceData->Buffer = (PCHAR)TraceDataBuffer;
374
375 /* Reset the buffer location */
376 TraceDataBufferPosition = 1;
377 }
378
379 VOID
380 NTAPI
381 KdpSetCommonState(IN ULONG NewState,
382 IN PCONTEXT Context,
383 IN PDBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange)
384 {
385 ULONG InstructionCount;
386 BOOLEAN HadBreakpoints;
387
388 /* Setup common stuff available for all CPU architectures */
389 WaitStateChange->NewState = NewState;
390 WaitStateChange->ProcessorLevel = KeProcessorLevel;
391 WaitStateChange->Processor = (USHORT)KeGetCurrentPrcb()->Number;
392 WaitStateChange->NumberProcessors = (ULONG)KeNumberProcessors;
393 WaitStateChange->Thread = (ULONG64)(LONG_PTR)KeGetCurrentThread();
394 WaitStateChange->ProgramCounter = (ULONG64)(LONG_PTR)KeGetContextPc(Context);
395
396 /* Zero out the entire Control Report */
397 KdpZeroMemory(&WaitStateChange->AnyControlReport,
398 sizeof(DBGKD_ANY_CONTROL_REPORT));
399
400 /* Now copy the instruction stream and set the count */
401 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter,
402 &WaitStateChange->ControlReport.InstructionStream[0],
403 DBGKD_MAXSTREAM,
404 0,
405 MMDBG_COPY_UNSAFE,
406 &InstructionCount);
407 WaitStateChange->ControlReport.InstructionCount = (USHORT)InstructionCount;
408
409 /* Clear all the breakpoints in this region */
410 HadBreakpoints =
411 KdpDeleteBreakpointRange((PVOID)(ULONG_PTR)WaitStateChange->ProgramCounter,
412 (PVOID)((ULONG_PTR)WaitStateChange->ProgramCounter +
413 WaitStateChange->ControlReport.InstructionCount - 1));
414 if (HadBreakpoints)
415 {
416 /* Copy the instruction stream again, this time without breakpoints */
417 KdpCopyMemoryChunks((ULONG_PTR)WaitStateChange->ProgramCounter,
418 &WaitStateChange->ControlReport.InstructionStream[0],
419 InstructionCount,
420 0,
421 MMDBG_COPY_UNSAFE,
422 NULL);
423 }
424 }
425
426 VOID
427 NTAPI
428 KdpSysGetVersion(IN PDBGKD_GET_VERSION64 Version)
429 {
430 /* Copy the version block */
431 KdpMoveMemory(Version,
432 &KdVersionBlock,
433 sizeof(DBGKD_GET_VERSION64));
434 }
435
436 VOID
437 NTAPI
438 KdpGetVersion(IN PDBGKD_MANIPULATE_STATE64 State)
439 {
440 STRING Header;
441
442 /* Fill out the header */
443 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
444 Header.Buffer = (PCHAR)State;
445
446 /* Get the version block */
447 KdpSysGetVersion(&State->u.GetVersion64);
448
449 /* Fill out the state */
450 State->ApiNumber = DbgKdGetVersionApi;
451 State->ReturnStatus = STATUS_SUCCESS;
452
453 /* Send the packet */
454 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
455 &Header,
456 NULL,
457 &KdpContext);
458 }
459
460 VOID
461 NTAPI
462 KdpReadVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
463 IN PSTRING Data,
464 IN PCONTEXT Context)
465 {
466 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
467 STRING Header;
468 ULONG Length = ReadMemory->TransferCount;
469
470 /* Setup the header */
471 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
472 Header.Buffer = (PCHAR)State;
473 ASSERT(Data->Length == 0);
474
475 /* Validate length */
476 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
477 {
478 /* Overflow, set it to maximum possible */
479 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
480 }
481
482 /* Do the read */
483 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress,
484 Data->Buffer,
485 Length,
486 0,
487 MMDBG_COPY_UNSAFE,
488 &Length);
489
490 /* Return the actual length read */
491 ReadMemory->ActualBytesRead = Length;
492 Data->Length = (USHORT)Length;
493
494 /* Send the packet */
495 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
496 &Header,
497 Data,
498 &KdpContext);
499 }
500
501 VOID
502 NTAPI
503 KdpWriteVirtualMemory(IN PDBGKD_MANIPULATE_STATE64 State,
504 IN PSTRING Data,
505 IN PCONTEXT Context)
506 {
507 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
508 STRING Header;
509
510 /* Setup the header */
511 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
512 Header.Buffer = (PCHAR)State;
513
514 /* Do the write */
515 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress,
516 Data->Buffer,
517 Data->Length,
518 0,
519 MMDBG_COPY_UNSAFE |
520 MMDBG_COPY_WRITE,
521 &WriteMemory->ActualBytesWritten);
522
523 /* Send the packet */
524 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
525 &Header,
526 NULL,
527 &KdpContext);
528 }
529
530 VOID
531 NTAPI
532 KdpReadPhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State,
533 IN PSTRING Data,
534 IN PCONTEXT Context)
535 {
536 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
537 STRING Header;
538 ULONG Length = ReadMemory->TransferCount;
539 ULONG Flags, CacheFlags;
540
541 /* Setup the header */
542 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
543 Header.Buffer = (PCHAR)State;
544 ASSERT(Data->Length == 0);
545
546 /* Validate length */
547 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
548 {
549 /* Overflow, set it to maximum possible */
550 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
551 }
552
553 /* Start with the default flags */
554 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_PHYSICAL;
555
556 /* Get the caching flags and check if a type is specified */
557 CacheFlags = ReadMemory->ActualBytesRead;
558 if (CacheFlags == DBGKD_CACHING_CACHED)
559 {
560 /* Cached */
561 Flags |= MMDBG_COPY_CACHED;
562 }
563 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
564 {
565 /* Uncached */
566 Flags |= MMDBG_COPY_UNCACHED;
567 }
568 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED)
569 {
570 /* Write Combined */
571 Flags |= MMDBG_COPY_WRITE_COMBINED;
572 }
573
574 /* Do the read */
575 State->ReturnStatus = KdpCopyMemoryChunks(ReadMemory->TargetBaseAddress,
576 Data->Buffer,
577 Length,
578 0,
579 Flags,
580 &Length);
581
582 /* Return the actual length read */
583 ReadMemory->ActualBytesRead = Length;
584 Data->Length = (USHORT)Length;
585
586 /* Send the packet */
587 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
588 &Header,
589 Data,
590 &KdpContext);
591 }
592
593 VOID
594 NTAPI
595 KdpWritePhysicalmemory(IN PDBGKD_MANIPULATE_STATE64 State,
596 IN PSTRING Data,
597 IN PCONTEXT Context)
598 {
599 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
600 STRING Header;
601 ULONG Flags, CacheFlags;
602
603 /* Setup the header */
604 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
605 Header.Buffer = (PCHAR)State;
606
607 /* Start with the default flags */
608 Flags = MMDBG_COPY_UNSAFE | MMDBG_COPY_WRITE | MMDBG_COPY_PHYSICAL;
609
610 /* Get the caching flags and check if a type is specified */
611 CacheFlags = WriteMemory->ActualBytesWritten;
612 if (CacheFlags == DBGKD_CACHING_CACHED)
613 {
614 /* Cached */
615 Flags |= MMDBG_COPY_CACHED;
616 }
617 else if (CacheFlags == DBGKD_CACHING_UNCACHED)
618 {
619 /* Uncached */
620 Flags |= MMDBG_COPY_UNCACHED;
621 }
622 else if (CacheFlags == DBGKD_CACHING_WRITE_COMBINED)
623 {
624 /* Write Combined */
625 Flags |= MMDBG_COPY_WRITE_COMBINED;
626 }
627
628 /* Do the write */
629 State->ReturnStatus = KdpCopyMemoryChunks(WriteMemory->TargetBaseAddress,
630 Data->Buffer,
631 Data->Length,
632 0,
633 Flags,
634 &WriteMemory->ActualBytesWritten);
635
636 /* Send the packet */
637 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
638 &Header,
639 NULL,
640 &KdpContext);
641 }
642
643 VOID
644 NTAPI
645 KdpReadControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
646 IN PSTRING Data,
647 IN PCONTEXT Context)
648 {
649 PDBGKD_READ_MEMORY64 ReadMemory = &State->u.ReadMemory;
650 STRING Header;
651 ULONG Length;
652
653 /* Setup the header */
654 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
655 Header.Buffer = (PCHAR)State;
656 ASSERT(Data->Length == 0);
657
658 /* Check the length requested */
659 Length = ReadMemory->TransferCount;
660 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
661 {
662 /* Use maximum allowed */
663 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
664 }
665
666 /* Call the internal routine */
667 State->ReturnStatus = KdpSysReadControlSpace(State->Processor,
668 ReadMemory->TargetBaseAddress,
669 Data->Buffer,
670 Length,
671 &Length);
672
673 /* Return the actual length read */
674 ReadMemory->ActualBytesRead = Length;
675 Data->Length = (USHORT)Length;
676
677 /* Send the reply */
678 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
679 &Header,
680 Data,
681 &KdpContext);
682 }
683
684 VOID
685 NTAPI
686 KdpWriteControlSpace(IN PDBGKD_MANIPULATE_STATE64 State,
687 IN PSTRING Data,
688 IN PCONTEXT Context)
689 {
690 PDBGKD_WRITE_MEMORY64 WriteMemory = &State->u.WriteMemory;
691 STRING Header;
692
693 /* Setup the header */
694 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
695 Header.Buffer = (PCHAR)State;
696
697 /* Call the internal routine */
698 State->ReturnStatus = KdpSysWriteControlSpace(State->Processor,
699 WriteMemory->TargetBaseAddress,
700 Data->Buffer,
701 Data->Length,
702 &WriteMemory->ActualBytesWritten);
703
704 /* Send the reply */
705 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
706 &Header,
707 Data,
708 &KdpContext);
709 }
710
711 VOID
712 NTAPI
713 KdpGetContext(IN PDBGKD_MANIPULATE_STATE64 State,
714 IN PSTRING Data,
715 IN PCONTEXT Context)
716 {
717 STRING Header;
718 PCONTEXT TargetContext;
719
720 /* Setup the header */
721 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
722 Header.Buffer = (PCHAR)State;
723 ASSERT(Data->Length == 0);
724
725 /* Make sure that this is a valid request */
726 if (State->Processor < KeNumberProcessors)
727 {
728 /* Check if the request is for this CPU */
729 if (State->Processor == KeGetCurrentPrcb()->Number)
730 {
731 /* We're just copying our own context */
732 TargetContext = Context;
733 }
734 else
735 {
736 /* Get the context from the PRCB array */
737 TargetContext = &KiProcessorBlock[State->Processor]->
738 ProcessorState.ContextFrame;
739 }
740
741 /* Copy it over to the debugger */
742 KdpMoveMemory(Data->Buffer,
743 TargetContext,
744 sizeof(CONTEXT));
745 Data->Length = sizeof(CONTEXT);
746
747 /* Let the debugger set the context now */
748 KdpContextSent = TRUE;
749
750 /* Finish up */
751 State->ReturnStatus = STATUS_SUCCESS;
752 }
753 else
754 {
755 /* Invalid request */
756 State->ReturnStatus = STATUS_UNSUCCESSFUL;
757 }
758
759 /* Send the reply */
760 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
761 &Header,
762 Data,
763 &KdpContext);
764 }
765
766 VOID
767 NTAPI
768 KdpSetContext(IN PDBGKD_MANIPULATE_STATE64 State,
769 IN PSTRING Data,
770 IN PCONTEXT Context)
771 {
772 STRING Header;
773 PCONTEXT TargetContext;
774
775 /* Setup the header */
776 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
777 Header.Buffer = (PCHAR)State;
778 ASSERT(Data->Length == sizeof(CONTEXT));
779
780 /* Make sure that this is a valid request */
781 if ((State->Processor < KeNumberProcessors) &&
782 (KdpContextSent))
783 {
784 /* Check if the request is for this CPU */
785 if (State->Processor == KeGetCurrentPrcb()->Number)
786 {
787 /* We're just copying our own context */
788 TargetContext = Context;
789 }
790 else
791 {
792 /* Get the context from the PRCB array */
793 TargetContext = &KiProcessorBlock[State->Processor]->
794 ProcessorState.ContextFrame;
795 }
796
797 /* Copy the new context to it */
798 KdpMoveMemory(TargetContext,
799 Data->Buffer,
800 sizeof(CONTEXT));
801
802 /* Finish up */
803 State->ReturnStatus = STATUS_SUCCESS;
804 }
805 else
806 {
807 /* Invalid request */
808 State->ReturnStatus = STATUS_UNSUCCESSFUL;
809 }
810
811 /* Send the reply */
812 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
813 &Header,
814 NULL,
815 &KdpContext);
816 }
817
818 VOID
819 NTAPI
820 KdpGetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
821 IN PSTRING Data,
822 IN PCONTEXT Context)
823 {
824 STRING Header;
825 PDBGKD_CONTEXT_EX ContextEx;
826 PCONTEXT TargetContext;
827 ASSERT(Data->Length == 0);
828
829 /* Get our struct */
830 ContextEx = &State->u.ContextEx;
831
832 /* Set up the header */
833 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
834 Header.Buffer = (PCHAR)State;
835
836 /* Make sure that this is a valid request */
837 if ((State->Processor < KeNumberProcessors) &&
838 (ContextEx->Offset + ContextEx->ByteCount) <= sizeof(CONTEXT))
839 {
840 /* Check if the request is for this CPU */
841 if (State->Processor == KeGetCurrentPrcb()->Number)
842 {
843 /* We're just copying our own context */
844 TargetContext = Context;
845 }
846 else
847 {
848 /* Get the context from the PRCB array */
849 TargetContext = &KiProcessorBlock[State->Processor]->
850 ProcessorState.ContextFrame;
851 }
852
853 /* Copy what is requested */
854 KdpMoveMemory(Data->Buffer,
855 (PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
856 ContextEx->ByteCount);
857
858 /* KD copies all */
859 Data->Length = ContextEx->BytesCopied = ContextEx->ByteCount;
860
861 /* Let the debugger set the context now */
862 KdpContextSent = TRUE;
863
864 /* Finish up */
865 State->ReturnStatus = STATUS_SUCCESS;
866 }
867 else
868 {
869 /* Invalid request */
870 ContextEx->BytesCopied = 0;
871 State->ReturnStatus = STATUS_UNSUCCESSFUL;
872 }
873
874 /* Send the reply */
875 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
876 &Header,
877 Data,
878 &KdpContext);
879 }
880
881 VOID
882 NTAPI
883 KdpSetContextEx(IN PDBGKD_MANIPULATE_STATE64 State,
884 IN PSTRING Data,
885 IN PCONTEXT Context)
886 {
887 STRING Header;
888 PDBGKD_CONTEXT_EX ContextEx;
889 PCONTEXT TargetContext;
890
891 /* Get our struct */
892 ContextEx = &State->u.ContextEx;
893 ASSERT(Data->Length == ContextEx->ByteCount);
894
895 /* Set up the header */
896 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
897 Header.Buffer = (PCHAR)State;
898
899 /* Make sure that this is a valid request */
900 if ((State->Processor < KeNumberProcessors) &&
901 ((ContextEx->Offset + ContextEx->ByteCount) <= sizeof(CONTEXT)) &&
902 (KdpContextSent))
903 {
904 /* Check if the request is for this CPU */
905 if (State->Processor == KeGetCurrentPrcb()->Number)
906 {
907 /* We're just copying our own context */
908 TargetContext = Context;
909 }
910 else
911 {
912 /* Get the context from the PRCB array */
913 TargetContext = &KiProcessorBlock[State->Processor]->
914 ProcessorState.ContextFrame;
915 }
916
917 /* Copy what is requested */
918 KdpMoveMemory((PVOID)((ULONG_PTR)TargetContext + ContextEx->Offset),
919 Data->Buffer,
920 ContextEx->ByteCount);
921
922 /* KD copies all */
923 ContextEx->BytesCopied = ContextEx->ByteCount;
924
925 /* Finish up */
926 State->ReturnStatus = STATUS_SUCCESS;
927 }
928 else
929 {
930 /* Invalid request */
931 ContextEx->BytesCopied = 0;
932 State->ReturnStatus = STATUS_UNSUCCESSFUL;
933 }
934
935 /* Send the reply */
936 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
937 &Header,
938 NULL,
939 &KdpContext);
940 }
941
942 VOID
943 NTAPI
944 KdpCauseBugCheck(IN PDBGKD_MANIPULATE_STATE64 State)
945 {
946 /* Crash with the special code */
947 KeBugCheck(MANUALLY_INITIATED_CRASH);
948 }
949
950 VOID
951 NTAPI
952 KdpReadMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
953 IN PSTRING Data,
954 IN PCONTEXT Context)
955 {
956 STRING Header;
957 PDBGKD_READ_WRITE_MSR ReadMsr = &State->u.ReadWriteMsr;
958 LARGE_INTEGER MsrValue;
959
960 /* Setup the header */
961 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
962 Header.Buffer = (PCHAR)State;
963 ASSERT(Data->Length == 0);
964
965 /* Call the internal routine */
966 State->ReturnStatus = KdpSysReadMsr(ReadMsr->Msr,
967 &MsrValue);
968
969 /* Return the data */
970 ReadMsr->DataValueLow = MsrValue.LowPart;
971 ReadMsr->DataValueHigh = MsrValue.HighPart;
972
973 /* Send the reply */
974 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
975 &Header,
976 NULL,
977 &KdpContext);
978 }
979
980 VOID
981 NTAPI
982 KdpWriteMachineSpecificRegister(IN PDBGKD_MANIPULATE_STATE64 State,
983 IN PSTRING Data,
984 IN PCONTEXT Context)
985 {
986 STRING Header;
987 PDBGKD_READ_WRITE_MSR WriteMsr = &State->u.ReadWriteMsr;
988 LARGE_INTEGER MsrValue;
989
990 /* Setup the header */
991 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
992 Header.Buffer = (PCHAR)State;
993 ASSERT(Data->Length == 0);
994
995 /* Call the internal routine */
996 MsrValue.LowPart = WriteMsr->DataValueLow;
997 MsrValue.HighPart = WriteMsr->DataValueHigh;
998 State->ReturnStatus = KdpSysWriteMsr(WriteMsr->Msr,
999 &MsrValue);
1000
1001 /* Send the reply */
1002 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1003 &Header,
1004 NULL,
1005 &KdpContext);
1006 }
1007
1008 VOID
1009 NTAPI
1010 KdpGetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
1011 IN PSTRING Data,
1012 IN PCONTEXT Context)
1013 {
1014 STRING Header;
1015 PDBGKD_GET_SET_BUS_DATA GetBusData = &State->u.GetSetBusData;
1016 ULONG Length;
1017
1018 /* Setup the header */
1019 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1020 Header.Buffer = (PCHAR)State;
1021 ASSERT(Data->Length == 0);
1022
1023 /* Check the length requested */
1024 Length = GetBusData->Length;
1025 if (Length > (PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64)))
1026 {
1027 /* Use maximum allowed */
1028 Length = PACKET_MAX_SIZE - sizeof(DBGKD_MANIPULATE_STATE64);
1029 }
1030
1031 /* Call the internal routine */
1032 State->ReturnStatus = KdpSysReadBusData(GetBusData->BusDataType,
1033 GetBusData->BusNumber,
1034 GetBusData->SlotNumber,
1035 GetBusData->Offset,
1036 Data->Buffer,
1037 Length,
1038 &Length);
1039
1040 /* Return the actual length read */
1041 GetBusData->Length = Length;
1042 Data->Length = (USHORT)Length;
1043
1044 /* Send the reply */
1045 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1046 &Header,
1047 Data,
1048 &KdpContext);
1049 }
1050
1051 VOID
1052 NTAPI
1053 KdpSetBusData(IN PDBGKD_MANIPULATE_STATE64 State,
1054 IN PSTRING Data,
1055 IN PCONTEXT Context)
1056 {
1057 STRING Header;
1058 PDBGKD_GET_SET_BUS_DATA SetBusData = &State->u.GetSetBusData;
1059 ULONG Length;
1060
1061 /* Setup the header */
1062 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1063 Header.Buffer = (PCHAR)State;
1064
1065 /* Call the internal routine */
1066 State->ReturnStatus = KdpSysWriteBusData(SetBusData->BusDataType,
1067 SetBusData->BusNumber,
1068 SetBusData->SlotNumber,
1069 SetBusData->Offset,
1070 Data->Buffer,
1071 SetBusData->Length,
1072 &Length);
1073
1074 /* Return the actual length written */
1075 SetBusData->Length = Length;
1076
1077 /* Send the reply */
1078 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1079 &Header,
1080 NULL,
1081 &KdpContext);
1082 }
1083
1084 VOID
1085 NTAPI
1086 KdpReadIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
1087 IN PSTRING Data,
1088 IN PCONTEXT Context)
1089 {
1090 STRING Header;
1091 PDBGKD_READ_WRITE_IO64 ReadIo = &State->u.ReadWriteIo;
1092
1093 /* Setup the header */
1094 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1095 Header.Buffer = (PCHAR)State;
1096 ASSERT(Data->Length == 0);
1097
1098 /*
1099 * Clear the value so 1 or 2 byte reads
1100 * don't leave the higher bits unmodified
1101 */
1102 ReadIo->DataValue = 0;
1103
1104 /* Call the internal routine */
1105 State->ReturnStatus = KdpSysReadIoSpace(Isa,
1106 0,
1107 1,
1108 ReadIo->IoAddress,
1109 &ReadIo->DataValue,
1110 ReadIo->DataSize,
1111 &ReadIo->DataSize);
1112
1113 /* Send the reply */
1114 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1115 &Header,
1116 NULL,
1117 &KdpContext);
1118 }
1119
1120 VOID
1121 NTAPI
1122 KdpWriteIoSpace(IN PDBGKD_MANIPULATE_STATE64 State,
1123 IN PSTRING Data,
1124 IN PCONTEXT Context)
1125 {
1126 STRING Header;
1127 PDBGKD_READ_WRITE_IO64 WriteIo = &State->u.ReadWriteIo;
1128
1129 /* Setup the header */
1130 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1131 Header.Buffer = (PCHAR)State;
1132 ASSERT(Data->Length == 0);
1133
1134 /* Call the internal routine */
1135 State->ReturnStatus = KdpSysWriteIoSpace(Isa,
1136 0,
1137 1,
1138 WriteIo->IoAddress,
1139 &WriteIo->DataValue,
1140 WriteIo->DataSize,
1141 &WriteIo->DataSize);
1142
1143 /* Send the reply */
1144 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1145 &Header,
1146 NULL,
1147 &KdpContext);
1148 }
1149
1150 VOID
1151 NTAPI
1152 KdpReadIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
1153 IN PSTRING Data,
1154 IN PCONTEXT Context)
1155 {
1156 STRING Header;
1157 PDBGKD_READ_WRITE_IO_EXTENDED64 ReadIoExtended = &State->u.
1158 ReadWriteIoExtended;
1159
1160 /* Setup the header */
1161 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1162 Header.Buffer = (PCHAR)State;
1163 ASSERT(Data->Length == 0);
1164
1165 /*
1166 * Clear the value so 1 or 2 byte reads
1167 * don't leave the higher bits unmodified
1168 */
1169 ReadIoExtended->DataValue = 0;
1170
1171 /* Call the internal routine */
1172 State->ReturnStatus = KdpSysReadIoSpace(ReadIoExtended->InterfaceType,
1173 ReadIoExtended->BusNumber,
1174 ReadIoExtended->AddressSpace,
1175 ReadIoExtended->IoAddress,
1176 &ReadIoExtended->DataValue,
1177 ReadIoExtended->DataSize,
1178 &ReadIoExtended->DataSize);
1179
1180 /* Send the reply */
1181 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1182 &Header,
1183 NULL,
1184 &KdpContext);
1185 }
1186
1187 VOID
1188 NTAPI
1189 KdpWriteIoSpaceExtended(IN PDBGKD_MANIPULATE_STATE64 State,
1190 IN PSTRING Data,
1191 IN PCONTEXT Context)
1192 {
1193 STRING Header;
1194 PDBGKD_READ_WRITE_IO_EXTENDED64 WriteIoExtended = &State->u.
1195 ReadWriteIoExtended;
1196
1197 /* Setup the header */
1198 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1199 Header.Buffer = (PCHAR)State;
1200 ASSERT(Data->Length == 0);
1201
1202 /* Call the internal routine */
1203 State->ReturnStatus = KdpSysWriteIoSpace(WriteIoExtended->InterfaceType,
1204 WriteIoExtended->BusNumber,
1205 WriteIoExtended->AddressSpace,
1206 WriteIoExtended->IoAddress,
1207 &WriteIoExtended->DataValue,
1208 WriteIoExtended->DataSize,
1209 &WriteIoExtended->DataSize);
1210
1211 /* Send the reply */
1212 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1213 &Header,
1214 NULL,
1215 &KdpContext);
1216 }
1217
1218 VOID
1219 NTAPI
1220 KdpCheckLowMemory(IN PDBGKD_MANIPULATE_STATE64 State)
1221 {
1222 STRING Header;
1223
1224 /* Setup the header */
1225 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1226 Header.Buffer = (PCHAR)State;
1227
1228 /* Call the internal routine */
1229 State->ReturnStatus = KdpSysCheckLowMemory(MMDBG_COPY_UNSAFE);
1230
1231 /* Send the reply */
1232 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1233 &Header,
1234 NULL,
1235 &KdpContext);
1236 }
1237
1238 VOID
1239 NTAPI
1240 KdpNotSupported(IN PDBGKD_MANIPULATE_STATE64 State)
1241 {
1242 STRING Header;
1243
1244 /* Set failure */
1245 State->ReturnStatus = STATUS_UNSUCCESSFUL;
1246
1247 /* Setup the packet */
1248 Header.Length = sizeof(DBGKD_MANIPULATE_STATE64);
1249 Header.Buffer = (PCHAR)State;
1250
1251 /* Send it */
1252 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1253 &Header,
1254 NULL,
1255 &KdpContext);
1256 }
1257
1258 KCONTINUE_STATUS
1259 NTAPI
1260 KdpSendWaitContinue(IN ULONG PacketType,
1261 IN PSTRING SendHeader,
1262 IN PSTRING SendData OPTIONAL,
1263 IN OUT PCONTEXT Context)
1264 {
1265 STRING Data, Header;
1266 DBGKD_MANIPULATE_STATE64 ManipulateState;
1267 ULONG Length;
1268 KDSTATUS RecvCode;
1269
1270 /* Setup the Manipulate State structure */
1271 Header.MaximumLength = sizeof(DBGKD_MANIPULATE_STATE64);
1272 Header.Buffer = (PCHAR)&ManipulateState;
1273 Data.MaximumLength = sizeof(KdpMessageBuffer);
1274 Data.Buffer = KdpMessageBuffer;
1275
1276 /*
1277 * Reset the context state to ensure the debugger has received
1278 * the current context before it sets it
1279 */
1280 KdpContextSent = FALSE;
1281
1282 SendPacket:
1283 /* Send the Packet */
1284 KdSendPacket(PacketType, SendHeader, SendData, &KdpContext);
1285
1286 /* If the debugger isn't present anymore, just return success */
1287 if (KdDebuggerNotPresent) return ContinueSuccess;
1288
1289 /* Main processing Loop */
1290 for (;;)
1291 {
1292 /* Receive Loop */
1293 do
1294 {
1295 /* Wait to get a reply to our packet */
1296 RecvCode = KdReceivePacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1297 &Header,
1298 &Data,
1299 &Length,
1300 &KdpContext);
1301
1302 /* If we got a resend request, do it */
1303 if (RecvCode == KdPacketNeedsResend) goto SendPacket;
1304 } while (RecvCode == KdPacketTimedOut);
1305
1306 /* Now check what API we got */
1307 switch (ManipulateState.ApiNumber)
1308 {
1309 case DbgKdReadVirtualMemoryApi:
1310
1311 /* Read virtual memory */
1312 KdpReadVirtualMemory(&ManipulateState, &Data, Context);
1313 break;
1314
1315 case DbgKdWriteVirtualMemoryApi:
1316
1317 /* Write virtual memory */
1318 KdpWriteVirtualMemory(&ManipulateState, &Data, Context);
1319 break;
1320
1321 case DbgKdGetContextApi:
1322
1323 /* Get the current context */
1324 KdpGetContext(&ManipulateState, &Data, Context);
1325 break;
1326
1327 case DbgKdSetContextApi:
1328
1329 /* Set a new context */
1330 KdpSetContext(&ManipulateState, &Data, Context);
1331 break;
1332
1333 case DbgKdWriteBreakPointApi:
1334
1335 /* Write the breakpoint */
1336 KdpWriteBreakpoint(&ManipulateState, &Data, Context);
1337 break;
1338
1339 case DbgKdRestoreBreakPointApi:
1340
1341 /* Restore the breakpoint */
1342 KdpRestoreBreakpoint(&ManipulateState, &Data, Context);
1343 break;
1344
1345 case DbgKdContinueApi:
1346
1347 /* Simply continue */
1348 return NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus);
1349
1350 case DbgKdReadControlSpaceApi:
1351
1352 /* Read control space */
1353 KdpReadControlSpace(&ManipulateState, &Data, Context);
1354 break;
1355
1356 case DbgKdWriteControlSpaceApi:
1357
1358 /* Write control space */
1359 KdpWriteControlSpace(&ManipulateState, &Data, Context);
1360 break;
1361
1362 case DbgKdReadIoSpaceApi:
1363
1364 /* Read I/O Space */
1365 KdpReadIoSpace(&ManipulateState, &Data, Context);
1366 break;
1367
1368 case DbgKdWriteIoSpaceApi:
1369
1370 /* Write I/O Space */
1371 KdpWriteIoSpace(&ManipulateState, &Data, Context);
1372 break;
1373
1374 case DbgKdRebootApi:
1375
1376 /* Reboot the system */
1377 HalReturnToFirmware(HalRebootRoutine);
1378 break;
1379
1380 case DbgKdContinueApi2:
1381
1382 /* Check if caller reports success */
1383 if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus))
1384 {
1385 /* Update the state */
1386 KdpGetStateChange(&ManipulateState, Context);
1387 return ContinueSuccess;
1388 }
1389 else
1390 {
1391 /* Return an error */
1392 return ContinueError;
1393 }
1394
1395 case DbgKdReadPhysicalMemoryApi:
1396
1397 /* Read physical memory */
1398 KdpReadPhysicalmemory(&ManipulateState, &Data, Context);
1399 break;
1400
1401 case DbgKdWritePhysicalMemoryApi:
1402
1403 /* Write physical memory */
1404 KdpWritePhysicalmemory(&ManipulateState, &Data, Context);
1405 break;
1406
1407 case DbgKdQuerySpecialCallsApi:
1408 case DbgKdSetSpecialCallApi:
1409 case DbgKdClearSpecialCallsApi:
1410
1411 /* TODO */
1412 KdpDprintf("Special Call support is unimplemented!\n");
1413 KdpNotSupported(&ManipulateState);
1414 break;
1415
1416 case DbgKdSetInternalBreakPointApi:
1417 case DbgKdGetInternalBreakPointApi:
1418
1419 /* TODO */
1420 KdpDprintf("Internal Breakpoint support is unimplemented!\n");
1421 KdpNotSupported(&ManipulateState);
1422 break;
1423
1424 case DbgKdReadIoSpaceExtendedApi:
1425
1426 /* Read I/O Space */
1427 KdpReadIoSpaceExtended(&ManipulateState, &Data, Context);
1428 break;
1429
1430 case DbgKdWriteIoSpaceExtendedApi:
1431
1432 /* Write I/O Space */
1433 KdpWriteIoSpaceExtended(&ManipulateState, &Data, Context);
1434 break;
1435
1436 case DbgKdGetVersionApi:
1437
1438 /* Get version data */
1439 KdpGetVersion(&ManipulateState);
1440 break;
1441
1442 case DbgKdWriteBreakPointExApi:
1443
1444 /* Write the breakpoint and check if it failed */
1445 if (!NT_SUCCESS(KdpWriteBreakPointEx(&ManipulateState,
1446 &Data,
1447 Context)))
1448 {
1449 /* Return an error */
1450 return ContinueError;
1451 }
1452 break;
1453
1454 case DbgKdRestoreBreakPointExApi:
1455
1456 /* Restore the breakpoint */
1457 KdpRestoreBreakPointEx(&ManipulateState, &Data, Context);
1458 break;
1459
1460 case DbgKdCauseBugCheckApi:
1461
1462 /* Crash the system */
1463 KdpCauseBugCheck(&ManipulateState);
1464 break;
1465
1466 case DbgKdSwitchProcessor:
1467
1468 /* TODO */
1469 KdpDprintf("Processor Switch support is unimplemented!\n");
1470 KdpNotSupported(&ManipulateState);
1471 break;
1472
1473 case DbgKdPageInApi:
1474
1475 /* TODO */
1476 KdpDprintf("Page-In support is unimplemented!\n");
1477 KdpNotSupported(&ManipulateState);
1478 break;
1479
1480 case DbgKdReadMachineSpecificRegister:
1481
1482 /* Read from the specified MSR */
1483 KdpReadMachineSpecificRegister(&ManipulateState, &Data, Context);
1484 break;
1485
1486 case DbgKdWriteMachineSpecificRegister:
1487
1488 /* Write to the specified MSR */
1489 KdpWriteMachineSpecificRegister(&ManipulateState, &Data, Context);
1490 break;
1491
1492 case DbgKdSearchMemoryApi:
1493
1494 /* Search memory */
1495 KdpSearchMemory(&ManipulateState, &Data, Context);
1496 break;
1497
1498 case DbgKdGetBusDataApi:
1499
1500 /* Read from the bus */
1501 KdpGetBusData(&ManipulateState, &Data, Context);
1502 break;
1503
1504 case DbgKdSetBusDataApi:
1505
1506 /* Write to the bus */
1507 KdpSetBusData(&ManipulateState, &Data, Context);
1508 break;
1509
1510 case DbgKdCheckLowMemoryApi:
1511
1512 /* Check for memory corruption in the lower 4 GB */
1513 KdpCheckLowMemory(&ManipulateState);
1514 break;
1515
1516 case DbgKdClearAllInternalBreakpointsApi:
1517
1518 /* Just clear the counter */
1519 KdpNumInternalBreakpoints = 0;
1520 break;
1521
1522 case DbgKdFillMemoryApi:
1523
1524 /* Fill memory */
1525 KdpFillMemory(&ManipulateState, &Data, Context);
1526 break;
1527
1528 case DbgKdQueryMemoryApi:
1529
1530 /* Query memory */
1531 KdpQueryMemory(&ManipulateState, Context);
1532 break;
1533
1534 case DbgKdSwitchPartition:
1535
1536 /* TODO */
1537 KdpDprintf("Partition Switch support is unimplemented!\n");
1538 KdpNotSupported(&ManipulateState);
1539 break;
1540
1541 case DbgKdWriteCustomBreakpointApi:
1542
1543 /* Write the customized breakpoint */
1544 KdpWriteCustomBreakpoint(&ManipulateState, &Data, Context);
1545 break;
1546
1547 case DbgKdGetContextExApi:
1548
1549 /* Extended Context Get */
1550 KdpGetContextEx(&ManipulateState, &Data, Context);
1551 break;
1552
1553 case DbgKdSetContextExApi:
1554
1555 /* Extended Context Set */
1556 KdpSetContextEx(&ManipulateState, &Data, Context);
1557 break;
1558
1559 /* Unsupported Messages */
1560 default:
1561
1562 /* Send warning */
1563 KdpDprintf("Received Unrecognized API 0x%lx\n", ManipulateState.ApiNumber);
1564
1565 /* Setup an empty message, with failure */
1566 Data.Length = 0;
1567 ManipulateState.ReturnStatus = STATUS_UNSUCCESSFUL;
1568
1569 /* Send it */
1570 KdSendPacket(PACKET_TYPE_KD_STATE_MANIPULATE,
1571 &Header,
1572 &Data,
1573 &KdpContext);
1574 break;
1575 }
1576 }
1577 }
1578
1579 VOID
1580 NTAPI
1581 KdpReportLoadSymbolsStateChange(IN PSTRING PathName,
1582 IN PKD_SYMBOLS_INFO SymbolInfo,
1583 IN BOOLEAN Unload,
1584 IN OUT PCONTEXT Context)
1585 {
1586 PSTRING ExtraData;
1587 STRING Data, Header;
1588 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1589 ULONG PathNameLength;
1590 KCONTINUE_STATUS Status;
1591
1592 /* Start wait loop */
1593 do
1594 {
1595 /* Build the architecture common parts of the message */
1596 KdpSetCommonState(DbgKdLoadSymbolsStateChange,
1597 Context,
1598 &WaitStateChange);
1599
1600 /* Now finish creating the structure */
1601 KdpSetContextState(&WaitStateChange, Context);
1602
1603 /* Fill out load data */
1604 WaitStateChange.u.LoadSymbols.UnloadSymbols = Unload;
1605 WaitStateChange.u.LoadSymbols.BaseOfDll = (ULONG64)(LONG_PTR)SymbolInfo->BaseOfDll;
1606 WaitStateChange.u.LoadSymbols.ProcessId = SymbolInfo->ProcessId;
1607 WaitStateChange.u.LoadSymbols.CheckSum = SymbolInfo->CheckSum;
1608 WaitStateChange.u.LoadSymbols.SizeOfImage = SymbolInfo->SizeOfImage;
1609
1610 /* Check if we have a path name */
1611 if (PathName)
1612 {
1613 /* Copy it to the path buffer */
1614 KdpCopyMemoryChunks((ULONG_PTR)PathName->Buffer,
1615 KdpPathBuffer,
1616 PathName->Length,
1617 0,
1618 MMDBG_COPY_UNSAFE,
1619 &PathNameLength);
1620
1621 /* Null terminate */
1622 KdpPathBuffer[PathNameLength++] = ANSI_NULL;
1623
1624 /* Set the path length */
1625 WaitStateChange.u.LoadSymbols.PathNameLength = PathNameLength;
1626
1627 /* Set up the data */
1628 Data.Buffer = KdpPathBuffer;
1629 Data.Length = (USHORT)PathNameLength;
1630 ExtraData = &Data;
1631 }
1632 else
1633 {
1634 /* No name */
1635 WaitStateChange.u.LoadSymbols.PathNameLength = 0;
1636 ExtraData = NULL;
1637 }
1638
1639 /* Setup the header */
1640 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1641 Header.Buffer = (PCHAR)&WaitStateChange;
1642
1643 /* Send the packet */
1644 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1645 &Header,
1646 ExtraData,
1647 Context);
1648 } while (Status == ContinueProcessorReselected);
1649 }
1650
1651 VOID
1652 NTAPI
1653 KdpReportCommandStringStateChange(IN PSTRING NameString,
1654 IN PSTRING CommandString,
1655 IN OUT PCONTEXT Context)
1656 {
1657 STRING Header, Data;
1658 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1659 ULONG Length, ActualLength, TotalLength;
1660 KCONTINUE_STATUS Status;
1661
1662 /* Start wait loop */
1663 do
1664 {
1665 /* Build the architecture common parts of the message */
1666 KdpSetCommonState(DbgKdCommandStringStateChange,
1667 Context,
1668 &WaitStateChange);
1669
1670 /* Set the context */
1671 KdpSetContextState(&WaitStateChange, Context);
1672
1673 /* Clear the command string structure */
1674 KdpZeroMemory(&WaitStateChange.u.CommandString,
1675 sizeof(DBGKD_COMMAND_STRING));
1676
1677 /* Normalize name string to max */
1678 Length = min(128 - 1, NameString->Length);
1679
1680 /* Copy it to the message buffer */
1681 KdpCopyMemoryChunks((ULONG_PTR)NameString->Buffer,
1682 KdpMessageBuffer,
1683 Length,
1684 0,
1685 MMDBG_COPY_UNSAFE,
1686 &ActualLength);
1687
1688 /* Null terminate and calculate the total length */
1689 TotalLength = ActualLength;
1690 KdpMessageBuffer[TotalLength++] = ANSI_NULL;
1691
1692 /* Check if the command string is too long */
1693 Length = CommandString->Length;
1694 if (Length > (PACKET_MAX_SIZE -
1695 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength))
1696 {
1697 /* Use maximum possible size */
1698 Length = (PACKET_MAX_SIZE -
1699 sizeof(DBGKD_ANY_WAIT_STATE_CHANGE) - TotalLength);
1700 }
1701
1702 /* Copy it to the message buffer */
1703 KdpCopyMemoryChunks((ULONG_PTR)CommandString->Buffer,
1704 KdpMessageBuffer + TotalLength,
1705 Length,
1706 0,
1707 MMDBG_COPY_UNSAFE,
1708 &ActualLength);
1709
1710 /* Null terminate and calculate the total length */
1711 TotalLength += ActualLength;
1712 KdpMessageBuffer[TotalLength++] = ANSI_NULL;
1713
1714 /* Now set up the header and the data */
1715 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1716 Header.Buffer = (PCHAR)&WaitStateChange;
1717 Data.Length = (USHORT)TotalLength;
1718 Data.Buffer = KdpMessageBuffer;
1719
1720 /* Send State Change packet and wait for a reply */
1721 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1722 &Header,
1723 &Data,
1724 Context);
1725 } while (Status == ContinueProcessorReselected);
1726 }
1727
1728 BOOLEAN
1729 NTAPI
1730 KdpReportExceptionStateChange(IN PEXCEPTION_RECORD ExceptionRecord,
1731 IN OUT PCONTEXT Context,
1732 IN BOOLEAN SecondChanceException)
1733 {
1734 STRING Header, Data;
1735 DBGKD_ANY_WAIT_STATE_CHANGE WaitStateChange;
1736 KCONTINUE_STATUS Status;
1737
1738 /* Start report loop */
1739 do
1740 {
1741 /* Build the architecture common parts of the message */
1742 KdpSetCommonState(DbgKdExceptionStateChange, Context, &WaitStateChange);
1743
1744 #if !defined(_WIN64)
1745
1746 /* Convert it and copy it over */
1747 ExceptionRecord32To64((PEXCEPTION_RECORD32)ExceptionRecord,
1748 &WaitStateChange.u.Exception.ExceptionRecord);
1749
1750 #else
1751
1752 /* Just copy it directly, no need to convert */
1753 KdpMoveMemory(&WaitStateChange.u.Exception.ExceptionRecord,
1754 ExceptionRecord,
1755 sizeof(EXCEPTION_RECORD));
1756
1757 #endif
1758
1759 /* Set the First Chance flag */
1760 WaitStateChange.u.Exception.FirstChance = !SecondChanceException;
1761
1762 /* Now finish creating the structure */
1763 KdpSetContextState(&WaitStateChange, Context);
1764
1765 /* Setup the actual header to send to KD */
1766 Header.Length = sizeof(DBGKD_ANY_WAIT_STATE_CHANGE);
1767 Header.Buffer = (PCHAR)&WaitStateChange;
1768
1769 /* Setup the trace data */
1770 DumpTraceData(&Data);
1771
1772 /* Send State Change packet and wait for a reply */
1773 Status = KdpSendWaitContinue(PACKET_TYPE_KD_STATE_CHANGE64,
1774 &Header,
1775 &Data,
1776 Context);
1777 } while (Status == ContinueProcessorReselected);
1778
1779 /* Return */
1780 return Status;
1781 }
1782
1783 VOID
1784 NTAPI
1785 KdpTimeSlipDpcRoutine(IN PKDPC Dpc,
1786 IN PVOID DeferredContext,
1787 IN PVOID SystemArgument1,
1788 IN PVOID SystemArgument2)
1789 {
1790 LONG OldSlip, NewSlip, PendingSlip;
1791
1792 /* Get the current pending slip */
1793 PendingSlip = KdpTimeSlipPending;
1794 do
1795 {
1796 /* Save the old value and either disable or enable it now. */
1797 OldSlip = PendingSlip;
1798 NewSlip = OldSlip > 1 ? 1 : 0;
1799
1800 /* Try to change the value */
1801 } while (InterlockedCompareExchange(&KdpTimeSlipPending,
1802 NewSlip,
1803 OldSlip) != OldSlip);
1804
1805 /* If the New Slip value is 1, then do the Time Slipping */
1806 if (NewSlip) ExQueueWorkItem(&KdpTimeSlipWorkItem, DelayedWorkQueue);
1807 }
1808
1809 VOID
1810 NTAPI
1811 KdpTimeSlipWork(IN PVOID Context)
1812 {
1813 KIRQL OldIrql;
1814 LARGE_INTEGER DueTime;
1815
1816 /* Update the System time from the CMOS */
1817 ExAcquireTimeRefreshLock(FALSE);
1818 ExUpdateSystemTimeFromCmos(FALSE, 0);
1819 ExReleaseTimeRefreshLock();
1820
1821 /* Check if we have a registered Time Slip Event and signal it */
1822 KeAcquireSpinLock(&KdpTimeSlipEventLock, &OldIrql);
1823 if (KdpTimeSlipEvent) KeSetEvent(KdpTimeSlipEvent, 0, FALSE);
1824 KeReleaseSpinLock(&KdpTimeSlipEventLock, OldIrql);
1825
1826 /* Delay the DPC until it runs next time */
1827 DueTime.QuadPart = -1800000000;
1828 KeSetTimer(&KdpTimeSlipTimer, DueTime, &KdpTimeSlipDpc);
1829 }
1830
1831 BOOLEAN
1832 NTAPI
1833 KdpSwitchProcessor(IN PEXCEPTION_RECORD ExceptionRecord,
1834 IN OUT PCONTEXT ContextRecord,
1835 IN BOOLEAN SecondChanceException)
1836 {
1837 BOOLEAN Status;
1838
1839 /* Save the port data */
1840 KdSave(FALSE);
1841
1842 /* Report a state change */
1843 Status = KdpReportExceptionStateChange(ExceptionRecord,
1844 ContextRecord,
1845 SecondChanceException);
1846
1847 /* Restore the port data and return */
1848 KdRestore(FALSE);
1849 return Status;
1850 }
1851
1852 LARGE_INTEGER
1853 NTAPI
1854 KdpQueryPerformanceCounter(IN PKTRAP_FRAME TrapFrame)
1855 {
1856 LARGE_INTEGER Null = {{0}};
1857
1858 /* Check if interrupts were disabled */
1859 if (!KeGetTrapFrameInterruptState(TrapFrame))
1860 {
1861 /* Nothing to return */
1862 return Null;
1863 }
1864
1865 /* Otherwise, do the call */
1866 return KeQueryPerformanceCounter(NULL);
1867 }
1868
1869 BOOLEAN
1870 NTAPI
1871 KdEnterDebugger(IN PKTRAP_FRAME TrapFrame,
1872 IN PKEXCEPTION_FRAME ExceptionFrame)
1873 {
1874 BOOLEAN Enable;
1875
1876 /* Check if we have a trap frame */
1877 if (TrapFrame)
1878 {
1879 /* Calculate the time difference for the enter */
1880 KdTimerStop = KdpQueryPerformanceCounter(TrapFrame);
1881 KdTimerDifference.QuadPart = KdTimerStop.QuadPart -
1882 KdTimerStart.QuadPart;
1883 }
1884 else
1885 {
1886 /* No trap frame, so can't calculate */
1887 KdTimerStop.QuadPart = 0;
1888 }
1889
1890 /* Save the current IRQL */
1891 KeGetCurrentPrcb()->DebuggerSavedIRQL = KeGetCurrentIrql();
1892
1893 /* Freeze all CPUs */
1894 Enable = KeFreezeExecution(TrapFrame, ExceptionFrame);
1895
1896 /* Lock the port, save the state and set debugger entered */
1897 KdpPortLocked = KeTryToAcquireSpinLockAtDpcLevel(&KdpDebuggerLock);
1898 KdSave(FALSE);
1899 KdEnteredDebugger = TRUE;
1900
1901 /* Check freeze flag */
1902 if (KiFreezeFlag & 1)
1903 {
1904 /* Print out errror */
1905 KdpDprintf("FreezeLock was jammed! Backup SpinLock was used!\n");
1906 }
1907
1908 /* Check processor state */
1909 if (KiFreezeFlag & 2)
1910 {
1911 /* Print out errror */
1912 KdpDprintf("Some processors not frozen in debugger!\n");
1913 }
1914
1915 /* Make sure we acquired the port */
1916 if (!KdpPortLocked) KdpDprintf("Port lock was not acquired!\n");
1917
1918 /* Return if interrupts needs to be re-enabled */
1919 return Enable;
1920 }
1921
1922 VOID
1923 NTAPI
1924 KdExitDebugger(IN BOOLEAN Enable)
1925 {
1926 ULONG TimeSlip;
1927
1928 /* Restore the state and unlock the port */
1929 KdRestore(FALSE);
1930 if (KdpPortLocked) KdpPortUnlock();
1931
1932 /* Unfreeze the CPUs */
1933 KeThawExecution(Enable);
1934
1935 /* Compare time with the one from KdEnterDebugger */
1936 if (!KdTimerStop.QuadPart)
1937 {
1938 /* We didn't get a trap frame earlier in so never got the time */
1939 KdTimerStart = KdTimerStop;
1940 }
1941 else
1942 {
1943 /* Query the timer */
1944 KdTimerStart = KeQueryPerformanceCounter(NULL);
1945 }
1946
1947 /* Check if a Time Slip was on queue */
1948 TimeSlip = InterlockedIncrement(&KdpTimeSlipPending);
1949 if (TimeSlip == 1)
1950 {
1951 /* Queue a DPC for the time slip */
1952 InterlockedIncrement(&KdpTimeSlipPending);
1953 KeInsertQueueDpc(&KdpTimeSlipDpc, NULL, NULL); // FIXME: this can trigger context switches!
1954 }
1955 }
1956
1957 NTSTATUS
1958 NTAPI
1959 KdEnableDebuggerWithLock(IN BOOLEAN NeedLock)
1960 {
1961 KIRQL OldIrql;
1962
1963 #if defined(__GNUC__)
1964 /* Make gcc happy */
1965 OldIrql = PASSIVE_LEVEL;
1966 #endif
1967
1968 /* Check if enabling the debugger is blocked */
1969 if (KdBlockEnable)
1970 {
1971 /* It is, fail the enable */
1972 return STATUS_ACCESS_DENIED;
1973 }
1974
1975 /* Check if we need to acquire the lock */
1976 if (NeedLock)
1977 {
1978 /* Lock the port */
1979 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
1980 KdpPortLock();
1981 }
1982
1983 /* Check if we're not disabled */
1984 if (!KdDisableCount)
1985 {
1986 /* Check if we had locked the port before */
1987 if (NeedLock)
1988 {
1989 /* Do the unlock */
1990 KeLowerIrql(OldIrql);
1991 KdpPortUnlock();
1992
1993 /* Fail: We're already enabled */
1994 return STATUS_INVALID_PARAMETER;
1995 }
1996 else
1997 {
1998 /*
1999 * This can only happen if we are called from a bugcheck
2000 * and were never initialized, so initialize the debugger now.
2001 */
2002 KdInitSystem(0, NULL);
2003
2004 /* Return success since we initialized */
2005 return STATUS_SUCCESS;
2006 }
2007 }
2008
2009 /* Decrease the disable count */
2010 if (!(--KdDisableCount))
2011 {
2012 /* We're now enabled again! Were we enabled before, too? */
2013 if (KdPreviouslyEnabled)
2014 {
2015 /* Reinitialize the Debugger */
2016 KdInitSystem(0, NULL);
2017 KdpRestoreAllBreakpoints();
2018 }
2019 }
2020
2021 /* Check if we had locked the port before */
2022 if (NeedLock)
2023 {
2024 /* Yes, now unlock it */
2025 KeLowerIrql(OldIrql);
2026 KdpPortUnlock();
2027 }
2028
2029 /* We're done */
2030 return STATUS_SUCCESS;
2031 }
2032
2033 NTSTATUS
2034 NTAPI
2035 KdDisableDebuggerWithLock(IN BOOLEAN NeedLock)
2036 {
2037 KIRQL OldIrql;
2038 NTSTATUS Status;
2039
2040 #if defined(__GNUC__)
2041 /* Make gcc happy */
2042 OldIrql = PASSIVE_LEVEL;
2043 #endif
2044
2045 /*
2046 * If enabling the debugger is blocked
2047 * then there is nothing to disable (duh)
2048 */
2049 if (KdBlockEnable)
2050 {
2051 /* Fail */
2052 return STATUS_ACCESS_DENIED;
2053 }
2054
2055 /* Check if we need to acquire the lock */
2056 if (NeedLock)
2057 {
2058 /* Lock the port */
2059 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
2060 KdpPortLock();
2061 }
2062
2063 /* Check if we're not disabled */
2064 if (!KdDisableCount)
2065 {
2066 /* Check if the debugger was never actually initialized */
2067 if (!(KdDebuggerEnabled) && !(KdPitchDebugger))
2068 {
2069 /* It wasn't, so don't re-enable it later */
2070 KdPreviouslyEnabled = FALSE;
2071 }
2072 else
2073 {
2074 /* It was, so we will re-enable it later */
2075 KdPreviouslyEnabled = TRUE;
2076 }
2077
2078 /* Check if we were called from the exported API and are enabled */
2079 if ((NeedLock) && (KdPreviouslyEnabled))
2080 {
2081 /* Check if it is safe to disable the debugger */
2082 Status = KdpAllowDisable();
2083 if (!NT_SUCCESS(Status))
2084 {
2085 /* Release the lock and fail */
2086 KeLowerIrql(OldIrql);
2087 KdpPortUnlock();
2088 return Status;
2089 }
2090 }
2091
2092 /* Only disable the debugger if it is enabled */
2093 if (KdDebuggerEnabled)
2094 {
2095 /*
2096 * Disable the debugger; suspend breakpoints
2097 * and reset the debug stub
2098 */
2099 KdpSuspendAllBreakPoints();
2100 KiDebugRoutine = KdpStub;
2101
2102 /* We are disabled now */
2103 KdDebuggerEnabled = FALSE;
2104 SharedUserData->KdDebuggerEnabled = FALSE;
2105 }
2106 }
2107
2108 /* Increment the disable count */
2109 KdDisableCount++;
2110
2111 /* Check if we had locked the port before */
2112 if (NeedLock)
2113 {
2114 /* Yes, now unlock it */
2115 KeLowerIrql(OldIrql);
2116 KdpPortUnlock();
2117 }
2118
2119 /* We're done */
2120 return STATUS_SUCCESS;
2121 }
2122
2123 /* PUBLIC FUNCTIONS **********************************************************/
2124
2125 /*
2126 * @implemented
2127 */
2128 NTSTATUS
2129 NTAPI
2130 KdEnableDebugger(VOID)
2131 {
2132 /* Use the internal routine */
2133 return KdEnableDebuggerWithLock(TRUE);
2134 }
2135
2136 /*
2137 * @implemented
2138 */
2139 NTSTATUS
2140 NTAPI
2141 KdDisableDebugger(VOID)
2142 {
2143 /* Use the internal routine */
2144 return KdDisableDebuggerWithLock(TRUE);
2145 }
2146
2147 /*
2148 * @unimplemented
2149 */
2150 NTSTATUS
2151 NTAPI
2152 KdSystemDebugControl(IN SYSDBG_COMMAND Command,
2153 IN PVOID InputBuffer,
2154 IN ULONG InputBufferLength,
2155 OUT PVOID OutputBuffer,
2156 IN ULONG OutputBufferLength,
2157 IN OUT PULONG ReturnLength,
2158 IN KPROCESSOR_MODE PreviousMode)
2159 {
2160 /* handle sime internal commands */
2161 if (Command == ' soR')
2162 {
2163 switch ((ULONG_PTR)InputBuffer)
2164 {
2165 case 0x24:
2166 MmDumpArmPfnDatabase(FALSE);
2167 break;
2168 }
2169 return STATUS_SUCCESS;
2170 }
2171
2172 /* Local kernel debugging is not yet supported */
2173 DbgPrint("KdSystemDebugControl is unimplemented!\n");
2174 return STATUS_NOT_IMPLEMENTED;
2175 }
2176
2177 /*
2178 * @implemented
2179 */
2180 NTSTATUS
2181 NTAPI
2182 KdChangeOption(IN KD_OPTION Option,
2183 IN ULONG InBufferBytes OPTIONAL,
2184 IN PVOID InBuffer,
2185 IN ULONG OutBufferBytes OPTIONAL,
2186 OUT PVOID OutBuffer,
2187 OUT PULONG OutBufferNeeded OPTIONAL)
2188 {
2189 /* Fail if there is no debugger */
2190 if (KdPitchDebugger)
2191 {
2192 /* No debugger, no options */
2193 return STATUS_DEBUGGER_INACTIVE;
2194 }
2195
2196 /* Do we recognize this option? */
2197 if (Option != KD_OPTION_SET_BLOCK_ENABLE)
2198 {
2199 /* We don't, clear the output length and fail */
2200 if (OutBufferNeeded) *OutBufferNeeded = 0;
2201 return STATUS_INVALID_INFO_CLASS;
2202 }
2203
2204 /* Verify parameters */
2205 if ((InBufferBytes != sizeof(BOOLEAN)) ||
2206 (OutBufferBytes != 0) ||
2207 (OutBuffer != NULL))
2208 {
2209 /* Invalid parameters for this option, fail */
2210 return STATUS_INVALID_PARAMETER;
2211 }
2212
2213 /*
2214 * Check if the high bit is set, meaning we don't
2215 * allow the debugger to be enabled
2216 */
2217 if (KdBlockEnable & 0x80)
2218 {
2219 /* Fail regardless of what state the caller tried to set */
2220 return STATUS_ACCESS_VIOLATION;
2221 }
2222
2223 /* Set the new block enable state */
2224 KdBlockEnable = *(PBOOLEAN)InBuffer;
2225
2226 /* No output buffer required for this option */
2227 if (OutBufferNeeded) *OutBufferNeeded = 0;
2228
2229 /* We are done */
2230 return STATUS_SUCCESS;
2231 }
2232
2233 /*
2234 * @implemented
2235 */
2236 NTSTATUS
2237 NTAPI
2238 KdPowerTransition(IN DEVICE_POWER_STATE NewState)
2239 {
2240 /* Check what power state this is */
2241 if (NewState == PowerDeviceD0)
2242 {
2243 /* Wake up the debug port */
2244 KdD0Transition();
2245 return STATUS_SUCCESS;
2246 }
2247 else if ((NewState == PowerDeviceD1) ||
2248 (NewState == PowerDeviceD2) ||
2249 (NewState == PowerDeviceD3))
2250 {
2251 /* Power down the debug port */
2252 KdD3Transition();
2253 return STATUS_SUCCESS;
2254 }
2255 else
2256 {
2257 /* Invalid state! */
2258 return STATUS_INVALID_PARAMETER_1;
2259 }
2260 }
2261
2262 /*
2263 * @implemented
2264 */
2265 BOOLEAN
2266 NTAPI
2267 KdRefreshDebuggerNotPresent(VOID)
2268 {
2269 BOOLEAN Enable, DebuggerNotPresent;
2270
2271 /* Check if the debugger is completely disabled */
2272 if (KdPitchDebugger)
2273 {
2274 /* Don't try to refresh then -- fail early */
2275 return TRUE;
2276 }
2277
2278 /* Enter the debugger */
2279 Enable = KdEnterDebugger(NULL, NULL);
2280
2281 /*
2282 * Attempt to send a string to the debugger to refresh the
2283 * connection state
2284 */
2285 KdpDprintf("KDTARGET: Refreshing KD connection\n");
2286
2287 /* Save the state while we are holding the lock */
2288 DebuggerNotPresent = KdDebuggerNotPresent;
2289
2290 /* Exit the debugger and return the state */
2291 KdExitDebugger(Enable);
2292 return DebuggerNotPresent;
2293 }
2294
2295 /*
2296 * @implemented
2297 */
2298 NTSTATUS
2299 NTAPI
2300 NtQueryDebugFilterState(IN ULONG ComponentId,
2301 IN ULONG Level)
2302 {
2303 PULONG Mask;
2304
2305 /* Check if the ID fits in the component table */
2306 if (ComponentId < KdComponentTableSize)
2307 {
2308 /* It does, so get the mask from there */
2309 Mask = KdComponentTable[ComponentId];
2310 }
2311 else if (ComponentId == MAXULONG)
2312 {
2313 /*
2314 * This is the internal ID used for DbgPrint messages without ID and
2315 * Level. Use the system-wide mask for those.
2316 */
2317 Mask = &Kd_WIN2000_Mask;
2318 }
2319 else
2320 {
2321 /* Invalid ID, fail */
2322 return STATUS_INVALID_PARAMETER_1;
2323 }
2324
2325 /* Convert Level to bit field if necessary */
2326 if (Level < 32) Level = 1 << Level;
2327
2328 /* Determine if this Level is filtered out */
2329 if ((Kd_WIN2000_Mask & Level) ||
2330 (*Mask & Level))
2331 {
2332 /* This mask will get through to the debugger */
2333 return (NTSTATUS)TRUE;
2334 }
2335 else
2336 {
2337 /* This mask is filtered out */
2338 return (NTSTATUS)FALSE;
2339 }
2340 }
2341
2342 /*
2343 * @implemented
2344 */
2345 NTSTATUS
2346 NTAPI
2347 NtSetDebugFilterState(IN ULONG ComponentId,
2348 IN ULONG Level,
2349 IN BOOLEAN State)
2350 {
2351 PULONG Mask;
2352
2353 /* Modifying debug filters requires the debug privilege */
2354 if (!SeSinglePrivilegeCheck(SeDebugPrivilege,
2355 ExGetPreviousMode()))
2356 {
2357 /* Fail */
2358 return STATUS_ACCESS_DENIED;
2359 }
2360
2361 /* Check if the ID fits in the component table */
2362 if (ComponentId < KdComponentTableSize)
2363 {
2364 /* It does, so get the mask from there */
2365 Mask = KdComponentTable[ComponentId];
2366 }
2367 else if (ComponentId == MAXULONG)
2368 {
2369 /*
2370 * This is the internal ID used for DbgPrint messages without ID and
2371 * Level. Use the system-wide mask for those.
2372 */
2373 Mask = &Kd_WIN2000_Mask;
2374 }
2375 else
2376 {
2377 /* Invalid ID, fail */
2378 return STATUS_INVALID_PARAMETER_1;
2379 }
2380
2381 /* Convert Level to bit field if required */
2382 if (Level < 32) Level = 1 << Level;
2383
2384 /* Check what kind of operation this is */
2385 if (State)
2386 {
2387 /* Set the Level */
2388 *Mask |= Level;
2389 }
2390 else
2391 {
2392 /* Remove the Level */
2393 *Mask &= ~Level;
2394 }
2395
2396 /* Success */
2397 return STATUS_SUCCESS;
2398 }