mirror of https://github.com/tongzx/nt5src
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.
426 lines
11 KiB
426 lines
11 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bushnd.c
|
|
|
|
Abstract:
|
|
|
|
KD Extension for BUS_HANDLER data structures.
|
|
|
|
Author:
|
|
|
|
Peter Johnston (peterj) 13-May-1998
|
|
|
|
Environment:
|
|
|
|
User Mode.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
//
|
|
// The following typedef is copied directly from nthals\bushnd.c.
|
|
//
|
|
|
|
/*
|
|
typedef struct _HAL_BUS_HANDLER {
|
|
LIST_ENTRY AllHandlers;
|
|
ULONG ReferenceCount;
|
|
BUS_HANDLER Handler;
|
|
} HAL_BUS_HANDLER, *PHAL_BUS_HANDLER;
|
|
*/
|
|
|
|
BOOLEAN
|
|
bushndReadMemory(
|
|
ULONG64 S,
|
|
PVOID D,
|
|
ULONG Len
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Wrapper for ReadMemory that's somewhat easier to use. Also
|
|
does a small amount of failsafe stuff, like failing the read
|
|
if the user pressed control-C.
|
|
|
|
Arguments:
|
|
|
|
S Source Address in host memory to read data from.
|
|
D Destination address in local memory.
|
|
Len length in bytes.
|
|
|
|
Return Value:
|
|
|
|
Returns TRUE if the operation was successful, FALSE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG result;
|
|
|
|
//
|
|
// Sanity: Only read kernel mode addresses. Kernel mode
|
|
// addresses are always greater than 2GB. Being greater than
|
|
// 2GB doesn't ensure it's kernel mode, but if it's less than
|
|
// 2GB it is certainly NOT kernel mode.
|
|
//
|
|
|
|
if (S < 0x80000000) {
|
|
dprintf("bushnd sanity: refusing to read usermode address %p\n", S);
|
|
return FALSE;
|
|
}
|
|
|
|
if (!ReadMemory(S,
|
|
D,
|
|
Len,
|
|
&result) && (result == Len)) {
|
|
|
|
dprintf("Unable to read structure at %p. ", S);
|
|
return FALSE;
|
|
}
|
|
|
|
if (CheckControlC()) {
|
|
dprintf("Terminating operation at user request.\n");
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
PUCHAR
|
|
bushndInterfaceType(
|
|
IN INTERFACE_TYPE InterfaceType
|
|
)
|
|
{
|
|
switch (InterfaceType) {
|
|
case InterfaceTypeUndefined: return "InterfaceTypeUndefined";
|
|
case Internal: return "Internal";
|
|
case Isa: return "Isa";
|
|
case Eisa: return "Eisa";
|
|
case MicroChannel: return "Micro Channel";
|
|
case TurboChannel: return "Turbo Channel";
|
|
case PCIBus: return "PCI";
|
|
case VMEBus: return "VME";
|
|
case NuBus: return "NuBus";
|
|
case PCMCIABus: return "PCMCIA";
|
|
case CBus: return "CBus";
|
|
case MPIBus: return "MPIBus";
|
|
case MPSABus: return "MPSABus";
|
|
case ProcessorInternal: return "Processor Internal";
|
|
case InternalPowerBus: return "Internal Power Bus";
|
|
case PNPISABus: return "PnP Isa";
|
|
case PNPBus: return "PnP Bus";
|
|
default: return "** Unknown Interface Type **";
|
|
}
|
|
}
|
|
|
|
VOID
|
|
bushndDisplayAddressRange(
|
|
IN ULONG64 HostAddress,
|
|
IN PUCHAR String
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Display a set of ranges. Used by bushndDisplayBusRanges.
|
|
(Pretty much just lifted this code from nthals/rangesup.c).
|
|
|
|
Arguments:
|
|
|
|
Pointer to a PSUPPORTED_RANGE structure. This is a linked
|
|
list of the ranges of this type for this bus handler.
|
|
|
|
Note: On entry we are pointing at a local copy of the first
|
|
PSUPPORTED_RANGE of this type embedded in the BUS_HANDLER
|
|
structure. We don't want to modify that so subsequent
|
|
ranges are read into a seperate local structure.
|
|
|
|
String. What sort of range this is (a heading).
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 Limit, Base, SystemBase, Next;
|
|
|
|
do {
|
|
|
|
InitTypeRead(HostAddress, SUPPORTED_RANGE);
|
|
|
|
Limit = ReadField(Limit); Base = ReadField(Base);
|
|
SystemBase = ReadField(SystemBase);
|
|
|
|
if (Limit) {
|
|
|
|
//
|
|
// Address->Limit == 0 means skip this range,... otherwise,...
|
|
//
|
|
// Print this range.
|
|
//
|
|
|
|
dprintf(" %s: %x:%08x - %x:%08x (tran %x:%08x space %d (r@%p))\n",
|
|
String,
|
|
(ULONG)(Base >> 32),
|
|
(ULONG)(Base),
|
|
(ULONG)(Limit >> 32),
|
|
(ULONG)(Limit),
|
|
(ULONG)(SystemBase >> 32),
|
|
(ULONG)(SystemBase),
|
|
(ULONG)ReadField(SystemAddressSpace),
|
|
HostAddress
|
|
);
|
|
String = " ";
|
|
}
|
|
|
|
//
|
|
// Advance.
|
|
//
|
|
|
|
if (!(HostAddress = ReadField(Next))) {
|
|
return;
|
|
}
|
|
|
|
if (GetFieldValue(HostAddress, "SUPPORTED_RANGE",
|
|
"Next", Next)) {
|
|
dprintf("Unable to follow range list.\n");
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Quick saftey check,... make sure we don't follow a
|
|
// self pointer,... would be good to do some more checking.
|
|
//
|
|
|
|
if (Next == HostAddress) {
|
|
|
|
//
|
|
// Self pointer.
|
|
//
|
|
|
|
dprintf("Ill-formed list, points to self at %p\n", HostAddress);
|
|
return;
|
|
}
|
|
|
|
} while (TRUE);
|
|
}
|
|
|
|
VOID
|
|
bushndDisplayBusRanges(
|
|
IN ULONG64 BusAddresses
|
|
)
|
|
{
|
|
ULONG Version, Offset;
|
|
|
|
if (!BusAddresses) {
|
|
dprintf(" No ranges associated with this bus.\n");
|
|
return;
|
|
}
|
|
|
|
if (GetFieldValue(BusAddresses, "SUPPORTED_RANGES",
|
|
"Version", Version)) {
|
|
dprintf("Cannot dump ranges for this bus handler.\n");
|
|
return;
|
|
}
|
|
|
|
GetFieldOffset("SUPPORTED_RANGES", "IO", &Offset);
|
|
bushndDisplayAddressRange(BusAddresses + Offset,
|
|
"IO......");
|
|
GetFieldOffset("SUPPORTED_RANGES", "Memory", &Offset);
|
|
bushndDisplayAddressRange(BusAddresses + Offset,
|
|
"Memory..");
|
|
GetFieldOffset("SUPPORTED_RANGES", "PrefetchMemory", &Offset);
|
|
bushndDisplayAddressRange(BusAddresses + Offset,
|
|
"PFMemory");
|
|
GetFieldOffset("SUPPORTED_RANGES", "Dma", &Offset);
|
|
bushndDisplayAddressRange(BusAddresses + Offset,
|
|
"DMA.....");
|
|
}
|
|
|
|
VOID
|
|
bushndDisplaySymbol(
|
|
IN PUCHAR Name,
|
|
IN ULONG64 Address
|
|
)
|
|
{
|
|
UCHAR Symbol[256];
|
|
ULONG64 Displacement;
|
|
|
|
GetSymbol((LONG64)Address, Symbol, &Displacement);
|
|
dprintf(" %s %08p (%s)\n", Name, Address, Symbol);
|
|
}
|
|
|
|
DECLARE_API( bushnd )
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
If no handler specified, dump the list of handlers and some simple
|
|
info about each of them.
|
|
|
|
If a handler is specified, dump everything we know about it.
|
|
|
|
Arguments:
|
|
|
|
Bus handler address [optional].
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG64 Handler;
|
|
ULONG64 HostHandler;
|
|
ULONG64 HalBusHandler;
|
|
ULONG64 HandlerListHead;
|
|
UCHAR SymbolBuffer[256];
|
|
|
|
HostHandler = GetExpression(args);
|
|
|
|
if (HostHandler) {
|
|
ULONG Version, InitTypeRead, InterfaceType;
|
|
ULONG64 DeviceObject, BusData;
|
|
|
|
//
|
|
// User supplied a handler address, dump details for that bus
|
|
// handler.
|
|
//
|
|
|
|
|
|
if (GetFieldValue(HostHandler, "BUS_HANDLER",
|
|
"Version", Version)) {
|
|
|
|
dprintf("-- Cannot continue --\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
InitTypeRead(HostHandler, BUS_HANDLER);
|
|
InterfaceType = (ULONG) ReadField(InterfaceType);
|
|
dprintf("Dump of bus handler %p\n", HostHandler);
|
|
dprintf(" Version %d\n", Version);
|
|
dprintf(" Interface Type (%d) = %s\n",
|
|
InterfaceType,
|
|
bushndInterfaceType(InterfaceType));
|
|
dprintf(" Bus Number %d\n", (ULONG) ReadField(BusNumber));
|
|
if (DeviceObject = ReadField(DeviceObject)) {
|
|
dprintf(" Device Object %p\n",
|
|
DeviceObject);
|
|
}
|
|
dprintf(" Parent Bus Handler %p\n", ReadField(ParentHandler));
|
|
if (BusData = ReadField(BusData)) {
|
|
dprintf(" BusData %p\n", BusData);
|
|
}
|
|
|
|
bushndDisplaySymbol("GetBusData ", ReadField(GetBusData));
|
|
bushndDisplaySymbol("SetBusData ", ReadField(SetBusData));
|
|
bushndDisplaySymbol("AdjustResourceList ", ReadField(AdjustResourceList));
|
|
bushndDisplaySymbol("AssignSlotResources", ReadField(AssignSlotResources));
|
|
bushndDisplaySymbol("GetInterruptVector ", ReadField(GetInterruptVector));
|
|
bushndDisplaySymbol("TranslateBusAddress", ReadField(TranslateBusAddress));
|
|
|
|
bushndDisplayBusRanges(ReadField(BusAddresses));
|
|
|
|
} else {
|
|
ULONG Off;
|
|
|
|
//
|
|
// User did not supply a handler address, try to find the
|
|
// list of all bus handlers and dump a summary of each handler.
|
|
//
|
|
|
|
HandlerListHead = GetExpression("hal!HalpAllBusHandlers");
|
|
|
|
if (!HandlerListHead) {
|
|
|
|
//
|
|
// Couldn't get address of HalpAllBusHandlers. Whine
|
|
// at user.
|
|
//
|
|
|
|
dprintf(
|
|
"Unable to get address of HalpAllBusHandlers, most likely\n"
|
|
"cause is failure to load HAL symbols, or, this HAL might\n"
|
|
"not actually use bus handlers. "
|
|
);
|
|
|
|
dprintf("-- Cannot continue --");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (GetFieldValue(HandlerListHead, "LIST_ENTRY",
|
|
"Flink", HalBusHandler)) {
|
|
dprintf(
|
|
"Could not read HalpAllBusHandlers from host memory (%p).\n"
|
|
"This is most likely caused by incorrect HAL symbols.\n",
|
|
HandlerListHead
|
|
);
|
|
|
|
dprintf("-- Cannot continue --\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
if (HalBusHandler == HandlerListHead) {
|
|
|
|
dprintf(
|
|
"HalpAllBusHandlers found (at %p) but list is empty.\n",
|
|
HandlerListHead
|
|
);
|
|
|
|
dprintf("-- Cannot continue --\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
GetFieldOffset("hal!_HAL_BUS_HANDLER", "Handler", &Off);
|
|
|
|
//
|
|
// In theory, we now have the handler list. Walk it.
|
|
//
|
|
|
|
do {
|
|
ULONG64 Next;
|
|
ULONG BusNumber, InterfaceType;
|
|
|
|
if (GetFieldValue(HalBusHandler, "hal!_HAL_BUS_HANDLER",
|
|
"AllHandlers.Flink", Next)) {
|
|
|
|
dprintf("-- Cannot continue --\n");
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//
|
|
// Brief summary.
|
|
//
|
|
|
|
Handler = HalBusHandler + Off;
|
|
GetFieldValue(HalBusHandler, "hal!_HAL_BUS_HANDLER", "BusNumber", BusNumber);
|
|
GetFieldValue(HalBusHandler, "hal!_HAL_BUS_HANDLER", "Handler.InterfaceType", InterfaceType);
|
|
dprintf(
|
|
"%p bus %d, type %s\n",
|
|
Handler,
|
|
BusNumber,
|
|
bushndInterfaceType(InterfaceType)
|
|
);
|
|
|
|
//
|
|
// Advance to next.
|
|
//
|
|
|
|
HalBusHandler = Next;
|
|
|
|
} while (HalBusHandler != HandlerListHead);
|
|
}
|
|
return S_OK;
|
|
}
|