]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
SecurityPkg: Incorrect warning message for Opal admin revert action
[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 ((!KeepUserData) &&
1541 (Dev->OpalDisk.EstimateTimeCost > MAX_ACCEPTABLE_REVERTING_TIME)) {
1542 BufferSize = StrSize (L"Warning: Revert action will take about ####### seconds, DO NOT power off system during the revert action!");
1543 PopUpString2 = AllocateZeroPool (BufferSize);
1544 ASSERT (PopUpString2 != NULL);
1545 UnicodeSPrint (
1546 PopUpString2,
1547 BufferSize,
1548 L"WARNING: Revert action will take about %d seconds, DO NOT power off system during the revert action!",
1549 Dev->OpalDisk.EstimateTimeCost
1550 );
1551 } else {
1552 PopUpString2 = NULL;
1553 }
1554
1555 Count = 0;
1556
1557 ZeroMem(&Session, sizeof(Session));
1558 Session.Sscp = Dev->OpalDisk.Sscp;
1559 Session.MediaId = Dev->OpalDisk.MediaId;
1560 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
1561
1562 while (Count < MAX_PASSWORD_TRY_COUNT) {
1563 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, PopUpString2, &PressEsc);
1564 if (PressEsc) {
1565 do {
1566 CreatePopUp (
1567 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1568 &Key,
1569 L"Press ENTER to skip the request and continue boot,",
1570 L"Press ESC to input password again",
1571 NULL
1572 );
1573 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
1574
1575 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
1576 gST->ConOut->ClearScreen(gST->ConOut);
1577 goto Done;
1578 } else {
1579 //
1580 // Let user input password again.
1581 //
1582 continue;
1583 }
1584 }
1585
1586 if (Password == NULL) {
1587 Count ++;
1588 continue;
1589 }
1590 PasswordLen = (UINT32) AsciiStrLen(Password);
1591
1592 if ((Dev->OpalDisk.SupportedAttributes.PyriteSsc == 1) &&
1593 (Dev->OpalDisk.LockingFeature.MediaEncryption == 0)) {
1594 //
1595 // For pyrite type device which does not support media encryption,
1596 // it does not accept "Keep User Data" parameter.
1597 // So here hardcode a FALSE for this case.
1598 //
1599 Ret = OpalUtilRevert(
1600 &Session,
1601 FALSE,
1602 Password,
1603 PasswordLen,
1604 &PasswordFailed,
1605 Dev->OpalDisk.Msid,
1606 Dev->OpalDisk.MsidLength
1607 );
1608 } else {
1609 Ret = OpalUtilRevert(
1610 &Session,
1611 KeepUserData,
1612 Password,
1613 PasswordLen,
1614 &PasswordFailed,
1615 Dev->OpalDisk.Msid,
1616 Dev->OpalDisk.MsidLength
1617 );
1618 }
1619 if (Ret == TcgResultSuccess) {
1620 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
1621 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
1622 } else {
1623 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
1624 }
1625
1626 if (Password != NULL) {
1627 ZeroMem (Password, PasswordLen);
1628 FreePool (Password);
1629 }
1630
1631 if (Ret == TcgResultSuccess) {
1632 break;
1633 }
1634
1635 Count++;
1636
1637 do {
1638 CreatePopUp (
1639 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1640 &Key,
1641 L"Invalid password, request failed.",
1642 L"Press ENTER to retry",
1643 NULL
1644 );
1645 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1646 }
1647
1648 if (Count >= MAX_PASSWORD_TRY_COUNT) {
1649 do {
1650 CreatePopUp (
1651 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1652 &Key,
1653 L"Opal password retry count exceeds the limit.",
1654 L"Press ENTER to skip the request and continue boot",
1655 NULL
1656 );
1657 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1658 gST->ConOut->ClearScreen(gST->ConOut);
1659 }
1660
1661 Done:
1662 if (PopUpString2 != NULL) {
1663 FreePool (PopUpString2);
1664 }
1665 }
1666
1667 /**
1668 Process Secure Erase OPAL request.
1669
1670 @param[in] Dev The device which has Secure Erase OPAL request.
1671 @param[in] RequestString Request string.
1672
1673 **/
1674 VOID
1675 ProcessOpalRequestSecureErase (
1676 IN OPAL_DRIVER_DEVICE *Dev,
1677 IN CHAR16 *RequestString
1678 )
1679 {
1680 UINT8 Count;
1681 CHAR8 *Password;
1682 UINT32 PasswordLen;
1683 OPAL_SESSION Session;
1684 BOOLEAN PressEsc;
1685 EFI_INPUT_KEY Key;
1686 TCG_RESULT Ret;
1687 BOOLEAN PasswordFailed;
1688 CHAR16 *PopUpString;
1689
1690 if (Dev == NULL) {
1691 return;
1692 }
1693
1694 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
1695
1696 PopUpString = OpalGetPopUpString (Dev, RequestString);
1697
1698 Count = 0;
1699
1700 ZeroMem(&Session, sizeof(Session));
1701 Session.Sscp = Dev->OpalDisk.Sscp;
1702 Session.MediaId = Dev->OpalDisk.MediaId;
1703 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
1704
1705 while (Count < MAX_PASSWORD_TRY_COUNT) {
1706 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);
1707 if (PressEsc) {
1708 do {
1709 CreatePopUp (
1710 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1711 &Key,
1712 L"Press ENTER to skip the request and continue boot,",
1713 L"Press ESC to input password again",
1714 NULL
1715 );
1716 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
1717
1718 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
1719 gST->ConOut->ClearScreen(gST->ConOut);
1720 return;
1721 } else {
1722 //
1723 // Let user input password again.
1724 //
1725 continue;
1726 }
1727 }
1728
1729 if (Password == NULL) {
1730 Count ++;
1731 continue;
1732 }
1733 PasswordLen = (UINT32) AsciiStrLen(Password);
1734
1735 Ret = OpalUtilSecureErase(&Session, Password, PasswordLen, &PasswordFailed);
1736 if (Ret == TcgResultSuccess) {
1737 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
1738 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
1739 } else {
1740 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
1741 }
1742
1743 if (Password != NULL) {
1744 ZeroMem (Password, PasswordLen);
1745 FreePool (Password);
1746 }
1747
1748 if (Ret == TcgResultSuccess) {
1749 break;
1750 }
1751
1752 Count++;
1753
1754 do {
1755 CreatePopUp (
1756 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1757 &Key,
1758 L"Invalid password, request failed.",
1759 L"Press ENTER to retry",
1760 NULL
1761 );
1762 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1763 }
1764
1765 if (Count >= MAX_PASSWORD_TRY_COUNT) {
1766 do {
1767 CreatePopUp (
1768 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1769 &Key,
1770 L"Opal password retry count exceeds the limit.",
1771 L"Press ENTER to skip the request and continue boot",
1772 NULL
1773 );
1774 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1775 gST->ConOut->ClearScreen(gST->ConOut);
1776 }
1777 }
1778
1779 /**
1780 Process Set Admin Pwd OPAL request.
1781
1782 @param[in] Dev The device which has Set Admin Pwd Feature OPAL request.
1783 @param[in] RequestString Request string.
1784
1785 **/
1786 VOID
1787 ProcessOpalRequestSetUserPwd (
1788 IN OPAL_DRIVER_DEVICE *Dev,
1789 IN CHAR16 *RequestString
1790 )
1791 {
1792 UINT8 Count;
1793 CHAR8 *OldPassword;
1794 UINT32 OldPasswordLen;
1795 CHAR8 *Password;
1796 UINT32 PasswordLen;
1797 CHAR8 *PasswordConfirm;
1798 UINT32 PasswordLenConfirm;
1799 OPAL_SESSION Session;
1800 BOOLEAN PressEsc;
1801 EFI_INPUT_KEY Key;
1802 TCG_RESULT Ret;
1803 CHAR16 *PopUpString;
1804
1805 if (Dev == NULL) {
1806 return;
1807 }
1808
1809 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
1810
1811 PopUpString = OpalGetPopUpString (Dev, RequestString);
1812
1813 Count = 0;
1814
1815 while (Count < MAX_PASSWORD_TRY_COUNT) {
1816 OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);
1817 if (PressEsc) {
1818 do {
1819 CreatePopUp (
1820 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1821 &Key,
1822 L"Press ENTER to skip the request and continue boot,",
1823 L"Press ESC to input password again",
1824 NULL
1825 );
1826 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
1827
1828 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
1829 gST->ConOut->ClearScreen(gST->ConOut);
1830 return;
1831 } else {
1832 //
1833 // Let user input password again.
1834 //
1835 continue;
1836 }
1837 }
1838
1839 if (OldPassword == NULL) {
1840 Count ++;
1841 continue;
1842 }
1843 OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
1844
1845 ZeroMem(&Session, sizeof(Session));
1846 Session.Sscp = Dev->OpalDisk.Sscp;
1847 Session.MediaId = Dev->OpalDisk.MediaId;
1848 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
1849 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_USER1_AUTHORITY);
1850 if (Ret == TcgResultSuccess) {
1851 DEBUG ((DEBUG_INFO, "Verify with USER1 authority : Success\n"));
1852 } else {
1853 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
1854 if (Ret == TcgResultSuccess) {
1855 DEBUG ((DEBUG_INFO, "Verify with ADMIN1 authority: Success\n"));
1856 } else {
1857 ZeroMem (OldPassword, OldPasswordLen);
1858 FreePool (OldPassword);
1859 DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
1860 do {
1861 CreatePopUp (
1862 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1863 &Key,
1864 L"Incorrect password.",
1865 L"Press ENTER to retry",
1866 NULL
1867 );
1868 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1869 Count ++;
1870 continue;
1871 }
1872 }
1873
1874 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);
1875 if (Password == NULL) {
1876 ZeroMem (OldPassword, OldPasswordLen);
1877 FreePool (OldPassword);
1878 Count ++;
1879 continue;
1880 }
1881 PasswordLen = (UINT32) AsciiStrLen(Password);
1882
1883 PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);
1884 if (PasswordConfirm == NULL) {
1885 ZeroMem (OldPassword, OldPasswordLen);
1886 FreePool (OldPassword);
1887 ZeroMem (Password, PasswordLen);
1888 FreePool (Password);
1889 Count ++;
1890 continue;
1891 }
1892 PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
1893 if ((PasswordLen != PasswordLenConfirm) ||
1894 (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
1895 ZeroMem (OldPassword, OldPasswordLen);
1896 FreePool (OldPassword);
1897 ZeroMem (Password, PasswordLen);
1898 FreePool (Password);
1899 ZeroMem (PasswordConfirm, PasswordLenConfirm);
1900 FreePool (PasswordConfirm);
1901 do {
1902 CreatePopUp (
1903 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1904 &Key,
1905 L"Passwords are not the same.",
1906 L"Press ENTER to retry",
1907 NULL
1908 );
1909 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1910 Count ++;
1911 continue;
1912 }
1913
1914 if (PasswordConfirm != NULL) {
1915 ZeroMem (PasswordConfirm, PasswordLenConfirm);
1916 FreePool (PasswordConfirm);
1917 }
1918
1919 ZeroMem(&Session, sizeof(Session));
1920 Session.Sscp = Dev->OpalDisk.Sscp;
1921 Session.MediaId = Dev->OpalDisk.MediaId;
1922 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
1923 Ret = OpalUtilSetUserPassword(
1924 &Session,
1925 OldPassword,
1926 OldPasswordLen,
1927 Password,
1928 PasswordLen
1929 );
1930 if (Ret == TcgResultSuccess) {
1931 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
1932 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
1933 } else {
1934 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
1935 }
1936
1937 if (OldPassword != NULL) {
1938 ZeroMem (OldPassword, OldPasswordLen);
1939 FreePool (OldPassword);
1940 }
1941
1942 if (Password != NULL) {
1943 ZeroMem (Password, PasswordLen);
1944 FreePool (Password);
1945 }
1946
1947 if (Ret == TcgResultSuccess) {
1948 break;
1949 }
1950
1951 Count++;
1952
1953 do {
1954 CreatePopUp (
1955 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1956 &Key,
1957 L"Request failed.",
1958 L"Press ENTER to retry",
1959 NULL
1960 );
1961 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1962 }
1963
1964 if (Count >= MAX_PASSWORD_TRY_COUNT) {
1965 do {
1966 CreatePopUp (
1967 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
1968 &Key,
1969 L"Opal password retry count exceeds the limit.",
1970 L"Press ENTER to skip the request and continue boot",
1971 NULL
1972 );
1973 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
1974 gST->ConOut->ClearScreen(gST->ConOut);
1975 }
1976 }
1977
1978 /**
1979 Process Set Admin Pwd OPAL request.
1980
1981 @param[in] Dev The device which has Set Admin Pwd Feature OPAL request.
1982 @param[in] RequestString Request string.
1983
1984 **/
1985 VOID
1986 ProcessOpalRequestSetAdminPwd (
1987 IN OPAL_DRIVER_DEVICE *Dev,
1988 IN CHAR16 *RequestString
1989 )
1990 {
1991 UINT8 Count;
1992 CHAR8 *OldPassword;
1993 UINT32 OldPasswordLen;
1994 CHAR8 *Password;
1995 UINT32 PasswordLen;
1996 CHAR8 *PasswordConfirm;
1997 UINT32 PasswordLenConfirm;
1998 OPAL_SESSION Session;
1999 BOOLEAN PressEsc;
2000 EFI_INPUT_KEY Key;
2001 TCG_RESULT Ret;
2002 CHAR16 *PopUpString;
2003
2004 if (Dev == NULL) {
2005 return;
2006 }
2007
2008 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));
2009
2010 PopUpString = OpalGetPopUpString (Dev, RequestString);
2011
2012 Count = 0;
2013
2014 while (Count < MAX_PASSWORD_TRY_COUNT) {
2015 OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);
2016 if (PressEsc) {
2017 do {
2018 CreatePopUp (
2019 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2020 &Key,
2021 L"Press ENTER to skip the request and continue boot,",
2022 L"Press ESC to input password again",
2023 NULL
2024 );
2025 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));
2026
2027 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
2028 gST->ConOut->ClearScreen(gST->ConOut);
2029 return;
2030 } else {
2031 //
2032 // Let user input password again.
2033 //
2034 continue;
2035 }
2036 }
2037
2038 if (OldPassword == NULL) {
2039 Count ++;
2040 continue;
2041 }
2042 OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);
2043
2044 ZeroMem(&Session, sizeof(Session));
2045 Session.Sscp = Dev->OpalDisk.Sscp;
2046 Session.MediaId = Dev->OpalDisk.MediaId;
2047 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
2048 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);
2049 if (Ret == TcgResultSuccess) {
2050 DEBUG ((DEBUG_INFO, "Verify: Success\n"));
2051 } else {
2052 ZeroMem (OldPassword, OldPasswordLen);
2053 FreePool (OldPassword);
2054 DEBUG ((DEBUG_INFO, "Verify: Failure\n"));
2055 do {
2056 CreatePopUp (
2057 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2058 &Key,
2059 L"Incorrect password.",
2060 L"Press ENTER to retry",
2061 NULL
2062 );
2063 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
2064 Count ++;
2065 continue;
2066 }
2067
2068 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);
2069 if (Password == NULL) {
2070 ZeroMem (OldPassword, OldPasswordLen);
2071 FreePool (OldPassword);
2072 Count ++;
2073 continue;
2074 }
2075 PasswordLen = (UINT32) AsciiStrLen(Password);
2076
2077 PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);
2078 if (PasswordConfirm == NULL) {
2079 ZeroMem (OldPassword, OldPasswordLen);
2080 FreePool (OldPassword);
2081 ZeroMem (Password, PasswordLen);
2082 FreePool (Password);
2083 Count ++;
2084 continue;
2085 }
2086 PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);
2087 if ((PasswordLen != PasswordLenConfirm) ||
2088 (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {
2089 ZeroMem (OldPassword, OldPasswordLen);
2090 FreePool (OldPassword);
2091 ZeroMem (Password, PasswordLen);
2092 FreePool (Password);
2093 ZeroMem (PasswordConfirm, PasswordLenConfirm);
2094 FreePool (PasswordConfirm);
2095 do {
2096 CreatePopUp (
2097 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2098 &Key,
2099 L"Passwords are not the same.",
2100 L"Press ENTER to retry",
2101 NULL
2102 );
2103 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
2104 Count ++;
2105 continue;
2106 }
2107
2108 if (PasswordConfirm != NULL) {
2109 ZeroMem (PasswordConfirm, PasswordLenConfirm);
2110 FreePool (PasswordConfirm);
2111 }
2112
2113
2114 ZeroMem(&Session, sizeof(Session));
2115 Session.Sscp = Dev->OpalDisk.Sscp;
2116 Session.MediaId = Dev->OpalDisk.MediaId;
2117 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;
2118 Ret = OpalUtilSetAdminPassword(
2119 &Session,
2120 OldPassword,
2121 OldPasswordLen,
2122 Password,
2123 PasswordLen
2124 );
2125 if (Ret == TcgResultSuccess) {
2126 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);
2127 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));
2128 } else {
2129 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));
2130 }
2131
2132 if (OldPassword != NULL) {
2133 ZeroMem (OldPassword, OldPasswordLen);
2134 FreePool (OldPassword);
2135 }
2136
2137 if (Password != NULL) {
2138 ZeroMem (Password, PasswordLen);
2139 FreePool (Password);
2140 }
2141
2142 if (Ret == TcgResultSuccess) {
2143 break;
2144 }
2145
2146 Count++;
2147
2148 do {
2149 CreatePopUp (
2150 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2151 &Key,
2152 L"Request failed.",
2153 L"Press ENTER to retry",
2154 NULL
2155 );
2156 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
2157 }
2158
2159 if (Count >= MAX_PASSWORD_TRY_COUNT) {
2160 do {
2161 CreatePopUp (
2162 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
2163 &Key,
2164 L"Opal password retry count exceeds the limit.",
2165 L"Press ENTER to skip the request and continue boot",
2166 NULL
2167 );
2168 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);
2169 gST->ConOut->ClearScreen(gST->ConOut);
2170 }
2171 }
2172
2173 /**
2174 Process OPAL request.
2175
2176 @param[in] Dev The device which has OPAL request.
2177
2178 **/
2179 VOID
2180 ProcessOpalRequest (
2181 IN OPAL_DRIVER_DEVICE *Dev
2182 )
2183 {
2184 EFI_STATUS Status;
2185 OPAL_REQUEST_VARIABLE *TempVariable;
2186 OPAL_REQUEST_VARIABLE *Variable;
2187 UINTN VariableSize;
2188 EFI_DEVICE_PATH_PROTOCOL *DevicePathInVariable;
2189 UINTN DevicePathSizeInVariable;
2190 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
2191 UINTN DevicePathSize;
2192 BOOLEAN KeepUserData;
2193
2194 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));
2195
2196 if (mOpalRequestVariable == NULL) {
2197 Status = GetVariable2 (
2198 OPAL_REQUEST_VARIABLE_NAME,
2199 &gHiiSetupVariableGuid,
2200 (VOID **) &Variable,
2201 &VariableSize
2202 );
2203 if (EFI_ERROR (Status) || (Variable == NULL)) {
2204 return;
2205 }
2206 mOpalRequestVariable = Variable;
2207 mOpalRequestVariableSize = VariableSize;
2208
2209 //
2210 // Delete the OPAL request variable.
2211 //
2212 Status = gRT->SetVariable (
2213 OPAL_REQUEST_VARIABLE_NAME,
2214 (EFI_GUID *) &gHiiSetupVariableGuid,
2215 0,
2216 0,
2217 NULL
2218 );
2219 ASSERT_EFI_ERROR (Status);
2220 } else {
2221 Variable = mOpalRequestVariable;
2222 VariableSize = mOpalRequestVariableSize;
2223 }
2224
2225 //
2226 // Process the OPAL requests.
2227 //
2228 TempVariable = Variable;
2229 while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&
2230 (VariableSize >= TempVariable->Length) &&
2231 (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {
2232 DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));
2233 DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);
2234 DevicePath = Dev->OpalDisk.OpalDevicePath;
2235 DevicePathSize = GetDevicePathSize (DevicePath);
2236 if ((DevicePathSize == DevicePathSizeInVariable) &&
2237 (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) {
2238 //
2239 // Found the node for the OPAL device.
2240 //
2241 if (TempVariable->OpalRequest.SetAdminPwd != 0) {
2242 ProcessOpalRequestSetAdminPwd (Dev, L"Update Admin Pwd:");
2243 }
2244 if (TempVariable->OpalRequest.SetUserPwd != 0) {
2245 ProcessOpalRequestSetUserPwd (Dev, L"Set User Pwd:");
2246 }
2247 if (TempVariable->OpalRequest.SecureErase!= 0) {
2248 ProcessOpalRequestSecureErase (Dev, L"Secure Erase:");
2249 }
2250 if (TempVariable->OpalRequest.Revert != 0) {
2251 KeepUserData = (BOOLEAN) TempVariable->OpalRequest.KeepUserData;
2252 ProcessOpalRequestRevert (
2253 Dev,
2254 KeepUserData,
2255 KeepUserData ? L"Admin Revert(keep):" : L"Admin Revert:"
2256 );
2257 }
2258 if (TempVariable->OpalRequest.PsidRevert != 0) {
2259 ProcessOpalRequestPsidRevert (Dev, L"Psid Revert:");
2260 }
2261 if (TempVariable->OpalRequest.DisableUser != 0) {
2262 ProcessOpalRequestDisableUser (Dev, L"Disable User:");
2263 }
2264 if (TempVariable->OpalRequest.EnableFeature != 0) {
2265 ProcessOpalRequestEnableFeature (Dev, L"Enable Feature:");
2266 }
2267
2268 break;
2269 }
2270
2271 VariableSize -= TempVariable->Length;
2272 TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length);
2273 }
2274
2275 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));
2276 }
2277
2278 /**
2279 Add new device to the global device list.
2280
2281 @param Dev New create device.
2282
2283 **/
2284 VOID
2285 AddDeviceToTail(
2286 IN OPAL_DRIVER_DEVICE *Dev
2287 )
2288 {
2289 OPAL_DRIVER_DEVICE *TmpDev;
2290
2291 if (mOpalDriver.DeviceList == NULL) {
2292 mOpalDriver.DeviceList = Dev;
2293 } else {
2294 TmpDev = mOpalDriver.DeviceList;
2295 while (TmpDev->Next != NULL) {
2296 TmpDev = TmpDev->Next;
2297 }
2298
2299 TmpDev->Next = Dev;
2300 }
2301 }
2302
2303 /**
2304 Remove one device in the global device list.
2305
2306 @param Dev The device need to be removed.
2307
2308 **/
2309 VOID
2310 RemoveDevice (
2311 IN OPAL_DRIVER_DEVICE *Dev
2312 )
2313 {
2314 OPAL_DRIVER_DEVICE *TmpDev;
2315
2316 if (mOpalDriver.DeviceList == NULL) {
2317 return;
2318 }
2319
2320 if (mOpalDriver.DeviceList == Dev) {
2321 mOpalDriver.DeviceList = NULL;
2322 return;
2323 }
2324
2325 TmpDev = mOpalDriver.DeviceList;
2326 while (TmpDev->Next != NULL) {
2327 if (TmpDev->Next == Dev) {
2328 TmpDev->Next = Dev->Next;
2329 break;
2330 }
2331 }
2332 }
2333
2334 /**
2335 Get current device count.
2336
2337 @retval return the current created device count.
2338
2339 **/
2340 UINT8
2341 GetDeviceCount (
2342 VOID
2343 )
2344 {
2345 UINT8 Count;
2346 OPAL_DRIVER_DEVICE *TmpDev;
2347
2348 Count = 0;
2349 TmpDev = mOpalDriver.DeviceList;
2350
2351 while (TmpDev != NULL) {
2352 Count++;
2353 TmpDev = TmpDev->Next;
2354 }
2355
2356 return Count;
2357 }
2358
2359 /**
2360 Get devcie list info.
2361
2362 @retval return the device list pointer.
2363 **/
2364 OPAL_DRIVER_DEVICE*
2365 OpalDriverGetDeviceList(
2366 VOID
2367 )
2368 {
2369 return mOpalDriver.DeviceList;
2370 }
2371
2372 /**
2373 ReadyToBoot callback to send BlockSid command.
2374
2375 @param Event Pointer to this event
2376 @param Context Event handler private Data
2377
2378 **/
2379 VOID
2380 EFIAPI
2381 ReadyToBootCallback (
2382 IN EFI_EVENT Event,
2383 IN VOID *Context
2384 )
2385 {
2386 OPAL_DRIVER_DEVICE *Itr;
2387 TCG_RESULT Result;
2388 OPAL_SESSION Session;
2389 UINT32 PpStorageFlag;
2390
2391 gBS->CloseEvent (Event);
2392
2393 PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();
2394 if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {
2395 //
2396 // Send BlockSID command to each Opal disk
2397 //
2398 Itr = mOpalDriver.DeviceList;
2399 while (Itr != NULL) {
2400 if (Itr->OpalDisk.SupportedAttributes.BlockSid) {
2401 ZeroMem(&Session, sizeof(Session));
2402 Session.Sscp = Itr->OpalDisk.Sscp;
2403 Session.MediaId = Itr->OpalDisk.MediaId;
2404 Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;
2405
2406 DEBUG ((DEBUG_INFO, "OpalPassword: ReadyToBoot point, send BlockSid command to device!\n"));
2407 Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE
2408 if (Result != TcgResultSuccess) {
2409 DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));
2410 break;
2411 }
2412 }
2413
2414 Itr = Itr->Next;
2415 }
2416 }
2417 }
2418
2419 /**
2420 Stop this Controller.
2421
2422 @param Dev The device need to be stopped.
2423
2424 **/
2425 VOID
2426 OpalDriverStopDevice (
2427 OPAL_DRIVER_DEVICE *Dev
2428 )
2429 {
2430 //
2431 // free each name
2432 //
2433 FreePool(Dev->Name16);
2434
2435 //
2436 // remove OPAL_DRIVER_DEVICE from the list
2437 // it updates the controllerList pointer
2438 //
2439 RemoveDevice(Dev);
2440
2441 //
2442 // close protocols that were opened
2443 //
2444 gBS->CloseProtocol(
2445 Dev->Handle,
2446 &gEfiStorageSecurityCommandProtocolGuid,
2447 gOpalDriverBinding.DriverBindingHandle,
2448 Dev->Handle
2449 );
2450
2451 gBS->CloseProtocol(
2452 Dev->Handle,
2453 &gEfiBlockIoProtocolGuid,
2454 gOpalDriverBinding.DriverBindingHandle,
2455 Dev->Handle
2456 );
2457
2458 FreePool(Dev);
2459 }
2460
2461 /**
2462 Get devcie name through the component name protocol.
2463
2464 @param[in] AllHandlesBuffer The handle buffer for current system.
2465 @param[in] NumAllHandles The number of handles for the handle buffer.
2466 @param[in] Dev The device which need to get name.
2467 @param[in] UseComp1 Whether use component name or name2 protocol.
2468
2469 @retval TRUE Find the name for this device.
2470 @retval FALSE Not found the name for this device.
2471 **/
2472 BOOLEAN
2473 OpalDriverGetDeviceNameByProtocol(
2474 EFI_HANDLE *AllHandlesBuffer,
2475 UINTN NumAllHandles,
2476 OPAL_DRIVER_DEVICE *Dev,
2477 BOOLEAN UseComp1
2478 )
2479 {
2480 EFI_HANDLE* ProtocolHandlesBuffer;
2481 UINTN NumProtocolHandles;
2482 EFI_STATUS Status;
2483 EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout
2484 EFI_GUID Protocol;
2485 UINTN StrLength;
2486 EFI_DEVICE_PATH_PROTOCOL* TmpDevPath;
2487 UINTN Index1;
2488 UINTN Index2;
2489 EFI_HANDLE TmpHandle;
2490 CHAR16 *DevName;
2491
2492 if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {
2493 return FALSE;
2494 }
2495
2496 Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;
2497
2498 //
2499 // Find all EFI_HANDLES with protocol
2500 //
2501 Status = gBS->LocateHandleBuffer(
2502 ByProtocol,
2503 &Protocol,
2504 NULL,
2505 &NumProtocolHandles,
2506 &ProtocolHandlesBuffer
2507 );
2508 if (EFI_ERROR(Status)) {
2509 return FALSE;
2510 }
2511
2512
2513 //
2514 // Exit early if no supported devices
2515 //
2516 if (NumProtocolHandles == 0) {
2517 return FALSE;
2518 }
2519
2520 //
2521 // Get printable name by iterating through all protocols
2522 // using the handle as the child, and iterate through all handles for the controller
2523 // exit loop early once found, if not found, then delete device
2524 // storage security protocol instances already exist, add them to internal list
2525 //
2526 Status = EFI_DEVICE_ERROR;
2527 for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {
2528 DevName = NULL;
2529
2530 if (Dev->Name16 != NULL) {
2531 return TRUE;
2532 }
2533
2534 TmpHandle = ProtocolHandlesBuffer[Index1];
2535
2536 Status = gBS->OpenProtocol(
2537 TmpHandle,
2538 &Protocol,
2539 (VOID**)&Cnp1_2,
2540 gImageHandle,
2541 NULL,
2542 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2543 );
2544 if (EFI_ERROR(Status) || Cnp1_2 == NULL) {
2545 continue;
2546 }
2547
2548 //
2549 // Use all handles array as controller handle
2550 //
2551 for (Index2 = 0; Index2 < NumAllHandles; Index2++) {
2552 Status = Cnp1_2->GetControllerName(
2553 Cnp1_2,
2554 AllHandlesBuffer[Index2],
2555 Dev->Handle,
2556 LANGUAGE_ISO_639_2_ENGLISH,
2557 &DevName
2558 );
2559 if (EFI_ERROR(Status)) {
2560 Status = Cnp1_2->GetControllerName(
2561 Cnp1_2,
2562 AllHandlesBuffer[Index2],
2563 Dev->Handle,
2564 LANGUAGE_RFC_3066_ENGLISH,
2565 &DevName
2566 );
2567 }
2568 if (!EFI_ERROR(Status) && DevName != NULL) {
2569 StrLength = StrLen(DevName) + 1; // Add one for NULL terminator
2570 Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));
2571 ASSERT (Dev->Name16 != NULL);
2572 StrCpyS (Dev->Name16, StrLength, DevName);
2573 Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);
2574 UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);
2575
2576 //
2577 // Retrieve bridge BDF info and port number or namespace depending on type
2578 //
2579 TmpDevPath = NULL;
2580 Status = gBS->OpenProtocol(
2581 Dev->Handle,
2582 &gEfiDevicePathProtocolGuid,
2583 (VOID**)&TmpDevPath,
2584 gImageHandle,
2585 NULL,
2586 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2587 );
2588 if (!EFI_ERROR(Status)) {
2589 Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);
2590 return TRUE;
2591 }
2592
2593 if (Dev->Name16 != NULL) {
2594 FreePool(Dev->Name16);
2595 Dev->Name16 = NULL;
2596 }
2597 if (Dev->NameZ != NULL) {
2598 FreePool(Dev->NameZ);
2599 Dev->NameZ = NULL;
2600 }
2601 }
2602 }
2603 }
2604
2605 return FALSE;
2606 }
2607
2608 /**
2609 Get devcie name through the component name protocol.
2610
2611 @param[in] Dev The device which need to get name.
2612
2613 @retval TRUE Find the name for this device.
2614 @retval FALSE Not found the name for this device.
2615 **/
2616 BOOLEAN
2617 OpalDriverGetDriverDeviceName(
2618 OPAL_DRIVER_DEVICE *Dev
2619 )
2620 {
2621 EFI_HANDLE* AllHandlesBuffer;
2622 UINTN NumAllHandles;
2623 EFI_STATUS Status;
2624
2625 if (Dev == NULL) {
2626 DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));
2627 return FALSE;
2628 }
2629
2630 //
2631 // Iterate through ComponentName2 handles to get name, if fails, try ComponentName
2632 //
2633 if (Dev->Name16 == NULL) {
2634 DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));
2635 //
2636 // Find all EFI_HANDLES
2637 //
2638 Status = gBS->LocateHandleBuffer(
2639 AllHandles,
2640 NULL,
2641 NULL,
2642 &NumAllHandles,
2643 &AllHandlesBuffer
2644 );
2645 if (EFI_ERROR(Status)) {
2646 DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));
2647 return FALSE;
2648 }
2649
2650 //
2651 // Try component Name2
2652 //
2653 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {
2654 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));
2655 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {
2656 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));
2657 return FALSE;
2658 }
2659 }
2660 }
2661
2662 return TRUE;
2663 }
2664
2665 /**
2666 Main entry for this driver.
2667
2668 @param ImageHandle Image Handle this driver.
2669 @param SystemTable Pointer to SystemTable.
2670
2671 @retval EFI_SUCESS This function always complete successfully.
2672 **/
2673 EFI_STATUS
2674 EFIAPI
2675 EfiDriverEntryPoint(
2676 IN EFI_HANDLE ImageHandle,
2677 IN EFI_SYSTEM_TABLE* SystemTable
2678 )
2679 {
2680 EFI_STATUS Status;
2681 EFI_EVENT ReadyToBootEvent;
2682 EFI_EVENT EndOfDxeEvent;
2683
2684 Status = EfiLibInstallDriverBindingComponentName2 (
2685 ImageHandle,
2686 SystemTable,
2687 &gOpalDriverBinding,
2688 ImageHandle,
2689 &gOpalComponentName,
2690 &gOpalComponentName2
2691 );
2692
2693 if (EFI_ERROR(Status)) {
2694 DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));
2695 return Status ;
2696 }
2697
2698 //
2699 // Initialize Driver object
2700 //
2701 ZeroMem(&mOpalDriver, sizeof(mOpalDriver));
2702 mOpalDriver.Handle = ImageHandle;
2703
2704 Status = gBS->CreateEventEx (
2705 EVT_NOTIFY_SIGNAL,
2706 TPL_CALLBACK,
2707 OpalEndOfDxeEventNotify,
2708 NULL,
2709 &gEfiEndOfDxeEventGroupGuid,
2710 &EndOfDxeEvent
2711 );
2712 ASSERT_EFI_ERROR (Status);
2713
2714 //
2715 // register a ReadyToBoot event callback for sending BlockSid command
2716 //
2717 Status = EfiCreateEventReadyToBootEx (
2718 TPL_CALLBACK,
2719 ReadyToBootCallback,
2720 (VOID *) &ImageHandle,
2721 &ReadyToBootEvent
2722 );
2723
2724 //
2725 // Install Hii packages.
2726 //
2727 HiiInstall();
2728
2729 return Status;
2730 }
2731
2732 /**
2733 Tests to see if this driver supports a given controller.
2734
2735 This function checks to see if the controller contains an instance of the
2736 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL
2737 and returns EFI_SUCCESS if it does.
2738
2739 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
2740 @param[in] ControllerHandle The Handle of the controller to test. This Handle
2741 must support a protocol interface that supplies
2742 an I/O abstraction to the driver.
2743 @param[in] RemainingDevicePath This parameter is ignored.
2744
2745 @retval EFI_SUCCESS The device contains required protocols
2746 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
2747 RemainingDevicePath is already being managed by the driver
2748 specified by This.
2749 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
2750 RemainingDevicePath is already being managed by a different
2751 driver or an application that requires exclusive access.
2752 Currently not implemented.
2753 @retval EFI_UNSUPPORTED The device does not contain requires protocols
2754
2755 **/
2756 EFI_STATUS
2757 EFIAPI
2758 OpalEfiDriverBindingSupported(
2759 IN EFI_DRIVER_BINDING_PROTOCOL* This,
2760 IN EFI_HANDLE Controller,
2761 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
2762 )
2763 {
2764 EFI_STATUS Status;
2765 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL* SecurityCommand;
2766 EFI_BLOCK_IO_PROTOCOL* BlkIo;
2767
2768 if (mOpalEndOfDxe) {
2769 return EFI_UNSUPPORTED;
2770 }
2771
2772 //
2773 // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.
2774 //
2775 Status = gBS->OpenProtocol(
2776 Controller,
2777 &gEfiStorageSecurityCommandProtocolGuid,
2778 ( VOID ** )&SecurityCommand,
2779 This->DriverBindingHandle,
2780 Controller,
2781 EFI_OPEN_PROTOCOL_BY_DRIVER
2782 );
2783
2784 if (Status == EFI_ALREADY_STARTED) {
2785 return EFI_SUCCESS;
2786 }
2787
2788 if (EFI_ERROR(Status)) {
2789 return Status;
2790 }
2791
2792 //
2793 // Close protocol and reopen in Start call
2794 //
2795 gBS->CloseProtocol(
2796 Controller,
2797 &gEfiStorageSecurityCommandProtocolGuid,
2798 This->DriverBindingHandle,
2799 Controller
2800 );
2801
2802 //
2803 // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
2804 // function APIs
2805 //
2806 Status = gBS->OpenProtocol(
2807 Controller,
2808 &gEfiBlockIoProtocolGuid,
2809 (VOID **)&BlkIo,
2810 This->DriverBindingHandle,
2811 Controller,
2812 EFI_OPEN_PROTOCOL_BY_DRIVER
2813 );
2814
2815 if (EFI_ERROR(Status)) {
2816 DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));
2817 return Status;
2818 }
2819
2820 //
2821 // Close protocol and reopen in Start call
2822 //
2823 gBS->CloseProtocol(
2824 Controller,
2825 &gEfiBlockIoProtocolGuid,
2826 This->DriverBindingHandle,
2827 Controller
2828 );
2829
2830 return EFI_SUCCESS;
2831 }
2832
2833 /**
2834 Enables Opal Management on a supported device if available.
2835
2836 The start function is designed to be called after the Opal UEFI Driver has confirmed the
2837 "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.
2838 This function will complete the other necessary checks, such as verifying the device supports
2839 the correct version of Opal. Upon verification, it will add the device to the
2840 Opal HII list in order to expose Opal managmeent options.
2841
2842 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
2843 @param[in] ControllerHandle The Handle of the controller to start. This Handle
2844 must support a protocol interface that supplies
2845 an I/O abstraction to the driver.
2846 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
2847 parameter is ignored by device drivers, and is optional for bus
2848 drivers. For a bus driver, if this parameter is NULL, then handles
2849 for all the children of Controller are created by this driver.
2850 If this parameter is not NULL and the first Device Path Node is
2851 not the End of Device Path Node, then only the Handle for the
2852 child device specified by the first Device Path Node of
2853 RemainingDevicePath is created by this driver.
2854 If the first Device Path Node of RemainingDevicePath is
2855 the End of Device Path Node, no child Handle is created by this
2856 driver.
2857
2858 @retval EFI_SUCCESS Opal management was enabled.
2859 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
2860 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2861 @retval Others The driver failed to start the device.
2862
2863 **/
2864 EFI_STATUS
2865 EFIAPI
2866 OpalEfiDriverBindingStart(
2867 IN EFI_DRIVER_BINDING_PROTOCOL* This,
2868 IN EFI_HANDLE Controller,
2869 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath
2870 )
2871 {
2872 EFI_STATUS Status;
2873 EFI_BLOCK_IO_PROTOCOL *BlkIo;
2874 OPAL_DRIVER_DEVICE *Dev;
2875 OPAL_DRIVER_DEVICE *Itr;
2876 BOOLEAN Result;
2877
2878 Itr = mOpalDriver.DeviceList;
2879 while (Itr != NULL) {
2880 if (Controller == Itr->Handle) {
2881 return EFI_SUCCESS;
2882 }
2883 Itr = Itr->Next;
2884 }
2885
2886 //
2887 // Create internal device for tracking. This allows all disks to be tracked
2888 // by same HII form
2889 //
2890 Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));
2891 if (Dev == NULL) {
2892 return EFI_OUT_OF_RESOURCES;
2893 }
2894 Dev->Handle = Controller;
2895
2896 //
2897 // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks
2898 //
2899 Status = gBS->OpenProtocol(
2900 Controller,
2901 &gEfiStorageSecurityCommandProtocolGuid,
2902 (VOID **)&Dev->Sscp,
2903 This->DriverBindingHandle,
2904 Controller,
2905 EFI_OPEN_PROTOCOL_BY_DRIVER
2906 );
2907 if (EFI_ERROR(Status)) {
2908 FreePool(Dev);
2909 return Status;
2910 }
2911
2912 //
2913 // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
2914 // function APIs
2915 //
2916 Status = gBS->OpenProtocol(
2917 Controller,
2918 &gEfiBlockIoProtocolGuid,
2919 (VOID **)&BlkIo,
2920 This->DriverBindingHandle,
2921 Controller,
2922 EFI_OPEN_PROTOCOL_BY_DRIVER
2923 );
2924 if (EFI_ERROR(Status)) {
2925 //
2926 // Close storage security that was opened
2927 //
2928 gBS->CloseProtocol(
2929 Controller,
2930 &gEfiStorageSecurityCommandProtocolGuid,
2931 This->DriverBindingHandle,
2932 Controller
2933 );
2934
2935 FreePool(Dev);
2936 return Status;
2937 }
2938
2939 //
2940 // Save mediaId
2941 //
2942 Dev->MediaId = BlkIo->Media->MediaId;
2943
2944 gBS->CloseProtocol(
2945 Controller,
2946 &gEfiBlockIoProtocolGuid,
2947 This->DriverBindingHandle,
2948 Controller
2949 );
2950
2951 //
2952 // Acquire Ascii printable name of child, if not found, then ignore device
2953 //
2954 Result = OpalDriverGetDriverDeviceName (Dev);
2955 if (!Result) {
2956 goto Done;
2957 }
2958
2959 Status = OpalDiskInitialize (Dev);
2960 if (EFI_ERROR (Status)) {
2961 goto Done;
2962 }
2963
2964 AddDeviceToTail(Dev);
2965
2966 //
2967 // Check if device is locked and prompt for password.
2968 //
2969 OpalDriverRequestPassword (Dev, L"Unlock:");
2970
2971 //
2972 // Process OPAL request from last boot.
2973 //
2974 ProcessOpalRequest (Dev);
2975
2976 return EFI_SUCCESS;
2977
2978 Done:
2979 //
2980 // free device, close protocols and exit
2981 //
2982 gBS->CloseProtocol(
2983 Controller,
2984 &gEfiStorageSecurityCommandProtocolGuid,
2985 This->DriverBindingHandle,
2986 Controller
2987 );
2988
2989 FreePool(Dev);
2990
2991 return EFI_DEVICE_ERROR;
2992 }
2993
2994 /**
2995 Stop this driver on Controller.
2996
2997 @param This Protocol instance pointer.
2998 @param Controller Handle of device to stop driver on
2999 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
3000 children is zero stop the entire bus driver.
3001 @param ChildHandleBuffer List of Child Handles to Stop.
3002
3003 @retval EFI_SUCCESS This driver is removed Controller.
3004 @retval other This driver could not be removed from this device.
3005
3006 **/
3007 EFI_STATUS
3008 EFIAPI
3009 OpalEfiDriverBindingStop(
3010 EFI_DRIVER_BINDING_PROTOCOL* This,
3011 EFI_HANDLE Controller,
3012 UINTN NumberOfChildren,
3013 EFI_HANDLE* ChildHandleBuffer
3014 )
3015 {
3016 OPAL_DRIVER_DEVICE* Itr;
3017
3018 Itr = mOpalDriver.DeviceList;
3019
3020 //
3021 // does Controller match any of the devices we are managing for Opal
3022 //
3023 while (Itr != NULL) {
3024 if (Itr->Handle == Controller) {
3025 OpalDriverStopDevice (Itr);
3026 return EFI_SUCCESS;
3027 }
3028
3029 Itr = Itr->Next;
3030 }
3031
3032 return EFI_NOT_FOUND;
3033 }
3034
3035
3036 /**
3037 Unloads UEFI Driver. Very useful for debugging and testing.
3038
3039 @param ImageHandle Image Handle this driver.
3040
3041 @retval EFI_SUCCESS This function always complete successfully.
3042 @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.
3043 **/
3044 EFI_STATUS
3045 EFIAPI
3046 OpalEfiDriverUnload (
3047 IN EFI_HANDLE ImageHandle
3048 )
3049 {
3050 EFI_STATUS Status;
3051 OPAL_DRIVER_DEVICE *Itr;
3052
3053 Status = EFI_SUCCESS;
3054
3055 if (ImageHandle != gImageHandle) {
3056 return (EFI_INVALID_PARAMETER);
3057 }
3058
3059 //
3060 // Uninstall any interface added to each device by us
3061 //
3062 while (mOpalDriver.DeviceList) {
3063 Itr = mOpalDriver.DeviceList;
3064 //
3065 // Remove OPAL_DRIVER_DEVICE from the list
3066 // it updates the controllerList pointer
3067 //
3068 OpalDriverStopDevice(Itr);
3069 }
3070
3071 //
3072 // Uninstall the HII capability
3073 //
3074 Status = HiiUninstall();
3075
3076 return Status;
3077 }
3078