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