]> git.proxmox.com Git - mirror_edk2.git/blame - SecurityPkg/Tcg/Opal/OpalPasswordDxe/OpalDriver.c
SecurityPkg OpalPasswordDxe: Change BlockSid position.
[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
391 UINT8 Count;\r
392 TCG_RESULT Result;\r
393 OPAL_EXTRA_INFO_VAR OpalExtraInfo;\r
394 UINTN DataSize;\r
395 OPAL_SESSION Session;\r
396\r
397 Count = 0;\r
398\r
399 gBS->CloseEvent (Event);\r
400\r
401 DataSize = sizeof (OPAL_EXTRA_INFO_VAR);\r
402 Status = gRT->GetVariable (\r
403 OPAL_EXTRA_INFO_VAR_NAME,\r
404 &gOpalExtraInfoVariableGuid,\r
405 NULL,\r
406 &DataSize,\r
407 &OpalExtraInfo\r
408 );\r
409 if (EFI_ERROR (Status)) {\r
410 return;\r
411 }\r
412\r
413 if (OpalExtraInfo.EnableBlockSid == TRUE) {\r
414 //\r
415 // Send BlockSID command to each Opal disk\r
416 //\r
417 Itr = mOpalDriver.DeviceList;\r
418 Count = 0;\r
419 while (Itr != NULL) {\r
420 ZeroMem(&Session, sizeof(Session));\r
421 Session.Sscp = Itr->OpalDisk.Sscp;\r
422 Session.MediaId = Itr->OpalDisk.MediaId;\r
423 Session.OpalBaseComId = Itr->OpalDisk.OpalBaseComId;\r
424\r
425 Result = OpalBlockSid (&Session, TRUE); // HardwareReset must always be TRUE\r
426 if (Result != TcgResultSuccess) {\r
427 DEBUG ((DEBUG_ERROR, "OpalBlockSid fail\n"));\r
428 break;\r
429 }\r
430\r
431 Itr = Itr->Next;\r
432 Count++;\r
433 }\r
434 }\r
435}\r
436\r
437/**\r
438 Stop this Controller.\r
439\r
440 @param Dev The device need to be stopped.\r
441\r
442**/\r
443VOID\r
444OpalDriverStopDevice (\r
445 OPAL_DRIVER_DEVICE *Dev\r
446 )\r
447{\r
448 //\r
449 // free each name\r
450 //\r
451 FreePool(Dev->Name16);\r
452\r
453 //\r
454 // remove OPAL_DRIVER_DEVICE from the list\r
455 // it updates the controllerList pointer\r
456 //\r
457 RemoveDevice(Dev);\r
458\r
459 //\r
460 // close protocols that were opened\r
461 //\r
462 gBS->CloseProtocol(\r
463 Dev->Handle,\r
464 &gEfiStorageSecurityCommandProtocolGuid,\r
465 gOpalDriverBinding.DriverBindingHandle,\r
466 Dev->Handle\r
467 );\r
468\r
469 gBS->CloseProtocol(\r
470 Dev->Handle,\r
471 &gEfiBlockIoProtocolGuid,\r
472 gOpalDriverBinding.DriverBindingHandle,\r
473 Dev->Handle\r
474 );\r
475\r
476 FreePool(Dev);\r
477}\r
478\r
479/**\r
480 Get devcie name through the component name protocol.\r
481\r
482 @param[in] AllHandlesBuffer The handle buffer for current system.\r
483 @param[in] NumAllHandles The number of handles for the handle buffer.\r
484 @param[in] Dev The device which need to get name.\r
485 @param[in] UseComp1 Whether use component name or name2 protocol.\r
486\r
487 @retval TRUE Find the name for this device.\r
488 @retval FALSE Not found the name for this device.\r
489**/\r
490BOOLEAN\r
491OpalDriverGetDeviceNameByProtocol(\r
492 EFI_HANDLE *AllHandlesBuffer,\r
493 UINTN NumAllHandles,\r
494 OPAL_DRIVER_DEVICE *Dev,\r
495 BOOLEAN UseComp1\r
496 )\r
497{\r
498 EFI_HANDLE* ProtocolHandlesBuffer;\r
499 UINTN NumProtocolHandles;\r
500 EFI_STATUS Status;\r
501 EFI_COMPONENT_NAME2_PROTOCOL* Cnp1_2; // efi component name and componentName2 have same layout\r
502 EFI_GUID Protocol;\r
503 UINTN StrLength;\r
504 EFI_DEVICE_PATH_PROTOCOL* TmpDevPath;\r
505 UINTN Index1;\r
506 UINTN Index2;\r
507 EFI_HANDLE TmpHandle;\r
508 CHAR16 *DevName;\r
509\r
510 if (Dev == NULL || AllHandlesBuffer == NULL || NumAllHandles == 0) {\r
511 return FALSE;\r
512 }\r
513\r
514 Protocol = UseComp1 ? gEfiComponentNameProtocolGuid : gEfiComponentName2ProtocolGuid;\r
515\r
516 //\r
517 // Find all EFI_HANDLES with protocol\r
518 //\r
519 Status = gBS->LocateHandleBuffer(\r
520 ByProtocol,\r
521 &Protocol,\r
522 NULL,\r
523 &NumProtocolHandles,\r
524 &ProtocolHandlesBuffer\r
525 );\r
526 if (EFI_ERROR(Status)) {\r
527 return FALSE;\r
528 }\r
529\r
530\r
531 //\r
532 // Exit early if no supported devices\r
533 //\r
534 if (NumProtocolHandles == 0) {\r
535 return FALSE;\r
536 }\r
537\r
538 //\r
539 // Get printable name by iterating through all protocols\r
540 // using the handle as the child, and iterate through all handles for the controller\r
541 // exit loop early once found, if not found, then delete device\r
542 // storage security protocol instances already exist, add them to internal list\r
543 //\r
544 Status = EFI_DEVICE_ERROR;\r
545 for (Index1 = 0; Index1 < NumProtocolHandles; Index1++) {\r
546 DevName = NULL;\r
547\r
548 if (Dev->Name16 != NULL) {\r
549 return TRUE;\r
550 }\r
551\r
552 TmpHandle = ProtocolHandlesBuffer[Index1];\r
553\r
554 Status = gBS->OpenProtocol(\r
555 TmpHandle,\r
556 &Protocol,\r
557 (VOID**)&Cnp1_2,\r
558 gImageHandle,\r
559 NULL,\r
560 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
561 );\r
562 if (EFI_ERROR(Status) || Cnp1_2 == NULL) {\r
563 continue;\r
564 }\r
565\r
566 //\r
567 // Use all handles array as controller handle\r
568 //\r
569 for (Index2 = 0; Index2 < NumAllHandles; Index2++) {\r
570 Status = Cnp1_2->GetControllerName(\r
571 Cnp1_2,\r
572 AllHandlesBuffer[Index2],\r
573 Dev->Handle,\r
574 LANGUAGE_ISO_639_2_ENGLISH,\r
575 &DevName\r
576 );\r
577 if (EFI_ERROR(Status)) {\r
578 Status = Cnp1_2->GetControllerName(\r
579 Cnp1_2,\r
580 AllHandlesBuffer[Index2],\r
581 Dev->Handle,\r
582 LANGUAGE_RFC_3066_ENGLISH,\r
583 &DevName\r
584 );\r
585 }\r
586 if (!EFI_ERROR(Status) && DevName != NULL) {\r
587 StrLength = StrLen(DevName) + 1; // Add one for NULL terminator\r
588 Dev->Name16 = AllocateZeroPool(StrLength * sizeof (CHAR16));\r
589 ASSERT (Dev->Name16 != NULL);\r
590 StrCpyS (Dev->Name16, StrLength, DevName);\r
591 Dev->NameZ = (CHAR8*)AllocateZeroPool(StrLength);\r
592 UnicodeStrToAsciiStr(DevName, Dev->NameZ);\r
593\r
594 //\r
595 // Retrieve bridge BDF info and port number or namespace depending on type\r
596 //\r
597 TmpDevPath = NULL;\r
598 Status = gBS->OpenProtocol(\r
599 Dev->Handle,\r
600 &gEfiDevicePathProtocolGuid,\r
601 (VOID**)&TmpDevPath,\r
602 gImageHandle,\r
603 NULL,\r
604 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
605 );\r
606 if (!EFI_ERROR(Status)) {\r
607 Dev->OpalDevicePath = DuplicateDevicePath (TmpDevPath);\r
608 return TRUE;\r
609 }\r
610\r
611 if (Dev->Name16 != NULL) {\r
612 FreePool(Dev->Name16);\r
613 Dev->Name16 = NULL;\r
614 }\r
615 if (Dev->NameZ != NULL) {\r
616 FreePool(Dev->NameZ);\r
617 Dev->NameZ = NULL;\r
618 }\r
619 }\r
620 }\r
621 }\r
622\r
623 return FALSE;\r
624}\r
625\r
626/**\r
627 Get devcie name through the component name protocol.\r
628\r
629 @param[in] Dev The device which need to get name.\r
630\r
631 @retval TRUE Find the name for this device.\r
632 @retval FALSE Not found the name for this device.\r
633**/\r
634BOOLEAN\r
635OpalDriverGetDriverDeviceName(\r
636 OPAL_DRIVER_DEVICE *Dev\r
637 )\r
638{\r
639 EFI_HANDLE* AllHandlesBuffer;\r
640 UINTN NumAllHandles;\r
641 EFI_STATUS Status;\r
642\r
643 if (Dev == NULL) {\r
644 DEBUG((DEBUG_ERROR | DEBUG_INIT, "OpalDriverGetDriverDeviceName Exiting, Dev=NULL\n"));\r
645 return FALSE;\r
646 }\r
647\r
648 //\r
649 // Iterate through ComponentName2 handles to get name, if fails, try ComponentName\r
650 //\r
651 if (Dev->Name16 == NULL) {\r
652 DEBUG((DEBUG_ERROR | DEBUG_INIT, "Name is null, update it\n"));\r
653 //\r
654 // Find all EFI_HANDLES\r
655 //\r
656 Status = gBS->LocateHandleBuffer(\r
657 AllHandles,\r
658 NULL,\r
659 NULL,\r
660 &NumAllHandles,\r
661 &AllHandlesBuffer\r
662 );\r
663 if (EFI_ERROR(Status)) {\r
664 DEBUG ((DEBUG_INFO, "LocateHandleBuffer for AllHandles failed %r\n", Status ));\r
665 return FALSE;\r
666 }\r
667\r
668 //\r
669 // Try component Name2\r
670 //\r
671 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, FALSE)) {\r
672 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName2 failed to get device name, try ComponentName\n"));\r
673 if (!OpalDriverGetDeviceNameByProtocol(AllHandlesBuffer, NumAllHandles, Dev, TRUE)) {\r
674 DEBUG((DEBUG_ERROR | DEBUG_INIT, "ComponentName failed to get device name, skip device\n"));\r
675 return FALSE;\r
676 }\r
677 }\r
678 }\r
679\r
680 return TRUE;\r
681}\r
682\r
683/**\r
684 Main entry for this driver.\r
685\r
686 @param ImageHandle Image Handle this driver.\r
687 @param SystemTable Pointer to SystemTable.\r
688\r
689 @retval EFI_SUCESS This function always complete successfully.\r
690**/\r
691EFI_STATUS\r
692EFIAPI\r
693EfiDriverEntryPoint(\r
694 IN EFI_HANDLE ImageHandle,\r
695 IN EFI_SYSTEM_TABLE* SystemTable\r
696 )\r
697{\r
698 EFI_STATUS Status;\r
699 EFI_EVENT ReadyToBootEvent;\r
700\r
701 Status = EfiLibInstallDriverBindingComponentName2 (\r
702 ImageHandle,\r
703 SystemTable,\r
704 &gOpalDriverBinding,\r
705 ImageHandle,\r
706 &gOpalComponentName,\r
707 &gOpalComponentName2\r
708 );\r
709\r
710 if (EFI_ERROR(Status)) {\r
711 DEBUG((DEBUG_ERROR, "Install protocols to Opal driver Handle failed\n"));\r
712 return Status ;\r
713 }\r
714\r
715 //\r
716 // Initialize Driver object\r
717 //\r
718 ZeroMem(&mOpalDriver, sizeof(mOpalDriver));\r
719 mOpalDriver.Handle = ImageHandle;\r
720\r
721 //\r
722 // register a ReadyToBoot event callback for sending BlockSid command\r
723 //\r
724 Status = EfiCreateEventReadyToBootEx (\r
725 TPL_CALLBACK,\r
726 ReadyToBootCallback,\r
727 (VOID *) &ImageHandle,\r
728 &ReadyToBootEvent\r
729 );\r
730\r
f1430748
ED
731 //\r
732 // Install Hii packages.\r
733 //\r
734 HiiInstall();\r
735\r
a06875e1
ED
736 return Status;\r
737}\r
738\r
739/**\r
740 Tests to see if this driver supports a given controller.\r
741\r
742 This function checks to see if the controller contains an instance of the\r
743 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL and the EFI_BLOCK_IO_PROTOCL\r
744 and returns EFI_SUCCESS if it does.\r
745\r
746 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
747 @param[in] ControllerHandle The Handle of the controller to test. This Handle\r
748 must support a protocol interface that supplies\r
749 an I/O abstraction to the driver.\r
750 @param[in] RemainingDevicePath This parameter is ignored.\r
751\r
752 @retval EFI_SUCCESS The device contains required protocols\r
753 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
754 RemainingDevicePath is already being managed by the driver\r
755 specified by This.\r
756 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
757 RemainingDevicePath is already being managed by a different\r
758 driver or an application that requires exclusive access.\r
759 Currently not implemented.\r
760 @retval EFI_UNSUPPORTED The device does not contain requires protocols\r
761\r
762**/\r
763EFI_STATUS\r
764EFIAPI\r
765OpalEfiDriverBindingSupported(\r
766 IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
767 IN EFI_HANDLE Controller,\r
768 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
769 )\r
770{\r
771 EFI_STATUS Status;\r
772 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL* SecurityCommand;\r
773 EFI_BLOCK_IO_PROTOCOL* BlkIo;\r
774\r
775 //\r
776 // Test EFI_STORAGE_SECURITY_COMMAND_PROTOCOL on controller Handle.\r
777 //\r
778 Status = gBS->OpenProtocol(\r
779 Controller,\r
780 &gEfiStorageSecurityCommandProtocolGuid,\r
781 ( VOID ** )&SecurityCommand,\r
782 This->DriverBindingHandle,\r
783 Controller,\r
784 EFI_OPEN_PROTOCOL_BY_DRIVER\r
785 );\r
786\r
787 if (Status == EFI_ALREADY_STARTED) {\r
788 return EFI_SUCCESS;\r
789 }\r
790\r
791 if (EFI_ERROR(Status)) {\r
792 return Status;\r
793 }\r
794\r
795 //\r
796 // Close protocol and reopen in Start call\r
797 //\r
798 gBS->CloseProtocol(\r
799 Controller,\r
800 &gEfiStorageSecurityCommandProtocolGuid,\r
801 This->DriverBindingHandle,\r
802 Controller\r
803 );\r
804\r
805 //\r
806 // Test EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
807 // function APIs\r
808 //\r
809 Status = gBS->OpenProtocol(\r
810 Controller,\r
811 &gEfiBlockIoProtocolGuid,\r
812 (VOID **)&BlkIo,\r
813 This->DriverBindingHandle,\r
814 Controller,\r
815 EFI_OPEN_PROTOCOL_BY_DRIVER\r
816 );\r
817\r
818 if (EFI_ERROR(Status)) {\r
819 DEBUG((DEBUG_INFO, "No EFI_BLOCK_IO_PROTOCOL on controller\n"));\r
820 return Status;\r
821 }\r
822\r
823 //\r
824 // Close protocol and reopen in Start call\r
825 //\r
826 gBS->CloseProtocol(\r
827 Controller,\r
828 &gEfiBlockIoProtocolGuid,\r
829 This->DriverBindingHandle,\r
830 Controller\r
831 );\r
832\r
833 return EFI_SUCCESS;\r
834}\r
835\r
836/**\r
837 Enables Opal Management on a supported device if available.\r
838\r
839 The start function is designed to be called after the Opal UEFI Driver has confirmed the\r
840 "controller", which is a child Handle, contains the EF_STORAGE_SECURITY_COMMAND protocols.\r
841 This function will complete the other necessary checks, such as verifying the device supports\r
842 the correct version of Opal. Upon verification, it will add the device to the\r
843 Opal HII list in order to expose Opal managmeent options.\r
844\r
845 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
846 @param[in] ControllerHandle The Handle of the controller to start. This Handle\r
847 must support a protocol interface that supplies\r
848 an I/O abstraction to the driver.\r
849 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
850 parameter is ignored by device drivers, and is optional for bus\r
851 drivers. For a bus driver, if this parameter is NULL, then handles\r
852 for all the children of Controller are created by this driver.\r
853 If this parameter is not NULL and the first Device Path Node is\r
854 not the End of Device Path Node, then only the Handle for the\r
855 child device specified by the first Device Path Node of\r
856 RemainingDevicePath is created by this driver.\r
857 If the first Device Path Node of RemainingDevicePath is\r
858 the End of Device Path Node, no child Handle is created by this\r
859 driver.\r
860\r
861 @retval EFI_SUCCESS Opal management was enabled.\r
862 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
863 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
864 @retval Others The driver failed to start the device.\r
865\r
866**/\r
867EFI_STATUS\r
868EFIAPI\r
869OpalEfiDriverBindingStart(\r
870 IN EFI_DRIVER_BINDING_PROTOCOL* This,\r
871 IN EFI_HANDLE Controller,\r
872 IN EFI_DEVICE_PATH_PROTOCOL* RemainingDevicePath\r
873 )\r
874{\r
875 EFI_STATUS Status;\r
876 EFI_BLOCK_IO_PROTOCOL *BlkIo;\r
877 OPAL_DRIVER_DEVICE *Dev;\r
878 OPAL_DRIVER_DEVICE *Itr;\r
879 BOOLEAN Result;\r
880\r
881 Itr = mOpalDriver.DeviceList;\r
882 while (Itr != NULL) {\r
883 if (Controller == Itr->Handle) {\r
884 return EFI_SUCCESS;\r
885 }\r
886 Itr = Itr->Next;\r
887 }\r
888\r
889 //\r
890 // Create internal device for tracking. This allows all disks to be tracked\r
891 // by same HII form\r
892 //\r
893 Dev = (OPAL_DRIVER_DEVICE*)AllocateZeroPool(sizeof(OPAL_DRIVER_DEVICE));\r
894 if (Dev == NULL) {\r
895 return EFI_OUT_OF_RESOURCES;\r
896 }\r
897 Dev->Handle = Controller;\r
898\r
899 //\r
900 // Open EFI_STORAGE_SECURITY_COMMAND_PROTOCOL to perform Opal supported checks\r
901 //\r
902 Status = gBS->OpenProtocol(\r
903 Controller,\r
904 &gEfiStorageSecurityCommandProtocolGuid,\r
905 (VOID **)&Dev->Sscp,\r
906 This->DriverBindingHandle,\r
907 Controller,\r
908 EFI_OPEN_PROTOCOL_BY_DRIVER\r
909 );\r
910 if (EFI_ERROR(Status)) {\r
911 FreePool(Dev);\r
912 return Status;\r
913 }\r
914\r
915 //\r
916 // Open EFI_BLOCK_IO_PROTOCOL on controller Handle, required by EFI_STORAGE_SECURITY_COMMAND_PROTOCOL\r
917 // function APIs\r
918 //\r
919 Status = gBS->OpenProtocol(\r
920 Controller,\r
921 &gEfiBlockIoProtocolGuid,\r
922 (VOID **)&BlkIo,\r
923 This->DriverBindingHandle,\r
924 Controller,\r
925 EFI_OPEN_PROTOCOL_BY_DRIVER\r
926 );\r
927 if (EFI_ERROR(Status)) {\r
928 //\r
929 // Close storage security that was opened\r
930 //\r
931 gBS->CloseProtocol(\r
932 Controller,\r
933 &gEfiStorageSecurityCommandProtocolGuid,\r
934 This->DriverBindingHandle,\r
935 Controller\r
936 );\r
937\r
938 FreePool(Dev);\r
939 return Status;\r
940 }\r
941\r
942 //\r
943 // Save mediaId\r
944 //\r
945 Dev->MediaId = BlkIo->Media->MediaId;\r
946\r
947 gBS->CloseProtocol(\r
948 Controller,\r
949 &gEfiBlockIoProtocolGuid,\r
950 This->DriverBindingHandle,\r
951 Controller\r
952 );\r
953\r
954 //\r
955 // Acquire Ascii printable name of child, if not found, then ignore device\r
956 //\r
957 Result = OpalDriverGetDriverDeviceName (Dev);\r
958 if (!Result) {\r
959 goto Done;\r
960 }\r
961\r
962 Status = OpalDiskInitialize (Dev);\r
963 if (EFI_ERROR (Status)) {\r
964 goto Done;\r
965 }\r
966\r
967 AddDeviceToTail(Dev);\r
968\r
a06875e1
ED
969 //\r
970 // check if device is locked and prompt for password\r
971 //\r
972 OpalDriverRequestPassword (Dev);\r
973\r
974 return EFI_SUCCESS;\r
975\r
976Done:\r
977 //\r
978 // free device, close protocols and exit\r
979 //\r
980 gBS->CloseProtocol(\r
981 Controller,\r
982 &gEfiStorageSecurityCommandProtocolGuid,\r
983 This->DriverBindingHandle,\r
984 Controller\r
985 );\r
986\r
987 FreePool(Dev);\r
988\r
989 return EFI_DEVICE_ERROR;\r
990}\r
991\r
992/**\r
993 Stop this driver on Controller.\r
994\r
995 @param This Protocol instance pointer.\r
996 @param Controller Handle of device to stop driver on\r
997 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
998 children is zero stop the entire bus driver.\r
999 @param ChildHandleBuffer List of Child Handles to Stop.\r
1000\r
1001 @retval EFI_SUCCESS This driver is removed Controller.\r
1002 @retval other This driver could not be removed from this device.\r
1003\r
1004**/\r
1005EFI_STATUS\r
1006EFIAPI\r
1007OpalEfiDriverBindingStop(\r
1008 EFI_DRIVER_BINDING_PROTOCOL* This,\r
1009 EFI_HANDLE Controller,\r
1010 UINTN NumberOfChildren,\r
1011 EFI_HANDLE* ChildHandleBuffer\r
1012 )\r
1013{\r
1014 OPAL_DRIVER_DEVICE* Itr;\r
1015\r
1016 Itr = mOpalDriver.DeviceList;\r
1017\r
1018 //\r
1019 // does Controller match any of the devices we are managing for Opal\r
1020 //\r
1021 while (Itr != NULL) {\r
1022 if (Itr->Handle == Controller) {\r
1023 OpalDriverStopDevice (Itr);\r
1024 return EFI_SUCCESS;\r
1025 }\r
1026\r
1027 Itr = Itr->Next;\r
1028 }\r
1029\r
1030 return EFI_NOT_FOUND;\r
1031}\r
1032\r
1033\r
1034/**\r
1035 Unloads UEFI Driver. Very useful for debugging and testing.\r
1036\r
1037 @param ImageHandle Image Handle this driver.\r
1038\r
1039 @retval EFI_SUCCESS This function always complete successfully.\r
1040 @retval EFI_INVALID_PARAMETER The input ImageHandle is not valid.\r
1041**/\r
1042EFI_STATUS\r
1043EFIAPI\r
1044OpalEfiDriverUnload (\r
1045 IN EFI_HANDLE ImageHandle\r
1046 )\r
1047{\r
1048 EFI_STATUS Status;\r
1049 OPAL_DRIVER_DEVICE *Itr;\r
1050\r
1051 Status = EFI_SUCCESS;\r
1052\r
1053 if (ImageHandle != gImageHandle) {\r
1054 return (EFI_INVALID_PARAMETER);\r
1055 }\r
1056\r
1057 //\r
1058 // Uninstall any interface added to each device by us\r
1059 //\r
1060 while (mOpalDriver.DeviceList) {\r
1061 Itr = mOpalDriver.DeviceList;\r
1062 //\r
1063 // Remove OPAL_DRIVER_DEVICE from the list\r
1064 // it updates the controllerList pointer\r
1065 //\r
1066 OpalDriverStopDevice(Itr);\r
1067 }\r
1068\r
1069 //\r
1070 // Uninstall the HII capability\r
1071 //\r
1072 Status = HiiUninstall();\r
1073\r
1074 return Status;\r
1075}\r
1076\r