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