Add PCI configuration space dump with PCI command
"MM" SBL Shell command can be used to dump PCI configuration space registers. On the other side, "PCI" command can be used to list all PCI devices. This patch enhanced "PCI" command to support PCI configuration space dump by redirecting it to "MM" command internally. Signed-off-by: Maurice Ma <maurice.ma@intel.com>
This commit is contained in:
parent
63ba5a4912
commit
9117f44534
|
@ -11,6 +11,24 @@
|
|||
#include <Library/PciExpressLib.h>
|
||||
#include "CmdPciUtil.h"
|
||||
|
||||
/**
|
||||
Read memory address given from mm command.
|
||||
|
||||
@param[in] Addr Starting address to read from
|
||||
@param[in] Width Width of the value to read
|
||||
@param[in] Count Number of times past the start to read
|
||||
@param[in] IsIoAddr If the address given is an IO address
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
MmRead (
|
||||
IN UINTN Addr,
|
||||
IN UINTN Width,
|
||||
IN UINT32 Count,
|
||||
IN BOOLEAN IsIoAddr
|
||||
);
|
||||
|
||||
/**
|
||||
Display PCI devices.
|
||||
|
||||
|
@ -60,59 +78,91 @@ ShellCommandPciFunc (
|
|||
PCI_CLASS_STRINGS ClassStrings;
|
||||
UINT32 ClassCode;
|
||||
BOOLEAN Verbose;
|
||||
UINT8 Value;
|
||||
UINT32 PciAddr;
|
||||
UINT32 Count;
|
||||
UINTN Addr;
|
||||
|
||||
Verbose = FALSE;
|
||||
|
||||
// Check flags
|
||||
for (Index = 0; Index < Argc; Index++) {
|
||||
Count = 0;
|
||||
PciAddr = 0;
|
||||
for (Index = 1; Index < Argc; Index++) {
|
||||
if (StrCmp (Argv[Index], L"-h") == 0) {
|
||||
goto usage;
|
||||
}
|
||||
if (StrCmp (Argv[Index], L"-v") == 0) {
|
||||
Verbose = TRUE;
|
||||
} else {
|
||||
Value = (UINT8)StrHexToUintn (Argv[Index]);
|
||||
switch (Count) {
|
||||
case 1:
|
||||
Value &= 0x1F;
|
||||
break;
|
||||
case 2:
|
||||
Value &= 0x07;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
PciAddr = (PciAddr << 8) | Value;
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Scan PCI config space and report present BDFs
|
||||
for (Bus = 0; Bus <= PCI_MAX_BUS; Bus++) {
|
||||
for (Dev = 0; Dev <= PCI_MAX_DEVICE; Dev++) {
|
||||
for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
|
||||
// Calculate MMIO address of PCI device configuration space
|
||||
PciDev = (volatile VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress)
|
||||
+ PCI_EXPRESS_LIB_ADDRESS (Bus, Dev, Func, 0));
|
||||
if ((Count != 0) && (Count != 3)) {
|
||||
goto usage;
|
||||
}
|
||||
|
||||
// Check Vendor ID to see if this device is present
|
||||
if (PciDev->VendorId == 0xffff) {
|
||||
if (Func == 0) {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (Count == 3) {
|
||||
// Redirect to MM to dump PCI configuration
|
||||
PciAddr = PciAddr << 8;
|
||||
Addr = (UINTN) (PcdGet64 (PcdPciExpressBaseAddress) +
|
||||
PCI_EXPRESS_LIB_ADDRESS ((PciAddr >> 24) & 0xFF, (PciAddr >> 16) & 0xFF, (PciAddr >> 8) & 0xFF, PciAddr & 0xFF));
|
||||
MmRead (Addr, 4, 64, FALSE);
|
||||
} else {
|
||||
// Scan PCI config space and report present BDFs
|
||||
for (Bus = 0; Bus <= PCI_MAX_BUS; Bus++) {
|
||||
for (Dev = 0; Dev <= PCI_MAX_DEVICE; Dev++) {
|
||||
for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
|
||||
// Calculate MMIO address of PCI device configuration space
|
||||
PciDev = (volatile VOID *) (UINTN) (PcdGet64 (PcdPciExpressBaseAddress)
|
||||
+ PCI_EXPRESS_LIB_ADDRESS (Bus, Dev, Func, 0));
|
||||
|
||||
// Get string descriptions of the class/subclass/interface
|
||||
ClassCode = ( (PciDev->ClassCode[2] << 16 )
|
||||
| (PciDev->ClassCode[1] << 8 )
|
||||
| (PciDev->ClassCode[0])
|
||||
);
|
||||
PciGetClassStrings (ClassCode, &ClassStrings);
|
||||
|
||||
// Report bus/device/function
|
||||
ShellPrint (L"%02x:%02x.%x %04x:%04x %s\n", Bus, Dev, Func,
|
||||
PciDev->VendorId,
|
||||
PciDev->DeviceId,
|
||||
ClassStrings.BaseClass);
|
||||
|
||||
// Report extra device information if the verbose flag was given
|
||||
if (Verbose) {
|
||||
ShellPrint (L"Config Space Address: %p\n", PciDev);
|
||||
if (StrLen (ClassStrings.SubClass)) {
|
||||
ShellPrint (L"SubClass: %s", ClassStrings.SubClass);
|
||||
if (StrLen (ClassStrings.PIFClass)) {
|
||||
ShellPrint (L" (%s)", ClassStrings.PIFClass);
|
||||
// Check Vendor ID to see if this device is present
|
||||
if (PciDev->VendorId == 0xffff) {
|
||||
if (Func == 0) {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ShellPrint (L"\n\n");
|
||||
|
||||
// Get string descriptions of the class/subclass/interface
|
||||
ClassCode = ( (PciDev->ClassCode[2] << 16 )
|
||||
| (PciDev->ClassCode[1] << 8 )
|
||||
| (PciDev->ClassCode[0])
|
||||
);
|
||||
PciGetClassStrings (ClassCode, &ClassStrings);
|
||||
|
||||
// Report bus/device/function
|
||||
ShellPrint (L"%02x:%02x.%x %04x:%04x %s\n", Bus, Dev, Func,
|
||||
PciDev->VendorId,
|
||||
PciDev->DeviceId,
|
||||
ClassStrings.BaseClass);
|
||||
|
||||
// Report extra device information if the verbose flag was given
|
||||
if (Verbose) {
|
||||
ShellPrint (L"Config Space Address: %p\n", PciDev);
|
||||
if (StrLen (ClassStrings.SubClass)) {
|
||||
ShellPrint (L"SubClass: %s", ClassStrings.SubClass);
|
||||
if (StrLen (ClassStrings.PIFClass)) {
|
||||
ShellPrint (L" (%s)", ClassStrings.PIFClass);
|
||||
}
|
||||
}
|
||||
ShellPrint (L"\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +171,7 @@ ShellCommandPciFunc (
|
|||
return EFI_SUCCESS;
|
||||
|
||||
usage:
|
||||
ShellPrint (L"Usage: %s [-v]\n", Argv[0]);
|
||||
ShellPrint (L"Usage: %s [bus dev func] [-v]\n", Argv[0]);
|
||||
ShellPrint (L"\n"
|
||||
L"Flags:\n"
|
||||
L" -v Verbose\n");
|
||||
|
|
Loading…
Reference in New Issue