+++ /dev/null
-/** @file\r
- Opal password smm driver which is used to support Opal security feature at s3 path.\r
-\r
-Copyright (c) 2016, 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
-\r
-**/\r
-\r
-#include "OpalPasswordSmm.h"\r
-\r
-#define SMM_SIZE_ALLOC_BYTES (512)\r
-#define RESPONSE_SIZE (200)\r
-\r
-#define PCI_CLASS_MASS_STORAGE_AHCI (0x06)\r
-\r
-#define OPAL_PCIE_ROOTPORT_SAVESIZE (0x40)\r
-#define STORE_INVALID_ROOTPORT_INDEX ((UINT8) -1)\r
-#define OPAL_DEVICE_TYPE_SATA 0x1\r
-#define OPAL_DEVICE_TYPE_NVME 0x2\r
-#define OPAL_DEVICE_TYPE_UNKNOWN 0xFF\r
-\r
-//\r
-// To unlock the Intel SATA controller at S3 Resume, restored the following registers.\r
-//\r
-const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {\r
- {0x9, S3BootScriptWidthUint8},\r
- {0x10, S3BootScriptWidthUint32},\r
- {0x14, S3BootScriptWidthUint32},\r
- {0x18, S3BootScriptWidthUint32},\r
- {0x1C, S3BootScriptWidthUint32},\r
- {0x20, S3BootScriptWidthUint32},\r
- {0x24, S3BootScriptWidthUint32},\r
- {0x3c, S3BootScriptWidthUint8},\r
- {0x3d, S3BootScriptWidthUint8},\r
- {0x40, S3BootScriptWidthUint16},\r
- {0x42, S3BootScriptWidthUint16},\r
- {0x92, S3BootScriptWidthUint16},\r
- {0x94, S3BootScriptWidthUint32},\r
- {0x9C, S3BootScriptWidthUint32},\r
- {0x4, S3BootScriptWidthUint16},\r
-};\r
-\r
-\r
-UINT8 mSwSmiValue;\r
-LIST_ENTRY *mOpalDeviceList;\r
-LIST_ENTRY mSmmDeviceList = INITIALIZE_LIST_HEAD_VARIABLE (mSmmDeviceList);\r
-\r
-BOOLEAN mSendBlockSID = FALSE;\r
-\r
-// AHCI\r
-UINT32 mAhciBar = 0;\r
-EFI_AHCI_REGISTERS mAhciRegisters;\r
-VOID *mBuffer = NULL; // DMA can not read/write Data to smram, so we pre-allocates Buffer from AcpiNVS.\r
-//\r
-// NVME\r
-NVME_CONTEXT mNvmeContext;\r
-\r
-/**\r
- Add new bridge node or nvme device info to the device list.\r
-\r
- @param[in] BusNum The bus number.\r
- @param[in] DevNum The device number.\r
- @param[in] FuncNum The function number.\r
- @param[in] Dev The device which need to add device node info.\r
-\r
-**/\r
-VOID\r
-AddPciDeviceNode (\r
- UINT32 BusNum,\r
- UINT32 DevNum,\r
- UINT32 FuncNum,\r
- OPAL_SMM_DEVICE *Dev\r
- )\r
-{\r
- UINT8 *DevList;\r
- PCI_DEVICE *DeviceNode;\r
-\r
- DevList = AllocateZeroPool (sizeof (PCI_DEVICE) + Dev->Length);\r
- ASSERT (DevList != NULL);\r
-\r
- if (Dev->Length != 0) {\r
- CopyMem (DevList, Dev->PciBridgeNode, Dev->Length);\r
- FreePool (Dev->PciBridgeNode);\r
- }\r
-\r
- DeviceNode = (PCI_DEVICE *) (DevList + Dev->Length);\r
-\r
- DeviceNode->BusNum = BusNum;\r
- DeviceNode->DevNum = DevNum;\r
- DeviceNode->FuncNum = FuncNum;\r
-\r
- Dev->Length += sizeof (PCI_DEVICE);\r
- Dev->PciBridgeNode = (PCI_DEVICE *)DevList;\r
-}\r
-\r
-/**\r
- Extract device info from the input device path.\r
-\r
- @param[in] DevicePath Device path info for the device.\r
- @param[in,out] Dev The device which new inputed.\r
-\r
-**/\r
-VOID\r
-ExtractDeviceInfoFromDevicePath (\r
- IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- IN OUT OPAL_SMM_DEVICE *Dev\r
- )\r
-{\r
- EFI_DEVICE_PATH_PROTOCOL *TmpDevPath;\r
- EFI_DEVICE_PATH_PROTOCOL *TmpDevPath2;\r
- PCI_DEVICE_PATH *PciDevPath;\r
- SATA_DEVICE_PATH *SataDevPath;\r
- NVME_NAMESPACE_DEVICE_PATH *NvmeDevPath;\r
- UINTN BusNum;\r
-\r
- TmpDevPath = DevicePath;\r
- Dev->DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;\r
-\r
- while (!IsDevicePathEnd(TmpDevPath)) {\r
- if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_SATA_DP) {\r
- //\r
- // SATA\r
- //\r
- SataDevPath = ( SATA_DEVICE_PATH* )TmpDevPath;\r
- Dev->SataPort = SataDevPath->HBAPortNumber;\r
- Dev->SataPortMultiplierPort = SataDevPath->PortMultiplierPortNumber;\r
- Dev->DeviceType = OPAL_DEVICE_TYPE_SATA;\r
- break;\r
- } else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {\r
- //\r
- // NVMe\r
- //\r
- NvmeDevPath = ( NVME_NAMESPACE_DEVICE_PATH* )TmpDevPath;\r
- Dev->NvmeNamespaceId = NvmeDevPath->NamespaceId;\r
- Dev->DeviceType = OPAL_DEVICE_TYPE_NVME;\r
- break;\r
- }\r
- TmpDevPath = NextDevicePathNode (TmpDevPath);\r
- }\r
-\r
- //\r
- // Get bridge node info for the nvme device.\r
- //\r
- BusNum = 0;\r
- TmpDevPath = DevicePath;\r
- TmpDevPath2 = NextDevicePathNode (DevicePath);\r
- while (!IsDevicePathEnd(TmpDevPath2)) {\r
- if (TmpDevPath->Type == HARDWARE_DEVICE_PATH && TmpDevPath->SubType == HW_PCI_DP) {\r
- PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;\r
- if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||\r
- (TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_SATA_DP)) {\r
- Dev->BusNum = (UINT32)BusNum;\r
- Dev->DevNum = PciDevPath->Device;\r
- Dev->FuncNum = PciDevPath->Function;\r
- } else {\r
- AddPciDeviceNode((UINT32)BusNum, PciDevPath->Device, PciDevPath->Function, Dev);\r
- if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH && TmpDevPath2->SubType == HW_PCI_DP) {\r
- BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum, PciDevPath->Device, PciDevPath->Function, NVME_PCIE_SEC_BNUM));\r
- }\r
- }\r
- }\r
-\r
- TmpDevPath = NextDevicePathNode (TmpDevPath);\r
- TmpDevPath2 = NextDevicePathNode (TmpDevPath2);\r
- }\r
-}\r
-\r
-/**\r
-\r
- The function returns whether or not the device is Opal Locked.\r
- TRUE means that the device is partially or fully locked.\r
- This will perform a Level 0 Discovery and parse the locking feature descriptor\r
-\r
- @param[in] OpalDev Opal object to determine if locked\r
- @param[out] BlockSidSupported Whether device support BlockSid feature.\r
-\r
-**/\r
-BOOLEAN\r
-IsOpalDeviceLocked(\r
- OPAL_SMM_DEVICE *OpalDev,\r
- BOOLEAN *BlockSidSupported\r
- )\r
-{\r
- OPAL_SESSION Session;\r
- OPAL_DISK_SUPPORT_ATTRIBUTE SupportedAttributes;\r
- TCG_LOCKING_FEATURE_DESCRIPTOR LockingFeature;\r
- UINT16 OpalBaseComId;\r
- TCG_RESULT Ret;\r
-\r
- Session.Sscp = &OpalDev->Sscp;\r
- Session.MediaId = 0;\r
-\r
- Ret = OpalGetSupportedAttributesInfo (&Session, &SupportedAttributes, &OpalBaseComId);\r
- if (Ret != TcgResultSuccess) {\r
- return FALSE;\r
- }\r
-\r
- OpalDev->OpalBaseComId = OpalBaseComId;\r
- Session.OpalBaseComId = OpalBaseComId;\r
- *BlockSidSupported = SupportedAttributes.BlockSid == 1 ? TRUE : FALSE;\r
-\r
- Ret = OpalGetLockingInfo(&Session, &LockingFeature);\r
- if (Ret != TcgResultSuccess) {\r
- return FALSE;\r
- }\r
-\r
- return OpalDeviceLocked (&SupportedAttributes, &LockingFeature);\r
-}\r
-\r
-/**\r
- Save/Restore RootPort configuration space.\r
-\r
- @param[in] DeviceNode - The device node.\r
- @param[in] SaveAction - TRUE: Save, FALSE: Restore\r
- @param[in,out] PcieConfBufferList - Configuration space data buffer for save/restore\r
-\r
- @retval - PCIE base address of this RootPort\r
-**/\r
-UINTN\r
-SaveRestoreRootportConfSpace (\r
- IN OPAL_SMM_DEVICE *DeviceNode,\r
- IN BOOLEAN SaveAction,\r
- IN OUT UINT8 **PcieConfBufferList\r
- )\r
-{\r
- UINTN RpBase;\r
- UINTN Length;\r
- PCI_DEVICE *DevNode;\r
- UINT8 *StorePcieConfData;\r
- UINTN Index;\r
-\r
- Length = 0;\r
- Index = 0;\r
- RpBase = 0;\r
-\r
- while (Length < DeviceNode->Length) {\r
- DevNode = (PCI_DEVICE *)((UINT8*)DeviceNode->PciBridgeNode + Length);\r
- RpBase = PCI_LIB_ADDRESS (DevNode->BusNum, DevNode->DevNum, DevNode->FuncNum, 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 (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
-}\r
-\r
-\r
-/**\r
- Dispatch function for a Software SMI handler.\r
-\r
- @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
- @param[in] RegisterContext Points to an optional handler context which was specified when the\r
- handler was registered.\r
- @param[in, out] CommBuffer A pointer to a collection of Data in memory that will\r
- be conveyed from a non-SMM environment into an SMM environment.\r
- @param[in, out] CommBufferSize The Size of the CommBuffer.\r
-\r
- @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers\r
- should still be called.\r
- @retval Others Other execution results.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SmmUnlockOpalPassword (\r
- IN EFI_HANDLE DispatchHandle,\r
- IN CONST VOID *RegisterContext,\r
- IN OUT VOID *CommBuffer,\r
- IN OUT UINTN *CommBufferSize\r
- )\r
-{\r
- EFI_STATUS Status;\r
- OPAL_SMM_DEVICE *OpalDev;\r
- LIST_ENTRY *Entry;\r
- UINT8 BaseClassCode;\r
- UINT8 SubClassCode;\r
- UINT8 ProgInt;\r
- TCG_RESULT Result;\r
- UINT8 SataCmdSt;\r
- UINT8 *StorePcieConfDataList[16];\r
- UINTN RpBase;\r
- UINTN MemoryBase;\r
- UINTN MemoryLength;\r
- OPAL_SESSION Session;\r
- BOOLEAN BlockSidSupport;\r
-\r
- ZeroMem (StorePcieConfDataList, sizeof (StorePcieConfDataList));\r
- Status = EFI_DEVICE_ERROR;\r
-\r
- //\r
- // try to unlock all locked hdd disks.\r
- //\r
- for (Entry = mSmmDeviceList.ForwardLink; Entry != &mSmmDeviceList; Entry = Entry->ForwardLink) {\r
- OpalDev = BASE_CR(Entry, OPAL_SMM_DEVICE, Link);\r
-\r
- RpBase = 0;\r
- SataCmdSt = 0;\r
-\r
- ///\r
- /// Configure RootPort for PCIe AHCI/NVME devices.\r
- ///\r
- if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
- ///\r
- /// Save original RootPort configuration space to heap\r
- ///\r
- RpBase = SaveRestoreRootportConfSpace (\r
- OpalDev,\r
- TRUE,\r
- StorePcieConfDataList\r
- );\r
- MemoryBase = mNvmeContext.Nbar;\r
- MemoryLength = 0;\r
- ConfigureRootPortForPcieNand (RpBase, OpalDev->BusNum, (UINT32) MemoryBase, (UINT32) MemoryLength);\r
-\r
- ///\r
- /// Enable PCIE decode for RootPort\r
- ///\r
- SataCmdSt = PciRead8 (RpBase + NVME_PCIE_PCICMD);\r
- PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0x6);\r
- } else {\r
- SataCmdSt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD));\r
- PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), 0x6);\r
- }\r
-\r
- BaseClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0B));\r
- SubClassCode = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0A));\r
- ProgInt = PciRead8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x09));\r
- if (BaseClassCode != PCI_CLASS_MASS_STORAGE) {\r
- Status = EFI_INVALID_PARAMETER;\r
- break;\r
- }\r
-\r
- Status = EFI_DEVICE_ERROR;\r
- if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_SATA) {\r
- if ((SubClassCode == PCI_CLASS_MASS_STORAGE_AHCI) || (SubClassCode == PCI_CLASS_MASS_STORAGE_RAID)) {\r
- Status = GetAhciBaseAddress (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "GetAhciBaseAddress error, Status: %r\n", Status));\r
- goto done;\r
- }\r
- Status = AhciModeInitialize ((UINT8)OpalDev->SataPort);\r
- ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "AhciModeInitialize error, Status: %r\n", Status));\r
- goto done;\r
- }\r
- } else {\r
- DEBUG ((DEBUG_ERROR, "SubClassCode not support for SATA device\n"));\r
- }\r
- } else if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
- if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) {\r
- if (ProgInt != PCI_IF_NVMHCI) {\r
- DEBUG ((DEBUG_ERROR, "PI not support, skipped\n"));\r
- Status = EFI_NOT_FOUND;\r
- goto done;\r
- }\r
-\r
- mNvmeContext.PciBase = PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, 0x0);\r
- mNvmeContext.NvmeInitWaitTime = 0;\r
- mNvmeContext.Nsid = OpalDev->NvmeNamespaceId;\r
- Status = NvmeControllerInit (&mNvmeContext);\r
- } else {\r
- DEBUG ((DEBUG_ERROR, "SubClassCode not support for NVME device\n"));\r
- }\r
- } else {\r
- DEBUG ((DEBUG_ERROR, "Invalid Devicetype\n"));\r
- goto done;\r
- }\r
-\r
- Status = EFI_DEVICE_ERROR;\r
- BlockSidSupport = FALSE;\r
- if (IsOpalDeviceLocked (OpalDev, &BlockSidSupport)) {\r
- ZeroMem(&Session, sizeof(Session));\r
- Session.Sscp = &OpalDev->Sscp;\r
- Session.MediaId = 0;\r
- Session.OpalBaseComId = OpalDev->OpalBaseComId;\r
-\r
- Result = OpalSupportUnlock (&Session, OpalDev->Password, OpalDev->PasswordLength, NULL);\r
- if (Result == TcgResultSuccess) {\r
- Status = EFI_SUCCESS;\r
- }\r
- }\r
-\r
- if (mSendBlockSID && BlockSidSupport) {\r
- Result = OpalBlockSid (&Session, TRUE);\r
- if (Result != TcgResultSuccess) {\r
- break;\r
- }\r
- }\r
-\r
- if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
- if (SubClassCode == PCI_CLASS_MASS_STORAGE_NVM) {\r
- Status = NvmeControllerExit (&mNvmeContext);\r
- }\r
- }\r
-\r
-done:\r
- if (OpalDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
- ASSERT (RpBase != 0);\r
- PciWrite8 (RpBase + NVME_PCIE_PCICMD, 0);\r
- RpBase = SaveRestoreRootportConfSpace (\r
- OpalDev,\r
- FALSE, // restore\r
- StorePcieConfDataList\r
- );\r
- PciWrite8 (RpBase + NVME_PCIE_PCICMD, SataCmdSt);\r
- } else {\r
- PciWrite8 (PCI_LIB_ADDRESS (OpalDev->BusNum, OpalDev->DevNum, OpalDev->FuncNum, NVME_PCIE_PCICMD), SataCmdSt);\r
- }\r
-\r
- if (EFI_ERROR (Status)) {\r
- break;\r
- }\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- The function extracts device information from OpalDeviceList and creat SmmDeviceList used for S3.\r
-\r
- @param[in] OpalDeviceList Opal device list created at POST which contains the information of OPAL_DISK_AND_PASSWORD_INFO\r
- @param[in,out] SmmDeviceList Opal Smm device list to be created and used for unlocking devices at S3 resume.\r
-\r
- @retval EFI_SUCCESS Create SmmDeviceList successfully.\r
- @retval Others Other execution results.\r
-**/\r
-EFI_STATUS\r
-CreateSmmDeviceList (\r
- IN LIST_ENTRY *OpalDeviceList,\r
- IN OUT LIST_ENTRY *SmmDeviceList\r
- )\r
-{\r
- LIST_ENTRY *Entry;\r
- OPAL_DISK_AND_PASSWORD_INFO *PciDev;\r
- OPAL_SMM_DEVICE *SmmDev;\r
-\r
- for (Entry = OpalDeviceList->ForwardLink; Entry != OpalDeviceList; Entry = Entry->ForwardLink) {\r
- PciDev = BASE_CR (Entry, OPAL_DISK_AND_PASSWORD_INFO, Link);\r
-\r
- SmmDev = AllocateZeroPool (sizeof (OPAL_SMM_DEVICE));\r
- if (SmmDev == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- SmmDev->Signature = OPAL_SMM_DEVICE_SIGNATURE;\r
-\r
- ExtractDeviceInfoFromDevicePath(&PciDev->OpalDevicePath, SmmDev);\r
-\r
- SmmDev->PasswordLength = PciDev->PasswordLength;\r
- CopyMem(&(SmmDev->Password), PciDev->Password, OPAL_PASSWORD_MAX_LENGTH);\r
-\r
- SmmDev->Sscp.ReceiveData = SecurityReceiveData;\r
- SmmDev->Sscp.SendData = SecuritySendData;\r
-\r
- DEBUG ((DEBUG_INFO, "Opal SMM: Insert device node to SmmDeviceList:\n"));\r
- DEBUG ((DEBUG_INFO, "DeviceType:%x, Bus:%d, Dev:%d, Fun:%d\n", \\r
- SmmDev->DeviceType, SmmDev->BusNum, SmmDev->DevNum, SmmDev->FuncNum));\r
- DEBUG ((DEBUG_INFO, "SataPort:%x, MultiplierPort:%x, NvmeNamespaceId:%x\n", \\r
- SmmDev->SataPort, SmmDev->SataPortMultiplierPort, SmmDev->NvmeNamespaceId));\r
-\r
- InsertHeadList (SmmDeviceList, &SmmDev->Link);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Main entry point for an SMM handler dispatch or communicate-based callback.\r
-\r
- @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
- @param[in] Context Points to an optional handler context which was specified when the\r
- handler was registered.\r
- @param[in,out] CommBuffer A pointer to a collection of Data in memory that will\r
- be conveyed from a non-SMM environment into an SMM environment.\r
- @param[in,out] CommBufferSize The Size of the CommBuffer.\r
-\r
- @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers\r
- should still be called.\r
- @retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should\r
- still be called.\r
- @retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still\r
- be called.\r
- @retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-S3SleepEntryCallBack (\r
- IN EFI_HANDLE DispatchHandle,\r
- IN CONST VOID *Context OPTIONAL,\r
- IN OUT VOID *CommBuffer OPTIONAL,\r
- IN OUT UINTN *CommBufferSize OPTIONAL\r
- )\r
-{\r
- UINTN Bus;\r
- UINTN Device;\r
- UINTN Function;\r
- UINTN Index;\r
- EFI_STATUS Status;\r
- LIST_ENTRY *Entry;\r
- UINTN Offset;\r
- UINT64 Address;\r
- S3_BOOT_SCRIPT_LIB_WIDTH Width;\r
- UINT32 Data;\r
- OPAL_HC_PCI_REGISTER_SAVE *HcRegisterSaveListPtr;\r
- UINTN Count;\r
- OPAL_SMM_DEVICE *SmmDev;\r
-\r
- Data = 0;\r
- Status = EFI_SUCCESS;\r
-\r
- mOpalDeviceList = OpalSupportGetOpalDeviceList();\r
- if (IsListEmpty (mOpalDeviceList)) {\r
- //\r
- // No Opal enabled device. Do nothing.\r
- //\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (IsListEmpty (&mSmmDeviceList)) {\r
- //\r
- // mSmmDeviceList for S3 is empty, creat it by mOpalDeviceList.\r
- //\r
- Status = CreateSmmDeviceList (mOpalDeviceList, &mSmmDeviceList);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- //\r
- // Go through SmmDeviceList to save register data for S3\r
- //\r
- for (Entry = mSmmDeviceList.ForwardLink; Entry != &mSmmDeviceList; Entry = Entry->ForwardLink) {\r
- SmmDev = BASE_CR (Entry, OPAL_SMM_DEVICE, Link);\r
-\r
- if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
- continue;\r
- }\r
-\r
- //\r
- // Save register Data for S3. Sata controller only.\r
- //\r
- Bus = SmmDev->BusNum;\r
- Device = SmmDev->DevNum;\r
- Function = SmmDev->FuncNum;\r
-\r
- ASSERT (SmmDev->DeviceType == OPAL_DEVICE_TYPE_SATA);\r
- HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *) mSataHcRegisterSaveTemplate;\r
- Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof (OPAL_HC_PCI_REGISTER_SAVE);\r
-\r
- for (Index = 0; Index < Count; Index += 1) {\r
- Offset = HcRegisterSaveListPtr[Index].Address;\r
- Width = HcRegisterSaveListPtr[Index].Width;\r
-\r
- switch (Width) {\r
- case S3BootScriptWidthUint8:\r
- Data = (UINT32)PciRead8 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
- break;\r
- case S3BootScriptWidthUint16:\r
- Data = (UINT32)PciRead16 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
- break;\r
- case S3BootScriptWidthUint32:\r
- Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
- break;\r
- default:\r
- ASSERT (FALSE);\r
- break;\r
- }\r
-\r
- Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function, Offset);\r
- Status = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
- }\r
- }\r
-\r
- Status = S3BootScriptSaveIoWrite (S3BootScriptWidthUint8, 0xB2, 1, &mSwSmiValue);\r
- ASSERT_EFI_ERROR (Status);\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Main entry for this driver.\r
-\r
- @param ImageHandle Image handle this driver.\r
- @param SystemTable Pointer to SystemTable.\r
-\r
- @retval EFI_SUCESS This function always complete successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-OpalPasswordSmmInit (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
- )\r
-{\r
- EFI_STATUS Status;\r
- EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;\r
- EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatch;\r
- EFI_HANDLE SwHandle;\r
- EFI_SMM_SW_REGISTER_CONTEXT Context;\r
- EFI_HANDLE S3SleepEntryHandle;\r
- EFI_SMM_SX_REGISTER_CONTEXT EntryRegisterContext;\r
- EFI_SMM_VARIABLE_PROTOCOL *SmmVariable;\r
- OPAL_EXTRA_INFO_VAR OpalExtraInfo;\r
- UINTN DataSize;\r
- EFI_PHYSICAL_ADDRESS Address;\r
-\r
- mBuffer = NULL;\r
- SwHandle = NULL;\r
- S3SleepEntryHandle = NULL;\r
- ZeroMem (&mNvmeContext, sizeof (NVME_CONTEXT));\r
-\r
- Status = gSmst->SmmLocateProtocol (\r
- &gEfiSmmSwDispatch2ProtocolGuid,\r
- NULL,\r
- (VOID **)&SwDispatch\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG((DEBUG_ERROR, " SmmLocateProtocol gEfiSmmSwDispatch2ProtocolGuid fail, Status: %r\n", Status));\r
- return Status;\r
- }\r
-\r
- Status = gSmst->SmmLocateProtocol (\r
- &gEfiSmmSxDispatch2ProtocolGuid,\r
- NULL,\r
- (VOID **)&SxDispatch\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG((DEBUG_ERROR, " SmmLocateProtocol gEfiSmmSxDispatch2ProtocolGuid fail, Status: %r\n", Status));\r
- return Status;\r
- }\r
-\r
- //\r
- // Preallocate a 512 bytes Buffer to perform trusted I/O.\r
- // Assume this is big enough for unlock commands\r
- // It's because DMA can not access smmram stack at the cmd execution.\r
- //\r
- Address = 0xFFFFFFFF;\r
- Status = gBS->AllocatePages (\r
- AllocateMaxAddress,\r
- EfiACPIMemoryNVS,\r
- EFI_SIZE_TO_PAGES (SMM_SIZE_ALLOC_BYTES),\r
- &Address\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG((DEBUG_ERROR, " AllocatePages for SATA DAM fail, Status: %r\n", Status));\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
- mBuffer = (VOID *)(UINTN)Address;\r
- ZeroMem ((VOID *)(UINTN)mBuffer, SMM_SIZE_ALLOC_BYTES);\r
-\r
- //\r
- // Preallocate resource for AHCI transfer descriptor.\r
- //\r
- Status = AhciAllocateResource ();\r
- if (EFI_ERROR (Status)) {\r
- DEBUG((DEBUG_ERROR, " AhciAllocateResource fail, Status: %r\n", Status));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Preallocate resource for NVMe configuration space.\r
- //\r
- Status = NvmeAllocateResource (ImageHandle, &mNvmeContext);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG((DEBUG_ERROR, " NvmeAllocateResource fail, Status: %r\n", Status));\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Register a S3 entry callback function to store ATA host controller context to boot script.\r
- // These boot scripts would be invoked at S3 path to recovery ATA host controller h/w context\r
- // for executing HDD unlock cmd.\r
- //\r
- EntryRegisterContext.Type = SxS3;\r
- EntryRegisterContext.Phase = SxEntry;\r
- Status = SxDispatch->Register (\r
- SxDispatch,\r
- S3SleepEntryCallBack,\r
- &EntryRegisterContext,\r
- &S3SleepEntryHandle\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // Register Opal password smm unlock handler\r
- //\r
- Context.SwSmiInputValue = (UINTN) -1;\r
- Status = SwDispatch->Register (\r
- SwDispatch,\r
- SmmUnlockOpalPassword,\r
- &Context,\r
- &SwHandle\r
- );\r
- ASSERT_EFI_ERROR (Status);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG((DEBUG_ERROR, " SwDispatch->Register fail, Status: %r\n", Status));\r
- goto EXIT;\r
- }\r
-\r
- //\r
- // trigger smi to unlock hdd if it's locked.\r
- //\r
- mSwSmiValue = (UINT8) Context.SwSmiInputValue;\r
-\r
- Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&SmmVariable);\r
- if (!EFI_ERROR (Status)) {\r
- DataSize = sizeof (OPAL_EXTRA_INFO_VAR);\r
- Status = SmmVariable->SmmGetVariable (\r
- OPAL_EXTRA_INFO_VAR_NAME,\r
- &gOpalExtraInfoVariableGuid,\r
- NULL,\r
- &DataSize,\r
- &OpalExtraInfo\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- mSendBlockSID = OpalExtraInfo.EnableBlockSid;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-\r
-EXIT:\r
- if (S3SleepEntryHandle != NULL) {\r
- SxDispatch->UnRegister (SxDispatch, S3SleepEntryHandle);\r
- }\r
-\r
- AhciFreeResource ();\r
-\r
- NvmeFreeResource (&mNvmeContext);\r
-\r
- if (mBuffer != NULL) {\r
- gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN) mBuffer, EFI_SIZE_TO_PAGES (SMM_SIZE_ALLOC_BYTES));\r
- }\r
-\r
- return Status;\r
-}\r
-\r
-/**\r
- Provide Io action support.\r
-\r
- @param[in] SmmDev the opal device need to perform trust 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 TcgResultSuccess Perform the io action success.\r
- @retval TcgResultFailure Perform the io action failed.\r
-\r
-**/\r
-EFI_STATUS\r
-PerformTrustedIo (\r
- OPAL_SMM_DEVICE *SmmDev,\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
-\r
- Status = EFI_DEVICE_ERROR;\r
- if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_SATA) {\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( mBuffer, HDD_PAYLOAD );\r
- ASSERT( TransferLength <= HDD_PAYLOAD );\r
-\r
- if (IoType == OpalSend) {\r
- CopyMem( mBuffer, Buffer, TransferLength );\r
- }\r
-\r
- Status = AhciPioTransfer(\r
- &mAhciRegisters,\r
- (UINT8) SmmDev->SataPort,\r
- (UINT8) SmmDev->SataPortMultiplierPort,\r
- NULL,\r
- 0,\r
- ( IoType == OpalSend ) ? FALSE : TRUE, // i/o direction\r
- &AtaCommandBlock,\r
- NULL,\r
- mBuffer,\r
- (UINT32)TransferLength,\r
- ATA_TIMEOUT\r
- );\r
-\r
- if (IoType == OpalRecv) {\r
- CopyMem( Buffer, mBuffer, TransferLength );\r
- }\r
- } else if (SmmDev->DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
- Status = NvmeSecuritySendReceive (\r
- &mNvmeContext,\r
- IoType == OpalSend,\r
- SecurityProtocol,\r
- SwapBytes16(SpSpecific),\r
- TransferLength,\r
- Buffer\r
- );\r
- } else {\r
- DEBUG((DEBUG_ERROR, "DeviceType(%x) not support.\n", SmmDev->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
- of one or more commands sent by SendData.\r
-\r
- The ReceiveData function sends a security protocol command to the given MediaId.\r
- The security protocol command sent is defined by SecurityProtocolId and contains\r
- the security protocol specific data SecurityProtocolSpecificData. The function\r
- returns the data from the security protocol command in PayloadBuffer.\r
-\r
- For devices supporting the SCSI command set, the security protocol command is sent\r
- using the SECURITY PROTOCOL IN command defined in SPC-4.\r
-\r
- For devices supporting the ATA command set, the security protocol command is sent\r
- using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize\r
- is non-zero.\r
-\r
- If the PayloadBufferSize is zero, the security protocol command is sent using the\r
- Trusted Non-Data command defined in ATA8-ACS.\r
-\r
- If PayloadBufferSize is too small to store the available data from the security\r
- protocol command, the function shall copy PayloadBufferSize bytes into the\r
- PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.\r
-\r
- If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,\r
- the function shall return EFI_INVALID_PARAMETER.\r
-\r
- If the given MediaId does not support security protocol commands, the function shall\r
- return EFI_UNSUPPORTED. If there is no media in the device, the function returns\r
- EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,\r
- the function returns EFI_MEDIA_CHANGED.\r
-\r
- If the security protocol fails to complete within the Timeout period, the function\r
- shall return EFI_TIMEOUT.\r
-\r
- If the security protocol command completes without an error, the function shall\r
- return EFI_SUCCESS. If the security protocol command completes with an error, the\r
- function shall return EFI_DEVICE_ERROR.\r
-\r
- @param This Indicates a pointer to the calling context.\r
- @param MediaId ID of the medium to receive data from.\r
- @param Timeout The timeout, in 100ns units, to use for the execution\r
- of the security protocol command. A Timeout value of 0\r
- means that this function will wait indefinitely for the\r
- security protocol command to execute. If Timeout is greater\r
- than zero, then this function will return EFI_TIMEOUT\r
- if the time required to execute the receive data command\r
- is greater than Timeout.\r
- @param SecurityProtocolId The value of the "Security Protocol" parameter of\r
- the security protocol command to be sent.\r
- @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
- of the security protocol command to be sent.\r
- @param PayloadBufferSize Size in bytes of the payload data buffer.\r
- @param PayloadBuffer A pointer to a destination buffer to store the security\r
- protocol command specific payload data for the security\r
- protocol command. The caller is responsible for having\r
- either implicit or explicit ownership of the buffer.\r
- @param PayloadTransferSize A pointer to a buffer to store the size in bytes of the\r
- data written to the payload data buffer.\r
-\r
- @retval EFI_SUCCESS The security protocol command completed successfully.\r
- @retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available\r
- data from the device. The PayloadBuffer contains the truncated data.\r
- @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.\r
- @retval EFI_DEVICE_ERROR The security protocol command completed with an error.\r
- @retval EFI_NO_MEDIA There is no media in the device.\r
- @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
- @retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and\r
- PayloadBufferSize is non-zero.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the security\r
- protocol command to execute.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SecurityReceiveData (\r
- IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,\r
- IN UINT32 MediaId,\r
- IN UINT64 Timeout,\r
- IN UINT8 SecurityProtocolId,\r
- IN UINT16 SecurityProtocolSpecificData,\r
- IN UINTN PayloadBufferSize,\r
- OUT VOID *PayloadBuffer,\r
- OUT UINTN *PayloadTransferSize\r
- )\r
-{\r
- OPAL_SMM_DEVICE *SmmDev;\r
-\r
- SmmDev = OPAL_SMM_DEVICE_FROM_THIS (This);\r
- if (SmmDev == NULL) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return PerformTrustedIo (\r
- SmmDev,\r
- OpalRecv,\r
- SecurityProtocolId,\r
- SecurityProtocolSpecificData,\r
- PayloadBufferSize,\r
- PayloadBuffer\r
- );\r
-}\r
-\r
-/**\r
- Send a security protocol command to a device.\r
-\r
- The SendData function sends a security protocol command containing the payload\r
- PayloadBuffer to the given MediaId. The security protocol command sent is\r
- defined by SecurityProtocolId and contains the security protocol specific data\r
- SecurityProtocolSpecificData. If the underlying protocol command requires a\r
- specific padding for the command payload, the SendData function shall add padding\r
- bytes to the command payload to satisfy the padding requirements.\r
-\r
- For devices supporting the SCSI command set, the security protocol command is sent\r
- using the SECURITY PROTOCOL OUT command defined in SPC-4.\r
-\r
- For devices supporting the ATA command set, the security protocol command is sent\r
- using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize\r
- is non-zero. If the PayloadBufferSize is zero, the security protocol command is\r
- sent using the Trusted Non-Data command defined in ATA8-ACS.\r
-\r
- If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall\r
- return EFI_INVALID_PARAMETER.\r
-\r
- If the given MediaId does not support security protocol commands, the function\r
- shall return EFI_UNSUPPORTED. If there is no media in the device, the function\r
- returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the\r
- device, the function returns EFI_MEDIA_CHANGED.\r
-\r
- If the security protocol fails to complete within the Timeout period, the function\r
- shall return EFI_TIMEOUT.\r
-\r
- If the security protocol command completes without an error, the function shall return\r
- EFI_SUCCESS. If the security protocol command completes with an error, the function\r
- shall return EFI_DEVICE_ERROR.\r
-\r
- @param This Indicates a pointer to the calling context.\r
- @param MediaId ID of the medium to receive data from.\r
- @param Timeout The timeout, in 100ns units, to use for the execution\r
- of the security protocol command. A Timeout value of 0\r
- means that this function will wait indefinitely for the\r
- security protocol command to execute. If Timeout is greater\r
- than zero, then this function will return EFI_TIMEOUT\r
- if the time required to execute the send data command\r
- is greater than Timeout.\r
- @param SecurityProtocolId The value of the "Security Protocol" parameter of\r
- the security protocol command to be sent.\r
- @param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter\r
- of the security protocol command to be sent.\r
- @param PayloadBufferSize Size in bytes of the payload data buffer.\r
- @param PayloadBuffer A pointer to a destination buffer to store the security\r
- protocol command specific payload data for the security\r
- protocol command.\r
-\r
- @retval EFI_SUCCESS The security protocol command completed successfully.\r
- @retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.\r
- @retval EFI_DEVICE_ERROR The security protocol command completed with an error.\r
- @retval EFI_NO_MEDIA There is no media in the device.\r
- @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.\r
- @retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.\r
- @retval EFI_TIMEOUT A timeout occurred while waiting for the security\r
- protocol command to execute.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-SecuritySendData (\r
- IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,\r
- IN UINT32 MediaId,\r
- IN UINT64 Timeout,\r
- IN UINT8 SecurityProtocolId,\r
- IN UINT16 SecurityProtocolSpecificData,\r
- IN UINTN PayloadBufferSize,\r
- IN VOID *PayloadBuffer\r
- )\r
-{\r
- OPAL_SMM_DEVICE *SmmDev;\r
-\r
- SmmDev = OPAL_SMM_DEVICE_FROM_THIS (This);\r
- if (SmmDev == NULL) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- return PerformTrustedIo (\r
- SmmDev,\r
- OpalSend,\r
- SecurityProtocolId,\r
- SecurityProtocolSpecificData,\r
- PayloadBufferSize,\r
- PayloadBuffer\r
- );\r
-\r
-}\r
-\r