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