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