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