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