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