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