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