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