]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
SecurityPkg/OpalPassword: Remove HW init codes and consume SSC PPI
[mirror_edk2.git] / SecurityPkg / Tcg / Opal / OpalPassword / OpalPasswordPei.c
index edb47ca8bc797f05ff0b6b46e07a5f0839807462..934c65bcee83703135a02d1cf7f8a1f6c44ee2f6 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Opal Password PEI driver which is used to unlock Opal Password for S3.\r
 \r
-Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -14,250 +14,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "OpalPasswordPei.h"\r
 \r
-EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;\r
-EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;\r
+EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;\r
 \r
-#define OPAL_PCIE_ROOTPORT_SAVESIZE               (0x40)\r
-#define STORE_INVALID_ROOTPORT_INDEX              ((UINT8) -1)\r
-\r
-/**\r
-  Get IOMMU PPI.\r
-\r
-  @return Pointer to IOMMU PPI.\r
-\r
-**/\r
-EDKII_IOMMU_PPI *\r
-GetIoMmu (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  EDKII_IOMMU_PPI           *IoMmu;\r
-\r
-  IoMmu = NULL;\r
-  Status = PeiServicesLocatePpi (\r
-             &gEdkiiIoMmuPpiGuid,\r
-             0,\r
-             NULL,\r
-             (VOID **) &IoMmu\r
-             );\r
-  if (!EFI_ERROR (Status) && (IoMmu != NULL)) {\r
-    return IoMmu;\r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
-  OperationBusMasterCommonBuffer64 mapping.\r
-\r
-  @param Pages                  The number of pages to allocate.\r
-  @param HostAddress            A pointer to store the base system memory address of the\r
-                                allocated range.\r
-  @param DeviceAddress          The resulting map address for the bus master PCI controller to use to\r
-                                access the hosts HostAddress.\r
-  @param Mapping                A resulting value to pass to Unmap().\r
-\r
-  @retval EFI_SUCCESS           The requested memory pages were allocated.\r
-  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are\r
-                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
-  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
-  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.\r
-\r
-**/\r
-EFI_STATUS\r
-IoMmuAllocateBuffer (\r
-  IN UINTN                  Pages,\r
-  OUT VOID                  **HostAddress,\r
-  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,\r
-  OUT VOID                  **Mapping\r
-  )\r
-{\r
-  EFI_STATUS            Status;\r
-  UINTN                 NumberOfBytes;\r
-  EFI_PHYSICAL_ADDRESS  HostPhyAddress;\r
-  EDKII_IOMMU_PPI       *IoMmu;\r
-\r
-  *HostAddress = NULL;\r
-  *DeviceAddress = 0;\r
-  *Mapping = NULL;\r
-\r
-  IoMmu = GetIoMmu ();\r
-\r
-  if (IoMmu != NULL) {\r
-    Status = IoMmu->AllocateBuffer (\r
-                      IoMmu,\r
-                      EfiBootServicesData,\r
-                      Pages,\r
-                      HostAddress,\r
-                      0\r
-                      );\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    NumberOfBytes = EFI_PAGES_TO_SIZE (Pages);\r
-    Status = IoMmu->Map (\r
-                      IoMmu,\r
-                      EdkiiIoMmuOperationBusMasterCommonBuffer,\r
-                      *HostAddress,\r
-                      &NumberOfBytes,\r
-                      DeviceAddress,\r
-                      Mapping\r
-                      );\r
-    if (EFI_ERROR (Status)) {\r
-      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);\r
-      *HostAddress = NULL;\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-    Status = IoMmu->SetAttribute (\r
-                      IoMmu,\r
-                      *Mapping,\r
-                      EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE\r
-                      );\r
-    if (EFI_ERROR (Status)) {\r
-      IoMmu->Unmap (IoMmu, *Mapping);\r
-      IoMmu->FreeBuffer (IoMmu, Pages, *HostAddress);\r
-      *Mapping = NULL;\r
-      *HostAddress = NULL;\r
-      return Status;\r
-    }\r
-  } else {\r
-    Status = PeiServicesAllocatePages (\r
-               EfiBootServicesData,\r
-               Pages,\r
-               &HostPhyAddress\r
-               );\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-    *HostAddress = (VOID *) (UINTN) HostPhyAddress;\r
-    *DeviceAddress = HostPhyAddress;\r
-    *Mapping = NULL;\r
-  }\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Frees memory that was allocated with AllocateBuffer().\r
-\r
-  @param Pages              The number of pages to free.\r
-  @param HostAddress        The base system memory address of the allocated range.\r
-  @param Mapping            The mapping value returned from Map().\r
-\r
-**/\r
-VOID\r
-IoMmuFreeBuffer (\r
-  IN UINTN                  Pages,\r
-  IN VOID                   *HostAddress,\r
-  IN VOID                   *Mapping\r
-  )\r
-{\r
-  EDKII_IOMMU_PPI       *IoMmu;\r
-\r
-  IoMmu = GetIoMmu ();\r
-\r
-  if (IoMmu != NULL) {\r
-    IoMmu->SetAttribute (IoMmu, Mapping, 0);\r
-    IoMmu->Unmap (IoMmu, Mapping);\r
-    IoMmu->FreeBuffer (IoMmu, Pages, HostAddress);\r
-  } else {\r
-    PeiServicesFreePages (\r
-      (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress,\r
-      Pages\r
-      );\r
-  }\r
-}\r
-\r
-/**\r
-  Provide IO action support.\r
-\r
-  @param[in]     PeiDev             The opal device need to perform trusted IO.\r
-  @param[in]     IoType             OPAL_IO_TYPE indicating whether to perform a Trusted Send or Trusted Receive.\r
-  @param[in]     SecurityProtocol   Security Protocol\r
-  @param[in]     SpSpecific         Security Protocol Specific\r
-  @param[in]     TransferLength     Transfer Length of Buffer (in bytes) - always a multiple of 512\r
-  @param[in]     Buffer             Address of Data to transfer\r
-\r
-  @retval        EFI_SUCCESS        Perform the IO action success.\r
-  @retval        Others             Perform the IO action failed.\r
-\r
-**/\r
-EFI_STATUS\r
-PerformTrustedIo (\r
-  OPAL_PEI_DEVICE  *PeiDev,\r
-  OPAL_IO_TYPE     IoType,\r
-  UINT8            SecurityProtocol,\r
-  UINT16           SpSpecific,\r
-  UINTN            TransferLength,\r
-  VOID             *Buffer\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  UINTN                         BufferSizeBlocks;\r
-  EFI_ATA_COMMAND_BLOCK         AtaCommandBlock;\r
-  OPAL_DEVICE_ATA               *DevInfoAta;\r
-  AHCI_CONTEXT                  *AhciContext;\r
-  NVME_CONTEXT                  *NvmeContext;\r
-\r
-  Status = EFI_DEVICE_ERROR;\r
-  if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_ATA) {\r
-    DevInfoAta = (OPAL_DEVICE_ATA *) PeiDev->Device;\r
-    AhciContext = (AHCI_CONTEXT *) PeiDev->Context;\r
-\r
-    BufferSizeBlocks = TransferLength / 512;\r
-\r
-    ZeroMem( &AtaCommandBlock, sizeof( EFI_ATA_COMMAND_BLOCK ) );\r
-    AtaCommandBlock.AtaCommand = ( IoType == OpalSend ) ? ATA_COMMAND_TRUSTED_SEND : ATA_COMMAND_TRUSTED_RECEIVE;\r
-    AtaCommandBlock.AtaSectorCount = ( UINT8 )BufferSizeBlocks;\r
-    AtaCommandBlock.AtaSectorNumber = ( UINT8 )( BufferSizeBlocks >> 8 );\r
-    AtaCommandBlock.AtaFeatures = SecurityProtocol;\r
-    AtaCommandBlock.AtaCylinderLow = ( UINT8 )( SpSpecific >> 8 );\r
-    AtaCommandBlock.AtaCylinderHigh = ( UINT8 )( SpSpecific );\r
-    AtaCommandBlock.AtaDeviceHead = ATA_DEVICE_LBA;\r
-\r
-\r
-    ZeroMem( AhciContext->Buffer, HDD_PAYLOAD );\r
-    ASSERT( TransferLength <= HDD_PAYLOAD );\r
-\r
-    if (IoType == OpalSend) {\r
-      CopyMem( AhciContext->Buffer, Buffer, TransferLength );\r
-    }\r
-\r
-    Status = AhciPioTransfer(\r
-                AhciContext,\r
-                (UINT8) DevInfoAta->Port,\r
-                (UINT8) DevInfoAta->PortMultiplierPort,\r
-                NULL,\r
-                0,\r
-                ( IoType == OpalSend ) ? FALSE : TRUE,   // i/o direction\r
-                &AtaCommandBlock,\r
-                NULL,\r
-                AhciContext->Buffer,\r
-                (UINT32)TransferLength,\r
-                ATA_TIMEOUT\r
-                );\r
-\r
-    if (IoType == OpalRecv) {\r
-      CopyMem( Buffer, AhciContext->Buffer, TransferLength );\r
-    }\r
-  } else if (PeiDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
-    NvmeContext = (NVME_CONTEXT *) PeiDev->Context;\r
-    Status = NvmeSecuritySendReceive (\r
-                NvmeContext,\r
-                IoType == OpalSend,\r
-                SecurityProtocol,\r
-                SwapBytes16(SpSpecific),\r
-                TransferLength,\r
-                Buffer\r
-              );\r
-  } else {\r
-    DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n", PeiDev->DeviceType));\r
-  }\r
-\r
-  return Status;\r
-}\r
 \r
 /**\r
   Send a security protocol command to a device that receives data and/or the result\r
@@ -351,14 +109,16 @@ SecurityReceiveData (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  return PerformTrustedIo (\r
-                        PeiDev,\r
-                        OpalRecv,\r
-                        SecurityProtocolId,\r
-                        SecurityProtocolSpecificData,\r
-                        PayloadBufferSize,\r
-                        PayloadBuffer\r
-                        );\r
+  return PeiDev->SscPpi->ReceiveData (\r
+                           PeiDev->SscPpi,\r
+                           PeiDev->DeviceIndex,\r
+                           SSC_PPI_GENERIC_TIMEOUT,\r
+                           SecurityProtocolId,\r
+                           SecurityProtocolSpecificData,\r
+                           PayloadBufferSize,\r
+                           PayloadBuffer,\r
+                           PayloadTransferSize\r
+                           );\r
 }\r
 \r
 /**\r
@@ -441,111 +201,15 @@ SecuritySendData (
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  return PerformTrustedIo (\r
-                          PeiDev,\r
-                          OpalSend,\r
-                          SecurityProtocolId,\r
-                          SecurityProtocolSpecificData,\r
-                          PayloadBufferSize,\r
-                          PayloadBuffer\r
-                          );\r
-\r
-}\r
-\r
-/**\r
-  Save/Restore RootPort configuration space.\r
-\r
-  @param[in]     DevInfoNvme            Pointer to NVMe device info.\r
-  @param[in]     SaveAction             TRUE: Save, FALSE: Restore\r
-  @param[in,out] PcieConfBufferList    Configuration space data buffer for save/restore\r
-\r
-  @return PCIE base address of this RootPort\r
-**/\r
-UINTN\r
-SaveRestoreRootportConfSpace (\r
-  IN     OPAL_DEVICE_NVME               *DevInfoNvme,\r
-  IN     BOOLEAN                        SaveAction,\r
-  IN OUT UINT8                          **PcieConfBufferList\r
-  )\r
-{\r
-  UINTN             RpBase;\r
-  UINTN             Length;\r
-  OPAL_PCI_DEVICE   *DevNode;\r
-  UINT8             *StorePcieConfData;\r
-  UINTN             Index;\r
-\r
-  Length = 0;\r
-  Index  = 0;\r
-  RpBase = 0;\r
-\r
-  while (sizeof (OPAL_DEVICE_NVME) + Length < DevInfoNvme->Length) {\r
-    DevNode = (OPAL_PCI_DEVICE *)((UINT8*)DevInfoNvme->PciBridgeNode + Length);\r
-    RpBase = PCI_LIB_ADDRESS (DevNode->Bus, DevNode->Device, DevNode->Function, 0x0);\r
-\r
-    if (PcieConfBufferList != NULL) {\r
-      if (SaveAction) {\r
-        StorePcieConfData = (UINT8 *) AllocateZeroPool (OPAL_PCIE_ROOTPORT_SAVESIZE);\r
-        ASSERT (StorePcieConfData != NULL);\r
-        OpalPciRead (StorePcieConfData, RpBase, OPAL_PCIE_ROOTPORT_SAVESIZE);\r
-        PcieConfBufferList[Index] = StorePcieConfData;\r
-      } else {\r
-        // Skip PCIe Command & Status registers\r
-        StorePcieConfData = PcieConfBufferList[Index];\r
-        OpalPciWrite (RpBase, StorePcieConfData, 4);\r
-        OpalPciWrite (RpBase + 8, StorePcieConfData + 8, OPAL_PCIE_ROOTPORT_SAVESIZE - 8);\r
-\r
-        FreePool (StorePcieConfData);\r
-      }\r
-    }\r
-\r
-    Length += sizeof (OPAL_PCI_DEVICE);\r
-    Index ++;\r
-  }\r
-\r
-  return RpBase;\r
-}\r
-\r
-/**\r
-  Configure RootPort for downstream PCIe NAND devices.\r
-\r
-  @param[in] RpBase             - PCIe configuration space address of this RootPort\r
-  @param[in] BusNumber          - Bus number\r
-  @param[in] MemoryBase         - Memory base address\r
-  @param[in] MemoryLength       - Memory size\r
-\r
-**/\r
-VOID\r
-ConfigureRootPortForPcieNand (\r
-  IN UINTN   RpBase,\r
-  IN UINTN   BusNumber,\r
-  IN UINT32  MemoryBase,\r
-  IN UINT32  MemoryLength\r
-  )\r
-{\r
-  UINT32  MemoryLimit;\r
-\r
-  DEBUG ((DEBUG_INFO, "ConfigureRootPortForPcieNand, BusNumber: %x, MemoryBase: %x, MemoryLength: %x\n",\r
-    BusNumber, MemoryBase, MemoryLength));\r
-\r
-  if (MemoryLength == 0) {\r
-    MemoryLimit = MemoryBase;\r
-  } else {\r
-    MemoryLimit = MemoryBase + MemoryLength + 0xFFFFF; // 1M\r
-  }\r
-\r
-  ///\r
-  /// Configue PCIE configuration space for RootPort\r
-  ///\r
-  PciWrite8  (RpBase + NVME_PCIE_BNUM + 1,  (UINT8) BusNumber);           // Secondary Bus Number registers\r
-  PciWrite8  (RpBase + NVME_PCIE_BNUM + 2,  (UINT8) BusNumber);           // Subordinate Bus Number registers\r
-  PciWrite8  (RpBase + NVME_PCIE_IOBL,      0xFF);                        // I/O Base registers\r
-  PciWrite8  (RpBase + NVME_PCIE_IOBL + 1,  0x00);                        // I/O Limit registers\r
-  PciWrite16 (RpBase + NVME_PCIE_MBL,       (UINT16) RShiftU64 ((UINTN)MemoryBase, 16));  // Memory Base register\r
-  PciWrite16 (RpBase + NVME_PCIE_MBL + 2,   (UINT16) RShiftU64 ((UINTN)MemoryLimit, 16)); // Memory Limit register\r
-  PciWrite16 (RpBase + NVME_PCIE_PMBL,      0xFFFF);                      // Prefetchable Memory Base registers\r
-  PciWrite16 (RpBase + NVME_PCIE_PMBL + 2,  0x0000);                      // Prefetchable Memory Limit registers\r
-  PciWrite32 (RpBase + NVME_PCIE_PMBU32,    0xFFFFFFFF);                  // Prefetchable Memory Upper Base registers\r
-  PciWrite32 (RpBase + NVME_PCIE_PMLU32,    0x00000000);                  // Prefetchable Memory Upper Limit registers\r
+  return PeiDev->SscPpi->SendData (\r
+                           PeiDev->SscPpi,\r
+                           PeiDev->DeviceIndex,\r
+                           SSC_PPI_GENERIC_TIMEOUT,\r
+                           SecurityProtocolId,\r
+                           SecurityProtocolSpecificData,\r
+                           PayloadBufferSize,\r
+                           PayloadBuffer\r
+                           );\r
 }\r
 \r
 /**\r
@@ -651,274 +315,137 @@ UnlockOpalPassword (
 }\r
 \r
 /**\r
-  Unlock ATA OPAL password for S3.\r
+  Unlock the OPAL NVM Express and ATA devices for S3.\r
+\r
+  @param[in] SscPpi    Pointer to the EDKII_PEI_STORAGE_SECURITY_CMD_PPI instance.\r
 \r
 **/\r
 VOID\r
-UnlockOpalPasswordAta (\r
-  VOID\r
+UnlockOpalPasswordDevices (\r
+  IN EDKII_PEI_STORAGE_SECURITY_CMD_PPI    *SscPpi\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  UINT8                         *DevInfo;\r
-  OPAL_DEVICE_ATA               TempDevInfoAta;\r
-  OPAL_DEVICE_ATA               *DevInfoAta;\r
-  UINTN                         DevInfoLengthAta;\r
-  UINT8                         Bus;\r
-  UINT8                         Device;\r
-  UINT8                         Function;\r
-  OPAL_PEI_DEVICE               OpalDev;\r
-  UINT8                         BaseClassCode;\r
-  UINT8                         SubClassCode;\r
-  UINT8                         SataCmdSt;\r
-  AHCI_CONTEXT                  AhciContext;\r
-  UINT32                        AhciBar;\r
-\r
-  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
+  EFI_STATUS                            Status;\r
+  UINT8                                 *DevInfoBuffer;\r
+  UINT8                                 DummyData;\r
+  OPAL_DEVICE_LOCKBOX_DATA              *DevInfo;\r
+  UINTN                                 DevInfoLength;\r
+  EFI_DEVICE_PATH_PROTOCOL              *SscDevicePath;\r
+  UINTN                                 SscDevicePathLength;\r
+  UINTN                                 SscDeviceNum;\r
+  UINTN                                 SscDeviceIndex;\r
+  OPAL_PEI_DEVICE                       OpalDev;\r
 \r
   //\r
-  // Get ATA OPAL device info from LockBox.\r
+  // Get OPAL devices info from LockBox.\r
   //\r
-  DevInfo = (UINT8 *) &TempDevInfoAta;\r
-  DevInfoLengthAta = sizeof (OPAL_DEVICE_ATA);\r
-  Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo, &DevInfoLengthAta);\r
+  DevInfoBuffer = &DummyData;\r
+  DevInfoLength = sizeof (DummyData);\r
+  Status = RestoreLockBox (&mOpalDeviceLockBoxGuid, DevInfoBuffer, &DevInfoLength);\r
   if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthAta));\r
-    if (DevInfo != NULL) {\r
-      Status = RestoreLockBox (&mOpalDeviceAtaGuid, DevInfo, &DevInfoLengthAta);\r
+    DevInfoBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLength));\r
+    if (DevInfoBuffer != NULL) {\r
+      Status = RestoreLockBox (&mOpalDeviceLockBoxGuid, DevInfoBuffer, &DevInfoLength);\r
     }\r
   }\r
