]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Tcg/Opal/OpalPassword/OpalPasswordPei.c
OvmfPkg/Csm/LegacyBiosDxe: Update to make it build for OVMF
[mirror_edk2.git] / SecurityPkg / Tcg / Opal / OpalPassword / OpalPasswordPei.c
index edb47ca8bc797f05ff0b6b46e07a5f0839807462..4e5e4eaa932d9ba617914c091166e5244d6fdc11 100644 (file)
 /** @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
-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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "OpalPasswordPei.h"\r
 \r
-EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;\r
-EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_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
+EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;\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 +103,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 +195,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 +309,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
-  }\r
-  if (EFI_ERROR (Status) || (DevInfo == NULL)) {\r
-    return;\r
+  Status = SscPpi->GetNumberofDevices (SscPpi, &SscDeviceNum);\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\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
+    // 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
-  ZeroMem (DevInfo, DevInfoLengthNvme);\r
-  if ((UINTN) DevInfo != (UINTN) &TempDevInfoNvme) {\r
-    FreePages (DevInfo, EFI_SIZE_TO_PAGES (DevInfoLengthNvme));\r
-  }\r
+Exit:\r
+  ZeroMem (DevInfoBuffer, DevInfoLength);\r
+  FreePages (DevInfoBuffer, EFI_SIZE_TO_PAGES (DevInfoLength));\r
 \r
-  DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
 }\r
 \r
 /**\r
-  Unlock OPAL password for S3.\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 +456,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