427 lines
11 KiB
C
427 lines
11 KiB
C
/*++
|
||
|
||
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;
|
||
}
|