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