Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

609 lines
13 KiB

/*++
Copyright (c) 1992-2001 Microsoft Corporation
Module Name:
physical.cpp
Abstract:
Extensions to read/display physocal memory
Environment:
User Mode.
Revision History:
Kshitiz K. Sharma (kksharma) 5/9/2001
--*/
#include "precomp.h"
#pragma hdrstop
#define PHYS_READ_MATCH_DUMPSIZE 0x100
#define PHYS_FLAG_MESSAGE \
"If you know the caching attributes used for the memory,\n" \
"try specifying [c], [uc] or [wc], as in !dd [c] <params>.\n" \
"WARNING: Incorrect use of these flags will cause unpredictable\n" \
"processor corruption. This may immediately (or at any time in\n" \
"the future until reboot) result in a system hang, incorrect data\n" \
"being displayed or other strange crashes and corruption.\n"
ULONG64 g_LastAddress = 0;
VOID
ReadPhysicalInChunks(
ULONG64 Address,
PUCHAR Buffer,
ULONG BufferSize,
ULONG Flags,
ULONG ChunkSize,
PULONG ActualRead
)
{
if ((Flags & PHYS_READ_MATCH_DUMPSIZE) &&
(ChunkSize != 0)) {
DWORD i, ret;
PUCHAR pReadBuff;
Flags &= 0xf;
for (i=0, pReadBuff = Buffer; i<BufferSize;
i+=ChunkSize, pReadBuff+=ChunkSize) {
ReadPhysicalWithFlags(Address + i,
pReadBuff,ChunkSize,Flags,&ret);
if (ret != ChunkSize) {
break;
}
*ActualRead += ret;
}
} else {
Flags &= 0xf;
ReadPhysicalWithFlags(Address,Buffer,BufferSize,Flags,ActualRead);
}
return;
}
/*++
Routine Description:
Dumps specified range of physical memory in given format
Arguments:
Address - Address to start
NumEntries - Number of entries to dump
EntrySize - Size of each entry
ShowAsAscii - print corresponding ascii chars
Return Value:
None.
--*/
BOOL
DumpPhysicalMemory(
ULONG64 Address,
ULONG NumEntries,
ULONG EntrySize,
BOOL ShowAsAscii,
ULONG Flags
)
{
#define NumberBytesToRead 32*4
UCHAR Buffer[NumberBytesToRead];
ULONG ActualRead=0;
if ((EntrySize != 1) && (EntrySize != 2) && (EntrySize != 4) && (EntrySize != 8)) {
EntrySize=4;
}
while (1) {
if (CheckControlC()) {
break;
}
ReadPhysicalInChunks(Address,Buffer,sizeof(Buffer),Flags, EntrySize,&ActualRead);
if (ActualRead != sizeof(Buffer) &&
ActualRead < NumEntries*EntrySize) {
dprintf("Physical memory read at %I64lx failed\n", Address);
if (Flags == PHYS_FLAG_DEFAULT && ActualRead == 0) {
dprintf(PHYS_FLAG_MESSAGE);
}
return FALSE;
} else {
PCHAR DumpByte = (PCHAR)&Buffer[0], pRow;
ULONG cnt;
for(cnt=0;cnt<NumberBytesToRead;DumpByte+=EntrySize) {
if (!(cnt & 0xf)) {
dprintf("#%8I64lx", Address+cnt);
pRow = DumpByte;
}
switch (EntrySize) {
case 1:
dprintf("%c%02lx", ((cnt&0xf) == 8 ? '-' : ' '),*((PUCHAR)DumpByte));
break;
case 2:
dprintf(" %04lx", *((PUSHORT) DumpByte));
break;
case 4:
dprintf(" %08lx", *((PULONG) DumpByte));
break;
case 8:
dprintf(" %08lx'%08lx", *((PULONG) DumpByte), *((PULONG) (DumpByte+4)));
break;
}
cnt+=EntrySize, NumEntries--;
if ((cnt && !(cnt & 0xf)) || !NumEntries) {
if (ShowAsAscii) {
unsigned char ch;
dprintf(" ");
for (ULONG d=0; d < 16; d++) {
ch = (UCHAR) pRow[d];
if (ch < 0x20 || ch > 0x7e) {
ch = '.';
}
dprintf("%c", ch);
}
}
dprintf("\n");
}
if (!NumEntries) {
break;
}
}
Address += cnt;
if (!NumEntries) {
break;
}
}
}
g_LastAddress = Address;
return TRUE;
}
/*++
Routine Description:
Reverse sign extension of the value returned by GetExpression()
based on the assumption that no physical address may be bigger
than 0xfffffff00000000.
Arguments:
Val - points to the value to reverse sign extension
Return Value:
None.
--*/
void
ReverseSignExtension(ULONG64* Val)
{
if ((*Val & 0xffffffff00000000) == 0xffffffff00000000)
{
*Val &= 0x00000000ffffffff;
}
}
PCSTR
GetPhyFlags(PCSTR Args, PULONG Flags)
{
*Flags = PHYS_FLAG_DEFAULT;
while (*Args && (*Args == ' ' || *Args == '\t')) {
++Args;
}
if (*Args == '[') {
Args++;
if (*Args == 'c') {
*Flags = PHYS_FLAG_CACHED;
Args++;
} else if (*Args == 'u' && *(Args + 1) == 'c') {
*Flags = PHYS_FLAG_UNCACHED;
Args += 2;
} else if (*Args == 'w' && *(Args + 1) == 'c') {
*Flags = PHYS_FLAG_WRITE_COMBINED;
Args += 2;
}
if (*Args != ']') {
*Flags = PHYS_FLAG_DEFAULT;
dprintf("Unknown physical memory caching attribute\n");
} else {
Args++;
}
}
if (*Args == '-' || *Args == '\\') {
++Args;
if (tolower(*Args) == 'm') {
*Flags |= PHYS_READ_MATCH_DUMPSIZE;
} else {
dprintf("Bad argument -%s\n", Args);
}
++Args;
}
return Args;
}
void
GetPhyDumpArgs(
PCSTR Args,
PULONG64 Address,
PULONG Range,
PULONG Flags
)
{
CHAR Buffer[100]={0};
*Flags = PHYS_FLAG_DEFAULT;
if(*Args == '\0') {
*Address=g_LastAddress;
} else {
Args = GetPhyFlags(Args, Flags);
while (*Args && (*Args == ' ' || *Args == '\t')) {
++Args;
}
if(*Args == '\0') {
*Address=g_LastAddress;
} else {
GetExpressionEx(Args, Address, &Args);
ReverseSignExtension(Address);
*Address &= (~0x3); // Truncate to dword boundary
g_LastAddress=*Address;
while (*Args && (*Args == ' ' || *Args == '\t')) {
++Args;
}
if (*Args == 'l' || *Args == 'L') {
++Args;
*Range = (ULONG) GetExpression(Args);
}
}
}
return;
}
DECLARE_API( db )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
ULONG Flags;
GetPhyDumpArgs(args, &Address, &Range, &Flags);
if (!Range) {
Range = 128;
}
DumpPhysicalMemory(Address, Range, 1, TRUE, Flags);
return S_OK;
}
DECLARE_API( dd )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
ULONG Flags;
GetPhyDumpArgs(args, &Address, &Range, &Flags);
if (!Range) {
Range = 32;
}
DumpPhysicalMemory(Address, Range, 4, FALSE, Flags);
return S_OK;
}
DECLARE_API( dw )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
ULONG Flags;
GetPhyDumpArgs(args, &Address, &Range, &Flags);
if (!Range) {
Range = 64;
}
DumpPhysicalMemory(Address, Range, 2, FALSE, Flags);
return S_OK;
}
DECLARE_API( dp )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
ULONG Flags;
GetPhyDumpArgs(args, &Address, &Range, &Flags);
if (!Range) {
Range = IsPtr64() ? 16 : 32;
}
DumpPhysicalMemory(Address, Range, IsPtr64() ? 8 : 4, FALSE, Flags);
return S_OK;
}
DECLARE_API( dc )
/*++
Routine Description:
Does a read of N ULONGS from the physical memory of the target machine,
dumping both hex and ASCII.
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0;
ULONG Flags;
GetPhyDumpArgs(args, &Address, &Range, &Flags);
if (!Range) {
Range = 32;
}
DumpPhysicalMemory(Address, Range, 4, TRUE, Flags);
return S_OK;
}
DECLARE_API( du )
/*++
Routine Description:
Does a read of 16 ULONGS from the physical memory of the target machine
Arguments:
args - Supplies physical address
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Range = 0, ActualRead;
WCHAR Buffer[MAX_PATH]={0};
ULONG Flags;
GetPhyDumpArgs(args, &Address, &Range, &Flags);
if (Range>MAX_PATH) {
Range = MAX_PATH;
}
if (!Range) {
Range = 16;
}
ReadPhysicalWithFlags(Address,Buffer,Range * sizeof(WCHAR),Flags,&ActualRead);
if (ActualRead != Range*sizeof(WCHAR)) {
dprintf("Physical memory read at %I64lx failed\n", Address);
if (Flags == PHYS_FLAG_DEFAULT && ActualRead == 0) {
dprintf(PHYS_FLAG_MESSAGE);
}
return FALSE;
} else {
ULONG cnt;
dprintf("#%8I64lx \"", Address);
for (ULONG d=0; d < Range; d++) {
WCHAR ch = Buffer[d];
if (ch == 0) {
break;
}
if (ch < 0x20 || ch > 0x7e) {
ch = '.';
}
dprintf("%wc", ch);
}
dprintf("\"\n");
}
return S_OK;
}
DECLARE_API( ed )
/*++
Routine Description:
Writes a sequence of ULONGs into a given physical address on the
target machine.
Arguments:
arg - Supplies both the target address and the data in the form of
"PHYSICAL_ADDRESS ULONG [ULONG, ULONG,...]"
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Buffer;
ULONG ActualWritten=0;
PCHAR NextToken;
ULONG Flags;
args = GetPhyFlags(args, &Flags);
Address = GetExpression(args);
strtok((PSTR)args," \t,"); // The first token is the address
// Since we're picking off one ULONG at a time, we'll make
// one DbgKdWritePhysicalMemoryAddress call per ULONG. This
// is slow, but easy to code.
while((NextToken=strtok(NULL," \t,")) != NULL) {
if (!sscanf(NextToken,"%lx",&Buffer)) {
break;
}
WritePhysicalWithFlags(Address,&Buffer,sizeof(Buffer),Flags,
&ActualWritten);
if (ActualWritten != sizeof(Buffer)) {
dprintf("Physical memory write at %I64lx failed\n", Address);
if (Flags == PHYS_FLAG_DEFAULT && ActualWritten == 0) {
dprintf(PHYS_FLAG_MESSAGE);
}
}
Address+=sizeof(Buffer);
}
return S_OK;
}
DECLARE_API( eb )
/*++
Routine Description:
Writes a sequence of BYTEs into a given physical address on the
target machine.
Arguments:
arg - Supplies both the target address and the data in the form of
"PHYSICAL_ADDRESS ULONG [ULONG, ULONG,...]"
Return Value:
None.
--*/
{
ULONG64 Address = 0;
ULONG Buffer;
UCHAR c;
ULONG ActualWritten;
PCHAR NextToken;
ULONG Flags;
UNREFERENCED_PARAMETER (Client);
args = GetPhyFlags(args, &Flags);
Address = GetExpression(args);
strtok((PSTR)args," \t,"); // The first token is the address
// Since we're picking off one BYTE at a time, we'll make
// one DbgKdWritePhysicalMemoryAddress call per BYTE. This
// is slow, but easy to code.
while((NextToken=strtok(NULL," \t,")) != NULL) {
if (!sscanf(NextToken,"%lx",&Buffer)) {
break;
}
c = (UCHAR)Buffer;
WritePhysicalWithFlags(Address,&c,sizeof(UCHAR),Flags,&ActualWritten);
if (ActualWritten != sizeof(UCHAR)) {
dprintf("Physical memory write at %I64lx failed\n", Address);
if (Flags == PHYS_FLAG_DEFAULT && ActualWritten == 0) {
dprintf(PHYS_FLAG_MESSAGE);
}
}
Address+=sizeof(UCHAR);
}
return S_OK;
}