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