3 Copyright (c) 2005 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
24 #include <Protocol/ServiceBinding.h>
25 #include <Protocol/SimpleNetwork.h>
26 #include <Protocol/LoadedImage.h>
27 #include <Protocol/NicIp4Config.h>
28 #include <Protocol/ComponentName.h>
29 #include <Protocol/ComponentName2.h>
31 #include <Library/NetLib.h>
32 #include <Library/BaseLib.h>
33 #include <Library/DebugLib.h>
34 #include <Library/BaseMemoryLib.h>
35 #include <Library/UefiBootServicesTableLib.h>
36 #include <Library/UefiRuntimeServicesTableLib.h>
37 #include <Library/UefiLib.h>
38 #include <Library/MemoryAllocationLib.h>
41 EFI_DPC_PROTOCOL
*mDpc
= NULL
;
44 // All the supported IP4 maskes in host byte order.
46 IP4_ADDR mIp4AllMasks
[IP4_MASK_NUM
] = {
85 EFI_IPv4_ADDRESS mZeroIp4Addr
= {{0, 0, 0, 0}};
88 Converts the low nibble of a byte to hex unicode character.
90 @param Nibble lower nibble of a byte.
92 @return Hex unicode character.
102 // This library interface is simply obsolete.
103 // Include the source code to user code.
108 return (CHAR16
)(Nibble
+ L
'0');
111 return (CHAR16
)(Nibble
- 0xA + L
'A');
115 Return the length of the mask. If the mask is invalid,
116 return the invalid length 33, which is IP4_MASK_NUM.
117 NetMask is in the host byte order.
119 @param NetMask The netmask to get the length from
121 @return The length of the netmask, IP4_MASK_NUM if the mask isn't
132 for (Index
= 0; Index
< IP4_MASK_NUM
; Index
++) {
133 if (NetMask
== mIp4AllMasks
[Index
]) {
144 Return the class of the address, such as class a, b, c.
145 Addr is in host byte order.
147 @param Addr The address to get the class from
149 @return IP address class, such as IP4_ADDR_CLASSA
159 ByteOne
= (UINT8
) (Addr
>> 24);
161 if ((ByteOne
& 0x80) == 0) {
162 return IP4_ADDR_CLASSA
;
164 } else if ((ByteOne
& 0xC0) == 0x80) {
165 return IP4_ADDR_CLASSB
;
167 } else if ((ByteOne
& 0xE0) == 0xC0) {
168 return IP4_ADDR_CLASSC
;
170 } else if ((ByteOne
& 0xF0) == 0xE0) {
171 return IP4_ADDR_CLASSD
;
174 return IP4_ADDR_CLASSE
;
181 Check whether the IP is a valid unicast address according to
182 the netmask. If NetMask is zero, use the IP address's class to
183 get the default mask.
185 @param Ip The IP to check againist
186 @param NetMask The mask of the IP
188 @return TRUE if IP is a valid unicast address on the network, otherwise FALSE
199 Class
= NetGetIpClass (Ip
);
201 if ((Ip
== 0) || (Class
>= IP4_ADDR_CLASSD
)) {
206 NetMask
= mIp4AllMasks
[Class
<< 3];
209 if (((Ip
&~NetMask
) == ~NetMask
) || ((Ip
&~NetMask
) == 0)) {
218 Initialize a random seed using current time.
222 @return The random seed initialized with current time.
233 gRT
->GetTime (&Time
, NULL
);
234 Seed
= (~Time
.Hour
<< 24 | Time
.Day
<< 16 | Time
.Minute
<< 8 | Time
.Second
);
235 Seed
^= Time
.Nanosecond
;
236 Seed
^= Time
.Year
<< 7;
243 Extract a UINT32 from a byte stream, then convert it to host
244 byte order. Use this function to avoid alignment error.
246 @param Buf The buffer to extract the UINT32.
248 @return The UINT32 extracted.
258 NetCopyMem (&Value
, Buf
, sizeof (UINT32
));
259 return NTOHL (Value
);
264 Put a UINT32 to the byte stream. Convert it from host byte order
265 to network byte order before putting.
267 @param Buf The buffer to put the UINT32
268 @param Data The data to put
280 NetCopyMem (Buf
, &Data
, sizeof (UINT32
));
285 Remove the first entry on the list
287 @param Head The list header
289 @return The entry that is removed from the list, NULL if the list is empty.
297 NET_LIST_ENTRY
*First
;
299 ASSERT (Head
!= NULL
);
301 if (NetListIsEmpty (Head
)) {
305 First
= Head
->ForwardLink
;
306 Head
->ForwardLink
= First
->ForwardLink
;
307 First
->ForwardLink
->BackLink
= Head
;
310 First
->ForwardLink
= (LIST_ENTRY
*) NULL
;
311 First
->BackLink
= (LIST_ENTRY
*) NULL
;
319 Remove the last entry on the list
321 @param Head The list head
323 @return The entry that is removed from the list, NULL if the list is empty.
331 NET_LIST_ENTRY
*Last
;
333 ASSERT (Head
!= NULL
);
335 if (NetListIsEmpty (Head
)) {
339 Last
= Head
->BackLink
;
340 Head
->BackLink
= Last
->BackLink
;
341 Last
->BackLink
->ForwardLink
= Head
;
344 Last
->ForwardLink
= (LIST_ENTRY
*) NULL
;
345 Last
->BackLink
= (LIST_ENTRY
*) NULL
;
353 Insert the NewEntry after the PrevEntry
355 @param PrevEntry The previous entry to insert after
356 @param NewEntry The new entry to insert
363 IN NET_LIST_ENTRY
*PrevEntry
,
364 IN NET_LIST_ENTRY
*NewEntry
367 NewEntry
->BackLink
= PrevEntry
;
368 NewEntry
->ForwardLink
= PrevEntry
->ForwardLink
;
369 PrevEntry
->ForwardLink
->BackLink
= NewEntry
;
370 PrevEntry
->ForwardLink
= NewEntry
;
375 Insert the NewEntry before the PostEntry
377 @param PostEntry The entry to insert before
378 @param NewEntry The new entry to insert
384 NetListInsertBefore (
385 IN NET_LIST_ENTRY
*PostEntry
,
386 IN NET_LIST_ENTRY
*NewEntry
389 NewEntry
->ForwardLink
= PostEntry
;
390 NewEntry
->BackLink
= PostEntry
->BackLink
;
391 PostEntry
->BackLink
->ForwardLink
= NewEntry
;
392 PostEntry
->BackLink
= NewEntry
;
397 Initialize the netmap. Netmap is a reposity to keep the <Key, Value> pairs.
399 @param Map The netmap to initialize
409 ASSERT (Map
!= NULL
);
411 NetListInit (&Map
->Used
);
412 NetListInit (&Map
->Recycled
);
418 To clean up the netmap, that is, release allocated memories.
420 @param Map The netmap to clean up.
431 NET_LIST_ENTRY
*Entry
;
432 NET_LIST_ENTRY
*Next
;
434 ASSERT (Map
!= NULL
);
436 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Map
->Used
) {
437 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
439 NetListRemoveEntry (&Item
->Link
);
445 ASSERT ((Map
->Count
== 0) && NetListIsEmpty (&Map
->Used
));
447 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Map
->Recycled
) {
448 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
450 NetListRemoveEntry (&Item
->Link
);
454 ASSERT (NetListIsEmpty (&Map
->Recycled
));
459 Test whether the netmap is empty
461 @param Map The net map to test
463 @return TRUE if the netmap is empty, otherwise FALSE.
471 ASSERT (Map
!= NULL
);
472 return (BOOLEAN
) (Map
->Count
== 0);
477 Return the number of the <Key, Value> pairs in the netmap.
479 @param Map The netmap to get the entry number
481 @return The entry number in the netmap.
494 Allocate an item for the netmap. It will try to allocate
495 a batch of items and return one.
497 @param Map The netmap to allocate item for
499 @return The allocated item or NULL
509 NET_LIST_ENTRY
*Head
;
512 ASSERT (Map
!= NULL
);
514 Head
= &Map
->Recycled
;
516 if (NetListIsEmpty (Head
)) {
517 for (Index
= 0; Index
< NET_MAP_INCREAMENT
; Index
++) {
518 Item
= NetAllocatePool (sizeof (NET_MAP_ITEM
));
528 NetListInsertHead (Head
, &Item
->Link
);
532 Item
= NET_LIST_HEAD (Head
, NET_MAP_ITEM
, Link
);
533 NetListRemoveHead (Head
);
540 Allocate an item to save the <Key, Value> pair to the head of the netmap.
542 @param Map The netmap to insert into
543 @param Key The user's key
544 @param Value The user's value for the key
546 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item
547 @retval EFI_SUCCESS The item is inserted to the head
554 IN VOID
*Value OPTIONAL
559 ASSERT (Map
!= NULL
);
561 Item
= NetMapAllocItem (Map
);
564 return EFI_OUT_OF_RESOURCES
;
569 NetListInsertHead (&Map
->Used
, &Item
->Link
);
577 Allocate an item to save the <Key, Value> pair to the tail of the netmap.
579 @param Map The netmap to insert into
580 @param Key The user's key
581 @param Value The user's value for the key
583 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the item
584 @retval EFI_SUCCESS The item is inserted to the tail
591 IN VOID
*Value OPTIONAL
596 ASSERT (Map
!= NULL
);
598 Item
= NetMapAllocItem (Map
);
601 return EFI_OUT_OF_RESOURCES
;
606 NetListInsertTail (&Map
->Used
, &Item
->Link
);
615 Check whther the item is in the Map
617 @param Map The netmap to search within
618 @param Item The item to search
620 @return TRUE if the item is in the netmap, otherwise FALSE.
627 IN NET_MAP_ITEM
*Item
630 NET_LIST_ENTRY
*ListEntry
;
632 NET_LIST_FOR_EACH (ListEntry
, &Map
->Used
) {
633 if (ListEntry
== &Item
->Link
) {
643 Find the key in the netmap
645 @param Map The netmap to search within
646 @param Key The key to search
648 @return The point to the item contains the Key, or NULL if Key isn't in the map.
657 NET_LIST_ENTRY
*Entry
;
660 ASSERT (Map
!= NULL
);
662 NET_LIST_FOR_EACH (Entry
, &Map
->Used
) {
663 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
665 if (Item
->Key
== Key
) {
675 Remove the item from the netmap
677 @param Map The netmap to remove the item from
678 @param Item The item to remove
679 @param Value The variable to receive the value if not NULL
681 @return The key of the removed item.
687 IN NET_MAP_ITEM
*Item
,
688 OUT VOID
**Value OPTIONAL
691 ASSERT ((Map
!= NULL
) && (Item
!= NULL
));
692 ASSERT (NetItemInMap (Map
, Item
));
694 NetListRemoveEntry (&Item
->Link
);
696 NetListInsertHead (&Map
->Recycled
, &Item
->Link
);
699 *Value
= Item
->Value
;
707 Remove the first entry on the netmap
709 @param Map The netmap to remove the head from
710 @param Value The variable to receive the value if not NULL
712 @return The key of the item removed
718 OUT VOID
**Value OPTIONAL
724 // Often, it indicates a programming error to remove
725 // the first entry in an empty list
727 ASSERT (Map
&& !NetListIsEmpty (&Map
->Used
));
729 Item
= NET_LIST_HEAD (&Map
->Used
, NET_MAP_ITEM
, Link
);
730 NetListRemoveEntry (&Item
->Link
);
732 NetListInsertHead (&Map
->Recycled
, &Item
->Link
);
735 *Value
= Item
->Value
;
743 Remove the last entry on the netmap
745 @param Map The netmap to remove the tail from
746 @param Value The variable to receive the value if not NULL
748 @return The key of the item removed
754 OUT VOID
**Value OPTIONAL
760 // Often, it indicates a programming error to remove
761 // the last entry in an empty list
763 ASSERT (Map
&& !NetListIsEmpty (&Map
->Used
));
765 Item
= NET_LIST_TAIL (&Map
->Used
, NET_MAP_ITEM
, Link
);
766 NetListRemoveEntry (&Item
->Link
);
768 NetListInsertHead (&Map
->Recycled
, &Item
->Link
);
771 *Value
= Item
->Value
;
779 Iterate through the netmap and call CallBack for each item. It will
780 contiue the traverse if CallBack returns EFI_SUCCESS, otherwise, break
781 from the loop. It returns the CallBack's last return value. This
782 function is delete safe for the current item.
784 @param Map The Map to iterate through
785 @param CallBack The callback function to call for each item.
786 @param Arg The opaque parameter to the callback
788 @return It returns the CallBack's last return value.
794 IN NET_MAP_CALLBACK CallBack
,
799 NET_LIST_ENTRY
*Entry
;
800 NET_LIST_ENTRY
*Next
;
801 NET_LIST_ENTRY
*Head
;
805 ASSERT ((Map
!= NULL
) && (CallBack
!= NULL
));
809 if (NetListIsEmpty (Head
)) {
813 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, Head
) {
814 Item
= NET_LIST_USER_STRUCT (Entry
, NET_MAP_ITEM
, Link
);
815 Result
= CallBack (Map
, Item
, Arg
);
817 if (EFI_ERROR (Result
)) {
827 This is the default unload handle for all the network drivers.
829 @param ImageHandle The drivers' driver image.
831 @retval EFI_SUCCESS The image is unloaded.
832 @retval Others Failed to unload the image.
837 NetLibDefaultUnload (
838 IN EFI_HANDLE ImageHandle
842 EFI_HANDLE
*DeviceHandleBuffer
;
843 UINTN DeviceHandleCount
;
845 EFI_DRIVER_BINDING_PROTOCOL
*DriverBinding
;
846 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
847 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
850 // Get the list of all the handles in the handle database.
851 // If there is an error getting the list, then the unload
854 Status
= gBS
->LocateHandleBuffer (
862 if (EFI_ERROR (Status
)) {
867 // Disconnect the driver specified by ImageHandle from all
868 // the devices in the handle database.
870 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
871 Status
= gBS
->DisconnectController (
872 DeviceHandleBuffer
[Index
],
879 // Uninstall all the protocols installed in the driver entry point
881 for (Index
= 0; Index
< DeviceHandleCount
; Index
++) {
882 Status
= gBS
->HandleProtocol (
883 DeviceHandleBuffer
[Index
],
884 &gEfiDriverBindingProtocolGuid
,
885 (VOID
**) &DriverBinding
888 if (EFI_ERROR (Status
)) {
892 if (DriverBinding
->ImageHandle
!= ImageHandle
) {
896 gBS
->UninstallProtocolInterface (
898 &gEfiDriverBindingProtocolGuid
,
901 Status
= gBS
->HandleProtocol (
902 DeviceHandleBuffer
[Index
],
903 &gEfiComponentNameProtocolGuid
,
904 (VOID
**) &ComponentName
906 if (!EFI_ERROR (Status
)) {
907 gBS
->UninstallProtocolInterface (
909 &gEfiComponentNameProtocolGuid
,
914 Status
= gBS
->HandleProtocol (
915 DeviceHandleBuffer
[Index
],
916 &gEfiComponentName2ProtocolGuid
,
917 (VOID
**) &ComponentName2
919 if (!EFI_ERROR (Status
)) {
920 gBS
->UninstallProtocolInterface (
922 &gEfiComponentName2ProtocolGuid
,
929 // Free the buffer containing the list of handles from the handle database
931 if (DeviceHandleBuffer
!= NULL
) {
932 gBS
->FreePool (DeviceHandleBuffer
);
941 Create a child of the service that is identified by ServiceBindingGuid.
943 @param Controller The controller which has the service installed.
944 @param Image The image handle used to open service.
945 @param ServiceBindingGuid The service's Guid.
946 @param ChildHandle The handle to receive the create child
948 @retval EFI_SUCCESS The child is successfully created.
949 @retval Others Failed to create the child.
953 NetLibCreateServiceChild (
954 IN EFI_HANDLE Controller
,
956 IN EFI_GUID
*ServiceBindingGuid
,
957 OUT EFI_HANDLE
*ChildHandle
961 EFI_SERVICE_BINDING_PROTOCOL
*Service
;
964 ASSERT ((ServiceBindingGuid
!= NULL
) && (ChildHandle
!= NULL
));
967 // Get the ServiceBinding Protocol
969 Status
= gBS
->OpenProtocol (
975 EFI_OPEN_PROTOCOL_GET_PROTOCOL
978 if (EFI_ERROR (Status
)) {
985 Status
= Service
->CreateChild (Service
, ChildHandle
);
991 Destory a child of the service that is identified by ServiceBindingGuid.
993 @param Controller The controller which has the service installed.
994 @param Image The image handle used to open service.
995 @param ServiceBindingGuid The service's Guid.
996 @param ChildHandle The child to destory
998 @retval EFI_SUCCESS The child is successfully destoried.
999 @retval Others Failed to destory the child.
1003 NetLibDestroyServiceChild (
1004 IN EFI_HANDLE Controller
,
1005 IN EFI_HANDLE Image
,
1006 IN EFI_GUID
*ServiceBindingGuid
,
1007 IN EFI_HANDLE ChildHandle
1011 EFI_SERVICE_BINDING_PROTOCOL
*Service
;
1013 ASSERT (ServiceBindingGuid
!= NULL
);
1016 // Get the ServiceBinding Protocol
1018 Status
= gBS
->OpenProtocol (
1024 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1027 if (EFI_ERROR (Status
)) {
1032 // destory the child
1034 Status
= Service
->DestroyChild (Service
, ChildHandle
);
1040 Convert the mac address of the simple network protocol installed on
1041 SnpHandle to a unicode string. Callers are responsible for freeing the
1044 @param SnpHandle The handle where the simple network protocol is
1046 @param ImageHandle The image handle used to act as the agent handle to
1047 get the simple network protocol.
1048 @param MacString The pointer to store the address of the string
1049 representation of the mac address.
1051 @retval EFI_OUT_OF_RESOURCES There are not enough memory resource.
1052 @retval other Failed to open the simple network protocol.
1056 NetLibGetMacString (
1057 IN EFI_HANDLE SnpHandle
,
1058 IN EFI_HANDLE ImageHandle
,
1059 IN OUT CHAR16
**MacString
1063 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1064 EFI_SIMPLE_NETWORK_MODE
*Mode
;
1071 // Get the Simple Network protocol from the SnpHandle.
1073 Status
= gBS
->OpenProtocol (
1075 &gEfiSimpleNetworkProtocolGuid
,
1079 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1081 if (EFI_ERROR (Status
)) {
1088 // It takes 2 unicode characters to represent a 1 byte binary buffer.
1089 // Plus one unicode character for the null-terminator.
1091 MacAddress
= NetAllocatePool ((2 * Mode
->HwAddressSize
+ 1) * sizeof (CHAR16
));
1092 if (MacAddress
== NULL
) {
1093 return EFI_OUT_OF_RESOURCES
;
1097 // Convert the mac address into a unicode string.
1099 for (Index
= 0; Index
< Mode
->HwAddressSize
; Index
++) {
1100 MacAddress
[Index
* 2] = NibbleToHexChar ((UINT8
) (Mode
->CurrentAddress
.Addr
[Index
] >> 4));
1101 MacAddress
[Index
* 2 + 1] = NibbleToHexChar (Mode
->CurrentAddress
.Addr
[Index
]);
1104 MacAddress
[Mode
->HwAddressSize
* 2] = L
'\0';
1106 *MacString
= MacAddress
;
1112 Check the default address used by the IPv4 driver is static or dynamic (acquired
1115 @param Controller The controller handle which has the NIC Ip4 Config Protocol
1116 relative with the default address to judge.
1118 @retval TRUE If the default address is static.
1119 @retval FALSE If the default address is acquired from DHCP.
1124 NetLibDefaultAddressIsStatic (
1125 IN EFI_HANDLE Controller
1129 EFI_NIC_IP4_CONFIG_PROTOCOL
*NicIp4
;
1131 NIC_IP4_CONFIG_INFO
*ConfigInfo
;
1134 Status
= gBS
->HandleProtocol (
1136 &gEfiNicIp4ConfigProtocolGuid
,
1139 if (EFI_ERROR (Status
)) {
1144 Status
= NicIp4
->GetInfo (NicIp4
, &Len
, NULL
);
1145 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1149 ConfigInfo
= NetAllocatePool (Len
);
1150 if (ConfigInfo
== NULL
) {
1155 Status
= NicIp4
->GetInfo (NicIp4
, &Len
, ConfigInfo
);
1156 if (EFI_ERROR (Status
)) {
1160 IsStatic
= (BOOLEAN
) (ConfigInfo
->Source
== IP4_CONFIG_SOURCE_STATIC
);
1164 NetFreePool (ConfigInfo
);
1170 Create an IPv4 device path node.
1172 @param Node Pointer to the IPv4 device path node.
1173 @param Controller The handle where the NIC IP4 config protocol resides.
1174 @param LocalIp The local IPv4 address.
1175 @param LocalPort The local port.
1176 @param RemoteIp The remote IPv4 address.
1177 @param RemotePort The remote port.
1178 @param Protocol The protocol type in the IP header.
1179 @param UseDefaultAddress Whether this instance is using default address or not.
1184 NetLibCreateIPv4DPathNode (
1185 IN OUT IPv4_DEVICE_PATH
*Node
,
1186 IN EFI_HANDLE Controller
,
1187 IN IP4_ADDR LocalIp
,
1188 IN UINT16 LocalPort
,
1189 IN IP4_ADDR RemoteIp
,
1190 IN UINT16 RemotePort
,
1192 IN BOOLEAN UseDefaultAddress
1195 Node
->Header
.Type
= MESSAGING_DEVICE_PATH
;
1196 Node
->Header
.SubType
= MSG_IPv4_DP
;
1197 SetDevicePathNodeLength (&Node
->Header
, 19);
1199 NetCopyMem (&Node
->LocalIpAddress
, &LocalIp
, sizeof (EFI_IPv4_ADDRESS
));
1200 NetCopyMem (&Node
->RemoteIpAddress
, &RemoteIp
, sizeof (EFI_IPv4_ADDRESS
));
1202 Node
->LocalPort
= LocalPort
;
1203 Node
->RemotePort
= RemotePort
;
1205 Node
->Protocol
= Protocol
;
1207 if (!UseDefaultAddress
) {
1208 Node
->StaticIpAddress
= TRUE
;
1210 Node
->StaticIpAddress
= NetLibDefaultAddressIsStatic (Controller
);
1216 Find the UNDI/SNP handle from controller and protocol GUID.
1217 For example, IP will open a MNP child to transmit/receive
1218 packets, when MNP is stopped, IP should also be stopped. IP
1219 needs to find its own private data which is related the IP's
1220 service binding instance that is install on UNDI/SNP handle.
1221 Now, the controller is either a MNP or ARP child handle. But
1222 IP opens these handle BY_DRIVER, use that info, we can get the
1225 @param Controller Then protocol handle to check
1226 @param ProtocolGuid The protocol that is related with the handle.
1228 @return The UNDI/SNP handle or NULL.
1232 NetLibGetNicHandle (
1233 IN EFI_HANDLE Controller
,
1234 IN EFI_GUID
*ProtocolGuid
1237 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenBuffer
;
1243 Status
= gBS
->OpenProtocolInformation (
1250 if (EFI_ERROR (Status
)) {
1256 for (Index
= 0; Index
< OpenCount
; Index
++) {
1257 if (OpenBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_DRIVER
) {
1258 Handle
= OpenBuffer
[Index
].ControllerHandle
;
1263 gBS
->FreePool (OpenBuffer
);
1268 Add a Deferred Procedure Call to the end of the DPC queue.
1270 @DpcTpl The EFI_TPL that the DPC should be invoked.
1271 @DpcProcedure Pointer to the DPC's function.
1272 @DpcContext Pointer to the DPC's context. Passed to DpcProcedure
1273 when DpcProcedure is invoked.
1275 @retval EFI_SUCCESS The DPC was queued.
1276 @retval EFI_INVALID_PARAMETER DpcTpl is not a valid EFI_TPL.
1277 DpcProcedure is NULL.
1278 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
1279 add the DPC to the queue.
1285 IN EFI_DPC_PROCEDURE DpcProcedure
,
1286 IN VOID
*DpcContext OPTIONAL
1289 return mDpc
->QueueDpc (mDpc
, DpcTpl
, DpcProcedure
, DpcContext
);
1293 Add a Deferred Procedure Call to the end of the DPC queue.
1295 @retval EFI_SUCCESS One or more DPCs were invoked.
1296 @retval EFI_NOT_FOUND No DPCs were invoked.
1304 return mDpc
->DispatchDpc(mDpc
);
1309 The constructor function caches the pointer to DPC protocol.
1311 The constructor function locates DPC protocol from protocol database.
1312 It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
1314 @param ImageHandle The firmware allocated handle for the EFI image.
1315 @param SystemTable A pointer to the EFI System Table.
1317 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
1323 IN EFI_HANDLE ImageHandle
,
1324 IN EFI_SYSTEM_TABLE
*SystemTable
1329 Status
= gBS
->LocateProtocol (&gEfiDpcProtocolGuid
, NULL
, (VOID
**) &mDpc
);
1330 ASSERT_EFI_ERROR (Status
);
1331 ASSERT (mDpc
!= NULL
);