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