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