xbox-kernel/private/ntos/kd64/kdinit.c
2020-09-30 17:17:25 +02:00

314 lines
8.4 KiB
C

/*++
Copyright (c) 1990-1999 Microsoft Corporation
Module Name:
kdinit.c
Abstract:
This module implements the initialization for the portable kernel debgger.
Author:
David N. Cutler 27-July-1990
Revision History:
--*/
#include "kdp.h"
#define ROM_BASE_ADDRESS 0xFFF00000
#define ROM_VERSION_OFFSET 30 // In DWORDs (0x78 is the absolute offset)
#define ROM_VERSION_KDDELAY_FLAG 0x80000000
VOID
KdInitSystem(
BOOLEAN InitializingSystem
)
/*++
Routine Description:
This routine initializes the portable kernel debugger.
Arguments:
InitializingSystem - Supplies a boolean value that determines whether we're
called in the context of system initialization or bugcheck code.
Return Value:
None.
--*/
{
ULONG Index;
BOOLEAN SuperIoInitialized;
BOOLEAN Initialize;
STRING NameString;
//
// If kernel debugger is already initialized, then return.
//
if (KdDebuggerEnabled != FALSE) {
return;
}
KiDebugRoutine = KdpStub;
//
// Determine whether or not the debugger should be enabled.
//
// Note that if InitializingSystem == FALSE, then KdInitSystem was called
// from BugCheck code. For this case the debugger is always enabled
// to report the bugcheck if possible.
//
if (InitializingSystem) {
//
// Initialize the loader data table entry for XBOXKRNL.EXE and attach it
// to the loaded module list.
//
KdpNtosDataTableEntry.DllBase = PsNtosImageBase;
KdpNtosDataTableEntry.SizeOfImage =
RtlImageNtHeader(PsNtosImageBase)->OptionalHeader.SizeOfImage;
KdpNtosDataTableEntry.LoadedImports = (PVOID)MAXULONG_PTR;
RtlInitUnicodeString(&KdpNtosDataTableEntry.FullDllName, L"xboxkrnl.exe");
RtlInitUnicodeString(&KdpNtosDataTableEntry.BaseDllName, L"xboxkrnl.exe");
InsertTailList(&KdLoadedModuleList, &KdpNtosDataTableEntry.InLoadOrderLinks);
//
// Initialize the debugger data block list when called at startup time.
//
InitializeListHead(&KdpDebuggerDataListHead);
//
// Fill in and register the debugger's debugger data block.
// Most fields are already initialized, some fields will not be
// filled in until later.
//
KdDebuggerDataBlock.KernBase = (ULONG_PTR) PsNtosImageBase;
KdRegisterDebuggerDataBlock(KDBG_TAG,
&KdDebuggerDataBlock.Header,
sizeof(KdDebuggerDataBlock));
//
// Always initialize the kernel debugger if the system has a super I/O
// controller that we can communicate with.
//
HalPulseHardwareMonitorPin();
Initialize = HalInitializeSuperIo();
} else {
Initialize = TRUE;
}
if ((KdPortInitialize(&KdDebugParameters, Initialize) == FALSE) ||
(Initialize == FALSE)) {
return;
}
//
// If we're going to delay the kernel debugger setup, then mark the debugger
// as not present for now.
//
if (((PULONG)ROM_BASE_ADDRESS)[ROM_VERSION_OFFSET] & ROM_VERSION_KDDELAY_FLAG) {
KdDebuggerNotPresent = TRUE;
}
//
// Set address of kernel debugger trap routine.
//
KiDebugRoutine = KdpTrap;
if (!KdpDebuggerStructuresInitialized) {
KdpBreakpointInstruction = KDP_BREAKPOINT_VALUE;
KdpOweBreakpoint = FALSE;
//
// Initialize the breakpoint table.
//
for (Index = 0; Index < BREAKPOINT_TABLE_SIZE; Index += 1) {
KdpBreakpointTable[Index].Flags = 0;
KdpBreakpointTable[Index].Address = NULL;
}
KdpDebuggerStructuresInitialized = TRUE ;
}
//
// Initialize timer facility - HACKHACK
//
KdPerformanceCounterRate = KeQueryPerformanceFrequency();
KdTimerStart.HighPart = 0L;
KdTimerStart.LowPart = 0L;
//
// Initialize ID for NEXT packet to send and Expect ID of next incoming
// packet.
//
KdpNextPacketIdToSend = INITIAL_PACKET_ID | SYNC_PACKET_ID;
KdpPacketIdExpected = INITIAL_PACKET_ID;
//
// Mark debugger enabled.
//
KdDebuggerEnabled = TRUE;
//
// Notify the debugger that XBOXKRNL.EXE is loaded.
//
if (InitializingSystem) {
RtlInitAnsiString(&NameString, "xboxkrnl.exe");
DbgLoadImageSymbols(&NameString, PsNtosImageBase, (ULONG)-1);
}
}
BOOLEAN
KdRegisterDebuggerDataBlock(
IN ULONG Tag,
IN PDBGKD_DEBUG_DATA_HEADER64 DataHeader,
IN ULONG Size
)
/*++
Routine Description:
This routine is called by a component or driver to register a
debugger data block. The data block is made accessible to the
kernel debugger, thus providing a reliable method of exposing
random data to debugger extensions.
Arguments:
Tag - Supplies a unique 4 byte tag which is used to identify the
data block.
DataHeader - Supplies the address of the debugger data block header.
The OwnerTag field must contain a unique value, and the Size
field must contain the size of the data block, including the
header. If this block is already present, or there is
already a block with the same value for OwnerTag, this one
will not be inserted. If Size is incorrect, this code will
not notice, but the usermode side of the debugger might not
function correctly.
Size - Supplies the size of the data block, including the header.
Return Value:
TRUE if the block was added to the list, FALSE if not.
--*/
{
KIRQL OldIrql;
PLIST_ENTRY List;
PDBGKD_DEBUG_DATA_HEADER64 Header;
OldIrql = KeRaiseIrqlToDpcLevel();
//
// Look for a record with the same tag or address
//
List = KdpDebuggerDataListHead.Flink;
while (List != &KdpDebuggerDataListHead) {
Header = CONTAINING_RECORD(List, DBGKD_DEBUG_DATA_HEADER64, List);
List = List->Flink;
if ((Header == DataHeader) || (Header->OwnerTag == Tag)) {
KeLowerIrql(OldIrql);
return FALSE;
}
}
//
// It wasn't already there, so add it.
//
DataHeader->OwnerTag = Tag;
DataHeader->Size = Size;
InsertTailList(&KdpDebuggerDataListHead, (PLIST_ENTRY)(&DataHeader->List));
KeLowerIrql(OldIrql);
return TRUE;
}
VOID
KdLogDbgPrint(
IN PSTRING String
)
{
KIRQL OldIrql;
ULONG Length;
ULONG LengthCopied;
KeRaiseIrql (HIGH_LEVEL, &OldIrql);
if (KdPrintCircularBuffer) {
Length = String->Length;
//
// truncate ridiculous strings
//
if (Length > KDPRINTBUFFERSIZE) {
Length = KDPRINTBUFFERSIZE;
}
if (KdPrintWritePointer + Length <= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) {
LengthCopied = KdpMoveMemory(KdPrintWritePointer, String->Buffer, Length);
KdPrintWritePointer += LengthCopied;
if (KdPrintWritePointer >= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) {
KdPrintWritePointer = KdPrintCircularBuffer;
KdPrintRolloverCount++;
}
} else {
ULONG First = (ULONG)(KdPrintCircularBuffer + KDPRINTBUFFERSIZE - KdPrintWritePointer);
LengthCopied = KdpMoveMemory(KdPrintWritePointer,
String->Buffer,
First);
if (LengthCopied == First) {
LengthCopied += KdpMoveMemory(KdPrintCircularBuffer,
String->Buffer + First,
Length - First);
}
if (LengthCopied > First) {
KdPrintWritePointer = KdPrintCircularBuffer + LengthCopied - First;
KdPrintRolloverCount++;
} else {
KdPrintWritePointer += LengthCopied;
if (KdPrintWritePointer >= KdPrintCircularBuffer+KDPRINTBUFFERSIZE) {
KdPrintWritePointer = KdPrintCircularBuffer;
KdPrintRolloverCount++;
}
}
}
}
KeLowerIrql(OldIrql);
}