+/** @file\r
+ Entrypoint of Opal UEFI Driver and contains all the logic to\r
+ register for new Opal device instances.\r
+\r
+Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+// This UEFI driver consumes EFI_STORAGE_SECURITY_PROTOCOL instances and installs an\r
+// HII GUI to manage Opal features if the device is Opal capable\r
+// If the Opal device is being managed by the UEFI Driver, it shall provide a popup\r
+// window during boot requesting a user password\r
+\r
+#include "OpalDriver.h"\r
+#include "OpalHii.h"\r
+\r
+EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;\r
+EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;\r
+\r
+BOOLEAN mOpalEndOfDxe = FALSE;\r
+OPAL_REQUEST_VARIABLE *mOpalRequestVariable = NULL;\r
+UINTN mOpalRequestVariableSize = 0;\r
+CHAR16 mPopUpString[256];\r
+\r
+typedef struct {\r
+ UINT32 Address;\r
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;\r
+} OPAL_HC_PCI_REGISTER_SAVE;\r
+\r
+//\r
+// To unlock the Intel SATA controller at S3 Resume, restored the following registers.\r
+//\r
+const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {\r
+ {0x9, S3BootScriptWidthUint8},\r
+ {0x10, S3BootScriptWidthUint32},\r
+ {0x14, S3BootScriptWidthUint32},\r
+ {0x18, S3BootScriptWidthUint32},\r
+ {0x1C, S3BootScriptWidthUint32},\r
+ {0x20, S3BootScriptWidthUint32},\r
+ {0x24, S3BootScriptWidthUint32},\r
+ {0x3c, S3BootScriptWidthUint8},\r
+ {0x3d, S3BootScriptWidthUint8},\r
+ {0x40, S3BootScriptWidthUint16},\r
+ {0x42, S3BootScriptWidthUint16},\r
+ {0x92, S3BootScriptWidthUint16},\r
+ {0x94, S3BootScriptWidthUint32},\r
+ {0x9C, S3BootScriptWidthUint32},\r
+ {0x4, S3BootScriptWidthUint16},\r
+};\r
+\r
+OPAL_DRIVER mOpalDriver;\r
+\r
+//\r
+// Globals\r
+//\r
+EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {\r
+ OpalEfiDriverBindingSupported,\r
+ OpalEfiDriverBindingStart,\r
+ OpalEfiDriverBindingStop,\r
+ 0x1b,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+/**\r
+\r
+ The function determines the available actions for the OPAL_DISK provided.\r
+\r
+ @param[in] SupportedAttributes The supported attributes for the device.\r
+ @param[in] LockingFeature The locking status for the device.\r
+ @param[in] OwnerShip The ownership for the device.\r
+ @param[out] AvalDiskActions Pointer to fill-out with appropriate disk actions.\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalSupportGetAvailableActions(\r
+ IN OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,\r
+ IN TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature,\r
+ IN UINT16 OwnerShip,\r
+ OUT OPAL_DISK_ACTIONS *AvalDiskActions\r
+ )\r
+{\r
+ BOOLEAN ExistingPassword;\r
+\r
+ NULL_CHECK(AvalDiskActions);\r
+\r
+ AvalDiskActions->AdminPass = 1;\r
+ AvalDiskActions->UserPass = 0;\r
+ AvalDiskActions->DisableUser = 0;\r
+ AvalDiskActions->Unlock = 0;\r
+\r
+ //\r
+ // Revert is performed on locking sp, so only allow if locking sp is enabled\r
+ //\r
+ if (LockingFeature->LockingEnabled) {\r
+ AvalDiskActions->Revert = 1;\r
+ }\r
+\r
+ //\r
+ // Psid revert is available for any device with media encryption support\r
+ // Revert is allowed for any device with media encryption support, however it requires\r
+ //\r
+ if (SupportedAttributes->MediaEncryption) {\r
+\r
+ //\r
+ // Only allow psid revert if media encryption is enabled.\r
+ // Otherwise, someone who steals a disk can psid revert the disk and the user Data is still\r
+ // intact and accessible\r
+ //\r
+ AvalDiskActions->PsidRevert = 1;\r
+ AvalDiskActions->RevertKeepDataForced = 0;\r
+\r
+ //\r
+ // Secure erase is performed by generating a new encryption key\r
+ // this is only available if encryption is supported\r
+ //\r
+ AvalDiskActions->SecureErase = 1;\r
+ } else {\r
+ AvalDiskActions->PsidRevert = 0;\r
+ AvalDiskActions->SecureErase = 0;\r
+\r
+ //\r
+ // If no media encryption is supported, then a revert (using password) will not\r
+ // erase the Data (since you can't generate a new encryption key)\r
+ //\r
+ AvalDiskActions->RevertKeepDataForced = 1;\r
+ }\r
+\r
+ if (LockingFeature->Locked) {\r
+ AvalDiskActions->Unlock = 1;\r
+ } else {\r
+ AvalDiskActions->Unlock = 0;\r
+ }\r
+\r
+ //\r
+ // Only allow user to set password if an admin password exists\r
+ //\r
+ ExistingPassword = OpalUtilAdminPasswordExists(OwnerShip, LockingFeature);\r
+ AvalDiskActions->UserPass = ExistingPassword;\r
+\r
+ //\r
+ // This will still show up even if there isn't a user, which is fine\r
+ //\r
+ AvalDiskActions->DisableUser = ExistingPassword;\r
+\r
+ return TcgResultSuccess;\r
+}\r
+\r
+/**\r
+ Enable Opal Feature for the input device.\r
+\r
+ @param[in] Session The opal session for the opal device.\r
+ @param[in] Msid Msid\r
+ @param[in] MsidLength Msid Length\r
+ @param[in] Password Admin password\r
+ @param[in] PassLength Length of password in bytes\r
+\r
+**/\r
+TCG_RESULT\r
+EFIAPI\r
+OpalSupportEnableOpalFeature (\r
+ IN OPAL_SESSION *Session,\r
+ IN VOID *Msid,\r
+ IN UINT32 MsidLength,\r
+ IN VOID *Password,\r
+ IN UINT32 PassLength\r
+ )\r
+{\r
+ TCG_RESULT Ret;\r
+\r
+ NULL_CHECK(Session);\r
+ NULL_CHECK(Msid);\r
+ NULL_CHECK(Password);\r
+\r
+ Ret = OpalUtilSetAdminPasswordAsSid(\r
+ Session,\r
+ Msid,\r
+ MsidLength,\r
+ Password,\r
+ PassLength\r
+ );\r
+ if (Ret == TcgResultSuccess) {\r
+ //\r
+ // Enable global locking range\r
+ //\r
+ Ret = OpalUtilSetOpalLockingRange(\r
+ Session,\r
+ Password,\r
+ PassLength,\r
+ OPAL_LOCKING_SP_LOCKING_GLOBALRANGE,\r
+ 0,\r
+ 0,\r
+ TRUE,\r
+ TRUE,\r
+ FALSE,\r
+ FALSE\r
+ );\r
+ }\r
+\r
+ return Ret;\r
+}\r
+\r
+/**\r
+ Update password for the Opal disk.\r
+\r
+ @param[in, out] OpalDisk The disk to update password.\r
+ @param[in] Password The input password.\r
+ @param[in] PasswordLength The input password length.\r
+\r
+**/\r
+VOID\r
+OpalSupportUpdatePassword (\r
+ IN OUT OPAL_DISK *OpalDisk,\r
+ IN VOID *Password,\r
+ IN UINT32 PasswordLength\r
+ )\r
+{\r
+ CopyMem (OpalDisk->Password, Password, PasswordLength);\r
+ OpalDisk->PasswordLength = (UINT8) PasswordLength;\r
+}\r
+\r
+/**\r
+ Extract device info from the device path.\r
+\r
+ @param[in] DevicePath Device path info for the device.\r
+ @param[out] DevInfoLength Device information length needed.\r
+ @param[out] DevInfo Device information extracted.\r
+\r
+ @return Device type.\r
+\r
+**/\r
+UINT8\r
+ExtractDeviceInfoFromDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
+ OUT UINT16 *DevInfoLength,\r
+ OUT OPAL_DEVICE_COMMON *DevInfo OPTIONAL\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevPath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpDevPath2;\r
+ PCI_DEVICE_PATH *PciDevPath;\r
+ UINT8 DeviceType;\r
+ UINT8 BusNum;\r
+ OPAL_PCI_DEVICE *PciDevice;\r
+ OPAL_DEVICE_ATA *DevInfoAta;\r
+ OPAL_DEVICE_NVME *DevInfoNvme;\r
+ SATA_DEVICE_PATH *SataDevPath;\r
+ NVME_NAMESPACE_DEVICE_PATH *NvmeDevPath;\r
+\r
+ ASSERT (DevicePath != NULL);\r
+ ASSERT (DevInfoLength != NULL);\r
+\r
+ DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;\r
+ *DevInfoLength = 0;\r
+\r
+ TmpDevPath = DevicePath;\r
+\r
+ //\r
+ // Get device type.\r
+ //\r
+ while (!IsDevicePathEnd (TmpDevPath)) {\r
+ if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_SATA_DP) {\r
+ //\r
+ // SATA\r
+ //\r
+ if (DevInfo != NULL) {\r
+ SataDevPath = (SATA_DEVICE_PATH *) TmpDevPath;\r
+ DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;\r
+ DevInfoAta->Port = SataDevPath->HBAPortNumber;\r
+ DevInfoAta->PortMultiplierPort = SataDevPath->PortMultiplierPortNumber;\r
+ }\r
+ DeviceType = OPAL_DEVICE_TYPE_ATA;\r
+ *DevInfoLength = sizeof (OPAL_DEVICE_ATA);\r
+ break;\r
+ } else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {\r
+ //\r
+ // NVMe\r
+ //\r
+ if (DevInfo != NULL) {\r
+ NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;\r
+ DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;\r
+ DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;\r
+ }\r
+ DeviceType = OPAL_DEVICE_TYPE_NVME;\r
+ *DevInfoLength = sizeof (OPAL_DEVICE_NVME);\r
+ break;\r
+ }\r
+ TmpDevPath = NextDevicePathNode (TmpDevPath);\r
+ }\r
+\r
+ //\r
+ // Get device info.\r
+ //\r
+ BusNum = 0;\r
+ TmpDevPath = DevicePath;\r
+ TmpDevPath2 = NextDevicePathNode (DevicePath);\r
+ while (!IsDevicePathEnd (TmpDevPath2)) {\r
+ if (TmpDevPath->Type == HARDWARE_DEVICE_PATH && TmpDevPath->SubType == HW_PCI_DP) {\r
+ PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;\r
+ if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||\r
+ (TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_SATA_DP)) {\r
+ if (DevInfo != NULL) {\r
+ PciDevice = &DevInfo->Device;\r
+ PciDevice->Segment = 0;\r
+ PciDevice->Bus = BusNum;\r
+ PciDevice->Device = PciDevPath->Device;\r
+ PciDevice->Function = PciDevPath->Function;\r
+ }\r
+ } else {\r
+ if (DevInfo != NULL) {\r
+ PciDevice = (OPAL_PCI_DEVICE *) ((UINTN) DevInfo + *DevInfoLength);\r
+ PciDevice->Segment = 0;\r
+ PciDevice->Bus = BusNum;\r
+ PciDevice->Device = PciDevPath->Device;\r
+ PciDevice->Function = PciDevPath->Function;\r
+ }\r
+ *DevInfoLength += sizeof (OPAL_PCI_DEVICE);\r
+ if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH && TmpDevPath2->SubType == HW_PCI_DP) {\r
+ BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum, PciDevPath->Device, PciDevPath->Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
+ }\r
+ }\r
+ }\r
+\r
+ TmpDevPath = NextDevicePathNode (TmpDevPath);\r
+ TmpDevPath2 = NextDevicePathNode (TmpDevPath2);\r
+ }\r
+\r
+ ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);\r
+ return DeviceType;\r
+}\r
+\r
+/**\r
+ Save boot script for ATA OPAL device.\r
+\r
+ @param[in] DevInfo Pointer to ATA Opal device information.\r
+\r
+ **/\r
+VOID\r
+OpalDeviceAtaSaveBootScript (\r
+ IN OPAL_DEVICE_ATA *DevInfo\r
+ )\r
+{\r
+ UINTN Bus;\r
+ UINTN Device;\r
+ UINTN Function;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
+ UINTN Offset;\r
+ UINT64 Address;\r
+ S3_BOOT_SCRIPT_LIB_WIDTH Width;\r
+ UINT32 Data;\r
+ OPAL_HC_PCI_REGISTER_SAVE *HcRegisterSaveListPtr;\r
+ UINTN Count;\r
+\r
+ Data = 0;\r
+\r
+ Bus = DevInfo->Device.Bus;\r
+ Device = DevInfo->Device.Device;\r
+ Function = DevInfo->Device.Function;\r
+\r
+ HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *) mSataHcRegisterSaveTemplate;\r
+ Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof (OPAL_HC_PCI_REGISTER_SAVE);\r
+\r
+ for (Index = 0; Index < Count; Index++) {\r
+ Offset = HcRegisterSaveListPtr[Index].Address;\r
+ Width = HcRegisterSaveListPtr[Index].Width;\r
+\r
+ switch (Width) {\r
+ case S3BootScriptWidthUint8:\r
+ Data = (UINT32)PciRead8 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
+ break;\r
+ case S3BootScriptWidthUint16:\r
+ Data = (UINT32)PciRead16 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
+ break;\r
+ case S3BootScriptWidthUint32:\r
+ Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
+ break;\r
+ default:\r
+ ASSERT (FALSE);\r
+ break;\r
+ }\r
+\r
+ Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function, Offset);\r
+ Status = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+}\r
+\r
+/**\r
+ Build ATA OPAL device info and save them to LockBox.\r
+\r
+ @param[in] BarAddr Bar address allocated.\r
+\r
+ **/\r
+VOID\r
+BuildOpalDeviceInfoAta (\r
+ IN UINT32 BarAddr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 DeviceType;\r
+ OPAL_DEVICE_ATA *DevInfoAta;\r
+ OPAL_DEVICE_ATA *TempDevInfoAta;\r
+ UINTN DevInfoLengthAta;\r
+ UINT16 DevInfoLength;\r
+ OPAL_DRIVER_DEVICE *TmpDev;\r
+\r
+ //\r
+ // Build ATA OPAL device info and save them to LockBox.\r
+ //\r
+ DevInfoLengthAta = 0;\r
+ TmpDev = mOpalDriver.DeviceList;\r
+ while (TmpDev != NULL) {\r
+ DeviceType = ExtractDeviceInfoFromDevicePath (\r
+ TmpDev->OpalDisk.OpalDevicePath,\r
+ &DevInfoLength,\r
+ NULL\r
+ );\r
+ if (DeviceType == OPAL_DEVICE_TYPE_ATA) {\r
+ DevInfoLengthAta += DevInfoLength;\r
+ }\r
+\r
+ TmpDev = TmpDev->Next;\r
+ }\r
+\r
+ if (DevInfoLengthAta == 0) {\r
+ return;\r
+ }\r
+\r
+ DevInfoAta = AllocateZeroPool (DevInfoLengthAta);\r
+ ASSERT (DevInfoAta != NULL);\r
+\r
+ TempDevInfoAta = DevInfoAta;\r
+ TmpDev = mOpalDriver.DeviceList;\r
+ while (TmpDev != NULL) {\r
+ DeviceType = ExtractDeviceInfoFromDevicePath (\r
+ TmpDev->OpalDisk.OpalDevicePath,\r
+ &DevInfoLength,\r
+ NULL\r
+ );\r
+ if (DeviceType == OPAL_DEVICE_TYPE_ATA) {\r
+ ExtractDeviceInfoFromDevicePath (\r
+ TmpDev->OpalDisk.OpalDevicePath,\r
+ &DevInfoLength,\r
+ (OPAL_DEVICE_COMMON *) TempDevInfoAta\r
+ );\r
+ TempDevInfoAta->Length = DevInfoLength;\r
+ TempDevInfoAta->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;\r
+ TempDevInfoAta->BarAddr = BarAddr;\r
+ CopyMem (\r
+ TempDevInfoAta->Password,\r
+ TmpDev->OpalDisk.Password,\r
+ TmpDev->OpalDisk.PasswordLength\r
+ );\r
+ TempDevInfoAta->PasswordLength = TmpDev->OpalDisk.PasswordLength;\r
+ OpalDeviceAtaSaveBootScript (TempDevInfoAta);\r
+ TempDevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) TempDevInfoAta + DevInfoLength);\r
+ }\r
+\r
+ TmpDev = TmpDev->Next;\r
+ }\r
+\r
+ Status = SaveLockBox (\r
+ &mOpalDeviceAtaGuid,\r
+ DevInfoAta,\r
+ DevInfoLengthAta\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = SetLockBoxAttributes (\r
+ &mOpalDeviceAtaGuid,\r
+ LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ ZeroMem (DevInfoAta, DevInfoLengthAta);\r
+ FreePool (DevInfoAta);\r
+}\r
+\r
+/**\r
+ Build NVMe OPAL device info and save them to LockBox.\r
+\r
+ @param[in] BarAddr Bar address allocated.\r
+\r
+ **/\r
+VOID\r
+BuildOpalDeviceInfoNvme (\r
+ IN UINT32 BarAddr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 DeviceType;\r
+ OPAL_DEVICE_NVME *DevInfoNvme;\r
+ OPAL_DEVICE_NVME *TempDevInfoNvme;\r
+ UINTN DevInfoLengthNvme;\r
+ UINT16 DevInfoLength;\r
+ OPAL_DRIVER_DEVICE *TmpDev;\r
+\r
+ //\r
+ // Build NVMe OPAL device info and save them to LockBox.\r
+ //\r
+ DevInfoLengthNvme = 0;\r
+ TmpDev = mOpalDriver.DeviceList;\r
+ while (TmpDev != NULL) {\r
+ DeviceType = ExtractDeviceInfoFromDevicePath (\r
+ TmpDev->OpalDisk.OpalDevicePath,\r
+ &DevInfoLength,\r
+ NULL\r
+ );\r
+ if (DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
+ DevInfoLengthNvme += DevInfoLength;\r
+ }\r
+\r
+ TmpDev = TmpDev->Next;\r
+ }\r
+\r
+ if (DevInfoLengthNvme == 0) {\r
+ return;\r
+ }\r
+\r
+ DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);\r
+ ASSERT (DevInfoNvme != NULL);\r
+\r
+ TempDevInfoNvme = DevInfoNvme;\r
+ TmpDev = mOpalDriver.DeviceList;\r
+ while (TmpDev != NULL) {\r
+ DeviceType = ExtractDeviceInfoFromDevicePath (\r
+ TmpDev->OpalDisk.OpalDevicePath,\r
+ &DevInfoLength,\r
+ NULL\r
+ );\r
+ if (DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
+ ExtractDeviceInfoFromDevicePath (\r
+ TmpDev->OpalDisk.OpalDevicePath,\r
+ &DevInfoLength,\r
+ (OPAL_DEVICE_COMMON *) TempDevInfoNvme\r
+ );\r
+ TempDevInfoNvme->Length = DevInfoLength;\r
+ TempDevInfoNvme->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;\r
+ TempDevInfoNvme->BarAddr = BarAddr;\r
+ CopyMem (\r
+ TempDevInfoNvme->Password,\r
+ TmpDev->OpalDisk.Password,\r
+ TmpDev->OpalDisk.PasswordLength\r
+ );\r
+ TempDevInfoNvme->PasswordLength = TmpDev->OpalDisk.PasswordLength;\r
+ TempDevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) TempDevInfoNvme + DevInfoLength);\r
+ }\r
+\r
+ TmpDev = TmpDev->Next;\r
+ }\r
+\r
+ Status = SaveLockBox (\r
+ &mOpalDeviceNvmeGuid,\r
+ DevInfoNvme,\r
+ DevInfoLengthNvme\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = SetLockBoxAttributes (\r
+ &mOpalDeviceNvmeGuid,\r
+ LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ ZeroMem (DevInfoNvme, DevInfoLengthNvme);\r
+ FreePool (DevInfoNvme);\r
+}\r
+\r
+/**\r
+ Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
+\r
+ This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
+\r
+ @param Event Event whose notification function is being invoked.\r
+ @param Context Pointer to the notification function's context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+OpalEndOfDxeEventNotify (\r
+ EFI_EVENT Event,\r
+ VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+ UINT64 Length;\r
+ OPAL_DRIVER_DEVICE *TmpDev;\r
+\r
+ DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
+\r
+ mOpalEndOfDxe = TRUE;\r
+\r
+ if (mOpalRequestVariable != NULL) {\r
+ //\r
+ // Free the OPAL request variable buffer here\r
+ // as the OPAL requests should have been processed.\r
+ //\r
+ FreePool (mOpalRequestVariable);\r
+ mOpalRequestVariable = NULL;\r
+ mOpalRequestVariableSize = 0;\r
+ }\r
+\r
+ //\r
+ // Assume 64K size and alignment are enough.\r
+ //\r
+ Length = 0x10000;\r
+ Address = 0xFFFFFFFF;\r
+ Status = gDS->AllocateMemorySpace (\r
+ EfiGcdAllocateMaxAddressSearchBottomUp,\r
+ EfiGcdMemoryTypeMemoryMappedIo,\r
+ 16, // 2^16: 64K Alignment\r
+ Length,\r
+ &Address,\r
+ gImageHandle,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ BuildOpalDeviceInfoAta ((UINT32) Address);\r
+ BuildOpalDeviceInfoNvme ((UINT32) Address);\r
+\r
+ //\r
+ // Zero passsword.\r
+ //\r
+ TmpDev = mOpalDriver.DeviceList;\r
+ while (TmpDev != NULL) {\r
+ ZeroMem (TmpDev->OpalDisk.Password, TmpDev->OpalDisk.PasswordLength);\r
+ TmpDev = TmpDev->Next;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
+\r
+ gBS->CloseEvent (Event);\r
+}\r
+\r
+/**\r
+ Get Psid input from the popup window.\r
+\r
+ @param[in] Dev The device which need Psid to process Psid Revert\r
+ OPAL request.\r
+ @param[in] PopUpString Pop up string.\r
+ @param[out] PressEsc Whether user escape function through Press ESC.\r
+\r
+ @retval Password string if success. NULL if failed.\r
+\r
+**/\r
+CHAR8 *\r
+OpalDriverPopUpPsidInput (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *PopUpString,\r
+ OUT BOOLEAN *PressEsc\r
+ )\r
+{\r
+ EFI_INPUT_KEY InputKey;\r
+ UINTN InputLength;\r
+ CHAR16 Mask[PSID_CHARACTER_LENGTH + 1];\r
+ CHAR16 Unicode[PSID_CHARACTER_LENGTH + 1];\r
+ CHAR8 *Ascii;\r
+\r
+ ZeroMem(Unicode, sizeof(Unicode));\r
+ ZeroMem(Mask, sizeof(Mask));\r
+\r
+ *PressEsc = FALSE;\r
+\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+\r
+ InputLength = 0;\r
+ while (TRUE) {\r
+ Mask[InputLength] = L'_';\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &InputKey,\r
+ PopUpString,\r
+ L"---------------------",\r
+ Mask,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // Check key.\r
+ //\r
+ if (InputKey.ScanCode == SCAN_NULL) {\r
+ //\r
+ // password finished\r
+ //\r
+ if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ //\r
+ // Add the null terminator.\r
+ //\r
+ Unicode[InputLength] = 0;\r
+ Mask[InputLength] = 0;\r
+ break;\r
+ } else if ((InputKey.UnicodeChar == CHAR_NULL) ||\r
+ (InputKey.UnicodeChar == CHAR_TAB) ||\r
+ (InputKey.UnicodeChar == CHAR_LINEFEED)\r
+ ) {\r
+ continue;\r
+ } else {\r
+ //\r
+ // delete last key entered\r
+ //\r
+ if (InputKey.UnicodeChar == CHAR_BACKSPACE) {\r
+ if (InputLength > 0) {\r
+ Unicode[InputLength] = 0;\r
+ Mask[InputLength] = 0;\r
+ InputLength--;\r
+ }\r
+ } else {\r
+ //\r
+ // add Next key entry\r
+ //\r
+ Unicode[InputLength] = InputKey.UnicodeChar;\r
+ Mask[InputLength] = InputKey.UnicodeChar;\r
+ InputLength++;\r
+ if (InputLength == PSID_CHARACTER_LENGTH) {\r
+ //\r
+ // Add the null terminator.\r
+ //\r
+ Unicode[InputLength] = 0;\r
+ Mask[InputLength] = 0;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // exit on ESC\r
+ //\r
+ if (InputKey.ScanCode == SCAN_ESC) {\r
+ *PressEsc = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+\r
+ if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {\r
+ ZeroMem (Unicode, sizeof (Unicode));\r
+ ZeroMem (Mask, sizeof (Mask));\r
+ return NULL;\r
+ }\r
+\r
+ Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);\r
+ if (Ascii == NULL) {\r
+ ZeroMem (Unicode, sizeof (Unicode));\r
+ ZeroMem (Mask, sizeof (Mask));\r
+ return NULL;\r
+ }\r
+\r
+ UnicodeStrToAsciiStrS (Unicode, Ascii, PSID_CHARACTER_LENGTH + 1);\r
+ ZeroMem (Unicode, sizeof (Unicode));\r
+ ZeroMem (Mask, sizeof (Mask));\r
+\r
+ return Ascii;\r
+}\r
+\r
+\r
+/**\r
+ Get password input from the popup window.\r
+\r
+ @param[in] Dev The device which need password to unlock or\r
+ process OPAL request.\r
+ @param[in] PopUpString1 Pop up string 1.\r
+ @param[in] PopUpString2 Pop up string 2.\r
+ @param[out] PressEsc Whether user escape function through Press ESC.\r
+\r
+ @retval Password string if success. NULL if failed.\r
+\r
+**/\r
+CHAR8 *\r
+OpalDriverPopUpPasswordInput (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *PopUpString1,\r
+ IN CHAR16 *PopUpString2,\r
+ OUT BOOLEAN *PressEsc\r
+ )\r
+{\r
+ EFI_INPUT_KEY InputKey;\r
+ UINTN InputLength;\r
+ CHAR16 Mask[OPAL_MAX_PASSWORD_SIZE + 1];\r
+ CHAR16 Unicode[OPAL_MAX_PASSWORD_SIZE + 1];\r
+ CHAR8 *Ascii;\r
+\r
+ ZeroMem(Unicode, sizeof(Unicode));\r
+ ZeroMem(Mask, sizeof(Mask));\r
+\r
+ *PressEsc = FALSE;\r
+\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+\r
+ InputLength = 0;\r
+ while (TRUE) {\r
+ Mask[InputLength] = L'_';\r
+ if (PopUpString2 == NULL) {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &InputKey,\r
+ PopUpString1,\r
+ L"---------------------",\r
+ Mask,\r
+ NULL\r
+ );\r
+ } else {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &InputKey,\r
+ PopUpString1,\r
+ PopUpString2,\r
+ L"---------------------",\r
+ Mask,\r
+ NULL\r
+ );\r
+ }\r
+\r
+ //\r
+ // Check key.\r
+ //\r
+ if (InputKey.ScanCode == SCAN_NULL) {\r
+ //\r
+ // password finished\r
+ //\r
+ if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ //\r
+ // Add the null terminator.\r
+ //\r
+ Unicode[InputLength] = 0;\r
+ Mask[InputLength] = 0;\r
+ break;\r
+ } else if ((InputKey.UnicodeChar == CHAR_NULL) ||\r
+ (InputKey.UnicodeChar == CHAR_TAB) ||\r
+ (InputKey.UnicodeChar == CHAR_LINEFEED)\r
+ ) {\r
+ continue;\r
+ } else {\r
+ //\r
+ // delete last key entered\r
+ //\r
+ if (InputKey.UnicodeChar == CHAR_BACKSPACE) {\r
+ if (InputLength > 0) {\r
+ Unicode[InputLength] = 0;\r
+ Mask[InputLength] = 0;\r
+ InputLength--;\r
+ }\r
+ } else {\r
+ //\r
+ // add Next key entry\r
+ //\r
+ Unicode[InputLength] = InputKey.UnicodeChar;\r
+ Mask[InputLength] = L'*';\r
+ InputLength++;\r
+ if (InputLength == OPAL_MAX_PASSWORD_SIZE) {\r
+ //\r
+ // Add the null terminator.\r
+ //\r
+ Unicode[InputLength] = 0;\r
+ Mask[InputLength] = 0;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // exit on ESC\r
+ //\r
+ if (InputKey.ScanCode == SCAN_ESC) {\r
+ *PressEsc = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+\r
+ if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {\r
+ ZeroMem (Unicode, sizeof (Unicode));\r
+ return NULL;\r
+ }\r
+\r
+ Ascii = AllocateZeroPool (OPAL_MAX_PASSWORD_SIZE + 1);\r
+ if (Ascii == NULL) {\r
+ ZeroMem (Unicode, sizeof (Unicode));\r
+ return NULL;\r
+ }\r
+\r
+ UnicodeStrToAsciiStrS (Unicode, Ascii, OPAL_MAX_PASSWORD_SIZE + 1);\r
+ ZeroMem (Unicode, sizeof (Unicode));\r
+\r
+ return Ascii;\r
+}\r
+\r
+/**\r
+ Check if disk is locked, show popup window and ask for password if it is.\r
+\r
+ @param[in] Dev The device which need to be unlocked.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+CHAR16 *\r
+OpalGetPopUpString (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINTN StrLength;\r
+\r
+ StrLength = StrLen (RequestString) + 1 + MAX (StrLen (Dev->Name16), StrLen (L"Disk"));\r
+ ASSERT (StrLength < sizeof (mPopUpString) / sizeof (CHAR16));\r
+\r
+ if (Dev->Name16 == NULL) {\r
+ UnicodeSPrint (mPopUpString, StrLength + 1, L"%s Disk", RequestString);\r
+ } else {\r
+ UnicodeSPrint (mPopUpString, StrLength + 1, L"%s %s", RequestString, Dev->Name16);\r
+ }\r
+\r
+ return mPopUpString;\r
+}\r
+\r
+/**\r
+ Check if disk is locked, show popup window and ask for password if it is.\r
+\r
+ @param[in] Dev The device which need to be unlocked.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+VOID\r
+OpalDriverRequestPassword (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINT8 Count;\r
+ BOOLEAN IsEnabled;\r
+ BOOLEAN IsLocked;\r
+ CHAR8 *Password;\r
+ UINT32 PasswordLen;\r
+ OPAL_SESSION Session;\r
+ BOOLEAN PressEsc;\r
+ EFI_INPUT_KEY Key;\r
+ TCG_RESULT Ret;\r
+ CHAR16 *PopUpString;\r
+\r
+ if (Dev == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+\r
+ PopUpString = OpalGetPopUpString (Dev, RequestString);\r
+\r
+ Count = 0;\r
+\r
+ IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);\r
+ if (IsEnabled) {\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+\r
+ IsLocked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);\r
+\r
+ while (Count < MAX_PASSWORD_TRY_COUNT) {\r
+ Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
+ if (PressEsc) {\r
+ if (IsLocked) {\r
+ //\r
+ // Current device in the lock status and\r
+ // User not input password and press ESC,\r
+ // keep device in lock status and continue boot.\r
+ //\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to skip the request and continue boot,",\r
+ L"Press ESC to input password again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ //\r
+ // Keep lock and continue boot.\r
+ //\r
+ return;\r
+ } else {\r
+ //\r
+ // Let user input password again.\r
+ //\r
+ continue;\r
+ }\r
+ } else {\r
+ //\r
+ // Current device in the unlock status and\r
+ // User not input password and press ESC,\r
+ // Shutdown the device.\r
+ //\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to shutdown, Press ESC to input password again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
+ } else {\r
+ //\r
+ // Let user input password again.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Password == NULL) {\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLen = (UINT32) AsciiStrLen(Password);\r
+\r
+ if (IsLocked) {\r
+ Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, FALSE, FALSE);\r
+ } else {\r
+ Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, TRUE, TRUE);\r
+ if (Ret == TcgResultSuccess) {\r
+ Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, FALSE, FALSE);\r
+ }\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
+ DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
+ }\r
+\r
+ if (Password != NULL) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ break;\r
+ }\r
+\r
+ Count++;\r
+\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Invalid password.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+\r
+ if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Opal password retry count exceeds the limit. Must shutdown!",\r
+ L"Press ENTER to shutdown",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+\r
+ gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Process Enable Feature OPAL request.\r
+\r
+ @param[in] Dev The device which has Enable Feature OPAL request.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+VOID\r
+ProcessOpalRequestEnableFeature (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINT8 Count;\r
+ CHAR8 *Password;\r
+ UINT32 PasswordLen;\r
+ CHAR8 *PasswordConfirm;\r
+ UINT32 PasswordLenConfirm;\r
+ OPAL_SESSION Session;\r
+ BOOLEAN PressEsc;\r
+ EFI_INPUT_KEY Key;\r
+ TCG_RESULT Ret;\r
+ CHAR16 *PopUpString;\r
+\r
+ if (Dev == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+\r
+ PopUpString = OpalGetPopUpString (Dev, RequestString);\r
+\r
+ Count = 0;\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+\r
+ while (Count < MAX_PASSWORD_TRY_COUNT) {\r
+ Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);\r
+ if (PressEsc) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to skip the request and continue boot,",\r
+ L"Press ESC to input password again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ return;\r
+ } else {\r
+ //\r
+ // Let user input password again.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Password == NULL) {\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLen = (UINT32) AsciiStrLen(Password);\r
+\r
+ PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);\r
+ if (PasswordConfirm == NULL) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);\r
+ if ((PasswordLen != PasswordLenConfirm) ||\r
+ (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
+ FreePool (PasswordConfirm);\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Passwords are not the same.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ Count ++;\r
+ continue;\r
+ }\r
+\r
+ if (PasswordConfirm != NULL) {\r
+ ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
+ FreePool (PasswordConfirm);\r
+ }\r
+\r
+ Ret = OpalSupportEnableOpalFeature (&Session, Dev->OpalDisk.Msid, Dev->OpalDisk.MsidLength, Password, PasswordLen);\r
+ if (Ret == TcgResultSuccess) {\r
+ OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
+ DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
+ }\r
+\r
+ if (Password != NULL) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ break;\r
+ }\r
+\r
+ Count++;\r
+\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Request failed.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+\r
+ if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Opal password retry count exceeds the limit.",\r
+ L"Press ENTER to skip the request and continue boot",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ }\r
+}\r
+\r
+/**\r
+ Process Disable User OPAL request.\r
+\r
+ @param[in] Dev The device which has Disable User OPAL request.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+VOID\r
+ProcessOpalRequestDisableUser (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINT8 Count;\r
+ CHAR8 *Password;\r
+ UINT32 PasswordLen;\r
+ OPAL_SESSION Session;\r
+ BOOLEAN PressEsc;\r
+ EFI_INPUT_KEY Key;\r
+ TCG_RESULT Ret;\r
+ BOOLEAN PasswordFailed;\r
+ CHAR16 *PopUpString;\r
+\r
+ if (Dev == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+\r
+ PopUpString = OpalGetPopUpString (Dev, RequestString);\r
+\r
+ Count = 0;\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+\r
+ while (Count < MAX_PASSWORD_TRY_COUNT) {\r
+ Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
+ if (PressEsc) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to skip the request and continue boot,",\r
+ L"Press ESC to input password again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ return;\r
+ } else {\r
+ //\r
+ // Let user input password again.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Password == NULL) {\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLen = (UINT32) AsciiStrLen(Password);\r
+\r
+ Ret = OpalUtilDisableUser(&Session, Password, PasswordLen, &PasswordFailed);\r
+ if (Ret == TcgResultSuccess) {\r
+ OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
+ DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
+ }\r
+\r
+ if (Password != NULL) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ break;\r
+ }\r
+\r
+ Count++;\r
+\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Invalid password, request failed.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+\r
+ if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Opal password retry count exceeds the limit.",\r
+ L"Press ENTER to skip the request and continue boot",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ }\r
+}\r
+\r
+/**\r
+ Process Psid Revert OPAL request.\r
+\r
+ @param[in] Dev The device which has Psid Revert OPAL request.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+VOID\r
+ProcessOpalRequestPsidRevert (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINT8 Count;\r
+ CHAR8 *Psid;\r
+ UINT32 PsidLen;\r
+ OPAL_SESSION Session;\r
+ BOOLEAN PressEsc;\r
+ EFI_INPUT_KEY Key;\r
+ TCG_RESULT Ret;\r
+ CHAR16 *PopUpString;\r
+\r
+ if (Dev == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+\r
+ PopUpString = OpalGetPopUpString (Dev, RequestString);\r
+\r
+ Count = 0;\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+\r
+ while (Count < MAX_PSID_TRY_COUNT) {\r
+ Psid = OpalDriverPopUpPsidInput (Dev, PopUpString, &PressEsc);\r
+ if (PressEsc) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to skip the request and continue boot,",\r
+ L"Press ESC to input Psid again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ return;\r
+ } else {\r
+ //\r
+ // Let user input Psid again.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Psid == NULL) {\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PsidLen = (UINT32) AsciiStrLen(Psid);\r
+\r
+ Ret = OpalUtilPsidRevert(&Session, Psid, PsidLen);\r
+ if (Ret == TcgResultSuccess) {\r
+ DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
+ }\r
+\r
+ if (Psid != NULL) {\r
+ ZeroMem (Psid, PsidLen);\r
+ FreePool (Psid);\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ break;\r
+ }\r
+\r
+ Count++;\r
+\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Invalid Psid, request failed.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+\r
+ if (Count >= MAX_PSID_TRY_COUNT) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Opal Psid retry count exceeds the limit.",\r
+ L"Press ENTER to skip the request and continue boot",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ }\r
+}\r
+\r
+/**\r
+ Process Admin Revert OPAL request.\r
+\r
+ @param[in] Dev The device which has Revert OPAL request.\r
+ @param[in] KeepUserData Whether to keep user data or not.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+VOID\r
+ProcessOpalRequestRevert (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN BOOLEAN KeepUserData,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINT8 Count;\r
+ CHAR8 *Password;\r
+ UINT32 PasswordLen;\r
+ OPAL_SESSION Session;\r
+ BOOLEAN PressEsc;\r
+ EFI_INPUT_KEY Key;\r
+ TCG_RESULT Ret;\r
+ BOOLEAN PasswordFailed;\r
+ CHAR16 *PopUpString;\r
+\r
+ if (Dev == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+\r
+ PopUpString = OpalGetPopUpString (Dev, RequestString);\r
+\r
+ Count = 0;\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+\r
+ while (Count < MAX_PASSWORD_TRY_COUNT) {\r
+ Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
+ if (PressEsc) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to skip the request and continue boot,",\r
+ L"Press ESC to input password again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ return;\r
+ } else {\r
+ //\r
+ // Let user input password again.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Password == NULL) {\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLen = (UINT32) AsciiStrLen(Password);\r
+\r
+ if ((Dev->OpalDisk.SupportedAttributes.PyriteSsc == 1) &&\r
+ (Dev->OpalDisk.LockingFeature.MediaEncryption == 0)) {\r
+ //\r
+ // For pyrite type device which does not support media encryption,\r
+ // it does not accept "Keep User Data" parameter.\r
+ // So here hardcode a FALSE for this case.\r
+ //\r
+ Ret = OpalUtilRevert(\r
+ &Session,\r
+ FALSE,\r
+ Password,\r
+ PasswordLen,\r
+ &PasswordFailed,\r
+ Dev->OpalDisk.Msid,\r
+ Dev->OpalDisk.MsidLength\r
+ );\r
+ } else {\r
+ Ret = OpalUtilRevert(\r
+ &Session,\r
+ KeepUserData,\r
+ Password,\r
+ PasswordLen,\r
+ &PasswordFailed,\r
+ Dev->OpalDisk.Msid,\r
+ Dev->OpalDisk.MsidLength\r
+ );\r
+ }\r
+ if (Ret == TcgResultSuccess) {\r
+ OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
+ DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
+ }\r
+\r
+ if (Password != NULL) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ break;\r
+ }\r
+\r
+ Count++;\r
+\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Invalid password, request failed.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+\r
+ if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Opal password retry count exceeds the limit.",\r
+ L"Press ENTER to skip the request and continue boot",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ }\r
+}\r
+\r
+/**\r
+ Process Secure Erase OPAL request.\r
+\r
+ @param[in] Dev The device which has Secure Erase OPAL request.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+VOID\r
+ProcessOpalRequestSecureErase (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINT8 Count;\r
+ CHAR8 *Password;\r
+ UINT32 PasswordLen;\r
+ OPAL_SESSION Session;\r
+ BOOLEAN PressEsc;\r
+ EFI_INPUT_KEY Key;\r
+ TCG_RESULT Ret;\r
+ BOOLEAN PasswordFailed;\r
+ CHAR16 *PopUpString;\r
+\r
+ if (Dev == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+\r
+ PopUpString = OpalGetPopUpString (Dev, RequestString);\r
+\r
+ Count = 0;\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+\r
+ while (Count < MAX_PASSWORD_TRY_COUNT) {\r
+ Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
+ if (PressEsc) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to skip the request and continue boot,",\r
+ L"Press ESC to input password again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ return;\r
+ } else {\r
+ //\r
+ // Let user input password again.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (Password == NULL) {\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLen = (UINT32) AsciiStrLen(Password);\r
+\r
+ Ret = OpalUtilSecureErase(&Session, Password, PasswordLen, &PasswordFailed);\r
+ if (Ret == TcgResultSuccess) {\r
+ OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
+ DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
+ }\r
+\r
+ if (Password != NULL) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ break;\r
+ }\r
+\r
+ Count++;\r
+\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Invalid password, request failed.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+\r
+ if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Opal password retry count exceeds the limit.",\r
+ L"Press ENTER to skip the request and continue boot",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ }\r
+}\r
+\r
+/**\r
+ Process Set Admin Pwd OPAL request.\r
+\r
+ @param[in] Dev The device which has Set Admin Pwd Feature OPAL request.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+VOID\r
+ProcessOpalRequestSetUserPwd (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINT8 Count;\r
+ CHAR8 *OldPassword;\r
+ UINT32 OldPasswordLen;\r
+ CHAR8 *Password;\r
+ UINT32 PasswordLen;\r
+ CHAR8 *PasswordConfirm;\r
+ UINT32 PasswordLenConfirm;\r
+ OPAL_SESSION Session;\r
+ BOOLEAN PressEsc;\r
+ EFI_INPUT_KEY Key;\r
+ TCG_RESULT Ret;\r
+ CHAR16 *PopUpString;\r
+\r
+ if (Dev == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+\r
+ PopUpString = OpalGetPopUpString (Dev, RequestString);\r
+\r
+ Count = 0;\r
+\r
+ while (Count < MAX_PASSWORD_TRY_COUNT) {\r
+ OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);\r
+ if (PressEsc) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to skip the request and continue boot,",\r
+ L"Press ESC to input password again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ return;\r
+ } else {\r
+ //\r
+ // Let user input password again.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (OldPassword == NULL) {\r
+ Count ++;\r
+ continue;\r
+ }\r
+ OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+ Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_USER1_AUTHORITY);\r
+ if (Ret == TcgResultSuccess) {\r
+ DEBUG ((DEBUG_INFO, "Verify with USER1 authority : Success\n"));\r
+ } else {\r
+ Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);\r
+ if (Ret == TcgResultSuccess) {\r
+ DEBUG ((DEBUG_INFO, "Verify with ADMIN1 authority: Success\n"));\r
+ } else {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ DEBUG ((DEBUG_INFO, "Verify: Failure\n"));\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Incorrect password.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ Count ++;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);\r
+ if (Password == NULL) {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLen = (UINT32) AsciiStrLen(Password);\r
+\r
+ PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);\r
+ if (PasswordConfirm == NULL) {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);\r
+ if ((PasswordLen != PasswordLenConfirm) ||\r
+ (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
+ FreePool (PasswordConfirm);\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Passwords are not the same.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ Count ++;\r
+ continue;\r
+ }\r
+\r
+ if (PasswordConfirm != NULL) {\r
+ ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
+ FreePool (PasswordConfirm);\r
+ }\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+ Ret = OpalUtilSetUserPassword(\r
+ &Session,\r
+ OldPassword,\r
+ OldPasswordLen,\r
+ Password,\r
+ PasswordLen\r
+ );\r
+ if (Ret == TcgResultSuccess) {\r
+ OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
+ DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
+ }\r
+\r
+ if (OldPassword != NULL) {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ }\r
+\r
+ if (Password != NULL) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ break;\r
+ }\r
+\r
+ Count++;\r
+\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Request failed.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+\r
+ if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Opal password retry count exceeds the limit.",\r
+ L"Press ENTER to skip the request and continue boot",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ }\r
+}\r
+\r
+/**\r
+ Process Set Admin Pwd OPAL request.\r
+\r
+ @param[in] Dev The device which has Set Admin Pwd Feature OPAL request.\r
+ @param[in] RequestString Request string.\r
+\r
+**/\r
+VOID\r
+ProcessOpalRequestSetAdminPwd (\r
+ IN OPAL_DRIVER_DEVICE *Dev,\r
+ IN CHAR16 *RequestString\r
+ )\r
+{\r
+ UINT8 Count;\r
+ CHAR8 *OldPassword;\r
+ UINT32 OldPasswordLen;\r
+ CHAR8 *Password;\r
+ UINT32 PasswordLen;\r
+ CHAR8 *PasswordConfirm;\r
+ UINT32 PasswordLenConfirm;\r
+ OPAL_SESSION Session;\r
+ BOOLEAN PressEsc;\r
+ EFI_INPUT_KEY Key;\r
+ TCG_RESULT Ret;\r
+ CHAR16 *PopUpString;\r
+\r
+ if (Dev == NULL) {\r
+ return;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
+\r
+ PopUpString = OpalGetPopUpString (Dev, RequestString);\r
+\r
+ Count = 0;\r
+\r
+ while (Count < MAX_PASSWORD_TRY_COUNT) {\r
+ OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);\r
+ if (PressEsc) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Press ENTER to skip the request and continue boot,",\r
+ L"Press ESC to input password again",\r
+ NULL\r
+ );\r
+ } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
+\r
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ return;\r
+ } else {\r
+ //\r
+ // Let user input password again.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (OldPassword == NULL) {\r
+ Count ++;\r
+ continue;\r
+ }\r
+ OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+ Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);\r
+ if (Ret == TcgResultSuccess) {\r
+ DEBUG ((DEBUG_INFO, "Verify: Success\n"));\r
+ } else {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ DEBUG ((DEBUG_INFO, "Verify: Failure\n"));\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Incorrect password.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ Count ++;\r
+ continue;\r
+ }\r
+\r
+ Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);\r
+ if (Password == NULL) {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLen = (UINT32) AsciiStrLen(Password);\r
+\r
+ PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);\r
+ if (PasswordConfirm == NULL) {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ Count ++;\r
+ continue;\r
+ }\r
+ PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);\r
+ if ((PasswordLen != PasswordLenConfirm) ||\r
+ (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
+ FreePool (PasswordConfirm);\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Passwords are not the same.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ Count ++;\r
+ continue;\r
+ }\r
+\r
+ if (PasswordConfirm != NULL) {\r
+ ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
+ FreePool (PasswordConfirm);\r
+ }\r
+\r
+\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Dev->OpalDisk.Sscp;\r
+ Session.MediaId = Dev->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
+ Ret = OpalUtilSetAdminPassword(\r
+ &Session,\r
+ OldPassword,\r
+ OldPasswordLen,\r
+ Password,\r
+ PasswordLen\r
+ );\r
+ if (Ret == TcgResultSuccess) {\r
+ OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
+ DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
+ }\r
+\r
+ if (OldPassword != NULL) {\r
+ ZeroMem (OldPassword, OldPasswordLen);\r
+ FreePool (OldPassword);\r
+ }\r
+\r
+ if (Password != NULL) {\r
+ ZeroMem (Password, PasswordLen);\r
+ FreePool (Password);\r
+ }\r
+\r
+ if (Ret == TcgResultSuccess) {\r
+ break;\r
+ }\r
+\r
+ Count++;\r
+\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Request failed.",\r
+ L"Press ENTER to retry",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ }\r
+\r
+ if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
+ do {\r
+ CreatePopUp (\r
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
+ &Key,\r
+ L"Opal password retry count exceeds the limit.",\r
+ L"Press ENTER to skip the request and continue boot",\r
+ NULL\r
+ );\r
+ } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
+ gST->ConOut->ClearScreen(gST->ConOut);\r
+ }\r
+}\r
+\r
+/**\r
+ Process OPAL request.\r
+\r
+ @param[in] Dev The device which has OPAL request.\r
+\r
+**/\r
+VOID\r
+ProcessOpalRequest (\r
+ IN OPAL_DRIVER_DEVICE *Dev\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ OPAL_REQUEST_VARIABLE *TempVariable;\r
+ OPAL_REQUEST_VARIABLE *Variable;\r
+ UINTN VariableSize;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathInVariable;\r
+ UINTN DevicePathSizeInVariable;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINTN DevicePathSize;\r
+ BOOLEAN KeepUserData;\r
+\r
+ DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
+\r
+ if (mOpalRequestVariable == NULL) {\r
+ Status = GetVariable2 (\r
+ OPAL_REQUEST_VARIABLE_NAME,\r
+ &gHiiSetupVariableGuid,\r
+ (VOID **) &Variable,\r
+ &VariableSize\r
+ );\r
+ if (EFI_ERROR (Status) || (Variable == NULL)) {\r
+ return;\r
+ }\r
+ mOpalRequestVariable = Variable;\r
+ mOpalRequestVariableSize = VariableSize;\r
+\r
+ //\r
+ // Delete the OPAL request variable.\r
+ //\r
+ Status = gRT->SetVariable (\r
+ OPAL_REQUEST_VARIABLE_NAME,\r
+ (EFI_GUID *) &gHiiSetupVariableGuid,\r
+ 0,\r
+ 0,\r
+ NULL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ Variable = mOpalRequestVariable;\r
+ VariableSize = mOpalRequestVariableSize;\r
+ }\r
+\r
+ //\r
+ // Process the OPAL requests.\r
+ //\r
+ TempVariable = Variable;\r
+ while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&\r
+ (VariableSize >= TempVariable->Length) &&\r
+ (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {\r
+ DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));\r
+ DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);\r
+ DevicePath = Dev->OpalDisk.OpalDevicePath;\r
+ DevicePathSize = GetDevicePathSize (DevicePath);\r
+ if ((DevicePathSize == DevicePathSizeInVariable) &&\r
+ (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) {\r
+ //\r
+ // Found the node for the OPAL device.\r
+ //\r
+ if (TempVariable->OpalRequest.SetAdminPwd != 0) {\r
+ ProcessOpalRequestSetAdminPwd (Dev, L"Update Admin Pwd:");\r
+ }\r
+ if (TempVariable->OpalRequest.SetUserPwd != 0) {\r
+ ProcessOpalRequestSetUserPwd (Dev, L"Set User Pwd:");\r
+ }\r
+ if (TempVariable->OpalRequest.SecureErase!= 0) {\r
+ ProcessOpalRequestSecureErase (Dev, L"Secure Erase:");\r
+ }\r
+ if (TempVariable->OpalRequest.Revert != 0) {\r
+ KeepUserData = (BOOLEAN) TempVariable->OpalRequest.KeepUserData;\r
+ ProcessOpalRequestRevert (\r
+ Dev,\r
+ KeepUserData,\r
+ KeepUserData ? L"Admin Revert(keep):" : L"Admin Revert:"\r
+ );\r
+ }\r
+ if (TempVariable->OpalRequest.PsidRevert != 0) {\r
+ ProcessOpalRequestPsidRevert (Dev, L"Psid Revert:");\r
+ }\r
+ if (TempVariable->OpalRequest.DisableUser != 0) {\r
+ ProcessOpalRequestDisableUser (Dev, L"Disable User:");\r
+ }\r
+ if (TempVariable->OpalRequest.EnableFeature != 0) {\r
+ ProcessOpalRequestEnableFeature (Dev, L"Enable Feature:");\r
+ }\r
+\r
+ break;\r
+ }\r
+\r
+ VariableSize -= TempVariable->Length;\r
+ TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length);\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
+}\r
+\r
+/**\r
+ Add new device to the global device list.\r
+\r
+ @param Dev New create device.\r
+\r
+**/\r
+VOID\r
+AddDeviceToTail(\r
+ IN OPAL_DRIVER_DEVICE *Dev\r
+ )\r
+{\r
+ OPAL_DRIVER_DEVICE *TmpDev;\r
+\r
+ if (mOpalDriver.DeviceList == NULL) {\r
+ mOpalDriver.DeviceList = Dev;\r
+ } else {\r
+ TmpDev = mOpalDriver.DeviceList;\r
+ while (TmpDev->Next != NULL) {\r
+ TmpDev = TmpDev->Next;\r
+ }\r
+\r
+ TmpDev->Next = Dev;\r
+ }\r
+}\r
+\r
+/**\r
+ Remove one device in the global device list.\r
+\r
+ @param Dev The device need to be removed.\r
+\r
+**/\r
+VOID\r
+RemoveDevice (\r
+ IN OPAL_DRIVER_DEVICE *Dev\r
+ )\r
+{\r
+ OPAL_DRIVER_DEVICE *TmpDev;\r
+\r
+ if (mOpalDriver.DeviceList == NULL) {\r
+ return;\r
+ }\r
+\r
+ if (mOpalDriver.DeviceList == Dev) {\r
+ mOpalDriver.DeviceList = NULL;\r
+ return;\r
+ }\r
+\r
+ TmpDev = mOpalDriver.DeviceList;\r
+ while (TmpDev->Next != NULL) {\r
+ if (TmpDev->Next == Dev) {\r
+ TmpDev->Next = Dev->Next;\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Get current device count.\r
+\r
+ @retval return the current created device count.\r
+\r
+**/\r
+UINT8\r
+GetDeviceCount (\r
+ VOID\r
+ )\r
+{\r
+ UINT8 Count;\r
+ OPAL_DRIVER_DEVICE *TmpDev;\r
+\r
+ Count = 0;\r
+ TmpDev = mOpalDriver.DeviceList;\r
+\r
+ while (TmpDev != NULL) {\r
+ Count++;\r
+ TmpDev = TmpDev->Next;\r
+ }\r
+\r
+ return Count;\r
+}\r
+\r
+/**\r
+ Get devcie list info.\r
+\r
+ @retval return the device list pointer.\r
+**/\r
+OPAL_DRIVER_DEVICE*\r
+OpalDriverGetDeviceList(\r
+ VOID\r
+ )\r
+{\r
+ return mOpalDriver.DeviceList;\r
+}\r
+\r
+/**\r
+ ReadyToBoot callback to send BlockSid command.\r
+\r
+ @param Event Pointer to this event\r
+ @param Context Event handler private Data\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ReadyToBootCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ OPAL_DRIVER_DEVICE *Itr;\r
+ TCG_RESULT Result;\r
+ OPAL_SESSION Session;\r
+ UINT32 PpStorageFlag;\r
+\r
+ gBS->CloseEvent (Event);\r
+\r
+ PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();\r
+ if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {\r
+ //\r
+ // Send BlockSID command to each Opal disk\r
+ //\r
+ Itr = mOpalDriver.DeviceList;\r
+ while (Itr != NULL) {\r
+ if (Itr->OpalDisk.SupportedAttributes.BlockSid) {\r
+ ZeroMem(&Session, sizeof(Session));\r
+ Session.Sscp = Itr->OpalDisk.Sscp;\r
+ Session.MediaId = Itr->OpalDisk.MediaId;\r
+ Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;\r
+\r
+ Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE\r
+ if (Result != TcgResultSuccess) {\r
+ DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));\r
+ break;\r
+ }\r
+ }\r
+\r
+ Itr = Itr->Next;\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Stop this Controller.\r
+\r
+ @param Dev The device need to be stopped.\r
+\r
+**/\r
+VOID\r
+OpalDriverStopDevice (\r
+ OPAL_DRIVER_DEVICE *Dev\r
+ )\r
+{\r
+ //\r
+ // free each name\r
+ //\r
+ FreePool(Dev->Name16);\r
+\r
+ //\r
+ // remove OPAL_DRIVER_DEVICE from the list\r
+ // it updates the controllerList pointer\r
+ //\r
+ RemoveDevice(Dev);\r
+\r
+ //\r
+ // close protocols that were opened\r
+ //\r
+ gBS->CloseProtocol(\r
+ Dev->Handle,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ gOpalDriverBinding.DriverBindingHandle,\r
+ Dev->Handle\r
+ );\r
+\r
+ gBS->CloseProtocol(\r
+ Dev->Handle,\r
+ &gEfiBlockIoProtocolGuid,\r
+ gOpalDriverBinding.DriverBindingHandle,\r
+ Dev->Handle\r
+ );\r
+\r
+ FreePool(Dev);\r
+}\r
+\r
+/**\r
+ Get devcie name through the component name protocol.\r
+\r
+ @param[in] AllHandlesBuffer The handle buffer for current system.\r
+ @param[in] NumAllHandles The number of handles for the handle buffer.\r
+ @param[in] Dev The device which need to get name.\r
+ @param[in] UseComp1 Whether use component name or name2 protocol.\r
+\r
+ @retval TRUE Find the name for this device.\r
+ @retval FALSE Not found the name for this device.\r
+**/\r
+BOOLEAN\r
+OpalDriverGetDeviceNameByProtocol(\r
+ EFI_HANDLE *AllHandlesBuffer,\r
+ UINTN NumAllHandles,\r
+ OPAL_DRIVER_DEVICE *Dev,\r
+ BOOLEAN UseComp1\r
+ )\r
+{\r
+ EFI_HANDLE* ProtocolHandlesBuffer;\r
+ UINTN NumProtocolHandles;\r
+ EFI_STATUS Status;\r
+ EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout\r
+ EFI_GUID Protocol;\r
+ UINTN StrLength;\r
+ EFI_DEVICE_PATH_PROTOCOL* TmpDevPath;\r
+ UINTN Index1;\r
+ UINTN Index2;\r
+ EFI_HANDLE TmpHandle;\r
+ CHAR16 *DevName;\r
+\r
+ if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;\r
+\r
+ //\r
+ // Find all EFI_HANDLES with protocol\r
+ //\r
+ Status = gBS->LocateHandleBuffer(\r
+ ByProtocol,\r
+ &Protocol,\r
+ NULL,\r
+ &NumProtocolHandles,\r
+ &ProtocolHandlesBuffer\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return FALSE;\r
+ }\r
+\r
+\r
+ //\r
+ // Exit early if no supported devices\r
+ //\r
+ if (NumProtocolHandles == 0) {\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Get printable name by iterating through all protocols\r
+ // using the handle as the child, and iterate through all handles for the controller\r
+ // exit loop early once found, if not found, then delete device\r
+ // storage security protocol instances already exist, add them to internal list\r
+ //\r
+ Status = EFI_DEVICE_ERROR;\r
+ for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {\r
+ DevName = NULL;\r
+\r
+ if (Dev->Name16 != NULL) {\r
+ return TRUE;\r
+ }\r
+\r
+ TmpHandle = ProtocolHandlesBuffer[Index1];\r
+\r
+ Status = gBS->OpenProtocol(\r
+ TmpHandle,\r
+ &Protocol,\r
+ (VOID**)&Cnp1_2,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR(Status) || Cnp1_2 == NULL) {\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Use all handles array as controller handle\r
+ //\r
+ for (Index2 = 0; Index2 < NumAllHandles; Index2++) {\r
+ Status = Cnp1_2->GetControllerName(\r
+ Cnp1_2,\r
+ AllHandlesBuffer[Index2],\r
+ Dev->Handle,\r
+ LANGUAGE_ISO_639_2_ENGLISH,\r
+ &DevName\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ Status = Cnp1_2->GetControllerName(\r
+ Cnp1_2,\r
+ AllHandlesBuffer[Index2],\r
+ Dev->Handle,\r
+ LANGUAGE_RFC_3066_ENGLISH,\r
+ &DevName\r
+ );\r
+ }\r
+ if (!EFI_ERROR(Status) && DevName != NULL) {\r
+ StrLength = StrLen(DevName) + 1; // Add one for NULL terminator\r
+ Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));\r
+ ASSERT (Dev->Name16 != NULL);\r
+ StrCpyS (Dev->Name16, StrLength, DevName);\r
+ Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);\r
+ UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);\r
+\r
+ //\r
+ // Retrieve bridge BDF info and port number or namespace depending on type\r
+ //\r
+ TmpDevPath = NULL;\r
+ Status = gBS->OpenProtocol(\r
+ Dev->Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID**)&TmpDevPath,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);\r
+ return TRUE;\r
+ }\r
+\r
+ if (Dev->Name16 != NULL) {\r
+ FreePool(Dev->Name16);\r
+ Dev->Name16 = NULL;\r
+ }\r
+ if (Dev->NameZ != NULL) {\r
+ FreePool(Dev->NameZ);\r
+ Dev->NameZ = NULL;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ return FALSE;\r
+}\r
+\r
+/**\r
+ Get devcie name through the component name protocol.\r
+\r
+ @param[in] Dev The device which need to get name.\r
+\r
+ @retval TRUE Find the name for this device.\r
+ @retval FALSE Not found the name for this device.\r
+**/\r
+BOOLEAN\r
+OpalDriverGetDriverDeviceName(\r
+ OPAL_DRIVER_DEVICE *Dev\r
+ )\r
+{\r
+ EFI_HANDLE* AllHandlesBuffer;\r
+ UINTN NumAllHandles;\r
+ EFI_STATUS Status;\r
+\r
+ if (Dev == NULL) {\r
+ DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Iterate through ComponentName2 handles to get name, if fails, try ComponentName\r
+ //\r
+ if (Dev->Name16 == NULL) {\r
+ DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));\r
+ //\r
+ // Find all EFI_HANDLES\r
+ //\r
+ Status = gBS->LocateHandleBuffer(\r
+ AllHandles,\r
+ NULL,\r
+ NULL,\r
+ &NumAllHandles,\r
+ &AllHandlesBuffer\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));\r
+ return FALSE;\r
+ }\r
+\r
+ //\r
+ // Try component Name2\r
+ //\r
+ if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {\r
+ DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));\r
+ if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {\r
+ DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));\r
+ return FALSE;\r
+ }\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Main entry for this driver.\r
+\r
+ @param ImageHandle Image Handle this driver.\r
+ @param SystemTable Pointer to SystemTable.\r
+\r
+ @retval EFI_SUCESS This function always complete successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDriverEntryPoint(\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE* SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_EVENT ReadyToBootEvent;\r
+ EFI_EVENT EndOfDxeEvent;\r
+\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gOpalDriverBinding,\r
+ ImageHandle,\r
+ &gOpalComponentName,\r
+ &gOpalComponentName2\r
+ );\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));\r
+ return Status ;\r
+ }\r
+\r
+ //\r
+ // Initialize Driver object\r
+ //\r
+ ZeroMem(&mOpalDriver, sizeof(mOpalDriver));\r
+ mOpalDriver.Handle = ImageHandle;\r
+\r
+ Status = gBS->CreateEventEx (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_CALLBACK,\r
+ OpalEndOfDxeEventNotify,\r
+ NULL,\r
+ &gEfiEndOfDxeEventGroupGuid,\r
+ &EndOfDxeEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // register a ReadyToBoot event callback for sending BlockSid command\r
+ //\r
+ Status = EfiCreateEventReadyToBootEx (\r
+ TPL_CALLBACK,\r
+ ReadyToBootCallback,\r
+ (VOID *) &ImageHandle,\r
+ &ReadyToBootEvent\r
+ );\r
+\r
+ //\r
+ // Install Hii packages.\r
+ //\r
+ HiiInstall();\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Tests to see if this driver supports a given controller.\r
+\r
+ This function checks to see if the controller contains an instance of the\r
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL\r
+ and returns EFI_SUCCESS if it does.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The Handle of the controller to test. This Handle\r
+ must support a protocol interface that supplies\r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath This parameter is ignored.\r
+\r
+ @retval EFI_SUCCESS The device contains required protocols\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device does not contain requires protocols\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OpalEfiDriverBindingSupported(\r
+ IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_STORAGE_SECURITY_COMMAND_PROTOCOL* SecurityCommand;\r
+ EFI_BLOCK_IO_PROTOCOL* BlkIo;\r
+\r
+ if (mOpalEndOfDxe) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.\r
+ //\r
+ Status = gBS->OpenProtocol(\r
+ Controller,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ ( VOID ** )&SecurityCommand,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (Status == EFI_ALREADY_STARTED) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Close protocol and reopen in Start call\r
+ //\r
+ gBS->CloseProtocol(\r
+ Controller,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ //\r
+ // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
+ // function APIs\r
+ //\r
+ Status = gBS->OpenProtocol(\r
+ Controller,\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **)&BlkIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Close protocol and reopen in Start call\r
+ //\r
+ gBS->CloseProtocol(\r
+ Controller,\r
+ &gEfiBlockIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Enables Opal Management on a supported device if available.\r
+\r
+ The start function is designed to be called after the Opal UEFI Driver has confirmed the\r
+ "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.\r
+ This function will complete the other necessary checks, such as verifying the device supports\r
+ the correct version of Opal. Upon verification, it will add the device to the\r
+ Opal HII list in order to expose Opal managmeent options.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The Handle of the controller to start. This Handle\r
+ must support a protocol interface that supplies\r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
+ parameter is ignored by device drivers, and is optional for bus\r
+ drivers. For a bus driver, if this parameter is NULL, then handles\r
+ for all the children of Controller are created by this driver.\r
+ If this parameter is not NULL and the first Device Path Node is\r
+ not the End of Device Path Node, then only the Handle for the\r
+ child device specified by the first Device Path Node of\r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is\r
+ the End of Device Path Node, no child Handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS Opal management was enabled.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failed to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OpalEfiDriverBindingStart(\r
+ IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
+ OPAL_DRIVER_DEVICE *Dev;\r
+ OPAL_DRIVER_DEVICE *Itr;\r
+ BOOLEAN Result;\r
+\r
+ Itr = mOpalDriver.DeviceList;\r
+ while (Itr != NULL) {\r
+ if (Controller == Itr->Handle) {\r
+ return EFI_SUCCESS;\r
+ }\r
+ Itr = Itr->Next;\r
+ }\r
+\r
+ //\r
+ // Create internal device for tracking. This allows all disks to be tracked\r
+ // by same HII form\r
+ //\r
+ Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));\r
+ if (Dev == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Dev->Handle = Controller;\r
+\r
+ //\r
+ // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks\r
+ //\r
+ Status = gBS->OpenProtocol(\r
+ Controller,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ (VOID **)&Dev->Sscp,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ FreePool(Dev);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
+ // function APIs\r
+ //\r
+ Status = gBS->OpenProtocol(\r
+ Controller,\r
+ &gEfiBlockIoProtocolGuid,\r
+ (VOID **)&BlkIo,\r
+ This->DriverBindingHandle,\r
+ Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ //\r
+ // Close storage security that was opened\r
+ //\r
+ gBS->CloseProtocol(\r
+ Controller,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ FreePool(Dev);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Save mediaId\r
+ //\r
+ Dev->MediaId = BlkIo->Media->MediaId;\r
+\r
+ gBS->CloseProtocol(\r
+ Controller,\r
+ &gEfiBlockIoProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ //\r
+ // Acquire Ascii printable name of child, if not found, then ignore device\r
+ //\r
+ Result = OpalDriverGetDriverDeviceName (Dev);\r
+ if (!Result) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = OpalDiskInitialize (Dev);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ AddDeviceToTail(Dev);\r
+\r
+ //\r
+ // Check if device is locked and prompt for password.\r
+ //\r
+ OpalDriverRequestPassword (Dev, L"Unlock:");\r
+\r
+ //\r
+ // Process OPAL request from last boot.\r
+ //\r
+ ProcessOpalRequest (Dev);\r
+\r
+ return EFI_SUCCESS;\r
+\r
+Done:\r
+ //\r
+ // free device, close protocols and exit\r
+ //\r
+ gBS->CloseProtocol(\r
+ Controller,\r
+ &gEfiStorageSecurityCommandProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Controller\r
+ );\r
+\r
+ FreePool(Dev);\r
+\r
+ return EFI_DEVICE_ERROR;\r
+}\r
+\r
+/**\r
+ Stop this driver on Controller.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Controller Handle of device to stop driver on\r
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
+ children is zero stop the entire bus driver.\r
+ @param ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+ @retval EFI_SUCCESS This driver is removed Controller.\r
+ @retval other This driver could not be removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OpalEfiDriverBindingStop(\r
+ EFI_DRIVER_BINDING_PROTOCOL* This,\r
+ EFI_HANDLE Controller,\r
+ UINTN NumberOfChildren,\r
+ EFI_HANDLE* ChildHandleBuffer\r
+ )\r
+{\r
+ OPAL_DRIVER_DEVICE* Itr;\r
+\r
+ Itr = mOpalDriver.DeviceList;\r
+\r
+ //\r
+ // does Controller match any of the devices we are managing for Opal\r
+ //\r
+ while (Itr != NULL) {\r
+ if (Itr->Handle == Controller) {\r
+ OpalDriverStopDevice (Itr);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Itr = Itr->Next;\r
+ }\r
+\r
+ return EFI_NOT_FOUND;\r
+}\r
+\r
+\r
+/**\r
+ Unloads UEFI Driver. Very useful for debugging and testing.\r
+\r
+ @param ImageHandle Image Handle this driver.\r
+\r
+ @retval EFI_SUCCESS This function always complete successfully.\r
+ @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+OpalEfiDriverUnload (\r
+ IN EFI_HANDLE ImageHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ OPAL_DRIVER_DEVICE *Itr;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (ImageHandle != gImageHandle) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
+ //\r
+ // Uninstall any interface added to each device by us\r
+ //\r
+ while (mOpalDriver.DeviceList) {\r
+ Itr = mOpalDriver.DeviceList;\r
+ //\r
+ // Remove OPAL_DRIVER_DEVICE from the list\r
+ // it updates the controllerList pointer\r
+ //\r
+ OpalDriverStopDevice(Itr);\r
+ }\r
+\r
+ //\r
+ // Uninstall the HII capability\r
+ //\r
+ Status = HiiUninstall();\r
+\r
+ return Status;\r
+}\r
+\r