-  if (EFI_ERROR (Status) || (DevInfo == NULL)) {\r
+  if (DevInfoBuffer == NULL || DevInfoBuffer == &DummyData) {\r
+    return;\r
+  } else if (EFI_ERROR (Status)) {\r
+    FreePages (DevInfoBuffer, EFI_SIZE_TO_PAGES (DevInfoLength));\r
     return;\r
   }\r
 \r
-  for (DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;\r
-       (UINTN) DevInfoAta < ((UINTN) DevInfo + DevInfoLengthAta);\r
-       DevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) DevInfoAta + DevInfoAta->Length)) {\r
-    Bus = DevInfoAta->Device.Bus;\r
-    Device = DevInfoAta->Device.Device;\r
-    Function = DevInfoAta->Device.Function;\r
-\r
-    SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET));\r
-    PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), 0x6);\r
-\r
-    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));\r
-    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));\r
-    if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||\r
-        ((SubClassCode != PCI_CLASS_MASS_STORAGE_SATADPA) && (SubClassCode != PCI_CLASS_MASS_STORAGE_RAID))) {\r
-      DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode are not supported\n", __FUNCTION__));\r
-    } else {\r
-      AhciBar = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24));\r
-      PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), DevInfoAta->BarAddr);\r
-\r
-      ZeroMem (&AhciContext, sizeof (AHCI_CONTEXT));\r
-      AhciContext.AhciBar = DevInfoAta->BarAddr;\r
-      AhciAllocateResource (&AhciContext);\r
-      Status = AhciModeInitialize (&AhciContext, (UINT8)DevInfoAta->Port);\r
-      ASSERT_EFI_ERROR (Status);\r
-      if (EFI_ERROR (Status)) {\r
-        DEBUG ((DEBUG_ERROR, "%a() AhciModeInitialize() error, Status: %r\n", __FUNCTION__, Status));\r
-      } else {\r
-        OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;\r
-        OpalDev.Sscp.ReceiveData = SecurityReceiveData;\r
-        OpalDev.Sscp.SendData = SecuritySendData;\r
-        OpalDev.DeviceType = OPAL_DEVICE_TYPE_ATA;\r
-        OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoAta;\r
-        OpalDev.Context = &AhciContext;\r
-\r
-        UnlockOpalPassword (&OpalDev);\r
-      }\r
-      AhciFreeResource (&AhciContext);\r
-      PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x24), AhciBar);\r
-    }\r
-    PciWrite8 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), SataCmdSt);\r
-  }\r
-\r
-  ZeroMem (DevInfo, DevInfoLengthAta);\r
-  if ((UINTN) DevInfo != (UINTN) &TempDevInfoAta) {\r
-    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthAta));\r
-  }\r
-\r
-  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
-}\r
-\r
-/**\r
-  Unlock NVMe OPAL password for S3.\r
-\r
-**/\r
-VOID\r
-UnlockOpalPasswordNvme (\r
-  VOID\r
-  )\r
-{\r
-  EFI_STATUS                    Status;\r
-  UINT8                         *DevInfo;\r
-  OPAL_DEVICE_NVME              TempDevInfoNvme;\r
-  OPAL_DEVICE_NVME              *DevInfoNvme;\r
-  UINTN                         DevInfoLengthNvme;\r
-  UINT8                         Bus;\r
-  UINT8                         Device;\r
-  UINT8                         Function;\r
-  OPAL_PEI_DEVICE               OpalDev;\r
-  UINT8                         BaseClassCode;\r
-  UINT8                         SubClassCode;\r
-  UINT8                         ProgInt;\r
-  UINT8                         NvmeCmdSt;\r
-  UINT8                         *StorePcieConfDataList[16];\r
-  UINTN                         RpBase;\r
-  UINTN                         MemoryBase;\r
-  UINTN                         MemoryLength;\r
-  NVME_CONTEXT                  NvmeContext;\r
-\r
-  DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
-\r
   //\r
-  // Get NVMe OPAL device info from LockBox.\r
+  // Go through all the devices managed by the SSC PPI instance.\r
   //\r
-  DevInfo = (UINT8 *) &TempDevInfoNvme;\r
-  DevInfoLengthNvme = sizeof (OPAL_DEVICE_NVME);\r
-  Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo, &DevInfoLengthNvme);\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    DevInfo = AllocatePages (EFI_SIZE_TO_PAGES (DevInfoLengthNvme));\r
-    if (DevInfo != NULL) {\r
-      Status = RestoreLockBox (&mOpalDeviceNvmeGuid, DevInfo, &DevInfoLengthNvme);\r
-    }\r
+  Status = SscPpi->GetNumberofDevices (SscPpi, &SscDeviceNum);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
   }\r
