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