TianoCore EDK2 master
Loading...
Searching...
No Matches
UnitTestUefiBootServicesTableLibProtocol.c
Go to the documentation of this file.
1
10
11STATIC LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
12STATIC LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
13STATIC UINT64 gHandleDatabaseKey = 0;
14STATIC UINTN mEfiLocateHandleRequest = 0;
15
16//
17// Helper Functions
18//
19
31 IN EFI_HANDLE UserHandle
32 )
33{
34 IHANDLE *Handle;
35 LIST_ENTRY *Link;
36
37 if (UserHandle == NULL) {
38 return EFI_INVALID_PARAMETER;
39 }
40
41 for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {
42 Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
43 if (Handle == (IHANDLE *)UserHandle) {
44 return EFI_SUCCESS;
45 }
46 }
47
48 return EFI_INVALID_PARAMETER;
49}
50
62 IN EFI_GUID *Protocol,
63 IN BOOLEAN Create
64 )
65{
66 LIST_ENTRY *Link;
67 PROTOCOL_ENTRY *Item;
68 PROTOCOL_ENTRY *ProtEntry;
69
70 //
71 // Search the database for the matching GUID
72 //
73
74 ProtEntry = NULL;
75 for (Link = mProtocolDatabase.ForwardLink;
76 Link != &mProtocolDatabase;
77 Link = Link->ForwardLink)
78 {
79 Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
80 if (CompareGuid (&Item->ProtocolID, Protocol)) {
81 //
82 // This is the protocol entry
83 //
84
85 ProtEntry = Item;
86 break;
87 }
88 }
89
90 //
91 // If the protocol entry was not found and Create is TRUE, then
92 // allocate a new entry
93 //
94 if ((ProtEntry == NULL) && Create) {
95 ProtEntry = AllocatePool (sizeof (PROTOCOL_ENTRY));
96
97 if (ProtEntry != NULL) {
98 //
99 // Initialize new protocol entry structure
100 //
101 ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
102 CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);
103 InitializeListHead (&ProtEntry->Protocols);
104 InitializeListHead (&ProtEntry->Notify);
105
106 //
107 // Add it to protocol database
108 //
109 InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
110 }
111 }
112
113 return ProtEntry;
114}
115
130 IN IHANDLE *Handle,
131 IN EFI_GUID *Protocol,
132 IN VOID *Interface
133 )
134{
135 PROTOCOL_INTERFACE *Prot;
136 PROTOCOL_ENTRY *ProtEntry;
137 LIST_ENTRY *Link;
138
139 Prot = NULL;
140
141 //
142 // Lookup the protocol entry for this protocol ID
143 //
144
145 ProtEntry = UnitTestFindProtocolEntry (Protocol, FALSE);
146 if (ProtEntry != NULL) {
147 //
148 // Look at each protocol interface for any matches
149 //
150 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
151 //
152 // If this protocol interface matches, remove it
153 //
154 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
155 if ((Prot->Interface == Interface) && (Prot->Protocol == ProtEntry)) {
156 break;
157 }
158
159 Prot = NULL;
160 }
161 }
162
163 return Prot;
164}
165
172VOID
174 IN PROTOCOL_ENTRY *ProtEntry
175 )
176{
177 PROTOCOL_NOTIFY *ProtNotify;
178 LIST_ENTRY *Link;
179
180 for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {
181 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
182 UnitTestSignalEvent (ProtNotify->Event);
183 }
184}
185
197IHANDLE *
199 IN OUT LOCATE_POSITION *Position,
200 OUT VOID **Interface
201 )
202{
203 IHANDLE *Handle;
204
205 //
206 // Next handle
207 //
208 Position->Position = Position->Position->ForwardLink;
209
210 //
211 // If not at the end of the list, get the handle
212 //
213 Handle = NULL;
214 *Interface = NULL;
215 if (Position->Position != &gHandleList) {
216 Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
217 }
218
219 return Handle;
220}
221
234IHANDLE *
236 IN OUT LOCATE_POSITION *Position,
237 OUT VOID **Interface
238 )
239{
240 IHANDLE *Handle;
241 PROTOCOL_NOTIFY *ProtNotify;
242 PROTOCOL_INTERFACE *Prot;
243 LIST_ENTRY *Link;
244
245 Handle = NULL;
246 *Interface = NULL;
247 ProtNotify = Position->SearchKey;
248
249 //
250 // If this is the first request, get the next handle
251 //
252 if (ProtNotify != NULL) {
253 ASSERT (ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
254 Position->SearchKey = NULL;
255
256 //
257 // If not at the end of the list, get the next handle
258 //
259 Link = ProtNotify->Position->ForwardLink;
260 if (Link != &ProtNotify->Protocol->Protocols) {
261 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
262 Handle = Prot->Handle;
263 *Interface = Prot->Interface;
264 }
265 }
266
267 return Handle;
268}
269
281IHANDLE *
283 IN OUT LOCATE_POSITION *Position,
284 OUT VOID **Interface
285 )
286{
287 IHANDLE *Handle;
288 LIST_ENTRY *Link;
289 PROTOCOL_INTERFACE *Prot;
290
291 Handle = NULL;
292 *Interface = NULL;
293 for ( ; ;) {
294 //
295 // Next entry
296 //
297 Link = Position->Position->ForwardLink;
298 Position->Position = Link;
299
300 //
301 // If not at the end, return the handle
302 //
303 if (Link == &Position->ProtEntry->Protocols) {
304 Handle = NULL;
305 break;
306 }
307
308 //
309 // Get the handle
310 //
311 Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
312 Handle = Prot->Handle;
313 *Interface = Prot->Interface;
314
315 //
316 // If this handle has not been returned this request, then
317 // return it now
318 //
319 if (Handle->LocateRequest != mEfiLocateHandleRequest) {
320 Handle->LocateRequest = mEfiLocateHandleRequest;
321 break;
322 }
323 }
324
325 return Handle;
326}
327
344 IN EFI_HANDLE UserHandle,
346 )
347{
348 EFI_STATUS Status;
349 BOOLEAN ItemFound;
350 LIST_ENTRY *Link;
351 OPEN_PROTOCOL_DATA *OpenData;
352
353 Status = EFI_SUCCESS;
354
355 //
356 // Attempt to disconnect all drivers from this protocol interface
357 //
358 do {
359 ItemFound = FALSE;
360 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
361 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
362 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
363 Status = UnitTestDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
364 if (!EFI_ERROR (Status)) {
365 ItemFound = TRUE;
366 }
367
368 break;
369 }
370 }
371 } while (ItemFound);
372
373 if (!EFI_ERROR (Status)) {
374 //
375 // Attempt to remove BY_HANDLE_PROTOCOL and GET_PROTOCOL and TEST_PROTOCOL Open List items
376 //
377 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {
378 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
379 if ((OpenData->Attributes &
380 (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0)
381 {
382 Link = RemoveEntryList (&OpenData->Link);
383 Prot->OpenListCount--;
384 FreePool (OpenData);
385 } else {
386 Link = Link->ForwardLink;
387 }
388 }
389 }
390
391 //
392 // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
393 //
394 if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
395 UnitTestConnectController (UserHandle, NULL, NULL, TRUE);
396 Status = EFI_ACCESS_DENIED;
397 }
398
399 return Status;
400}
401
414 IN IHANDLE *Handle,
415 IN EFI_GUID *Protocol,
416 IN VOID *Interface
417 )
418{
419 PROTOCOL_INTERFACE *Prot;
420 PROTOCOL_NOTIFY *ProtNotify;
421 PROTOCOL_ENTRY *ProtEntry;
422 LIST_ENTRY *Link;
423
424 Prot = UnitTestFindProtocolInterface (Handle, Protocol, Interface);
425 if (Prot != NULL) {
426 ProtEntry = Prot->Protocol;
427
428 //
429 // If there's a protocol notify location pointing to this entry, back it up one
430 //
431 for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {
432 ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
433
434 if (ProtNotify->Position == &Prot->ByProtocol) {
435 ProtNotify->Position = Prot->ByProtocol.BackLink;
436 }
437 }
438
439 //
440 // Remove the protocol interface entry
441 //
443 }
444
445 return Prot;
446}
447
448//
449// Boot Services Function Implementation
450//
451
463 IN EFI_HANDLE UserHandle,
464 IN EFI_GUID *Protocol
465 )
466{
467 EFI_STATUS Status;
468 PROTOCOL_ENTRY *ProtEntry;
469 PROTOCOL_INTERFACE *Prot;
470 IHANDLE *Handle;
471 LIST_ENTRY *Link;
472
473 Status = UnitTestValidateHandle (UserHandle);
474 if (EFI_ERROR (Status)) {
475 return NULL;
476 }
477
478 Handle = (IHANDLE *)UserHandle;
479
480 //
481 // Look at each protocol interface for a match
482 //
483 for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
484 Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
485 ProtEntry = Prot->Protocol;
486 if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
487 return Prot;
488 }
489 }
490
491 return NULL;
492}
493
513 IN OUT EFI_HANDLE *UserHandle,
514 IN EFI_GUID *Protocol,
515 IN EFI_INTERFACE_TYPE InterfaceType,
516 IN VOID *Interface,
517 IN BOOLEAN Notify
518 )
519{
520 PROTOCOL_INTERFACE *Prot;
521 PROTOCOL_ENTRY *ProtEntry;
522 IHANDLE *Handle;
523 EFI_STATUS Status;
524 VOID *ExistingInterface;
525
526 //
527 // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
528 // Also added check for invalid UserHandle and Protocol pointers.
529 //
530 if ((UserHandle == NULL) || (Protocol == NULL)) {
531 return EFI_INVALID_PARAMETER;
532 }
533
534 if (InterfaceType != EFI_NATIVE_INTERFACE) {
535 return EFI_INVALID_PARAMETER;
536 }
537
538 //
539 // Print debug message
540 //
541 UT_LOG_INFO ("InstallProtocolInterface: %g %p\n", Protocol, Interface);
542
543 Status = EFI_OUT_OF_RESOURCES;
544 Prot = NULL;
545 Handle = NULL;
546
547 if (*UserHandle != NULL) {
548 Status = UnitTestHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
549 if (!EFI_ERROR (Status)) {
550 return EFI_INVALID_PARAMETER;
551 }
552 }
553
554 //
555 // Lookup the Protocol Entry for the requested protocol
556 //
557 ProtEntry = UnitTestFindProtocolEntry (Protocol, TRUE);
558 if (ProtEntry == NULL) {
559 goto Done;
560 }
561
562 //
563 // Allocate a new protocol interface structure
564 //
565 Prot = AllocateZeroPool (sizeof (PROTOCOL_INTERFACE));
566 if (Prot == NULL) {
567 Status = EFI_OUT_OF_RESOURCES;
568 goto Done;
569 }
570
571 //
572 // If caller didn't supply a handle, allocate a new one
573 //
574 Handle = (IHANDLE *)*UserHandle;
575 if (Handle == NULL) {
576 Handle = AllocateZeroPool (sizeof (IHANDLE));
577 if (Handle == NULL) {
578 Status = EFI_OUT_OF_RESOURCES;
579 goto Done;
580 }
581
582 //
583 // Initialize new handler structure
584 //
585 Handle->Signature = EFI_HANDLE_SIGNATURE;
586 InitializeListHead (&Handle->Protocols);
587
588 //
589 // Initialize the Key to show that the handle has been created/modified
590 //
591 gHandleDatabaseKey++;
592 Handle->Key = gHandleDatabaseKey;
593
594 //
595 // Add this handle to the list global list of all handles
596 // in the system
597 //
598 InsertTailList (&gHandleList, &Handle->AllHandles);
599 } else {
600 Status = UnitTestValidateHandle (Handle);
601 if (EFI_ERROR (Status)) {
602 DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));
603 goto Done;
604 }
605 }
606
607 //
608 // Each interface that is added must be unique
609 //
610 ASSERT (UnitTestFindProtocolInterface (Handle, Protocol, Interface) == NULL);
611
612 //
613 // Initialize the protocol interface structure
614 //
615 Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
616 Prot->Handle = Handle;
617 Prot->Protocol = ProtEntry;
618 Prot->Interface = Interface;
619
620 //
621 // Initialize OpenProtocol Data base
622 //
624 Prot->OpenListCount = 0;
625
626 //
627 // Add this protocol interface to the head of the supported
628 // protocol list for this handle
629 //
630 InsertHeadList (&Handle->Protocols, &Prot->Link);
631
632 //
633 // Add this protocol interface to the tail of the
634 // protocol entry
635 //
636 InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
637
638 //
639 // Notify the notification list for this protocol
640 //
641 if (Notify) {
642 UnitTestNotifyProtocolEntry (ProtEntry);
643 }
644
645 Status = EFI_SUCCESS;
646
647Done:
648 if (!EFI_ERROR (Status)) {
649 //
650 // Return the new handle back to the caller
651 //
652 *UserHandle = Handle;
653 } else {
654 //
655 // There was an error, clean up
656 //
657 if (Prot != NULL) {
658 UnitTestFreePool (Prot);
659 }
660
661 DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));
662 }
663
664 return Status;
665}
666
682EFIAPI
684 IN OUT EFI_HANDLE *UserHandle,
685 IN EFI_GUID *Protocol,
686 IN EFI_INTERFACE_TYPE InterfaceType,
687 IN VOID *Interface
688 )
689{
691 UserHandle,
692 Protocol,
693 InterfaceType,
694 Interface,
695 TRUE
696 );
697}
698
714EFIAPI
716 IN EFI_HANDLE UserHandle,
717 IN EFI_GUID *Protocol,
718 IN VOID *OldInterface,
719 IN VOID *NewInterface
720 )
721{
723}
724
739EFIAPI
741 IN EFI_HANDLE UserHandle,
742 IN EFI_GUID *Protocol,
743 IN VOID *Interface
744 )
745{
746 EFI_STATUS Status;
747 IHANDLE *Handle;
748 PROTOCOL_INTERFACE *Prot;
749
750 //
751 // Check that Protocol is valid
752 //
753 if (Protocol == NULL) {
754 return EFI_INVALID_PARAMETER;
755 }
756
757 //
758 // Check that UserHandle is a valid handle
759 //
760 Status = UnitTestValidateHandle (UserHandle);
761 if (EFI_ERROR (Status)) {
762 return Status;
763 }
764
765 //
766 // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
767 //
768 Prot = UnitTestFindProtocolInterface (UserHandle, Protocol, Interface);
769 if (Prot == NULL) {
770 Status = EFI_NOT_FOUND;
771 goto Done;
772 }
773
774 //
775 // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
776 //
778 UserHandle,
779 Prot
780 );
781 if (EFI_ERROR (Status)) {
782 //
783 // One or more drivers refused to release, so return the error
784 //
785 goto Done;
786 }
787
788 //
789 // Remove the protocol interface from the protocol
790 //
791 Status = EFI_NOT_FOUND;
792 Handle = (IHANDLE *)UserHandle;
793 Prot = UnitTestRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
794
795 if (Prot != NULL) {
796 //
797 // Update the Key to show that the handle has been created/modified
798 //
799 gHandleDatabaseKey++;
800 Handle->Key = gHandleDatabaseKey;
801
802 //
803 // Remove the protocol interface from the handle
804 //
805 RemoveEntryList (&Prot->Link);
806
807 //
808 // Free the memory
809 //
810 Prot->Signature = 0;
811 FreePool (Prot);
812 Status = EFI_SUCCESS;
813 }
814
815 //
816 // If there are no more handlers for the handle, free the handle
817 //
818 if (IsListEmpty (&Handle->Protocols)) {
819 Handle->Signature = 0;
820 RemoveEntryList (&Handle->AllHandles);
821 FreePool (Handle);
822 }
823
824Done:
825 return Status;
826}
827
840EFIAPI
842 IN EFI_HANDLE UserHandle,
843 IN EFI_GUID *Protocol,
844 OUT VOID **Interface
845 )
846{
847 return UnitTestOpenProtocol (
848 UserHandle,
849 Protocol,
850 Interface,
852 NULL,
853 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
854 );
855}
856
871EFIAPI
873 IN EFI_GUID *Protocol,
874 IN EFI_EVENT Event,
875 OUT VOID **Registration
876 )
877{
879}
880
900EFIAPI
902 IN EFI_LOCATE_SEARCH_TYPE SearchType,
903 IN EFI_GUID *Protocol OPTIONAL,
904 IN VOID *SearchKey OPTIONAL,
905 IN OUT UINTN *BufferSize,
906 OUT EFI_HANDLE *Buffer
907 )
908{
909 EFI_STATUS Status;
910 LOCATE_POSITION Position;
911 PROTOCOL_NOTIFY *ProtNotify;
912 UNIT_TEST_GET_NEXT GetNext;
913 UINTN ResultSize;
914 IHANDLE *Handle;
915 IHANDLE **ResultBuffer;
916 VOID *Interface;
917
918 if (BufferSize == NULL) {
919 return EFI_INVALID_PARAMETER;
920 }
921
922 if ((*BufferSize > 0) && (Buffer == NULL)) {
923 return EFI_INVALID_PARAMETER;
924 }
925
926 GetNext = NULL;
927
928 //
929 // Set initial position
930 //
931 Position.Protocol = Protocol;
932 Position.SearchKey = SearchKey;
933 Position.Position = &gHandleList;
934
935 ResultSize = 0;
936 ResultBuffer = (IHANDLE **)Buffer;
937 Status = EFI_SUCCESS;
938
939 //
940 // Get the search function based on type
941 //
942 switch (SearchType) {
943 case AllHandles:
945 break;
946
947 case ByRegisterNotify:
948 //
949 // Must have SearchKey for locate ByRegisterNotify
950 //
951 if (SearchKey == NULL) {
952 Status = EFI_INVALID_PARAMETER;
953 break;
954 }
955
957 break;
958
959 case ByProtocol:
961 if (Protocol == NULL) {
962 Status = EFI_INVALID_PARAMETER;
963 break;
964 }
965
966 //
967 // Look up the protocol entry and set the head pointer
968 //
969 Position.ProtEntry = UnitTestFindProtocolEntry (Protocol, FALSE);
970 if (Position.ProtEntry == NULL) {
971 Status = EFI_NOT_FOUND;
972 break;
973 }
974
975 Position.Position = &Position.ProtEntry->Protocols;
976 break;
977
978 default:
979 Status = EFI_INVALID_PARAMETER;
980 break;
981 }
982
983 if (EFI_ERROR (Status)) {
984 return Status;
985 }
986
987 ASSERT (GetNext != NULL);
988 //
989 // Enumerate out the matching handles
990 //
991 mEfiLocateHandleRequest += 1;
992 for ( ; ;) {
993 //
994 // Get the next handle. If no more handles, stop
995 //
996 Handle = GetNext (&Position, &Interface);
997 if (NULL == Handle) {
998 break;
999 }
1000
1001 //
1002 // Increase the resulting buffer size, and if this handle
1003 // fits return it
1004 //
1005 ResultSize += sizeof (Handle);
1006 if (ResultSize <= *BufferSize) {
1007 *ResultBuffer = Handle;
1008 ResultBuffer += 1;
1009 }
1010 }
1011
1012 //
1013 // If the result is a zero length buffer, then there were no
1014 // matching handles
1015 //
1016 if (ResultSize == 0) {
1017 Status = EFI_NOT_FOUND;
1018 } else {
1019 //
1020 // Return the resulting buffer size. If it's larger than what
1021 // was passed, then set the error code
1022 //
1023 if (ResultSize > *BufferSize) {
1024 Status = EFI_BUFFER_TOO_SMALL;
1025 }
1026
1027 *BufferSize = ResultSize;
1028
1029 if ((SearchType == ByRegisterNotify) && !EFI_ERROR (Status)) {
1030 //
1031 // If this is a search by register notify and a handle was
1032 // returned, update the register notification position
1033 //
1034 ASSERT (SearchKey != NULL);
1035 ProtNotify = SearchKey;
1036 ProtNotify->Position = ProtNotify->Position->ForwardLink;
1037 }
1038 }
1039
1040 return Status;
1041}
1042
1059EFIAPI
1061 IN EFI_GUID *Protocol,
1062 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
1063 OUT EFI_HANDLE *Device
1064 )
1065{
1066 return EFI_NOT_AVAILABLE_YET;
1067}
1068
1085EFIAPI
1087 IN EFI_GUID *Guid,
1088 IN VOID *Table
1089 )
1090{
1091 return EFI_NOT_AVAILABLE_YET;
1092}
1093
1115EFIAPI
1117 IN EFI_HANDLE UserHandle,
1118 IN EFI_GUID *Protocol,
1119 OUT VOID **Interface OPTIONAL,
1120 IN EFI_HANDLE ImageHandle,
1121 IN EFI_HANDLE ControllerHandle,
1122 IN UINT32 Attributes
1123 )
1124{
1125 EFI_STATUS Status;
1126 PROTOCOL_INTERFACE *Prot;
1127 LIST_ENTRY *Link;
1128 OPEN_PROTOCOL_DATA *OpenData;
1129 BOOLEAN ByDriver;
1130 BOOLEAN Exclusive;
1131 BOOLEAN Disconnect;
1132 BOOLEAN ExactMatch;
1133
1134 //
1135 // Check for invalid Protocol
1136 //
1137 if (Protocol == NULL) {
1138 return EFI_INVALID_PARAMETER;
1139 }
1140
1141 //
1142 // Check for invalid Interface
1143 //
1144 if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {
1145 return EFI_INVALID_PARAMETER;
1146 }
1147
1148 //
1149 // Check for invalid UserHandle
1150 //
1151 Status = UnitTestValidateHandle (UserHandle);
1152 if (EFI_ERROR (Status)) {
1153 return Status;
1154 }
1155
1156 //
1157 // Check for invalid Attributes
1158 //
1159 switch (Attributes) {
1160 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
1161 Status = UnitTestValidateHandle (ImageHandle);
1162 if (EFI_ERROR (Status)) {
1163 return Status;
1164 }
1165
1166 Status = UnitTestValidateHandle (ControllerHandle);
1167 if (EFI_ERROR (Status)) {
1168 return Status;
1169 }
1170
1171 if (UserHandle == ControllerHandle) {
1172 return EFI_INVALID_PARAMETER;
1173 }
1174
1175 break;
1176 case EFI_OPEN_PROTOCOL_BY_DRIVER:
1177 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
1178 Status = UnitTestValidateHandle (ImageHandle);
1179 if (EFI_ERROR (Status)) {
1180 return Status;
1181 }
1182
1183 Status = UnitTestValidateHandle (ControllerHandle);
1184 if (EFI_ERROR (Status)) {
1185 return Status;
1186 }
1187
1188 break;
1189 case EFI_OPEN_PROTOCOL_EXCLUSIVE:
1190 Status = UnitTestValidateHandle (ImageHandle);
1191 if (EFI_ERROR (Status)) {
1192 return Status;
1193 }
1194
1195 break;
1196 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
1197 case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
1198 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
1199 break;
1200 default:
1201 return EFI_INVALID_PARAMETER;
1202 }
1203
1204 //
1205 // Look at each protocol interface for a match
1206 //
1207 Prot = UnitTestGetProtocolInterface (UserHandle, Protocol);
1208 if (Prot == NULL) {
1209 Status = EFI_UNSUPPORTED;
1210 goto Done;
1211 }
1212
1213 Status = EFI_SUCCESS;
1214
1215 ByDriver = FALSE;
1216 Exclusive = FALSE;
1217 for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
1218 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1219 ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
1220 (OpenData->Attributes == Attributes) &&
1221 (OpenData->ControllerHandle == ControllerHandle));
1222 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1223 ByDriver = TRUE;
1224 if (ExactMatch) {
1225 Status = EFI_ALREADY_STARTED;
1226 goto Done;
1227 }
1228 }
1229
1230 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
1231 Exclusive = TRUE;
1232 } else if (ExactMatch) {
1233 OpenData->OpenCount++;
1234 Status = EFI_SUCCESS;
1235 goto Done;
1236 }
1237 }
1238
1239 //
1240 // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
1241 // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
1242 // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
1243 // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
1244 //
1245
1246 switch (Attributes) {
1247 case EFI_OPEN_PROTOCOL_BY_DRIVER:
1248 if (Exclusive || ByDriver) {
1249 Status = EFI_ACCESS_DENIED;
1250 goto Done;
1251 }
1252
1253 break;
1254 case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
1255 case EFI_OPEN_PROTOCOL_EXCLUSIVE:
1256 if (Exclusive) {
1257 Status = EFI_ACCESS_DENIED;
1258 goto Done;
1259 }
1260
1261 if (ByDriver) {
1262 do {
1263 Disconnect = FALSE;
1264 for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
1265 OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
1266 if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
1267 Disconnect = TRUE;
1268 Status = UnitTestDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
1269 if (EFI_ERROR (Status)) {
1270 Status = EFI_ACCESS_DENIED;
1271 goto Done;
1272 } else {
1273 break;
1274 }
1275 }
1276 }
1277 } while (Disconnect);
1278 }
1279
1280 break;
1281 case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
1282 case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
1283 case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
1284 case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
1285 break;
1286 }
1287
1288 if (ImageHandle == NULL) {
1289 Status = EFI_SUCCESS;
1290 goto Done;
1291 }
1292
1293 //
1294 // Create new entry
1295 //
1296 OpenData = AllocatePool (sizeof (OPEN_PROTOCOL_DATA));
1297 if (OpenData == NULL) {
1298 Status = EFI_OUT_OF_RESOURCES;
1299 } else {
1300 OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
1301 OpenData->AgentHandle = ImageHandle;
1302 OpenData->ControllerHandle = ControllerHandle;
1303 OpenData->Attributes = Attributes;
1304 OpenData->OpenCount = 1;
1305 InsertTailList (&Prot->OpenList, &OpenData->Link);
1306 Prot->OpenListCount++;
1307 Status = EFI_SUCCESS;
1308 }
1309
1310Done:
1311
1312 if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
1313 //
1314 // Keep Interface unmodified in case of any Error
1315 // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.
1316 //
1317 if (!EFI_ERROR (Status) || (Status == EFI_ALREADY_STARTED)) {
1318 //
1319 // According to above logic, if 'Prot' is NULL, then the 'Status' must be
1320 // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'
1321 // must be not NULL.
1322 //
1323 // The ASSERT here is for addressing a false positive NULL pointer
1324 // dereference issue raised from static analysis.
1325 //
1326 ASSERT (Prot != NULL);
1327 //
1328 // EFI_ALREADY_STARTED is not an error for bus driver.
1329 // Return the corresponding protocol interface.
1330 //
1331 *Interface = Prot->Interface;
1332 } else if (Status == EFI_UNSUPPORTED) {
1333 //
1334 // Return NULL Interface if Unsupported Protocol.
1335 //
1336 *Interface = NULL;
1337 }
1338 }
1339
1340 return Status;
1341}
1342
1369EFIAPI
1371 IN EFI_HANDLE UserHandle,
1372 IN EFI_GUID *Protocol,
1373 IN EFI_HANDLE AgentHandle,
1374 IN EFI_HANDLE ControllerHandle
1375 )
1376{
1377 return EFI_NOT_AVAILABLE_YET;
1378}
1379
1392EFIAPI
1394 IN EFI_HANDLE UserHandle,
1395 IN EFI_GUID *Protocol,
1397 OUT UINTN *EntryCount
1398 )
1399{
1400 return EFI_NOT_AVAILABLE_YET;
1401}
1402
1427EFIAPI
1429 IN EFI_HANDLE UserHandle,
1430 OUT EFI_GUID ***ProtocolBuffer,
1431 OUT UINTN *ProtocolBufferCount
1432 )
1433{
1434 return EFI_NOT_AVAILABLE_YET;
1435}
1436
1460EFIAPI
1462 IN EFI_LOCATE_SEARCH_TYPE SearchType,
1463 IN EFI_GUID *Protocol OPTIONAL,
1464 IN VOID *SearchKey OPTIONAL,
1465 IN OUT UINTN *NumberHandles,
1466 OUT EFI_HANDLE **Buffer
1467 )
1468{
1469 EFI_STATUS Status;
1470 UINTN BufferSize;
1471
1472 if (NumberHandles == NULL) {
1473 return EFI_INVALID_PARAMETER;
1474 }
1475
1476 if (Buffer == NULL) {
1477 return EFI_INVALID_PARAMETER;
1478 }
1479
1480 BufferSize = 0;
1481 *NumberHandles = 0;
1482 *Buffer = NULL;
1483 Status = UnitTestLocateHandle (
1484 SearchType,
1485 Protocol,
1486 SearchKey,
1487 &BufferSize,
1488 *Buffer
1489 );
1490 //
1491 // LocateHandleBuffer() returns incorrect status code if SearchType is
1492 // invalid.
1493 //
1494 // Add code to correctly handle expected errors from UnitTestLocateHandle().
1495 //
1496 if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
1497 if (Status != EFI_INVALID_PARAMETER) {
1498 Status = EFI_NOT_FOUND;
1499 }
1500
1501 return Status;
1502 }
1503
1504 *Buffer = AllocatePool (BufferSize);
1505 if (*Buffer == NULL) {
1506 return EFI_OUT_OF_RESOURCES;
1507 }
1508
1509 Status = UnitTestLocateHandle (
1510 SearchType,
1511 Protocol,
1512 SearchKey,
1513 &BufferSize,
1514 *Buffer
1515 );
1516
1517 *NumberHandles = BufferSize / sizeof (EFI_HANDLE);
1518 if (EFI_ERROR (Status)) {
1519 *NumberHandles = 0;
1520 }
1521
1522 return Status;
1523}
1524
1542EFIAPI
1544 IN EFI_GUID *Protocol,
1545 IN VOID *Registration OPTIONAL,
1546 OUT VOID **Interface
1547 )
1548{
1549 return EFI_NOT_AVAILABLE_YET;
1550}
1551
1574EFIAPI
1576 IN OUT EFI_HANDLE *Handle,
1577 ...
1578 )
1579{
1580 return EFI_NOT_AVAILABLE_YET;
1581}
1582
1598EFIAPI
1600 IN EFI_HANDLE Handle,
1601 ...
1602 )
1603{
1604 EFI_STATUS Status;
1605 VA_LIST Args;
1606 EFI_GUID *Protocol;
1607 VOID *Interface;
1608 UINTN Index;
1609
1610 VA_START (Args, Handle);
1611 for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
1612 //
1613 // If protocol is NULL, then it's the end of the list
1614 //
1615 Protocol = VA_ARG (Args, EFI_GUID *);
1616 if (Protocol == NULL) {
1617 break;
1618 }
1619
1620 Interface = VA_ARG (Args, VOID *);
1621
1622 //
1623 // Uninstall it
1624 //
1625 Status = UnitTestUninstallProtocolInterface (Handle, Protocol, Interface);
1626 }
1627
1628 VA_END (Args);
1629
1630 //
1631 // If there was an error, add all the interfaces that were
1632 // uninstalled without any errors
1633 //
1634 if (EFI_ERROR (Status)) {
1635 //
1636 // Reset the va_arg back to the first argument.
1637 //
1638 VA_START (Args, Handle);
1639 for ( ; Index > 1; Index--) {
1640 Protocol = VA_ARG (Args, EFI_GUID *);
1641 Interface = VA_ARG (Args, VOID *);
1642 UnitTestInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
1643 }
1644
1645 VA_END (Args);
1646 Status = EFI_INVALID_PARAMETER;
1647 }
1648
1649 return Status;
1650}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead)
Definition: BaseLib.h:2904
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
Definition: MemLibGuid.c:73
GUID *EFIAPI CopyGuid(OUT GUID *DestinationGuid, IN CONST GUID *SourceGuid)
Definition: MemLibGuid.c:39
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define STATIC
Definition: Base.h:264
#define VA_ARG(Marker, TYPE)
Definition: Base.h:679
#define VA_START(Marker, Parameter)
Definition: Base.h:661
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
CHAR8 * VA_LIST
Definition: Base.h:643
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define VA_END(Marker)
Definition: Base.h:691
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
#define EFI_NOT_AVAILABLE_YET
Definition: PiMultiPhase.h:54
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_INTERFACE_TYPE
Definition: UefiSpec.h:1189
@ EFI_NATIVE_INTERFACE
Definition: UefiSpec.h:1193
EFI_LOCATE_SEARCH_TYPE
Definition: UefiSpec.h:1505
@ ByProtocol
Definition: UefiSpec.h:1518
@ ByRegisterNotify
Definition: UefiSpec.h:1513
@ AllHandles
Definition: UefiSpec.h:1509
#define UT_LOG_INFO(Format,...)
Definition: UnitTestLib.h:813
EFI_STATUS EFIAPI UnitTestSignalEvent(IN EFI_EVENT UserEvent)
EFI_STATUS EFIAPI UnitTestDisconnectController(IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE DriverImageHandle OPTIONAL, IN EFI_HANDLE ChildHandle OPTIONAL)
EFI_STATUS EFIAPI UnitTestFreePool(IN VOID *Buffer)
EFI_STATUS EFIAPI UnitTestConnectController(IN EFI_HANDLE ControllerHandle, IN EFI_HANDLE *DriverImageHandle OPTIONAL, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, IN BOOLEAN Recursive)
EFI_STATUS EFIAPI UnitTestOpenProtocol(IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, OUT VOID **Interface OPTIONAL, IN EFI_HANDLE ImageHandle, IN EFI_HANDLE ControllerHandle, IN UINT32 Attributes)
EFI_STATUS EFIAPI UnitTestCloseProtocol(IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, IN EFI_HANDLE AgentHandle, IN EFI_HANDLE ControllerHandle)
EFI_STATUS EFIAPI UnitTestRegisterProtocolNotify(IN EFI_GUID *Protocol, IN EFI_EVENT Event, OUT VOID **Registration)
PROTOCOL_INTERFACE * UnitTestFindProtocolInterface(IN IHANDLE *Handle, IN EFI_GUID *Protocol, IN VOID *Interface)
EFI_STATUS EFIAPI UnitTestLocateDevicePath(IN EFI_GUID *Protocol, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, OUT EFI_HANDLE *Device)
IHANDLE * UnitTestGetNextLocateByProtocol(IN OUT LOCATE_POSITION *Position, OUT VOID **Interface)
VOID UnitTestNotifyProtocolEntry(IN PROTOCOL_ENTRY *ProtEntry)
EFI_STATUS EFIAPI UnitTestInstallProtocolInterface(IN OUT EFI_HANDLE *UserHandle, IN EFI_GUID *Protocol, IN EFI_INTERFACE_TYPE InterfaceType, IN VOID *Interface)
EFI_STATUS EFIAPI UnitTestLocateHandleBuffer(IN EFI_LOCATE_SEARCH_TYPE SearchType, IN EFI_GUID *Protocol OPTIONAL, IN VOID *SearchKey OPTIONAL, IN OUT UINTN *NumberHandles, OUT EFI_HANDLE **Buffer)
EFI_STATUS UnitTestValidateHandle(IN EFI_HANDLE UserHandle)
EFI_STATUS EFIAPI UnitTestUninstallMultipleProtocolInterfaces(IN EFI_HANDLE Handle,...)
EFI_STATUS EFIAPI UnitTestReinstallProtocolInterface(IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, IN VOID *OldInterface, IN VOID *NewInterface)
EFI_STATUS EFIAPI UnitTestUninstallProtocolInterface(IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, IN VOID *Interface)
EFI_STATUS EFIAPI UnitTestProtocolsPerHandle(IN EFI_HANDLE UserHandle, OUT EFI_GUID ***ProtocolBuffer, OUT UINTN *ProtocolBufferCount)
PROTOCOL_ENTRY * UnitTestFindProtocolEntry(IN EFI_GUID *Protocol, IN BOOLEAN Create)
IHANDLE * UnitTestGetNextLocateAllHandles(IN OUT LOCATE_POSITION *Position, OUT VOID **Interface)
EFI_STATUS EFIAPI UnitTestOpenProtocolInformation(IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, OUT UINTN *EntryCount)
EFI_STATUS EFIAPI UnitTestHandleProtocol(IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol, OUT VOID **Interface)
PROTOCOL_INTERFACE * UnitTestRemoveInterfaceFromProtocol(IN IHANDLE *Handle, IN EFI_GUID *Protocol, IN VOID *Interface)
EFI_STATUS EFIAPI UnitTestLocateHandle(IN EFI_LOCATE_SEARCH_TYPE SearchType, IN EFI_GUID *Protocol OPTIONAL, IN VOID *SearchKey OPTIONAL, IN OUT UINTN *BufferSize, OUT EFI_HANDLE *Buffer)
PROTOCOL_INTERFACE * UnitTestGetProtocolInterface(IN EFI_HANDLE UserHandle, IN EFI_GUID *Protocol)
EFI_STATUS EFIAPI UnitTestInstallConfigurationTable(IN EFI_GUID *Guid, IN VOID *Table)
EFI_STATUS EFIAPI UnitTestInstallMultipleProtocolInterfaces(IN OUT EFI_HANDLE *Handle,...)
EFI_STATUS UnitTestDisconnectControllersUsingProtocolInterface(IN EFI_HANDLE UserHandle, IN PROTOCOL_INTERFACE *Prot)
IHANDLE * UnitTestGetNextLocateByRegisterNotify(IN OUT LOCATE_POSITION *Position, OUT VOID **Interface)
EFI_STATUS EFIAPI UnitTestLocateProtocol(IN EFI_GUID *Protocol, IN VOID *Registration OPTIONAL, OUT VOID **Interface)
EFI_STATUS UnitTestInstallProtocolInterfaceNotify(IN OUT EFI_HANDLE *UserHandle, IN EFI_GUID *Protocol, IN EFI_INTERFACE_TYPE InterfaceType, IN VOID *Interface, IN BOOLEAN Notify)
Definition: Base.h:213
Definition: Handle.h:17
LIST_ENTRY AllHandles
All handles list of IHANDLE.
Definition: Handle.h:20
UINT64 Key
The Handle Database Key value when this handle was last created or modified.
Definition: Handle.h:25
LIST_ENTRY Protocols
List of PROTOCOL_INTERFACE's for this handle.
Definition: Handle.h:22
LIST_ENTRY Link
Link on PROTOCOL_INTERFACE.OpenList.
Definition: Handle.h:77
LIST_ENTRY Notify
Registerd notification handlers.
Definition: Handle.h:46
LIST_ENTRY AllEntries
Link Entry inserted to mProtocolDatabase.
Definition: Handle.h:40
EFI_GUID ProtocolID
ID of the protocol.
Definition: Handle.h:42
LIST_ENTRY Protocols
All protocol interfaces.
Definition: Handle.h:44
LIST_ENTRY Link
Link on IHANDLE.Protocols.
Definition: Handle.h:58
IHANDLE * Handle
Back pointer.
Definition: Handle.h:60
LIST_ENTRY OpenList
OPEN_PROTOCOL_DATA list.
Definition: Handle.h:68
PROTOCOL_ENTRY * Protocol
The protocol ID.
Definition: Handle.h:64
VOID * Interface
The interface value.
Definition: Handle.h:66
LIST_ENTRY ByProtocol
Link on PROTOCOL_ENTRY.Protocols.
Definition: Handle.h:62
EFI_EVENT Event
Event to notify.
Definition: Handle.h:96
LIST_ENTRY * Position
Last position notified.
Definition: Handle.h:98