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