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