]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
OvmfPkg/LockBoxLib: Update the comments for API UpdateLockBox()
[mirror_edk2.git] / SecurityPkg / Tcg / Opal / OpalPassword / OpalDriver.c
CommitLineData
112e584b
SZ
1/** @file\r
2 Entrypoint of Opal UEFI Driver and contains all the logic to\r
3 register for new Opal device instances.\r
4\r
d72d8561 5Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>\r
112e584b
SZ
6This program and the accompanying materials\r
7are licensed and made available under the terms and conditions of the BSD License\r
8which accompanies this distribution. The full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16// This UEFI driver consumes EFI_STORAGE_SECURITY_PROTOCOL instances and installs an\r
17// HII GUI to manage Opal features if the device is Opal capable\r
18// If the Opal device is being managed by the UEFI Driver, it shall provide a popup\r
19// window during boot requesting a user password\r
20\r
21#include "OpalDriver.h"\r
22#include "OpalHii.h"\r
23\r
24EFI_GUID mOpalDeviceAtaGuid = OPAL_DEVICE_ATA_GUID;\r
25EFI_GUID mOpalDeviceNvmeGuid = OPAL_DEVICE_NVME_GUID;\r
26\r
27BOOLEAN mOpalEndOfDxe = FALSE;\r
28OPAL_REQUEST_VARIABLE *mOpalRequestVariable = NULL;\r
29UINTN mOpalRequestVariableSize = 0;\r
aa085730 30CHAR16 mPopUpString[100];\r
112e584b
SZ
31\r
32typedef struct {\r
33 UINT32 Address;\r
34 S3_BOOT_SCRIPT_LIB_WIDTH Width;\r
35} OPAL_HC_PCI_REGISTER_SAVE;\r
36\r
37//\r
38// To unlock the Intel SATA controller at S3 Resume, restored the following registers.\r
39//\r
40const OPAL_HC_PCI_REGISTER_SAVE mSataHcRegisterSaveTemplate[] = {\r
41 {0x9, S3BootScriptWidthUint8},\r
42 {0x10, S3BootScriptWidthUint32},\r
43 {0x14, S3BootScriptWidthUint32},\r
44 {0x18, S3BootScriptWidthUint32},\r
45 {0x1C, S3BootScriptWidthUint32},\r
46 {0x20, S3BootScriptWidthUint32},\r
47 {0x24, S3BootScriptWidthUint32},\r
48 {0x3c, S3BootScriptWidthUint8},\r
49 {0x3d, S3BootScriptWidthUint8},\r
50 {0x40, S3BootScriptWidthUint16},\r
51 {0x42, S3BootScriptWidthUint16},\r
52 {0x92, S3BootScriptWidthUint16},\r
53 {0x94, S3BootScriptWidthUint32},\r
54 {0x9C, S3BootScriptWidthUint32},\r
55 {0x4, S3BootScriptWidthUint16},\r
56};\r
57\r
58OPAL_DRIVER mOpalDriver;\r
59\r
60//\r
61// Globals\r
62//\r
63EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {\r
64 OpalEfiDriverBindingSupported,\r
65 OpalEfiDriverBindingStart,\r
66 OpalEfiDriverBindingStop,\r
67 0x1b,\r
68 NULL,\r
69 NULL\r
70};\r
71\r
72/**\r
73\r
74 The function determines the available actions for the OPAL_DISK provided.\r
75\r
76 @param[in] SupportedAttributes The supported attributes for the device.\r
77 @param[in] LockingFeature The locking status for the device.\r
78 @param[in] OwnerShip The ownership for the device.\r
79 @param[out] AvalDiskActions Pointer to fill-out with appropriate disk actions.\r
80\r
81**/\r
82TCG_RESULT\r
83EFIAPI\r
84OpalSupportGetAvailableActions(\r
85 IN OPAL_DISK_SUPPORT_ATTRIBUTE *SupportedAttributes,\r
86 IN TCG_LOCKING_FEATURE_DESCRIPTOR *LockingFeature,\r
87 IN UINT16 OwnerShip,\r
88 OUT OPAL_DISK_ACTIONS *AvalDiskActions\r
89 )\r
90{\r
91 BOOLEAN ExistingPassword;\r
92\r
93 NULL_CHECK(AvalDiskActions);\r
94\r
95 AvalDiskActions->AdminPass = 1;\r
96 AvalDiskActions->UserPass = 0;\r
97 AvalDiskActions->DisableUser = 0;\r
98 AvalDiskActions->Unlock = 0;\r
99\r
100 //\r
101 // Revert is performed on locking sp, so only allow if locking sp is enabled\r
102 //\r
103 if (LockingFeature->LockingEnabled) {\r
104 AvalDiskActions->Revert = 1;\r
105 }\r
106\r
107 //\r
40d32e79 108 // Psid revert is available for any device with media encryption support or pyrite 2.0 type support.\r
112e584b 109 //\r
40d32e79 110 if (SupportedAttributes->PyriteSscV2 || SupportedAttributes->MediaEncryption) {\r
112e584b
SZ
111\r
112 //\r
40d32e79 113 // Only allow psid revert if media encryption is enabled or pyrite 2.0 type support..\r
112e584b
SZ
114 // Otherwise, someone who steals a disk can psid revert the disk and the user Data is still\r
115 // intact and accessible\r
116 //\r
117 AvalDiskActions->PsidRevert = 1;\r
118 AvalDiskActions->RevertKeepDataForced = 0;\r
119\r
120 //\r
121 // Secure erase is performed by generating a new encryption key\r
122 // this is only available if encryption is supported\r
123 //\r
124 AvalDiskActions->SecureErase = 1;\r
125 } else {\r
126 AvalDiskActions->PsidRevert = 0;\r
127 AvalDiskActions->SecureErase = 0;\r
128\r
129 //\r
130 // If no media encryption is supported, then a revert (using password) will not\r
131 // erase the Data (since you can't generate a new encryption key)\r
132 //\r
133 AvalDiskActions->RevertKeepDataForced = 1;\r
134 }\r
135\r
136 if (LockingFeature->Locked) {\r
137 AvalDiskActions->Unlock = 1;\r
138 } else {\r
139 AvalDiskActions->Unlock = 0;\r
140 }\r
141\r
142 //\r
143 // Only allow user to set password if an admin password exists\r
144 //\r
145 ExistingPassword = OpalUtilAdminPasswordExists(OwnerShip, LockingFeature);\r
146 AvalDiskActions->UserPass = ExistingPassword;\r
147\r
148 //\r
149 // This will still show up even if there isn't a user, which is fine\r
150 //\r
151 AvalDiskActions->DisableUser = ExistingPassword;\r
152\r
153 return TcgResultSuccess;\r
154}\r
155\r
156/**\r
157 Enable Opal Feature for the input device.\r
158\r
159 @param[in] Session The opal session for the opal device.\r
160 @param[in] Msid Msid\r
161 @param[in] MsidLength Msid Length\r
162 @param[in] Password Admin password\r
163 @param[in] PassLength Length of password in bytes\r
164\r
165**/\r
166TCG_RESULT\r
167EFIAPI\r
168OpalSupportEnableOpalFeature (\r
169 IN OPAL_SESSION *Session,\r
170 IN VOID *Msid,\r
171 IN UINT32 MsidLength,\r
172 IN VOID *Password,\r
173 IN UINT32 PassLength\r
174 )\r
175{\r
176 TCG_RESULT Ret;\r
177\r
178 NULL_CHECK(Session);\r
179 NULL_CHECK(Msid);\r
180 NULL_CHECK(Password);\r
181\r
182 Ret = OpalUtilSetAdminPasswordAsSid(\r
183 Session,\r
184 Msid,\r
185 MsidLength,\r
186 Password,\r
187 PassLength\r
188 );\r
189 if (Ret == TcgResultSuccess) {\r
190 //\r
191 // Enable global locking range\r
192 //\r
193 Ret = OpalUtilSetOpalLockingRange(\r
194 Session,\r
195 Password,\r
196 PassLength,\r
197 OPAL_LOCKING_SP_LOCKING_GLOBALRANGE,\r
198 0,\r
199 0,\r
200 TRUE,\r
201 TRUE,\r
202 FALSE,\r
203 FALSE\r
204 );\r
205 }\r
206\r
207 return Ret;\r
208}\r
209\r
210/**\r
211 Update password for the Opal disk.\r
212\r
213 @param[in, out] OpalDisk The disk to update password.\r
214 @param[in] Password The input password.\r
215 @param[in] PasswordLength The input password length.\r
216\r
217**/\r
218VOID\r
219OpalSupportUpdatePassword (\r
220 IN OUT OPAL_DISK *OpalDisk,\r
221 IN VOID *Password,\r
222 IN UINT32 PasswordLength\r
223 )\r
224{\r
225 CopyMem (OpalDisk->Password, Password, PasswordLength);\r
226 OpalDisk->PasswordLength = (UINT8) PasswordLength;\r
227}\r
228\r
229/**\r
230 Extract device info from the device path.\r
231\r
232 @param[in] DevicePath Device path info for the device.\r
233 @param[out] DevInfoLength Device information length needed.\r
234 @param[out] DevInfo Device information extracted.\r
235\r
236 @return Device type.\r
237\r
238**/\r
239UINT8\r
240ExtractDeviceInfoFromDevicePath (\r
241 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,\r
242 OUT UINT16 *DevInfoLength,\r
243 OUT OPAL_DEVICE_COMMON *DevInfo OPTIONAL\r
244 )\r
245{\r
246 EFI_DEVICE_PATH_PROTOCOL *TmpDevPath;\r
247 EFI_DEVICE_PATH_PROTOCOL *TmpDevPath2;\r
248 PCI_DEVICE_PATH *PciDevPath;\r
249 UINT8 DeviceType;\r
250 UINT8 BusNum;\r
251 OPAL_PCI_DEVICE *PciDevice;\r
252 OPAL_DEVICE_ATA *DevInfoAta;\r
253 OPAL_DEVICE_NVME *DevInfoNvme;\r
254 SATA_DEVICE_PATH *SataDevPath;\r
255 NVME_NAMESPACE_DEVICE_PATH *NvmeDevPath;\r
256\r
257 ASSERT (DevicePath != NULL);\r
258 ASSERT (DevInfoLength != NULL);\r
259\r
260 DeviceType = OPAL_DEVICE_TYPE_UNKNOWN;\r
261 *DevInfoLength = 0;\r
262\r
263 TmpDevPath = DevicePath;\r
264\r
265 //\r
266 // Get device type.\r
267 //\r
268 while (!IsDevicePathEnd (TmpDevPath)) {\r
269 if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_SATA_DP) {\r
270 //\r
271 // SATA\r
272 //\r
273 if (DevInfo != NULL) {\r
274 SataDevPath = (SATA_DEVICE_PATH *) TmpDevPath;\r
275 DevInfoAta = (OPAL_DEVICE_ATA *) DevInfo;\r
276 DevInfoAta->Port = SataDevPath->HBAPortNumber;\r
277 DevInfoAta->PortMultiplierPort = SataDevPath->PortMultiplierPortNumber;\r
278 }\r
279 DeviceType = OPAL_DEVICE_TYPE_ATA;\r
280 *DevInfoLength = sizeof (OPAL_DEVICE_ATA);\r
281 break;\r
282 } else if (TmpDevPath->Type == MESSAGING_DEVICE_PATH && TmpDevPath->SubType == MSG_NVME_NAMESPACE_DP) {\r
283 //\r
284 // NVMe\r
285 //\r
286 if (DevInfo != NULL) {\r
287 NvmeDevPath = (NVME_NAMESPACE_DEVICE_PATH *) TmpDevPath;\r
288 DevInfoNvme = (OPAL_DEVICE_NVME *) DevInfo;\r
289 DevInfoNvme->NvmeNamespaceId = NvmeDevPath->NamespaceId;\r
290 }\r
291 DeviceType = OPAL_DEVICE_TYPE_NVME;\r
292 *DevInfoLength = sizeof (OPAL_DEVICE_NVME);\r
293 break;\r
294 }\r
295 TmpDevPath = NextDevicePathNode (TmpDevPath);\r
296 }\r
297\r
298 //\r
299 // Get device info.\r
300 //\r
301 BusNum = 0;\r
302 TmpDevPath = DevicePath;\r
303 TmpDevPath2 = NextDevicePathNode (DevicePath);\r
304 while (!IsDevicePathEnd (TmpDevPath2)) {\r
305 if (TmpDevPath->Type == HARDWARE_DEVICE_PATH && TmpDevPath->SubType == HW_PCI_DP) {\r
306 PciDevPath = (PCI_DEVICE_PATH *) TmpDevPath;\r
307 if ((TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_NVME_NAMESPACE_DP)||\r
308 (TmpDevPath2->Type == MESSAGING_DEVICE_PATH && TmpDevPath2->SubType == MSG_SATA_DP)) {\r
309 if (DevInfo != NULL) {\r
310 PciDevice = &DevInfo->Device;\r
311 PciDevice->Segment = 0;\r
312 PciDevice->Bus = BusNum;\r
313 PciDevice->Device = PciDevPath->Device;\r
314 PciDevice->Function = PciDevPath->Function;\r
315 }\r
316 } else {\r
317 if (DevInfo != NULL) {\r
318 PciDevice = (OPAL_PCI_DEVICE *) ((UINTN) DevInfo + *DevInfoLength);\r
319 PciDevice->Segment = 0;\r
320 PciDevice->Bus = BusNum;\r
321 PciDevice->Device = PciDevPath->Device;\r
322 PciDevice->Function = PciDevPath->Function;\r
323 }\r
324 *DevInfoLength += sizeof (OPAL_PCI_DEVICE);\r
325 if (TmpDevPath2->Type == HARDWARE_DEVICE_PATH && TmpDevPath2->SubType == HW_PCI_DP) {\r
326 BusNum = PciRead8 (PCI_LIB_ADDRESS (BusNum, PciDevPath->Device, PciDevPath->Function, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));\r
327 }\r
328 }\r
329 }\r
330\r
331 TmpDevPath = NextDevicePathNode (TmpDevPath);\r
332 TmpDevPath2 = NextDevicePathNode (TmpDevPath2);\r
333 }\r
334\r
335 ASSERT (DeviceType != OPAL_DEVICE_TYPE_UNKNOWN);\r
336 return DeviceType;\r
337}\r
338\r
339/**\r
340 Save boot script for ATA OPAL device.\r
341\r
342 @param[in] DevInfo Pointer to ATA Opal device information.\r
343\r
344 **/\r
345VOID\r
346OpalDeviceAtaSaveBootScript (\r
347 IN OPAL_DEVICE_ATA *DevInfo\r
348 )\r
349{\r
350 UINTN Bus;\r
351 UINTN Device;\r
352 UINTN Function;\r
353 UINTN Index;\r
354 EFI_STATUS Status;\r
355 UINTN Offset;\r
356 UINT64 Address;\r
357 S3_BOOT_SCRIPT_LIB_WIDTH Width;\r
358 UINT32 Data;\r
359 OPAL_HC_PCI_REGISTER_SAVE *HcRegisterSaveListPtr;\r
360 UINTN Count;\r
361\r
362 Data = 0;\r
363\r
364 Bus = DevInfo->Device.Bus;\r
365 Device = DevInfo->Device.Device;\r
366 Function = DevInfo->Device.Function;\r
367\r
368 HcRegisterSaveListPtr = (OPAL_HC_PCI_REGISTER_SAVE *) mSataHcRegisterSaveTemplate;\r
369 Count = sizeof (mSataHcRegisterSaveTemplate) / sizeof (OPAL_HC_PCI_REGISTER_SAVE);\r
370\r
371 for (Index = 0; Index < Count; Index++) {\r
372 Offset = HcRegisterSaveListPtr[Index].Address;\r
373 Width = HcRegisterSaveListPtr[Index].Width;\r
374\r
375 switch (Width) {\r
376 case S3BootScriptWidthUint8:\r
377 Data = (UINT32)PciRead8 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
378 break;\r
379 case S3BootScriptWidthUint16:\r
380 Data = (UINT32)PciRead16 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
381 break;\r
382 case S3BootScriptWidthUint32:\r
383 Data = PciRead32 (PCI_LIB_ADDRESS(Bus,Device,Function,Offset));\r
384 break;\r
385 default:\r
386 ASSERT (FALSE);\r
387 break;\r
388 }\r
389\r
390 Address = S3_BOOT_SCRIPT_LIB_PCI_ADDRESS (Bus, Device, Function, Offset);\r
391 Status = S3BootScriptSavePciCfgWrite (Width, Address, 1, &Data);\r
392 ASSERT_EFI_ERROR (Status);\r
393 }\r
394}\r
395\r
396/**\r
397 Build ATA OPAL device info and save them to LockBox.\r
398\r
399 @param[in] BarAddr Bar address allocated.\r
400\r
401 **/\r
402VOID\r
403BuildOpalDeviceInfoAta (\r
404 IN UINT32 BarAddr\r
405 )\r
406{\r
407 EFI_STATUS Status;\r
408 UINT8 DeviceType;\r
409 OPAL_DEVICE_ATA *DevInfoAta;\r
410 OPAL_DEVICE_ATA *TempDevInfoAta;\r
411 UINTN DevInfoLengthAta;\r
412 UINT16 DevInfoLength;\r
413 OPAL_DRIVER_DEVICE *TmpDev;\r
414\r
415 //\r
416 // Build ATA OPAL device info and save them to LockBox.\r
417 //\r
418 DevInfoLengthAta = 0;\r
419 TmpDev = mOpalDriver.DeviceList;\r
420 while (TmpDev != NULL) {\r
421 DeviceType = ExtractDeviceInfoFromDevicePath (\r
422 TmpDev->OpalDisk.OpalDevicePath,\r
423 &DevInfoLength,\r
424 NULL\r
425 );\r
426 if (DeviceType == OPAL_DEVICE_TYPE_ATA) {\r
427 DevInfoLengthAta += DevInfoLength;\r
428 }\r
429\r
430 TmpDev = TmpDev->Next;\r
431 }\r
432\r
433 if (DevInfoLengthAta == 0) {\r
434 return;\r
435 }\r
436\r
437 DevInfoAta = AllocateZeroPool (DevInfoLengthAta);\r
438 ASSERT (DevInfoAta != NULL);\r
d72d8561
ED
439 if (DevInfoAta == NULL) {\r
440 return;\r
441 }\r
112e584b
SZ
442\r
443 TempDevInfoAta = DevInfoAta;\r
444 TmpDev = mOpalDriver.DeviceList;\r
445 while (TmpDev != NULL) {\r
446 DeviceType = ExtractDeviceInfoFromDevicePath (\r
447 TmpDev->OpalDisk.OpalDevicePath,\r
448 &DevInfoLength,\r
449 NULL\r
450 );\r
451 if (DeviceType == OPAL_DEVICE_TYPE_ATA) {\r
452 ExtractDeviceInfoFromDevicePath (\r
453 TmpDev->OpalDisk.OpalDevicePath,\r
454 &DevInfoLength,\r
455 (OPAL_DEVICE_COMMON *) TempDevInfoAta\r
456 );\r
457 TempDevInfoAta->Length = DevInfoLength;\r
458 TempDevInfoAta->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;\r
459 TempDevInfoAta->BarAddr = BarAddr;\r
460 CopyMem (\r
461 TempDevInfoAta->Password,\r
462 TmpDev->OpalDisk.Password,\r
463 TmpDev->OpalDisk.PasswordLength\r
464 );\r
465 TempDevInfoAta->PasswordLength = TmpDev->OpalDisk.PasswordLength;\r
466 OpalDeviceAtaSaveBootScript (TempDevInfoAta);\r
467 TempDevInfoAta = (OPAL_DEVICE_ATA *) ((UINTN) TempDevInfoAta + DevInfoLength);\r
468 }\r
469\r
470 TmpDev = TmpDev->Next;\r
471 }\r
472\r
473 Status = SaveLockBox (\r
474 &mOpalDeviceAtaGuid,\r
475 DevInfoAta,\r
476 DevInfoLengthAta\r
477 );\r
478 ASSERT_EFI_ERROR (Status);\r
479\r
480 Status = SetLockBoxAttributes (\r
481 &mOpalDeviceAtaGuid,\r
482 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
483 );\r
484 ASSERT_EFI_ERROR (Status);\r
485\r
486 ZeroMem (DevInfoAta, DevInfoLengthAta);\r
487 FreePool (DevInfoAta);\r
488}\r
489\r
490/**\r
491 Build NVMe OPAL device info and save them to LockBox.\r
492\r
493 @param[in] BarAddr Bar address allocated.\r
494\r
495 **/\r
496VOID\r
497BuildOpalDeviceInfoNvme (\r
498 IN UINT32 BarAddr\r
499 )\r
500{\r
501 EFI_STATUS Status;\r
502 UINT8 DeviceType;\r
503 OPAL_DEVICE_NVME *DevInfoNvme;\r
504 OPAL_DEVICE_NVME *TempDevInfoNvme;\r
505 UINTN DevInfoLengthNvme;\r
506 UINT16 DevInfoLength;\r
507 OPAL_DRIVER_DEVICE *TmpDev;\r
508\r
509 //\r
510 // Build NVMe OPAL device info and save them to LockBox.\r
511 //\r
512 DevInfoLengthNvme = 0;\r
513 TmpDev = mOpalDriver.DeviceList;\r
514 while (TmpDev != NULL) {\r
515 DeviceType = ExtractDeviceInfoFromDevicePath (\r
516 TmpDev->OpalDisk.OpalDevicePath,\r
517 &DevInfoLength,\r
518 NULL\r
519 );\r
520 if (DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
521 DevInfoLengthNvme += DevInfoLength;\r
522 }\r
523\r
524 TmpDev = TmpDev->Next;\r
525 }\r
526\r
527 if (DevInfoLengthNvme == 0) {\r
528 return;\r
529 }\r
530\r
531 DevInfoNvme = AllocateZeroPool (DevInfoLengthNvme);\r
532 ASSERT (DevInfoNvme != NULL);\r
d72d8561
ED
533 if (DevInfoNvme == NULL) {\r
534 return;\r
535 }\r
112e584b
SZ
536\r
537 TempDevInfoNvme = DevInfoNvme;\r
538 TmpDev = mOpalDriver.DeviceList;\r
539 while (TmpDev != NULL) {\r
540 DeviceType = ExtractDeviceInfoFromDevicePath (\r
541 TmpDev->OpalDisk.OpalDevicePath,\r
542 &DevInfoLength,\r
543 NULL\r
544 );\r
545 if (DeviceType == OPAL_DEVICE_TYPE_NVME) {\r
546 ExtractDeviceInfoFromDevicePath (\r
547 TmpDev->OpalDisk.OpalDevicePath,\r
548 &DevInfoLength,\r
549 (OPAL_DEVICE_COMMON *) TempDevInfoNvme\r
550 );\r
551 TempDevInfoNvme->Length = DevInfoLength;\r
552 TempDevInfoNvme->OpalBaseComId = TmpDev->OpalDisk.OpalBaseComId;\r
553 TempDevInfoNvme->BarAddr = BarAddr;\r
554 CopyMem (\r
555 TempDevInfoNvme->Password,\r
556 TmpDev->OpalDisk.Password,\r
557 TmpDev->OpalDisk.PasswordLength\r
558 );\r
559 TempDevInfoNvme->PasswordLength = TmpDev->OpalDisk.PasswordLength;\r
560 TempDevInfoNvme = (OPAL_DEVICE_NVME *) ((UINTN) TempDevInfoNvme + DevInfoLength);\r
561 }\r
562\r
563 TmpDev = TmpDev->Next;\r
564 }\r
565\r
566 Status = SaveLockBox (\r
567 &mOpalDeviceNvmeGuid,\r
568 DevInfoNvme,\r
569 DevInfoLengthNvme\r
570 );\r
571 ASSERT_EFI_ERROR (Status);\r
572\r
573 Status = SetLockBoxAttributes (\r
574 &mOpalDeviceNvmeGuid,\r
575 LOCK_BOX_ATTRIBUTE_RESTORE_IN_S3_ONLY\r
576 );\r
577 ASSERT_EFI_ERROR (Status);\r
578\r
579 ZeroMem (DevInfoNvme, DevInfoLengthNvme);\r
580 FreePool (DevInfoNvme);\r
581}\r
582\r
583/**\r
584 Notification function of EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
585\r
586 This is a notification function registered on EFI_END_OF_DXE_EVENT_GROUP_GUID event group.\r
587\r
588 @param Event Event whose notification function is being invoked.\r
589 @param Context Pointer to the notification function's context.\r
590\r
591**/\r
592VOID\r
593EFIAPI\r
594OpalEndOfDxeEventNotify (\r
595 EFI_EVENT Event,\r
596 VOID *Context\r
597 )\r
598{\r
599 EFI_STATUS Status;\r
600 EFI_PHYSICAL_ADDRESS Address;\r
601 UINT64 Length;\r
602 OPAL_DRIVER_DEVICE *TmpDev;\r
603\r
604 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
605\r
606 mOpalEndOfDxe = TRUE;\r
607\r
608 if (mOpalRequestVariable != NULL) {\r
609 //\r
610 // Free the OPAL request variable buffer here\r
611 // as the OPAL requests should have been processed.\r
612 //\r
613 FreePool (mOpalRequestVariable);\r
614 mOpalRequestVariable = NULL;\r
615 mOpalRequestVariableSize = 0;\r
616 }\r
617\r
fbe1328a
SZ
618 //\r
619 // If no any device, return directly.\r
620 //\r
621 if (mOpalDriver.DeviceList == NULL) {\r
622 gBS->CloseEvent (Event);\r
623 return;\r
624 }\r
625\r
112e584b
SZ
626 //\r
627 // Assume 64K size and alignment are enough.\r
628 //\r
629 Length = 0x10000;\r
630 Address = 0xFFFFFFFF;\r
631 Status = gDS->AllocateMemorySpace (\r
632 EfiGcdAllocateMaxAddressSearchBottomUp,\r
633 EfiGcdMemoryTypeMemoryMappedIo,\r
634 16, // 2^16: 64K Alignment\r
635 Length,\r
636 &Address,\r
637 gImageHandle,\r
638 NULL\r
639 );\r
640 ASSERT_EFI_ERROR (Status);\r
641\r
642 BuildOpalDeviceInfoAta ((UINT32) Address);\r
643 BuildOpalDeviceInfoNvme ((UINT32) Address);\r
644\r
645 //\r
646 // Zero passsword.\r
647 //\r
648 TmpDev = mOpalDriver.DeviceList;\r
649 while (TmpDev != NULL) {\r
650 ZeroMem (TmpDev->OpalDisk.Password, TmpDev->OpalDisk.PasswordLength);\r
651 TmpDev = TmpDev->Next;\r
652 }\r
653\r
654 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
655\r
656 gBS->CloseEvent (Event);\r
657}\r
658\r
659/**\r
660 Get Psid input from the popup window.\r
661\r
662 @param[in] Dev The device which need Psid to process Psid Revert\r
663 OPAL request.\r
664 @param[in] PopUpString Pop up string.\r
40d32e79
ED
665 @param[in] PopUpString2 Pop up string in line 2.\r
666\r
112e584b
SZ
667 @param[out] PressEsc Whether user escape function through Press ESC.\r
668\r
aa085730 669 @retval Psid string if success. NULL if failed.\r
112e584b
SZ
670\r
671**/\r
672CHAR8 *\r
673OpalDriverPopUpPsidInput (\r
674 IN OPAL_DRIVER_DEVICE *Dev,\r
675 IN CHAR16 *PopUpString,\r
40d32e79 676 IN CHAR16 *PopUpString2,\r
112e584b
SZ
677 OUT BOOLEAN *PressEsc\r
678 )\r
679{\r
680 EFI_INPUT_KEY InputKey;\r
681 UINTN InputLength;\r
682 CHAR16 Mask[PSID_CHARACTER_LENGTH + 1];\r
683 CHAR16 Unicode[PSID_CHARACTER_LENGTH + 1];\r
684 CHAR8 *Ascii;\r
685\r
686 ZeroMem(Unicode, sizeof(Unicode));\r
687 ZeroMem(Mask, sizeof(Mask));\r
688\r
689 *PressEsc = FALSE;\r
690\r
691 gST->ConOut->ClearScreen(gST->ConOut);\r
692\r
693 InputLength = 0;\r
694 while (TRUE) {\r
695 Mask[InputLength] = L'_';\r
63c76537
ED
696 if (PopUpString2 == NULL) {\r
697 CreatePopUp (\r
698 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
699 &InputKey,\r
700 PopUpString,\r
701 L"---------------------",\r
702 Mask,\r
703 NULL\r
704 );\r
705 } else {\r
706 CreatePopUp (\r
707 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
708 &InputKey,\r
709 PopUpString,\r
710 PopUpString2,\r
711 L"---------------------",\r
712 Mask,\r
713 NULL\r
714 );\r
715 }\r
112e584b
SZ
716\r
717 //\r
718 // Check key.\r
719 //\r
720 if (InputKey.ScanCode == SCAN_NULL) {\r
721 //\r
722 // password finished\r
723 //\r
724 if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
725 //\r
726 // Add the null terminator.\r
727 //\r
728 Unicode[InputLength] = 0;\r
729 Mask[InputLength] = 0;\r
730 break;\r
731 } else if ((InputKey.UnicodeChar == CHAR_NULL) ||\r
732 (InputKey.UnicodeChar == CHAR_TAB) ||\r
733 (InputKey.UnicodeChar == CHAR_LINEFEED)\r
734 ) {\r
735 continue;\r
736 } else {\r
737 //\r
738 // delete last key entered\r
739 //\r
740 if (InputKey.UnicodeChar == CHAR_BACKSPACE) {\r
741 if (InputLength > 0) {\r
742 Unicode[InputLength] = 0;\r
743 Mask[InputLength] = 0;\r
744 InputLength--;\r
745 }\r
746 } else {\r
747 //\r
748 // add Next key entry\r
749 //\r
750 Unicode[InputLength] = InputKey.UnicodeChar;\r
751 Mask[InputLength] = InputKey.UnicodeChar;\r
752 InputLength++;\r
753 if (InputLength == PSID_CHARACTER_LENGTH) {\r
754 //\r
755 // Add the null terminator.\r
756 //\r
757 Unicode[InputLength] = 0;\r
758 Mask[InputLength] = 0;\r
759 break;\r
760 }\r
761 }\r
762 }\r
763 }\r
764\r
765 //\r
766 // exit on ESC\r
767 //\r
768 if (InputKey.ScanCode == SCAN_ESC) {\r
769 *PressEsc = TRUE;\r
770 break;\r
771 }\r
772 }\r
773\r
774 gST->ConOut->ClearScreen(gST->ConOut);\r
775\r
776 if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {\r
777 ZeroMem (Unicode, sizeof (Unicode));\r
778 ZeroMem (Mask, sizeof (Mask));\r
779 return NULL;\r
780 }\r
781\r
782 Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);\r
783 if (Ascii == NULL) {\r
784 ZeroMem (Unicode, sizeof (Unicode));\r
785 ZeroMem (Mask, sizeof (Mask));\r
786 return NULL;\r
787 }\r
788\r
789 UnicodeStrToAsciiStrS (Unicode, Ascii, PSID_CHARACTER_LENGTH + 1);\r
790 ZeroMem (Unicode, sizeof (Unicode));\r
791 ZeroMem (Mask, sizeof (Mask));\r
792\r
793 return Ascii;\r
794}\r
795\r
796\r
797/**\r
798 Get password input from the popup window.\r
799\r
800 @param[in] Dev The device which need password to unlock or\r
801 process OPAL request.\r
802 @param[in] PopUpString1 Pop up string 1.\r
803 @param[in] PopUpString2 Pop up string 2.\r
804 @param[out] PressEsc Whether user escape function through Press ESC.\r
805\r
806 @retval Password string if success. NULL if failed.\r
807\r
808**/\r
809CHAR8 *\r
810OpalDriverPopUpPasswordInput (\r
811 IN OPAL_DRIVER_DEVICE *Dev,\r
812 IN CHAR16 *PopUpString1,\r
813 IN CHAR16 *PopUpString2,\r
814 OUT BOOLEAN *PressEsc\r
815 )\r
816{\r
817 EFI_INPUT_KEY InputKey;\r
818 UINTN InputLength;\r
819 CHAR16 Mask[OPAL_MAX_PASSWORD_SIZE + 1];\r
820 CHAR16 Unicode[OPAL_MAX_PASSWORD_SIZE + 1];\r
821 CHAR8 *Ascii;\r
822\r
823 ZeroMem(Unicode, sizeof(Unicode));\r
824 ZeroMem(Mask, sizeof(Mask));\r
825\r
826 *PressEsc = FALSE;\r
827\r
828 gST->ConOut->ClearScreen(gST->ConOut);\r
829\r
830 InputLength = 0;\r
831 while (TRUE) {\r
832 Mask[InputLength] = L'_';\r
833 if (PopUpString2 == NULL) {\r
834 CreatePopUp (\r
835 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
836 &InputKey,\r
837 PopUpString1,\r
838 L"---------------------",\r
839 Mask,\r
840 NULL\r
841 );\r
842 } else {\r
843 CreatePopUp (\r
844 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
845 &InputKey,\r
846 PopUpString1,\r
847 PopUpString2,\r
848 L"---------------------",\r
849 Mask,\r
850 NULL\r
851 );\r
852 }\r
853\r
854 //\r
855 // Check key.\r
856 //\r
857 if (InputKey.ScanCode == SCAN_NULL) {\r
858 //\r
859 // password finished\r
860 //\r
861 if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
862 //\r
863 // Add the null terminator.\r
864 //\r
865 Unicode[InputLength] = 0;\r
866 Mask[InputLength] = 0;\r
867 break;\r
868 } else if ((InputKey.UnicodeChar == CHAR_NULL) ||\r
869 (InputKey.UnicodeChar == CHAR_TAB) ||\r
870 (InputKey.UnicodeChar == CHAR_LINEFEED)\r
871 ) {\r
872 continue;\r
873 } else {\r
874 //\r
875 // delete last key entered\r
876 //\r
877 if (InputKey.UnicodeChar == CHAR_BACKSPACE) {\r
878 if (InputLength > 0) {\r
879 Unicode[InputLength] = 0;\r
880 Mask[InputLength] = 0;\r
881 InputLength--;\r
882 }\r
883 } else {\r
884 //\r
885 // add Next key entry\r
886 //\r
887 Unicode[InputLength] = InputKey.UnicodeChar;\r
888 Mask[InputLength] = L'*';\r
889 InputLength++;\r
890 if (InputLength == OPAL_MAX_PASSWORD_SIZE) {\r
891 //\r
892 // Add the null terminator.\r
893 //\r
894 Unicode[InputLength] = 0;\r
895 Mask[InputLength] = 0;\r
896 break;\r
897 }\r
898 }\r
899 }\r
900 }\r
901\r
902 //\r
903 // exit on ESC\r
904 //\r
905 if (InputKey.ScanCode == SCAN_ESC) {\r
906 *PressEsc = TRUE;\r
907 break;\r
908 }\r
909 }\r
910\r
911 gST->ConOut->ClearScreen(gST->ConOut);\r
912\r
913 if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {\r
914 ZeroMem (Unicode, sizeof (Unicode));\r
915 return NULL;\r
916 }\r
917\r
918 Ascii = AllocateZeroPool (OPAL_MAX_PASSWORD_SIZE + 1);\r
919 if (Ascii == NULL) {\r
920 ZeroMem (Unicode, sizeof (Unicode));\r
921 return NULL;\r
922 }\r
923\r
924 UnicodeStrToAsciiStrS (Unicode, Ascii, OPAL_MAX_PASSWORD_SIZE + 1);\r
925 ZeroMem (Unicode, sizeof (Unicode));\r
926\r
927 return Ascii;\r
928}\r
929\r
930/**\r
aa085730 931 Get pop up string.\r
112e584b 932\r
aa085730 933 @param[in] Dev The OPAL device.\r
112e584b
SZ
934 @param[in] RequestString Request string.\r
935\r
aa085730
SZ
936 @return Pop up string.\r
937\r
112e584b
SZ
938**/\r
939CHAR16 *\r
940OpalGetPopUpString (\r
941 IN OPAL_DRIVER_DEVICE *Dev,\r
942 IN CHAR16 *RequestString\r
943 )\r
944{\r
112e584b 945 if (Dev->Name16 == NULL) {\r
aa085730 946 UnicodeSPrint (mPopUpString, sizeof (mPopUpString), L"%s Disk", RequestString);\r
112e584b 947 } else {\r
aa085730 948 UnicodeSPrint (mPopUpString, sizeof (mPopUpString), L"%s %s", RequestString, Dev->Name16);\r
112e584b
SZ
949 }\r
950\r
951 return mPopUpString;\r
952}\r
953\r
954/**\r
955 Check if disk is locked, show popup window and ask for password if it is.\r
956\r
957 @param[in] Dev The device which need to be unlocked.\r
958 @param[in] RequestString Request string.\r
959\r
960**/\r
961VOID\r
962OpalDriverRequestPassword (\r
963 IN OPAL_DRIVER_DEVICE *Dev,\r
964 IN CHAR16 *RequestString\r
965 )\r
966{\r
967 UINT8 Count;\r
968 BOOLEAN IsEnabled;\r
969 BOOLEAN IsLocked;\r
970 CHAR8 *Password;\r
971 UINT32 PasswordLen;\r
972 OPAL_SESSION Session;\r
973 BOOLEAN PressEsc;\r
974 EFI_INPUT_KEY Key;\r
975 TCG_RESULT Ret;\r
976 CHAR16 *PopUpString;\r
977\r
978 if (Dev == NULL) {\r
979 return;\r
980 }\r
981\r
982 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
983\r
984 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
985\r
986 Count = 0;\r
987\r
988 IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);\r
989 if (IsEnabled) {\r
990 ZeroMem(&Session, sizeof(Session));\r
991 Session.Sscp = Dev->OpalDisk.Sscp;\r
992 Session.MediaId = Dev->OpalDisk.MediaId;\r
993 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
994\r
995 IsLocked = OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);\r
996\r
8a9301cd
CM
997 if (IsLocked && PcdGetBool (PcdSkipOpalDxeUnlock)) {\r
998 return;\r
999 }\r
1000\r
112e584b
SZ
1001 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
1002 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
1003 if (PressEsc) {\r
1004 if (IsLocked) {\r
1005 //\r
1006 // Current device in the lock status and\r
1007 // User not input password and press ESC,\r
1008 // keep device in lock status and continue boot.\r
1009 //\r
1010 do {\r
1011 CreatePopUp (\r
1012 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1013 &Key,\r
1014 L"Press ENTER to skip the request and continue boot,",\r
1015 L"Press ESC to input password again",\r
1016 NULL\r
1017 );\r
1018 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1019\r
1020 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1021 gST->ConOut->ClearScreen(gST->ConOut);\r
1022 //\r
1023 // Keep lock and continue boot.\r
1024 //\r
1025 return;\r
1026 } else {\r
1027 //\r
1028 // Let user input password again.\r
1029 //\r
1030 continue;\r
1031 }\r
1032 } else {\r
1033 //\r
1034 // Current device in the unlock status and\r
1035 // User not input password and press ESC,\r
1036 // Shutdown the device.\r
1037 //\r
1038 do {\r
1039 CreatePopUp (\r
1040 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1041 &Key,\r
1042 L"Press ENTER to shutdown, Press ESC to input password again",\r
1043 NULL\r
1044 );\r
1045 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1046\r
1047 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1048 gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
1049 } else {\r
1050 //\r
1051 // Let user input password again.\r
1052 //\r
1053 continue;\r
1054 }\r
1055 }\r
1056 }\r
1057\r
1058 if (Password == NULL) {\r
1059 Count ++;\r
1060 continue;\r
1061 }\r
1062 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1063\r
1064 if (IsLocked) {\r
1065 Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, FALSE, FALSE);\r
1066 } else {\r
1067 Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, TRUE, TRUE);\r
1068 if (Ret == TcgResultSuccess) {\r
1069 Ret = OpalUtilUpdateGlobalLockingRange(&Session, Password, PasswordLen, FALSE, FALSE);\r
1070 }\r
1071 }\r
1072\r
1073 if (Ret == TcgResultSuccess) {\r
1074 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1075 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1076 } else {\r
1077 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1078 }\r
1079\r
1080 if (Password != NULL) {\r
1081 ZeroMem (Password, PasswordLen);\r
1082 FreePool (Password);\r
1083 }\r
1084\r
1085 if (Ret == TcgResultSuccess) {\r
1086 break;\r
1087 }\r
1088\r
e4e314b1
ED
1089 //\r
1090 // Check whether opal device's Tries value has reach the TryLimit value, if yes, force a shutdown\r
1091 // before accept new password.\r
1092 //\r
1093 if (Ret == TcgResultFailureInvalidType) {\r
1094 Count = MAX_PASSWORD_TRY_COUNT;\r
1095 break;\r
1096 }\r
1097\r
112e584b
SZ
1098 Count++;\r
1099\r
1100 do {\r
1101 CreatePopUp (\r
1102 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1103 &Key,\r
1104 L"Invalid password.",\r
1105 L"Press ENTER to retry",\r
1106 NULL\r
1107 );\r
1108 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1109 }\r
1110\r
1111 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1112 do {\r
1113 CreatePopUp (\r
1114 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1115 &Key,\r
1116 L"Opal password retry count exceeds the limit. Must shutdown!",\r
1117 L"Press ENTER to shutdown",\r
1118 NULL\r
1119 );\r
1120 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1121\r
1122 gRT->ResetSystem (EfiResetShutdown, EFI_SUCCESS, 0, NULL);\r
1123 }\r
1124 }\r
1125}\r
1126\r
1127/**\r
1128 Process Enable Feature OPAL request.\r
1129\r
1130 @param[in] Dev The device which has Enable Feature OPAL request.\r
1131 @param[in] RequestString Request string.\r
1132\r
1133**/\r
1134VOID\r
1135ProcessOpalRequestEnableFeature (\r
1136 IN OPAL_DRIVER_DEVICE *Dev,\r
1137 IN CHAR16 *RequestString\r
1138 )\r
1139{\r
1140 UINT8 Count;\r
1141 CHAR8 *Password;\r
1142 UINT32 PasswordLen;\r
1143 CHAR8 *PasswordConfirm;\r
1144 UINT32 PasswordLenConfirm;\r
1145 OPAL_SESSION Session;\r
1146 BOOLEAN PressEsc;\r
1147 EFI_INPUT_KEY Key;\r
1148 TCG_RESULT Ret;\r
1149 CHAR16 *PopUpString;\r
1150\r
1151 if (Dev == NULL) {\r
1152 return;\r
1153 }\r
1154\r
1155 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1156\r
1157 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1158\r
1159 Count = 0;\r
1160\r
1161 ZeroMem(&Session, sizeof(Session));\r
1162 Session.Sscp = Dev->OpalDisk.Sscp;\r
1163 Session.MediaId = Dev->OpalDisk.MediaId;\r
1164 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1165\r
1166 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
1167 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);\r
1168 if (PressEsc) {\r
1169 do {\r
1170 CreatePopUp (\r
1171 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1172 &Key,\r
1173 L"Press ENTER to skip the request and continue boot,",\r
1174 L"Press ESC to input password again",\r
1175 NULL\r
1176 );\r
1177 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1178\r
1179 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1180 gST->ConOut->ClearScreen(gST->ConOut);\r
1181 return;\r
1182 } else {\r
1183 //\r
1184 // Let user input password again.\r
1185 //\r
1186 continue;\r
1187 }\r
1188 }\r
1189\r
1190 if (Password == NULL) {\r
1191 Count ++;\r
1192 continue;\r
1193 }\r
1194 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1195\r
1196 PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);\r
1197 if (PasswordConfirm == NULL) {\r
1198 ZeroMem (Password, PasswordLen);\r
1199 FreePool (Password);\r
1200 Count ++;\r
1201 continue;\r
1202 }\r
1203 PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);\r
1204 if ((PasswordLen != PasswordLenConfirm) ||\r
1205 (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {\r
1206 ZeroMem (Password, PasswordLen);\r
1207 FreePool (Password);\r
1208 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
1209 FreePool (PasswordConfirm);\r
1210 do {\r
1211 CreatePopUp (\r
1212 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1213 &Key,\r
1214 L"Passwords are not the same.",\r
1215 L"Press ENTER to retry",\r
1216 NULL\r
1217 );\r
1218 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1219 Count ++;\r
1220 continue;\r
1221 }\r
1222\r
1223 if (PasswordConfirm != NULL) {\r
1224 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
1225 FreePool (PasswordConfirm);\r
1226 }\r
1227\r
1228 Ret = OpalSupportEnableOpalFeature (&Session, Dev->OpalDisk.Msid, Dev->OpalDisk.MsidLength, Password, PasswordLen);\r
1229 if (Ret == TcgResultSuccess) {\r
1230 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1231 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1232 } else {\r
1233 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1234 }\r
1235\r
1236 if (Password != NULL) {\r
1237 ZeroMem (Password, PasswordLen);\r
1238 FreePool (Password);\r
1239 }\r
1240\r
1241 if (Ret == TcgResultSuccess) {\r
1242 break;\r
1243 }\r
1244\r
1245 Count++;\r
1246\r
1247 do {\r
1248 CreatePopUp (\r
1249 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1250 &Key,\r
1251 L"Request failed.",\r
1252 L"Press ENTER to retry",\r
1253 NULL\r
1254 );\r
1255 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1256 }\r
1257\r
1258 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1259 do {\r
1260 CreatePopUp (\r
1261 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1262 &Key,\r
1263 L"Opal password retry count exceeds the limit.",\r
1264 L"Press ENTER to skip the request and continue boot",\r
1265 NULL\r
1266 );\r
1267 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1268 gST->ConOut->ClearScreen(gST->ConOut);\r
1269 }\r
1270}\r
1271\r
1272/**\r
1273 Process Disable User OPAL request.\r
1274\r
1275 @param[in] Dev The device which has Disable User OPAL request.\r
1276 @param[in] RequestString Request string.\r
1277\r
1278**/\r
1279VOID\r
1280ProcessOpalRequestDisableUser (\r
1281 IN OPAL_DRIVER_DEVICE *Dev,\r
1282 IN CHAR16 *RequestString\r
1283 )\r
1284{\r
1285 UINT8 Count;\r
1286 CHAR8 *Password;\r
1287 UINT32 PasswordLen;\r
1288 OPAL_SESSION Session;\r
1289 BOOLEAN PressEsc;\r
1290 EFI_INPUT_KEY Key;\r
1291 TCG_RESULT Ret;\r
1292 BOOLEAN PasswordFailed;\r
1293 CHAR16 *PopUpString;\r
1294\r
1295 if (Dev == NULL) {\r
1296 return;\r
1297 }\r
1298\r
1299 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1300\r
1301 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1302\r
1303 Count = 0;\r
1304\r
1305 ZeroMem(&Session, sizeof(Session));\r
1306 Session.Sscp = Dev->OpalDisk.Sscp;\r
1307 Session.MediaId = Dev->OpalDisk.MediaId;\r
1308 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1309\r
1310 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
1311 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
1312 if (PressEsc) {\r
1313 do {\r
1314 CreatePopUp (\r
1315 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1316 &Key,\r
1317 L"Press ENTER to skip the request and continue boot,",\r
1318 L"Press ESC to input password again",\r
1319 NULL\r
1320 );\r
1321 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1322\r
1323 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1324 gST->ConOut->ClearScreen(gST->ConOut);\r
1325 return;\r
1326 } else {\r
1327 //\r
1328 // Let user input password again.\r
1329 //\r
1330 continue;\r
1331 }\r
1332 }\r
1333\r
1334 if (Password == NULL) {\r
1335 Count ++;\r
1336 continue;\r
1337 }\r
1338 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1339\r
1340 Ret = OpalUtilDisableUser(&Session, Password, PasswordLen, &PasswordFailed);\r
1341 if (Ret == TcgResultSuccess) {\r
1342 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1343 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1344 } else {\r
1345 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1346 }\r
1347\r
1348 if (Password != NULL) {\r
1349 ZeroMem (Password, PasswordLen);\r
1350 FreePool (Password);\r
1351 }\r
1352\r
1353 if (Ret == TcgResultSuccess) {\r
1354 break;\r
1355 }\r
1356\r
1357 Count++;\r
1358\r
1359 do {\r
1360 CreatePopUp (\r
1361 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1362 &Key,\r
1363 L"Invalid password, request failed.",\r
1364 L"Press ENTER to retry",\r
1365 NULL\r
1366 );\r
1367 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1368 }\r
1369\r
1370 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1371 do {\r
1372 CreatePopUp (\r
1373 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1374 &Key,\r
1375 L"Opal password retry count exceeds the limit.",\r
1376 L"Press ENTER to skip the request and continue boot",\r
1377 NULL\r
1378 );\r
1379 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1380 gST->ConOut->ClearScreen(gST->ConOut);\r
1381 }\r
1382}\r
1383\r
1384/**\r
1385 Process Psid Revert OPAL request.\r
1386\r
1387 @param[in] Dev The device which has Psid Revert OPAL request.\r
1388 @param[in] RequestString Request string.\r
1389\r
1390**/\r
1391VOID\r
1392ProcessOpalRequestPsidRevert (\r
1393 IN OPAL_DRIVER_DEVICE *Dev,\r
1394 IN CHAR16 *RequestString\r
1395 )\r
1396{\r
1397 UINT8 Count;\r
1398 CHAR8 *Psid;\r
1399 UINT32 PsidLen;\r
1400 OPAL_SESSION Session;\r
1401 BOOLEAN PressEsc;\r
1402 EFI_INPUT_KEY Key;\r
1403 TCG_RESULT Ret;\r
1404 CHAR16 *PopUpString;\r
40d32e79
ED
1405 CHAR16 *PopUpString2;\r
1406 UINTN BufferSize;\r
112e584b
SZ
1407\r
1408 if (Dev == NULL) {\r
1409 return;\r
1410 }\r
1411\r
1412 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1413\r
1414 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1415\r
40d32e79
ED
1416 if (Dev->OpalDisk.EstimateTimeCost > MAX_ACCEPTABLE_REVERTING_TIME) {\r
1417 BufferSize = StrSize (L"Warning: Revert action will take about ####### seconds, DO NOT power off system during the revert action!");\r
1418 PopUpString2 = AllocateZeroPool (BufferSize);\r
1419 ASSERT (PopUpString2 != NULL);\r
1420 UnicodeSPrint (\r
1421 PopUpString2,\r
1422 BufferSize,\r
1423 L"WARNING: Revert action will take about %d seconds, DO NOT power off system during the revert action!",\r
1424 Dev->OpalDisk.EstimateTimeCost\r
1425 );\r
1426 } else {\r
1427 PopUpString2 = NULL;\r
1428 }\r
1429\r
112e584b
SZ
1430 Count = 0;\r
1431\r
1432 ZeroMem(&Session, sizeof(Session));\r
1433 Session.Sscp = Dev->OpalDisk.Sscp;\r
1434 Session.MediaId = Dev->OpalDisk.MediaId;\r
1435 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1436\r
1437 while (Count < MAX_PSID_TRY_COUNT) {\r
40d32e79 1438 Psid = OpalDriverPopUpPsidInput (Dev, PopUpString, PopUpString2, &PressEsc);\r
112e584b
SZ
1439 if (PressEsc) {\r
1440 do {\r
1441 CreatePopUp (\r
1442 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1443 &Key,\r
1444 L"Press ENTER to skip the request and continue boot,",\r
1445 L"Press ESC to input Psid again",\r
1446 NULL\r
1447 );\r
1448 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1449\r
1450 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1451 gST->ConOut->ClearScreen(gST->ConOut);\r
40d32e79 1452 goto Done;\r
112e584b
SZ
1453 } else {\r
1454 //\r
1455 // Let user input Psid again.\r
1456 //\r
1457 continue;\r
1458 }\r
1459 }\r
1460\r
1461 if (Psid == NULL) {\r
1462 Count ++;\r
1463 continue;\r
1464 }\r
1465 PsidLen = (UINT32) AsciiStrLen(Psid);\r
1466\r
1467 Ret = OpalUtilPsidRevert(&Session, Psid, PsidLen);\r
1468 if (Ret == TcgResultSuccess) {\r
1469 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1470 } else {\r
1471 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1472 }\r
1473\r
1474 if (Psid != NULL) {\r
1475 ZeroMem (Psid, PsidLen);\r
1476 FreePool (Psid);\r
1477 }\r
1478\r
1479 if (Ret == TcgResultSuccess) {\r
1480 break;\r
1481 }\r
1482\r
1483 Count++;\r
1484\r
1485 do {\r
1486 CreatePopUp (\r
1487 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1488 &Key,\r
1489 L"Invalid Psid, request failed.",\r
1490 L"Press ENTER to retry",\r
1491 NULL\r
1492 );\r
1493 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1494 }\r
1495\r
1496 if (Count >= MAX_PSID_TRY_COUNT) {\r
1497 do {\r
1498 CreatePopUp (\r
1499 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1500 &Key,\r
1501 L"Opal Psid retry count exceeds the limit.",\r
1502 L"Press ENTER to skip the request and continue boot",\r
1503 NULL\r
1504 );\r
1505 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1506 gST->ConOut->ClearScreen(gST->ConOut);\r
1507 }\r
40d32e79
ED
1508\r
1509Done:\r
1510 if (PopUpString2 != NULL) {\r
1511 FreePool (PopUpString2);\r
1512 }\r
112e584b
SZ
1513}\r
1514\r
1515/**\r
1516 Process Admin Revert OPAL request.\r
1517\r
1518 @param[in] Dev The device which has Revert OPAL request.\r
1519 @param[in] KeepUserData Whether to keep user data or not.\r
1520 @param[in] RequestString Request string.\r
1521\r
1522**/\r
1523VOID\r
1524ProcessOpalRequestRevert (\r
1525 IN OPAL_DRIVER_DEVICE *Dev,\r
1526 IN BOOLEAN KeepUserData,\r
1527 IN CHAR16 *RequestString\r
1528 )\r
1529{\r
1530 UINT8 Count;\r
1531 CHAR8 *Password;\r
1532 UINT32 PasswordLen;\r
1533 OPAL_SESSION Session;\r
1534 BOOLEAN PressEsc;\r
1535 EFI_INPUT_KEY Key;\r
1536 TCG_RESULT Ret;\r
1537 BOOLEAN PasswordFailed;\r
1538 CHAR16 *PopUpString;\r
40d32e79
ED
1539 CHAR16 *PopUpString2;\r
1540 UINTN BufferSize;\r
112e584b
SZ
1541\r
1542 if (Dev == NULL) {\r
1543 return;\r
1544 }\r
1545\r
1546 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1547\r
1548 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1549\r
4ec00f82
CM
1550 if ((!KeepUserData) &&\r
1551 (Dev->OpalDisk.EstimateTimeCost > MAX_ACCEPTABLE_REVERTING_TIME)) {\r
40d32e79
ED
1552 BufferSize = StrSize (L"Warning: Revert action will take about ####### seconds, DO NOT power off system during the revert action!");\r
1553 PopUpString2 = AllocateZeroPool (BufferSize);\r
1554 ASSERT (PopUpString2 != NULL);\r
1555 UnicodeSPrint (\r
1556 PopUpString2,\r
1557 BufferSize,\r
1558 L"WARNING: Revert action will take about %d seconds, DO NOT power off system during the revert action!",\r
1559 Dev->OpalDisk.EstimateTimeCost\r
1560 );\r
1561 } else {\r
1562 PopUpString2 = NULL;\r
1563 }\r
1564\r
112e584b
SZ
1565 Count = 0;\r
1566\r
1567 ZeroMem(&Session, sizeof(Session));\r
1568 Session.Sscp = Dev->OpalDisk.Sscp;\r
1569 Session.MediaId = Dev->OpalDisk.MediaId;\r
1570 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1571\r
1572 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
40d32e79 1573 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, PopUpString2, &PressEsc);\r
112e584b
SZ
1574 if (PressEsc) {\r
1575 do {\r
1576 CreatePopUp (\r
1577 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1578 &Key,\r
1579 L"Press ENTER to skip the request and continue boot,",\r
1580 L"Press ESC to input password again",\r
1581 NULL\r
1582 );\r
1583 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1584\r
1585 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1586 gST->ConOut->ClearScreen(gST->ConOut);\r
40d32e79 1587 goto Done;\r
112e584b
SZ
1588 } else {\r
1589 //\r
1590 // Let user input password again.\r
1591 //\r
1592 continue;\r
1593 }\r
1594 }\r
1595\r
1596 if (Password == NULL) {\r
1597 Count ++;\r
1598 continue;\r
1599 }\r
1600 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1601\r
1602 if ((Dev->OpalDisk.SupportedAttributes.PyriteSsc == 1) &&\r
1603 (Dev->OpalDisk.LockingFeature.MediaEncryption == 0)) {\r
1604 //\r
1605 // For pyrite type device which does not support media encryption,\r
1606 // it does not accept "Keep User Data" parameter.\r
1607 // So here hardcode a FALSE for this case.\r
1608 //\r
1609 Ret = OpalUtilRevert(\r
1610 &Session,\r
1611 FALSE,\r
1612 Password,\r
1613 PasswordLen,\r
1614 &PasswordFailed,\r
1615 Dev->OpalDisk.Msid,\r
1616 Dev->OpalDisk.MsidLength\r
1617 );\r
1618 } else {\r
1619 Ret = OpalUtilRevert(\r
1620 &Session,\r
1621 KeepUserData,\r
1622 Password,\r
1623 PasswordLen,\r
1624 &PasswordFailed,\r
1625 Dev->OpalDisk.Msid,\r
1626 Dev->OpalDisk.MsidLength\r
1627 );\r
1628 }\r
1629 if (Ret == TcgResultSuccess) {\r
1630 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1631 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1632 } else {\r
1633 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1634 }\r
1635\r
1636 if (Password != NULL) {\r
1637 ZeroMem (Password, PasswordLen);\r
1638 FreePool (Password);\r
1639 }\r
1640\r
1641 if (Ret == TcgResultSuccess) {\r
1642 break;\r
1643 }\r
1644\r
1645 Count++;\r
1646\r
1647 do {\r
1648 CreatePopUp (\r
1649 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1650 &Key,\r
1651 L"Invalid password, request failed.",\r
1652 L"Press ENTER to retry",\r
1653 NULL\r
1654 );\r
1655 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1656 }\r
1657\r
1658 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1659 do {\r
1660 CreatePopUp (\r
1661 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1662 &Key,\r
1663 L"Opal password retry count exceeds the limit.",\r
1664 L"Press ENTER to skip the request and continue boot",\r
1665 NULL\r
1666 );\r
1667 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1668 gST->ConOut->ClearScreen(gST->ConOut);\r
1669 }\r
40d32e79
ED
1670\r
1671Done:\r
1672 if (PopUpString2 != NULL) {\r
1673 FreePool (PopUpString2);\r
1674 }\r
112e584b
SZ
1675}\r
1676\r
1677/**\r
1678 Process Secure Erase OPAL request.\r
1679\r
1680 @param[in] Dev The device which has Secure Erase OPAL request.\r
1681 @param[in] RequestString Request string.\r
1682\r
1683**/\r
1684VOID\r
1685ProcessOpalRequestSecureErase (\r
1686 IN OPAL_DRIVER_DEVICE *Dev,\r
1687 IN CHAR16 *RequestString\r
1688 )\r
1689{\r
1690 UINT8 Count;\r
1691 CHAR8 *Password;\r
1692 UINT32 PasswordLen;\r
1693 OPAL_SESSION Session;\r
1694 BOOLEAN PressEsc;\r
1695 EFI_INPUT_KEY Key;\r
1696 TCG_RESULT Ret;\r
1697 BOOLEAN PasswordFailed;\r
1698 CHAR16 *PopUpString;\r
1699\r
1700 if (Dev == NULL) {\r
1701 return;\r
1702 }\r
1703\r
1704 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1705\r
1706 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1707\r
1708 Count = 0;\r
1709\r
1710 ZeroMem(&Session, sizeof(Session));\r
1711 Session.Sscp = Dev->OpalDisk.Sscp;\r
1712 Session.MediaId = Dev->OpalDisk.MediaId;\r
1713 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1714\r
1715 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
1716 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
1717 if (PressEsc) {\r
1718 do {\r
1719 CreatePopUp (\r
1720 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1721 &Key,\r
1722 L"Press ENTER to skip the request and continue boot,",\r
1723 L"Press ESC to input password again",\r
1724 NULL\r
1725 );\r
1726 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1727\r
1728 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1729 gST->ConOut->ClearScreen(gST->ConOut);\r
1730 return;\r
1731 } else {\r
1732 //\r
1733 // Let user input password again.\r
1734 //\r
1735 continue;\r
1736 }\r
1737 }\r
1738\r
1739 if (Password == NULL) {\r
1740 Count ++;\r
1741 continue;\r
1742 }\r
1743 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1744\r
1745 Ret = OpalUtilSecureErase(&Session, Password, PasswordLen, &PasswordFailed);\r
1746 if (Ret == TcgResultSuccess) {\r
1747 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1748 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1749 } else {\r
1750 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1751 }\r
1752\r
1753 if (Password != NULL) {\r
1754 ZeroMem (Password, PasswordLen);\r
1755 FreePool (Password);\r
1756 }\r
1757\r
1758 if (Ret == TcgResultSuccess) {\r
1759 break;\r
1760 }\r
1761\r
1762 Count++;\r
1763\r
1764 do {\r
1765 CreatePopUp (\r
1766 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1767 &Key,\r
1768 L"Invalid password, request failed.",\r
1769 L"Press ENTER to retry",\r
1770 NULL\r
1771 );\r
1772 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1773 }\r
1774\r
1775 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1776 do {\r
1777 CreatePopUp (\r
1778 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1779 &Key,\r
1780 L"Opal password retry count exceeds the limit.",\r
1781 L"Press ENTER to skip the request and continue boot",\r
1782 NULL\r
1783 );\r
1784 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1785 gST->ConOut->ClearScreen(gST->ConOut);\r
1786 }\r
1787}\r
1788\r
1789/**\r
1790 Process Set Admin Pwd OPAL request.\r
1791\r
1792 @param[in] Dev The device which has Set Admin Pwd Feature OPAL request.\r
1793 @param[in] RequestString Request string.\r
1794\r
1795**/\r
1796VOID\r
1797ProcessOpalRequestSetUserPwd (\r
1798 IN OPAL_DRIVER_DEVICE *Dev,\r
1799 IN CHAR16 *RequestString\r
1800 )\r
1801{\r
1802 UINT8 Count;\r
1803 CHAR8 *OldPassword;\r
1804 UINT32 OldPasswordLen;\r
1805 CHAR8 *Password;\r
1806 UINT32 PasswordLen;\r
1807 CHAR8 *PasswordConfirm;\r
1808 UINT32 PasswordLenConfirm;\r
1809 OPAL_SESSION Session;\r
1810 BOOLEAN PressEsc;\r
1811 EFI_INPUT_KEY Key;\r
1812 TCG_RESULT Ret;\r
1813 CHAR16 *PopUpString;\r
1814\r
1815 if (Dev == NULL) {\r
1816 return;\r
1817 }\r
1818\r
1819 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1820\r
1821 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1822\r
1823 Count = 0;\r
1824\r
1825 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
1826 OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);\r
1827 if (PressEsc) {\r
1828 do {\r
1829 CreatePopUp (\r
1830 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1831 &Key,\r
1832 L"Press ENTER to skip the request and continue boot,",\r
1833 L"Press ESC to input password again",\r
1834 NULL\r
1835 );\r
1836 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1837\r
1838 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1839 gST->ConOut->ClearScreen(gST->ConOut);\r
1840 return;\r
1841 } else {\r
1842 //\r
1843 // Let user input password again.\r
1844 //\r
1845 continue;\r
1846 }\r
1847 }\r
1848\r
1849 if (OldPassword == NULL) {\r
1850 Count ++;\r
1851 continue;\r
1852 }\r
1853 OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);\r
1854\r
1855 ZeroMem(&Session, sizeof(Session));\r
1856 Session.Sscp = Dev->OpalDisk.Sscp;\r
1857 Session.MediaId = Dev->OpalDisk.MediaId;\r
1858 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1859 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_USER1_AUTHORITY);\r
1860 if (Ret == TcgResultSuccess) {\r
1861 DEBUG ((DEBUG_INFO, "Verify with USER1 authority : Success\n"));\r
1862 } else {\r
1863 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);\r
1864 if (Ret == TcgResultSuccess) {\r
1865 DEBUG ((DEBUG_INFO, "Verify with ADMIN1 authority: Success\n"));\r
1866 } else {\r
1867 ZeroMem (OldPassword, OldPasswordLen);\r
1868 FreePool (OldPassword);\r
1869 DEBUG ((DEBUG_INFO, "Verify: Failure\n"));\r
1870 do {\r
1871 CreatePopUp (\r
1872 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1873 &Key,\r
1874 L"Incorrect password.",\r
1875 L"Press ENTER to retry",\r
1876 NULL\r
1877 );\r
1878 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1879 Count ++;\r
1880 continue;\r
1881 }\r
1882 }\r
1883\r
1884 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);\r
1885 if (Password == NULL) {\r
1886 ZeroMem (OldPassword, OldPasswordLen);\r
1887 FreePool (OldPassword);\r
1888 Count ++;\r
1889 continue;\r
1890 }\r
1891 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1892\r
1893 PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);\r
1894 if (PasswordConfirm == NULL) {\r
1895 ZeroMem (OldPassword, OldPasswordLen);\r
1896 FreePool (OldPassword);\r
1897 ZeroMem (Password, PasswordLen);\r
1898 FreePool (Password);\r
1899 Count ++;\r
1900 continue;\r
1901 }\r
1902 PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);\r
1903 if ((PasswordLen != PasswordLenConfirm) ||\r
1904 (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {\r
1905 ZeroMem (OldPassword, OldPasswordLen);\r
1906 FreePool (OldPassword);\r
1907 ZeroMem (Password, PasswordLen);\r
1908 FreePool (Password);\r
1909 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
1910 FreePool (PasswordConfirm);\r
1911 do {\r
1912 CreatePopUp (\r
1913 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1914 &Key,\r
1915 L"Passwords are not the same.",\r
1916 L"Press ENTER to retry",\r
1917 NULL\r
1918 );\r
1919 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1920 Count ++;\r
1921 continue;\r
1922 }\r
1923\r
1924 if (PasswordConfirm != NULL) {\r
1925 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
1926 FreePool (PasswordConfirm);\r
1927 }\r
1928\r
1929 ZeroMem(&Session, sizeof(Session));\r
1930 Session.Sscp = Dev->OpalDisk.Sscp;\r
1931 Session.MediaId = Dev->OpalDisk.MediaId;\r
1932 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1933 Ret = OpalUtilSetUserPassword(\r
1934 &Session,\r
1935 OldPassword,\r
1936 OldPasswordLen,\r
1937 Password,\r
1938 PasswordLen\r
1939 );\r
1940 if (Ret == TcgResultSuccess) {\r
1941 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1942 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1943 } else {\r
1944 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1945 }\r
1946\r
1947 if (OldPassword != NULL) {\r
1948 ZeroMem (OldPassword, OldPasswordLen);\r
1949 FreePool (OldPassword);\r
1950 }\r
1951\r
1952 if (Password != NULL) {\r
1953 ZeroMem (Password, PasswordLen);\r
1954 FreePool (Password);\r
1955 }\r
1956\r
1957 if (Ret == TcgResultSuccess) {\r
1958 break;\r
1959 }\r
1960\r
1961 Count++;\r
1962\r
1963 do {\r
1964 CreatePopUp (\r
1965 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1966 &Key,\r
1967 L"Request failed.",\r
1968 L"Press ENTER to retry",\r
1969 NULL\r
1970 );\r
1971 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1972 }\r
1973\r
1974 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1975 do {\r
1976 CreatePopUp (\r
1977 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1978 &Key,\r
1979 L"Opal password retry count exceeds the limit.",\r
1980 L"Press ENTER to skip the request and continue boot",\r
1981 NULL\r
1982 );\r
1983 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1984 gST->ConOut->ClearScreen(gST->ConOut);\r
1985 }\r
1986}\r
1987\r
1988/**\r
1989 Process Set Admin Pwd OPAL request.\r
1990\r
1991 @param[in] Dev The device which has Set Admin Pwd Feature OPAL request.\r
1992 @param[in] RequestString Request string.\r
1993\r
1994**/\r
1995VOID\r
1996ProcessOpalRequestSetAdminPwd (\r
1997 IN OPAL_DRIVER_DEVICE *Dev,\r
1998 IN CHAR16 *RequestString\r
1999 )\r
2000{\r
2001 UINT8 Count;\r
2002 CHAR8 *OldPassword;\r
2003 UINT32 OldPasswordLen;\r
2004 CHAR8 *Password;\r
2005 UINT32 PasswordLen;\r
2006 CHAR8 *PasswordConfirm;\r
2007 UINT32 PasswordLenConfirm;\r
2008 OPAL_SESSION Session;\r
2009 BOOLEAN PressEsc;\r
2010 EFI_INPUT_KEY Key;\r
2011 TCG_RESULT Ret;\r
2012 CHAR16 *PopUpString;\r
2013\r
2014 if (Dev == NULL) {\r
2015 return;\r
2016 }\r
2017\r
2018 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
2019\r
2020 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
2021\r
2022 Count = 0;\r
2023\r
2024 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
2025 OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);\r
2026 if (PressEsc) {\r
2027 do {\r
2028 CreatePopUp (\r
2029 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2030 &Key,\r
2031 L"Press ENTER to skip the request and continue boot,",\r
2032 L"Press ESC to input password again",\r
2033 NULL\r
2034 );\r
2035 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
2036\r
2037 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
2038 gST->ConOut->ClearScreen(gST->ConOut);\r
2039 return;\r
2040 } else {\r
2041 //\r
2042 // Let user input password again.\r
2043 //\r
2044 continue;\r
2045 }\r
2046 }\r
2047\r
2048 if (OldPassword == NULL) {\r
2049 Count ++;\r
2050 continue;\r
2051 }\r
2052 OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);\r
2053\r
2054 ZeroMem(&Session, sizeof(Session));\r
2055 Session.Sscp = Dev->OpalDisk.Sscp;\r
2056 Session.MediaId = Dev->OpalDisk.MediaId;\r
2057 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
2058 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);\r
2059 if (Ret == TcgResultSuccess) {\r
2060 DEBUG ((DEBUG_INFO, "Verify: Success\n"));\r
2061 } else {\r
2062 ZeroMem (OldPassword, OldPasswordLen);\r
2063 FreePool (OldPassword);\r
2064 DEBUG ((DEBUG_INFO, "Verify: Failure\n"));\r
2065 do {\r
2066 CreatePopUp (\r
2067 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2068 &Key,\r
2069 L"Incorrect password.",\r
2070 L"Press ENTER to retry",\r
2071 NULL\r
2072 );\r
2073 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2074 Count ++;\r
2075 continue;\r
2076 }\r
2077\r
2078 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);\r
2079 if (Password == NULL) {\r
2080 ZeroMem (OldPassword, OldPasswordLen);\r
2081 FreePool (OldPassword);\r
2082 Count ++;\r
2083 continue;\r
2084 }\r
2085 PasswordLen = (UINT32) AsciiStrLen(Password);\r
2086\r
2087 PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);\r
2088 if (PasswordConfirm == NULL) {\r
2089 ZeroMem (OldPassword, OldPasswordLen);\r
2090 FreePool (OldPassword);\r
2091 ZeroMem (Password, PasswordLen);\r
2092 FreePool (Password);\r
2093 Count ++;\r
2094 continue;\r
2095 }\r
2096 PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);\r
2097 if ((PasswordLen != PasswordLenConfirm) ||\r
2098 (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {\r
2099 ZeroMem (OldPassword, OldPasswordLen);\r
2100 FreePool (OldPassword);\r
2101 ZeroMem (Password, PasswordLen);\r
2102 FreePool (Password);\r
2103 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
2104 FreePool (PasswordConfirm);\r
2105 do {\r
2106 CreatePopUp (\r
2107 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2108 &Key,\r
2109 L"Passwords are not the same.",\r
2110 L"Press ENTER to retry",\r
2111 NULL\r
2112 );\r
2113 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2114 Count ++;\r
2115 continue;\r
2116 }\r
2117\r
2118 if (PasswordConfirm != NULL) {\r
2119 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
2120 FreePool (PasswordConfirm);\r
2121 }\r
2122\r
2123\r
2124 ZeroMem(&Session, sizeof(Session));\r
2125 Session.Sscp = Dev->OpalDisk.Sscp;\r
2126 Session.MediaId = Dev->OpalDisk.MediaId;\r
2127 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
2128 Ret = OpalUtilSetAdminPassword(\r
2129 &Session,\r
2130 OldPassword,\r
2131 OldPasswordLen,\r
2132 Password,\r
2133 PasswordLen\r
2134 );\r
2135 if (Ret == TcgResultSuccess) {\r
2136 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
2137 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
2138 } else {\r
2139 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
2140 }\r
2141\r
2142 if (OldPassword != NULL) {\r
2143 ZeroMem (OldPassword, OldPasswordLen);\r
2144 FreePool (OldPassword);\r
2145 }\r
2146\r
2147 if (Password != NULL) {\r
2148 ZeroMem (Password, PasswordLen);\r
2149 FreePool (Password);\r
2150 }\r
2151\r
2152 if (Ret == TcgResultSuccess) {\r
2153 break;\r
2154 }\r
2155\r
2156 Count++;\r
2157\r
2158 do {\r
2159 CreatePopUp (\r
2160 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2161 &Key,\r
2162 L"Request failed.",\r
2163 L"Press ENTER to retry",\r
2164 NULL\r
2165 );\r
2166 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2167 }\r
2168\r
2169 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
2170 do {\r
2171 CreatePopUp (\r
2172 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2173 &Key,\r
2174 L"Opal password retry count exceeds the limit.",\r
2175 L"Press ENTER to skip the request and continue boot",\r
2176 NULL\r
2177 );\r
2178 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2179 gST->ConOut->ClearScreen(gST->ConOut);\r
2180 }\r
2181}\r
2182\r
2183/**\r
2184 Process OPAL request.\r
2185\r
2186 @param[in] Dev The device which has OPAL request.\r
2187\r
2188**/\r
2189VOID\r
2190ProcessOpalRequest (\r
2191 IN OPAL_DRIVER_DEVICE *Dev\r
2192 )\r
2193{\r
2194 EFI_STATUS Status;\r
2195 OPAL_REQUEST_VARIABLE *TempVariable;\r
2196 OPAL_REQUEST_VARIABLE *Variable;\r
2197 UINTN VariableSize;\r
2198 EFI_DEVICE_PATH_PROTOCOL *DevicePathInVariable;\r
2199 UINTN DevicePathSizeInVariable;\r
2200 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2201 UINTN DevicePathSize;\r
2202 BOOLEAN KeepUserData;\r
2203\r
2204 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
2205\r
2206 if (mOpalRequestVariable == NULL) {\r
2207 Status = GetVariable2 (\r
2208 OPAL_REQUEST_VARIABLE_NAME,\r
2209 &gHiiSetupVariableGuid,\r
2210 (VOID **) &Variable,\r
2211 &VariableSize\r
2212 );\r
2213 if (EFI_ERROR (Status) || (Variable == NULL)) {\r
2214 return;\r
2215 }\r
2216 mOpalRequestVariable = Variable;\r
2217 mOpalRequestVariableSize = VariableSize;\r
2218\r
2219 //\r
2220 // Delete the OPAL request variable.\r
2221 //\r
2222 Status = gRT->SetVariable (\r
2223 OPAL_REQUEST_VARIABLE_NAME,\r
2224 (EFI_GUID *) &gHiiSetupVariableGuid,\r
2225 0,\r
2226 0,\r
2227 NULL\r
2228 );\r
2229 ASSERT_EFI_ERROR (Status);\r
2230 } else {\r
2231 Variable = mOpalRequestVariable;\r
2232 VariableSize = mOpalRequestVariableSize;\r
2233 }\r
2234\r
2235 //\r
2236 // Process the OPAL requests.\r
2237 //\r
2238 TempVariable = Variable;\r
2239 while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&\r
2240 (VariableSize >= TempVariable->Length) &&\r
2241 (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {\r
2242 DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));\r
2243 DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);\r
2244 DevicePath = Dev->OpalDisk.OpalDevicePath;\r
2245 DevicePathSize = GetDevicePathSize (DevicePath);\r
2246 if ((DevicePathSize == DevicePathSizeInVariable) &&\r
2247 (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) {\r
2248 //\r
2249 // Found the node for the OPAL device.\r
2250 //\r
2251 if (TempVariable->OpalRequest.SetAdminPwd != 0) {\r
2252 ProcessOpalRequestSetAdminPwd (Dev, L"Update Admin Pwd:");\r
2253 }\r
2254 if (TempVariable->OpalRequest.SetUserPwd != 0) {\r
2255 ProcessOpalRequestSetUserPwd (Dev, L"Set User Pwd:");\r
2256 }\r
2257 if (TempVariable->OpalRequest.SecureErase!= 0) {\r
2258 ProcessOpalRequestSecureErase (Dev, L"Secure Erase:");\r
2259 }\r
2260 if (TempVariable->OpalRequest.Revert != 0) {\r
2261 KeepUserData = (BOOLEAN) TempVariable->OpalRequest.KeepUserData;\r
2262 ProcessOpalRequestRevert (\r
2263 Dev,\r
2264 KeepUserData,\r
2265 KeepUserData ? L"Admin Revert(keep):" : L"Admin Revert:"\r
2266 );\r
2267 }\r
2268 if (TempVariable->OpalRequest.PsidRevert != 0) {\r
2269 ProcessOpalRequestPsidRevert (Dev, L"Psid Revert:");\r
2270 }\r
2271 if (TempVariable->OpalRequest.DisableUser != 0) {\r
2272 ProcessOpalRequestDisableUser (Dev, L"Disable User:");\r
2273 }\r
2274 if (TempVariable->OpalRequest.EnableFeature != 0) {\r
2275 ProcessOpalRequestEnableFeature (Dev, L"Enable Feature:");\r
2276 }\r
2277\r
2278 break;\r
2279 }\r
2280\r
2281 VariableSize -= TempVariable->Length;\r
2282 TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length);\r
2283 }\r
2284\r
2285 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
2286}\r
2287\r
2288/**\r
2289 Add new device to the global device list.\r
2290\r
2291 @param Dev New create device.\r
2292\r
2293**/\r
2294VOID\r
2295AddDeviceToTail(\r
2296 IN OPAL_DRIVER_DEVICE *Dev\r
2297 )\r
2298{\r
2299 OPAL_DRIVER_DEVICE *TmpDev;\r
2300\r
2301 if (mOpalDriver.DeviceList == NULL) {\r
2302 mOpalDriver.DeviceList = Dev;\r
2303 } else {\r
2304 TmpDev = mOpalDriver.DeviceList;\r
2305 while (TmpDev->Next != NULL) {\r
2306 TmpDev = TmpDev->Next;\r
2307 }\r
2308\r
2309 TmpDev->Next = Dev;\r
2310 }\r
2311}\r
2312\r
2313/**\r
2314 Remove one device in the global device list.\r
2315\r
2316 @param Dev The device need to be removed.\r
2317\r
2318**/\r
2319VOID\r
2320RemoveDevice (\r
2321 IN OPAL_DRIVER_DEVICE *Dev\r
2322 )\r
2323{\r
2324 OPAL_DRIVER_DEVICE *TmpDev;\r
2325\r
2326 if (mOpalDriver.DeviceList == NULL) {\r
2327 return;\r
2328 }\r
2329\r
2330 if (mOpalDriver.DeviceList == Dev) {\r
2331 mOpalDriver.DeviceList = NULL;\r
2332 return;\r
2333 }\r
2334\r
2335 TmpDev = mOpalDriver.DeviceList;\r
2336 while (TmpDev->Next != NULL) {\r
2337 if (TmpDev->Next == Dev) {\r
2338 TmpDev->Next = Dev->Next;\r
2339 break;\r
2340 }\r
2341 }\r
2342}\r
2343\r
2344/**\r
2345 Get current device count.\r
2346\r
2347 @retval return the current created device count.\r
2348\r
2349**/\r
2350UINT8\r
2351GetDeviceCount (\r
2352 VOID\r
2353 )\r
2354{\r
2355 UINT8 Count;\r
2356 OPAL_DRIVER_DEVICE *TmpDev;\r
2357\r
2358 Count = 0;\r
2359 TmpDev = mOpalDriver.DeviceList;\r
2360\r
2361 while (TmpDev != NULL) {\r
2362 Count++;\r
2363 TmpDev = TmpDev->Next;\r
2364 }\r
2365\r
2366 return Count;\r
2367}\r
2368\r
2369/**\r
2370 Get devcie list info.\r
2371\r
2372 @retval return the device list pointer.\r
2373**/\r
2374OPAL_DRIVER_DEVICE*\r
2375OpalDriverGetDeviceList(\r
2376 VOID\r
2377 )\r
2378{\r
2379 return mOpalDriver.DeviceList;\r
2380}\r
2381\r
2382/**\r
2383 ReadyToBoot callback to send BlockSid command.\r
2384\r
2385 @param Event Pointer to this event\r
2386 @param Context Event handler private Data\r
2387\r
2388**/\r
2389VOID\r
2390EFIAPI\r
2391ReadyToBootCallback (\r
2392 IN EFI_EVENT Event,\r
2393 IN VOID *Context\r
2394 )\r
2395{\r
2396 OPAL_DRIVER_DEVICE *Itr;\r
2397 TCG_RESULT Result;\r
2398 OPAL_SESSION Session;\r
2399 UINT32 PpStorageFlag;\r
2400\r
2401 gBS->CloseEvent (Event);\r
2402\r
2403 PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();\r
2404 if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {\r
2405 //\r
2406 // Send BlockSID command to each Opal disk\r
2407 //\r
2408 Itr = mOpalDriver.DeviceList;\r
2409 while (Itr != NULL) {\r
2410 if (Itr->OpalDisk.SupportedAttributes.BlockSid) {\r
2411 ZeroMem(&Session, sizeof(Session));\r
2412 Session.Sscp = Itr->OpalDisk.Sscp;\r
2413 Session.MediaId = Itr->OpalDisk.MediaId;\r
2414 Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;\r
2415\r
40d32e79 2416 DEBUG ((DEBUG_INFO, "OpalPassword: ReadyToBoot point, send BlockSid command to device!\n"));\r
112e584b
SZ
2417 Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE\r
2418 if (Result != TcgResultSuccess) {\r
2419 DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));\r
2420 break;\r
2421 }\r
2422 }\r
2423\r
2424 Itr = Itr->Next;\r
2425 }\r
2426 }\r
2427}\r
2428\r
2429/**\r
2430 Stop this Controller.\r
2431\r
2432 @param Dev The device need to be stopped.\r
2433\r
2434**/\r
2435VOID\r
2436OpalDriverStopDevice (\r
2437 OPAL_DRIVER_DEVICE *Dev\r
2438 )\r
2439{\r
2440 //\r
2441 // free each name\r
2442 //\r
2443 FreePool(Dev->Name16);\r
2444\r
2445 //\r
2446 // remove OPAL_DRIVER_DEVICE from the list\r
2447 // it updates the controllerList pointer\r
2448 //\r
2449 RemoveDevice(Dev);\r
2450\r
2451 //\r
2452 // close protocols that were opened\r
2453 //\r
2454 gBS->CloseProtocol(\r
2455 Dev->Handle,\r
2456 &gEfiStorageSecurityCommandProtocolGuid,\r
2457 gOpalDriverBinding.DriverBindingHandle,\r
2458 Dev->Handle\r
2459 );\r
2460\r
2461 gBS->CloseProtocol(\r
2462 Dev->Handle,\r
2463 &gEfiBlockIoProtocolGuid,\r
2464 gOpalDriverBinding.DriverBindingHandle,\r
2465 Dev->Handle\r
2466 );\r
2467\r
2468 FreePool(Dev);\r
2469}\r
2470\r
2471/**\r
2472 Get devcie name through the component name protocol.\r
2473\r
2474 @param[in] AllHandlesBuffer The handle buffer for current system.\r
2475 @param[in] NumAllHandles The number of handles for the handle buffer.\r
2476 @param[in] Dev The device which need to get name.\r
2477 @param[in] UseComp1 Whether use component name or name2 protocol.\r
2478\r
2479 @retval TRUE Find the name for this device.\r
2480 @retval FALSE Not found the name for this device.\r
2481**/\r
2482BOOLEAN\r
2483OpalDriverGetDeviceNameByProtocol(\r
2484 EFI_HANDLE *AllHandlesBuffer,\r
2485 UINTN NumAllHandles,\r
2486 OPAL_DRIVER_DEVICE *Dev,\r
2487 BOOLEAN UseComp1\r
2488 )\r
2489{\r
2490 EFI_HANDLE* ProtocolHandlesBuffer;\r
2491 UINTN NumProtocolHandles;\r
2492 EFI_STATUS Status;\r
2493 EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout\r
2494 EFI_GUID Protocol;\r
2495 UINTN StrLength;\r
2496 EFI_DEVICE_PATH_PROTOCOL* TmpDevPath;\r
2497 UINTN Index1;\r
2498 UINTN Index2;\r
2499 EFI_HANDLE TmpHandle;\r
2500 CHAR16 *DevName;\r
2501\r
2502 if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {\r
2503 return FALSE;\r
2504 }\r
2505\r
2506 Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;\r
2507\r
2508 //\r
2509 // Find all EFI_HANDLES with protocol\r
2510 //\r
2511 Status = gBS->LocateHandleBuffer(\r
2512 ByProtocol,\r
2513 &Protocol,\r
2514 NULL,\r
2515 &NumProtocolHandles,\r
2516 &ProtocolHandlesBuffer\r
2517 );\r
2518 if (EFI_ERROR(Status)) {\r
2519 return FALSE;\r
2520 }\r
2521\r
2522\r
2523 //\r
2524 // Exit early if no supported devices\r
2525 //\r
2526 if (NumProtocolHandles == 0) {\r
2527 return FALSE;\r
2528 }\r
2529\r
2530 //\r
2531 // Get printable name by iterating through all protocols\r
2532 // using the handle as the child, and iterate through all handles for the controller\r
2533 // exit loop early once found, if not found, then delete device\r
2534 // storage security protocol instances already exist, add them to internal list\r
2535 //\r
2536 Status = EFI_DEVICE_ERROR;\r
2537 for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {\r
2538 DevName = NULL;\r
2539\r
2540 if (Dev->Name16 != NULL) {\r
2541 return TRUE;\r
2542 }\r
2543\r
2544 TmpHandle = ProtocolHandlesBuffer[Index1];\r
2545\r
2546 Status = gBS->OpenProtocol(\r
2547 TmpHandle,\r
2548 &Protocol,\r
2549 (VOID**)&Cnp1_2,\r
2550 gImageHandle,\r
2551 NULL,\r
2552 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2553 );\r
2554 if (EFI_ERROR(Status) || Cnp1_2 == NULL) {\r
2555 continue;\r
2556 }\r
2557\r
2558 //\r
2559 // Use all handles array as controller handle\r
2560 //\r
2561 for (Index2 = 0; Index2 < NumAllHandles; Index2++) {\r
2562 Status = Cnp1_2->GetControllerName(\r
2563 Cnp1_2,\r
2564 AllHandlesBuffer[Index2],\r
2565 Dev->Handle,\r
2566 LANGUAGE_ISO_639_2_ENGLISH,\r
2567 &DevName\r
2568 );\r
2569 if (EFI_ERROR(Status)) {\r
2570 Status = Cnp1_2->GetControllerName(\r
2571 Cnp1_2,\r
2572 AllHandlesBuffer[Index2],\r
2573 Dev->Handle,\r
2574 LANGUAGE_RFC_3066_ENGLISH,\r
2575 &DevName\r
2576 );\r
2577 }\r
2578 if (!EFI_ERROR(Status) && DevName != NULL) {\r
2579 StrLength = StrLen(DevName) + 1; // Add one for NULL terminator\r
2580 Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));\r
2581 ASSERT (Dev->Name16 != NULL);\r
2582 StrCpyS (Dev->Name16, StrLength, DevName);\r
2583 Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);\r
2584 UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);\r
2585\r
2586 //\r
2587 // Retrieve bridge BDF info and port number or namespace depending on type\r
2588 //\r
2589 TmpDevPath = NULL;\r
2590 Status = gBS->OpenProtocol(\r
2591 Dev->Handle,\r
2592 &gEfiDevicePathProtocolGuid,\r
2593 (VOID**)&TmpDevPath,\r
2594 gImageHandle,\r
2595 NULL,\r
2596 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2597 );\r
2598 if (!EFI_ERROR(Status)) {\r
2599 Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);\r
2600 return TRUE;\r
2601 }\r
2602\r
2603 if (Dev->Name16 != NULL) {\r
2604 FreePool(Dev->Name16);\r
2605 Dev->Name16 = NULL;\r
2606 }\r
2607 if (Dev->NameZ != NULL) {\r
2608 FreePool(Dev->NameZ);\r
2609 Dev->NameZ = NULL;\r
2610 }\r
2611 }\r
2612 }\r
2613 }\r
2614\r
2615 return FALSE;\r
2616}\r
2617\r
2618/**\r
2619 Get devcie name through the component name protocol.\r
2620\r
2621 @param[in] Dev The device which need to get name.\r
2622\r
2623 @retval TRUE Find the name for this device.\r
2624 @retval FALSE Not found the name for this device.\r
2625**/\r
2626BOOLEAN\r
2627OpalDriverGetDriverDeviceName(\r
2628 OPAL_DRIVER_DEVICE *Dev\r
2629 )\r
2630{\r
2631 EFI_HANDLE* AllHandlesBuffer;\r
2632 UINTN NumAllHandles;\r
2633 EFI_STATUS Status;\r
2634\r
2635 if (Dev == NULL) {\r
2636 DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));\r
2637 return FALSE;\r
2638 }\r
2639\r
2640 //\r
2641 // Iterate through ComponentName2 handles to get name, if fails, try ComponentName\r
2642 //\r
2643 if (Dev->Name16 == NULL) {\r
2644 DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));\r
2645 //\r
2646 // Find all EFI_HANDLES\r
2647 //\r
2648 Status = gBS->LocateHandleBuffer(\r
2649 AllHandles,\r
2650 NULL,\r
2651 NULL,\r
2652 &NumAllHandles,\r
2653 &AllHandlesBuffer\r
2654 );\r
2655 if (EFI_ERROR(Status)) {\r
2656 DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));\r
2657 return FALSE;\r
2658 }\r
2659\r
2660 //\r
2661 // Try component Name2\r
2662 //\r
2663 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {\r
2664 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));\r
2665 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {\r
2666 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));\r
2667 return FALSE;\r
2668 }\r
2669 }\r
2670 }\r
2671\r
2672 return TRUE;\r
2673}\r
2674\r
2675/**\r
2676 Main entry for this driver.\r
2677\r
2678 @param ImageHandle Image Handle this driver.\r
2679 @param SystemTable Pointer to SystemTable.\r
2680\r
2681 @retval EFI_SUCESS This function always complete successfully.\r
2682**/\r
2683EFI_STATUS\r
2684EFIAPI\r
2685EfiDriverEntryPoint(\r
2686 IN EFI_HANDLE ImageHandle,\r
2687 IN EFI_SYSTEM_TABLE* SystemTable\r
2688 )\r
2689{\r
2690 EFI_STATUS Status;\r
2691 EFI_EVENT ReadyToBootEvent;\r
2692 EFI_EVENT EndOfDxeEvent;\r
2693\r
2694 Status = EfiLibInstallDriverBindingComponentName2 (\r
2695 ImageHandle,\r
2696 SystemTable,\r
2697 &gOpalDriverBinding,\r
2698 ImageHandle,\r
2699 &gOpalComponentName,\r
2700 &gOpalComponentName2\r
2701 );\r
2702\r
2703 if (EFI_ERROR(Status)) {\r
2704 DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));\r
2705 return Status ;\r
2706 }\r
2707\r
2708 //\r
2709 // Initialize Driver object\r
2710 //\r
2711 ZeroMem(&mOpalDriver, sizeof(mOpalDriver));\r
2712 mOpalDriver.Handle = ImageHandle;\r
2713\r
2714 Status = gBS->CreateEventEx (\r
2715 EVT_NOTIFY_SIGNAL,\r
2716 TPL_CALLBACK,\r
2717 OpalEndOfDxeEventNotify,\r
2718 NULL,\r
2719 &gEfiEndOfDxeEventGroupGuid,\r
2720 &EndOfDxeEvent\r
2721 );\r
2722 ASSERT_EFI_ERROR (Status);\r
2723\r
2724 //\r
2725 // register a ReadyToBoot event callback for sending BlockSid command\r
2726 //\r
2727 Status = EfiCreateEventReadyToBootEx (\r
2728 TPL_CALLBACK,\r
2729 ReadyToBootCallback,\r
2730 (VOID *) &ImageHandle,\r
2731 &ReadyToBootEvent\r
2732 );\r
2733\r
2734 //\r
2735 // Install Hii packages.\r
2736 //\r
2737 HiiInstall();\r
2738\r
2739 return Status;\r
2740}\r
2741\r
2742/**\r
2743 Tests to see if this driver supports a given controller.\r
2744\r
2745 This function checks to see if the controller contains an instance of the\r
2746 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL\r
2747 and returns EFI_SUCCESS if it does.\r
2748\r
2749 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
2750 @param[in] ControllerHandle The Handle of the controller to test. This Handle\r
2751 must support a protocol interface that supplies\r
2752 an I/O abstraction to the driver.\r
2753 @param[in] RemainingDevicePath This parameter is ignored.\r
2754\r
2755 @retval EFI_SUCCESS The device contains required protocols\r
2756 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
2757 RemainingDevicePath is already being managed by the driver\r
2758 specified by This.\r
2759 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
2760 RemainingDevicePath is already being managed by a different\r
2761 driver or an application that requires exclusive access.\r
2762 Currently not implemented.\r
2763 @retval EFI_UNSUPPORTED The device does not contain requires protocols\r
2764\r
2765**/\r
2766EFI_STATUS\r
2767EFIAPI\r
2768OpalEfiDriverBindingSupported(\r
2769 IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
2770 IN EFI_HANDLE Controller,\r
2771 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
2772 )\r
2773{\r
2774 EFI_STATUS Status;\r
2775 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL* SecurityCommand;\r
2776 EFI_BLOCK_IO_PROTOCOL* BlkIo;\r
2777\r
2778 if (mOpalEndOfDxe) {\r
2779 return EFI_UNSUPPORTED;\r
2780 }\r
2781\r
2782 //\r
2783 // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.\r
2784 //\r
2785 Status = gBS->OpenProtocol(\r
2786 Controller,\r
2787 &gEfiStorageSecurityCommandProtocolGuid,\r
2788 ( VOID ** )&SecurityCommand,\r
2789 This->DriverBindingHandle,\r
2790 Controller,\r
2791 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2792 );\r
2793\r
2794 if (Status == EFI_ALREADY_STARTED) {\r
2795 return EFI_SUCCESS;\r
2796 }\r
2797\r
2798 if (EFI_ERROR(Status)) {\r
2799 return Status;\r
2800 }\r
2801\r
2802 //\r
2803 // Close protocol and reopen in Start call\r
2804 //\r
2805 gBS->CloseProtocol(\r
2806 Controller,\r
2807 &gEfiStorageSecurityCommandProtocolGuid,\r
2808 This->DriverBindingHandle,\r
2809 Controller\r
2810 );\r
2811\r
2812 //\r
2813 // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
2814 // function APIs\r
2815 //\r
2816 Status = gBS->OpenProtocol(\r
2817 Controller,\r
2818 &gEfiBlockIoProtocolGuid,\r
2819 (VOID **)&BlkIo,\r
2820 This->DriverBindingHandle,\r
2821 Controller,\r
2822 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2823 );\r
2824\r
2825 if (EFI_ERROR(Status)) {\r
2826 DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));\r
2827 return Status;\r
2828 }\r
2829\r
2830 //\r
2831 // Close protocol and reopen in Start call\r
2832 //\r
2833 gBS->CloseProtocol(\r
2834 Controller,\r
2835 &gEfiBlockIoProtocolGuid,\r
2836 This->DriverBindingHandle,\r
2837 Controller\r
2838 );\r
2839\r
2840 return EFI_SUCCESS;\r
2841}\r
2842\r
2843/**\r
2844 Enables Opal Management on a supported device if available.\r
2845\r
2846 The start function is designed to be called after the Opal UEFI Driver has confirmed the\r
2847 "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.\r
2848 This function will complete the other necessary checks, such as verifying the device supports\r
2849 the correct version of Opal. Upon verification, it will add the device to the\r
2850 Opal HII list in order to expose Opal managmeent options.\r
2851\r
2852 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
2853 @param[in] ControllerHandle The Handle of the controller to start. This Handle\r
2854 must support a protocol interface that supplies\r
2855 an I/O abstraction to the driver.\r
2856 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
2857 parameter is ignored by device drivers, and is optional for bus\r
2858 drivers. For a bus driver, if this parameter is NULL, then handles\r
2859 for all the children of Controller are created by this driver.\r
2860 If this parameter is not NULL and the first Device Path Node is\r
2861 not the End of Device Path Node, then only the Handle for the\r
2862 child device specified by the first Device Path Node of\r
2863 RemainingDevicePath is created by this driver.\r
2864 If the first Device Path Node of RemainingDevicePath is\r
2865 the End of Device Path Node, no child Handle is created by this\r
2866 driver.\r
2867\r
2868 @retval EFI_SUCCESS Opal management was enabled.\r
2869 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
2870 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2871 @retval Others The driver failed to start the device.\r
2872\r
2873**/\r
2874EFI_STATUS\r
2875EFIAPI\r
2876OpalEfiDriverBindingStart(\r
2877 IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
2878 IN EFI_HANDLE Controller,\r
2879 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
2880 )\r
2881{\r
2882 EFI_STATUS Status;\r
2883 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
2884 OPAL_DRIVER_DEVICE *Dev;\r
2885 OPAL_DRIVER_DEVICE *Itr;\r
2886 BOOLEAN Result;\r
2887\r
2888 Itr = mOpalDriver.DeviceList;\r
2889 while (Itr != NULL) {\r
2890 if (Controller == Itr->Handle) {\r
2891 return EFI_SUCCESS;\r
2892 }\r
2893 Itr = Itr->Next;\r
2894 }\r
2895\r
2896 //\r
2897 // Create internal device for tracking. This allows all disks to be tracked\r
2898 // by same HII form\r
2899 //\r
2900 Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));\r
2901 if (Dev == NULL) {\r
2902 return EFI_OUT_OF_RESOURCES;\r
2903 }\r
2904 Dev->Handle = Controller;\r
2905\r
2906 //\r
2907 // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks\r
2908 //\r
2909 Status = gBS->OpenProtocol(\r
2910 Controller,\r
2911 &gEfiStorageSecurityCommandProtocolGuid,\r
2912 (VOID **)&Dev->Sscp,\r
2913 This->DriverBindingHandle,\r
2914 Controller,\r
2915 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2916 );\r
2917 if (EFI_ERROR(Status)) {\r
2918 FreePool(Dev);\r
2919 return Status;\r
2920 }\r
2921\r
2922 //\r
2923 // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
2924 // function APIs\r
2925 //\r
2926 Status = gBS->OpenProtocol(\r
2927 Controller,\r
2928 &gEfiBlockIoProtocolGuid,\r
2929 (VOID **)&BlkIo,\r
2930 This->DriverBindingHandle,\r
2931 Controller,\r
2932 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2933 );\r
2934 if (EFI_ERROR(Status)) {\r
2935 //\r
2936 // Close storage security that was opened\r
2937 //\r
2938 gBS->CloseProtocol(\r
2939 Controller,\r
2940 &gEfiStorageSecurityCommandProtocolGuid,\r
2941 This->DriverBindingHandle,\r
2942 Controller\r
2943 );\r
2944\r
2945 FreePool(Dev);\r
2946 return Status;\r
2947 }\r
2948\r
2949 //\r
2950 // Save mediaId\r
2951 //\r
2952 Dev->MediaId = BlkIo->Media->MediaId;\r
2953\r
2954 gBS->CloseProtocol(\r
2955 Controller,\r
2956 &gEfiBlockIoProtocolGuid,\r
2957 This->DriverBindingHandle,\r
2958 Controller\r
2959 );\r
2960\r
2961 //\r
2962 // Acquire Ascii printable name of child, if not found, then ignore device\r
2963 //\r
2964 Result = OpalDriverGetDriverDeviceName (Dev);\r
2965 if (!Result) {\r
2966 goto Done;\r
2967 }\r
2968\r
2969 Status = OpalDiskInitialize (Dev);\r
2970 if (EFI_ERROR (Status)) {\r
2971 goto Done;\r
2972 }\r
2973\r
2974 AddDeviceToTail(Dev);\r
2975\r
2976 //\r
2977 // Check if device is locked and prompt for password.\r
2978 //\r
2979 OpalDriverRequestPassword (Dev, L"Unlock:");\r
2980\r
2981 //\r
2982 // Process OPAL request from last boot.\r
2983 //\r
2984 ProcessOpalRequest (Dev);\r
2985\r
2986 return EFI_SUCCESS;\r
2987\r
2988Done:\r
2989 //\r
2990 // free device, close protocols and exit\r
2991 //\r
2992 gBS->CloseProtocol(\r
2993 Controller,\r
2994 &gEfiStorageSecurityCommandProtocolGuid,\r
2995 This->DriverBindingHandle,\r
2996 Controller\r
2997 );\r
2998\r
2999 FreePool(Dev);\r
3000\r
3001 return EFI_DEVICE_ERROR;\r
3002}\r
3003\r
3004/**\r
3005 Stop this driver on Controller.\r
3006\r
3007 @param This Protocol instance pointer.\r
3008 @param Controller Handle of device to stop driver on\r
3009 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
3010 children is zero stop the entire bus driver.\r
3011 @param ChildHandleBuffer List of Child Handles to Stop.\r
3012\r
3013 @retval EFI_SUCCESS This driver is removed Controller.\r
3014 @retval other This driver could not be removed from this device.\r
3015\r
3016**/\r
3017EFI_STATUS\r
3018EFIAPI\r
3019OpalEfiDriverBindingStop(\r
3020 EFI_DRIVER_BINDING_PROTOCOL* This,\r
3021 EFI_HANDLE Controller,\r
3022 UINTN NumberOfChildren,\r
3023 EFI_HANDLE* ChildHandleBuffer\r
3024 )\r
3025{\r
3026 OPAL_DRIVER_DEVICE* Itr;\r
3027\r
3028 Itr = mOpalDriver.DeviceList;\r
3029\r
3030 //\r
3031 // does Controller match any of the devices we are managing for Opal\r
3032 //\r
3033 while (Itr != NULL) {\r
3034 if (Itr->Handle == Controller) {\r
3035 OpalDriverStopDevice (Itr);\r
3036 return EFI_SUCCESS;\r
3037 }\r
3038\r
3039 Itr = Itr->Next;\r
3040 }\r
3041\r
3042 return EFI_NOT_FOUND;\r
3043}\r
3044\r
3045\r
3046/**\r
3047 Unloads UEFI Driver. Very useful for debugging and testing.\r
3048\r
3049 @param ImageHandle Image Handle this driver.\r
3050\r
3051 @retval EFI_SUCCESS This function always complete successfully.\r
3052 @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.\r
3053**/\r
3054EFI_STATUS\r
3055EFIAPI\r
3056OpalEfiDriverUnload (\r
3057 IN EFI_HANDLE ImageHandle\r
3058 )\r
3059{\r
3060 EFI_STATUS Status;\r
3061 OPAL_DRIVER_DEVICE *Itr;\r
3062\r
3063 Status = EFI_SUCCESS;\r
3064\r
3065 if (ImageHandle != gImageHandle) {\r
3066 return (EFI_INVALID_PARAMETER);\r
3067 }\r
3068\r
3069 //\r
3070 // Uninstall any interface added to each device by us\r
3071 //\r
3072 while (mOpalDriver.DeviceList) {\r
3073 Itr = mOpalDriver.DeviceList;\r
3074 //\r
3075 // Remove OPAL_DRIVER_DEVICE from the list\r
3076 // it updates the controllerList pointer\r
3077 //\r
3078 OpalDriverStopDevice(Itr);\r
3079 }\r
3080\r
3081 //\r
3082 // Uninstall the HII capability\r
3083 //\r
3084 Status = HiiUninstall();\r
3085\r
3086 return Status;\r
3087}\r
3088\r