@@ -29,6 +29,33 @@ typedef struct {
//UINT32 DataObjectDW[Length];
} PCI_DOE_DATA_OBJECT_HEADER;
+/* Extended Capabilities (PCI-X 2.0 and Express) */
+#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
+#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf)
+#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc)
+
+#define PCIE_EXT_CAP_OFFSET 0x100
+#define PCI_EXT_CAP_ID_DOE 0x2e /* Data Object Exchange */
+
+/* DOE Capabilities Register */
+#define PCIE_DOE_CAP 0x04
+#define PCIE_DOE_CAP_INTR_SUPP 0x00000001
+/* DOE Control Register */
+#define PCIE_DOE_CTRL 0x08
+#define PCIE_DOE_CTRL_ABORT 0x00000001
+#define PCIE_DOE_CTRL_INTR_EN 0x00000002
+#define PCIE_DOE_CTRL_GO 0x80000000
+/* DOE Status Register */
+#define PCIE_DOE_STATUS 0x0c
+#define PCIE_DOE_STATUS_BUSY 0x00000001
+#define PCIE_DOE_STATUS_INTR 0x00000002
+#define PCIE_DOE_STATUS_ERR 0x00000004
+#define PCIE_DOE_STATUS_DO_RDY 0x80000000
+/* DOE Write Data Mailbox Register */
+#define PCIE_DOE_WR_DATA_MBOX 0x10
+/* DOE Read Data Mailbox Register */
+#define PCIE_DOE_RD_DATA_MBOX 0x14
+
#define PCI_DOE_VENDOR_ID_PCISIG 0x0001
#define PCI_DOE_DATA_OBJECT_TYPE_DOE_DISCOVERY 0x00
@@ -32,6 +32,11 @@ UINT32 mExeSession = (0 |
EXE_SESSION_MEAS |
0);
+extern struct pcie_dev dev;
+extern char filename[41];
+struct pcie_dev dev = {0};
+char filename[41];
+
VOID
PrintUsage (
IN CHAR8* Name
@@ -364,6 +369,64 @@ Done:
return Ret;
}
+/* Ref: pciutils/lib/filter.c */
+/* Slot filter syntax: [[[domain]:][bus]:][slot][.[func]] */
+static char *pci_filter_parse_slot(struct pcie_dev *f, char *str)
+{
+ char *colon = strrchr(str, ':');
+ char *dot = strchr((colon ? colon + 1 : str), '.');
+ char *mid = str;
+ char *e, *bus, *colon2;
+
+ if (colon) {
+ *colon++ = 0;
+ mid = colon;
+ colon2 = strchr(str, ':');
+
+ if (colon2) {
+ *colon2++ = 0;
+ bus = colon2;
+ if (str[0] && strcmp(str, "*")) {
+ long int x = strtol(str, &e, 16);
+ if ((e && *e) || (x < 0 || x > 0x7fffffff)) {
+ return "Invalid domain number";
+ }
+ f->domain = x;
+ }
+ } else
+ bus = str;
+
+ if (bus[0] && strcmp(bus, "*")) {
+ long int x = strtol(bus, &e, 16);
+ if ((e && *e) || (x < 0 || x > 0xff)) {
+ return "Invalid bus number";
+ }
+ f->bus = x;
+ }
+ }
+
+ if (dot) {
+ *dot++ = 0;
+ }
+
+ if (mid[0] && strcmp(mid, "*")) {
+ long int x = strtol(mid, &e, 16);
+ if ((e && *e) || (x < 0 || x > 0x1f)) {
+ return "Invalid slot number";
+ }
+ f->slot = x;
+ }
+
+ if (dot && dot[0] && strcmp(dot, "*")) {
+ long int x = strtol(dot, &e, 16);
+ if ((e && *e) || (x < 0 || x > 7)) {
+ return "Invalid function number";
+ }
+ f->func = x;
+ }
+ return NULL;
+}
+
void
ProcessArgs (
char *ProgramName,
@@ -373,6 +436,7 @@ ProcessArgs (
{
UINT32 Data32;
CHAR8 *PcapFileName;
+ char *err;
PcapFileName = NULL;
@@ -854,6 +918,27 @@ ProcessArgs (
}
}
+ if (strcmp (argv[0], "-s") == 0) {
+ if (argc >= 2) {
+ err = pci_filter_parse_slot(&dev, argv[1]);
+ if (err) {
+ printf("%s\n", err);
+ PrintUsage (ProgramName);
+ exit (0);
+ }
+ sprintf(filename, "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/config",
+ dev.domain, dev.bus, dev.slot, dev.func);
+
+ argc -= 2;
+ argv += 2;
+ continue;
+ } else {
+ printf ("invalid -s\n");
+ PrintUsage (ProgramName);
+ exit (0);
+ }
+ }
+
printf ("invalid %s\n", argv[0]);
PrintUsage (ProgramName);
exit (0);
@@ -156,4 +156,11 @@ ProcessArgs (
char *argv[ ]
);
+struct pcie_dev {
+ int pdev;
+ int domain;
+ int bus;
+ int slot;
+ int func;
+};
#endif
@@ -11,6 +11,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
VOID *mSpdmContext;
SOCKET mSocket;
+extern struct pcie_dev dev;
BOOLEAN
CommunicatePlatformData (
@@ -53,6 +54,30 @@ CommunicatePlatformData (
RETURN_STATUS
EFIAPI
+AvyPCIConfigWriteDW (
+ IN UINT64 Address,
+ IN OUT UINT32 Data
+ )
+{
+ pwrite(dev.pdev, &Data, sizeof(uint32_t), Address);
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
+AvyPCIConfigReadDW (
+ IN UINT64 Address,
+ IN OUT UINT32 *Data
+ )
+{
+ pread(dev.pdev, Data, sizeof(uint32_t), Address);
+
+ return RETURN_SUCCESS;
+}
+
+RETURN_STATUS
+EFIAPI
SpdmDeviceSendMessage (
IN VOID *SpdmContext,
IN UINTN RequestSize,
@@ -60,19 +85,30 @@ SpdmDeviceSendMessage (
IN UINT64 Timeout
)
{
+ RETURN_STATUS PCIResult;
BOOLEAN Result;
+ INT32 Index;
+ UINT32 DoeStatus = 0;
- Result = SendPlatformData (mSocket, SOCKET_SPDM_COMMAND_NORMAL, Request, (UINT32)RequestSize);
- if (!Result) {
- printf ("SendPlatformData Error - %x\n",
-#ifdef _MSC_VER
- WSAGetLastError()
-#else
- errno
-#endif
- );
- return RETURN_DEVICE_ERROR;
+ while (DoeStatus & PCIE_DOE_STATUS_BUSY) {
+ Result = AvyPCIConfigReadDW(mDOEBaseAddress + PCIE_DOE_STATUS, &DoeStatus);
+ if (Result) {
+ return Result;
+ }
+ }
+
+ for (Index = 0; Index < (INT32)(RequestSize / 4) ; Index++) {
+ PCIResult = AvyPCIConfigWriteDW (mDOEBaseAddress + PCIE_DOE_WR_DATA_MBOX, ((UINT32 *)Request)[Index]);
+ if (PCIResult) {
+ return PCIResult;
}
+ }
+
+ PCIResult = AvyPCIConfigWriteDW (mDOEBaseAddress + PCIE_DOE_CTRL, PCIE_DOE_CTRL_GO);
+ if (PCIResult) {
+ return PCIResult;
+ }
+
return RETURN_SUCCESS;
}
@@ -85,20 +121,40 @@ SpdmDeviceReceiveMessage (
IN UINT64 Timeout
)
{
- BOOLEAN Result;
- UINT32 Command;
+ RETURN_STATUS Result;
+ UINT32 RecieveBuffer[MAX_SPDM_MESSAGE_BUFFER_SIZE];
+ UINT32 RecieveBufferCount = 0, DoeStatus = 0;
- Result = ReceivePlatformData (mSocket, &Command, Response, ResponseSize);
- if (!Result) {
- printf ("ReceivePlatformData Error - %x\n",
-#ifdef _MSC_VER
- WSAGetLastError()
-#else
- errno
-#endif
- );
- return RETURN_DEVICE_ERROR;
+ while ((!(DoeStatus & PCIE_DOE_STATUS_DO_RDY)) || (DoeStatus & PCIE_DOE_STATUS_BUSY)) {
+ Result = AvyPCIConfigReadDW(mDOEBaseAddress + PCIE_DOE_STATUS, &DoeStatus);
+ if (Result) {
+ return Result;
}
+ }
+
+ while (DoeStatus & PCIE_DOE_STATUS_DO_RDY) {
+ Result = AvyPCIConfigReadDW (mDOEBaseAddress + PCIE_DOE_RD_DATA_MBOX, RecieveBuffer + RecieveBufferCount);
+ if (Result) {
+ return Result;
+ }
+ RecieveBufferCount++;
+
+ Result = AvyPCIConfigWriteDW (mDOEBaseAddress + PCIE_DOE_RD_DATA_MBOX, 0x1);
+ if (Result) {
+ return Result;
+ }
+
+ Result = AvyPCIConfigReadDW (mDOEBaseAddress + PCIE_DOE_STATUS, &DoeStatus);
+ if (Result) {
+ return Result;
+ }
+ }
+ *ResponseSize = RecieveBufferCount * 4;
+ CopyMem (Response, RecieveBuffer, *ResponseSize);
+
+ DumpData ((UINT8 *)Response, *ResponseSize);
+ printf ("\n");
+
return RETURN_SUCCESS;
}
@@ -22,6 +22,10 @@ extern SOCKET mSocket;
extern VOID *mSpdmContext;
+extern struct pcie_dev dev;
+UINT32 mDOEBaseAddress = 0;
+extern char filename[41];
+
VOID *
SpdmClientInit (
VOID
@@ -53,6 +57,31 @@ DoSessionViaSpdm (
IN BOOLEAN UsePsk
);
+RETURN_STATUS
+EFIAPI
+AvyPCIConfigReadDW (
+ IN UINT64 Address,
+ IN OUT UINT32 *Data
+ );
+
+RETURN_STATUS
+EFIAPI
+SpdmDeviceSendMessage (
+ IN VOID *SpdmContext,
+ IN UINTN RequestSize,
+ IN VOID *Request,
+ IN UINT64 Timeout
+ );
+
+RETURN_STATUS
+EFIAPI
+SpdmDeviceReceiveMessage (
+ IN VOID *SpdmContext,
+ IN OUT UINTN *ResponseSize,
+ IN OUT VOID *Response,
+ IN UINT64 Timeout
+ );
+
BOOLEAN
InitClient (
OUT SOCKET *Socket,
@@ -116,12 +145,18 @@ PlatformClientRoutine (
IN UINT16 PortNumber
)
{
+#if 0
SOCKET PlatformSocket;
BOOLEAN Result;
UINT32 Response;
+#endif
UINTN ResponseSize;
+ INT32 Result;
RETURN_STATUS Status;
+ UINT32 CapabilityOffset = 0, PCIRegister;
+ BOOLEAN ProtocolFound = FALSE;
+#if 0
#ifdef _MSC_VER
WSADATA Ws;
if (WSAStartup(MAKEWORD(2,2), &Ws) != 0) {
@@ -176,6 +211,49 @@ PlatformClientRoutine (
mDoeRequest.DoeDiscoveryRequest.Index = DoeResponse.DoeDiscoveryResponse.NextIndex;
} while (DoeResponse.DoeDiscoveryResponse.NextIndex != 0);
}
+#endif
+ if (mUseTransportLayer == SOCKET_TRANSPORT_TYPE_PCI_DOE) {
+ DOE_DISCOVERY_RESPONSE_MINE DoeResponse;
+
+ for (CapabilityOffset = PCIE_EXT_CAP_OFFSET; CapabilityOffset;
+ CapabilityOffset = PCI_EXT_CAP_NEXT(PCIRegister)) {
+ Result = AvyPCIConfigReadDW (CapabilityOffset, &PCIRegister);
+ if (Result) {
+ printf ("Config Read error\n");
+ goto Done;
+ }
+
+ if (PCI_EXT_CAP_ID(PCIRegister) == PCI_EXT_CAP_ID_DOE) {
+ mDOEBaseAddress = CapabilityOffset;
+
+ // DOE Discovery
+ do {
+ SpdmDeviceSendMessage (NULL, sizeof(mDoeRequest), &mDoeRequest, 0);
+ SpdmDeviceReceiveMessage (NULL, &ResponseSize, &DoeResponse, 0);
+
+ if (DoeResponse.DoeHeader.VendorId == PCI_DOE_VENDOR_ID_PCISIG &&
+ DoeResponse.DoeDiscoveryResponse.DataObjectType == PCI_DOE_DATA_OBJECT_TYPE_SPDM) {
+ ProtocolFound = TRUE;
+ break;
+ }
+
+ mDoeRequest.DoeDiscoveryRequest.Index = DoeResponse.DoeDiscoveryResponse.NextIndex;
+ } while (DoeResponse.DoeDiscoveryResponse.NextIndex != 0);
+
+ if (ProtocolFound) {
+ break;
+ }
+ }
+ }
+
+ if (!mDOEBaseAddress) {
+ printf ("DOE Capability not found\n");
+ goto Done;
+ } else if (!ProtocolFound) {
+ printf ("SPDM protocol not found\n");
+ goto Done;
+ }
+ }
mSpdmContext = SpdmClientInit ();
if (mSpdmContext == NULL) {
@@ -217,24 +295,26 @@ PlatformClientRoutine (
}
// Do test - end
+ printf ("\033[1mTest End\033[m\n");
+ return TRUE;
Done:
- ResponseSize = 0;
- Result = CommunicatePlatformData (
- PlatformSocket,
- SOCKET_SPDM_COMMAND_SHUTDOWN - mExeMode,
- NULL,
- 0,
- &Response,
- &ResponseSize,
- NULL
- );
+ //ResponseSize = 0;
+ //Result = CommunicatePlatformData (
+ // PlatformSocket,
+ // SOCKET_SPDM_COMMAND_SHUTDOWN - mExeMode,
+ // NULL,
+ // 0,
+ // &Response,
+ // &ResponseSize,
+ // NULL
+ // );
if (mSpdmContext != NULL) {
free (mSpdmContext);
}
- closesocket (PlatformSocket);
+ //closesocket (PlatformSocket);
#ifdef _MSC_VER
WSACleanup();
@@ -253,9 +333,16 @@ int main (
ProcessArgs ("SpdmRequesterEmu", argc, argv);
+ dev.pdev = open(filename, O_RDWR);
+ if (dev.pdev < 0) {
+ printf("Fail to open %s\n", filename);
+ return -1;
+ }
+
PlatformClientRoutine (DEFAULT_SPDM_PLATFORM_PORT);
printf ("Client stopped\n");
ClosePcapPacketFile ();
+ close(dev.pdev);
return 0;
}
@@ -20,4 +20,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "stdio.h"
#include "SpdmEmu.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+extern UINT32 mDOEBaseAddress;
#endif