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
+Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\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
+EFI_GUID mOpalDeviceLockBoxGuid = OPAL_DEVICE_LOCKBOX_GUID;\r
\r
BOOLEAN mOpalEndOfDxe = FALSE;\r
OPAL_REQUEST_VARIABLE *mOpalRequestVariable = NULL;\r
UINTN mOpalRequestVariableSize = 0;\r
CHAR16 mPopUpString[100];\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
@param[out] DevInfoLength Device information length needed.\r
@param[out] DevInfo Device information extracted.\r
\r
- @return Device type.\r
-\r
**/\r
-UINT8\r
+VOID\r
ExtractDeviceInfoFromDevicePath (\r
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
- OUT UINT16 *DevInfoLength,\r
- OUT OPAL_DEVICE_COMMON *DevInfo OPTIONAL\r
+ OUT UINT32 *DevInfoLength,\r
+ OUT OPAL_DEVICE_LOCKBOX_DATA *DevInfo OPTIONAL\r
)\r
{\r
EFI_DEVICE_PATH_PROTOCOL *TmpDevPath;\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
// 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 ((TmpDevPath->Type == MESSAGING_DEVICE_PATH) &&\r
+ (TmpDevPath->SubType == MSG_SATA_DP || TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP)) {\r
if (DevInfo != NULL) {\r
- NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;\r
- DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;\r
- DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;\r
+ DevInfo->DevicePathLength = (UINT32) GetDevicePathSize (DevicePath);\r
+ CopyMem (DevInfo->DevicePath, DevicePath, DevInfo->DevicePathLength);\r
}\r
- DeviceType = OPAL_DEVICE_TYPE_NVME;\r
- *DevInfoLength = sizeof (OPAL_DEVICE_NVME);\r
+\r
+ DeviceType = (TmpDevPath->SubType == MSG_SATA_DP) ? OPAL_DEVICE_TYPE_ATA : OPAL_DEVICE_TYPE_NVME;\r
+ *DevInfoLength = sizeof (OPAL_DEVICE_LOCKBOX_DATA) + (UINT32) GetDevicePathSize (DevicePath);\r
break;\r
}\r
TmpDevPath = NextDevicePathNode (TmpDevPath);\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 ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH) &&\r
+ (TmpDevPath2->SubType == MSG_SATA_DP || TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)) {\r
if (DevInfo != NULL) {\r
PciDevice = &DevInfo->Device;\r
PciDevice->Segment = 0;\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
ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);\r
- return DeviceType;\r
+ return;\r
}\r
\r
/**\r
- Save boot script for ATA OPAL device.\r
-\r
- @param[in] DevInfo Pointer to ATA Opal device information.\r
+ Build OPAL device info and save them to LockBox.\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
+BuildOpalDeviceInfo (\r
+ VOID\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
+ EFI_STATUS Status;\r
+ OPAL_DEVICE_LOCKBOX_DATA *DevInfo;\r
+ OPAL_DEVICE_LOCKBOX_DATA *TempDevInfo;\r
+ UINTN TotalDevInfoLength;\r
+ UINT32 DevInfoLength;\r
+ OPAL_DRIVER_DEVICE *TmpDev;\r
+ UINT8 DummyData;\r
+ BOOLEAN S3InitDevicesExist;\r
+ UINTN S3InitDevicesLength;\r
+ EFI_DEVICE_PATH_PROTOCOL *S3InitDevices;\r
+ EFI_DEVICE_PATH_PROTOCOL *S3InitDevicesBak;\r
\r
//\r
- // Build ATA OPAL device info and save them to LockBox.\r
+ // Build OPAL device info and save them to LockBox.\r
//\r
- DevInfoLengthAta = 0;\r
+ TotalDevInfoLength = 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
+ ExtractDeviceInfoFromDevicePath (\r
+ TmpDev->OpalDisk.OpalDevicePath,\r
+ &DevInfoLength,\r
+ NULL\r
+ );\r
+ TotalDevInfoLength += DevInfoLength;\r
TmpDev = TmpDev->Next;\r
}\r
\r
- if (DevInfoLengthAta == 0) {\r
+ if (TotalDevInfoLength == 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
+ S3InitDevicesLength = sizeof (DummyData);\r
+ Status = RestoreLockBox (\r
+ &gS3StorageDeviceInitListGuid,\r
+ &DummyData,\r
+ &S3InitDevicesLength\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
+ ASSERT ((Status == EFI_NOT_FOUND) || (Status == EFI_BUFFER_TOO_SMALL));\r
+ if (Status == EFI_NOT_FOUND) {\r
+ S3InitDevices = NULL;\r
+ S3InitDevicesExist = FALSE;\r
+ } else if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ S3InitDevices = AllocatePool (S3InitDevicesLength);\r
+ ASSERT (S3InitDevices != NULL);\r
+ if (S3InitDevices == NULL) {\r
+ return;\r
}\r
\r
- TmpDev = TmpDev->Next;\r
+ Status = RestoreLockBox (\r
+ &gS3StorageDeviceInitListGuid,\r
+ S3InitDevices,\r
+ &S3InitDevicesLength\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ S3InitDevicesExist = TRUE;\r
+ } else {\r
+ return;\r
}\r
\r
- if (DevInfoLengthNvme == 0) {\r
+ DevInfo = AllocateZeroPool (TotalDevInfoLength);\r
+ ASSERT (DevInfo != NULL);\r
+ if (DevInfo == NULL) {\r
return;\r
}\r
\r
- DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);\r
- ASSERT (DevInfoNvme != NULL);\r
-\r
- TempDevInfoNvme = DevInfoNvme;\r
- TmpDev = mOpalDriver.DeviceList;\r
+ TempDevInfo = DevInfo;\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
+ ExtractDeviceInfoFromDevicePath (\r
+ TmpDev->OpalDisk.OpalDevicePath,\r
+ &DevInfoLength,\r
+ TempDevInfo\r
+ );\r
+ TempDevInfo->Length = DevInfoLength;\r
+ TempDevInfo->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;\r
+ CopyMem (\r
+ TempDevInfo->Password,\r
+ TmpDev->OpalDisk.Password,\r
+ TmpDev->OpalDisk.PasswordLength\r
+ );\r
+ TempDevInfo->PasswordLength = TmpDev->OpalDisk.PasswordLength;\r
+\r
+ S3InitDevicesBak = S3InitDevices;\r
+ S3InitDevices = AppendDevicePathInstance (\r
+ S3InitDevicesBak,\r
+ TmpDev->OpalDisk.OpalDevicePath\r
+ );\r
+ if (S3InitDevicesBak != NULL) {\r
+ FreePool (S3InitDevicesBak);\r
+ }\r
+ ASSERT (S3InitDevices != NULL);\r
+ if (S3InitDevices == NULL) {\r
+ return;\r
}\r
\r
+ TempDevInfo = (OPAL_DEVICE_LOCKBOX_DATA *) ((UINTN) TempDevInfo + DevInfoLength);\r
TmpDev = TmpDev->Next;\r
}\r
\r
Status = SaveLockBox (\r
- &mOpalDeviceNvmeGuid,\r
- DevInfoNvme,\r
- DevInfoLengthNvme\r
+ &mOpalDeviceLockBoxGuid,\r
+ DevInfo,\r
+ TotalDevInfoLength\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
Status = SetLockBoxAttributes (\r
- &mOpalDeviceNvmeGuid,\r
+ &mOpalDeviceLockBoxGuid,\r
LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
- ZeroMem (DevInfoNvme, DevInfoLengthNvme);\r
- FreePool (DevInfoNvme);\r
+ S3InitDevicesLength = GetDevicePathSize (S3InitDevices);\r
+ if (S3InitDevicesExist) {\r
+ Status = UpdateLockBox (\r
+ &gS3StorageDeviceInitListGuid,\r
+ 0,\r
+ S3InitDevices,\r
+ S3InitDevicesLength\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ } else {\r
+ Status = SaveLockBox (\r
+ &gS3StorageDeviceInitListGuid,\r
+ S3InitDevices,\r
+ S3InitDevicesLength\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ Status = SetLockBoxAttributes (\r
+ &gS3StorageDeviceInitListGuid,\r
+ LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ ZeroMem (DevInfo, TotalDevInfoLength);\r
+ FreePool (DevInfo);\r
+ FreePool (S3InitDevices);\r
}\r
\r
/**\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
return;\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
+ BuildOpalDeviceInfo ();\r
\r
//\r
// Zero passsword.\r
\r
IsLocked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);\r
\r
+ if (IsLocked && PcdGetBool (PcdSkipOpalDxeUnlock)) {\r
+ return;\r
+ }\r
+\r
while (Count < MAX_PASSWORD_TRY_COUNT) {\r
Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
if (PressEsc) {\r