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