-  if (EFI_ERROR (Status) || (DevInfo == NULL)) {\r
-    return;\r
-  }\r
-\r
-  for (DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;\r
-       (UINTN) DevInfoNvme < ((UINTN) DevInfo + DevInfoLengthNvme);\r
-       DevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) DevInfoNvme + DevInfoNvme->Length)) {\r
-    Bus = DevInfoNvme->Device.Bus;\r
-    Device = DevInfoNvme->Device.Device;\r
-    Function = DevInfoNvme->Device.Function;\r
-\r
-    RpBase    = 0;\r
-    NvmeCmdSt = 0;\r
-\r
-    ///\r
-    /// Save original RootPort configuration space to heap\r
-    ///\r
-    RpBase = SaveRestoreRootportConfSpace (\r
-                DevInfoNvme,\r
-                TRUE, // save\r
-                StorePcieConfDataList\r
-                );\r
-    MemoryBase = DevInfoNvme->BarAddr;\r
-    MemoryLength = 0;\r
-    ConfigureRootPortForPcieNand (RpBase, Bus, (UINT32) MemoryBase, (UINT32) MemoryLength);\r
-\r
-    ///\r
-    /// Enable PCIE decode for RootPort\r
-    ///\r
-    NvmeCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);\r
-    PciWrite8  (RpBase + NVME_PCIE_PCICMD,  0x6);\r
-\r
-    BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));\r
-    SubClassCode  = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));\r
-    ProgInt       = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x09));\r
-    if ((BaseClassCode != PCI_CLASS_MASS_STORAGE) ||\r
-        (SubClassCode != PCI_CLASS_MASS_STORAGE_NVM) ||\r
-        (ProgInt != PCI_IF_NVMHCI)) {\r
-      DEBUG ((DEBUG_ERROR, "%a() ClassCode/SubClassCode/PI are not supported\n", __FUNCTION__));\r
-    } else {\r
-      ZeroMem (&NvmeContext, sizeof (NVME_CONTEXT));\r
-      NvmeContext.Nbar = DevInfoNvme->BarAddr;\r
-      NvmeContext.PciBase = PCI_LIB_ADDRESS (Bus, Device, Function, 0x0);\r
-      NvmeContext.NvmeInitWaitTime = 0;\r
-      NvmeContext.Nsid = DevInfoNvme->NvmeNamespaceId;\r
-      NvmeAllocateResource (&NvmeContext);\r
-      Status = NvmeControllerInit (&NvmeContext);\r
-\r
-      OpalDev.Signature = OPAL_PEI_DEVICE_SIGNATURE;\r
-      OpalDev.Sscp.ReceiveData = SecurityReceiveData;\r
-      OpalDev.Sscp.SendData = SecuritySendData;\r
-      OpalDev.DeviceType = OPAL_DEVICE_TYPE_NVME;\r
-      OpalDev.Device = (OPAL_DEVICE_COMMON *) DevInfoNvme;\r
-      OpalDev.Context = &NvmeContext;\r
-\r
-      UnlockOpalPassword (&OpalDev);\r
-\r
-      Status = NvmeControllerExit (&NvmeContext);\r
-      NvmeFreeResource (&NvmeContext);\r
+  for (SscDeviceIndex = 1; SscDeviceIndex <= SscDeviceNum; SscDeviceIndex++) {\r
+    Status = SscPpi->GetDevicePath (\r
+                       SscPpi,\r
+                       SscDeviceIndex,\r
+                       &SscDevicePathLength,\r
+                       &SscDevicePath\r
+                       );\r
+    if (SscDevicePathLength <= sizeof (EFI_DEVICE_PATH_PROTOCOL)) {\r
+      //\r
+      // Device path validity check.\r
+      //\r
+      continue;\r
     }\r
 \r
-    ASSERT (RpBase != 0);\r
-    PciWrite8  (RpBase + NVME_PCIE_PCICMD, 0);\r
-    RpBase = SaveRestoreRootportConfSpace (\r
-                DevInfoNvme,\r
-                FALSE,  // restore\r
-                StorePcieConfDataList\r
-                );\r
-    PciWrite8  (RpBase + NVME_PCIE_PCICMD, NvmeCmdSt);\r
-  }\r
-\r
-  ZeroMem (DevInfo, DevInfoLengthNvme);\r
-  if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {\r
-    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));\r
+    //\r
+    // Search the device in the restored LockBox.\r
+    //\r
+    for (DevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) DevInfoBuffer;\r
+         (UINTN) DevInfo < ((UINTN) DevInfoBuffer + DevInfoLength);\r
+         DevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) ((UINTN) DevInfo + DevInfo->Length)) {\r
+      //\r
+      // Find the matching device.\r
+      //\r
+      if ((DevInfo->DevicePathLength >= SscDevicePathLength) &&\r
+          (CompareMem (\r
+             DevInfo->DevicePath,\r
+             SscDevicePath,\r
+             SscDevicePathLength - sizeof (EFI_DEVICE_PATH_PROTOCOL)) == 0)) {\r
+        OpalDev.Signature        = OPAL_PEI_DEVICE_SIGNATURE;\r
+        OpalDev.Sscp.ReceiveData = SecurityReceiveData;\r
+        OpalDev.Sscp.SendData    = SecuritySendData;\r
+        OpalDev.Device           = DevInfo;\r
+        OpalDev.Context          = NULL;\r
+        OpalDev.SscPpi           = SscPpi;\r
+        OpalDev.DeviceIndex      = SscDeviceIndex;\r
+        UnlockOpalPassword (&OpalDev);\r
+        break;\r
+      }\r
+    }\r
   }\r
 \r
