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