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