blob: 1c3bfffb8689f368b2256d56efda706ea0a88a24 [file] [log] [blame]
/** @file
Implementation of Opal password support library.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "OpalPasswordSupportNotify.h"
LIST_ENTRY mDeviceList = INITIALIZE_LIST_HEAD_VARIABLE (mDeviceList);
BOOLEAN gInSmm = FALSE;
EFI_GUID gOpalPasswordNotifyProtocolGuid = OPAL_PASSWORD_NOTIFY_PROTOCOL_GUID;
/**
The function performs determines the available actions for the OPAL_DISK provided.
@param[in] SupportedAttributes The support attribute for the device.
@param[in] LockingFeature The locking status for the device.
@param[in] OwnerShip The ownership for the device.
@param[out] AvalDiskActions Pointer to fill-out with appropriate disk actions.
**/
TCG_RESULT
EFIAPI
OpalSupportGetAvailableActions(
IN OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,
IN TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature,
IN UINT16 OwnerShip,
OUT OPAL_DISK_ACTIONS *AvalDiskActions
)
{
BOOLEAN ExistingPassword;
NULL_CHECK(AvalDiskActions);
AvalDiskActions->AdminPass = 1;
AvalDiskActions->UserPass = 0;
AvalDiskActions->DisableUser = 0;
AvalDiskActions->Unlock = 0;
//
// Revert is performed on locking sp, so only allow if locking sp is enabled
//
if (LockingFeature->LockingEnabled) {
AvalDiskActions->Revert = 1;
}
//
// Psid revert is available for any device with media encryption support
// Revert is allowed for any device with media encryption support, however it requires
//
if (SupportedAttributes->MediaEncryption) {
//
// Only allow psid revert if media encryption is enabled.
// Otherwise, someone who steals a disk can psid revert the disk and the user Data is still
// intact and accessible
//
AvalDiskActions->PsidRevert = 1;
AvalDiskActions->RevertKeepDataForced = 0;
//
// Secure erase is performed by generating a new encryption key
// this is only available is encryption is supported
//
AvalDiskActions->SecureErase = 1;
} else {
AvalDiskActions->PsidRevert = 0;
AvalDiskActions->SecureErase = 0;
//
// If no media encryption is supported, then a revert (using password) will not
// erase the Data (since you can't generate a new encryption key)
//
AvalDiskActions->RevertKeepDataForced = 1;
}
if (LockingFeature->Locked) {
AvalDiskActions->Unlock = 1;
} else {
AvalDiskActions->Unlock = 0;
}
//
// Only allow user to set password if an admin password exists
//
ExistingPassword = OpalUtilAdminPasswordExists(OwnerShip, LockingFeature);
AvalDiskActions->UserPass = ExistingPassword;
//
// This will still show up even if there isn't a user, which is fine
//
AvalDiskActions->DisableUser = ExistingPassword;
return TcgResultSuccess;
}
/**
Creates a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts device using Admin SP Revert method.
@param[in] Session The opal session for the opal device.
@param[in] Psid PSID of device to revert.
@param[in] PsidLength Length of PSID in bytes.
@param[in] DevicePath The device path for the opal devcie.
**/
TCG_RESULT
EFIAPI
OpalSupportPsidRevert(
IN OPAL_SESSION *Session,
IN VOID *Psid,
IN UINT32 PsidLength,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
TCG_RESULT Ret;
NULL_CHECK(Session);
NULL_CHECK(Psid);
Ret = OpalUtilPsidRevert (Session, Psid, PsidLength);
if (Ret == TcgResultSuccess && !gInSmm) {
OpalSupportSendPasword (DevicePath, 0, NULL);
}
return Ret;
}
/**
Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_SID_AUTHORITY,
sets OPAL_UID_ADMIN_SP_C_PIN_SID with the new password,
and sets OPAL_LOCKING_SP_C_PIN_ADMIN1 with the new password.
@param[in] Session The opal session for the opal device.
@param[in] OldPassword Current admin password
@param[in] OldPasswordLength Length of current admin password in bytes
@param[in] NewPassword New admin password to set
@param[in] NewPasswordLength Length of new password in bytes
@param[in] DevicePath The device path for the opal devcie.
@param[in] SetAdmin Whether set admin password or user password.
TRUE for admin, FALSE for user.
**/
TCG_RESULT
EFIAPI
OpalSupportSetPassword(
IN OPAL_SESSION *Session,
IN VOID *OldPassword,
IN UINT32 OldPasswordLength,
IN VOID *NewPassword,
IN UINT32 NewPasswordLength,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN BOOLEAN SetAdmin
)
{
TCG_RESULT Ret;
NULL_CHECK(Session);
NULL_CHECK(OldPassword);
NULL_CHECK(NewPassword);
if (SetAdmin) {
Ret = OpalUtilSetAdminPassword(Session, OldPassword, OldPasswordLength, NewPassword, NewPasswordLength);
} else {
Ret = OpalUtilSetUserPassword(Session, OldPassword, OldPasswordLength, NewPassword, NewPasswordLength);
}
if (Ret == TcgResultSuccess && !gInSmm) {
OpalSupportSendPasword (DevicePath, NewPasswordLength, NewPassword);
}
return Ret;
}
/**
Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_ADMIN1_AUTHORITY and disables the User1 authority.
@param[in] Session The opal session for the opal device.
@param[in] Password Admin password
@param[in] PasswordLength Length of password in bytes
@param[out] PasswordFailed Indicates if password failed (start session didn't work)
@param[in] DevicePath The device path for the opal devcie.
**/
TCG_RESULT
EFIAPI
OpalSupportDisableUser(
IN OPAL_SESSION *Session,
IN VOID *Password,
IN UINT32 PasswordLength,
OUT BOOLEAN *PasswordFailed,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
TCG_RESULT Ret;
NULL_CHECK(Session);
NULL_CHECK(Password);
NULL_CHECK(PasswordFailed);
Ret = OpalUtilDisableUser(Session, Password, PasswordLength, PasswordFailed);
if (Ret == TcgResultSuccess && !gInSmm) {
OpalSupportSendPasword (DevicePath, PasswordLength, Password);
}
return Ret;
}
/**
Enable Opal Feature for the input device.
@param[in] Session The opal session for the opal device.
@param[in] Msid Msid
@param[in] MsidLength Msid Length
@param[in] Password Admin password
@param[in] PassLength Length of password in bytes
@param[in] DevicePath The device path for the opal devcie.
**/
TCG_RESULT
EFIAPI
OpalSupportEnableOpalFeature (
IN OPAL_SESSION *Session,
IN VOID *Msid,
IN UINT32 MsidLength,
IN VOID *Password,
IN UINT32 PassLength,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
TCG_RESULT Ret;
NULL_CHECK(Session);
NULL_CHECK(Msid);
NULL_CHECK(Password);
Ret = OpalUtilSetAdminPasswordAsSid(
Session,
Msid,
MsidLength,
Password,
PassLength
);
if (Ret == TcgResultSuccess) {
//
// Enable global locking range
//
Ret = OpalUtilSetOpalLockingRange(
Session,
Password,
PassLength,
OPAL_LOCKING_SP_LOCKING_GLOBALRANGE,
0,
0,
TRUE,
TRUE,
FALSE,
FALSE
);
}
if (Ret == TcgResultSuccess && !gInSmm) {
OpalSupportSendPasword (DevicePath, PassLength, Password);
}
return Ret;
}
/**
Opens a session with OPAL_UID_ADMIN_SP as OPAL_ADMIN_SP_PSID_AUTHORITY, then reverts the device using the RevertSP method.
@param[in] Session The opal session for the opal device.
@param[in] KeepUserData TRUE to keep existing Data on the disk, or FALSE to erase it
@param[in] Password Admin password
@param[in] PasswordLength Length of password in bytes
@param[in] Msid Msid
@param[in] MsidLength Msid Length
@param[out] PasswordFailed indicates if password failed (start session didn't work)
@param[in] DevicePath The device path for the opal devcie.
**/
TCG_RESULT
EFIAPI
OpalSupportRevert(
IN OPAL_SESSION *Session,
IN BOOLEAN KeepUserData,
IN VOID *Password,
IN UINT32 PasswordLength,
IN VOID *Msid,
IN UINT32 MsidLength,
OUT BOOLEAN *PasswordFailed,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
TCG_RESULT Ret;
NULL_CHECK(Session);
NULL_CHECK(Password);
NULL_CHECK(Msid);
NULL_CHECK(PasswordFailed);
Ret = OpalUtilRevert(Session, KeepUserData, Password, PasswordLength, PasswordFailed, Msid, MsidLength);
if (Ret == TcgResultSuccess && !gInSmm) {
OpalSupportSendPasword (DevicePath, 0, NULL);
}
return Ret;
}
/**
Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY
and updates the global locking range ReadLocked and WriteLocked columns to FALSE.
@param[in] Session The opal session for the opal device.
@param[in] Password Admin or user password
@param[in] PasswordLength Length of password in bytes
@param[in] DevicePath The device path for the opal devcie.
**/
TCG_RESULT
EFIAPI
OpalSupportUnlock(
IN OPAL_SESSION *Session,
IN VOID *Password,
IN UINT32 PasswordLength,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
TCG_RESULT Ret;
NULL_CHECK(Session);
NULL_CHECK(Password);
Ret = OpalUtilUpdateGlobalLockingRange(Session, Password, PasswordLength, FALSE, FALSE);
if (Ret == TcgResultSuccess && !gInSmm) {
OpalSupportSendPasword (DevicePath, PasswordLength, Password);
}
return Ret;
}
/**
Starts a session with OPAL_UID_LOCKING_SP as OPAL_LOCKING_SP_USER1_AUTHORITY or OPAL_LOCKING_SP_ADMIN1_AUTHORITY
and updates the global locking range ReadLocked and WriteLocked columns to TRUE.
@param[in] Session The opal session for the opal device.
@param[in] Password Admin or user password
@param[in] PasswordLength Length of password in bytes
@param[in] DevicePath The device path for the opal devcie.
**/
TCG_RESULT
EFIAPI
OpalSupportLock(
IN OPAL_SESSION *Session,
IN VOID *Password,
IN UINT32 PasswordLength,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
)
{
TCG_RESULT Ret;
NULL_CHECK(Session);
NULL_CHECK(Password);
Ret = OpalUtilUpdateGlobalLockingRange(Session, Password, PasswordLength, TRUE, TRUE);
if (Ret == TcgResultSuccess && !gInSmm) {
OpalSupportSendPasword (DevicePath, PasswordLength, Password);
}
return Ret;
}
/**
Initialize the communicate Buffer using DataSize and Function.
@param[out] DataPtr Points to the Data in the communicate Buffer.
@param[in] DataSize The Data Size to send to SMM.
@param[in] Function The function number to initialize the communicate Header.
@retval EFI_INVALID_PARAMETER The Data Size is too big.
@retval EFI_SUCCESS Find the specified variable.
**/
VOID*
OpalInitCommunicateBuffer (
OUT VOID **DataPtr OPTIONAL,
IN UINTN DataSize,
IN UINTN Function
)
{
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
OPAL_SMM_COMMUNICATE_HEADER *SmmFunctionHeader;
VOID *Buffer;
EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *SmmCommRegionTable;
EFI_MEMORY_DESCRIPTOR *SmmCommMemRegion;
UINTN Index;
UINTN Size;
EFI_STATUS Status;
Buffer = NULL;
Status = EfiGetSystemConfigurationTable (
&gEdkiiPiSmmCommunicationRegionTableGuid,
(VOID **) &SmmCommRegionTable
);
if (EFI_ERROR (Status)) {
return NULL;
}
ASSERT (SmmCommRegionTable != NULL);
SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *) (SmmCommRegionTable + 1);
Size = 0;
for (Index = 0; Index < SmmCommRegionTable->NumberOfEntries; Index++) {
if (SmmCommMemRegion->Type == EfiConventionalMemory) {
Size = EFI_PAGES_TO_SIZE ((UINTN) SmmCommMemRegion->NumberOfPages);
if (Size >= (DataSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data))) {
break;
}
}
SmmCommMemRegion = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) SmmCommMemRegion + SmmCommRegionTable->DescriptorSize);
}
ASSERT (Index < SmmCommRegionTable->NumberOfEntries);
Buffer = (VOID*)(UINTN)SmmCommMemRegion->PhysicalStart;
ASSERT (Buffer != NULL);
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) Buffer;
CopyGuid (&SmmCommunicateHeader->HeaderGuid, &gOpalPasswordNotifyProtocolGuid);
SmmCommunicateHeader->MessageLength = DataSize + OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data);
SmmFunctionHeader = (OPAL_SMM_COMMUNICATE_HEADER *) SmmCommunicateHeader->Data;
SmmFunctionHeader->Function = Function;
if (DataPtr != NULL) {
*DataPtr = SmmFunctionHeader->Data;
}
return Buffer;
}
/**
Send the Data in communicate Buffer to SMM.
@param[in] Buffer Points to the Data in the communicate Buffer.
@param[in] DataSize This Size of the function Header and the Data.
@retval EFI_SUCCESS Success is returned from the functin in SMM.
@retval Others Failure is returned from the function in SMM.
**/
EFI_STATUS
OpalSendCommunicateBuffer (
IN VOID *Buffer,
IN UINTN DataSize
)
{
EFI_STATUS Status;
UINTN CommSize;
EFI_SMM_COMMUNICATE_HEADER *SmmCommunicateHeader;
OPAL_SMM_COMMUNICATE_HEADER *SmmFunctionHeader;
EFI_SMM_COMMUNICATION_PROTOCOL *SmmCommunication;
Status = gBS->LocateProtocol (&gEfiSmmCommunicationProtocolGuid, NULL, (VOID **) &SmmCommunication);
if (EFI_ERROR (Status)) {
return Status;
}
CommSize = DataSize + OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, Data) + OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data);
Status = SmmCommunication->Communicate (SmmCommunication, Buffer, &CommSize);
if (EFI_ERROR (Status)) {
return Status;
}
SmmCommunicateHeader = (EFI_SMM_COMMUNICATE_HEADER *) Buffer;
SmmFunctionHeader = (OPAL_SMM_COMMUNICATE_HEADER *)SmmCommunicateHeader->Data;
return SmmFunctionHeader->ReturnStatus;
}
/**
Transfer the password to the smm driver.
@param[in] DevicePath The device path for the opal devcie.
@param PasswordLen The input password length.
@param Password Input password buffer.
@retval EFI_SUCCESS Do the required action success.
@retval Others Error occured.
**/
EFI_STATUS
EFIAPI
OpalSupportSendPasword(
EFI_DEVICE_PATH_PROTOCOL *DevicePath,
UINTN PasswordLen,
VOID *Password
)
{
OPAL_COMM_DEVICE_LIST *Parameter;
VOID *Buffer;
UINTN Length;
EFI_STATUS Status;
UINTN DevicePathLen;
Parameter = NULL;
Buffer = NULL;
if (DevicePath == NULL) {
//
// Assume DevicePath == NULL only when library used by SMM driver
// and should not run to here, just return success.
//
return EFI_SUCCESS;
}
DevicePathLen = GetDevicePathSize (DevicePath);
Length = OFFSET_OF (OPAL_COMM_DEVICE_LIST, OpalDevicePath) + DevicePathLen;
Buffer = OpalInitCommunicateBuffer((VOID**)&Parameter, Length, SMM_FUNCTION_SET_OPAL_PASSWORD);
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (Password != NULL) {
CopyMem((VOID*)Parameter->Password, Password, PasswordLen);
Parameter->PasswordLength = (UINT8)PasswordLen;
}
CopyMem (&Parameter->OpalDevicePath, DevicePath, DevicePathLen);
Status = OpalSendCommunicateBuffer(Buffer, Length);
if (EFI_ERROR(Status)) {
goto EXIT;
}
EXIT:
ZeroMem(Parameter, Length);
return Status;
}
/**
Get saved Opal device list.
@retval return opal device list.
**/
LIST_ENTRY*
EFIAPI
OpalSupportGetOpalDeviceList (
VOID
)
{
return &mDeviceList;
}
/**
Check if the password is full zero.
@param[in] Password Points to the Data Buffer
@retval TRUE This password string is full zero.
@retval FALSE This password string is not full zero.
**/
BOOLEAN
OpalPasswordIsFullZero (
IN UINT8 *Password
)
{
UINTN Index;
for (Index = 0; Index < OPAL_PASSWORD_MAX_LENGTH; Index++) {
if (Password[Index] != 0) {
return FALSE;
}
}
return TRUE;
}
/**
Save hdd password to SMM.
@param[in] DevicePath Input device path info for the device.
@param[in] Password The hdd password of attached ATA device.
@param[in] PasswordLength The hdd password length.
@retval EFI_OUT_OF_RESOURCES Insufficient resources to create database record
@retval EFI_SUCCESS The function has been successfully executed.
**/
EFI_STATUS
OpalSavePasswordToSmm (
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
IN UINT8 *Password,
IN UINT8 PasswordLength
)
{
OPAL_DISK_AND_PASSWORD_INFO *List;
OPAL_DISK_AND_PASSWORD_INFO *Dev;
LIST_ENTRY *Entry;
UINTN DevicePathLen;
DevicePathLen = GetDevicePathSize (DevicePath);
for (Entry = mDeviceList.ForwardLink; Entry != &mDeviceList; Entry = Entry->ForwardLink) {
List = BASE_CR (Entry, OPAL_DISK_AND_PASSWORD_INFO, Link);
if (CompareMem (&List->OpalDevicePath, DevicePath, DevicePathLen) == 0) {
CopyMem(List->Password, Password, OPAL_PASSWORD_MAX_LENGTH);
return EFI_SUCCESS;
}
}
Dev = AllocateZeroPool (OFFSET_OF (OPAL_DISK_AND_PASSWORD_INFO, OpalDevicePath) + DevicePathLen);
if (Dev == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Dev->PasswordLength = PasswordLength;
CopyMem(&(Dev->Password), Password, OPAL_PASSWORD_MAX_LENGTH);
CopyMem(&(Dev->OpalDevicePath), DevicePath, DevicePathLen);
InsertHeadList (&mDeviceList, &Dev->Link);
return EFI_SUCCESS;
}
/**
Communication service SMI Handler entry.
This SMI handler provides services for saving HDD password and saving S3 boot script when ready to boot.
@param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
@param[in] RegisterContext Points to an optional handler context which was specified when the
handler was registered.
@param[in, out] CommBuffer A pointer to a collection of Data in memory that will
be conveyed from a non-SMM environment into an SMM environment.
@param[in, out] CommBufferSize The Size of the CommBuffer.
@retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
should still be called.
@retval EFI_WARN_INTERRUPT_SOURCE_QUIESCED The interrupt has been quiesced but other handlers should
still be called.
@retval EFI_WARN_INTERRUPT_SOURCE_PENDING The interrupt is still pending and other handlers should still
be called.
@retval EFI_INTERRUPT_PENDING The interrupt could not be quiesced.
**/
EFI_STATUS
EFIAPI
SmmOpalPasswordHandler (
IN EFI_HANDLE DispatchHandle,
IN CONST VOID *RegisterContext,
IN OUT VOID *CommBuffer,
IN OUT UINTN *CommBufferSize
)
{
EFI_STATUS Status;
OPAL_SMM_COMMUNICATE_HEADER *SmmFunctionHeader;
UINTN TempCommBufferSize;
UINTN RemainedDevicePathSize;
OPAL_COMM_DEVICE_LIST *DeviceBuffer;
if (CommBuffer == NULL || CommBufferSize == NULL) {
return EFI_SUCCESS;
}
Status = EFI_SUCCESS;
DeviceBuffer = NULL;
TempCommBufferSize = *CommBufferSize;
if (TempCommBufferSize < OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data)) {
return EFI_SUCCESS;
}
SmmFunctionHeader = (OPAL_SMM_COMMUNICATE_HEADER *)CommBuffer;
switch (SmmFunctionHeader->Function) {
case SMM_FUNCTION_SET_OPAL_PASSWORD:
if (TempCommBufferSize <= OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data) + OFFSET_OF (OPAL_COMM_DEVICE_LIST, OpalDevicePath)) {
return EFI_SUCCESS;
}
DeviceBuffer = AllocateCopyPool (TempCommBufferSize - OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data), SmmFunctionHeader->Data);
if (DeviceBuffer == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto EXIT;
}
//
// Validate the DevicePath.
//
RemainedDevicePathSize = TempCommBufferSize - OFFSET_OF (OPAL_SMM_COMMUNICATE_HEADER, Data)
- OFFSET_OF (OPAL_COMM_DEVICE_LIST, OpalDevicePath);
if (!IsDevicePathValid(&DeviceBuffer->OpalDevicePath, RemainedDevicePathSize) ||
(RemainedDevicePathSize != GetDevicePathSize (&DeviceBuffer->OpalDevicePath))) {
Status = EFI_SUCCESS;
goto EXIT;
}
if (OpalPasswordIsFullZero (DeviceBuffer->Password) ||
DeviceBuffer->PasswordLength == 0 ||
DeviceBuffer->PasswordLength > OPAL_PASSWORD_MAX_LENGTH) {
Status = EFI_INVALID_PARAMETER;
goto EXIT;
}
//
// The AsmLfence() call here is to ensure the above range checks for the
// CommBuffer have been completed before calling into OpalSavePasswordToSmm().
//
AsmLfence ();
Status = OpalSavePasswordToSmm (&DeviceBuffer->OpalDevicePath, DeviceBuffer->Password, DeviceBuffer->PasswordLength);
break;
default:
Status = EFI_UNSUPPORTED;
break;
}
EXIT:
SmmFunctionHeader->ReturnStatus = Status;
if (DeviceBuffer != NULL) {
FreePool (DeviceBuffer);
}
//
// Return EFI_SUCCESS cause only one handler can be trigged.
// so return EFI_WARN_INTERRUPT_SOURCE_PENDING to make all handler can be trigged.
//
return EFI_WARN_INTERRUPT_SOURCE_PENDING;
}
/**
The constructor function.
Register SMI handler when link to SMM driver.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
**/
EFI_STATUS
EFIAPI
OpalPasswordSupportLibConstructor (
VOID
)
{
EFI_SMM_BASE2_PROTOCOL *SmmBase2;
EFI_SMM_SYSTEM_TABLE2 *Smst;
EFI_HANDLE SmmHandle;
EFI_STATUS Status;
Status = gBS->LocateProtocol (&gEfiSmmBase2ProtocolGuid, NULL, (VOID**) &SmmBase2);
if (EFI_ERROR (Status)) {
return RETURN_SUCCESS;
}
Status = SmmBase2->InSmm (SmmBase2, &gInSmm);
if (EFI_ERROR (Status)) {
return RETURN_SUCCESS;
}
if (!gInSmm) {
return RETURN_SUCCESS;
}
//
// Good, we are in SMM
//
Status = SmmBase2->GetSmstLocation (SmmBase2, &Smst);
if (EFI_ERROR (Status)) {
return RETURN_SUCCESS;
}
SmmHandle = NULL;
Status = Smst->SmiHandlerRegister (SmmOpalPasswordHandler, &gOpalPasswordNotifyProtocolGuid, &SmmHandle);
ASSERT_EFI_ERROR (Status);
return EFI_SUCCESS;
}
/**
The Destructor function.
Clean the saved opal device list.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
**/
EFI_STATUS
EFIAPI
OpalPasswordSupportLibDestructor (
VOID
)
{
OPAL_DISK_AND_PASSWORD_INFO *Device;
while (!IsListEmpty (&mDeviceList)) {
Device = BASE_CR (mDeviceList.ForwardLink, OPAL_DISK_AND_PASSWORD_INFO, Link);
RemoveEntryList (&Device->Link);
FreePool (Device);
}
return EFI_SUCCESS;
}