| /** @file | |
| Entrypoint of Opal UEFI Driver and contains all the logic to | |
| register for new Opal device instances. | |
| Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.<BR> | |
| 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 | |
| // | |
| if (SupportedAttributes->MediaEncryption) { | |
| AvalDiskActions->SecureErase = 1; | |
| } else { | |
| AvalDiskActions->SecureErase = 0; | |
| } | |
| } 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| 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", __func__)); | |
| } | |
| /** | |
| 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 = Dev->Next; | |
| return; | |
| } | |
| TmpDev = mOpalDriver.DeviceList; | |
| while (TmpDev->Next != NULL) { | |
| if (TmpDev->Next == Dev) { | |
| TmpDev->Next = Dev->Next; | |
| break; | |
| } | |
| TmpDev = TmpDev->Next; | |
| } | |
| } | |
| /** | |
| 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 device 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_DEVICE_PATH_PROTOCOL *TmpDevPath = NULL; | |
| EFI_DEVICE_PATH_PROTOCOL *TmpDevPath2 = NULL; | |
| EFI_DEVICE_PATH_PROTOCOL *ChildDevNode = NULL; | |
| EFI_STATUS Status; | |
| CHAR16 *DevName = NULL; | |
| EFI_HANDLE ParentHandle; | |
| EFI_GUID **ProtocolGuidArray = NULL; | |
| UINTN ArrayCount; | |
| UINTN ProtocolIndex; | |
| EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo = NULL; | |
| UINTN OpenInfoCount; | |
| UINTN OpenInfoIndex; | |
| EFI_COMPONENT_NAME2_PROTOCOL *Cnp1_2 = NULL; // EFI component name and componentName2 have same layout | |
| UINTN StrLength; | |
| if (Dev == NULL) { | |
| DEBUG ((DEBUG_ERROR | DEBUG_INIT, "%a: Exiting on Dev == NULL.\n", __func__)); | |
| return FALSE; | |
| } | |
| // | |
| // 1. Find the parent controller device path by deleting the last node of the child device path. | |
| // 2. Find the parent controller handle by its device path. | |
| // 3. Find the agent handle by checking a protocol that is on the parent handle and is opened by the child handle. | |
| // 4. Find the device name from ComponentName2/ComponentName protocols on the agent handle. | |
| // | |
| if (Dev->Name16 == NULL) { | |
| DEBUG ((DEBUG_ERROR | DEBUG_INIT, "%a: Dev->Name is NULL, so updating it.\n", __func__)); | |
| Status = gBS->OpenProtocol ( | |
| Dev->Handle, | |
| &gEfiDevicePathProtocolGuid, | |
| (VOID **)&TmpDevPath, | |
| gImageHandle, | |
| NULL, | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath); | |
| TmpDevPath2 = DuplicateDevicePath (TmpDevPath); | |
| TmpDevPath = TmpDevPath2; | |
| while (!IsDevicePathEnd (TmpDevPath)) { | |
| ChildDevNode = TmpDevPath; | |
| TmpDevPath = NextDevicePathNode (TmpDevPath); | |
| } | |
| // | |
| // Remove the last node to get its parent device path | |
| // | |
| SetDevicePathEndNode (ChildDevNode); | |
| TmpDevPath = TmpDevPath2; | |
| ParentHandle = NULL; | |
| Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TmpDevPath, &ParentHandle); | |
| if (!EFI_ERROR (Status) && (ParentHandle != NULL) && IsDevicePathEnd (TmpDevPath)) { | |
| // | |
| // Found Parent handle | |
| // | |
| Status = gBS->ProtocolsPerHandle ( | |
| ParentHandle, | |
| &ProtocolGuidArray, | |
| &ArrayCount | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { | |
| Status = gBS->OpenProtocolInformation ( | |
| ParentHandle, | |
| ProtocolGuidArray[ProtocolIndex], | |
| &OpenInfo, | |
| &OpenInfoCount | |
| ); | |
| if (!EFI_ERROR (Status)) { | |
| for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { | |
| if ((OpenInfo[OpenInfoIndex].ControllerHandle == Dev->Handle) && | |
| ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) | |
| { | |
| // | |
| // Found Agent handle | |
| // | |
| Status = gBS->OpenProtocol ( | |
| OpenInfo[OpenInfoIndex].AgentHandle, | |
| &gEfiComponentName2ProtocolGuid, | |
| (VOID **)&Cnp1_2, | |
| gImageHandle, | |
| NULL, | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| Status = gBS->OpenProtocol ( | |
| OpenInfo[OpenInfoIndex].AgentHandle, | |
| &gEfiComponentNameProtocolGuid, | |
| (VOID **)&Cnp1_2, | |
| gImageHandle, | |
| NULL, | |
| EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
| ); | |
| } | |
| if (!EFI_ERROR (Status)) { | |
| Status = Cnp1_2->GetControllerName ( | |
| Cnp1_2, | |
| ParentHandle, | |
| Dev->Handle, | |
| LANGUAGE_ISO_639_2_ENGLISH, | |
| &DevName | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| Status = Cnp1_2->GetControllerName ( | |
| Cnp1_2, | |
| ParentHandle, | |
| Dev->Handle, | |
| LANGUAGE_RFC_3066_ENGLISH, | |
| &DevName | |
| ); | |
| } | |
| if (!EFI_ERROR (Status) && (DevName != NULL)) { | |
| StrLength = StrLen (DevName) + 1; | |
| 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); | |
| FreePool (OpenInfo); | |
| FreePool (ProtocolGuidArray); | |
| FreePool (TmpDevPath2); | |
| DEBUG ((DEBUG_INFO, " Dev Name: %s\n", DevName)); | |
| return TRUE; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| if (OpenInfo != NULL) { | |
| FreePool (OpenInfo); | |
| OpenInfo = NULL; | |
| } | |
| } | |
| } | |
| if (ProtocolGuidArray != NULL) { | |
| FreePool (ProtocolGuidArray); | |
| } | |
| } | |
| if (TmpDevPath2 != NULL) { | |
| FreePool (TmpDevPath2); | |
| } | |
| } | |
| } | |
| return FALSE; | |
| } | |
| /** | |
| 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; | |
| } |