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