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.
18 The implementation of the IpIo layer.
25 #include <Protocol/Udp4.h>
27 #include <Library/IpIoLib.h>
28 #include <Library/BaseLib.h>
29 #include <Library/DebugLib.h>
30 #include <Library/UefiBootServicesTableLib.h>
31 #include <Library/MemoryAllocationLib.h>
32 #include <Library/BaseMemoryLib.h>
35 #define NET_PROTO_HDR(Buf, Type) ((Type *) ((Buf)->BlockOp[0].Head))
36 #define ICMP_ERRLEN(IpHdr) \
37 (sizeof(IP4_ICMP_HEAD) + EFI_IP4_HEADER_LEN(IpHdr) + 8)
39 LIST_ENTRY mActiveIpIoList
= {
44 EFI_IP4_CONFIG_DATA mIpIoDefaultIpConfigData
= {
61 ICMP_ERROR_INFO mIcmpErrMap
[10] = {
76 IpIoTransmitHandlerDpc (
89 This function create an ip child ,open the IP protocol, return the opened
90 Ip protocol to Interface.
92 @param ControllerHandle The controller handle.
93 @param ImageHandle The image handle.
94 @param ChildHandle Pointer to the buffer to save the ip child handle.
95 @param Interface Pointer used to get the ip protocol interface.
97 @retval EFI_SUCCESS The ip child is created and the ip protocol
98 interface is retrieved.
99 @retval other The required operation failed.
103 IpIoCreateIpChildOpenProtocol (
104 IN EFI_HANDLE ControllerHandle
,
105 IN EFI_HANDLE ImageHandle
,
106 IN EFI_HANDLE
*ChildHandle
,
113 // Create an ip child.
115 Status
= NetLibCreateServiceChild (
118 &gEfiIp4ServiceBindingProtocolGuid
,
121 if (EFI_ERROR (Status
)) {
126 // Open the ip protocol installed on the *ChildHandle.
128 Status
= gBS
->OpenProtocol (
130 &gEfiIp4ProtocolGuid
,
134 EFI_OPEN_PROTOCOL_BY_DRIVER
136 if (EFI_ERROR (Status
)) {
138 // On failure, destroy the ip child.
140 NetLibDestroyServiceChild (
143 &gEfiIp4ServiceBindingProtocolGuid
,
153 This function close the previously openned ip protocol and destroy the ip child.
155 @param ControllerHandle The controller handle.
156 @param ImageHandle the image handle.
157 @param ChildHandle The child handle of the ip child.
159 @retval EFI_SUCCESS The ip protocol is closed and the relevant ip child
161 @retval other The required operation failed.
165 IpIoCloseProtocolDestroyIpChild (
166 IN EFI_HANDLE ControllerHandle
,
167 IN EFI_HANDLE ImageHandle
,
168 IN EFI_HANDLE ChildHandle
174 // Close the previously openned ip protocol.
178 &gEfiIp4ProtocolGuid
,
184 // Destroy the ip child.
186 Status
= NetLibDestroyServiceChild (
189 &gEfiIp4ServiceBindingProtocolGuid
,
200 @param IpIo Pointer to the IP_IO instance.
201 @param Pkt Pointer to the ICMP packet.
202 @param Session Pointer to the net session of this ICMP packet.
204 @retval EFI_SUCCESS The ICMP packet is handled successfully.
205 @retval EFI_ABORTED This type of ICMP packet is not supported.
212 IN EFI_NET_SESSION_DATA
*Session
215 IP4_ICMP_ERROR_HEAD
*IcmpHdr
;
216 EFI_IP4_HEADER
*IpHdr
;
223 IcmpHdr
= NET_PROTO_HDR (Pkt
, IP4_ICMP_ERROR_HEAD
);
224 IpHdr
= (EFI_IP4_HEADER
*) (&IcmpHdr
->IpHead
);
227 // Check the ICMP packet length.
229 if (Pkt
->TotalSize
< ICMP_ERRLEN (IpHdr
)) {
234 Type
= IcmpHdr
->Head
.Type
;
235 Code
= IcmpHdr
->Head
.Code
;
238 // Analyze the ICMP Error in this ICMP pkt
241 case ICMP_TYPE_UNREACH
:
243 case ICMP_CODE_UNREACH_NET
:
244 case ICMP_CODE_UNREACH_HOST
:
245 case ICMP_CODE_UNREACH_PROTOCOL
:
246 case ICMP_CODE_UNREACH_PORT
:
247 case ICMP_CODE_UNREACH_SRCFAIL
:
248 IcmpErr
= (ICMP_ERROR
) (ICMP_ERR_UNREACH_NET
+ Code
);
252 case ICMP_CODE_UNREACH_NEEDFRAG
:
253 IcmpErr
= ICMP_ERR_MSGSIZE
;
257 case ICMP_CODE_UNREACH_NET_UNKNOWN
:
258 case ICMP_CODE_UNREACH_NET_PROHIB
:
259 case ICMP_CODE_UNREACH_TOSNET
:
260 IcmpErr
= ICMP_ERR_UNREACH_NET
;
264 case ICMP_CODE_UNREACH_HOST_UNKNOWN
:
265 case ICMP_CODE_UNREACH_ISOLATED
:
266 case ICMP_CODE_UNREACH_HOST_PROHIB
:
267 case ICMP_CODE_UNREACH_TOSHOST
:
268 IcmpErr
= ICMP_ERR_UNREACH_HOST
;
280 case ICMP_TYPE_TIMXCEED
:
285 IcmpErr
= (ICMP_ERROR
) (Code
+ ICMP_ERR_TIMXCEED_INTRANS
);
289 case ICMP_TYPE_PARAMPROB
:
294 IcmpErr
= ICMP_ERR_PARAMPROB
;
298 case ICMP_TYPE_SOURCEQUENCH
:
303 IcmpErr
= ICMP_ERR_QUENCH
;
314 // Notify user the ICMP pkt only containing payload except
315 // IP and ICMP header
317 PayLoadHdr
= (UINT8
*) ((UINT8
*) IpHdr
+ EFI_IP4_HEADER_LEN (IpHdr
));
318 TrimBytes
= (UINT32
) (PayLoadHdr
- (UINT8
*) IcmpHdr
);
320 NetbufTrim (Pkt
, TrimBytes
, TRUE
);
322 IpIo
->PktRcvdNotify (EFI_ICMP_ERROR
, IcmpErr
, Session
, Pkt
, IpIo
->RcvdContext
);
329 Ext free function for net buffer. This function is
330 called when the net buffer is freed. It is used to
331 signal the recycle event to notify IP to recycle the
334 @param Event The event to be signaled.
344 gBS
->SignalEvent ((EFI_EVENT
) Event
);
349 Create a send entry to wrap a packet before sending
352 @param IpIo Pointer to the IP_IO instance.
353 @param Pkt Pointer to the packet.
354 @param Sender Pointer to the IP sender.
355 @param NotifyData Pointer to the notify data.
356 @param Dest Pointer to the destination IP address.
357 @param Override Pointer to the overriden IP_IO data.
359 @return Pointer to the data structure created to wrap the packet. If NULL,
360 @return resource limit occurred.
367 IN EFI_IP4_PROTOCOL
*Sender
,
368 IN VOID
*Context OPTIONAL
,
369 IN VOID
*NotifyData OPTIONAL
,
371 IN IP_IO_OVERRIDE
*Override
374 IP_IO_SEND_ENTRY
*SndEntry
;
375 EFI_IP4_COMPLETION_TOKEN
*SndToken
;
376 EFI_IP4_TRANSMIT_DATA
*TxData
;
378 EFI_IP4_OVERRIDE_DATA
*OverrideData
;
379 volatile UINT32 Index
;
382 // Allocate resource for SndEntry
384 SndEntry
= AllocatePool (sizeof (IP_IO_SEND_ENTRY
));
385 if (NULL
== SndEntry
) {
390 // Allocate resource for SndToken
392 SndToken
= AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN
));
393 if (NULL
== SndToken
) {
394 goto ReleaseSndEntry
;
397 Status
= gBS
->CreateEvent (
404 if (EFI_ERROR (Status
)) {
405 goto ReleaseSndToken
;
409 // Allocate resource for TxData
411 TxData
= AllocatePool (
412 sizeof (EFI_IP4_TRANSMIT_DATA
) +
413 sizeof (EFI_IP4_FRAGMENT_DATA
) * (Pkt
->BlockOpNum
- 1)
416 if (NULL
== TxData
) {
421 // Allocate resource for OverrideData if needed
424 if (NULL
!= Override
) {
426 OverrideData
= AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA
));
427 if (NULL
== OverrideData
) {
428 goto ReleaseResource
;
431 // Set the fields of OverrideData
433 CopyMem (OverrideData
, Override
, sizeof (*OverrideData
));
437 // Set the fields of TxData
439 CopyMem (&TxData
->DestinationAddress
, &Dest
, sizeof (EFI_IPv4_ADDRESS
));
440 TxData
->OverrideData
= OverrideData
;
441 TxData
->OptionsLength
= 0;
442 TxData
->OptionsBuffer
= NULL
;
443 TxData
->TotalDataLength
= Pkt
->TotalSize
;
444 TxData
->FragmentCount
= Pkt
->BlockOpNum
;
447 for (Index
= 0; Index
< Pkt
->BlockOpNum
; Index
++) {
448 TxData
->FragmentTable
[Index
].FragmentBuffer
= Pkt
->BlockOp
[Index
].Head
;
449 TxData
->FragmentTable
[Index
].FragmentLength
= Pkt
->BlockOp
[Index
].Size
;
453 // Set the fields of SndToken
455 SndToken
->Packet
.TxData
= TxData
;
458 // Set the fields of SndEntry
460 SndEntry
->IpIo
= IpIo
;
461 SndEntry
->Ip
= Sender
;
462 SndEntry
->Context
= Context
;
463 SndEntry
->NotifyData
= NotifyData
;
468 SndEntry
->SndToken
= SndToken
;
470 InsertTailList (&IpIo
->PendingSndList
, &SndEntry
->Entry
);
475 gBS
->FreePool (TxData
);
478 gBS
->CloseEvent (SndToken
->Event
);
481 gBS
->FreePool (SndToken
);
484 gBS
->FreePool (SndEntry
);
491 Destroy the SndEntry.
493 @param SndEntry Pointer to the send entry to be destroyed.
499 IpIoDestroySndEntry (
500 IN IP_IO_SEND_ENTRY
*SndEntry
503 EFI_IP4_TRANSMIT_DATA
*TxData
;
505 TxData
= SndEntry
->SndToken
->Packet
.TxData
;
507 if (NULL
!= TxData
->OverrideData
) {
508 gBS
->FreePool (TxData
->OverrideData
);
511 gBS
->FreePool (TxData
);
512 NetbufFree (SndEntry
->Pkt
);
513 gBS
->CloseEvent (SndEntry
->SndToken
->Event
);
515 gBS
->FreePool (SndEntry
->SndToken
);
516 RemoveEntryList (&SndEntry
->Entry
);
518 gBS
->FreePool (SndEntry
);
523 Notify function for IP transmit token.
525 @param Context The context passed in by the event notifier.
532 IpIoTransmitHandlerDpc (
537 IP_IO_SEND_ENTRY
*SndEntry
;
539 SndEntry
= (IP_IO_SEND_ENTRY
*) Context
;
541 IpIo
= SndEntry
->IpIo
;
543 if (IpIo
->PktSentNotify
&& SndEntry
->NotifyData
) {
544 IpIo
->PktSentNotify (
545 SndEntry
->SndToken
->Status
,
552 IpIoDestroySndEntry (SndEntry
);
556 Notify function for IP transmit token.
558 @param Event The event signaled.
559 @param Context The context passed in by the event notifier.
567 IpIoTransmitHandler (
573 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
575 NetLibQueueDpc (TPL_CALLBACK
, IpIoTransmitHandlerDpc
, Context
);
580 The dummy handler for the dummy IP receive token.
582 @param Context The context passed in by the event notifier.
589 IpIoDummyHandlerDpc (
593 IP_IO_IP_INFO
*IpInfo
;
594 EFI_IP4_COMPLETION_TOKEN
*DummyToken
;
596 IpInfo
= (IP_IO_IP_INFO
*) Context
;
597 DummyToken
= &(IpInfo
->DummyRcvToken
);
599 if (EFI_ABORTED
== DummyToken
->Status
) {
601 // The reception is actively aborted by the consumer, directly return.
604 } else if (EFI_SUCCESS
== DummyToken
->Status
) {
605 ASSERT (DummyToken
->Packet
.RxData
);
607 gBS
->SignalEvent (DummyToken
->Packet
.RxData
->RecycleSignal
);
610 IpInfo
->Ip
->Receive (IpInfo
->Ip
, DummyToken
);
615 Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK.
617 @param Event The event signaled.
618 @param Context The context passed in by the event notifier.
631 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
633 NetLibQueueDpc (TPL_CALLBACK
, IpIoDummyHandlerDpc
, Context
);
638 Notify function for the IP receive token, used to process
639 the received IP packets.
641 @param Context The context passed in by the event notifier.
648 IpIoListenHandlerDpc (
654 EFI_IP4_RECEIVE_DATA
*RxData
;
655 EFI_IP4_PROTOCOL
*Ip
;
656 EFI_NET_SESSION_DATA Session
;
659 IpIo
= (IP_IO
*) Context
;
662 Status
= IpIo
->RcvToken
.Status
;
663 RxData
= IpIo
->RcvToken
.Packet
.RxData
;
665 if (EFI_ABORTED
== Status
) {
667 // The reception is actively aborted by the consumer, directly return.
672 if (((EFI_SUCCESS
!= Status
) && (EFI_ICMP_ERROR
!= Status
)) || (NULL
== RxData
)) {
674 // Only process the normal packets and the icmp error packets, if RxData is NULL
675 // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
676 // this should be a bug of the low layer (IP).
681 if (NULL
== IpIo
->PktRcvdNotify
) {
685 if ((EFI_IP4 (RxData
->Header
->SourceAddress
) != 0) &&
686 !Ip4IsUnicast (EFI_NTOHL (RxData
->Header
->SourceAddress
), 0)) {
688 // The source address is not zero and it's not a unicast IP address, discard it.
694 // Create a netbuffer representing packet
696 Pkt
= NetbufFromExt (
697 (NET_FRAGMENT
*) RxData
->FragmentTable
,
698 RxData
->FragmentCount
,
702 RxData
->RecycleSignal
709 // Create a net session
711 Session
.Source
= EFI_IP4 (RxData
->Header
->SourceAddress
);
712 Session
.Dest
= EFI_IP4 (RxData
->Header
->DestinationAddress
);
713 Session
.IpHdr
= RxData
->Header
;
715 if (EFI_SUCCESS
== Status
) {
717 IpIo
->PktRcvdNotify (EFI_SUCCESS
, (ICMP_ERROR
) 0, &Session
, Pkt
, IpIo
->RcvdContext
);
720 // Status is EFI_ICMP_ERROR
722 Status
= IpIoIcmpHandler (IpIo
, Pkt
, &Session
);
723 if (EFI_ERROR (Status
)) {
731 gBS
->SignalEvent (RxData
->RecycleSignal
);
734 Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
739 Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
741 @param Event The event signaled.
742 @param Context The context passed in by the event notifier.
755 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
757 NetLibQueueDpc (TPL_CALLBACK
, IpIoListenHandlerDpc
, Context
);
762 Create a new IP_IO instance.
764 @param Image The image handle of an IP_IO consumer protocol.
765 @param Controller The controller handle of an IP_IO consumer protocol
768 @return Pointer to a newly created IP_IO instance.
775 IN EFI_HANDLE Controller
781 IpIo
= AllocateZeroPool (sizeof (IP_IO
));
786 InitializeListHead (&(IpIo
->PendingSndList
));
787 InitializeListHead (&(IpIo
->IpList
));
788 IpIo
->Controller
= Controller
;
791 Status
= gBS
->CreateEvent (
796 &(IpIo
->RcvToken
.Event
)
798 if (EFI_ERROR (Status
)) {
803 // Create an IP child and open IP protocol
805 Status
= IpIoCreateIpChildOpenProtocol (
811 if (EFI_ERROR (Status
)) {
819 if (NULL
!= IpIo
->RcvToken
.Event
) {
820 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
823 gBS
->FreePool (IpIo
);
830 Open an IP_IO instance for use.
832 @param IpIo Pointer to an IP_IO instance that needs to open.
833 @param OpenData The configuration data for the IP_IO instance.
835 @retval EFI_SUCCESS The IP_IO instance opened with OpenData
837 @retval other Error condition occurred.
844 IN IP_IO_OPEN_DATA
*OpenData
848 EFI_IP4_PROTOCOL
*Ip
;
850 if (IpIo
->IsConfigured
) {
851 return EFI_ACCESS_DENIED
;
859 Status
= Ip
->Configure (Ip
, &OpenData
->IpConfigData
);
860 if (EFI_ERROR (Status
)) {
865 // bugbug: to delete the default route entry in this Ip, if it is:
866 // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
869 Status
= Ip
->Routes (Ip
, TRUE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &mZeroIp4Addr
);
871 if (EFI_ERROR (Status
) && (EFI_NOT_FOUND
!= Status
)) {
875 IpIo
->PktRcvdNotify
= OpenData
->PktRcvdNotify
;
876 IpIo
->PktSentNotify
= OpenData
->PktSentNotify
;
878 IpIo
->RcvdContext
= OpenData
->RcvdContext
;
879 IpIo
->SndContext
= OpenData
->SndContext
;
881 IpIo
->Protocol
= OpenData
->IpConfigData
.DefaultProtocol
;
884 // start to listen incoming packet
886 Status
= Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
887 if (EFI_ERROR (Status
)) {
888 Ip
->Configure (Ip
, NULL
);
892 IpIo
->IsConfigured
= TRUE
;
893 InsertTailList (&mActiveIpIoList
, &IpIo
->Entry
);
902 Stop an IP_IO instance.
904 @param IpIo Pointer to the IP_IO instance that needs to stop.
906 @retval EFI_SUCCESS The IP_IO instance stopped successfully.
907 @retval other Error condition occurred.
916 EFI_IP4_PROTOCOL
*Ip
;
917 IP_IO_IP_INFO
*IpInfo
;
919 if (!IpIo
->IsConfigured
) {
924 // Remove the IpIo from the active IpIo list.
926 RemoveEntryList (&IpIo
->Entry
);
933 Status
= Ip
->Configure (Ip
, NULL
);
934 if (EFI_ERROR (Status
)) {
938 IpIo
->IsConfigured
= FALSE
;
941 // Detroy the Ip List used by IpIo
944 while (!IsListEmpty (&(IpIo
->IpList
))) {
945 IpInfo
= NET_LIST_HEAD (&(IpIo
->IpList
), IP_IO_IP_INFO
, Entry
);
947 IpIoRemoveIp (IpIo
, IpInfo
);
951 // All pending snd tokens should be flushed by reseting the IP instances.
953 ASSERT (IsListEmpty (&IpIo
->PendingSndList
));
956 // Close the receive event.
958 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
965 Destroy an IP_IO instance.
967 @param IpIo Pointer to the IP_IO instance that needs to
970 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.
971 @retval other Error condition occurred.
986 // Close the IP protocol and destroy the child.
988 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpIo
->ChildHandle
);
990 gBS
->FreePool (IpIo
);
997 Send out an IP packet.
999 @param IpIo Pointer to an IP_IO instance used for sending IP
1001 @param Pkt Pointer to the IP packet to be sent.
1002 @param Sender The IP protocol instance used for sending.
1004 @param Dest The destination IP address to send this packet to.
1005 @param OverrideData The data to override some configuration of the IP
1006 instance used for sending.
1008 @retval EFI_SUCCESS The operation is completed successfully.
1009 @retval EFI_NOT_STARTED The IpIo is not configured.
1010 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
1018 IN IP_IO_IP_INFO
*Sender
,
1019 IN VOID
*Context OPTIONAL
,
1020 IN VOID
*NotifyData OPTIONAL
,
1022 IN IP_IO_OVERRIDE
*OverrideData
1026 EFI_IP4_PROTOCOL
*Ip
;
1027 IP_IO_SEND_ENTRY
*SndEntry
;
1029 if (!IpIo
->IsConfigured
) {
1030 return EFI_NOT_STARTED
;
1033 Ip
= (NULL
== Sender
) ? IpIo
->Ip
: Sender
->Ip
;
1036 // create a new SndEntry
1038 SndEntry
= IpIoCreateSndEntry (IpIo
, Pkt
, Ip
, Context
, NotifyData
, Dest
, OverrideData
);
1039 if (NULL
== SndEntry
) {
1040 return EFI_OUT_OF_RESOURCES
;
1046 Status
= Ip
->Transmit (Ip
, SndEntry
->SndToken
);
1047 if (EFI_ERROR (Status
)) {
1048 IpIoDestroySndEntry (SndEntry
);
1056 Cancel the IP transmit token which wraps this Packet.
1058 @param IpIo Pointer to the IP_IO instance.
1059 @param Packet Pointer to the packet to cancel.
1072 IP_IO_SEND_ENTRY
*SndEntry
;
1073 EFI_IP4_PROTOCOL
*Ip
;
1075 ASSERT (IpIo
&& Packet
);
1077 NET_LIST_FOR_EACH (Node
, &IpIo
->PendingSndList
) {
1079 SndEntry
= NET_LIST_USER_STRUCT (Node
, IP_IO_SEND_ENTRY
, Entry
);
1081 if (SndEntry
->Pkt
== Packet
) {
1084 Ip
->Cancel (Ip
, SndEntry
->SndToken
);
1094 Add a new IP instance for sending data.
1096 @param IpIo Pointer to a IP_IO instance to add a new IP
1097 instance for sending purpose.
1099 @return Pointer to the created IP_IO_IP_INFO structure, NULL is failed.
1109 IP_IO_IP_INFO
*IpInfo
;
1113 IpInfo
= AllocatePool (sizeof (IP_IO_IP_INFO
));
1114 if (IpInfo
== NULL
) {
1119 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1122 InitializeListHead (&IpInfo
->Entry
);
1123 IpInfo
->ChildHandle
= NULL
;
1125 IpInfo
->SubnetMask
= 0;
1129 // Create the IP instance and open the Ip4 protocol.
1131 Status
= IpIoCreateIpChildOpenProtocol (
1134 &IpInfo
->ChildHandle
,
1135 (VOID
**) &IpInfo
->Ip
1137 if (EFI_ERROR (Status
)) {
1142 // Create the event for the DummyRcvToken.
1144 Status
= gBS
->CreateEvent (
1149 &IpInfo
->DummyRcvToken
.Event
1151 if (EFI_ERROR (Status
)) {
1152 goto ReleaseIpChild
;
1156 // Link this IpInfo into the IpIo.
1158 InsertTailList (&IpIo
->IpList
, &IpInfo
->Entry
);
1164 IpIoCloseProtocolDestroyIpChild (
1172 gBS
->FreePool (IpInfo
);
1179 Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1182 @param IpInfo Pointer to the IP_IO_IP_INFO instance.
1183 @param Ip4ConfigData The IP4 configure data used to configure the ip
1184 instance, if NULL the ip instance is reseted. If
1185 UseDefaultAddress is set to TRUE, and the configure
1186 operation succeeds, the default address information
1187 is written back in this Ip4ConfigData.
1189 @retval EFI_STATUS The status returned by IP4->Configure or
1196 IN IP_IO_IP_INFO
*IpInfo
,
1197 IN OUT EFI_IP4_CONFIG_DATA
*Ip4ConfigData OPTIONAL
1201 EFI_IP4_PROTOCOL
*Ip
;
1202 EFI_IP4_MODE_DATA Ip4ModeData
;
1206 if (IpInfo
->RefCnt
> 1) {
1208 // This IP instance is shared, don't reconfigure it until it has only one
1209 // consumer. Currently, only the tcp children cloned from their passive parent
1210 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1211 // let the last consumer clean the IP instance.
1218 Status
= Ip
->Configure (Ip
, Ip4ConfigData
);
1219 if (EFI_ERROR (Status
)) {
1223 if (Ip4ConfigData
!= NULL
) {
1225 if (Ip4ConfigData
->UseDefaultAddress
) {
1226 Ip
->GetModeData (Ip
, &Ip4ModeData
, NULL
, NULL
);
1228 Ip4ConfigData
->StationAddress
= Ip4ModeData
.ConfigData
.StationAddress
;
1229 Ip4ConfigData
->SubnetMask
= Ip4ModeData
.ConfigData
.SubnetMask
;
1232 CopyMem (&IpInfo
->Addr
, &Ip4ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
1233 CopyMem (&IpInfo
->SubnetMask
, &Ip4ConfigData
->SubnetMask
, sizeof (IP4_ADDR
));
1235 Status
= Ip
->Receive (Ip
, &IpInfo
->DummyRcvToken
);
1236 if (EFI_ERROR (Status
)) {
1237 Ip
->Configure (Ip
, NULL
);
1242 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1245 IpInfo
->SubnetMask
=0;
1255 Destroy an IP instance maintained in IpIo->IpList for
1258 @param IpIo Pointer to the IP_IO instance.
1259 @param IpInfo Pointer to the IpInfo to be removed.
1268 IN IP_IO_IP_INFO
*IpInfo
1271 ASSERT (IpInfo
->RefCnt
> 0);
1273 NET_PUT_REF (IpInfo
);
1275 if (IpInfo
->RefCnt
> 0) {
1280 RemoveEntryList (&IpInfo
->Entry
);
1282 IpInfo
->Ip
->Configure (IpInfo
->Ip
, NULL
);
1284 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpInfo
->ChildHandle
);
1286 gBS
->CloseEvent (IpInfo
->DummyRcvToken
.Event
);
1288 gBS
->FreePool (IpInfo
);
1293 Find the first IP protocol maintained in IpIo whose local
1294 address is the same with Src.
1296 @param IpIo Pointer to the pointer of the IP_IO instance.
1297 @param Src The local IP address.
1299 @return Pointer to the IP protocol can be used for sending purpose and its local
1300 @return address is the same with Src.
1306 IN OUT IP_IO
**IpIo
,
1310 LIST_ENTRY
*IpIoEntry
;
1312 LIST_ENTRY
*IpInfoEntry
;
1313 IP_IO_IP_INFO
*IpInfo
;
1315 NET_LIST_FOR_EACH (IpIoEntry
, &mActiveIpIoList
) {
1316 IpIoPtr
= NET_LIST_USER_STRUCT (IpIoEntry
, IP_IO
, Entry
);
1318 if ((*IpIo
!= NULL
) && (*IpIo
!= IpIoPtr
)) {
1322 NET_LIST_FOR_EACH (IpInfoEntry
, &IpIoPtr
->IpList
) {
1323 IpInfo
= NET_LIST_USER_STRUCT (IpInfoEntry
, IP_IO_IP_INFO
, Entry
);
1325 if (IpInfo
->Addr
== Src
) {
1340 Get the ICMP error map information, the ErrorStatus will be returned.
1341 The IsHard and Notify are optional. If they are not NULL, this rouine will
1343 We move IcmpErrMap[] to local variable to enable EBC build.
1345 @param IcmpError IcmpError Type
1346 @param IsHard Whether it is a hard error
1347 @param Notify Whether it need to notify SockError
1349 @return ICMP Error Status
1354 IpIoGetIcmpErrStatus (
1355 IN ICMP_ERROR IcmpError
,
1356 OUT BOOLEAN
*IsHard
, OPTIONAL
1357 OUT BOOLEAN
*Notify OPTIONAL
1360 ASSERT ((IcmpError
>= ICMP_ERR_UNREACH_NET
) && (IcmpError
<= ICMP_ERR_PARAMPROB
));
1362 if (IsHard
!= NULL
) {
1363 *IsHard
= mIcmpErrMap
[IcmpError
].IsHard
;
1366 if (Notify
!= NULL
) {
1367 *Notify
= mIcmpErrMap
[IcmpError
].Notify
;
1370 switch (IcmpError
) {
1371 case ICMP_ERR_UNREACH_NET
:
1372 return EFI_NETWORK_UNREACHABLE
;
1374 case ICMP_ERR_TIMXCEED_INTRANS
:
1375 case ICMP_ERR_TIMXCEED_REASS
:
1376 case ICMP_ERR_UNREACH_HOST
:
1377 return EFI_HOST_UNREACHABLE
;
1379 case ICMP_ERR_UNREACH_PROTOCOL
:
1380 return EFI_PROTOCOL_UNREACHABLE
;
1382 case ICMP_ERR_UNREACH_PORT
:
1383 return EFI_PORT_UNREACHABLE
;
1385 case ICMP_ERR_MSGSIZE
:
1386 case ICMP_ERR_UNREACH_SRCFAIL
:
1387 case ICMP_ERR_QUENCH
:
1388 case ICMP_ERR_PARAMPROB
:
1389 return EFI_ICMP_ERROR
;
1393 // will never run here!
1396 return EFI_UNSUPPORTED
;