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