/** @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
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
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
}\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
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