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