-  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
-}\r
-\r
-/**\r
-  Unlock OPAL password for S3.\r
+Exit:\r
+  ZeroMem (DevInfoBuffer, DevInfoLength);\r
+  FreePages (DevInfoBuffer, EFI_SIZE_TO_PAGES (DevInfoLength));\r
 \r
-**/\r
-VOID\r
-OpalPasswordS3 (\r
-  VOID\r
-  )\r
-{\r
-  UnlockOpalPasswordAta ();\r
-  UnlockOpalPasswordNvme ();\r
 }\r
 \r
 /**\r
-  Entry point of the notification callback function itself within the PEIM.\r
+  One notified function at the installation of EDKII_PEI_STORAGE_SECURITY_CMD_PPI.\r
   It is to unlock OPAL password for S3.\r
 \r
-  @param  PeiServices      Indirect reference to the PEI Services Table.\r
-  @param  NotifyDescriptor Address of the notification descriptor data structure.\r
-  @param  Ppi              Address of the PPI that was installed.\r
+  @param[in] PeiServices         Indirect reference to the PEI Services Table.\r
+  @param[in] NotifyDescriptor    Address of the notification descriptor data structure.\r
+  @param[in] Ppi                 Address of the PPI that was installed.\r
 \r
   @return Status of the notification.\r
           The status code returned from this function is ignored.\r
+\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-OpalPasswordEndOfPeiNotify(\r
-  IN EFI_PEI_SERVICES          **PeiServices,\r
-  IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
-  IN VOID                      *Ppi\r
+OpalPasswordStorageSecurityPpiNotify (\r
+  IN EFI_PEI_SERVICES             **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR    *NotifyDesc,\r
+  IN VOID                         *Ppi\r
   )\r
 {\r
-  EFI_STATUS                        Status;\r
-  EFI_BOOT_MODE                     BootMode;\r
-\r
-  Status = PeiServicesGetBootMode (&BootMode);\r
-  ASSERT_EFI_ERROR (Status);\r
-  if (BootMode != BOOT_ON_S3_RESUME) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  DEBUG ((DEBUG_INFO, "%a() - enter at S3 resume\n", __FUNCTION__));\r
+  DEBUG ((DEBUG_INFO, "%a entered at S3 resume!\n", __FUNCTION__));\r
 \r
-  OpalPasswordS3 ();\r
+  UnlockOpalPasswordDevices ((EDKII_PEI_STORAGE_SECURITY_CMD_PPI *) Ppi);\r
 \r
-  DEBUG ((DEBUG_INFO, "%a() - exit at S3 resume\n", __FUNCTION__));\r
+  DEBUG ((DEBUG_INFO, "%a exit at S3 resume!\n", __FUNCTION__));\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordEndOfPeiNotifyDesc = {\r
+\r
+EFI_PEI_NOTIFY_DESCRIPTOR mOpalPasswordStorageSecurityPpiNotifyDesc = {\r
   (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
-  &gEfiEndOfPeiSignalPpiGuid,\r
-  OpalPasswordEndOfPeiNotify\r
+  &gEdkiiPeiStorageSecurityCommandPpiGuid,\r
+  OpalPasswordStorageSecurityPpiNotify\r
 };\r
 \r
+\r
 /**\r
   Main entry for this module.\r
 \r
@@ -935,10 +462,17 @@ OpalPasswordPeiInit (
   IN CONST EFI_PEI_SERVICES     **PeiServices\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
+  EFI_STATUS       Status;\r
+  EFI_BOOT_MODE    BootMode;\r
+\r
+  Status = PeiServicesGetBootMode (&BootMode);\r
+  if ((EFI_ERROR (Status)) || (BootMode != BOOT_ON_S3_RESUME)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
 \r
-  Status = PeiServicesNotifyPpi (&mOpalPasswordEndOfPeiNotifyDesc);\r
+  DEBUG ((DEBUG_INFO, "%a: Enters in S3 path.\n", __FUNCTION__));\r
+\r
+  Status = PeiServicesNotifyPpi (&mOpalPasswordStorageSecurityPpiNotifyDesc);\r
   ASSERT_EFI_ERROR (Status);\r
   return Status;\r
 }\r
-\r