diff mbox series

[v1,openspdm,on,QEMU,CXL/PCIe,Device,2/2] requester: Modified for QEMU emulation

Message ID 1624665672-4964-1-git-send-email-cbrowy@avery-design.com (mailing list archive)
State New, archived
Headers show
Series Testing PCIe DOE in QEMU CXL/PCIe Device using openspdm | expand

Commit Message

Chris Browy June 26, 2021, 12:01 a.m. UTC
From: hchkuo <hchkuo@avery-design.com.tw>

The requester should be used as a PCIe app to access the SPDM object in
the PCEe device.

Signed-off-by: Chris Browy <cbrowy@avery-design.com>
---
 Include/IndustryStandard/PciDoeBinding.h    |  27 +++++++
 SpdmEmu/SpdmEmuCommon/SpdmEmu.c             |  85 ++++++++++++++++++++++
 SpdmEmu/SpdmEmuCommon/SpdmEmu.h             |   7 ++
 SpdmEmu/SpdmRequesterEmu/SpdmRequester.c    | 100 +++++++++++++++++++------
 SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.c | 109 +++++++++++++++++++++++++---
 SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.h |   5 ++
 6 files changed, 300 insertions(+), 33 deletions(-)
diff mbox series

Patch

diff --git a/Include/IndustryStandard/PciDoeBinding.h b/Include/IndustryStandard/PciDoeBinding.h
index c7cd7d3..6d199f7 100644
--- a/Include/IndustryStandard/PciDoeBinding.h
+++ b/Include/IndustryStandard/PciDoeBinding.h
@@ -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
diff --git a/SpdmEmu/SpdmEmuCommon/SpdmEmu.c b/SpdmEmu/SpdmEmuCommon/SpdmEmu.c
index b9a4311..768a8b0 100644
--- a/SpdmEmu/SpdmEmuCommon/SpdmEmu.c
+++ b/SpdmEmu/SpdmEmuCommon/SpdmEmu.c
@@ -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);
diff --git a/SpdmEmu/SpdmEmuCommon/SpdmEmu.h b/SpdmEmu/SpdmEmuCommon/SpdmEmu.h
index 640cf00..5335fc9 100644
--- a/SpdmEmu/SpdmEmuCommon/SpdmEmu.h
+++ b/SpdmEmu/SpdmEmuCommon/SpdmEmu.h
@@ -156,4 +156,11 @@  ProcessArgs (
   char  *argv[ ]
   );
 
+struct pcie_dev {
+    int pdev;
+    int domain;
+    int bus;
+    int slot;
+    int func;
+};
 #endif
diff --git a/SpdmEmu/SpdmRequesterEmu/SpdmRequester.c b/SpdmEmu/SpdmRequesterEmu/SpdmRequester.c
index 7635e7e..cfa1723 100644
--- a/SpdmEmu/SpdmRequesterEmu/SpdmRequester.c
+++ b/SpdmEmu/SpdmRequesterEmu/SpdmRequester.c
@@ -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;
 }
 
diff --git a/SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.c b/SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.c
index 61d38d8..64b7381 100644
--- a/SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.c
+++ b/SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.c
@@ -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;
 }
diff --git a/SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.h b/SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.h
index 5671536..c1d03ef 100644
--- a/SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.h
+++ b/SpdmEmu/SpdmRequesterEmu/SpdmRequesterEmu.h
@@ -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