]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/Opal/OpalPassword/OpalDriver.c
SecurityPkg/TcgStorageOpalLib: Fix GCC build failure.
[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
690 CreatePopUp (\r
691 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
692 &InputKey,\r
693 PopUpString,\r
40d32e79 694 PopUpString2,\r
112e584b
SZ
695 L"---------------------",\r
696 Mask,\r
697 NULL\r
698 );\r
699\r
700 //\r
701 // Check key.\r
702 //\r
703 if (InputKey.ScanCode == SCAN_NULL) {\r
704 //\r
705 // password finished\r
706 //\r
707 if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
708 //\r
709 // Add the null terminator.\r
710 //\r
711 Unicode[InputLength] = 0;\r
712 Mask[InputLength] = 0;\r
713 break;\r
714 } else if ((InputKey.UnicodeChar == CHAR_NULL) ||\r
715 (InputKey.UnicodeChar == CHAR_TAB) ||\r
716 (InputKey.UnicodeChar == CHAR_LINEFEED)\r
717 ) {\r
718 continue;\r
719 } else {\r
720 //\r
721 // delete last key entered\r
722 //\r
723 if (InputKey.UnicodeChar == CHAR_BACKSPACE) {\r
724 if (InputLength > 0) {\r
725 Unicode[InputLength] = 0;\r
726 Mask[InputLength] = 0;\r
727 InputLength--;\r
728 }\r
729 } else {\r
730 //\r
731 // add Next key entry\r
732 //\r
733 Unicode[InputLength] = InputKey.UnicodeChar;\r
734 Mask[InputLength] = InputKey.UnicodeChar;\r
735 InputLength++;\r
736 if (InputLength == PSID_CHARACTER_LENGTH) {\r
737 //\r
738 // Add the null terminator.\r
739 //\r
740 Unicode[InputLength] = 0;\r
741 Mask[InputLength] = 0;\r
742 break;\r
743 }\r
744 }\r
745 }\r
746 }\r
747\r
748 //\r
749 // exit on ESC\r
750 //\r
751 if (InputKey.ScanCode == SCAN_ESC) {\r
752 *PressEsc = TRUE;\r
753 break;\r
754 }\r
755 }\r
756\r
757 gST->ConOut->ClearScreen(gST->ConOut);\r
758\r
759 if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {\r
760 ZeroMem (Unicode, sizeof (Unicode));\r
761 ZeroMem (Mask, sizeof (Mask));\r
762 return NULL;\r
763 }\r
764\r
765 Ascii = AllocateZeroPool (PSID_CHARACTER_LENGTH + 1);\r
766 if (Ascii == NULL) {\r
767 ZeroMem (Unicode, sizeof (Unicode));\r
768 ZeroMem (Mask, sizeof (Mask));\r
769 return NULL;\r
770 }\r
771\r
772 UnicodeStrToAsciiStrS (Unicode, Ascii, PSID_CHARACTER_LENGTH + 1);\r
773 ZeroMem (Unicode, sizeof (Unicode));\r
774 ZeroMem (Mask, sizeof (Mask));\r
775\r
776 return Ascii;\r
777}\r
778\r
779\r
780/**\r
781 Get password input from the popup window.\r
782\r
783 @param[in] Dev The device which need password to unlock or\r
784 process OPAL request.\r
785 @param[in] PopUpString1 Pop up string 1.\r
786 @param[in] PopUpString2 Pop up string 2.\r
787 @param[out] PressEsc Whether user escape function through Press ESC.\r
788\r
789 @retval Password string if success. NULL if failed.\r
790\r
791**/\r
792CHAR8 *\r
793OpalDriverPopUpPasswordInput (\r
794 IN OPAL_DRIVER_DEVICE *Dev,\r
795 IN CHAR16 *PopUpString1,\r
796 IN CHAR16 *PopUpString2,\r
797 OUT BOOLEAN *PressEsc\r
798 )\r
799{\r
800 EFI_INPUT_KEY InputKey;\r
801 UINTN InputLength;\r
802 CHAR16 Mask[OPAL_MAX_PASSWORD_SIZE + 1];\r
803 CHAR16 Unicode[OPAL_MAX_PASSWORD_SIZE + 1];\r
804 CHAR8 *Ascii;\r
805\r
806 ZeroMem(Unicode, sizeof(Unicode));\r
807 ZeroMem(Mask, sizeof(Mask));\r
808\r
809 *PressEsc = FALSE;\r
810\r
811 gST->ConOut->ClearScreen(gST->ConOut);\r
812\r
813 InputLength = 0;\r
814 while (TRUE) {\r
815 Mask[InputLength] = L'_';\r
816 if (PopUpString2 == NULL) {\r
817 CreatePopUp (\r
818 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
819 &InputKey,\r
820 PopUpString1,\r
821 L"---------------------",\r
822 Mask,\r
823 NULL\r
824 );\r
825 } else {\r
826 CreatePopUp (\r
827 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
828 &InputKey,\r
829 PopUpString1,\r
830 PopUpString2,\r
831 L"---------------------",\r
832 Mask,\r
833 NULL\r
834 );\r
835 }\r
836\r
837 //\r
838 // Check key.\r
839 //\r
840 if (InputKey.ScanCode == SCAN_NULL) {\r
841 //\r
842 // password finished\r
843 //\r
844 if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
845 //\r
846 // Add the null terminator.\r
847 //\r
848 Unicode[InputLength] = 0;\r
849 Mask[InputLength] = 0;\r
850 break;\r
851 } else if ((InputKey.UnicodeChar == CHAR_NULL) ||\r
852 (InputKey.UnicodeChar == CHAR_TAB) ||\r
853 (InputKey.UnicodeChar == CHAR_LINEFEED)\r
854 ) {\r
855 continue;\r
856 } else {\r
857 //\r
858 // delete last key entered\r
859 //\r
860 if (InputKey.UnicodeChar == CHAR_BACKSPACE) {\r
861 if (InputLength > 0) {\r
862 Unicode[InputLength] = 0;\r
863 Mask[InputLength] = 0;\r
864 InputLength--;\r
865 }\r
866 } else {\r
867 //\r
868 // add Next key entry\r
869 //\r
870 Unicode[InputLength] = InputKey.UnicodeChar;\r
871 Mask[InputLength] = L'*';\r
872 InputLength++;\r
873 if (InputLength == OPAL_MAX_PASSWORD_SIZE) {\r
874 //\r
875 // Add the null terminator.\r
876 //\r
877 Unicode[InputLength] = 0;\r
878 Mask[InputLength] = 0;\r
879 break;\r
880 }\r
881 }\r
882 }\r
883 }\r
884\r
885 //\r
886 // exit on ESC\r
887 //\r
888 if (InputKey.ScanCode == SCAN_ESC) {\r
889 *PressEsc = TRUE;\r
890 break;\r
891 }\r
892 }\r
893\r
894 gST->ConOut->ClearScreen(gST->ConOut);\r
895\r
896 if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {\r
897 ZeroMem (Unicode, sizeof (Unicode));\r
898 return NULL;\r
899 }\r
900\r
901 Ascii = AllocateZeroPool (OPAL_MAX_PASSWORD_SIZE + 1);\r
902 if (Ascii == NULL) {\r
903 ZeroMem (Unicode, sizeof (Unicode));\r
904 return NULL;\r
905 }\r
906\r
907 UnicodeStrToAsciiStrS (Unicode, Ascii, OPAL_MAX_PASSWORD_SIZE + 1);\r
908 ZeroMem (Unicode, sizeof (Unicode));\r
909\r
910 return Ascii;\r
911}\r
912\r
913/**\r
aa085730 914 Get pop up string.\r
112e584b 915\r
aa085730 916 @param[in] Dev The OPAL device.\r
112e584b
SZ
917 @param[in] RequestString Request string.\r
918\r
aa085730
SZ
919 @return Pop up string.\r
920\r
112e584b
SZ
921**/\r
922CHAR16 *\r
923OpalGetPopUpString (\r
924 IN OPAL_DRIVER_DEVICE *Dev,\r
925 IN CHAR16 *RequestString\r
926 )\r
927{\r
112e584b 928 if (Dev->Name16 == NULL) {\r
aa085730 929 UnicodeSPrint (mPopUpString, sizeof (mPopUpString), L"%s Disk", RequestString);\r
112e584b 930 } else {\r
aa085730 931 UnicodeSPrint (mPopUpString, sizeof (mPopUpString), L"%s %s", RequestString, Dev->Name16);\r
112e584b
SZ
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
40d32e79
ED
1375 CHAR16 *PopUpString2;\r
1376 UINTN BufferSize;\r
112e584b
SZ
1377\r
1378 if (Dev == NULL) {\r
1379 return;\r
1380 }\r
1381\r
1382 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1383\r
1384 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1385\r
40d32e79
ED
1386 if (Dev->OpalDisk.EstimateTimeCost > MAX_ACCEPTABLE_REVERTING_TIME) {\r
1387 BufferSize = StrSize (L"Warning: Revert action will take about ####### seconds, DO NOT power off system during the revert action!");\r
1388 PopUpString2 = AllocateZeroPool (BufferSize);\r
1389 ASSERT (PopUpString2 != NULL);\r
1390 UnicodeSPrint (\r
1391 PopUpString2,\r
1392 BufferSize,\r
1393 L"WARNING: Revert action will take about %d seconds, DO NOT power off system during the revert action!",\r
1394 Dev->OpalDisk.EstimateTimeCost\r
1395 );\r
1396 } else {\r
1397 PopUpString2 = NULL;\r
1398 }\r
1399\r
112e584b
SZ
1400 Count = 0;\r
1401\r
1402 ZeroMem(&Session, sizeof(Session));\r
1403 Session.Sscp = Dev->OpalDisk.Sscp;\r
1404 Session.MediaId = Dev->OpalDisk.MediaId;\r
1405 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1406\r
1407 while (Count < MAX_PSID_TRY_COUNT) {\r
40d32e79 1408 Psid = OpalDriverPopUpPsidInput (Dev, PopUpString, PopUpString2, &PressEsc);\r
112e584b
SZ
1409 if (PressEsc) {\r
1410 do {\r
1411 CreatePopUp (\r
1412 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1413 &Key,\r
1414 L"Press ENTER to skip the request and continue boot,",\r
1415 L"Press ESC to input Psid again",\r
1416 NULL\r
1417 );\r
1418 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1419\r
1420 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1421 gST->ConOut->ClearScreen(gST->ConOut);\r
40d32e79 1422 goto Done;\r
112e584b
SZ
1423 } else {\r
1424 //\r
1425 // Let user input Psid again.\r
1426 //\r
1427 continue;\r
1428 }\r
1429 }\r
1430\r
1431 if (Psid == NULL) {\r
1432 Count ++;\r
1433 continue;\r
1434 }\r
1435 PsidLen = (UINT32) AsciiStrLen(Psid);\r
1436\r
1437 Ret = OpalUtilPsidRevert(&Session, Psid, PsidLen);\r
1438 if (Ret == TcgResultSuccess) {\r
1439 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1440 } else {\r
1441 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1442 }\r
1443\r
1444 if (Psid != NULL) {\r
1445 ZeroMem (Psid, PsidLen);\r
1446 FreePool (Psid);\r
1447 }\r
1448\r
1449 if (Ret == TcgResultSuccess) {\r
1450 break;\r
1451 }\r
1452\r
1453 Count++;\r
1454\r
1455 do {\r
1456 CreatePopUp (\r
1457 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1458 &Key,\r
1459 L"Invalid Psid, request failed.",\r
1460 L"Press ENTER to retry",\r
1461 NULL\r
1462 );\r
1463 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1464 }\r
1465\r
1466 if (Count >= MAX_PSID_TRY_COUNT) {\r
1467 do {\r
1468 CreatePopUp (\r
1469 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1470 &Key,\r
1471 L"Opal Psid retry count exceeds the limit.",\r
1472 L"Press ENTER to skip the request and continue boot",\r
1473 NULL\r
1474 );\r
1475 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1476 gST->ConOut->ClearScreen(gST->ConOut);\r
1477 }\r
40d32e79
ED
1478\r
1479Done:\r
1480 if (PopUpString2 != NULL) {\r
1481 FreePool (PopUpString2);\r
1482 }\r
112e584b
SZ
1483}\r
1484\r
1485/**\r
1486 Process Admin Revert OPAL request.\r
1487\r
1488 @param[in] Dev The device which has Revert OPAL request.\r
1489 @param[in] KeepUserData Whether to keep user data or not.\r
1490 @param[in] RequestString Request string.\r
1491\r
1492**/\r
1493VOID\r
1494ProcessOpalRequestRevert (\r
1495 IN OPAL_DRIVER_DEVICE *Dev,\r
1496 IN BOOLEAN KeepUserData,\r
1497 IN CHAR16 *RequestString\r
1498 )\r
1499{\r
1500 UINT8 Count;\r
1501 CHAR8 *Password;\r
1502 UINT32 PasswordLen;\r
1503 OPAL_SESSION Session;\r
1504 BOOLEAN PressEsc;\r
1505 EFI_INPUT_KEY Key;\r
1506 TCG_RESULT Ret;\r
1507 BOOLEAN PasswordFailed;\r
1508 CHAR16 *PopUpString;\r
40d32e79
ED
1509 CHAR16 *PopUpString2;\r
1510 UINTN BufferSize;\r
112e584b
SZ
1511\r
1512 if (Dev == NULL) {\r
1513 return;\r
1514 }\r
1515\r
1516 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1517\r
1518 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1519\r
40d32e79
ED
1520 if (Dev->OpalDisk.EstimateTimeCost > MAX_ACCEPTABLE_REVERTING_TIME) {\r
1521 BufferSize = StrSize (L"Warning: Revert action will take about ####### seconds, DO NOT power off system during the revert action!");\r
1522 PopUpString2 = AllocateZeroPool (BufferSize);\r
1523 ASSERT (PopUpString2 != NULL);\r
1524 UnicodeSPrint (\r
1525 PopUpString2,\r
1526 BufferSize,\r
1527 L"WARNING: Revert action will take about %d seconds, DO NOT power off system during the revert action!",\r
1528 Dev->OpalDisk.EstimateTimeCost\r
1529 );\r
1530 } else {\r
1531 PopUpString2 = NULL;\r
1532 }\r
1533\r
112e584b
SZ
1534 Count = 0;\r
1535\r
1536 ZeroMem(&Session, sizeof(Session));\r
1537 Session.Sscp = Dev->OpalDisk.Sscp;\r
1538 Session.MediaId = Dev->OpalDisk.MediaId;\r
1539 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1540\r
1541 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
40d32e79 1542 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, PopUpString2, &PressEsc);\r
112e584b
SZ
1543 if (PressEsc) {\r
1544 do {\r
1545 CreatePopUp (\r
1546 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1547 &Key,\r
1548 L"Press ENTER to skip the request and continue boot,",\r
1549 L"Press ESC to input password again",\r
1550 NULL\r
1551 );\r
1552 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1553\r
1554 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1555 gST->ConOut->ClearScreen(gST->ConOut);\r
40d32e79 1556 goto Done;\r
112e584b
SZ
1557 } else {\r
1558 //\r
1559 // Let user input password again.\r
1560 //\r
1561 continue;\r
1562 }\r
1563 }\r
1564\r
1565 if (Password == NULL) {\r
1566 Count ++;\r
1567 continue;\r
1568 }\r
1569 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1570\r
1571 if ((Dev->OpalDisk.SupportedAttributes.PyriteSsc == 1) &&\r
1572 (Dev->OpalDisk.LockingFeature.MediaEncryption == 0)) {\r
1573 //\r
1574 // For pyrite type device which does not support media encryption,\r
1575 // it does not accept "Keep User Data" parameter.\r
1576 // So here hardcode a FALSE for this case.\r
1577 //\r
1578 Ret = OpalUtilRevert(\r
1579 &Session,\r
1580 FALSE,\r
1581 Password,\r
1582 PasswordLen,\r
1583 &PasswordFailed,\r
1584 Dev->OpalDisk.Msid,\r
1585 Dev->OpalDisk.MsidLength\r
1586 );\r
1587 } else {\r
1588 Ret = OpalUtilRevert(\r
1589 &Session,\r
1590 KeepUserData,\r
1591 Password,\r
1592 PasswordLen,\r
1593 &PasswordFailed,\r
1594 Dev->OpalDisk.Msid,\r
1595 Dev->OpalDisk.MsidLength\r
1596 );\r
1597 }\r
1598 if (Ret == TcgResultSuccess) {\r
1599 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1600 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1601 } else {\r
1602 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1603 }\r
1604\r
1605 if (Password != NULL) {\r
1606 ZeroMem (Password, PasswordLen);\r
1607 FreePool (Password);\r
1608 }\r
1609\r
1610 if (Ret == TcgResultSuccess) {\r
1611 break;\r
1612 }\r
1613\r
1614 Count++;\r
1615\r
1616 do {\r
1617 CreatePopUp (\r
1618 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1619 &Key,\r
1620 L"Invalid password, request failed.",\r
1621 L"Press ENTER to retry",\r
1622 NULL\r
1623 );\r
1624 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1625 }\r
1626\r
1627 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1628 do {\r
1629 CreatePopUp (\r
1630 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1631 &Key,\r
1632 L"Opal password retry count exceeds the limit.",\r
1633 L"Press ENTER to skip the request and continue boot",\r
1634 NULL\r
1635 );\r
1636 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1637 gST->ConOut->ClearScreen(gST->ConOut);\r
1638 }\r
40d32e79
ED
1639\r
1640Done:\r
1641 if (PopUpString2 != NULL) {\r
1642 FreePool (PopUpString2);\r
1643 }\r
112e584b
SZ
1644}\r
1645\r
1646/**\r
1647 Process Secure Erase OPAL request.\r
1648\r
1649 @param[in] Dev The device which has Secure Erase OPAL request.\r
1650 @param[in] RequestString Request string.\r
1651\r
1652**/\r
1653VOID\r
1654ProcessOpalRequestSecureErase (\r
1655 IN OPAL_DRIVER_DEVICE *Dev,\r
1656 IN CHAR16 *RequestString\r
1657 )\r
1658{\r
1659 UINT8 Count;\r
1660 CHAR8 *Password;\r
1661 UINT32 PasswordLen;\r
1662 OPAL_SESSION Session;\r
1663 BOOLEAN PressEsc;\r
1664 EFI_INPUT_KEY Key;\r
1665 TCG_RESULT Ret;\r
1666 BOOLEAN PasswordFailed;\r
1667 CHAR16 *PopUpString;\r
1668\r
1669 if (Dev == NULL) {\r
1670 return;\r
1671 }\r
1672\r
1673 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1674\r
1675 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1676\r
1677 Count = 0;\r
1678\r
1679 ZeroMem(&Session, sizeof(Session));\r
1680 Session.Sscp = Dev->OpalDisk.Sscp;\r
1681 Session.MediaId = Dev->OpalDisk.MediaId;\r
1682 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1683\r
1684 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
1685 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, NULL, &PressEsc);\r
1686 if (PressEsc) {\r
1687 do {\r
1688 CreatePopUp (\r
1689 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1690 &Key,\r
1691 L"Press ENTER to skip the request and continue boot,",\r
1692 L"Press ESC to input password again",\r
1693 NULL\r
1694 );\r
1695 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1696\r
1697 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1698 gST->ConOut->ClearScreen(gST->ConOut);\r
1699 return;\r
1700 } else {\r
1701 //\r
1702 // Let user input password again.\r
1703 //\r
1704 continue;\r
1705 }\r
1706 }\r
1707\r
1708 if (Password == NULL) {\r
1709 Count ++;\r
1710 continue;\r
1711 }\r
1712 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1713\r
1714 Ret = OpalUtilSecureErase(&Session, Password, PasswordLen, &PasswordFailed);\r
1715 if (Ret == TcgResultSuccess) {\r
1716 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1717 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1718 } else {\r
1719 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1720 }\r
1721\r
1722 if (Password != NULL) {\r
1723 ZeroMem (Password, PasswordLen);\r
1724 FreePool (Password);\r
1725 }\r
1726\r
1727 if (Ret == TcgResultSuccess) {\r
1728 break;\r
1729 }\r
1730\r
1731 Count++;\r
1732\r
1733 do {\r
1734 CreatePopUp (\r
1735 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1736 &Key,\r
1737 L"Invalid password, request failed.",\r
1738 L"Press ENTER to retry",\r
1739 NULL\r
1740 );\r
1741 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1742 }\r
1743\r
1744 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1745 do {\r
1746 CreatePopUp (\r
1747 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1748 &Key,\r
1749 L"Opal password retry count exceeds the limit.",\r
1750 L"Press ENTER to skip the request and continue boot",\r
1751 NULL\r
1752 );\r
1753 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1754 gST->ConOut->ClearScreen(gST->ConOut);\r
1755 }\r
1756}\r
1757\r
1758/**\r
1759 Process Set Admin Pwd OPAL request.\r
1760\r
1761 @param[in] Dev The device which has Set Admin Pwd Feature OPAL request.\r
1762 @param[in] RequestString Request string.\r
1763\r
1764**/\r
1765VOID\r
1766ProcessOpalRequestSetUserPwd (\r
1767 IN OPAL_DRIVER_DEVICE *Dev,\r
1768 IN CHAR16 *RequestString\r
1769 )\r
1770{\r
1771 UINT8 Count;\r
1772 CHAR8 *OldPassword;\r
1773 UINT32 OldPasswordLen;\r
1774 CHAR8 *Password;\r
1775 UINT32 PasswordLen;\r
1776 CHAR8 *PasswordConfirm;\r
1777 UINT32 PasswordLenConfirm;\r
1778 OPAL_SESSION Session;\r
1779 BOOLEAN PressEsc;\r
1780 EFI_INPUT_KEY Key;\r
1781 TCG_RESULT Ret;\r
1782 CHAR16 *PopUpString;\r
1783\r
1784 if (Dev == NULL) {\r
1785 return;\r
1786 }\r
1787\r
1788 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1789\r
1790 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1791\r
1792 Count = 0;\r
1793\r
1794 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
1795 OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);\r
1796 if (PressEsc) {\r
1797 do {\r
1798 CreatePopUp (\r
1799 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1800 &Key,\r
1801 L"Press ENTER to skip the request and continue boot,",\r
1802 L"Press ESC to input password again",\r
1803 NULL\r
1804 );\r
1805 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
1806\r
1807 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
1808 gST->ConOut->ClearScreen(gST->ConOut);\r
1809 return;\r
1810 } else {\r
1811 //\r
1812 // Let user input password again.\r
1813 //\r
1814 continue;\r
1815 }\r
1816 }\r
1817\r
1818 if (OldPassword == NULL) {\r
1819 Count ++;\r
1820 continue;\r
1821 }\r
1822 OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);\r
1823\r
1824 ZeroMem(&Session, sizeof(Session));\r
1825 Session.Sscp = Dev->OpalDisk.Sscp;\r
1826 Session.MediaId = Dev->OpalDisk.MediaId;\r
1827 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1828 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_USER1_AUTHORITY);\r
1829 if (Ret == TcgResultSuccess) {\r
1830 DEBUG ((DEBUG_INFO, "Verify with USER1 authority : Success\n"));\r
1831 } else {\r
1832 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);\r
1833 if (Ret == TcgResultSuccess) {\r
1834 DEBUG ((DEBUG_INFO, "Verify with ADMIN1 authority: Success\n"));\r
1835 } else {\r
1836 ZeroMem (OldPassword, OldPasswordLen);\r
1837 FreePool (OldPassword);\r
1838 DEBUG ((DEBUG_INFO, "Verify: Failure\n"));\r
1839 do {\r
1840 CreatePopUp (\r
1841 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1842 &Key,\r
1843 L"Incorrect password.",\r
1844 L"Press ENTER to retry",\r
1845 NULL\r
1846 );\r
1847 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1848 Count ++;\r
1849 continue;\r
1850 }\r
1851 }\r
1852\r
1853 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);\r
1854 if (Password == NULL) {\r
1855 ZeroMem (OldPassword, OldPasswordLen);\r
1856 FreePool (OldPassword);\r
1857 Count ++;\r
1858 continue;\r
1859 }\r
1860 PasswordLen = (UINT32) AsciiStrLen(Password);\r
1861\r
1862 PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);\r
1863 if (PasswordConfirm == NULL) {\r
1864 ZeroMem (OldPassword, OldPasswordLen);\r
1865 FreePool (OldPassword);\r
1866 ZeroMem (Password, PasswordLen);\r
1867 FreePool (Password);\r
1868 Count ++;\r
1869 continue;\r
1870 }\r
1871 PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);\r
1872 if ((PasswordLen != PasswordLenConfirm) ||\r
1873 (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {\r
1874 ZeroMem (OldPassword, OldPasswordLen);\r
1875 FreePool (OldPassword);\r
1876 ZeroMem (Password, PasswordLen);\r
1877 FreePool (Password);\r
1878 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
1879 FreePool (PasswordConfirm);\r
1880 do {\r
1881 CreatePopUp (\r
1882 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1883 &Key,\r
1884 L"Passwords are not the same.",\r
1885 L"Press ENTER to retry",\r
1886 NULL\r
1887 );\r
1888 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1889 Count ++;\r
1890 continue;\r
1891 }\r
1892\r
1893 if (PasswordConfirm != NULL) {\r
1894 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
1895 FreePool (PasswordConfirm);\r
1896 }\r
1897\r
1898 ZeroMem(&Session, sizeof(Session));\r
1899 Session.Sscp = Dev->OpalDisk.Sscp;\r
1900 Session.MediaId = Dev->OpalDisk.MediaId;\r
1901 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
1902 Ret = OpalUtilSetUserPassword(\r
1903 &Session,\r
1904 OldPassword,\r
1905 OldPasswordLen,\r
1906 Password,\r
1907 PasswordLen\r
1908 );\r
1909 if (Ret == TcgResultSuccess) {\r
1910 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
1911 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
1912 } else {\r
1913 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
1914 }\r
1915\r
1916 if (OldPassword != NULL) {\r
1917 ZeroMem (OldPassword, OldPasswordLen);\r
1918 FreePool (OldPassword);\r
1919 }\r
1920\r
1921 if (Password != NULL) {\r
1922 ZeroMem (Password, PasswordLen);\r
1923 FreePool (Password);\r
1924 }\r
1925\r
1926 if (Ret == TcgResultSuccess) {\r
1927 break;\r
1928 }\r
1929\r
1930 Count++;\r
1931\r
1932 do {\r
1933 CreatePopUp (\r
1934 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1935 &Key,\r
1936 L"Request failed.",\r
1937 L"Press ENTER to retry",\r
1938 NULL\r
1939 );\r
1940 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1941 }\r
1942\r
1943 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
1944 do {\r
1945 CreatePopUp (\r
1946 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1947 &Key,\r
1948 L"Opal password retry count exceeds the limit.",\r
1949 L"Press ENTER to skip the request and continue boot",\r
1950 NULL\r
1951 );\r
1952 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
1953 gST->ConOut->ClearScreen(gST->ConOut);\r
1954 }\r
1955}\r
1956\r
1957/**\r
1958 Process Set Admin Pwd OPAL request.\r
1959\r
1960 @param[in] Dev The device which has Set Admin Pwd Feature OPAL request.\r
1961 @param[in] RequestString Request string.\r
1962\r
1963**/\r
1964VOID\r
1965ProcessOpalRequestSetAdminPwd (\r
1966 IN OPAL_DRIVER_DEVICE *Dev,\r
1967 IN CHAR16 *RequestString\r
1968 )\r
1969{\r
1970 UINT8 Count;\r
1971 CHAR8 *OldPassword;\r
1972 UINT32 OldPasswordLen;\r
1973 CHAR8 *Password;\r
1974 UINT32 PasswordLen;\r
1975 CHAR8 *PasswordConfirm;\r
1976 UINT32 PasswordLenConfirm;\r
1977 OPAL_SESSION Session;\r
1978 BOOLEAN PressEsc;\r
1979 EFI_INPUT_KEY Key;\r
1980 TCG_RESULT Ret;\r
1981 CHAR16 *PopUpString;\r
1982\r
1983 if (Dev == NULL) {\r
1984 return;\r
1985 }\r
1986\r
1987 DEBUG ((DEBUG_INFO, "%a()\n", __FUNCTION__));\r
1988\r
1989 PopUpString = OpalGetPopUpString (Dev, RequestString);\r
1990\r
1991 Count = 0;\r
1992\r
1993 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
1994 OldPassword = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your password", &PressEsc);\r
1995 if (PressEsc) {\r
1996 do {\r
1997 CreatePopUp (\r
1998 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
1999 &Key,\r
2000 L"Press ENTER to skip the request and continue boot,",\r
2001 L"Press ESC to input password again",\r
2002 NULL\r
2003 );\r
2004 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
2005\r
2006 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
2007 gST->ConOut->ClearScreen(gST->ConOut);\r
2008 return;\r
2009 } else {\r
2010 //\r
2011 // Let user input password again.\r
2012 //\r
2013 continue;\r
2014 }\r
2015 }\r
2016\r
2017 if (OldPassword == NULL) {\r
2018 Count ++;\r
2019 continue;\r
2020 }\r
2021 OldPasswordLen = (UINT32) AsciiStrLen(OldPassword);\r
2022\r
2023 ZeroMem(&Session, sizeof(Session));\r
2024 Session.Sscp = Dev->OpalDisk.Sscp;\r
2025 Session.MediaId = Dev->OpalDisk.MediaId;\r
2026 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
2027 Ret = OpalUtilVerifyPassword (&Session, OldPassword, OldPasswordLen, OPAL_LOCKING_SP_ADMIN1_AUTHORITY);\r
2028 if (Ret == TcgResultSuccess) {\r
2029 DEBUG ((DEBUG_INFO, "Verify: Success\n"));\r
2030 } else {\r
2031 ZeroMem (OldPassword, OldPasswordLen);\r
2032 FreePool (OldPassword);\r
2033 DEBUG ((DEBUG_INFO, "Verify: Failure\n"));\r
2034 do {\r
2035 CreatePopUp (\r
2036 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2037 &Key,\r
2038 L"Incorrect password.",\r
2039 L"Press ENTER to retry",\r
2040 NULL\r
2041 );\r
2042 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2043 Count ++;\r
2044 continue;\r
2045 }\r
2046\r
2047 Password = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please type in your new password", &PressEsc);\r
2048 if (Password == NULL) {\r
2049 ZeroMem (OldPassword, OldPasswordLen);\r
2050 FreePool (OldPassword);\r
2051 Count ++;\r
2052 continue;\r
2053 }\r
2054 PasswordLen = (UINT32) AsciiStrLen(Password);\r
2055\r
2056 PasswordConfirm = OpalDriverPopUpPasswordInput (Dev, PopUpString, L"Please confirm your new password", &PressEsc);\r
2057 if (PasswordConfirm == NULL) {\r
2058 ZeroMem (OldPassword, OldPasswordLen);\r
2059 FreePool (OldPassword);\r
2060 ZeroMem (Password, PasswordLen);\r
2061 FreePool (Password);\r
2062 Count ++;\r
2063 continue;\r
2064 }\r
2065 PasswordLenConfirm = (UINT32) AsciiStrLen(PasswordConfirm);\r
2066 if ((PasswordLen != PasswordLenConfirm) ||\r
2067 (CompareMem (Password, PasswordConfirm, PasswordLen) != 0)) {\r
2068 ZeroMem (OldPassword, OldPasswordLen);\r
2069 FreePool (OldPassword);\r
2070 ZeroMem (Password, PasswordLen);\r
2071 FreePool (Password);\r
2072 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
2073 FreePool (PasswordConfirm);\r
2074 do {\r
2075 CreatePopUp (\r
2076 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2077 &Key,\r
2078 L"Passwords are not the same.",\r
2079 L"Press ENTER to retry",\r
2080 NULL\r
2081 );\r
2082 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2083 Count ++;\r
2084 continue;\r
2085 }\r
2086\r
2087 if (PasswordConfirm != NULL) {\r
2088 ZeroMem (PasswordConfirm, PasswordLenConfirm);\r
2089 FreePool (PasswordConfirm);\r
2090 }\r
2091\r
2092\r
2093 ZeroMem(&Session, sizeof(Session));\r
2094 Session.Sscp = Dev->OpalDisk.Sscp;\r
2095 Session.MediaId = Dev->OpalDisk.MediaId;\r
2096 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
2097 Ret = OpalUtilSetAdminPassword(\r
2098 &Session,\r
2099 OldPassword,\r
2100 OldPasswordLen,\r
2101 Password,\r
2102 PasswordLen\r
2103 );\r
2104 if (Ret == TcgResultSuccess) {\r
2105 OpalSupportUpdatePassword (&Dev->OpalDisk, Password, PasswordLen);\r
2106 DEBUG ((DEBUG_INFO, "%s Success\n", RequestString));\r
2107 } else {\r
2108 DEBUG ((DEBUG_INFO, "%s Failure\n", RequestString));\r
2109 }\r
2110\r
2111 if (OldPassword != NULL) {\r
2112 ZeroMem (OldPassword, OldPasswordLen);\r
2113 FreePool (OldPassword);\r
2114 }\r
2115\r
2116 if (Password != NULL) {\r
2117 ZeroMem (Password, PasswordLen);\r
2118 FreePool (Password);\r
2119 }\r
2120\r
2121 if (Ret == TcgResultSuccess) {\r
2122 break;\r
2123 }\r
2124\r
2125 Count++;\r
2126\r
2127 do {\r
2128 CreatePopUp (\r
2129 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2130 &Key,\r
2131 L"Request failed.",\r
2132 L"Press ENTER to retry",\r
2133 NULL\r
2134 );\r
2135 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2136 }\r
2137\r
2138 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
2139 do {\r
2140 CreatePopUp (\r
2141 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
2142 &Key,\r
2143 L"Opal password retry count exceeds the limit.",\r
2144 L"Press ENTER to skip the request and continue boot",\r
2145 NULL\r
2146 );\r
2147 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
2148 gST->ConOut->ClearScreen(gST->ConOut);\r
2149 }\r
2150}\r
2151\r
2152/**\r
2153 Process OPAL request.\r
2154\r
2155 @param[in] Dev The device which has OPAL request.\r
2156\r
2157**/\r
2158VOID\r
2159ProcessOpalRequest (\r
2160 IN OPAL_DRIVER_DEVICE *Dev\r
2161 )\r
2162{\r
2163 EFI_STATUS Status;\r
2164 OPAL_REQUEST_VARIABLE *TempVariable;\r
2165 OPAL_REQUEST_VARIABLE *Variable;\r
2166 UINTN VariableSize;\r
2167 EFI_DEVICE_PATH_PROTOCOL *DevicePathInVariable;\r
2168 UINTN DevicePathSizeInVariable;\r
2169 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
2170 UINTN DevicePathSize;\r
2171 BOOLEAN KeepUserData;\r
2172\r
2173 DEBUG ((DEBUG_INFO, "%a() - enter\n", __FUNCTION__));\r
2174\r
2175 if (mOpalRequestVariable == NULL) {\r
2176 Status = GetVariable2 (\r
2177 OPAL_REQUEST_VARIABLE_NAME,\r
2178 &gHiiSetupVariableGuid,\r
2179 (VOID **) &Variable,\r
2180 &VariableSize\r
2181 );\r
2182 if (EFI_ERROR (Status) || (Variable == NULL)) {\r
2183 return;\r
2184 }\r
2185 mOpalRequestVariable = Variable;\r
2186 mOpalRequestVariableSize = VariableSize;\r
2187\r
2188 //\r
2189 // Delete the OPAL request variable.\r
2190 //\r
2191 Status = gRT->SetVariable (\r
2192 OPAL_REQUEST_VARIABLE_NAME,\r
2193 (EFI_GUID *) &gHiiSetupVariableGuid,\r
2194 0,\r
2195 0,\r
2196 NULL\r
2197 );\r
2198 ASSERT_EFI_ERROR (Status);\r
2199 } else {\r
2200 Variable = mOpalRequestVariable;\r
2201 VariableSize = mOpalRequestVariableSize;\r
2202 }\r
2203\r
2204 //\r
2205 // Process the OPAL requests.\r
2206 //\r
2207 TempVariable = Variable;\r
2208 while ((VariableSize > sizeof (OPAL_REQUEST_VARIABLE)) &&\r
2209 (VariableSize >= TempVariable->Length) &&\r
2210 (TempVariable->Length > sizeof (OPAL_REQUEST_VARIABLE))) {\r
2211 DevicePathInVariable = (EFI_DEVICE_PATH_PROTOCOL *) ((UINTN) TempVariable + sizeof (OPAL_REQUEST_VARIABLE));\r
2212 DevicePathSizeInVariable = GetDevicePathSize (DevicePathInVariable);\r
2213 DevicePath = Dev->OpalDisk.OpalDevicePath;\r
2214 DevicePathSize = GetDevicePathSize (DevicePath);\r
2215 if ((DevicePathSize == DevicePathSizeInVariable) &&\r
2216 (CompareMem (DevicePath, DevicePathInVariable, DevicePathSize) == 0)) {\r
2217 //\r
2218 // Found the node for the OPAL device.\r
2219 //\r
2220 if (TempVariable->OpalRequest.SetAdminPwd != 0) {\r
2221 ProcessOpalRequestSetAdminPwd (Dev, L"Update Admin Pwd:");\r
2222 }\r
2223 if (TempVariable->OpalRequest.SetUserPwd != 0) {\r
2224 ProcessOpalRequestSetUserPwd (Dev, L"Set User Pwd:");\r
2225 }\r
2226 if (TempVariable->OpalRequest.SecureErase!= 0) {\r
2227 ProcessOpalRequestSecureErase (Dev, L"Secure Erase:");\r
2228 }\r
2229 if (TempVariable->OpalRequest.Revert != 0) {\r
2230 KeepUserData = (BOOLEAN) TempVariable->OpalRequest.KeepUserData;\r
2231 ProcessOpalRequestRevert (\r
2232 Dev,\r
2233 KeepUserData,\r
2234 KeepUserData ? L"Admin Revert(keep):" : L"Admin Revert:"\r
2235 );\r
2236 }\r
2237 if (TempVariable->OpalRequest.PsidRevert != 0) {\r
2238 ProcessOpalRequestPsidRevert (Dev, L"Psid Revert:");\r
2239 }\r
2240 if (TempVariable->OpalRequest.DisableUser != 0) {\r
2241 ProcessOpalRequestDisableUser (Dev, L"Disable User:");\r
2242 }\r
2243 if (TempVariable->OpalRequest.EnableFeature != 0) {\r
2244 ProcessOpalRequestEnableFeature (Dev, L"Enable Feature:");\r
2245 }\r
2246\r
2247 break;\r
2248 }\r
2249\r
2250 VariableSize -= TempVariable->Length;\r
2251 TempVariable = (OPAL_REQUEST_VARIABLE *) ((UINTN) TempVariable + TempVariable->Length);\r
2252 }\r
2253\r
2254 DEBUG ((DEBUG_INFO, "%a() - exit\n", __FUNCTION__));\r
2255}\r
2256\r
2257/**\r
2258 Add new device to the global device list.\r
2259\r
2260 @param Dev New create device.\r
2261\r
2262**/\r
2263VOID\r
2264AddDeviceToTail(\r
2265 IN OPAL_DRIVER_DEVICE *Dev\r
2266 )\r
2267{\r
2268 OPAL_DRIVER_DEVICE *TmpDev;\r
2269\r
2270 if (mOpalDriver.DeviceList == NULL) {\r
2271 mOpalDriver.DeviceList = Dev;\r
2272 } else {\r
2273 TmpDev = mOpalDriver.DeviceList;\r
2274 while (TmpDev->Next != NULL) {\r
2275 TmpDev = TmpDev->Next;\r
2276 }\r
2277\r
2278 TmpDev->Next = Dev;\r
2279 }\r
2280}\r
2281\r
2282/**\r
2283 Remove one device in the global device list.\r
2284\r
2285 @param Dev The device need to be removed.\r
2286\r
2287**/\r
2288VOID\r
2289RemoveDevice (\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 return;\r
2297 }\r
2298\r
2299 if (mOpalDriver.DeviceList == Dev) {\r
2300 mOpalDriver.DeviceList = NULL;\r
2301 return;\r
2302 }\r
2303\r
2304 TmpDev = mOpalDriver.DeviceList;\r
2305 while (TmpDev->Next != NULL) {\r
2306 if (TmpDev->Next == Dev) {\r
2307 TmpDev->Next = Dev->Next;\r
2308 break;\r
2309 }\r
2310 }\r
2311}\r
2312\r
2313/**\r
2314 Get current device count.\r
2315\r
2316 @retval return the current created device count.\r
2317\r
2318**/\r
2319UINT8\r
2320GetDeviceCount (\r
2321 VOID\r
2322 )\r
2323{\r
2324 UINT8 Count;\r
2325 OPAL_DRIVER_DEVICE *TmpDev;\r
2326\r
2327 Count = 0;\r
2328 TmpDev = mOpalDriver.DeviceList;\r
2329\r
2330 while (TmpDev != NULL) {\r
2331 Count++;\r
2332 TmpDev = TmpDev->Next;\r
2333 }\r
2334\r
2335 return Count;\r
2336}\r
2337\r
2338/**\r
2339 Get devcie list info.\r
2340\r
2341 @retval return the device list pointer.\r
2342**/\r
2343OPAL_DRIVER_DEVICE*\r
2344OpalDriverGetDeviceList(\r
2345 VOID\r
2346 )\r
2347{\r
2348 return mOpalDriver.DeviceList;\r
2349}\r
2350\r
2351/**\r
2352 ReadyToBoot callback to send BlockSid command.\r
2353\r
2354 @param Event Pointer to this event\r
2355 @param Context Event handler private Data\r
2356\r
2357**/\r
2358VOID\r
2359EFIAPI\r
2360ReadyToBootCallback (\r
2361 IN EFI_EVENT Event,\r
2362 IN VOID *Context\r
2363 )\r
2364{\r
2365 OPAL_DRIVER_DEVICE *Itr;\r
2366 TCG_RESULT Result;\r
2367 OPAL_SESSION Session;\r
2368 UINT32 PpStorageFlag;\r
2369\r
2370 gBS->CloseEvent (Event);\r
2371\r
2372 PpStorageFlag = Tcg2PhysicalPresenceLibGetManagementFlags ();\r
2373 if ((PpStorageFlag & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_ENABLE_BLOCK_SID) != 0) {\r
2374 //\r
2375 // Send BlockSID command to each Opal disk\r
2376 //\r
2377 Itr = mOpalDriver.DeviceList;\r
2378 while (Itr != NULL) {\r
2379 if (Itr->OpalDisk.SupportedAttributes.BlockSid) {\r
2380 ZeroMem(&Session, sizeof(Session));\r
2381 Session.Sscp = Itr->OpalDisk.Sscp;\r
2382 Session.MediaId = Itr->OpalDisk.MediaId;\r
2383 Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;\r
2384\r
40d32e79 2385 DEBUG ((DEBUG_INFO, "OpalPassword: ReadyToBoot point, send BlockSid command to device!\n"));\r
112e584b
SZ
2386 Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE\r
2387 if (Result != TcgResultSuccess) {\r
2388 DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));\r
2389 break;\r
2390 }\r
2391 }\r
2392\r
2393 Itr = Itr->Next;\r
2394 }\r
2395 }\r
2396}\r
2397\r
2398/**\r
2399 Stop this Controller.\r
2400\r
2401 @param Dev The device need to be stopped.\r
2402\r
2403**/\r
2404VOID\r
2405OpalDriverStopDevice (\r
2406 OPAL_DRIVER_DEVICE *Dev\r
2407 )\r
2408{\r
2409 //\r
2410 // free each name\r
2411 //\r
2412 FreePool(Dev->Name16);\r
2413\r
2414 //\r
2415 // remove OPAL_DRIVER_DEVICE from the list\r
2416 // it updates the controllerList pointer\r
2417 //\r
2418 RemoveDevice(Dev);\r
2419\r
2420 //\r
2421 // close protocols that were opened\r
2422 //\r
2423 gBS->CloseProtocol(\r
2424 Dev->Handle,\r
2425 &gEfiStorageSecurityCommandProtocolGuid,\r
2426 gOpalDriverBinding.DriverBindingHandle,\r
2427 Dev->Handle\r
2428 );\r
2429\r
2430 gBS->CloseProtocol(\r
2431 Dev->Handle,\r
2432 &gEfiBlockIoProtocolGuid,\r
2433 gOpalDriverBinding.DriverBindingHandle,\r
2434 Dev->Handle\r
2435 );\r
2436\r
2437 FreePool(Dev);\r
2438}\r
2439\r
2440/**\r
2441 Get devcie name through the component name protocol.\r
2442\r
2443 @param[in] AllHandlesBuffer The handle buffer for current system.\r
2444 @param[in] NumAllHandles The number of handles for the handle buffer.\r
2445 @param[in] Dev The device which need to get name.\r
2446 @param[in] UseComp1 Whether use component name or name2 protocol.\r
2447\r
2448 @retval TRUE Find the name for this device.\r
2449 @retval FALSE Not found the name for this device.\r
2450**/\r
2451BOOLEAN\r
2452OpalDriverGetDeviceNameByProtocol(\r
2453 EFI_HANDLE *AllHandlesBuffer,\r
2454 UINTN NumAllHandles,\r
2455 OPAL_DRIVER_DEVICE *Dev,\r
2456 BOOLEAN UseComp1\r
2457 )\r
2458{\r
2459 EFI_HANDLE* ProtocolHandlesBuffer;\r
2460 UINTN NumProtocolHandles;\r
2461 EFI_STATUS Status;\r
2462 EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout\r
2463 EFI_GUID Protocol;\r
2464 UINTN StrLength;\r
2465 EFI_DEVICE_PATH_PROTOCOL* TmpDevPath;\r
2466 UINTN Index1;\r
2467 UINTN Index2;\r
2468 EFI_HANDLE TmpHandle;\r
2469 CHAR16 *DevName;\r
2470\r
2471 if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {\r
2472 return FALSE;\r
2473 }\r
2474\r
2475 Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;\r
2476\r
2477 //\r
2478 // Find all EFI_HANDLES with protocol\r
2479 //\r
2480 Status = gBS->LocateHandleBuffer(\r
2481 ByProtocol,\r
2482 &Protocol,\r
2483 NULL,\r
2484 &NumProtocolHandles,\r
2485 &ProtocolHandlesBuffer\r
2486 );\r
2487 if (EFI_ERROR(Status)) {\r
2488 return FALSE;\r
2489 }\r
2490\r
2491\r
2492 //\r
2493 // Exit early if no supported devices\r
2494 //\r
2495 if (NumProtocolHandles == 0) {\r
2496 return FALSE;\r
2497 }\r
2498\r
2499 //\r
2500 // Get printable name by iterating through all protocols\r
2501 // using the handle as the child, and iterate through all handles for the controller\r
2502 // exit loop early once found, if not found, then delete device\r
2503 // storage security protocol instances already exist, add them to internal list\r
2504 //\r
2505 Status = EFI_DEVICE_ERROR;\r
2506 for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {\r
2507 DevName = NULL;\r
2508\r
2509 if (Dev->Name16 != NULL) {\r
2510 return TRUE;\r
2511 }\r
2512\r
2513 TmpHandle = ProtocolHandlesBuffer[Index1];\r
2514\r
2515 Status = gBS->OpenProtocol(\r
2516 TmpHandle,\r
2517 &Protocol,\r
2518 (VOID**)&Cnp1_2,\r
2519 gImageHandle,\r
2520 NULL,\r
2521 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2522 );\r
2523 if (EFI_ERROR(Status) || Cnp1_2 == NULL) {\r
2524 continue;\r
2525 }\r
2526\r
2527 //\r
2528 // Use all handles array as controller handle\r
2529 //\r
2530 for (Index2 = 0; Index2 < NumAllHandles; Index2++) {\r
2531 Status = Cnp1_2->GetControllerName(\r
2532 Cnp1_2,\r
2533 AllHandlesBuffer[Index2],\r
2534 Dev->Handle,\r
2535 LANGUAGE_ISO_639_2_ENGLISH,\r
2536 &DevName\r
2537 );\r
2538 if (EFI_ERROR(Status)) {\r
2539 Status = Cnp1_2->GetControllerName(\r
2540 Cnp1_2,\r
2541 AllHandlesBuffer[Index2],\r
2542 Dev->Handle,\r
2543 LANGUAGE_RFC_3066_ENGLISH,\r
2544 &DevName\r
2545 );\r
2546 }\r
2547 if (!EFI_ERROR(Status) && DevName != NULL) {\r
2548 StrLength = StrLen(DevName) + 1; // Add one for NULL terminator\r
2549 Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));\r
2550 ASSERT (Dev->Name16 != NULL);\r
2551 StrCpyS (Dev->Name16, StrLength, DevName);\r
2552 Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);\r
2553 UnicodeStrToAsciiStrS (DevName, Dev->NameZ, StrLength);\r
2554\r
2555 //\r
2556 // Retrieve bridge BDF info and port number or namespace depending on type\r
2557 //\r
2558 TmpDevPath = NULL;\r
2559 Status = gBS->OpenProtocol(\r
2560 Dev->Handle,\r
2561 &gEfiDevicePathProtocolGuid,\r
2562 (VOID**)&TmpDevPath,\r
2563 gImageHandle,\r
2564 NULL,\r
2565 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
2566 );\r
2567 if (!EFI_ERROR(Status)) {\r
2568 Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);\r
2569 return TRUE;\r
2570 }\r
2571\r
2572 if (Dev->Name16 != NULL) {\r
2573 FreePool(Dev->Name16);\r
2574 Dev->Name16 = NULL;\r
2575 }\r
2576 if (Dev->NameZ != NULL) {\r
2577 FreePool(Dev->NameZ);\r
2578 Dev->NameZ = NULL;\r
2579 }\r
2580 }\r
2581 }\r
2582 }\r
2583\r
2584 return FALSE;\r
2585}\r
2586\r
2587/**\r
2588 Get devcie name through the component name protocol.\r
2589\r
2590 @param[in] Dev The device which need to get name.\r
2591\r
2592 @retval TRUE Find the name for this device.\r
2593 @retval FALSE Not found the name for this device.\r
2594**/\r
2595BOOLEAN\r
2596OpalDriverGetDriverDeviceName(\r
2597 OPAL_DRIVER_DEVICE *Dev\r
2598 )\r
2599{\r
2600 EFI_HANDLE* AllHandlesBuffer;\r
2601 UINTN NumAllHandles;\r
2602 EFI_STATUS Status;\r
2603\r
2604 if (Dev == NULL) {\r
2605 DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));\r
2606 return FALSE;\r
2607 }\r
2608\r
2609 //\r
2610 // Iterate through ComponentName2 handles to get name, if fails, try ComponentName\r
2611 //\r
2612 if (Dev->Name16 == NULL) {\r
2613 DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));\r
2614 //\r
2615 // Find all EFI_HANDLES\r
2616 //\r
2617 Status = gBS->LocateHandleBuffer(\r
2618 AllHandles,\r
2619 NULL,\r
2620 NULL,\r
2621 &NumAllHandles,\r
2622 &AllHandlesBuffer\r
2623 );\r
2624 if (EFI_ERROR(Status)) {\r
2625 DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));\r
2626 return FALSE;\r
2627 }\r
2628\r
2629 //\r
2630 // Try component Name2\r
2631 //\r
2632 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {\r
2633 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));\r
2634 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {\r
2635 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));\r
2636 return FALSE;\r
2637 }\r
2638 }\r
2639 }\r
2640\r
2641 return TRUE;\r
2642}\r
2643\r
2644/**\r
2645 Main entry for this driver.\r
2646\r
2647 @param ImageHandle Image Handle this driver.\r
2648 @param SystemTable Pointer to SystemTable.\r
2649\r
2650 @retval EFI_SUCESS This function always complete successfully.\r
2651**/\r
2652EFI_STATUS\r
2653EFIAPI\r
2654EfiDriverEntryPoint(\r
2655 IN EFI_HANDLE ImageHandle,\r
2656 IN EFI_SYSTEM_TABLE* SystemTable\r
2657 )\r
2658{\r
2659 EFI_STATUS Status;\r
2660 EFI_EVENT ReadyToBootEvent;\r
2661 EFI_EVENT EndOfDxeEvent;\r
2662\r
2663 Status = EfiLibInstallDriverBindingComponentName2 (\r
2664 ImageHandle,\r
2665 SystemTable,\r
2666 &gOpalDriverBinding,\r
2667 ImageHandle,\r
2668 &gOpalComponentName,\r
2669 &gOpalComponentName2\r
2670 );\r
2671\r
2672 if (EFI_ERROR(Status)) {\r
2673 DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));\r
2674 return Status ;\r
2675 }\r
2676\r
2677 //\r
2678 // Initialize Driver object\r
2679 //\r
2680 ZeroMem(&mOpalDriver, sizeof(mOpalDriver));\r
2681 mOpalDriver.Handle = ImageHandle;\r
2682\r
2683 Status = gBS->CreateEventEx (\r
2684 EVT_NOTIFY_SIGNAL,\r
2685 TPL_CALLBACK,\r
2686 OpalEndOfDxeEventNotify,\r
2687 NULL,\r
2688 &gEfiEndOfDxeEventGroupGuid,\r
2689 &EndOfDxeEvent\r
2690 );\r
2691 ASSERT_EFI_ERROR (Status);\r
2692\r
2693 //\r
2694 // register a ReadyToBoot event callback for sending BlockSid command\r
2695 //\r
2696 Status = EfiCreateEventReadyToBootEx (\r
2697 TPL_CALLBACK,\r
2698 ReadyToBootCallback,\r
2699 (VOID *) &ImageHandle,\r
2700 &ReadyToBootEvent\r
2701 );\r
2702\r
2703 //\r
2704 // Install Hii packages.\r
2705 //\r
2706 HiiInstall();\r
2707\r
2708 return Status;\r
2709}\r
2710\r
2711/**\r
2712 Tests to see if this driver supports a given controller.\r
2713\r
2714 This function checks to see if the controller contains an instance of the\r
2715 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL\r
2716 and returns EFI_SUCCESS if it does.\r
2717\r
2718 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
2719 @param[in] ControllerHandle The Handle of the controller to test. This Handle\r
2720 must support a protocol interface that supplies\r
2721 an I/O abstraction to the driver.\r
2722 @param[in] RemainingDevicePath This parameter is ignored.\r
2723\r
2724 @retval EFI_SUCCESS The device contains required protocols\r
2725 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
2726 RemainingDevicePath is already being managed by the driver\r
2727 specified by This.\r
2728 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
2729 RemainingDevicePath is already being managed by a different\r
2730 driver or an application that requires exclusive access.\r
2731 Currently not implemented.\r
2732 @retval EFI_UNSUPPORTED The device does not contain requires protocols\r
2733\r
2734**/\r
2735EFI_STATUS\r
2736EFIAPI\r
2737OpalEfiDriverBindingSupported(\r
2738 IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
2739 IN EFI_HANDLE Controller,\r
2740 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
2741 )\r
2742{\r
2743 EFI_STATUS Status;\r
2744 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL* SecurityCommand;\r
2745 EFI_BLOCK_IO_PROTOCOL* BlkIo;\r
2746\r
2747 if (mOpalEndOfDxe) {\r
2748 return EFI_UNSUPPORTED;\r
2749 }\r
2750\r
2751 //\r
2752 // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.\r
2753 //\r
2754 Status = gBS->OpenProtocol(\r
2755 Controller,\r
2756 &gEfiStorageSecurityCommandProtocolGuid,\r
2757 ( VOID ** )&SecurityCommand,\r
2758 This->DriverBindingHandle,\r
2759 Controller,\r
2760 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2761 );\r
2762\r
2763 if (Status == EFI_ALREADY_STARTED) {\r
2764 return EFI_SUCCESS;\r
2765 }\r
2766\r
2767 if (EFI_ERROR(Status)) {\r
2768 return Status;\r
2769 }\r
2770\r
2771 //\r
2772 // Close protocol and reopen in Start call\r
2773 //\r
2774 gBS->CloseProtocol(\r
2775 Controller,\r
2776 &gEfiStorageSecurityCommandProtocolGuid,\r
2777 This->DriverBindingHandle,\r
2778 Controller\r
2779 );\r
2780\r
2781 //\r
2782 // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
2783 // function APIs\r
2784 //\r
2785 Status = gBS->OpenProtocol(\r
2786 Controller,\r
2787 &gEfiBlockIoProtocolGuid,\r
2788 (VOID **)&BlkIo,\r
2789 This->DriverBindingHandle,\r
2790 Controller,\r
2791 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2792 );\r
2793\r
2794 if (EFI_ERROR(Status)) {\r
2795 DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));\r
2796 return Status;\r
2797 }\r
2798\r
2799 //\r
2800 // Close protocol and reopen in Start call\r
2801 //\r
2802 gBS->CloseProtocol(\r
2803 Controller,\r
2804 &gEfiBlockIoProtocolGuid,\r
2805 This->DriverBindingHandle,\r
2806 Controller\r
2807 );\r
2808\r
2809 return EFI_SUCCESS;\r
2810}\r
2811\r
2812/**\r
2813 Enables Opal Management on a supported device if available.\r
2814\r
2815 The start function is designed to be called after the Opal UEFI Driver has confirmed the\r
2816 "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.\r
2817 This function will complete the other necessary checks, such as verifying the device supports\r
2818 the correct version of Opal. Upon verification, it will add the device to the\r
2819 Opal HII list in order to expose Opal managmeent options.\r
2820\r
2821 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
2822 @param[in] ControllerHandle The Handle of the controller to start. This Handle\r
2823 must support a protocol interface that supplies\r
2824 an I/O abstraction to the driver.\r
2825 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
2826 parameter is ignored by device drivers, and is optional for bus\r
2827 drivers. For a bus driver, if this parameter is NULL, then handles\r
2828 for all the children of Controller are created by this driver.\r
2829 If this parameter is not NULL and the first Device Path Node is\r
2830 not the End of Device Path Node, then only the Handle for the\r
2831 child device specified by the first Device Path Node of\r
2832 RemainingDevicePath is created by this driver.\r
2833 If the first Device Path Node of RemainingDevicePath is\r
2834 the End of Device Path Node, no child Handle is created by this\r
2835 driver.\r
2836\r
2837 @retval EFI_SUCCESS Opal management was enabled.\r
2838 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
2839 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
2840 @retval Others The driver failed to start the device.\r
2841\r
2842**/\r
2843EFI_STATUS\r
2844EFIAPI\r
2845OpalEfiDriverBindingStart(\r
2846 IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
2847 IN EFI_HANDLE Controller,\r
2848 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
2849 )\r
2850{\r
2851 EFI_STATUS Status;\r
2852 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
2853 OPAL_DRIVER_DEVICE *Dev;\r
2854 OPAL_DRIVER_DEVICE *Itr;\r
2855 BOOLEAN Result;\r
2856\r
2857 Itr = mOpalDriver.DeviceList;\r
2858 while (Itr != NULL) {\r
2859 if (Controller == Itr->Handle) {\r
2860 return EFI_SUCCESS;\r
2861 }\r
2862 Itr = Itr->Next;\r
2863 }\r
2864\r
2865 //\r
2866 // Create internal device for tracking. This allows all disks to be tracked\r
2867 // by same HII form\r
2868 //\r
2869 Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));\r
2870 if (Dev == NULL) {\r
2871 return EFI_OUT_OF_RESOURCES;\r
2872 }\r
2873 Dev->Handle = Controller;\r
2874\r
2875 //\r
2876 // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks\r
2877 //\r
2878 Status = gBS->OpenProtocol(\r
2879 Controller,\r
2880 &gEfiStorageSecurityCommandProtocolGuid,\r
2881 (VOID **)&Dev->Sscp,\r
2882 This->DriverBindingHandle,\r
2883 Controller,\r
2884 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2885 );\r
2886 if (EFI_ERROR(Status)) {\r
2887 FreePool(Dev);\r
2888 return Status;\r
2889 }\r
2890\r
2891 //\r
2892 // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
2893 // function APIs\r
2894 //\r
2895 Status = gBS->OpenProtocol(\r
2896 Controller,\r
2897 &gEfiBlockIoProtocolGuid,\r
2898 (VOID **)&BlkIo,\r
2899 This->DriverBindingHandle,\r
2900 Controller,\r
2901 EFI_OPEN_PROTOCOL_BY_DRIVER\r
2902 );\r
2903 if (EFI_ERROR(Status)) {\r
2904 //\r
2905 // Close storage security that was opened\r
2906 //\r
2907 gBS->CloseProtocol(\r
2908 Controller,\r
2909 &gEfiStorageSecurityCommandProtocolGuid,\r
2910 This->DriverBindingHandle,\r
2911 Controller\r
2912 );\r
2913\r
2914 FreePool(Dev);\r
2915 return Status;\r
2916 }\r
2917\r
2918 //\r
2919 // Save mediaId\r
2920 //\r
2921 Dev->MediaId = BlkIo->Media->MediaId;\r
2922\r
2923 gBS->CloseProtocol(\r
2924 Controller,\r
2925 &gEfiBlockIoProtocolGuid,\r
2926 This->DriverBindingHandle,\r
2927 Controller\r
2928 );\r
2929\r
2930 //\r
2931 // Acquire Ascii printable name of child, if not found, then ignore device\r
2932 //\r
2933 Result = OpalDriverGetDriverDeviceName (Dev);\r
2934 if (!Result) {\r
2935 goto Done;\r
2936 }\r
2937\r
2938 Status = OpalDiskInitialize (Dev);\r
2939 if (EFI_ERROR (Status)) {\r
2940 goto Done;\r
2941 }\r
2942\r
2943 AddDeviceToTail(Dev);\r
2944\r
2945 //\r
2946 // Check if device is locked and prompt for password.\r
2947 //\r
2948 OpalDriverRequestPassword (Dev, L"Unlock:");\r
2949\r
2950 //\r
2951 // Process OPAL request from last boot.\r
2952 //\r
2953 ProcessOpalRequest (Dev);\r
2954\r
2955 return EFI_SUCCESS;\r
2956\r
2957Done:\r
2958 //\r
2959 // free device, close protocols and exit\r
2960 //\r
2961 gBS->CloseProtocol(\r
2962 Controller,\r
2963 &gEfiStorageSecurityCommandProtocolGuid,\r
2964 This->DriverBindingHandle,\r
2965 Controller\r
2966 );\r
2967\r
2968 FreePool(Dev);\r
2969\r
2970 return EFI_DEVICE_ERROR;\r
2971}\r
2972\r
2973/**\r
2974 Stop this driver on Controller.\r
2975\r
2976 @param This Protocol instance pointer.\r
2977 @param Controller Handle of device to stop driver on\r
2978 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
2979 children is zero stop the entire bus driver.\r
2980 @param ChildHandleBuffer List of Child Handles to Stop.\r
2981\r
2982 @retval EFI_SUCCESS This driver is removed Controller.\r
2983 @retval other This driver could not be removed from this device.\r
2984\r
2985**/\r
2986EFI_STATUS\r
2987EFIAPI\r
2988OpalEfiDriverBindingStop(\r
2989 EFI_DRIVER_BINDING_PROTOCOL* This,\r
2990 EFI_HANDLE Controller,\r
2991 UINTN NumberOfChildren,\r
2992 EFI_HANDLE* ChildHandleBuffer\r
2993 )\r
2994{\r
2995 OPAL_DRIVER_DEVICE* Itr;\r
2996\r
2997 Itr = mOpalDriver.DeviceList;\r
2998\r
2999 //\r
3000 // does Controller match any of the devices we are managing for Opal\r
3001 //\r
3002 while (Itr != NULL) {\r
3003 if (Itr->Handle == Controller) {\r
3004 OpalDriverStopDevice (Itr);\r
3005 return EFI_SUCCESS;\r
3006 }\r
3007\r
3008 Itr = Itr->Next;\r
3009 }\r
3010\r
3011 return EFI_NOT_FOUND;\r
3012}\r
3013\r
3014\r
3015/**\r
3016 Unloads UEFI Driver. Very useful for debugging and testing.\r
3017\r
3018 @param ImageHandle Image Handle this driver.\r
3019\r
3020 @retval EFI_SUCCESS This function always complete successfully.\r
3021 @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.\r
3022**/\r
3023EFI_STATUS\r
3024EFIAPI\r
3025OpalEfiDriverUnload (\r
3026 IN EFI_HANDLE ImageHandle\r
3027 )\r
3028{\r
3029 EFI_STATUS Status;\r
3030 OPAL_DRIVER_DEVICE *Itr;\r
3031\r
3032 Status = EFI_SUCCESS;\r
3033\r
3034 if (ImageHandle != gImageHandle) {\r
3035 return (EFI_INVALID_PARAMETER);\r
3036 }\r
3037\r
3038 //\r
3039 // Uninstall any interface added to each device by us\r
3040 //\r
3041 while (mOpalDriver.DeviceList) {\r
3042 Itr = mOpalDriver.DeviceList;\r
3043 //\r
3044 // Remove OPAL_DRIVER_DEVICE from the list\r
3045 // it updates the controllerList pointer\r
3046 //\r
3047 OpalDriverStopDevice(Itr);\r
3048 }\r
3049\r
3050 //\r
3051 // Uninstall the HII capability\r
3052 //\r
3053 Status = HiiUninstall();\r
3054\r
3055 return Status;\r
3056}\r
3057\r