]> git.proxmox.com Git - mirror_edk2.git/blob - UnitTestFrameworkPkg/Library/UnitTestUefiBootServicesTableLib/UnitTestUefiBootServicesTableLibProtocol.c
UnitTestFrameworkPkg: Add UnitTestUefiBootServicesTableLib
[mirror_edk2.git] / UnitTestFrameworkPkg / Library / UnitTestUefiBootServicesTableLib / UnitTestUefiBootServicesTableLibProtocol.c
1 /** @file
2 Implementation of protocol related services in the UEFI Boot Services table for use in unit tests.
3
4 Copyright (c) Microsoft Corporation
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "UnitTestUefiBootServicesTableLibProtocol.h"
10
11 STATIC LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
12 STATIC LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
13 STATIC UINT64 gHandleDatabaseKey = 0;
14 STATIC UINTN mEfiLocateHandleRequest = 0;
15
16 //
17 // Helper Functions
18 //
19
20 /**
21 Check whether a handle is a valid EFI_HANDLE
22
23 @param UserHandle The handle to check
24
25 @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
26 @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
27
28 **/
29 EFI_STATUS
30 UnitTestValidateHandle (
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
51 /**
52 Finds the protocol entry for the requested protocol.
53
54 @param Protocol The ID of the protocol
55 @param Create Create a new entry if not found
56
57 @return Protocol entry
58
59 **/
60 PROTOCOL_ENTRY *
61 UnitTestFindProtocolEntry (
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
116 /**
117 Finds the protocol instance for the requested handle and protocol.
118 Note: This function doesn't do parameters checking, it's caller's responsibility
119 to pass in valid parameters.
120
121 @param Handle The handle to search the protocol on
122 @param Protocol GUID of the protocol
123 @param Interface The interface for the protocol being searched
124
125 @return Protocol instance (NULL: Not found)
126
127 **/
128 PROTOCOL_INTERFACE *
129 UnitTestFindProtocolInterface (
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
166 /**
167 Signal event for every protocol in protocol entry.
168
169 @param ProtEntry Protocol entry
170
171 **/
172 VOID
173 UnitTestNotifyProtocolEntry (
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
186 /**
187 Routine to get the next Handle, when you are searching for all handles.
188
189 @param Position Information about which Handle to seach for.
190 @param Interface Return the interface structure for the matching
191 protocol.
192
193 @return An pointer to IHANDLE if the next Position is not the end of the list.
194 Otherwise,NULL is returned.
195
196 **/
197 IHANDLE *
198 UnitTestGetNextLocateAllHandles (
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
222 /**
223 Routine to get the next Handle, when you are searching for register protocol
224 notifies.
225
226 @param Position Information about which Handle to seach for.
227 @param Interface Return the interface structure for the matching
228 protocol.
229
230 @return An pointer to IHANDLE if the next Position is not the end of the list.
231 Otherwise,NULL is returned.
232
233 **/
234 IHANDLE *
235 UnitTestGetNextLocateByRegisterNotify (
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
270 /**
271 Routine to get the next Handle, when you are searching for a given protocol.
272
273 @param Position Information about which Handle to seach for.
274 @param Interface Return the interface structure for the matching
275 protocol.
276
277 @return An pointer to IHANDLE if the next Position is not the end of the list.
278 Otherwise,NULL is returned.
279
280 **/
281 IHANDLE *
282 UnitTestGetNextLocateByProtocol (
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
328 /**
329 Attempts to disconnect all drivers that are using the protocol interface being queried.
330 If failed, reconnect all drivers disconnected.
331 Note: This function doesn't do parameters checking, it's caller's responsibility
332 to pass in valid parameters.
333
334 @param UserHandle The handle on which the protocol is installed
335 @param Prot The protocol to disconnect drivers from
336
337 @retval EFI_SUCCESS Drivers using the protocol interface are all
338 disconnected
339 @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
340
341 **/
342 EFI_STATUS
343 UnitTestDisconnectControllersUsingProtocolInterface (
344 IN EFI_HANDLE UserHandle,
345 IN PROTOCOL_INTERFACE *Prot
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
402 /**
403 Removes Protocol from the protocol list (but not the handle list).
404
405 @param Handle The handle to remove protocol on.
406 @param Protocol GUID of the protocol to be moved
407 @param Interface The interface of the protocol
408
409 @return Protocol Entry
410
411 **/
412 PROTOCOL_INTERFACE *
413 UnitTestRemoveInterfaceFromProtocol (
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 //
442 RemoveEntryList (&Prot->ByProtocol);
443 }
444
445 return Prot;
446 }
447
448 //
449 // Boot Services Function Implementation
450 //
451
452 /**
453 Locate a certain GUID protocol interface in a Handle's protocols.
454
455 @param UserHandle The handle to obtain the protocol interface on
456 @param Protocol The GUID of the protocol
457
458 @return The requested protocol interface for the handle
459
460 **/
461 PROTOCOL_INTERFACE *
462 UnitTestGetProtocolInterface (
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
494 /**
495 Installs a protocol interface into the boot services environment.
496
497 @param UserHandle The handle to install the protocol handler on,
498 or NULL if a new handle is to be allocated
499 @param Protocol The protocol to add to the handle
500 @param InterfaceType Indicates whether Interface is supplied in
501 native form.
502 @param Interface The interface for the protocol being added
503 @param Notify indicates whether notify the notification list
504 for this protocol
505
506 @retval EFI_INVALID_PARAMETER Invalid parameter
507 @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
508 @retval EFI_SUCCESS Protocol interface successfully installed
509
510 **/
511 EFI_STATUS
512 UnitTestInstallProtocolInterfaceNotify (
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 //
623 InitializeListHead (&Prot->OpenList);
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
647 Done:
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
667 /**
668 Wrapper function to UnitTestInstallProtocolInterfaceNotify. This is the public API which
669 Calls the private one which contains a BOOLEAN parameter for notifications
670
671 @param UserHandle The handle to install the protocol handler on,
672 or NULL if a new handle is to be allocated
673 @param Protocol The protocol to add to the handle
674 @param InterfaceType Indicates whether Interface is supplied in
675 native form.
676 @param Interface The interface for the protocol being added
677
678 @return Status code
679
680 **/
681 EFI_STATUS
682 EFIAPI
683 UnitTestInstallProtocolInterface (
684 IN OUT EFI_HANDLE *UserHandle,
685 IN EFI_GUID *Protocol,
686 IN EFI_INTERFACE_TYPE InterfaceType,
687 IN VOID *Interface
688 )
689 {
690 return UnitTestInstallProtocolInterfaceNotify (
691 UserHandle,
692 Protocol,
693 InterfaceType,
694 Interface,
695 TRUE
696 );
697 }
698
699 /**
700 Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
701
702 @param UserHandle Handle on which the interface is to be
703 reinstalled
704 @param Protocol The numeric ID of the interface
705 @param OldInterface A pointer to the old interface
706 @param NewInterface A pointer to the new interface
707
708 @retval EFI_SUCCESS The protocol interface was installed
709 @retval EFI_NOT_FOUND The OldInterface on the handle was not found
710 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
711
712 **/
713 EFI_STATUS
714 EFIAPI
715 UnitTestReinstallProtocolInterface (
716 IN EFI_HANDLE UserHandle,
717 IN EFI_GUID *Protocol,
718 IN VOID *OldInterface,
719 IN VOID *NewInterface
720 )
721 {
722 return EFI_NOT_AVAILABLE_YET;
723 }
724
725 /**
726 Uninstalls all instances of a protocol:interfacer from a handle.
727 If the last protocol interface is remove from the handle, the
728 handle is freed.
729
730 @param UserHandle The handle to remove the protocol handler from
731 @param Protocol The protocol, of protocol:interface, to remove
732 @param Interface The interface, of protocol:interface, to remove
733
734 @retval EFI_INVALID_PARAMETER Protocol is NULL.
735 @retval EFI_SUCCESS Protocol interface successfully uninstalled.
736
737 **/
738 EFI_STATUS
739 EFIAPI
740 UnitTestUninstallProtocolInterface (
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 //
777 Status = UnitTestDisconnectControllersUsingProtocolInterface (
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
824 Done:
825 return Status;
826 }
827
828 /**
829 Queries a handle to determine if it supports a specified protocol.
830
831 @param UserHandle The handle being queried.
832 @param Protocol The published unique identifier of the protocol.
833 @param Interface Supplies the address where a pointer to the
834 corresponding Protocol Interface is returned.
835
836 @return The requested protocol interface for the handle
837
838 **/
839 EFI_STATUS
840 EFIAPI
841 UnitTestHandleProtocol (
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,
851 gImageHandle,
852 NULL,
853 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
854 );
855 }
856
857 /**
858 Add a new protocol notification record for the request protocol.
859
860 @param Protocol The requested protocol to add the notify
861 registration
862 @param Event The event to signal
863 @param Registration Returns the registration record
864
865 @retval EFI_INVALID_PARAMETER Invalid parameter
866 @retval EFI_SUCCESS Successfully returned the registration record
867 that has been added
868
869 **/
870 EFI_STATUS
871 EFIAPI
872 UnitTestRegisterProtocolNotify (
873 IN EFI_GUID *Protocol,
874 IN EFI_EVENT Event,
875 OUT VOID **Registration
876 )
877 {
878 return EFI_NOT_AVAILABLE_YET;
879 }
880
881 /**
882 Locates the requested handle(s) and returns them in Buffer.
883
884 @param SearchType The type of search to perform to locate the
885 handles
886 @param Protocol The protocol to search for
887 @param SearchKey Dependant on SearchType
888 @param BufferSize On input the size of Buffer. On output the
889 size of data returned.
890 @param Buffer The buffer to return the results in
891
892 @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
893 returned in BufferSize.
894 @retval EFI_INVALID_PARAMETER Invalid parameter
895 @retval EFI_SUCCESS Successfully found the requested handle(s) and
896 returns them in Buffer.
897
898 **/
899 EFI_STATUS
900 EFIAPI
901 UnitTestLocateHandle (
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:
944 GetNext = UnitTestGetNextLocateAllHandles;
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
956 GetNext = UnitTestGetNextLocateByRegisterNotify;
957 break;
958
959 case ByProtocol:
960 GetNext = UnitTestGetNextLocateByProtocol;
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
1043 /**
1044 Locates the handle to a device on the device path that best matches the specified protocol.
1045
1046 @param Protocol The protocol to search for.
1047 @param DevicePath On input, a pointer to a pointer to the device
1048 path. On output, the device path pointer is
1049 modified to point to the remaining part of the
1050 devicepath.
1051 @param Device A pointer to the returned device handle.
1052
1053 @retval EFI_SUCCESS The resulting handle was returned.
1054 @retval EFI_NOT_FOUND No handles matched the search.
1055 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
1056
1057 **/
1058 EFI_STATUS
1059 EFIAPI
1060 UnitTestLocateDevicePath (
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
1069 /**
1070 Boot Service called to add, modify, or remove a system configuration table from
1071 the EFI System Table.
1072
1073 @param Guid Pointer to the GUID for the entry to add, update, or
1074 remove
1075 @param Table Pointer to the configuration table for the entry to add,
1076 update, or remove, may be NULL.
1077
1078 @return EFI_SUCCESS Guid, Table pair added, updated, or removed.
1079 @return EFI_INVALID_PARAMETER Input GUID not valid.
1080 @return EFI_NOT_FOUND Attempted to delete non-existant entry
1081 @return EFI_OUT_OF_RESOURCES Not enough memory available
1082
1083 **/
1084 EFI_STATUS
1085 EFIAPI
1086 UnitTestInstallConfigurationTable (
1087 IN EFI_GUID *Guid,
1088 IN VOID *Table
1089 )
1090 {
1091 return EFI_NOT_AVAILABLE_YET;
1092 }
1093
1094 /**
1095 Locates the installed protocol handler for the handle, and
1096 invokes it to obtain the protocol interface. Usage information
1097 is registered in the protocol data base.
1098
1099 @param UserHandle The handle to obtain the protocol interface on
1100 @param Protocol The ID of the protocol
1101 @param Interface The location to return the protocol interface
1102 @param ImageHandle The handle of the Image that is opening the
1103 protocol interface specified by Protocol and
1104 Interface.
1105 @param ControllerHandle The controller handle that is requiring this
1106 interface.
1107 @param Attributes The open mode of the protocol interface
1108 specified by Handle and Protocol.
1109
1110 @retval EFI_INVALID_PARAMETER Protocol is NULL.
1111 @retval EFI_SUCCESS Get the protocol interface.
1112
1113 **/
1114 EFI_STATUS
1115 EFIAPI
1116 UnitTestOpenProtocol (
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
1310 Done:
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
1343 /**
1344 Closes a protocol on a handle that was opened using OpenProtocol().
1345
1346 @param UserHandle The handle for the protocol interface that was
1347 previously opened with OpenProtocol(), and is
1348 now being closed.
1349 @param Protocol The published unique identifier of the protocol.
1350 It is the caller's responsibility to pass in a
1351 valid GUID.
1352 @param AgentHandle The handle of the agent that is closing the
1353 protocol interface.
1354 @param ControllerHandle If the agent that opened a protocol is a driver
1355 that follows the EFI Driver Model, then this
1356 parameter is the controller handle that required
1357 the protocol interface. If the agent does not
1358 follow the EFI Driver Model, then this parameter
1359 is optional and may be NULL.
1360
1361 @retval EFI_SUCCESS The protocol instance was closed.
1362 @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
1363 valid EFI_HANDLE.
1364 @retval EFI_NOT_FOUND Can not find the specified protocol or
1365 AgentHandle.
1366
1367 **/
1368 EFI_STATUS
1369 EFIAPI
1370 UnitTestCloseProtocol (
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
1380 /**
1381 Return information about Opened protocols in the system
1382
1383 @param UserHandle The handle to close the protocol interface on
1384 @param Protocol The ID of the protocol
1385 @param EntryBuffer A pointer to a buffer of open protocol
1386 information in the form of
1387 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
1388 @param EntryCount Number of EntryBuffer entries
1389
1390 **/
1391 EFI_STATUS
1392 EFIAPI
1393 UnitTestOpenProtocolInformation (
1394 IN EFI_HANDLE UserHandle,
1395 IN EFI_GUID *Protocol,
1396 OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
1397 OUT UINTN *EntryCount
1398 )
1399 {
1400 return EFI_NOT_AVAILABLE_YET;
1401 }
1402
1403 /**
1404 Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
1405 from pool.
1406
1407 @param UserHandle The handle from which to retrieve the list of
1408 protocol interface GUIDs.
1409 @param ProtocolBuffer A pointer to the list of protocol interface GUID
1410 pointers that are installed on Handle.
1411 @param ProtocolBufferCount A pointer to the number of GUID pointers present
1412 in ProtocolBuffer.
1413
1414 @retval EFI_SUCCESS The list of protocol interface GUIDs installed
1415 on Handle was returned in ProtocolBuffer. The
1416 number of protocol interface GUIDs was returned
1417 in ProtocolBufferCount.
1418 @retval EFI_INVALID_PARAMETER Handle is NULL.
1419 @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
1420 @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
1421 @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
1422 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1423 results.
1424
1425 **/
1426 EFI_STATUS
1427 EFIAPI
1428 UnitTestProtocolsPerHandle (
1429 IN EFI_HANDLE UserHandle,
1430 OUT EFI_GUID ***ProtocolBuffer,
1431 OUT UINTN *ProtocolBufferCount
1432 )
1433 {
1434 return EFI_NOT_AVAILABLE_YET;
1435 }
1436
1437 /**
1438 Function returns an array of handles that support the requested protocol
1439 in a buffer allocated from pool. This is a version of UnitTestLocateHandle()
1440 that allocates a buffer for the caller.
1441
1442 @param SearchType Specifies which handle(s) are to be returned.
1443 @param Protocol Provides the protocol to search by. This
1444 parameter is only valid for SearchType
1445 ByProtocol.
1446 @param SearchKey Supplies the search key depending on the
1447 SearchType.
1448 @param NumberHandles The number of handles returned in Buffer.
1449 @param Buffer A pointer to the buffer to return the requested
1450 array of handles that support Protocol.
1451
1452 @retval EFI_SUCCESS The result array of handles was returned.
1453 @retval EFI_NOT_FOUND No handles match the search.
1454 @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
1455 matching results.
1456 @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
1457
1458 **/
1459 EFI_STATUS
1460 EFIAPI
1461 UnitTestLocateHandleBuffer (
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
1525 /**
1526 Return the first Protocol Interface that matches the Protocol GUID. If
1527 Registration is passed in, return a Protocol Instance that was just add
1528 to the system. If Registration is NULL return the first Protocol Interface
1529 you find.
1530
1531 @param Protocol The protocol to search for
1532 @param Registration Optional Registration Key returned from
1533 RegisterProtocolNotify()
1534 @param Interface Return the Protocol interface (instance).
1535
1536 @retval EFI_SUCCESS If a valid Interface is returned
1537 @retval EFI_INVALID_PARAMETER Invalid parameter
1538 @retval EFI_NOT_FOUND Protocol interface not found
1539
1540 **/
1541 EFI_STATUS
1542 EFIAPI
1543 UnitTestLocateProtocol (
1544 IN EFI_GUID *Protocol,
1545 IN VOID *Registration OPTIONAL,
1546 OUT VOID **Interface
1547 )
1548 {
1549 return EFI_NOT_AVAILABLE_YET;
1550 }
1551
1552 /**
1553 Installs a list of protocol interface into the boot services environment.
1554 This function calls InstallProtocolInterface() in a loop. If any error
1555 occurs all the protocols added by this function are removed. This is
1556 basically a lib function to save space.
1557
1558 @param Handle The handle to install the protocol handlers on,
1559 or NULL if a new handle is to be allocated
1560 @param ... EFI_GUID followed by protocol instance. A NULL
1561 terminates the list. The pairs are the
1562 arguments to InstallProtocolInterface(). All the
1563 protocols are added to Handle.
1564
1565 @retval EFI_SUCCESS All the protocol interface was installed.
1566 @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
1567 @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
1568 the handle database.
1569 @retval EFI_INVALID_PARAMETER Handle is NULL.
1570 @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
1571
1572 **/
1573 EFI_STATUS
1574 EFIAPI
1575 UnitTestInstallMultipleProtocolInterfaces (
1576 IN OUT EFI_HANDLE *Handle,
1577 ...
1578 )
1579 {
1580 return EFI_NOT_AVAILABLE_YET;
1581 }
1582
1583 /**
1584 Uninstalls a list of protocol interface in the boot services environment.
1585 This function calls UninstallProtocolInterface() in a loop. This is
1586 basically a lib function to save space.
1587
1588 @param Handle The handle to uninstall the protocol
1589 @param ... EFI_GUID followed by protocol instance. A NULL
1590 terminates the list. The pairs are the
1591 arguments to UninstallProtocolInterface(). All
1592 the protocols are added to Handle.
1593
1594 @return Status code
1595
1596 **/
1597 EFI_STATUS
1598 EFIAPI
1599 UnitTestUninstallMultipleProtocolInterfaces (
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 }