mirror of https://github.com/acidanthera/audk.git
2967 lines
82 KiB
C
2967 lines
82 KiB
C
/** @file
|
|
Entrypoint of Opal UEFI Driver and contains all the logic to
|
|
register for new Opal device instances.
|
|
|
|
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
// This UEFI driver consumes EFI_STORAGE_SECURITY_PROTOCOL instances and installs an
|
|
// HII GUI to manage Opal features if the device is Opal capable
|
|
// If the Opal device is being managed by the UEFI Driver, it shall provide a popup
|
|
// window during boot requesting a user password
|
|
|
|
#include "OpalDriver.h"
|
|
#include "OpalHii.h"
|
|
|
|
EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;
|
|
|
|
BOOLEAN mOpalEndOfDxe = FALSE;
|
|
OPAL_REQUEST_VARIABLE *mOpalRequestVariable = NULL;
|
|
UINTN mOpalRequestVariableSize = 0;
|
|
CHAR16 mPopUpString[100];
|
|
|
|
OPAL_DRIVER mOpalDriver;
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {
|
|
OpalEfiDriverBindingSupported,
|
|
OpalEfiDriverBindingStart,
|
|
OpalEfiDriverBindingStop,
|
|
0x1b,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
/**
|
|
|
|
The function determines the available actions for the OPAL_DISK provided.
|
|
|
|
@param[in] SupportedAttributes The supported attributes 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 or pyrite 2.0 type support.
|
|
//
|
|
if (SupportedAttributes->PyriteSscV2 || SupportedAttributes->MediaEncryption) {
|
|
|
|
//
|
|
// Only allow psid revert if media encryption is enabled or pyrite 2.0 type support..
|
|
// 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 if 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;
|
|
}
|
|
|
|
/**
|
|
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
|
|
|
|
**/
|
|
TCG_RESULT
|
|
EFIAPI
|
|
OpalSupportEnableOpalFeature (
|
|
IN OPAL_SESSION *Session,
|
|
IN VOID *Msid,
|
|
IN UINT32 MsidLength,
|
|
IN VOID *Password,
|
|
IN UINT32 PassLength
|
|
)
|
|
{
|
|
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
|
|
);
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/**
|
|
Update password for the Opal disk.
|
|
|
|
@param[in, out] OpalDisk The disk to update password.
|
|
@param[in] Password The input password.
|
|
@param[in] PasswordLength The input password length.
|
|
|
|
**/
|
|
VOID
|
|
OpalSupportUpdatePassword (
|
|
IN OUT OPAL_DISK *OpalDisk,
|
|
IN VOID *Password,
|
|
IN UINT32 PasswordLength
|
|
)
|
|
{
|
|
CopyMem (OpalDisk->Password, Password, PasswordLength);
|
|
OpalDisk->PasswordLength = (UINT8) PasswordLength;
|
|
}
|
|
|
|
/**
|
|
Extract device info from the device path.
|
|
|
|
@param[in] DevicePath Device path info for the device.
|
|
@param[out] DevInfoLength Device information length needed.
|
|
@param[out] DevInfo Device information extracted.
|
|
|
|
**/
|
|
VOID
|
|
ExtractDeviceInfoFromDevicePath (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
|
OUT UINT32 *DevInfoLength,
|
|
OUT OPAL_DEVICE_LOCKBOX_DATA *DevInfo OPTIONAL
|
|
)
|
|
{
|
|
EFI_DEVICE_PATH_PROTOCOL *TmpDevPath;
|
|
EFI_DEVICE_PATH_PROTOCOL *TmpDevPath2;
|
|
PCI_DEVICE_PATH *PciDevPath;
|
|
UINT8 DeviceType;
|
|
UINT8 BusNum;
|
|
OPAL_PCI_DEVICE *PciDevice;
|
|
|
|
ASSERT (DevicePath != NULL);
|
|
ASSERT (DevInfoLength != NULL);
|
|
|
|
DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;
|
|
*DevInfoLength = 0;
|
|
|
|
TmpDevPath = DevicePath;
|
|
|
|
//
|
|
// Get device type.
|
|
//
|
|
while (!IsDevicePathEnd (TmpDevPath)) {
|
|
if ((TmpDevPath->Type == MESSAGING_DEVICE_PATH) &&
|
|
(TmpDevPath->SubType == MSG_SATA_DP || TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP)) {
|
|
if (DevInfo != NULL) {
|
|
DevInfo->DevicePathLength = (UINT32) GetDevicePathSize (DevicePath);
|
|
CopyMem (DevInfo->DevicePath, DevicePath, DevInfo->DevicePathLength);
|
|
}
|
|
|
|
DeviceType = (TmpDevPath->SubType == MSG_SATA_DP) ? OPAL_DEVICE_TYPE_ATA : OPAL_DEVICE_TYPE_NVME;
|
|
*DevInfoLength = sizeof (OPAL_DEVICE_LOCKBOX_DATA) + (UINT32) GetDevicePathSize (DevicePath);
|
|
break;
|
|
}
|
|
TmpDevPath = NextDevicePathNode (TmpDevPath);
|
|
}
|
|
|
|
//
|
|
// Get device info.
|
|
//
|
|
BusNum = 0;
|
|
TmpDevPath = DevicePath;
|
|
TmpDevPath2 = NextDevicePathNode (DevicePath);
|
|
while (!IsDevicePathEnd (TmpDevPath2)) {
|
|
if (TmpDevPath->Type == HARDWARE_DEVICE_PATH && TmpDevPath->SubType == HW_PCI_DP) {
|
|
PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;
|
|
if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH) &&
|
|
(TmpDevPath2->SubType == MSG_SATA_DP || TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)) {
|
|
if (DevInfo != NULL) {
|
|
PciDevice = &DevInfo->Device;
|
|
PciDevice->Segment = 0;
|
|
PciDevice->Bus = BusNum;
|
|
PciDevice->Device = PciDevPath->Device;
|
|
PciDevice->Function = PciDevPath->Function;
|
|
}
|
|
} else {
|
|
if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH && TmpDevPath2->SubType == HW_PCI_DP) {
|
|
BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum, PciDevPath->Device, PciDevPath->Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
|
|
}
|
|
}
|
|
}
|
|
|
|
TmpDevPath = NextDevicePathNode (TmpDevPath);
|
|
TmpDevPath2 = NextDevicePathNode (TmpDevPath2);
|
|
}
|
|
|
|
ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);
|
|
return;
|
|
}
|
|
|
|
/**
|
|
Build OPAL device info and save them to LockBox.
|
|
|
|
**/
|
|
VOID
|
|
BuildOpalDeviceInfo (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
OPAL_DEVICE_LOCKBOX_DATA *DevInfo;
|
|
OPAL_DEVICE_LOCKBOX_DATA *TempDevInfo;
|
|
UINTN TotalDevInfoLength;
|
|
UINT32 DevInfoLength;
|
|
OPAL_DRIVER_DEVICE *TmpDev;
|
|
UINT8 DummyData;
|
|
BOOLEAN S3InitDevicesExist;
|
|
UINTN S3InitDevicesLength;
|
|
EFI_DEVICE_PATH_PROTOCOL *S3InitDevices;
|
|
EFI_DEVICE_PATH_PROTOCOL *S3InitDevicesBak;
|
|
|
|
//
|
|
// Build OPAL device info and save them to LockBox.
|
|
//
|
|
TotalDevInfoLength = 0;
|
|
TmpDev = mOpalDriver.DeviceList;
|
|
while (TmpDev != NULL) {
|
|
ExtractDeviceInfoFromDevicePath (
|
|
TmpDev->OpalDisk.OpalDevicePath,
|
|
&DevInfoLength,
|
|
NULL
|
|
);
|
|
TotalDevInfoLength += DevInfoLength;
|
|
TmpDev = TmpDev->Next;
|
|
}
|
|
|
|
if (TotalDevInfoLength == 0) {
|
|
return;
|
|
}
|
|
|
|
S3InitDevicesLength = sizeof (DummyData);
|
|
Status = RestoreLockBox (
|
|
&gS3StorageDeviceInitListGuid,
|
|
&DummyData,
|
|
&S3InitDevicesLength
|
|
);
|
|
ASSERT ((Status == EFI_NOT_FOUND) || (Status == EFI_BUFFER_TOO_SMALL));
|
|
if (Status == EFI_NOT_FOUND) {
|
|
S3InitDevices = NULL;
|
|
S3InitDevicesExist = FALSE;
|
|
} else if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
S3InitDevices = AllocatePool (S3InitDevicesLength);
|
|
ASSERT (S3InitDevices != NULL);
|
|
if (S3InitDevices == NULL) {
|
|
return;
|
|
}
|
|
|
|
Status = RestoreLockBox (
|
|
&gS3StorageDeviceInitListGuid,
|
|
S3InitDevices,
|
|
&S3InitDevicesLength
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
S3InitDevicesExist = TRUE;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
DevInfo = AllocateZeroPool (TotalDevInfoLength);
|
|
ASSERT (DevInfo != NULL);
|
|
if (DevInfo == NULL) {
|
|
return;
|
|
}
|
|
|
|
TempDevInfo = DevInfo;
|
|
TmpDev = mOpalDriver.DeviceList;
|
|
while (TmpDev != NULL) {
|
|
ExtractDeviceInfoFromDevicePath (
|
|
TmpDev->OpalDisk.OpalDevicePath,
|
|
&DevInfoLength,
|
|
TempDevInfo
|
|
);
|
|
TempDevInfo->Length = DevInfoLength;
|
|
TempDevInfo->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;
|
|
CopyMem (
|
|
TempDevInfo->Password,
|
|
TmpDev->OpalDisk.Password,
|
|
TmpDev->OpalDisk.PasswordLength
|
|
);
|
|
TempDevInfo->PasswordLength = TmpDev->OpalDisk.PasswordLength;
|
|
|
|
S3InitDevicesBak = S3InitDevices;
|
|
S3InitDevices = AppendDevicePathInstance (
|
|
S3InitDevicesBak,
|
|
TmpDev->OpalDisk.OpalDevicePath
|
|
);
|
|
if (S3InitDevicesBak != NULL) {
|
|
FreePool (S3InitDevicesBak);
|
|
}
|
|
ASSERT (S3InitDevices != NULL);
|
|
if (S3InitDevices == NULL) {
|
|
return;
|
|
}
|
|
|
|
TempDevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) ((UINTN) TempDevInfo + DevInfoLength);
|
|
TmpDev = TmpDev->Next;
|
|
}
|
|
|
|
Status = SaveLockBox (
|
|
&mOpalDeviceLockBoxGuid,
|
|
DevInfo,
|
|
TotalDevInfoLength
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = SetLockBoxAttributes (
|
|
&mOpalDeviceLockBoxGuid,
|
|
LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
S3InitDevicesLength = GetDevicePathSize (S3InitDevices);
|
|
if (S3InitDevicesExist) {
|
|
Status = UpdateLockBox (
|
|
&gS3StorageDeviceInitListGuid,
|
|
0,
|
|
S3InitDevices,
|
|
S3InitDevicesLength
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
} else {
|
|
Status = SaveLockBox (
|
|
&gS3StorageDeviceInitListGuid,
|
|
S3InitDevices,
|
|
S3InitDevicesLength
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = SetLockBoxAttributes (
|
|
&gS3StorageDeviceInitListGuid,
|
|
LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
ZeroMem (DevInfo, TotalDevInfoLength);
|
|
FreePool (DevInfo);
|
|
FreePool (S3InitDevices);
|
|
}
|
|
|
|
/**
|
|
|
|
Send BlockSid command if needed.
|
|
|
|
**/
|
|
VOID
|
|
SendBlockSidCommand (
|
|
VOID
|
|
)
|
|
{
|
|
OPAL_DRIVER_DEVICE *Itr;
|
|
TCG_RESULT Result;
|
|
OPAL_SESSION Session;
|
|
UINT32 PpStorageFlag;
|
|
|
|
PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
|
|
if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
|
|
//
|
|
// Send BlockSID command to each Opal disk
|
|
//
|
|
Itr = mOpalDriver.DeviceList;
|
|
while (Itr != NULL) {
|
|
if (Itr->OpalDisk.SupportedAttributes.BlockSid) {
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Itr->OpalDisk.Sscp;
|
|
Session.MediaId = Itr->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;
|
|
|
|
DEBUG ((DEBUG_INFO, "OpalPassword: EndOfDxe point, send BlockSid command to device!\n"));
|
|
Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE
|
|
if (Result != TcgResultSuccess) {
|
|
DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Record BlockSID command has been sent.
|
|
//
|
|
Itr->OpalDisk.SentBlockSID = TRUE;
|
|
}
|
|
|
|
Itr = Itr->Next;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
|
|
|
|
This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.
|
|
|
|
@param Event Event whose notification function is being invoked.
|
|
@param Context Pointer to the notification function's context.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
OpalEndOfDxeEventNotify (
|
|
EFI_EVENT Event,
|
|
VOID *Context
|
|
)
|
|
{
|
|
OPAL_DRIVER_DEVICE *TmpDev;
|
|
|
|
DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
|
|
|
|
mOpalEndOfDxe = TRUE;
|
|
|
|
if (mOpalRequestVariable != NULL) {
|
|
//
|
|
// Free the OPAL request variable buffer here
|
|
// as the OPAL requests should have been processed.
|
|
//
|
|
FreePool (mOpalRequestVariable);
|
|
mOpalRequestVariable = NULL;
|
|
mOpalRequestVariableSize = 0;
|
|
}
|
|
|
|
//
|
|
// If no any device, return directly.
|
|
//
|
|
if (mOpalDriver.DeviceList == NULL) {
|
|
gBS->CloseEvent (Event);
|
|
return;
|
|
}
|
|
|
|
BuildOpalDeviceInfo ();
|
|
|
|
//
|
|
// Zero passsword.
|
|
//
|
|
TmpDev = mOpalDriver.DeviceList;
|
|
while (TmpDev != NULL) {
|
|
ZeroMem (TmpDev->OpalDisk.Password, TmpDev->OpalDisk.PasswordLength);
|
|
TmpDev = TmpDev->Next;
|
|
}
|
|
|
|
//
|
|
// Send BlockSid command if needed.
|
|
//
|
|
SendBlockSidCommand ();
|
|
|
|
DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
|
|
|
|
gBS->CloseEvent (Event);
|
|
}
|
|
|
|
/**
|
|
Get Psid input from the popup window.
|
|
|
|
@param[in] Dev The device which need Psid to process Psid Revert
|
|
OPAL request.
|
|
@param[in] PopUpString Pop up string.
|
|
@param[in] PopUpString2 Pop up string in line 2.
|
|
@param[in] PopUpString3 Pop up string in line 3.
|
|
|
|
@param[out] PressEsc Whether user escape function through Press ESC.
|
|
|
|
@retval Psid string if success. NULL if failed.
|
|
|
|
**/
|
|
CHAR8 *
|
|
OpalDriverPopUpPsidInput (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *PopUpString,
|
|
IN CHAR16 *PopUpString2,
|
|
IN CHAR16 *PopUpString3,
|
|
OUT BOOLEAN *PressEsc
|
|
)
|
|
{
|
|
EFI_INPUT_KEY InputKey;
|
|
UINTN InputLength;
|
|
CHAR16 Mask[PSID_CHARACTER_LENGTH + 1];
|
|
CHAR16 Unicode[PSID_CHARACTER_LENGTH + 1];
|
|
CHAR8 *Ascii;
|
|
|
|
ZeroMem(Unicode, sizeof(Unicode));
|
|
ZeroMem(Mask, sizeof(Mask));
|
|
|
|
*PressEsc = FALSE;
|
|
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
|
|
InputLength = 0;
|
|
while (TRUE) {
|
|
Mask[InputLength] = L'_';
|
|
if (PopUpString2 == NULL) {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&InputKey,
|
|
PopUpString,
|
|
L"---------------------",
|
|
Mask,
|
|
NULL
|
|
);
|
|
} else {
|
|
if (PopUpString3 == NULL) {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&InputKey,
|
|
PopUpString,
|
|
PopUpString2,
|
|
L"---------------------",
|
|
Mask,
|
|
NULL
|
|
);
|
|
} else {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&InputKey,
|
|
PopUpString,
|
|
PopUpString2,
|
|
PopUpString3,
|
|
L"---------------------",
|
|
Mask,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check key.
|
|
//
|
|
if (InputKey.ScanCode == SCAN_NULL) {
|
|
//
|
|
// password finished
|
|
//
|
|
if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
//
|
|
// Add the null terminator.
|
|
//
|
|
Unicode[InputLength] = 0;
|
|
Mask[InputLength] = 0;
|
|
break;
|
|
} else if ((InputKey.UnicodeChar == CHAR_NULL) ||
|
|
(InputKey.UnicodeChar == CHAR_TAB) ||
|
|
(InputKey.UnicodeChar == CHAR_LINEFEED)
|
|
) {
|
|
continue;
|
|
} else {
|
|
//
|
|
// delete last key entered
|
|
//
|
|
if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
|
|
if (InputLength > 0) {
|
|
Unicode[InputLength] = 0;
|
|
Mask[InputLength] = 0;
|
|
InputLength--;
|
|
}
|
|
} else {
|
|
//
|
|
// add Next key entry
|
|
//
|
|
Unicode[InputLength] = InputKey.UnicodeChar;
|
|
Mask[InputLength] = InputKey.UnicodeChar;
|
|
InputLength++;
|
|
if (InputLength == PSID_CHARACTER_LENGTH) {
|
|
//
|
|
// Add the null terminator.
|
|
//
|
|
Unicode[InputLength] = 0;
|
|
Mask[InputLength] = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// exit on ESC
|
|
//
|
|
if (InputKey.ScanCode == SCAN_ESC) {
|
|
*PressEsc = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
|
|
if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
|
|
ZeroMem (Unicode, sizeof (Unicode));
|
|
ZeroMem (Mask, sizeof (Mask));
|
|
return NULL;
|
|
}
|
|
|
|
Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);
|
|
if (Ascii == NULL) {
|
|
ZeroMem (Unicode, sizeof (Unicode));
|
|
ZeroMem (Mask, sizeof (Mask));
|
|
return NULL;
|
|
}
|
|
|
|
UnicodeStrToAsciiStrS (Unicode, Ascii, PSID_CHARACTER_LENGTH + 1);
|
|
ZeroMem (Unicode, sizeof (Unicode));
|
|
ZeroMem (Mask, sizeof (Mask));
|
|
|
|
return Ascii;
|
|
}
|
|
|
|
|
|
/**
|
|
Get password input from the popup window.
|
|
|
|
@param[in] Dev The device which need password to unlock or
|
|
process OPAL request.
|
|
@param[in] PopUpString1 Pop up string 1.
|
|
@param[in] PopUpString2 Pop up string 2.
|
|
@param[in] PopUpString3 Pop up string 3.
|
|
@param[out] PressEsc Whether user escape function through Press ESC.
|
|
|
|
@retval Password string if success. NULL if failed.
|
|
|
|
**/
|
|
CHAR8 *
|
|
OpalDriverPopUpPasswordInput (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *PopUpString1,
|
|
IN CHAR16 *PopUpString2,
|
|
IN CHAR16 *PopUpString3,
|
|
OUT BOOLEAN *PressEsc
|
|
)
|
|
{
|
|
EFI_INPUT_KEY InputKey;
|
|
UINTN InputLength;
|
|
CHAR16 Mask[OPAL_MAX_PASSWORD_SIZE + 1];
|
|
CHAR16 Unicode[OPAL_MAX_PASSWORD_SIZE + 1];
|
|
CHAR8 *Ascii;
|
|
|
|
ZeroMem(Unicode, sizeof(Unicode));
|
|
ZeroMem(Mask, sizeof(Mask));
|
|
|
|
*PressEsc = FALSE;
|
|
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
|
|
InputLength = 0;
|
|
while (TRUE) {
|
|
Mask[InputLength] = L'_';
|
|
if (PopUpString2 == NULL) {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&InputKey,
|
|
PopUpString1,
|
|
L"---------------------",
|
|
Mask,
|
|
NULL
|
|
);
|
|
} else {
|
|
if (PopUpString3 == NULL) {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&InputKey,
|
|
PopUpString1,
|
|
PopUpString2,
|
|
L"---------------------",
|
|
Mask,
|
|
NULL
|
|
);
|
|
} else {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&InputKey,
|
|
PopUpString1,
|
|
PopUpString2,
|
|
PopUpString3,
|
|
L"---------------------",
|
|
Mask,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Check key.
|
|
//
|
|
if (InputKey.ScanCode == SCAN_NULL) {
|
|
//
|
|
// password finished
|
|
//
|
|
if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
//
|
|
// Add the null terminator.
|
|
//
|
|
Unicode[InputLength] = 0;
|
|
Mask[InputLength] = 0;
|
|
break;
|
|
} else if ((InputKey.UnicodeChar == CHAR_NULL) ||
|
|
(InputKey.UnicodeChar == CHAR_TAB) ||
|
|
(InputKey.UnicodeChar == CHAR_LINEFEED)
|
|
) {
|
|
continue;
|
|
} else {
|
|
//
|
|
// delete last key entered
|
|
//
|
|
if (InputKey.UnicodeChar == CHAR_BACKSPACE) {
|
|
if (InputLength > 0) {
|
|
Unicode[InputLength] = 0;
|
|
Mask[InputLength] = 0;
|
|
InputLength--;
|
|
}
|
|
} else {
|
|
//
|
|
// add Next key entry
|
|
//
|
|
Unicode[InputLength] = InputKey.UnicodeChar;
|
|
Mask[InputLength] = L'*';
|
|
InputLength++;
|
|
if (InputLength == OPAL_MAX_PASSWORD_SIZE) {
|
|
//
|
|
// Add the null terminator.
|
|
//
|
|
Unicode[InputLength] = 0;
|
|
Mask[InputLength] = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// exit on ESC
|
|
//
|
|
if (InputKey.ScanCode == SCAN_ESC) {
|
|
*PressEsc = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
|
|
if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {
|
|
ZeroMem (Unicode, sizeof (Unicode));
|
|
return NULL;
|
|
}
|
|
|
|
Ascii = AllocateZeroPool (OPAL_MAX_PASSWORD_SIZE + 1);
|
|
if (Ascii == NULL) {
|
|
ZeroMem (Unicode, sizeof (Unicode));
|
|
return NULL;
|
|
}
|
|
|
|
UnicodeStrToAsciiStrS (Unicode, Ascii, OPAL_MAX_PASSWORD_SIZE + 1);
|
|
ZeroMem (Unicode, sizeof (Unicode));
|
|
|
|
return Ascii;
|
|
}
|
|
|
|
/**
|
|
Get pop up string.
|
|
|
|
@param[in] Dev The OPAL device.
|
|
@param[in] RequestString Request string.
|
|
|
|
@return Pop up string.
|
|
|
|
**/
|
|
CHAR16 *
|
|
OpalGetPopUpString (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
if (Dev->Name16 == NULL) {
|
|
UnicodeSPrint (mPopUpString, sizeof (mPopUpString), L"%s Disk", RequestString);
|
|
} else {
|
|
UnicodeSPrint (mPopUpString, sizeof (mPopUpString), L"%s %s", RequestString, Dev->Name16);
|
|
}
|
|
|
|
return mPopUpString;
|
|
}
|
|
|
|
/**
|
|
Check if disk is locked, show popup window and ask for password if it is.
|
|
|
|
@param[in] Dev The device which need to be unlocked.
|
|
@param[in] RequestString Request string.
|
|
|
|
**/
|
|
VOID
|
|
OpalDriverRequestPassword (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
BOOLEAN IsEnabled;
|
|
BOOLEAN IsLocked;
|
|
CHAR8 *Password;
|
|
UINT32 PasswordLen;
|
|
OPAL_SESSION Session;
|
|
BOOLEAN PressEsc;
|
|
EFI_INPUT_KEY Key;
|
|
TCG_RESULT Ret;
|
|
CHAR16 *PopUpString;
|
|
|
|
if (Dev == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
|
|
|
|
PopUpString = OpalGetPopUpString (Dev, RequestString);
|
|
|
|
Count = 0;
|
|
|
|
IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);
|
|
if (IsEnabled) {
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
|
|
IsLocked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);
|
|
|
|
//
|
|
// Add PcdSkipOpalPasswordPrompt to determin whether to skip password prompt.
|
|
// Due to board design, device may not power off during system warm boot, which result in
|
|
// security status remain unlocked status, hence we add device security status check here.
|
|
//
|
|
// If device is in the locked status, device keeps locked and system continues booting.
|
|
// If device is in the unlocked status, system is forced shutdown to support security requirement.
|
|
//
|
|
if (PcdGetBool (PcdSkipOpalPasswordPrompt)) {
|
|
if (IsLocked) {
|
|
return;
|
|
} else {
|
|
gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
|
}
|
|
}
|
|
|
|
while (Count < MAX_PASSWORD_TRY_COUNT) {
|
|
Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, NULL, &PressEsc);
|
|
if (PressEsc) {
|
|
if (IsLocked) {
|
|
//
|
|
// Current device in the lock status and
|
|
// User not input password and press ESC,
|
|
// keep device in lock status and continue boot.
|
|
//
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to skip the request and continue boot,",
|
|
L"Press ESC to input password again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
//
|
|
// Keep lock and continue boot.
|
|
//
|
|
return;
|
|
} else {
|
|
//
|
|
// Let user input password again.
|
|
//
|
|
continue;
|
|
}
|
|
} else {
|
|
//
|
|
// Current device in the unlock status and
|
|
// User not input password and press ESC,
|
|
// Shutdown the device.
|
|
//
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to shutdown, Press ESC to input password again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
|
} else {
|
|
//
|
|
// Let user input password again.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Password == NULL) {
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLen = (UINT32) AsciiStrLen(Password);
|
|
|
|
if (IsLocked) {
|
|
Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, FALSE, FALSE);
|
|
} else {
|
|
Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, TRUE, TRUE);
|
|
if (Ret == TcgResultSuccess) {
|
|
Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, FALSE, FALSE);
|
|
}
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
|
|
DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
|
|
}
|
|
|
|
if (Password != NULL) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Check whether opal device's Tries value has reach the TryLimit value, if yes, force a shutdown
|
|
// before accept new password.
|
|
//
|
|
if (Ret == TcgResultFailureInvalidType) {
|
|
Count = MAX_PASSWORD_TRY_COUNT;
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Invalid password.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
}
|
|
|
|
if (Count >= MAX_PASSWORD_TRY_COUNT) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Opal password retry count exceeds the limit. Must shutdown!",
|
|
L"Press ENTER to shutdown",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
|
|
gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Process Enable Feature OPAL request.
|
|
|
|
@param[in] Dev The device which has Enable Feature OPAL request.
|
|
@param[in] RequestString Request string.
|
|
|
|
**/
|
|
VOID
|
|
ProcessOpalRequestEnableFeature (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
CHAR8 *Password;
|
|
UINT32 PasswordLen;
|
|
CHAR8 *PasswordConfirm;
|
|
UINT32 PasswordLenConfirm;
|
|
OPAL_SESSION Session;
|
|
BOOLEAN PressEsc;
|
|
EFI_INPUT_KEY Key;
|
|
TCG_RESULT Ret;
|
|
CHAR16 *PopUpString;
|
|
|
|
if (Dev == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
|
|
|
|
PopUpString = OpalGetPopUpString (Dev, RequestString);
|
|
|
|
Count = 0;
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
|
|
while (Count < MAX_PASSWORD_TRY_COUNT) {
|
|
Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", NULL, &PressEsc);
|
|
if (PressEsc) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to skip the request and continue boot,",
|
|
L"Press ESC to input password again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
return;
|
|
} else {
|
|
//
|
|
// Let user input password again.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (Password == NULL) {
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLen = (UINT32) AsciiStrLen(Password);
|
|
|
|
PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", NULL, &PressEsc);
|
|
if (PasswordConfirm == NULL) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
|
|
if ((PasswordLen != PasswordLenConfirm) ||
|
|
(CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
ZeroMem (PasswordConfirm, PasswordLenConfirm);
|
|
FreePool (PasswordConfirm);
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Passwords are not the same.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
|
|
if (PasswordConfirm != NULL) {
|
|
ZeroMem (PasswordConfirm, PasswordLenConfirm);
|
|
FreePool (PasswordConfirm);
|
|
}
|
|
|
|
Ret = OpalSupportEnableOpalFeature (&Session, Dev->OpalDisk.Msid, Dev->OpalDisk.MsidLength, Password, PasswordLen);
|
|
if (Ret == TcgResultSuccess) {
|
|
OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
|
|
DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
|
|
}
|
|
|
|
if (Password != NULL) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Request failed.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
}
|
|
|
|
if (Count >= MAX_PASSWORD_TRY_COUNT) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Opal password retry count exceeds the limit.",
|
|
L"Press ENTER to skip the request and continue boot",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Process Disable User OPAL request.
|
|
|
|
@param[in] Dev The device which has Disable User OPAL request.
|
|
@param[in] RequestString Request string.
|
|
|
|
**/
|
|
VOID
|
|
ProcessOpalRequestDisableUser (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
CHAR8 *Password;
|
|
UINT32 PasswordLen;
|
|
OPAL_SESSION Session;
|
|
BOOLEAN PressEsc;
|
|
EFI_INPUT_KEY Key;
|
|
TCG_RESULT Ret;
|
|
BOOLEAN PasswordFailed;
|
|
CHAR16 *PopUpString;
|
|
|
|
if (Dev == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
|
|
|
|
PopUpString = OpalGetPopUpString (Dev, RequestString);
|
|
|
|
Count = 0;
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
|
|
while (Count < MAX_PASSWORD_TRY_COUNT) {
|
|
Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, NULL, &PressEsc);
|
|
if (PressEsc) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to skip the request and continue boot,",
|
|
L"Press ESC to input password again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
return;
|
|
} else {
|
|
//
|
|
// Let user input password again.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (Password == NULL) {
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLen = (UINT32) AsciiStrLen(Password);
|
|
|
|
Ret = OpalUtilDisableUser(&Session, Password, PasswordLen, &PasswordFailed);
|
|
if (Ret == TcgResultSuccess) {
|
|
OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
|
|
DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
|
|
}
|
|
|
|
if (Password != NULL) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Invalid password, request failed.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
}
|
|
|
|
if (Count >= MAX_PASSWORD_TRY_COUNT) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Opal password retry count exceeds the limit.",
|
|
L"Press ENTER to skip the request and continue boot",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Process Psid Revert OPAL request.
|
|
|
|
@param[in] Dev The device which has Psid Revert OPAL request.
|
|
@param[in] RequestString Request string.
|
|
|
|
**/
|
|
VOID
|
|
ProcessOpalRequestPsidRevert (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
CHAR8 *Psid;
|
|
UINT32 PsidLen;
|
|
OPAL_SESSION Session;
|
|
BOOLEAN PressEsc;
|
|
EFI_INPUT_KEY Key;
|
|
TCG_RESULT Ret;
|
|
CHAR16 *PopUpString;
|
|
CHAR16 *PopUpString2;
|
|
CHAR16 *PopUpString3;
|
|
UINTN BufferSize;
|
|
|
|
if (Dev == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
|
|
|
|
PopUpString = OpalGetPopUpString (Dev, RequestString);
|
|
|
|
if (Dev->OpalDisk.EstimateTimeCost > MAX_ACCEPTABLE_REVERTING_TIME) {
|
|
BufferSize = StrSize (L"Warning: Revert action will take about ####### seconds");
|
|
PopUpString2 = AllocateZeroPool (BufferSize);
|
|
ASSERT (PopUpString2 != NULL);
|
|
UnicodeSPrint (
|
|
PopUpString2,
|
|
BufferSize,
|
|
L"WARNING: Revert action will take about %d seconds",
|
|
Dev->OpalDisk.EstimateTimeCost
|
|
);
|
|
PopUpString3 = L"DO NOT power off system during the revert action!";
|
|
} else {
|
|
PopUpString2 = NULL;
|
|
PopUpString3 = NULL;
|
|
}
|
|
|
|
Count = 0;
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
|
|
while (Count < MAX_PSID_TRY_COUNT) {
|
|
Psid = OpalDriverPopUpPsidInput (Dev, PopUpString, PopUpString2, PopUpString3, &PressEsc);
|
|
if (PressEsc) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to skip the request and continue boot,",
|
|
L"Press ESC to input Psid again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
goto Done;
|
|
} else {
|
|
//
|
|
// Let user input Psid again.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (Psid == NULL) {
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PsidLen = (UINT32) AsciiStrLen(Psid);
|
|
|
|
Ret = OpalUtilPsidRevert(&Session, Psid, PsidLen);
|
|
if (Ret == TcgResultSuccess) {
|
|
DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
|
|
}
|
|
|
|
if (Psid != NULL) {
|
|
ZeroMem (Psid, PsidLen);
|
|
FreePool (Psid);
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Invalid Psid, request failed.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
}
|
|
|
|
if (Count >= MAX_PSID_TRY_COUNT) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Opal Psid retry count exceeds the limit.",
|
|
L"Press ENTER to skip the request and continue boot",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
}
|
|
|
|
Done:
|
|
if (PopUpString2 != NULL) {
|
|
FreePool (PopUpString2);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Process Admin Revert OPAL request.
|
|
|
|
@param[in] Dev The device which has Revert OPAL request.
|
|
@param[in] KeepUserData Whether to keep user data or not.
|
|
@param[in] RequestString Request string.
|
|
|
|
**/
|
|
VOID
|
|
ProcessOpalRequestRevert (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN BOOLEAN KeepUserData,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
CHAR8 *Password;
|
|
UINT32 PasswordLen;
|
|
OPAL_SESSION Session;
|
|
BOOLEAN PressEsc;
|
|
EFI_INPUT_KEY Key;
|
|
TCG_RESULT Ret;
|
|
BOOLEAN PasswordFailed;
|
|
CHAR16 *PopUpString;
|
|
CHAR16 *PopUpString2;
|
|
CHAR16 *PopUpString3;
|
|
UINTN BufferSize;
|
|
|
|
if (Dev == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
|
|
|
|
PopUpString = OpalGetPopUpString (Dev, RequestString);
|
|
|
|
if ((!KeepUserData) &&
|
|
(Dev->OpalDisk.EstimateTimeCost > MAX_ACCEPTABLE_REVERTING_TIME)) {
|
|
BufferSize = StrSize (L"Warning: Revert action will take about ####### seconds");
|
|
PopUpString2 = AllocateZeroPool (BufferSize);
|
|
ASSERT (PopUpString2 != NULL);
|
|
UnicodeSPrint (
|
|
PopUpString2,
|
|
BufferSize,
|
|
L"WARNING: Revert action will take about %d seconds",
|
|
Dev->OpalDisk.EstimateTimeCost
|
|
);
|
|
PopUpString3 = L"DO NOT power off system during the revert action!";
|
|
} else {
|
|
PopUpString2 = NULL;
|
|
PopUpString3 = NULL;
|
|
}
|
|
|
|
Count = 0;
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
|
|
while (Count < MAX_PASSWORD_TRY_COUNT) {
|
|
Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, PopUpString2, PopUpString3, &PressEsc);
|
|
if (PressEsc) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to skip the request and continue boot,",
|
|
L"Press ESC to input password again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
goto Done;
|
|
} else {
|
|
//
|
|
// Let user input password again.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (Password == NULL) {
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLen = (UINT32) AsciiStrLen(Password);
|
|
|
|
if ((Dev->OpalDisk.SupportedAttributes.PyriteSsc == 1) &&
|
|
(Dev->OpalDisk.LockingFeature.MediaEncryption == 0)) {
|
|
//
|
|
// For pyrite type device which does not support media encryption,
|
|
// it does not accept "Keep User Data" parameter.
|
|
// So here hardcode a FALSE for this case.
|
|
//
|
|
Ret = OpalUtilRevert(
|
|
&Session,
|
|
FALSE,
|
|
Password,
|
|
PasswordLen,
|
|
&PasswordFailed,
|
|
Dev->OpalDisk.Msid,
|
|
Dev->OpalDisk.MsidLength
|
|
);
|
|
} else {
|
|
Ret = OpalUtilRevert(
|
|
&Session,
|
|
KeepUserData,
|
|
Password,
|
|
PasswordLen,
|
|
&PasswordFailed,
|
|
Dev->OpalDisk.Msid,
|
|
Dev->OpalDisk.MsidLength
|
|
);
|
|
}
|
|
if (Ret == TcgResultSuccess) {
|
|
OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
|
|
DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
|
|
}
|
|
|
|
if (Password != NULL) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Invalid password, request failed.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
}
|
|
|
|
if (Count >= MAX_PASSWORD_TRY_COUNT) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Opal password retry count exceeds the limit.",
|
|
L"Press ENTER to skip the request and continue boot",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
}
|
|
|
|
Done:
|
|
if (PopUpString2 != NULL) {
|
|
FreePool (PopUpString2);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Process Secure Erase OPAL request.
|
|
|
|
@param[in] Dev The device which has Secure Erase OPAL request.
|
|
@param[in] RequestString Request string.
|
|
|
|
**/
|
|
VOID
|
|
ProcessOpalRequestSecureErase (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
CHAR8 *Password;
|
|
UINT32 PasswordLen;
|
|
OPAL_SESSION Session;
|
|
BOOLEAN PressEsc;
|
|
EFI_INPUT_KEY Key;
|
|
TCG_RESULT Ret;
|
|
BOOLEAN PasswordFailed;
|
|
CHAR16 *PopUpString;
|
|
CHAR16 *PopUpString2;
|
|
CHAR16 *PopUpString3;
|
|
UINTN BufferSize;
|
|
|
|
if (Dev == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
|
|
|
|
PopUpString = OpalGetPopUpString (Dev, RequestString);
|
|
|
|
if (Dev->OpalDisk.EstimateTimeCost > MAX_ACCEPTABLE_REVERTING_TIME) {
|
|
BufferSize = StrSize (L"Warning: Secure erase action will take about ####### seconds");
|
|
PopUpString2 = AllocateZeroPool (BufferSize);
|
|
ASSERT (PopUpString2 != NULL);
|
|
UnicodeSPrint (
|
|
PopUpString2,
|
|
BufferSize,
|
|
L"WARNING: Secure erase action will take about %d seconds",
|
|
Dev->OpalDisk.EstimateTimeCost
|
|
);
|
|
PopUpString3 = L"DO NOT power off system during the action!";
|
|
} else {
|
|
PopUpString2 = NULL;
|
|
PopUpString3 = NULL;
|
|
}
|
|
Count = 0;
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
|
|
while (Count < MAX_PASSWORD_TRY_COUNT) {
|
|
Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, PopUpString2, PopUpString3, &PressEsc);
|
|
if (PressEsc) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to skip the request and continue boot,",
|
|
L"Press ESC to input password again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
goto Done;
|
|
} else {
|
|
//
|
|
// Let user input password again.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (Password == NULL) {
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLen = (UINT32) AsciiStrLen(Password);
|
|
|
|
Ret = OpalUtilSecureErase(&Session, Password, PasswordLen, &PasswordFailed);
|
|
if (Ret == TcgResultSuccess) {
|
|
OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
|
|
DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
|
|
}
|
|
|
|
if (Password != NULL) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Invalid password, request failed.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
}
|
|
|
|
if (Count >= MAX_PASSWORD_TRY_COUNT) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Opal password retry count exceeds the limit.",
|
|
L"Press ENTER to skip the request and continue boot",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
}
|
|
|
|
Done:
|
|
if (PopUpString2 != NULL) {
|
|
FreePool (PopUpString2);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Process Set Admin Pwd OPAL request.
|
|
|
|
@param[in] Dev The device which has Set Admin Pwd Feature OPAL request.
|
|
@param[in] RequestString Request string.
|
|
|
|
**/
|
|
VOID
|
|
ProcessOpalRequestSetUserPwd (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
CHAR8 *OldPassword;
|
|
UINT32 OldPasswordLen;
|
|
CHAR8 *Password;
|
|
UINT32 PasswordLen;
|
|
CHAR8 *PasswordConfirm;
|
|
UINT32 PasswordLenConfirm;
|
|
OPAL_SESSION Session;
|
|
BOOLEAN PressEsc;
|
|
EFI_INPUT_KEY Key;
|
|
TCG_RESULT Ret;
|
|
CHAR16 *PopUpString;
|
|
|
|
if (Dev == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
|
|
|
|
PopUpString = OpalGetPopUpString (Dev, RequestString);
|
|
|
|
Count = 0;
|
|
|
|
while (Count < MAX_PASSWORD_TRY_COUNT) {
|
|
OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", NULL, &PressEsc);
|
|
if (PressEsc) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to skip the request and continue boot,",
|
|
L"Press ESC to input password again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
return;
|
|
} else {
|
|
//
|
|
// Let user input password again.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (OldPassword == NULL) {
|
|
Count ++;
|
|
continue;
|
|
}
|
|
OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_USER1_AUTHORITY);
|
|
if (Ret == TcgResultSuccess) {
|
|
DEBUG ((DEBUG_INFO, "Verify with USER1 authority : Success\n"));
|
|
} else {
|
|
Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
|
|
if (Ret == TcgResultSuccess) {
|
|
DEBUG ((DEBUG_INFO, "Verify with ADMIN1 authority: Success\n"));
|
|
} else {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Incorrect password.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", NULL, &PressEsc);
|
|
if (Password == NULL) {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLen = (UINT32) AsciiStrLen(Password);
|
|
|
|
PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", NULL, &PressEsc);
|
|
if (PasswordConfirm == NULL) {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
|
|
if ((PasswordLen != PasswordLenConfirm) ||
|
|
(CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
ZeroMem (PasswordConfirm, PasswordLenConfirm);
|
|
FreePool (PasswordConfirm);
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Passwords are not the same.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
|
|
if (PasswordConfirm != NULL) {
|
|
ZeroMem (PasswordConfirm, PasswordLenConfirm);
|
|
FreePool (PasswordConfirm);
|
|
}
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
Ret = OpalUtilSetUserPassword(
|
|
&Session,
|
|
OldPassword,
|
|
OldPasswordLen,
|
|
Password,
|
|
PasswordLen
|
|
);
|
|
if (Ret == TcgResultSuccess) {
|
|
OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
|
|
DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
|
|
}
|
|
|
|
if (OldPassword != NULL) {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
}
|
|
|
|
if (Password != NULL) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Request failed.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
}
|
|
|
|
if (Count >= MAX_PASSWORD_TRY_COUNT) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Opal password retry count exceeds the limit.",
|
|
L"Press ENTER to skip the request and continue boot",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Process Set Admin Pwd OPAL request.
|
|
|
|
@param[in] Dev The device which has Set Admin Pwd Feature OPAL request.
|
|
@param[in] RequestString Request string.
|
|
|
|
**/
|
|
VOID
|
|
ProcessOpalRequestSetAdminPwd (
|
|
IN OPAL_DRIVER_DEVICE *Dev,
|
|
IN CHAR16 *RequestString
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
CHAR8 *OldPassword;
|
|
UINT32 OldPasswordLen;
|
|
CHAR8 *Password;
|
|
UINT32 PasswordLen;
|
|
CHAR8 *PasswordConfirm;
|
|
UINT32 PasswordLenConfirm;
|
|
OPAL_SESSION Session;
|
|
BOOLEAN PressEsc;
|
|
EFI_INPUT_KEY Key;
|
|
TCG_RESULT Ret;
|
|
CHAR16 *PopUpString;
|
|
|
|
if (Dev == NULL) {
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
|
|
|
|
PopUpString = OpalGetPopUpString (Dev, RequestString);
|
|
|
|
Count = 0;
|
|
|
|
while (Count < MAX_PASSWORD_TRY_COUNT) {
|
|
OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", NULL, &PressEsc);
|
|
if (PressEsc) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Press ENTER to skip the request and continue boot,",
|
|
L"Press ESC to input password again",
|
|
NULL
|
|
);
|
|
} while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
|
|
|
|
if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
return;
|
|
} else {
|
|
//
|
|
// Let user input password again.
|
|
//
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (OldPassword == NULL) {
|
|
Count ++;
|
|
continue;
|
|
}
|
|
OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
|
|
if (Ret == TcgResultSuccess) {
|
|
DEBUG ((DEBUG_INFO, "Verify: Success\n"));
|
|
} else {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Incorrect password.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
|
|
Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", NULL, &PressEsc);
|
|
if (Password == NULL) {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLen = (UINT32) AsciiStrLen(Password);
|
|
|
|
PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", NULL, &PressEsc);
|
|
if (PasswordConfirm == NULL) {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
|
|
if ((PasswordLen != PasswordLenConfirm) ||
|
|
(CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
ZeroMem (PasswordConfirm, PasswordLenConfirm);
|
|
FreePool (PasswordConfirm);
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Passwords are not the same.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
Count ++;
|
|
continue;
|
|
}
|
|
|
|
if (PasswordConfirm != NULL) {
|
|
ZeroMem (PasswordConfirm, PasswordLenConfirm);
|
|
FreePool (PasswordConfirm);
|
|
}
|
|
|
|
|
|
ZeroMem(&Session, sizeof(Session));
|
|
Session.Sscp = Dev->OpalDisk.Sscp;
|
|
Session.MediaId = Dev->OpalDisk.MediaId;
|
|
Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
|
|
Ret = OpalUtilSetAdminPassword(
|
|
&Session,
|
|
OldPassword,
|
|
OldPasswordLen,
|
|
Password,
|
|
PasswordLen
|
|
);
|
|
if (Ret == TcgResultSuccess) {
|
|
OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
|
|
DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
|
|
}
|
|
|
|
if (OldPassword != NULL) {
|
|
ZeroMem (OldPassword, OldPasswordLen);
|
|
FreePool (OldPassword);
|
|
}
|
|
|
|
if (Password != NULL) {
|
|
ZeroMem (Password, PasswordLen);
|
|
FreePool (Password);
|
|
}
|
|
|
|
if (Ret == TcgResultSuccess) {
|
|
break;
|
|
}
|
|
|
|
Count++;
|
|
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Request failed.",
|
|
L"Press ENTER to retry",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
}
|
|
|
|
if (Count >= MAX_PASSWORD_TRY_COUNT) {
|
|
do {
|
|
CreatePopUp (
|
|
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
|
|
&Key,
|
|
L"Opal password retry count exceeds the limit.",
|
|
L"Press ENTER to skip the request and continue boot",
|
|
NULL
|
|
);
|
|
} while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
|
|
gST->ConOut->ClearScreen(gST->ConOut);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Process OPAL request.
|
|
|
|
@param[in] Dev The device which has OPAL request.
|
|
|
|
**/
|
|
VOID
|
|
ProcessOpalRequest (
|
|
IN OPAL_DRIVER_DEVICE *Dev
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
OPAL_REQUEST_VARIABLE *TempVariable;
|
|
OPAL_REQUEST_VARIABLE *Variable;
|
|
UINTN VariableSize;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePathInVariable;
|
|
UINTN DevicePathSizeInVariable;
|
|
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
|
UINTN DevicePathSize;
|
|
BOOLEAN KeepUserData;
|
|
|
|
DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
|
|
|
|
if (mOpalRequestVariable == NULL) {
|
|
Status = GetVariable2 (
|
|
OPAL_REQUEST_VARIABLE_NAME,
|
|
&gHiiSetupVariableGuid,
|
|
(VOID **) &Variable,
|
|
&VariableSize
|
|
);
|
|
if (EFI_ERROR (Status) || (Variable == NULL)) {
|
|
return;
|
|
}
|
|
mOpalRequestVariable = Variable;
|
|
mOpalRequestVariableSize = VariableSize;
|
|
|
|
//
|
|
// Delete the OPAL request variable.
|
|
//
|
|
Status = gRT->SetVariable (
|
|
OPAL_REQUEST_VARIABLE_NAME,
|
|
(EFI_GUID *) &gHiiSetupVariableGuid,
|
|
0,
|
|
0,
|
|
NULL
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
} else {
|
|
Variable = mOpalRequestVariable;
|
|
VariableSize = mOpalRequestVariableSize;
|
|
}
|
|
|
|
//
|
|
// Process the OPAL requests.
|
|
//
|
|
TempVariable = Variable;
|
|
while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
|
|
(VariableSize >= TempVariable->Length) &&
|
|
(TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
|
|
DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
|
|
DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
|
|
DevicePath = Dev->OpalDisk.OpalDevicePath;
|
|
DevicePathSize = GetDevicePathSize (DevicePath);
|
|
if ((DevicePathSize == DevicePathSizeInVariable) &&
|
|
(CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) {
|
|
//
|
|
// Found the node for the OPAL device.
|
|
//
|
|
if (TempVariable->OpalRequest.SetAdminPwd != 0) {
|
|
ProcessOpalRequestSetAdminPwd (Dev, L"Update Admin Pwd:");
|
|
}
|
|
if (TempVariable->OpalRequest.SetUserPwd != 0) {
|
|
ProcessOpalRequestSetUserPwd (Dev, L"Set User Pwd:");
|
|
}
|
|
if (TempVariable->OpalRequest.SecureErase!= 0) {
|
|
ProcessOpalRequestSecureErase (Dev, L"Secure Erase:");
|
|
}
|
|
if (TempVariable->OpalRequest.Revert != 0) {
|
|
KeepUserData = (BOOLEAN) TempVariable->OpalRequest.KeepUserData;
|
|
ProcessOpalRequestRevert (
|
|
Dev,
|
|
KeepUserData,
|
|
KeepUserData ? L"Admin Revert(keep):" : L"Admin Revert:"
|
|
);
|
|
}
|
|
if (TempVariable->OpalRequest.PsidRevert != 0) {
|
|
ProcessOpalRequestPsidRevert (Dev, L"Psid Revert:");
|
|
}
|
|
if (TempVariable->OpalRequest.DisableUser != 0) {
|
|
ProcessOpalRequestDisableUser (Dev, L"Disable User:");
|
|
}
|
|
if (TempVariable->OpalRequest.EnableFeature != 0) {
|
|
ProcessOpalRequestEnableFeature (Dev, L"Enable Feature:");
|
|
}
|
|
|
|
//
|
|
// Update Device ownership.
|
|
// Later BlockSID command may block the update.
|
|
//
|
|
OpalDiskUpdateOwnerShip (&Dev->OpalDisk);
|
|
|
|
break;
|
|
}
|
|
|
|
VariableSize -= TempVariable->Length;
|
|
TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
|
|
}
|
|
|
|
/**
|
|
Add new device to the global device list.
|
|
|
|
@param Dev New create device.
|
|
|
|
**/
|
|
VOID
|
|
AddDeviceToTail(
|
|
IN OPAL_DRIVER_DEVICE *Dev
|
|
)
|
|
{
|
|
OPAL_DRIVER_DEVICE *TmpDev;
|
|
|
|
if (mOpalDriver.DeviceList == NULL) {
|
|
mOpalDriver.DeviceList = Dev;
|
|
} else {
|
|
TmpDev = mOpalDriver.DeviceList;
|
|
while (TmpDev->Next != NULL) {
|
|
TmpDev = TmpDev->Next;
|
|
}
|
|
|
|
TmpDev->Next = Dev;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Remove one device in the global device list.
|
|
|
|
@param Dev The device need to be removed.
|
|
|
|
**/
|
|
VOID
|
|
RemoveDevice (
|
|
IN OPAL_DRIVER_DEVICE *Dev
|
|
)
|
|
{
|
|
OPAL_DRIVER_DEVICE *TmpDev;
|
|
|
|
if (mOpalDriver.DeviceList == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (mOpalDriver.DeviceList == Dev) {
|
|
mOpalDriver.DeviceList = NULL;
|
|
return;
|
|
}
|
|
|
|
TmpDev = mOpalDriver.DeviceList;
|
|
while (TmpDev->Next != NULL) {
|
|
if (TmpDev->Next == Dev) {
|
|
TmpDev->Next = Dev->Next;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Get current device count.
|
|
|
|
@retval return the current created device count.
|
|
|
|
**/
|
|
UINT8
|
|
GetDeviceCount (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Count;
|
|
OPAL_DRIVER_DEVICE *TmpDev;
|
|
|
|
Count = 0;
|
|
TmpDev = mOpalDriver.DeviceList;
|
|
|
|
while (TmpDev != NULL) {
|
|
Count++;
|
|
TmpDev = TmpDev->Next;
|
|
}
|
|
|
|
return Count;
|
|
}
|
|
|
|
/**
|
|
Get devcie list info.
|
|
|
|
@retval return the device list pointer.
|
|
**/
|
|
OPAL_DRIVER_DEVICE*
|
|
OpalDriverGetDeviceList(
|
|
VOID
|
|
)
|
|
{
|
|
return mOpalDriver.DeviceList;
|
|
}
|
|
|
|
/**
|
|
Stop this Controller.
|
|
|
|
@param Dev The device need to be stopped.
|
|
|
|
**/
|
|
VOID
|
|
OpalDriverStopDevice (
|
|
OPAL_DRIVER_DEVICE *Dev
|
|
)
|
|
{
|
|
//
|
|
// free each name
|
|
//
|
|
FreePool(Dev->Name16);
|
|
|
|
//
|
|
// remove OPAL_DRIVER_DEVICE from the list
|
|
// it updates the controllerList pointer
|
|
//
|
|
RemoveDevice(Dev);
|
|
|
|
//
|
|
// close protocols that were opened
|
|
//
|
|
gBS->CloseProtocol(
|
|
Dev->Handle,
|
|
&gEfiStorageSecurityCommandProtocolGuid,
|
|
gOpalDriverBinding.DriverBindingHandle,
|
|
Dev->Handle
|
|
);
|
|
|
|
gBS->CloseProtocol(
|
|
Dev->Handle,
|
|
&gEfiBlockIoProtocolGuid,
|
|
gOpalDriverBinding.DriverBindingHandle,
|
|
Dev->Handle
|
|
);
|
|
|
|
FreePool(Dev);
|
|
}
|
|
|
|
/**
|
|
Get devcie name through the component name protocol.
|
|
|
|
@param[in] AllHandlesBuffer The handle buffer for current system.
|
|
@param[in] NumAllHandles The number of handles for the handle buffer.
|
|
@param[in] Dev The device which need to get name.
|
|
@param[in] UseComp1 Whether use component name or name2 protocol.
|
|
|
|
@retval TRUE Find the name for this device.
|
|
@retval FALSE Not found the name for this device.
|
|
**/
|
|
BOOLEAN
|
|
OpalDriverGetDeviceNameByProtocol(
|
|
EFI_HANDLE *AllHandlesBuffer,
|
|
UINTN NumAllHandles,
|
|
OPAL_DRIVER_DEVICE *Dev,
|
|
BOOLEAN UseComp1
|
|
)
|
|
{
|
|
EFI_HANDLE* ProtocolHandlesBuffer;
|
|
UINTN NumProtocolHandles;
|
|
EFI_STATUS Status;
|
|
EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout
|
|
EFI_GUID Protocol;
|
|
UINTN StrLength;
|
|
EFI_DEVICE_PATH_PROTOCOL* TmpDevPath;
|
|
UINTN Index1;
|
|
UINTN Index2;
|
|
EFI_HANDLE TmpHandle;
|
|
CHAR16 *DevName;
|
|
|
|
if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;
|
|
|
|
//
|
|
// Find all EFI_HANDLES with protocol
|
|
//
|
|
Status = gBS->LocateHandleBuffer(
|
|
ByProtocol,
|
|
&Protocol,
|
|
NULL,
|
|
&NumProtocolHandles,
|
|
&ProtocolHandlesBuffer
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Exit early if no supported devices
|
|
//
|
|
if (NumProtocolHandles == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get printable name by iterating through all protocols
|
|
// using the handle as the child, and iterate through all handles for the controller
|
|
// exit loop early once found, if not found, then delete device
|
|
// storage security protocol instances already exist, add them to internal list
|
|
//
|
|
Status = EFI_DEVICE_ERROR;
|
|
for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {
|
|
DevName = NULL;
|
|
|
|
if (Dev->Name16 != NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
TmpHandle = ProtocolHandlesBuffer[Index1];
|
|
|
|
Status = gBS->OpenProtocol(
|
|
TmpHandle,
|
|
&Protocol,
|
|
(VOID**)&Cnp1_2,
|
|
gImageHandle,
|
|
NULL,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if (EFI_ERROR(Status) || Cnp1_2 == NULL) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Use all handles array as controller handle
|
|
//
|
|
for (Index2 = 0; Index2 < NumAllHandles; Index2++) {
|
|
Status = Cnp1_2->GetControllerName(
|
|
Cnp1_2,
|
|
AllHandlesBuffer[Index2],
|
|
Dev->Handle,
|
|
LANGUAGE_ISO_639_2_ENGLISH,
|
|
&DevName
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
Status = Cnp1_2->GetControllerName(
|
|
Cnp1_2,
|
|
AllHandlesBuffer[Index2],
|
|
Dev->Handle,
|
|
LANGUAGE_RFC_3066_ENGLISH,
|
|
&DevName
|
|
);
|
|
}
|
|
if (!EFI_ERROR(Status) && DevName != NULL) {
|
|
StrLength = StrLen(DevName) + 1; // Add one for NULL terminator
|
|
Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));
|
|
ASSERT (Dev->Name16 != NULL);
|
|
StrCpyS (Dev->Name16, StrLength, DevName);
|
|
Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);
|
|
UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);
|
|
|
|
//
|
|
// Retrieve bridge BDF info and port number or namespace depending on type
|
|
//
|
|
TmpDevPath = NULL;
|
|
Status = gBS->OpenProtocol(
|
|
Dev->Handle,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID**)&TmpDevPath,
|
|
gImageHandle,
|
|
NULL,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if (!EFI_ERROR(Status)) {
|
|
Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);
|
|
return TRUE;
|
|
}
|
|
|
|
if (Dev->Name16 != NULL) {
|
|
FreePool(Dev->Name16);
|
|
Dev->Name16 = NULL;
|
|
}
|
|
if (Dev->NameZ != NULL) {
|
|
FreePool(Dev->NameZ);
|
|
Dev->NameZ = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Get devcie name through the component name protocol.
|
|
|
|
@param[in] Dev The device which need to get name.
|
|
|
|
@retval TRUE Find the name for this device.
|
|
@retval FALSE Not found the name for this device.
|
|
**/
|
|
BOOLEAN
|
|
OpalDriverGetDriverDeviceName(
|
|
OPAL_DRIVER_DEVICE *Dev
|
|
)
|
|
{
|
|
EFI_HANDLE* AllHandlesBuffer;
|
|
UINTN NumAllHandles;
|
|
EFI_STATUS Status;
|
|
|
|
if (Dev == NULL) {
|
|
DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Iterate through ComponentName2 handles to get name, if fails, try ComponentName
|
|
//
|
|
if (Dev->Name16 == NULL) {
|
|
DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));
|
|
//
|
|
// Find all EFI_HANDLES
|
|
//
|
|
Status = gBS->LocateHandleBuffer(
|
|
AllHandles,
|
|
NULL,
|
|
NULL,
|
|
&NumAllHandles,
|
|
&AllHandlesBuffer
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Try component Name2
|
|
//
|
|
if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {
|
|
DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));
|
|
if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {
|
|
DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Main entry for this driver.
|
|
|
|
@param ImageHandle Image Handle this driver.
|
|
@param SystemTable Pointer to SystemTable.
|
|
|
|
@retval EFI_SUCCESS This function always complete successfully.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EfiDriverEntryPoint(
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE* SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_EVENT EndOfDxeEvent;
|
|
|
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&gOpalDriverBinding,
|
|
ImageHandle,
|
|
&gOpalComponentName,
|
|
&gOpalComponentName2
|
|
);
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));
|
|
return Status ;
|
|
}
|
|
|
|
//
|
|
// Initialize Driver object
|
|
//
|
|
ZeroMem(&mOpalDriver, sizeof(mOpalDriver));
|
|
mOpalDriver.Handle = ImageHandle;
|
|
|
|
Status = gBS->CreateEventEx (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
OpalEndOfDxeEventNotify,
|
|
NULL,
|
|
&gEfiEndOfDxeEventGroupGuid,
|
|
&EndOfDxeEvent
|
|
);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Install Hii packages.
|
|
//
|
|
HiiInstall();
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Tests to see if this driver supports a given controller.
|
|
|
|
This function checks to see if the controller contains an instance of the
|
|
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCOL
|
|
and returns EFI_SUCCESS if it does.
|
|
|
|
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param[in] ControllerHandle The Handle of the controller to test. This Handle
|
|
must support a protocol interface that supplies
|
|
an I/O abstraction to the driver.
|
|
@param[in] RemainingDevicePath This parameter is ignored.
|
|
|
|
@retval EFI_SUCCESS The device contains required protocols
|
|
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
|
|
RemainingDevicePath is already being managed by the driver
|
|
specified by This.
|
|
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
|
|
RemainingDevicePath is already being managed by a different
|
|
driver or an application that requires exclusive access.
|
|
Currently not implemented.
|
|
@retval EFI_UNSUPPORTED The device does not contain requires protocols
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
OpalEfiDriverBindingSupported(
|
|
IN EFI_DRIVER_BINDING_PROTOCOL* This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL* SecurityCommand;
|
|
|
|
if (mOpalEndOfDxe) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.
|
|
//
|
|
Status = gBS->OpenProtocol(
|
|
Controller,
|
|
&gEfiStorageSecurityCommandProtocolGuid,
|
|
( VOID ** )&SecurityCommand,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
|
|
if (Status == EFI_ALREADY_STARTED) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (EFI_ERROR(Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Close protocol and reopen in Start call
|
|
//
|
|
gBS->CloseProtocol(
|
|
Controller,
|
|
&gEfiStorageSecurityCommandProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Enables Opal Management on a supported device if available.
|
|
|
|
The start function is designed to be called after the Opal UEFI Driver has confirmed the
|
|
"controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.
|
|
This function will complete the other necessary checks, such as verifying the device supports
|
|
the correct version of Opal. Upon verification, it will add the device to the
|
|
Opal HII list in order to expose Opal management options.
|
|
|
|
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param[in] ControllerHandle The Handle of the controller to start. This Handle
|
|
must support a protocol interface that supplies
|
|
an I/O abstraction to the driver.
|
|
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
|
parameter is ignored by device drivers, and is optional for bus
|
|
drivers. For a bus driver, if this parameter is NULL, then handles
|
|
for all the children of Controller are created by this driver.
|
|
If this parameter is not NULL and the first Device Path Node is
|
|
not the End of Device Path Node, then only the Handle for the
|
|
child device specified by the first Device Path Node of
|
|
RemainingDevicePath is created by this driver.
|
|
If the first Device Path Node of RemainingDevicePath is
|
|
the End of Device Path Node, no child Handle is created by this
|
|
driver.
|
|
|
|
@retval EFI_SUCCESS Opal management was enabled.
|
|
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
|
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
|
@retval Others The driver failed to start the device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
OpalEfiDriverBindingStart(
|
|
IN EFI_DRIVER_BINDING_PROTOCOL* This,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_BLOCK_IO_PROTOCOL *BlkIo;
|
|
OPAL_DRIVER_DEVICE *Dev;
|
|
OPAL_DRIVER_DEVICE *Itr;
|
|
BOOLEAN Result;
|
|
|
|
Itr = mOpalDriver.DeviceList;
|
|
while (Itr != NULL) {
|
|
if (Controller == Itr->Handle) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
Itr = Itr->Next;
|
|
}
|
|
|
|
//
|
|
// Create internal device for tracking. This allows all disks to be tracked
|
|
// by same HII form
|
|
//
|
|
Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));
|
|
if (Dev == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Dev->Handle = Controller;
|
|
|
|
//
|
|
// Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks
|
|
//
|
|
Status = gBS->OpenProtocol(
|
|
Controller,
|
|
&gEfiStorageSecurityCommandProtocolGuid,
|
|
(VOID **)&Dev->Sscp,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
FreePool(Dev);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
|
|
// function APIs
|
|
//
|
|
Status = gBS->OpenProtocol(
|
|
Controller,
|
|
&gEfiBlockIoProtocolGuid,
|
|
(VOID **)&BlkIo,
|
|
This->DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
//
|
|
// Block_IO not supported on handle
|
|
//
|
|
if(Status == EFI_UNSUPPORTED) {
|
|
BlkIo = NULL;
|
|
} else {
|
|
//
|
|
// Close storage security that was opened
|
|
//
|
|
gBS->CloseProtocol(
|
|
Controller,
|
|
&gEfiStorageSecurityCommandProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
FreePool(Dev);
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Save mediaId
|
|
//
|
|
if(BlkIo == NULL) {
|
|
// If no Block IO present, use defined MediaId value.
|
|
Dev->MediaId = 0x0;
|
|
} else {
|
|
Dev->MediaId = BlkIo->Media->MediaId;
|
|
|
|
gBS->CloseProtocol(
|
|
Controller,
|
|
&gEfiBlockIoProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
}
|
|
|
|
//
|
|
// Acquire Ascii printable name of child, if not found, then ignore device
|
|
//
|
|
Result = OpalDriverGetDriverDeviceName (Dev);
|
|
if (!Result) {
|
|
goto Done;
|
|
}
|
|
|
|
Status = OpalDiskInitialize (Dev);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Done;
|
|
}
|
|
|
|
AddDeviceToTail(Dev);
|
|
|
|
//
|
|
// Check if device is locked and prompt for password.
|
|
//
|
|
OpalDriverRequestPassword (Dev, L"Unlock:");
|
|
|
|
//
|
|
// Process OPAL request from last boot.
|
|
//
|
|
ProcessOpalRequest (Dev);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
Done:
|
|
//
|
|
// free device, close protocols and exit
|
|
//
|
|
gBS->CloseProtocol(
|
|
Controller,
|
|
&gEfiStorageSecurityCommandProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
Controller
|
|
);
|
|
|
|
FreePool(Dev);
|
|
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
/**
|
|
Stop this driver on Controller.
|
|
|
|
@param This Protocol instance pointer.
|
|
@param Controller Handle of device to stop driver on
|
|
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
|
children is zero stop the entire bus driver.
|
|
@param ChildHandleBuffer List of Child Handles to Stop.
|
|
|
|
@retval EFI_SUCCESS This driver is removed Controller.
|
|
@retval other This driver could not be removed from this device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
OpalEfiDriverBindingStop(
|
|
EFI_DRIVER_BINDING_PROTOCOL* This,
|
|
EFI_HANDLE Controller,
|
|
UINTN NumberOfChildren,
|
|
EFI_HANDLE* ChildHandleBuffer
|
|
)
|
|
{
|
|
OPAL_DRIVER_DEVICE* Itr;
|
|
|
|
Itr = mOpalDriver.DeviceList;
|
|
|
|
//
|
|
// does Controller match any of the devices we are managing for Opal
|
|
//
|
|
while (Itr != NULL) {
|
|
if (Itr->Handle == Controller) {
|
|
OpalDriverStopDevice (Itr);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Itr = Itr->Next;
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
|
|
/**
|
|
Unloads UEFI Driver. Very useful for debugging and testing.
|
|
|
|
@param ImageHandle Image Handle this driver.
|
|
|
|
@retval EFI_SUCCESS This function always complete successfully.
|
|
@retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
OpalEfiDriverUnload (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
OPAL_DRIVER_DEVICE *Itr;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
if (ImageHandle != gImageHandle) {
|
|
return (EFI_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// Uninstall any interface added to each device by us
|
|
//
|
|
while (mOpalDriver.DeviceList) {
|
|
Itr = mOpalDriver.DeviceList;
|
|
//
|
|
// Remove OPAL_DRIVER_DEVICE from the list
|
|
// it updates the controllerList pointer
|
|
//
|
|
OpalDriverStopDevice(Itr);
|
|
}
|
|
|
|
//
|
|
// Uninstall the HII capability
|
|
//
|
|
Status = HiiUninstall();
|
|
|
|
return Status;
|
|
}
|
|
|