HyperDbg/hyperdbg/libhyperdbg/code/debugger/commands/extension-commands/pcicam.cpp
Max Raulea 38a59b795f
Some checks are pending
vs2026-ci / win-amd64-build (debug, x64) (push) Waiting to run
vs2026-ci / win-amd64-build (release, x64) (push) Waiting to run
vs2026-ci / Deploy release (push) Blocked by required conditions
Some new lib calls and reverted sleep macro to function
2026-07-17 17:54:05 +02:00

374 lines
20 KiB
C++
Raw Permalink Blame History

/**
* @file pcicam.cpp
* @author Bj<42>rn Ruytenberg (bjorn@bjornweb.nl)
* @brief !pcicam command
* @details
* @version 0.13
* @date 2024-12-17
*
* @copyright This project is released under the GNU Public License v3.
*
*/
#include "pch.h"
//
// Global Variables
//
extern BOOLEAN g_IsKdModuleLoaded;
extern BOOLEAN g_IsSerialConnectedToRemoteDebuggee;
/**
* @brief !pcicam command help
*
* @return VOID
*/
VOID
CommandPcicamHelp()
{
ShowMessages("!pcicam : dumps the PCI configuration space (CAM) for a given device.\n\n");
ShowMessages("syntax : \t!pcicam [Bus (hex)] [Device (hex)] [Function (hex)]\n");
ShowMessages("syntax : \t!pcicam [Bus (hex)] [Device (hex)] [Function (hex)] [Dump (string)]\n");
ShowMessages("\n");
ShowMessages("\t\te.g : !pcicam 0 2 0\n");
ShowMessages("\t\te.g : !pcicam 3 0 0 x\n");
}
/**
* @brief !pcicam command handler
*
* @param CommandTokens
* @param Command
*
* @return VOID
*/
VOID
CommandPcicam(vector<CommandToken> CommandTokens, string Command)
{
BOOL Status;
ULONG ReturnedLength;
DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PcidevinfoPacket = {0};
UINT32 TargetBus = 0;
UINT32 TargetDevice = 0;
UINT32 TargetFunction = 0;
const CHAR * PciHeaderTypes[] = {"Endpoint", "PCI-to-PCI Bridge", "PCI-to-CardBus Bridge"};
if (CommandTokens.size() < 4 || CommandTokens.size() > 5)
{
ShowMessages("Incorrect use of '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
CommandPcicamHelp();
return;
}
if (ConvertTokenToUInt32(CommandTokens.at(1), &TargetBus))
{
if (TargetBus > BUS_MAX_NUM)
{
ShowMessages("Invalid bus number '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str());
CommandPcicamHelp();
return;
}
PcidevinfoPacket.DeviceInfo.Bus = (UINT8)TargetBus;
}
if (ConvertTokenToUInt32(CommandTokens.at(2), &TargetDevice))
{
if (TargetDevice > DEVICE_MAX_NUM)
{
ShowMessages("Invalid device number '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str());
CommandPcicamHelp();
return;
}
PcidevinfoPacket.DeviceInfo.Device = (UINT8)TargetDevice;
}
if (ConvertTokenToUInt32(CommandTokens.at(3), &TargetFunction))
{
if (TargetFunction > FUNCTION_MAX_NUM)
{
ShowMessages("Invalid function number '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str());
CommandPcicamHelp();
return;
}
PcidevinfoPacket.DeviceInfo.Function = (UINT8)TargetFunction;
}
if (CommandTokens.size() == 5)
{
if (strncmp(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)).c_str(), "x", 1) == 0)
{
PcidevinfoPacket.PrintRaw = TRUE;
}
else
{
ShowMessages("Invalid parameter '%s'\n\n",
GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)).c_str());
CommandPcicamHelp();
return;
}
}
//
// Send buffer
//
if (g_IsSerialConnectedToRemoteDebuggee)
{
KdSendPcidevinfoPacketToDebuggee(&PcidevinfoPacket);
}
else
{
AssertShowMessageReturnStmt(g_IsKdModuleLoaded, g_DeviceHandle, ASSERT_MESSAGE_KD_NOT_LOADED, ASSERT_MESSAGE_DRIVER_NOT_LOADED, AssertReturn);
//
// Send IOCTL
//
Status = DeviceIoControl(
g_DeviceHandle, // Handle to device
IOCTL_PCIDEVINFO_ENUM, // IO Control Code (IOCTL)
&PcidevinfoPacket, // Input Buffer to driver.
SIZEOF_DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET, // Input buffer length
&PcidevinfoPacket, // Output Buffer from driver.
SIZEOF_DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET, // Length of output
// buffer in bytes.
&ReturnedLength, // Bytes placed in buffer.
NULL // synchronous call
);
if (!Status)
{
ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
return;
}
if (PcidevinfoPacket.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
{
//
// For some reason, MSVC refuses to initialize these at top of case
//
const CHAR * PciHeaderTypeAsString[] = {"Endpoint", "PCI-to-PCI Bridge", "PCI-to-CardBus Bridge"};
const CHAR * PciMmioBarTypeAsString[] = {"32-bit Wide",
"Reserved",
"64-bit Wide",
"Reserved"};
UINT8 BarNumOffset = 0;
ShowMessages("PCI configuration space (CAM) for device %04x:%02x:%02x:%x\n",
0, // TODO: Add support for domains beyond 0000
PcidevinfoPacket.DeviceInfo.Bus,
PcidevinfoPacket.DeviceInfo.Device,
PcidevinfoPacket.DeviceInfo.Function);
if (!PcidevinfoPacket.PrintRaw)
{
Vendor * CurrentVendor = GetVendorById(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.VendorId);
CHAR * CurrentVendorName = (CHAR *)"N/A";
CHAR * CurrentDeviceName = (CHAR *)"N/A";
if (CurrentVendor != NULL)
{
CurrentVendorName = CurrentVendor->VendorName;
Device * CurrentDevice = GetDeviceFromVendor(CurrentVendor, PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.DeviceId);
if (CurrentDevice != NULL)
{
CurrentDeviceName = CurrentDevice->DeviceName;
}
}
ShowMessages("\nCommon Header:\nVID:DID: %04x:%04x\nVendor Name: %-17.*s\nDevice Name: %.*s\nCommand: %04x\n",
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.VendorId,
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.DeviceId,
PlatformStrnlen(CurrentVendorName, PCI_NAME_STR_LENGTH),
CurrentVendorName,
PlatformStrnlen(CurrentDeviceName, PCI_NAME_STR_LENGTH),
CurrentDeviceName,
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command);
if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0) // Only applicable to endpoints
{
ShowMessages(" Memory Space: %u\n I/O Space: %u\n",
(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1,
(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x1));
}
ShowMessages("Status: %04x\nRevision ID: %02x\nClass Code: %06x\nCacheLineSize: %02x\nPrimaryLatencyTimer: %02x\nHeaderType: %s (%02x)\n Multi-function Device: %s\nBist: %02x\n",
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Status,
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.RevisionId,
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.ClassCode,
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.CacheLineSize,
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.PrimaryLatencyTimer,
(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) < 2 ? PciHeaderTypeAsString[(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x1)] : "Unknown",
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType,
(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x1) ? "True" : "False",
PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Bist);
FreeVendor(CurrentVendor);
FreePciIdDatabase();
ShowMessages("\nDevice Header:\n");
if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0) // Endpoint
{
for (UINT8 i = 0; i < 5; i++)
{
//
// Memory I/O
//
if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x1) == 0)
{
//
// 64-bit BAR
//
if (((PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1) == 2)
{
UINT64 BarMsb = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i + 1];
UINT64 BarLsb = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i];
UINT64 ActualBar = ((BarMsb & 0xFFFFFFFF) << 32) + (BarLsb & 0xFFFFFFF0);
ShowMessages("BAR%u %s\n BAR Type: MMIO\n MMIO BAR Type: %s (%02x)\n BAR MSB: %08x\n BAR LSB: %08x\n BAR (actual): %016llx\n Prefetchable: %s\n",
i - BarNumOffset,
((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1 == 0) || !PcidevinfoPacket.DeviceInfo.MmioBarInfo[i].IsEnabled ? "[disabled]" : "",
PciMmioBarTypeAsString[(PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1],
(PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1,
BarMsb,
BarLsb,
ActualBar,
(PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x8 >> 3) ? "True" : "False");
i++;
BarNumOffset++;
}
//
// 32-bit BAR
//
else
{
UINT32 ActualBar = (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFF0);
ShowMessages("BAR%u %s\n BAR Type: MMIO\n BAR: %08x\n BAR (actual): %08x\n Prefetchable: %s\n",
i - BarNumOffset,
((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1 == 0) || !PcidevinfoPacket.DeviceInfo.MmioBarInfo[i].IsEnabled ? "[disabled]" : "",
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i],
ActualBar,
(PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x8 >> 3) ? "True" : "False");
}
}
//
// Port I/O
//
else
{
//
// 32-bit BAR is the only flavor we have here
//
UINT32 ActualBar32 = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFFC;
ShowMessages("BAR%u %s\n BAR Type: Port IO\n BAR: %08x\n BAR (actual): %08x\n Reserved: %u\n",
i - BarNumOffset,
((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x1) == 0) ? "[disabled]" : "",
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i],
ActualBar32,
(PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x2) >> 1);
}
}
ShowMessages("Cardbus CIS Pointer: %08x\nSubsystem Vendor ID: %04x\nSubsystem ID: %04x\nROM BAR: %08x\nCapabilities Pointer: %02x\nReserved (0xD): %06x\nReserved (0xE): %08x\nInterrupt Line: %02x\nInterrupt Pin: %02x\nMin Grant: %02x\nMax latency: %02x\n",
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.CardBusCISPtr,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.SubVendorId,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.SubSystemId,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.ROMBar,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.CapabilitiesPtr,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Reserved,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Reserved1,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.InterruptLine,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.InterruptPin,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.MinGnt,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.MaxLat);
}
else if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) == 1) // PCI-to-PCI Bridge
{
ShowMessages("BAR0: %08x\nBAR1: %08x\n", PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Bar[0], PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Bar[1]);
ShowMessages("Primary Bus Number: %02x\nSecondary Bus Number: %02x\nSubordinate Bus Number: %02x\nSecondary Latency Timer: %02x\nI/O Base: %02x\nI/O Limit: %02x\nSecondary Status: %04x\nMemory Base: %04x\nMemory Limit: %04x\nPrefetchable Memory Base: %04x\nPrefetchable Memory Limit: %04x\nPrefetchable Base Upper 32 Bits: %08x\nPrefetchable Limit Upper 32 Bits: %08x\nI/O Base Upper 16 Bits: %04x\nI/O Limit Upper 16 Bits: %04x\nCapability Pointer: %02x\nReserved: %06x\nROM BAR: %08x\nInterrupt Line: %02x\nInterrupt Pin: %02x\nBridge Control: %04x\n",
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrimaryBusNumber,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryBusNumber,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SubordinateBusNumber,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryLatencyTimer,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoBase,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoLimit,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.SecondaryStatus,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.MemoryBase,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.MemoryLimit,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableMemoryBase,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableMemoryLimit,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableBaseUpper32b,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.PrefetchableLimitUpper32b,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoLimitUpper16b,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.IoBaseUpper16b,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.CapabilityPtr,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Reserved,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.ROMBar,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.InterruptLine,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.InterruptPin,
PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.BridgeControl);
}
else if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) == 2) // PCI-to-CardBus Bridge
{
ShowMessages("Parsing header type %s (%02x) currently unsupported\n", PciHeaderTypeAsString[PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01], PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01);
}
else
{
ShowMessages("\nDevice Header:\nUnknown header type %02x\n", (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f));
}
}
else
{
UINT32 * cs = (UINT32 *)&PcidevinfoPacket.DeviceInfo.ConfigSpace; // Overflows into .ConfigSpaceAdditional - no padding due to pack(0)
ShowMessages(" 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
for (UINT16 i = 0; i < CAM_CONFIG_SPACE_LENGTH; i += 16)
{
ShowMessages("%02x: ", i);
for (UINT8 j = 0; j < 16; j++)
{
ShowMessages("%02x ", *(((BYTE *)cs) + j));
}
//
// Print ASCII representation
// Replace non-printable characters with "."
//
for (UINT8 j = 0; j < 16; j++)
{
CHAR c = (CHAR) * (cs + j);
if (c >= 32 && c <= 126)
{
ShowMessages("%c", c);
}
else
{
ShowMessages(".");
}
}
ShowMessages("\n");
cs += 4;
}
}
}
else
{
//
// An err occurred, no results
//
ShowMessages("An error occurred, no results:");
ShowErrorMessage(PcidevinfoPacket.KernelStatus);
}
}
}