]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
MdeModulePkg/UsbMouseAbsolutePointerDxe: fix VS2015 NOOPT build error
[mirror_edk2.git] / SecurityPkg / Tcg / Opal / OpalPasswordDxe / OpalDriver.c
CommitLineData
a06875e1
ED
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, 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 "OpalDriverPrivate.h"\r
23#include "OpalHii.h"\r
24\r
25OPAL_DRIVER mOpalDriver;\r
26\r
a06875e1
ED
27#define MAX_PASSWORD_SIZE 32\r
28#define MAX_PASSWORD_TRY_COUNT 5\r
29\r
30//\r
31// Globals\r
32//\r
33EFI_DRIVER_BINDING_PROTOCOL gOpalDriverBinding = {\r
34 OpalEfiDriverBindingSupported,\r
35 OpalEfiDriverBindingStart,\r
36 OpalEfiDriverBindingStop,\r
37 0x1b,\r
38 NULL,\r
39 NULL\r
40};\r
41\r
42\r
43/**\r
44 Add new device to the global device list.\r
45\r
46 @param Dev New create device.\r
47\r
48**/\r
49VOID\r
50AddDeviceToTail(\r
51 IN OPAL_DRIVER_DEVICE *Dev\r
52 )\r
53{\r
54 OPAL_DRIVER_DEVICE *TmpDev;\r
55\r
56 if (mOpalDriver.DeviceList == NULL) {\r
57 mOpalDriver.DeviceList = Dev;\r
58 } else {\r
59 TmpDev = mOpalDriver.DeviceList;\r
60 while (TmpDev->Next != NULL) {\r
61 TmpDev = TmpDev->Next;\r
62 }\r
63\r
64 TmpDev->Next = Dev;\r
65 }\r
66}\r
67\r
68/**\r
69 Remove one device in the global device list.\r
70\r
71 @param Dev The device need to be removed.\r
72\r
73**/\r
74VOID\r
75RemoveDevice (\r
76 IN OPAL_DRIVER_DEVICE *Dev\r
77 )\r
78{\r
79 OPAL_DRIVER_DEVICE *TmpDev;\r
80\r
81 if (mOpalDriver.DeviceList == NULL) {\r
82 return;\r
83 }\r
84\r
85 if (mOpalDriver.DeviceList == Dev) {\r
86 mOpalDriver.DeviceList = NULL;\r
87 return;\r
88 }\r
89\r
90 TmpDev = mOpalDriver.DeviceList;\r
91 while (TmpDev->Next != NULL) {\r
92 if (TmpDev->Next == Dev) {\r
93 TmpDev->Next = Dev->Next;\r
94 break;\r
95 }\r
96 }\r
97}\r
98\r
99/**\r
100 Get current device count.\r
101\r
102 @retval return the current created device count.\r
103\r
104**/\r
105UINT8\r
106GetDeviceCount (\r
107 VOID\r
108 )\r
109{\r
110 UINT8 Count;\r
111 OPAL_DRIVER_DEVICE *TmpDev;\r
112\r
113 Count = 0;\r
114 TmpDev = mOpalDriver.DeviceList;\r
115\r
116 while (TmpDev != NULL) {\r
117 Count++;\r
118 TmpDev = TmpDev->Next;\r
119 }\r
120\r
121 return Count;\r
122}\r
123\r
124/**\r
125 Get password input from the popup windows, and unlock the device.\r
126\r
127 @param[in] Dev The device which need to be unlock.\r
128 @param[out] PressEsc Whether user escape function through Press ESC.\r
129\r
130 @retval Password string if success. NULL if failed.\r
131\r
132**/\r
133CHAR8 *\r
134OpalDriverPopUpHddPassword (\r
135 IN OPAL_DRIVER_DEVICE *Dev,\r
136 OUT BOOLEAN *PressEsc\r
137 )\r
138{\r
139 EFI_INPUT_KEY InputKey;\r
140 UINTN InputLength;\r
141 CHAR16 Mask[MAX_PASSWORD_SIZE + 1];\r
142 CHAR16 Unicode[MAX_PASSWORD_SIZE + 1];\r
143 CHAR8 *Ascii;\r
144 CHAR16 *PopUpString;\r
145 UINTN StrLength;\r
146\r
147 ZeroMem(Unicode, sizeof(Unicode));\r
148 ZeroMem(Mask, sizeof(Mask));\r
149\r
150 StrLength = StrLen(Dev->Name16);\r
151 PopUpString = (CHAR16*) AllocateZeroPool ((8 + StrLength) * 2);\r
152 *PressEsc = FALSE;\r
153\r
154 if (Dev->Name16 == NULL) {\r
155 UnicodeSPrint(PopUpString, StrLen(L"Unlock Disk") + 1, L"Unlock Disk");\r
156 } else {\r
157 UnicodeSPrint(PopUpString, StrLen(L"Unlock ") + StrLength + 1, L"Unlock %s", Dev->Name16);\r
158 }\r
159\r
160 gST->ConOut->ClearScreen(gST->ConOut);\r
161\r
162 InputLength = 0;\r
163 while (TRUE) {\r
164 Mask[InputLength] = L'_';\r
165 CreatePopUp(\r
166 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
167 &InputKey,\r
168 PopUpString,\r
169 L"---------------------",\r
170 Mask,\r
171 NULL\r
172 );\r
173\r
174 //\r
175 // Check key.\r
176 //\r
177 if (InputKey.ScanCode == SCAN_NULL) {\r
178 //\r
179 // password finished\r
180 //\r
181 if (InputKey.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
182 //\r
183 // Add the null terminator.\r
184 //\r
185 Unicode[InputLength] = 0;\r
186 InputLength++;\r
187 break;\r
188 } else if ((InputKey.UnicodeChar == CHAR_NULL) ||\r
189 (InputKey.UnicodeChar == CHAR_TAB) ||\r
190 (InputKey.UnicodeChar == CHAR_LINEFEED)\r
191 ) {\r
192 continue;\r
193 } else {\r
194 //\r
195 // delete last key entered\r
196 //\r
197 if (InputKey.UnicodeChar == CHAR_BACKSPACE) {\r
198 if (InputLength > 0) {\r
199 Unicode[InputLength] = 0;\r
200 Mask[InputLength] = 0;\r
201 InputLength--;\r
202 }\r
203 } else {\r
204 //\r
205 // add Next key entry\r
206 //\r
207 Unicode[InputLength] = InputKey.UnicodeChar;\r
208 Mask[InputLength] = L'*';\r
209 InputLength++;\r
210 if (InputLength == MAX_PASSWORD_SIZE) {\r
211 //\r
212 // Add the null terminator.\r
213 //\r
214 Unicode[InputLength] = 0;\r
215 Mask[InputLength] = 0;\r
216 break;\r
217 }\r
218 }\r
219 }\r
220 }\r
221\r
222 //\r
223 // exit on ESC\r
224 //\r
225 if (InputKey.ScanCode == SCAN_ESC) {\r
226 *PressEsc = TRUE;\r
227 break;\r
228 }\r
229 }\r
230\r
231 gST->ConOut->ClearScreen(gST->ConOut);\r
232\r
233 if (InputLength == 0 || InputKey.ScanCode == SCAN_ESC) {\r
234 return NULL;\r
235 }\r
236\r
237 Ascii = AllocateZeroPool (MAX_PASSWORD_SIZE + 1);\r
238 if (Ascii == NULL) {\r
239 return NULL;\r
240 }\r
241\r
242 UnicodeStrToAsciiStr(Unicode, Ascii);\r
243\r
244 return Ascii;\r
245}\r
246\r
247/**\r
248 Check if disk is locked, show popup window and ask for password if it is\r
249\r
250 @param[in] Dev The device which need to be unlock.\r
251\r
252**/\r
253VOID\r
254OpalDriverRequestPassword (\r
255 OPAL_DRIVER_DEVICE *Dev\r
256 )\r
257{\r
258 UINT8 Count;\r
259 BOOLEAN IsEnabled;\r
260 CHAR8 *Password;\r
261 UINT32 PasswordLen;\r
262 TCG_RESULT Ret;\r
263 EFI_INPUT_KEY Key;\r
264 OPAL_SESSION Session;\r
265 BOOLEAN PressEsc;\r
266\r
267 if (Dev == NULL) {\r
268 return;\r
269 }\r
270\r
271 Count = 0;\r
272\r
273 IsEnabled = OpalFeatureEnabled (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature);\r
274 if (IsEnabled) {\r
275 ZeroMem(&Session, sizeof(Session));\r
276 Session.Sscp = Dev->OpalDisk.Sscp;\r
277 Session.MediaId = Dev->OpalDisk.MediaId;\r
278 Session.OpalBaseComId = Dev->OpalDisk.OpalBaseComId;\r
279\r
280 while (Count < MAX_PASSWORD_TRY_COUNT) {\r
281 Password = OpalDriverPopUpHddPassword (Dev, &PressEsc);\r
282 if (PressEsc) {\r
283 //\r
284 // User not input password and press ESC, keep device in lock status and continue boot.\r
285 //\r
286 do {\r
287 CreatePopUp (\r
288 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
289 &Key,\r
290 L"Confirm: Not unlock device and continue boot?.",\r
291 L"Press ENTER to confirm, Press Esc to input password",\r
292 NULL\r
293 );\r
294 } while ((Key.ScanCode != SCAN_ESC) && (Key.UnicodeChar != CHAR_CARRIAGE_RETURN));\r
295\r
296 if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {\r
297 gST->ConOut->ClearScreen(gST->ConOut);\r
298 //\r
299 // Keep lock and continue boot.\r
300 //\r
301 return;\r
302 } else {\r
303 //\r
304 // Let user input password again.\r
305 //\r
306 continue;\r
307 }\r
308 }\r
309\r
310 if (Password == NULL) {\r
311 Count ++;\r
312 continue;\r
313 }\r
314 PasswordLen = (UINT32) AsciiStrLen(Password);\r
315\r
316 if (OpalDeviceLocked (&Dev->OpalDisk.SupportedAttributes, &Dev->OpalDisk.LockingFeature)) {\r
317 Ret = OpalSupportUnlock(&Session, Password, PasswordLen, Dev->OpalDevicePath);\r
318 } else {\r
319 Ret = OpalSupportLock(&Session, Password, PasswordLen, Dev->OpalDevicePath);\r
320 if (Ret == TcgResultSuccess) {\r
321 Ret = OpalSupportUnlock(&Session, Password, PasswordLen, Dev->OpalDevicePath);\r
322 }\r
323 }\r
324\r
325 if (Password != NULL) {\r
326 ZeroMem (Password, PasswordLen);\r
327 FreePool (Password);\r
328 }\r
329\r
330 if (Ret == TcgResultSuccess) {\r
331 break;\r
332 }\r
333\r
334 Count++;\r
335\r
336 do {\r
337 CreatePopUp (\r
338 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
339 &Key,\r
340 L"Invalid password.",\r
341 L"Press ENTER to retry",\r
342 NULL\r
343 );\r
344 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
345 }\r
346\r
347 if (Count >= MAX_PASSWORD_TRY_COUNT) {\r
348 do {\r
349 CreatePopUp (\r
350 EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,\r
351 &Key,\r
352 L"Opal password retry count is expired. Keep lock and continue boot.",\r
353 L"Press ENTER to continue",\r
354 NULL\r
355 );\r
356 } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN);\r
357 gST->ConOut->ClearScreen(gST->ConOut);\r
358 }\r
359 }\r
360}\r
361\r
362/**\r
363 Get devcie list info.\r
364\r
365 @retval return the device list pointer.\r
366**/\r
367OPAL_DRIVER_DEVICE*\r
368OpalDriverGetDeviceList(\r
369 VOID\r
370 )\r
371{\r
372 return mOpalDriver.DeviceList;\r
373}\r
374\r
375/**\r
376 ReadyToBoot callback to send BlockSid command.\r
377\r
378 @param Event Pointer to this event\r
379 @param Context Event hanlder private Data\r
380\r
381**/\r
382VOID\r
383EFIAPI\r
384ReadyToBootCallback (\r
385 IN EFI_EVENT Event,\r
386 IN VOID *Context\r
387 )\r
388{\r
389 EFI_STATUS Status;\r
390 OPAL_DRIVER_DEVICE* Itr;\r
a06875e1
ED
391 TCG_RESULT Result;\r
392 OPAL_EXTRA_INFO_VAR OpalExtraInfo;\r
393 UINTN DataSize;\r
394 OPAL_SESSION Session;\r
395\r
a06875e1
ED
396 gBS->CloseEvent (Event);\r
397\r
398 DataSize = sizeof (OPAL_EXTRA_INFO_VAR);\r
399 Status = gRT->GetVariable (\r
400 OPAL_EXTRA_INFO_VAR_NAME,\r
401 &gOpalExtraInfoVariableGuid,\r
402 NULL,\r
403 &DataSize,\r
404 &OpalExtraInfo\r
405 );\r
406 if (EFI_ERROR (Status)) {\r
407 return;\r
408 }\r
409\r
410 if (OpalExtraInfo.EnableBlockSid == TRUE) {\r
411 //\r
412 // Send BlockSID command to each Opal disk\r
413 //\r
414 Itr = mOpalDriver.DeviceList;\r
a06875e1 415 while (Itr != NULL) {\r
be087553
ED
416 if (Itr->OpalDisk.SupportedAttributes.BlockSid) {\r
417 ZeroMem(&Session, sizeof(Session));\r
418 Session.Sscp = Itr->OpalDisk.Sscp;\r
419 Session.MediaId = Itr->OpalDisk.MediaId;\r
420 Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;\r
421\r
422 Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE\r
423 if (Result != TcgResultSuccess) {\r
424 DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));\r
425 break;\r
426 }\r
a06875e1
ED
427 }\r
428\r
429 Itr = Itr->Next;\r
a06875e1
ED
430 }\r
431 }\r
432}\r
433\r
434/**\r
435 Stop this Controller.\r
436\r
437 @param Dev The device need to be stopped.\r
438\r
439**/\r
440VOID\r
441OpalDriverStopDevice (\r
442 OPAL_DRIVER_DEVICE *Dev\r
443 )\r
444{\r
445 //\r
446 // free each name\r
447 //\r
448 FreePool(Dev->Name16);\r
449\r
450 //\r
451 // remove OPAL_DRIVER_DEVICE from the list\r
452 // it updates the controllerList pointer\r
453 //\r
454 RemoveDevice(Dev);\r
455\r
456 //\r
457 // close protocols that were opened\r
458 //\r
459 gBS->CloseProtocol(\r
460 Dev->Handle,\r
461 &gEfiStorageSecurityCommandProtocolGuid,\r
462 gOpalDriverBinding.DriverBindingHandle,\r
463 Dev->Handle\r
464 );\r
465\r
466 gBS->CloseProtocol(\r
467 Dev->Handle,\r
468 &gEfiBlockIoProtocolGuid,\r
469 gOpalDriverBinding.DriverBindingHandle,\r
470 Dev->Handle\r
471 );\r
472\r
473 FreePool(Dev);\r
474}\r
475\r
476/**\r
477 Get devcie name through the component name protocol.\r
478\r
479 @param[in] AllHandlesBuffer The handle buffer for current system.\r
480 @param[in] NumAllHandles The number of handles for the handle buffer.\r
481 @param[in] Dev The device which need to get name.\r
482 @param[in] UseComp1 Whether use component name or name2 protocol.\r
483\r
484 @retval TRUE Find the name for this device.\r
485 @retval FALSE Not found the name for this device.\r
486**/\r
487BOOLEAN\r
488OpalDriverGetDeviceNameByProtocol(\r
489 EFI_HANDLE *AllHandlesBuffer,\r
490 UINTN NumAllHandles,\r
491 OPAL_DRIVER_DEVICE *Dev,\r
492 BOOLEAN UseComp1\r
493 )\r
494{\r
495 EFI_HANDLE* ProtocolHandlesBuffer;\r
496 UINTN NumProtocolHandles;\r
497 EFI_STATUS Status;\r
498 EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout\r
499 EFI_GUID Protocol;\r
500 UINTN StrLength;\r
501 EFI_DEVICE_PATH_PROTOCOL* TmpDevPath;\r
502 UINTN Index1;\r
503 UINTN Index2;\r
504 EFI_HANDLE TmpHandle;\r
505 CHAR16 *DevName;\r
506\r
507 if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {\r
508 return FALSE;\r
509 }\r
510\r
511 Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;\r
512\r
513 //\r
514 // Find all EFI_HANDLES with protocol\r
515 //\r
516 Status = gBS->LocateHandleBuffer(\r
517 ByProtocol,\r
518 &Protocol,\r
519 NULL,\r
520 &NumProtocolHandles,\r
521 &ProtocolHandlesBuffer\r
522 );\r
523 if (EFI_ERROR(Status)) {\r
524 return FALSE;\r
525 }\r
526\r
527\r
528 //\r
529 // Exit early if no supported devices\r
530 //\r
531 if (NumProtocolHandles == 0) {\r
532 return FALSE;\r
533 }\r
534\r
535 //\r
536 // Get printable name by iterating through all protocols\r
537 // using the handle as the child, and iterate through all handles for the controller\r
538 // exit loop early once found, if not found, then delete device\r
539 // storage security protocol instances already exist, add them to internal list\r
540 //\r
541 Status = EFI_DEVICE_ERROR;\r
542 for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {\r
543 DevName = NULL;\r
544\r
545 if (Dev->Name16 != NULL) {\r
546 return TRUE;\r
547 }\r
548\r
549 TmpHandle = ProtocolHandlesBuffer[Index1];\r
550\r
551 Status = gBS->OpenProtocol(\r
552 TmpHandle,\r
553 &Protocol,\r
554 (VOID**)&Cnp1_2,\r
555 gImageHandle,\r
556 NULL,\r
557 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
558 );\r
559 if (EFI_ERROR(Status) || Cnp1_2 == NULL) {\r
560 continue;\r
561 }\r
562\r
563 //\r
564 // Use all handles array as controller handle\r
565 //\r
566 for (Index2 = 0; Index2 < NumAllHandles; Index2++) {\r
567 Status = Cnp1_2->GetControllerName(\r
568 Cnp1_2,\r
569 AllHandlesBuffer[Index2],\r
570 Dev->Handle,\r
571 LANGUAGE_ISO_639_2_ENGLISH,\r
572 &DevName\r
573 );\r
574 if (EFI_ERROR(Status)) {\r
575 Status = Cnp1_2->GetControllerName(\r
576 Cnp1_2,\r
577 AllHandlesBuffer[Index2],\r
578 Dev->Handle,\r
579 LANGUAGE_RFC_3066_ENGLISH,\r
580 &DevName\r
581 );\r
582 }\r
583 if (!EFI_ERROR(Status) && DevName != NULL) {\r
584 StrLength = StrLen(DevName) + 1; // Add one for NULL terminator\r
585 Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));\r
586 ASSERT (Dev->Name16 != NULL);\r
587 StrCpyS (Dev->Name16, StrLength, DevName);\r
588 Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);\r
589 UnicodeStrToAsciiStr(DevName, Dev->NameZ);\r
590\r
591 //\r
592 // Retrieve bridge BDF info and port number or namespace depending on type\r
593 //\r
594 TmpDevPath = NULL;\r
595 Status = gBS->OpenProtocol(\r
596 Dev->Handle,\r
597 &gEfiDevicePathProtocolGuid,\r
598 (VOID**)&TmpDevPath,\r
599 gImageHandle,\r
600 NULL,\r
601 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
602 );\r
603 if (!EFI_ERROR(Status)) {\r
604 Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);\r
605 return TRUE;\r
606 }\r
607\r
608 if (Dev->Name16 != NULL) {\r
609 FreePool(Dev->Name16);\r
610 Dev->Name16 = NULL;\r
611 }\r
612 if (Dev->NameZ != NULL) {\r
613 FreePool(Dev->NameZ);\r
614 Dev->NameZ = NULL;\r
615 }\r
616 }\r
617 }\r
618 }\r
619\r
620 return FALSE;\r
621}\r
622\r
623/**\r
624 Get devcie name through the component name protocol.\r
625\r
626 @param[in] Dev The device which need to get name.\r
627\r
628 @retval TRUE Find the name for this device.\r
629 @retval FALSE Not found the name for this device.\r
630**/\r
631BOOLEAN\r
632OpalDriverGetDriverDeviceName(\r
633 OPAL_DRIVER_DEVICE *Dev\r
634 )\r
635{\r
636 EFI_HANDLE* AllHandlesBuffer;\r
637 UINTN NumAllHandles;\r
638 EFI_STATUS Status;\r
639\r
640 if (Dev == NULL) {\r
641 DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));\r
642 return FALSE;\r
643 }\r
644\r
645 //\r
646 // Iterate through ComponentName2 handles to get name, if fails, try ComponentName\r
647 //\r
648 if (Dev->Name16 == NULL) {\r
649 DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));\r
650 //\r
651 // Find all EFI_HANDLES\r
652 //\r
653 Status = gBS->LocateHandleBuffer(\r
654 AllHandles,\r
655 NULL,\r
656 NULL,\r
657 &NumAllHandles,\r
658 &AllHandlesBuffer\r
659 );\r
660 if (EFI_ERROR(Status)) {\r
661 DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));\r
662 return FALSE;\r
663 }\r
664\r
665 //\r
666 // Try component Name2\r
667 //\r
668 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {\r
669 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));\r
670 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {\r
671 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));\r
672 return FALSE;\r
673 }\r
674 }\r
675 }\r
676\r
677 return TRUE;\r
678}\r
679\r
680/**\r
681 Main entry for this driver.\r
682\r
683 @param ImageHandle Image Handle this driver.\r
684 @param SystemTable Pointer to SystemTable.\r
685\r
686 @retval EFI_SUCESS This function always complete successfully.\r
687**/\r
688EFI_STATUS\r
689EFIAPI\r
690EfiDriverEntryPoint(\r
691 IN EFI_HANDLE ImageHandle,\r
692 IN EFI_SYSTEM_TABLE* SystemTable\r
693 )\r
694{\r
695 EFI_STATUS Status;\r
696 EFI_EVENT ReadyToBootEvent;\r
697\r
698 Status = EfiLibInstallDriverBindingComponentName2 (\r
699 ImageHandle,\r
700 SystemTable,\r
701 &gOpalDriverBinding,\r
702 ImageHandle,\r
703 &gOpalComponentName,\r
704 &gOpalComponentName2\r
705 );\r
706\r
707 if (EFI_ERROR(Status)) {\r
708 DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));\r
709 return Status ;\r
710 }\r
711\r
712 //\r
713 // Initialize Driver object\r
714 //\r
715 ZeroMem(&mOpalDriver, sizeof(mOpalDriver));\r
716 mOpalDriver.Handle = ImageHandle;\r
717\r
718 //\r
719 // register a ReadyToBoot event callback for sending BlockSid command\r
720 //\r
721 Status = EfiCreateEventReadyToBootEx (\r
722 TPL_CALLBACK,\r
723 ReadyToBootCallback,\r
724 (VOID *) &ImageHandle,\r
725 &ReadyToBootEvent\r
726 );\r
727\r
f1430748
ED
728 //\r
729 // Install Hii packages.\r
730 //\r
731 HiiInstall();\r
732\r
a06875e1
ED
733 return Status;\r
734}\r
735\r
736/**\r
737 Tests to see if this driver supports a given controller.\r
738\r
739 This function checks to see if the controller contains an instance of the\r
740 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL\r
741 and returns EFI_SUCCESS if it does.\r
742\r
743 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
744 @param[in] ControllerHandle The Handle of the controller to test. This Handle\r
745 must support a protocol interface that supplies\r
746 an I/O abstraction to the driver.\r
747 @param[in] RemainingDevicePath This parameter is ignored.\r
748\r
749 @retval EFI_SUCCESS The device contains required protocols\r
750 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
751 RemainingDevicePath is already being managed by the driver\r
752 specified by This.\r
753 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
754 RemainingDevicePath is already being managed by a different\r
755 driver or an application that requires exclusive access.\r
756 Currently not implemented.\r
757 @retval EFI_UNSUPPORTED The device does not contain requires protocols\r
758\r
759**/\r
760EFI_STATUS\r
761EFIAPI\r
762OpalEfiDriverBindingSupported(\r
763 IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
764 IN EFI_HANDLE Controller,\r
765 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
766 )\r
767{\r
768 EFI_STATUS Status;\r
769 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL* SecurityCommand;\r
770 EFI_BLOCK_IO_PROTOCOL* BlkIo;\r
771\r
772 //\r
773 // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.\r
774 //\r
775 Status = gBS->OpenProtocol(\r
776 Controller,\r
777 &gEfiStorageSecurityCommandProtocolGuid,\r
778 ( VOID ** )&SecurityCommand,\r
779 This->DriverBindingHandle,\r
780 Controller,\r
781 EFI_OPEN_PROTOCOL_BY_DRIVER\r
782 );\r
783\r
784 if (Status == EFI_ALREADY_STARTED) {\r
785 return EFI_SUCCESS;\r
786 }\r
787\r
788 if (EFI_ERROR(Status)) {\r
789 return Status;\r
790 }\r
791\r
792 //\r
793 // Close protocol and reopen in Start call\r
794 //\r
795 gBS->CloseProtocol(\r
796 Controller,\r
797 &gEfiStorageSecurityCommandProtocolGuid,\r
798 This->DriverBindingHandle,\r
799 Controller\r
800 );\r
801\r
802 //\r
803 // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
804 // function APIs\r
805 //\r
806 Status = gBS->OpenProtocol(\r
807 Controller,\r
808 &gEfiBlockIoProtocolGuid,\r
809 (VOID **)&BlkIo,\r
810 This->DriverBindingHandle,\r
811 Controller,\r
812 EFI_OPEN_PROTOCOL_BY_DRIVER\r
813 );\r
814\r
815 if (EFI_ERROR(Status)) {\r
816 DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));\r
817 return Status;\r
818 }\r
819\r
820 //\r
821 // Close protocol and reopen in Start call\r
822 //\r
823 gBS->CloseProtocol(\r
824 Controller,\r
825 &gEfiBlockIoProtocolGuid,\r
826 This->DriverBindingHandle,\r
827 Controller\r
828 );\r
829\r
830 return EFI_SUCCESS;\r
831}\r
832\r
833/**\r
834 Enables Opal Management on a supported device if available.\r
835\r
836 The start function is designed to be called after the Opal UEFI Driver has confirmed the\r
837 "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.\r
838 This function will complete the other necessary checks, such as verifying the device supports\r
839 the correct version of Opal. Upon verification, it will add the device to the\r
840 Opal HII list in order to expose Opal managmeent options.\r
841\r
842 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
843 @param[in] ControllerHandle The Handle of the controller to start. This Handle\r
844 must support a protocol interface that supplies\r
845 an I/O abstraction to the driver.\r
846 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
847 parameter is ignored by device drivers, and is optional for bus\r
848 drivers. For a bus driver, if this parameter is NULL, then handles\r
849 for all the children of Controller are created by this driver.\r
850 If this parameter is not NULL and the first Device Path Node is\r
851 not the End of Device Path Node, then only the Handle for the\r
852 child device specified by the first Device Path Node of\r
853 RemainingDevicePath is created by this driver.\r
854 If the first Device Path Node of RemainingDevicePath is\r
855 the End of Device Path Node, no child Handle is created by this\r
856 driver.\r
857\r
858 @retval EFI_SUCCESS Opal management was enabled.\r
859 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
860 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
861 @retval Others The driver failed to start the device.\r
862\r
863**/\r
864EFI_STATUS\r
865EFIAPI\r
866OpalEfiDriverBindingStart(\r
867 IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
868 IN EFI_HANDLE Controller,\r
869 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
870 )\r
871{\r
872 EFI_STATUS Status;\r
873 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
874 OPAL_DRIVER_DEVICE *Dev;\r
875 OPAL_DRIVER_DEVICE *Itr;\r
876 BOOLEAN Result;\r
877\r
878 Itr = mOpalDriver.DeviceList;\r
879 while (Itr != NULL) {\r
880 if (Controller == Itr->Handle) {\r
881 return EFI_SUCCESS;\r
882 }\r
883 Itr = Itr->Next;\r
884 }\r
885\r
886 //\r
887 // Create internal device for tracking. This allows all disks to be tracked\r
888 // by same HII form\r
889 //\r
890 Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));\r
891 if (Dev == NULL) {\r
892 return EFI_OUT_OF_RESOURCES;\r
893 }\r
894 Dev->Handle = Controller;\r
895\r
896 //\r
897 // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks\r
898 //\r
899 Status = gBS->OpenProtocol(\r
900 Controller,\r
901 &gEfiStorageSecurityCommandProtocolGuid,\r
902 (VOID **)&Dev->Sscp,\r
903 This->DriverBindingHandle,\r
904 Controller,\r
905 EFI_OPEN_PROTOCOL_BY_DRIVER\r
906 );\r
907 if (EFI_ERROR(Status)) {\r
908 FreePool(Dev);\r
909 return Status;\r
910 }\r
911\r
912 //\r
913 // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
914 // function APIs\r
915 //\r
916 Status = gBS->OpenProtocol(\r
917 Controller,\r
918 &gEfiBlockIoProtocolGuid,\r
919 (VOID **)&BlkIo,\r
920 This->DriverBindingHandle,\r
921 Controller,\r
922 EFI_OPEN_PROTOCOL_BY_DRIVER\r
923 );\r
924 if (EFI_ERROR(Status)) {\r
925 //\r
926 // Close storage security that was opened\r
927 //\r
928 gBS->CloseProtocol(\r
929 Controller,\r
930 &gEfiStorageSecurityCommandProtocolGuid,\r
931 This->DriverBindingHandle,\r
932 Controller\r
933 );\r
934\r
935 FreePool(Dev);\r
936 return Status;\r
937 }\r
938\r
939 //\r
940 // Save mediaId\r
941 //\r
942 Dev->MediaId = BlkIo->Media->MediaId;\r
943\r
944 gBS->CloseProtocol(\r
945 Controller,\r
946 &gEfiBlockIoProtocolGuid,\r
947 This->DriverBindingHandle,\r
948 Controller\r
949 );\r
950\r
951 //\r
952 // Acquire Ascii printable name of child, if not found, then ignore device\r
953 //\r
954 Result = OpalDriverGetDriverDeviceName (Dev);\r
955 if (!Result) {\r
956 goto Done;\r
957 }\r
958\r
959 Status = OpalDiskInitialize (Dev);\r
960 if (EFI_ERROR (Status)) {\r
961 goto Done;\r
962 }\r
963\r
964 AddDeviceToTail(Dev);\r
965\r
a06875e1
ED
966 //\r
967 // check if device is locked and prompt for password\r
968 //\r
969 OpalDriverRequestPassword (Dev);\r
970\r
971 return EFI_SUCCESS;\r
972\r
973Done:\r
974 //\r
975 // free device, close protocols and exit\r
976 //\r
977 gBS->CloseProtocol(\r
978 Controller,\r
979 &gEfiStorageSecurityCommandProtocolGuid,\r
980 This->DriverBindingHandle,\r
981 Controller\r
982 );\r
983\r
984 FreePool(Dev);\r
985\r
986 return EFI_DEVICE_ERROR;\r
987}\r
988\r
989/**\r
990 Stop this driver on Controller.\r
991\r
992 @param This Protocol instance pointer.\r
993 @param Controller Handle of device to stop driver on\r
994 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
995 children is zero stop the entire bus driver.\r
996 @param ChildHandleBuffer List of Child Handles to Stop.\r
997\r
998 @retval EFI_SUCCESS This driver is removed Controller.\r
999 @retval other This driver could not be removed from this device.\r
1000\r
1001**/\r
1002EFI_STATUS\r
1003EFIAPI\r
1004OpalEfiDriverBindingStop(\r
1005 EFI_DRIVER_BINDING_PROTOCOL* This,\r
1006 EFI_HANDLE Controller,\r
1007 UINTN NumberOfChildren,\r
1008 EFI_HANDLE* ChildHandleBuffer\r
1009 )\r
1010{\r
1011 OPAL_DRIVER_DEVICE* Itr;\r
1012\r
1013 Itr = mOpalDriver.DeviceList;\r
1014\r
1015 //\r
1016 // does Controller match any of the devices we are managing for Opal\r
1017 //\r
1018 while (Itr != NULL) {\r
1019 if (Itr->Handle == Controller) {\r
1020 OpalDriverStopDevice (Itr);\r
1021 return EFI_SUCCESS;\r
1022 }\r
1023\r
1024 Itr = Itr->Next;\r
1025 }\r
1026\r
1027 return EFI_NOT_FOUND;\r
1028}\r
1029\r
1030\r
1031/**\r
1032 Unloads UEFI Driver. Very useful for debugging and testing.\r
1033\r
1034 @param ImageHandle Image Handle this driver.\r
1035\r
1036 @retval EFI_SUCCESS This function always complete successfully.\r
1037 @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.\r
1038**/\r
1039EFI_STATUS\r
1040EFIAPI\r
1041OpalEfiDriverUnload (\r
1042 IN EFI_HANDLE ImageHandle\r
1043 )\r
1044{\r
1045 EFI_STATUS Status;\r
1046 OPAL_DRIVER_DEVICE *Itr;\r
1047\r
1048 Status = EFI_SUCCESS;\r
1049\r
1050 if (ImageHandle != gImageHandle) {\r
1051 return (EFI_INVALID_PARAMETER);\r
1052 }\r
1053\r
1054 //\r
1055 // Uninstall any interface added to each device by us\r
1056 //\r
1057 while (mOpalDriver.DeviceList) {\r
1058 Itr = mOpalDriver.DeviceList;\r
1059 //\r
1060 // Remove OPAL_DRIVER_DEVICE from the list\r
1061 // it updates the controllerList pointer\r
1062 //\r
1063 OpalDriverStopDevice(Itr);\r
1064 }\r
1065\r
1066 //\r
1067 // Uninstall the HII capability\r
1068 //\r
1069 Status = HiiUninstall();\r
1070\r
1071 return Status;\r
1072}\r
1073\r