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