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