HyperDbg Debugger
Loading...
Searching...
No Matches
pcicam.cpp File Reference

!pcicam command More...

#include "pch.h"

Functions

VOID CommandPcicamHelp ()
 !pcicam command help
VOID CommandPcicam (vector< CommandToken > CommandTokens, string Command)
 !pcicam command handler

Variables

BOOLEAN g_IsKdModuleLoaded
 shows whether the kernel debugger (KD) module is loaded or not
BOOLEAN g_IsSerialConnectedToRemoteDebuggee
 Shows if the debugger was connected to remote debuggee over (A remote guest).

Detailed Description

!pcicam command

Author
Bj�rn Ruytenberg (bjorn.nosp@m.@bjo.nosp@m.rnweb.nosp@m..nl)
Version
0.13
Date
2024-12-17

Function Documentation

◆ CommandPcicam()

VOID CommandPcicam ( vector< CommandToken > CommandTokens,
string Command )

!pcicam command handler

Parameters
CommandTokens
Command
Returns
VOID
48{
49 BOOL Status;
50 ULONG ReturnedLength;
52 UINT32 TargetBus = 0;
53 UINT32 TargetDevice = 0;
54 UINT32 TargetFunction = 0;
55
56 const CHAR * PciHeaderTypes[] = {"Endpoint", "PCI-to-PCI Bridge", "PCI-to-CardBus Bridge"};
57
58 if (CommandTokens.size() < 4 || CommandTokens.size() > 5)
59 {
60 ShowMessages("Incorrect use of '%s'\n\n",
61 GetCaseSensitiveStringFromCommandToken(CommandTokens.at(0)).c_str());
63 return;
64 }
65
66 if (ConvertTokenToUInt32(CommandTokens.at(1), &TargetBus))
67 {
68 if (TargetBus > BUS_MAX_NUM)
69 {
70 ShowMessages("Invalid bus number '%s'\n\n",
71 GetCaseSensitiveStringFromCommandToken(CommandTokens.at(1)).c_str());
73 return;
74 }
75 PcidevinfoPacket.DeviceInfo.Bus = (UINT8)TargetBus;
76 }
77
78 if (ConvertTokenToUInt32(CommandTokens.at(2), &TargetDevice))
79 {
80 if (TargetDevice > DEVICE_MAX_NUM)
81 {
82 ShowMessages("Invalid device number '%s'\n\n",
83 GetCaseSensitiveStringFromCommandToken(CommandTokens.at(2)).c_str());
85 return;
86 }
87 PcidevinfoPacket.DeviceInfo.Device = (UINT8)TargetDevice;
88 }
89
90 if (ConvertTokenToUInt32(CommandTokens.at(3), &TargetFunction))
91 {
92 if (TargetFunction > FUNCTION_MAX_NUM)
93 {
94 ShowMessages("Invalid function number '%s'\n\n",
95 GetCaseSensitiveStringFromCommandToken(CommandTokens.at(3)).c_str());
97 return;
98 }
99 PcidevinfoPacket.DeviceInfo.Function = (UINT8)TargetFunction;
100 }
101
102 if (CommandTokens.size() == 5)
103 {
104 if (strncmp(GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)).c_str(), "x", 1) == 0)
105 {
106 PcidevinfoPacket.PrintRaw = TRUE;
107 }
108 else
109 {
110 ShowMessages("Invalid parameter '%s'\n\n",
111 GetCaseSensitiveStringFromCommandToken(CommandTokens.at(4)).c_str());
113 return;
114 }
115 }
116
117 //
118 // Send buffer
119 //
121 {
122 KdSendPcidevinfoPacketToDebuggee(&PcidevinfoPacket);
123 }
124 else
125 {
127
128 //
129 // Send IOCTL
130 //
131 Status = DeviceIoControl(
132 g_DeviceHandle, // Handle to device
133 IOCTL_PCIDEVINFO_ENUM, // IO Control Code (IOCTL)
134 &PcidevinfoPacket, // Input Buffer to driver.
136 &PcidevinfoPacket, // Output Buffer from driver.
138 // buffer in bytes.
139 &ReturnedLength, // Bytes placed in buffer.
140 NULL // synchronous call
141 );
142
143 if (!Status)
144 {
145 ShowMessages("ioctl failed with code 0x%x\n", GetLastError());
146 return;
147 }
148
149 if (PcidevinfoPacket.KernelStatus == DEBUGGER_OPERATION_WAS_SUCCESSFUL)
150 {
151 //
152 // For some reason, MSVC refuses to initialize these at top of case
153 //
154 const CHAR * PciHeaderTypeAsString[] = {"Endpoint", "PCI-to-PCI Bridge", "PCI-to-CardBus Bridge"};
155 const CHAR * PciMmioBarTypeAsString[] = {"32-bit Wide",
156 "Reserved",
157 "64-bit Wide",
158 "Reserved"};
159 UINT8 BarNumOffset = 0;
160
161 ShowMessages("PCI configuration space (CAM) for device %04x:%02x:%02x:%x\n",
162 0, // TODO: Add support for domains beyond 0000
163 PcidevinfoPacket.DeviceInfo.Bus,
164 PcidevinfoPacket.DeviceInfo.Device,
165 PcidevinfoPacket.DeviceInfo.Function);
166
167 if (!PcidevinfoPacket.PrintRaw)
168 {
169 Vendor * CurrentVendor = GetVendorById(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.VendorId);
170 CHAR * CurrentVendorName = (CHAR *)"N/A";
171 CHAR * CurrentDeviceName = (CHAR *)"N/A";
172
173 if (CurrentVendor != NULL)
174 {
175 CurrentVendorName = CurrentVendor->VendorName;
176 Device * CurrentDevice = GetDeviceFromVendor(CurrentVendor, PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.DeviceId);
177
178 if (CurrentDevice != NULL)
179 {
180 CurrentDeviceName = CurrentDevice->DeviceName;
181 }
182 }
183
184 ShowMessages("\nCommon Header:\nVID:DID: %04x:%04x\nVendor Name: %-17.*s\nDevice Name: %.*s\nCommand: %04x\n",
187 strnlen_s(CurrentVendorName, PCI_NAME_STR_LENGTH),
188 CurrentVendorName,
189 strnlen_s(CurrentDeviceName, PCI_NAME_STR_LENGTH),
190 CurrentDeviceName,
191 PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command);
192
193 if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0) // Only applicable to endpoints
194 {
195 ShowMessages(" Memory Space: %u\n I/O Space: %u\n",
196 (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1,
197 (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x1));
198 }
199
200 ShowMessages("Status: %04x\nRevision ID: %02x\nClass Code: %06x\nCacheLineSize: %02x\nPrimaryLatencyTimer: %02x\nHeaderType: %s (%02x)\n Multi-function Device: %s\nBist: %02x\n",
201 PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Status,
206 (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) < 2 ? PciHeaderTypeAsString[(PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x1)] : "Unknown",
208 (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x1) ? "True" : "False",
209 PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Bist);
210 FreeVendor(CurrentVendor);
212
213 ShowMessages("\nDevice Header:\n");
214
215 if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01) << 7 == 0) // Endpoint
216 {
217 for (UINT8 i = 0; i < 5; i++)
218 {
219 //
220 // Memory I/O
221 //
222 if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x1) == 0)
223 {
224 //
225 // 64-bit BAR
226 //
227 if (((PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1) == 2)
228 {
229 UINT64 BarMsb = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i + 1];
230 UINT64 BarLsb = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i];
231 UINT64 ActualBar = ((BarMsb & 0xFFFFFFFF) << 32) + (BarLsb & 0xFFFFFFF0);
232
233 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",
234 i - BarNumOffset,
235 ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1 == 0) || !PcidevinfoPacket.DeviceInfo.MmioBarInfo[i].IsEnabled ? "[disabled]" : "",
236 PciMmioBarTypeAsString[(PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1],
237 (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x6) >> 1,
238 BarMsb,
239 BarLsb,
240 ActualBar,
241 (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x8 >> 3) ? "True" : "False");
242
243 i++;
244 BarNumOffset++;
245 }
246 //
247 // 32-bit BAR
248 //
249 else
250 {
251 UINT32 ActualBar = (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFF0);
252
253 ShowMessages("BAR%u %s\n BAR Type: MMIO\n BAR: %08x\n BAR (actual): %08x\n Prefetchable: %s\n",
254 i - BarNumOffset,
255 ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x2) >> 1 == 0) || !PcidevinfoPacket.DeviceInfo.MmioBarInfo[i].IsEnabled ? "[disabled]" : "",
257 ActualBar,
258 (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x8 >> 3) ? "True" : "False");
259 }
260 }
261 //
262 // Port I/O
263 //
264 else
265 {
266 //
267 // 32-bit BAR is the only flavor we have here
268 //
269 UINT32 ActualBar32 = PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0xFFFFFFFC;
270
271 ShowMessages("BAR%u %s\n BAR Type: Port IO\n BAR: %08x\n BAR (actual): %08x\n Reserved: %u\n",
272 i - BarNumOffset,
273 ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.Command & 0x1) == 0) ? "[disabled]" : "",
275 ActualBar32,
276 (PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpaceEp.Bar[i] & 0x2) >> 1);
277 }
278 }
279
280 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",
292 }
293 else if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) == 1) // PCI-to-PCI Bridge
294 {
295 ShowMessages("BAR0: %08x\nBAR1: %08x\n", PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Bar[0], PcidevinfoPacket.DeviceInfo.ConfigSpace.DeviceHeader.ConfigSpacePtpBridge.Bar[1]);
296
297 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",
319 }
320 else if ((PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f) == 2) // PCI-to-CardBus Bridge
321 {
322 ShowMessages("Parsing header type %s (%02x) currently unsupported\n", PciHeaderTypeAsString[PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01], PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x01);
323 }
324 else
325 {
326 ShowMessages("\nDevice Header:\nUnknown header type %02x\n", (PcidevinfoPacket.DeviceInfo.ConfigSpace.CommonHeader.HeaderType & 0x3f));
327 }
328 }
329 else
330 {
331 UINT32 * cs = (UINT32 *)&PcidevinfoPacket.DeviceInfo.ConfigSpace; // Overflows into .ConfigSpaceAdditional - no padding due to pack(0)
332
333 ShowMessages(" 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
334
335 for (UINT16 i = 0; i < CAM_CONFIG_SPACE_LENGTH; i += 16)
336 {
337 ShowMessages("%02x: ", i);
338 for (UINT8 j = 0; j < 16; j++)
339 {
340 ShowMessages("%02x ", *(((BYTE *)cs) + j));
341 }
342
343 //
344 // Print ASCII representation
345 // Replace non-printable characters with "."
346 //
347 for (UINT8 j = 0; j < 16; j++)
348 {
349 CHAR c = (CHAR) * (cs + j);
350 if (c >= 32 && c <= 126)
351 {
352 ShowMessages("%c", c);
353 }
354 else
355 {
356 ShowMessages(".");
357 }
358 }
359 ShowMessages("\n");
360 cs += 4;
361 }
362 }
363 }
364 else
365 {
366 //
367 // An err occurred, no results
368 //
369 ShowMessages("An error occurred, no results:");
370
371 ShowErrorMessage(PcidevinfoPacket.KernelStatus);
372 }
373 }
374}
BOOLEAN g_IsSerialConnectedToRemoteDebuggee
Shows if the debugger was connected to remote debuggee over (A remote guest).
Definition globals.h:253
int BOOL
Definition BasicTypes.h:25
unsigned short UINT16
Definition BasicTypes.h:53
unsigned char BYTE
Definition BasicTypes.h:40
#define TRUE
Definition BasicTypes.h:114
unsigned char UINT8
Definition BasicTypes.h:52
unsigned int UINT32
Definition BasicTypes.h:54
char CHAR
Definition BasicTypes.h:33
unsigned long ULONG
Definition BasicTypes.h:31
#define DEBUGGER_OPERATION_WAS_SUCCESSFUL
General value to indicate that the operation or request was successful.
Definition ErrorCodes.h:23
#define IOCTL_PCIDEVINFO_ENUM
ioctl, to query for PCI endpoint info
Definition Ioctls.h:368
#define FUNCTION_MAX_NUM
Definition Pcie.h:41
#define DEVICE_MAX_NUM
Definition Pcie.h:40
#define BUS_MAX_NUM
Definition Pcie.h:39
#define CAM_CONFIG_SPACE_LENGTH
Definition Pcie.h:43
#define SIZEOF_DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET
check so the DEBUGGEE_PCITREE_REQUEST_RESPONSE_PACKET should be smaller than packet size
Definition RequestStructures.h:1663
struct _DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET DEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET
PCI device info Request-Response Packet, used by !pcicam and future PCI-related commands....
std::string GetCaseSensitiveStringFromCommandToken(CommandToken TargetToken)
Get case sensitive string from command token.
Definition common.cpp:467
BOOLEAN ConvertTokenToUInt32(CommandToken TargetToken, PUINT32 Result)
check and convert command token to a 32 bit unsigned integer
Definition common.cpp:546
BOOLEAN ShowErrorMessage(UINT32 Error)
shows the error message
Definition debugger.cpp:40
BOOLEAN KdSendPcidevinfoPacketToDebuggee(PDEBUGGEE_PCIDEVINFO_REQUEST_RESPONSE_PACKET PciepinfoPacket)
Request PCI device info (CAM). Current consumers include '!pcicam'.
Definition kd.cpp:3621
#define ASSERT_MESSAGE_KD_NOT_LOADED
Definition common.h:29
#define AssertShowMessageReturnStmt(expr1, expr2, message1, message2, rc)
Definition common.h:59
#define AssertReturn
Definition common.h:19
#define ASSERT_MESSAGE_DRIVER_NOT_LOADED
Definition common.h:27
HANDLE g_DeviceHandle
Holds the global handle of device which is used to send the request to the kernel by IOCTL,...
Definition globals.h:481
BOOLEAN g_IsKdModuleLoaded
shows whether the kernel debugger (KD) module is loaded or not
Definition globals.h:22
Device * GetDeviceFromVendor(Vendor *VendorToUse, UINT16 DeviceId)
Returns Device entry corresponding to DeviceId.
Definition pci-id.cpp:339
Vendor * GetVendorById(UINT16 VendorId)
Returns Vendor entry, including corresponding devices and subdevices.
Definition pci-id.cpp:305
VOID FreePciIdDatabase()
Frees PciIdDatabaseBuffer.
Definition pci-id.cpp:288
VOID FreeVendor(Vendor *VendorToFree)
Frees Vendor and all of its members.
Definition pci-id.cpp:260
#define PCI_NAME_STR_LENGTH
Definition pci-id.h:15
VOID CommandPcicamHelp()
!pcicam command help
Definition pcicam.cpp:26
PCI_DEV DeviceInfo
Definition RequestStructures.h:1674
UINT32 KernelStatus
Definition RequestStructures.h:1672
BOOL PrintRaw
Definition RequestStructures.h:1673
BOOL IsEnabled
Definition Pcie.h:147
UINT8 Device
Definition Pcie.h:169
UINT8 Bus
Definition Pcie.h:168
UINT8 Function
Definition Pcie.h:170
PCI_DEV_MMIOBAR_INFO MmioBarInfo[6]
Definition Pcie.h:173
PORTABLE_PCI_CONFIG_SPACE_HEADER ConfigSpace
Definition Pcie.h:171
UINT8 Bist
Definition Pcie.h:60
UINT8 ClassCode[3]
Definition Pcie.h:56
UINT8 RevisionId
Definition Pcie.h:55
UINT16 Command
Definition Pcie.h:53
UINT8 CacheLineSize
Definition Pcie.h:57
UINT16 VendorId
Definition Pcie.h:51
UINT16 DeviceId
Definition Pcie.h:52
UINT8 HeaderType
Definition Pcie.h:59
UINT16 Status
Definition Pcie.h:54
UINT8 PrimaryLatencyTimer
Definition Pcie.h:58
PORTABLE_PCI_COMMON_HEADER CommonHeader
Definition Pcie.h:158
PORTABLE_PCI_DEVICE_HEADER DeviceHeader
Definition Pcie.h:159
Definition pci-id.h:26
CHAR DeviceName[PCI_NAME_STR_LENGTH]
Definition pci-id.h:28
Definition pci-id.h:34
CHAR VendorName[PCI_NAME_STR_LENGTH]
Definition pci-id.h:36
struct _PORTABLE_PCI_DEVICE_HEADER::_PORTABLE_PCI_EP_HEADER ConfigSpaceEp
struct _PORTABLE_PCI_DEVICE_HEADER::_PORTABLE_PCI_BRIDGE_HEADER ConfigSpacePtpBridge

◆ CommandPcicamHelp()

VOID CommandPcicamHelp ( )

!pcicam command help

Returns
VOID
27{
28 ShowMessages("!pcicam : dumps the PCI configuration space (CAM) for a given device.\n\n");
29
30 ShowMessages("syntax : \t!pcicam [Bus (hex)] [Device (hex)] [Function (hex)]\n");
31 ShowMessages("syntax : \t!pcicam [Bus (hex)] [Device (hex)] [Function (hex)] [Dump (string)]\n");
32
33 ShowMessages("\n");
34 ShowMessages("\t\te.g : !pcicam 0 2 0\n");
35 ShowMessages("\t\te.g : !pcicam 3 0 0 x\n");
36}

Variable Documentation

◆ g_IsKdModuleLoaded

BOOLEAN g_IsKdModuleLoaded
extern

shows whether the kernel debugger (KD) module is loaded or not

◆ g_IsSerialConnectedToRemoteDebuggee

BOOLEAN g_IsSerialConnectedToRemoteDebuggee
extern

Shows if the debugger was connected to remote debuggee over (A remote guest).