4 Copyright (c) 2005 - 2007, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Protocol/Udp4.h>
18 #include <Library/IpIoLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23 #include <Library/MemoryAllocationLib.h>
26 LIST_ENTRY mActiveIpIoList
= {
31 EFI_IP4_CONFIG_DATA mIpIoDefaultIpConfigData
= {
48 ICMP_ERROR_INFO mIcmpErrMap
[10] = {
63 Notify function for IP transmit token.
65 @param[in] Context The context passed in by the event notifier.
70 IpIoTransmitHandlerDpc (
76 Notify function for IP transmit token.
78 @param[in] Event The event signaled.
79 @param[in] Context The context passed in by the event notifier.
91 This function create an IP child ,open the IP protocol, and return the opened
92 IP protocol as Interface.
94 @param[in] ControllerHandle The controller handle.
95 @param[in] ImageHandle The image handle.
96 @param[in] ChildHandle Pointer to the buffer to save the IP child handle.
97 @param[out] Interface Pointer used to get the IP protocol interface.
99 @retval EFI_SUCCESS The IP child is created and the IP protocol
100 interface is retrieved.
101 @retval Others The required operation failed.
105 IpIoCreateIpChildOpenProtocol (
106 IN EFI_HANDLE ControllerHandle
,
107 IN EFI_HANDLE ImageHandle
,
108 IN EFI_HANDLE
*ChildHandle
,
115 // Create an IP child.
117 Status
= NetLibCreateServiceChild (
120 &gEfiIp4ServiceBindingProtocolGuid
,
123 if (EFI_ERROR (Status
)) {
128 // Open the IP protocol installed on the *ChildHandle.
130 Status
= gBS
->OpenProtocol (
132 &gEfiIp4ProtocolGuid
,
136 EFI_OPEN_PROTOCOL_BY_DRIVER
138 if (EFI_ERROR (Status
)) {
140 // On failure, destroy the IP child.
142 NetLibDestroyServiceChild (
145 &gEfiIp4ServiceBindingProtocolGuid
,
155 This function close the previously openned IP protocol and destroy the IP child.
157 @param[in] ControllerHandle The controller handle.
158 @param[in] ImageHandle The image handle.
159 @param[in] ChildHandle The child handle of the IP child.
161 @retval EFI_SUCCESS The IP protocol is closed and the relevant IP child
163 @retval Others The required operation failed.
167 IpIoCloseProtocolDestroyIpChild (
168 IN EFI_HANDLE ControllerHandle
,
169 IN EFI_HANDLE ImageHandle
,
170 IN EFI_HANDLE ChildHandle
176 // Close the previously openned IP protocol.
180 &gEfiIp4ProtocolGuid
,
186 // Destroy the IP child.
188 Status
= NetLibDestroyServiceChild (
191 &gEfiIp4ServiceBindingProtocolGuid
,
200 This function handles ICMP packets.
202 @param[in] IpIo Pointer to the IP_IO instance.
203 @param[in, out] Pkt Pointer to the ICMP packet.
204 @param[in] Session Pointer to the net session of this ICMP packet.
206 @retval EFI_SUCCESS The ICMP packet is handled successfully.
207 @retval EFI_ABORTED This type of ICMP packet is not supported.
214 IN EFI_NET_SESSION_DATA
*Session
217 IP4_ICMP_ERROR_HEAD
*IcmpHdr
;
218 EFI_IP4_HEADER
*IpHdr
;
225 IcmpHdr
= NET_PROTO_HDR (Pkt
, IP4_ICMP_ERROR_HEAD
);
226 IpHdr
= (EFI_IP4_HEADER
*) (&IcmpHdr
->IpHead
);
229 // Check the ICMP packet length.
231 if (Pkt
->TotalSize
< ICMP_ERRLEN (IpHdr
)) {
236 Type
= IcmpHdr
->Head
.Type
;
237 Code
= IcmpHdr
->Head
.Code
;
240 // Analyze the ICMP Error in this ICMP pkt
243 case ICMP_TYPE_UNREACH
:
245 case ICMP_CODE_UNREACH_NET
:
246 case ICMP_CODE_UNREACH_HOST
:
247 case ICMP_CODE_UNREACH_PROTOCOL
:
248 case ICMP_CODE_UNREACH_PORT
:
249 case ICMP_CODE_UNREACH_SRCFAIL
:
250 IcmpErr
= (ICMP_ERROR
) (ICMP_ERR_UNREACH_NET
+ Code
);
254 case ICMP_CODE_UNREACH_NEEDFRAG
:
255 IcmpErr
= ICMP_ERR_MSGSIZE
;
259 case ICMP_CODE_UNREACH_NET_UNKNOWN
:
260 case ICMP_CODE_UNREACH_NET_PROHIB
:
261 case ICMP_CODE_UNREACH_TOSNET
:
262 IcmpErr
= ICMP_ERR_UNREACH_NET
;
266 case ICMP_CODE_UNREACH_HOST_UNKNOWN
:
267 case ICMP_CODE_UNREACH_ISOLATED
:
268 case ICMP_CODE_UNREACH_HOST_PROHIB
:
269 case ICMP_CODE_UNREACH_TOSHOST
:
270 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
;
312 // Notify user the ICMP pkt only containing payload except
313 // IP and ICMP header
315 PayLoadHdr
= (UINT8
*) ((UINT8
*) IpHdr
+ EFI_IP4_HEADER_LEN (IpHdr
));
316 TrimBytes
= (UINT32
) (PayLoadHdr
- (UINT8
*) IcmpHdr
);
318 NetbufTrim (Pkt
, TrimBytes
, TRUE
);
320 IpIo
->PktRcvdNotify (EFI_ICMP_ERROR
, IcmpErr
, Session
, Pkt
, IpIo
->RcvdContext
);
327 Free function for receive token of IP_IO. It is used to
328 signal the recycle event to notify IP to recycle the
331 @param[in] Event The event to be signaled.
339 gBS
->SignalEvent ((EFI_EVENT
) Event
);
344 Create a send entry to wrap a packet before sending
347 @param[in, out] IpIo Pointer to the IP_IO instance.
348 @param[in, out] Pkt Pointer to the packet.
349 @param[in] Sender Pointer to the IP sender.
350 @param[in] Context Pointer to the context.
351 @param[in] NotifyData Pointer to the notify data.
352 @param[in] Dest Pointer to the destination IP address.
353 @param[in] Override Pointer to the overriden IP_IO data.
355 @return Pointer to the data structure created to wrap the packet. If NULL,
356 @return resource limit occurred.
363 IN EFI_IP4_PROTOCOL
*Sender
,
364 IN VOID
*Context OPTIONAL
,
365 IN VOID
*NotifyData OPTIONAL
,
367 IN IP_IO_OVERRIDE
*Override
370 IP_IO_SEND_ENTRY
*SndEntry
;
371 EFI_IP4_COMPLETION_TOKEN
*SndToken
;
372 EFI_IP4_TRANSMIT_DATA
*TxData
;
374 EFI_IP4_OVERRIDE_DATA
*OverrideData
;
375 volatile UINT32 Index
;
378 // Allocate resource for SndEntry
380 SndEntry
= AllocatePool (sizeof (IP_IO_SEND_ENTRY
));
381 if (NULL
== SndEntry
) {
386 // Allocate resource for SndToken
388 SndToken
= AllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN
));
389 if (NULL
== SndToken
) {
390 goto ReleaseSndEntry
;
393 Status
= gBS
->CreateEvent (
400 if (EFI_ERROR (Status
)) {
401 goto ReleaseSndToken
;
405 // Allocate resource for TxData
407 TxData
= AllocatePool (
408 sizeof (EFI_IP4_TRANSMIT_DATA
) +
409 sizeof (EFI_IP4_FRAGMENT_DATA
) * (Pkt
->BlockOpNum
- 1)
412 if (NULL
== TxData
) {
417 // Allocate resource for OverrideData if needed
420 if (NULL
!= Override
) {
422 OverrideData
= AllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA
));
423 if (NULL
== OverrideData
) {
424 goto ReleaseResource
;
427 // Set the fields of OverrideData
429 CopyMem (OverrideData
, Override
, sizeof (*OverrideData
));
433 // Set the fields of TxData
435 CopyMem (&TxData
->DestinationAddress
, &Dest
, sizeof (EFI_IPv4_ADDRESS
));
436 TxData
->OverrideData
= OverrideData
;
437 TxData
->OptionsLength
= 0;
438 TxData
->OptionsBuffer
= NULL
;
439 TxData
->TotalDataLength
= Pkt
->TotalSize
;
440 TxData
->FragmentCount
= Pkt
->BlockOpNum
;
443 for (Index
= 0; Index
< Pkt
->BlockOpNum
; Index
++) {
444 TxData
->FragmentTable
[Index
].FragmentBuffer
= Pkt
->BlockOp
[Index
].Head
;
445 TxData
->FragmentTable
[Index
].FragmentLength
= Pkt
->BlockOp
[Index
].Size
;
449 // Set the fields of SndToken
451 SndToken
->Packet
.TxData
= TxData
;
454 // Set the fields of SndEntry
456 SndEntry
->IpIo
= IpIo
;
457 SndEntry
->Ip
= Sender
;
458 SndEntry
->Context
= Context
;
459 SndEntry
->NotifyData
= NotifyData
;
464 SndEntry
->SndToken
= SndToken
;
466 InsertTailList (&IpIo
->PendingSndList
, &SndEntry
->Entry
);
471 gBS
->FreePool (TxData
);
474 gBS
->CloseEvent (SndToken
->Event
);
477 gBS
->FreePool (SndToken
);
480 gBS
->FreePool (SndEntry
);
487 Destroy the SndEntry.
489 This function pairs with IpIoCreateSndEntry().
491 @param[in] SndEntry Pointer to the send entry to be destroyed.
495 IpIoDestroySndEntry (
496 IN IP_IO_SEND_ENTRY
*SndEntry
499 EFI_IP4_TRANSMIT_DATA
*TxData
;
501 TxData
= SndEntry
->SndToken
->Packet
.TxData
;
503 if (NULL
!= TxData
->OverrideData
) {
504 gBS
->FreePool (TxData
->OverrideData
);
507 gBS
->FreePool (TxData
);
508 NetbufFree (SndEntry
->Pkt
);
509 gBS
->CloseEvent (SndEntry
->SndToken
->Event
);
511 gBS
->FreePool (SndEntry
->SndToken
);
512 RemoveEntryList (&SndEntry
->Entry
);
514 gBS
->FreePool (SndEntry
);
519 Notify function for IP transmit token.
521 @param[in] Context The context passed in by the event notifier.
526 IpIoTransmitHandlerDpc (
531 IP_IO_SEND_ENTRY
*SndEntry
;
533 SndEntry
= (IP_IO_SEND_ENTRY
*) Context
;
535 IpIo
= SndEntry
->IpIo
;
537 if ((IpIo
->PktSentNotify
!= NULL
) && (SndEntry
->NotifyData
!= NULL
)) {
538 IpIo
->PktSentNotify (
539 SndEntry
->SndToken
->Status
,
546 IpIoDestroySndEntry (SndEntry
);
551 Notify function for IP transmit token.
553 @param[in] Event The event signaled.
554 @param[in] Context The context passed in by the event notifier.
559 IpIoTransmitHandler (
565 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
567 NetLibQueueDpc (TPL_CALLBACK
, IpIoTransmitHandlerDpc
, Context
);
572 The dummy handler for the dummy IP receive token.
574 @param[in] Context The context passed in by the event notifier.
579 IpIoDummyHandlerDpc (
583 IP_IO_IP_INFO
*IpInfo
;
584 EFI_IP4_COMPLETION_TOKEN
*DummyToken
;
586 IpInfo
= (IP_IO_IP_INFO
*) Context
;
587 DummyToken
= &(IpInfo
->DummyRcvToken
);
589 if (EFI_ABORTED
== DummyToken
->Status
) {
591 // The reception is actively aborted by the consumer, directly return.
594 } else if (EFI_SUCCESS
== DummyToken
->Status
) {
595 ASSERT ((DummyToken
->Packet
.RxData
)!= NULL
);
597 gBS
->SignalEvent (DummyToken
->Packet
.RxData
->RecycleSignal
);
600 IpInfo
->Ip
->Receive (IpInfo
->Ip
, DummyToken
);
605 This function add IpIoDummyHandlerDpc to the end of the DPC queue.
607 @param[in] Event The event signaled.
608 @param[in] Context The context passed in by the event notifier.
619 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
621 NetLibQueueDpc (TPL_CALLBACK
, IpIoDummyHandlerDpc
, Context
);
626 Notify function for the IP receive token, used to process
627 the received IP packets.
629 @param[in] Context The context passed in by the event notifier.
634 IpIoListenHandlerDpc (
640 EFI_IP4_RECEIVE_DATA
*RxData
;
641 EFI_IP4_PROTOCOL
*Ip
;
642 EFI_NET_SESSION_DATA Session
;
645 IpIo
= (IP_IO
*) Context
;
648 Status
= IpIo
->RcvToken
.Status
;
649 RxData
= IpIo
->RcvToken
.Packet
.RxData
;
651 if (EFI_ABORTED
== Status
) {
653 // The reception is actively aborted by the consumer, directly return.
658 if (((EFI_SUCCESS
!= Status
) && (EFI_ICMP_ERROR
!= Status
)) || (NULL
== RxData
)) {
660 // @bug Only process the normal packets and the icmp error packets, if RxData is NULL
661 // @bug with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
662 // @bug this should be a bug of the low layer (IP).
667 if (NULL
== IpIo
->PktRcvdNotify
) {
671 if ((EFI_IP4 (RxData
->Header
->SourceAddress
) != 0) &&
672 !Ip4IsUnicast (EFI_NTOHL (RxData
->Header
->SourceAddress
), 0)) {
674 // The source address is not zero and it's not a unicast IP address, discard it.
680 // Create a netbuffer representing packet
682 Pkt
= NetbufFromExt (
683 (NET_FRAGMENT
*) RxData
->FragmentTable
,
684 RxData
->FragmentCount
,
688 RxData
->RecycleSignal
695 // Create a net session
697 Session
.Source
= EFI_IP4 (RxData
->Header
->SourceAddress
);
698 Session
.Dest
= EFI_IP4 (RxData
->Header
->DestinationAddress
);
699 Session
.IpHdr
= RxData
->Header
;
701 if (EFI_SUCCESS
== Status
) {
703 IpIo
->PktRcvdNotify (EFI_SUCCESS
, (ICMP_ERROR
) 0, &Session
, Pkt
, IpIo
->RcvdContext
);
706 // Status is EFI_ICMP_ERROR
708 Status
= IpIoIcmpHandler (IpIo
, Pkt
, &Session
);
709 if (EFI_ERROR (Status
)) {
717 gBS
->SignalEvent (RxData
->RecycleSignal
);
720 Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
725 This function add IpIoListenHandlerDpc to the end of the DPC queue.
727 @param[in] Event The event signaled.
728 @param[in] Context The context passed in by the event notifier.
739 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
741 NetLibQueueDpc (TPL_CALLBACK
, IpIoListenHandlerDpc
, Context
);
746 Create a new IP_IO instance.
748 This function uses IP4 service binding protocol in Controller to create an IP4
749 child (aka IP4 instance).
751 @param[in] Image The image handle of the driver or application that
753 @param[in] Controller The controller handle that has IP4 service binding
756 @return Pointer to a newly created IP_IO instance, or NULL if failed.
763 IN EFI_HANDLE Controller
769 IpIo
= AllocateZeroPool (sizeof (IP_IO
));
774 InitializeListHead (&(IpIo
->PendingSndList
));
775 InitializeListHead (&(IpIo
->IpList
));
776 IpIo
->Controller
= Controller
;
779 Status
= gBS
->CreateEvent (
784 &(IpIo
->RcvToken
.Event
)
786 if (EFI_ERROR (Status
)) {
791 // Create an IP child and open IP protocol
793 Status
= IpIoCreateIpChildOpenProtocol (
799 if (EFI_ERROR (Status
)) {
807 if (NULL
!= IpIo
->RcvToken
.Event
) {
808 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
811 gBS
->FreePool (IpIo
);
818 Open an IP_IO instance for use.
820 This function is called after IpIoCreate(). It is used for configuring the IP
821 instance and register the callbacks and their context data for sending and
822 receiving IP packets.
824 @param[in, out] IpIo Pointer to an IP_IO instance that needs
826 @param[in] OpenData The configuration data and callbacks for
829 @retval EFI_SUCCESS The IP_IO instance opened with OpenData
831 @retval EFI_ACCESS_DENIED The IP_IO instance is configured, avoid to
833 @retval Others Error condition occurred.
840 IN IP_IO_OPEN_DATA
*OpenData
844 EFI_IP4_PROTOCOL
*Ip
;
846 if (IpIo
->IsConfigured
) {
847 return EFI_ACCESS_DENIED
;
855 Status
= Ip
->Configure (Ip
, &OpenData
->IpConfigData
);
856 if (EFI_ERROR (Status
)) {
861 // @bug To delete the default route entry in this Ip, if it is:
862 // @bug (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
865 Status
= Ip
->Routes (Ip
, TRUE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &mZeroIp4Addr
);
867 if (EFI_ERROR (Status
) && (EFI_NOT_FOUND
!= Status
)) {
871 IpIo
->PktRcvdNotify
= OpenData
->PktRcvdNotify
;
872 IpIo
->PktSentNotify
= OpenData
->PktSentNotify
;
874 IpIo
->RcvdContext
= OpenData
->RcvdContext
;
875 IpIo
->SndContext
= OpenData
->SndContext
;
877 IpIo
->Protocol
= OpenData
->IpConfigData
.DefaultProtocol
;
880 // start to listen incoming packet
882 Status
= Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
883 if (EFI_ERROR (Status
)) {
884 Ip
->Configure (Ip
, NULL
);
888 IpIo
->IsConfigured
= TRUE
;
889 InsertTailList (&mActiveIpIoList
, &IpIo
->Entry
);
898 Stop an IP_IO instance.
900 This function is paired with IpIoOpen(). The IP_IO will be unconfigured and all
901 the pending send/receive tokens will be canceled.
903 @param[in, out] IpIo Pointer to the IP_IO instance that needs to stop.
905 @retval EFI_SUCCESS The IP_IO instance stopped successfully.
906 @retval Others 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 send 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 This function is paired with IpIoCreate(). The IP_IO will be closed first.
968 Resource will be freed afterwards. See IpIoCloseProtocolDestroyIpChild().
970 @param[in, out] IpIo Pointer to the IP_IO instance that needs to be
973 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.
974 @retval Others Error condition occurred.
989 // Close the IP protocol and destroy the child.
991 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpIo
->ChildHandle
);
993 gBS
->FreePool (IpIo
);
1000 Send out an IP packet.
1002 This function is called after IpIoOpen(). The data to be sent are wrapped in
1003 Pkt. The IP instance wrapped in IpIo is used for sending by default but can be
1004 overriden by Sender. Other sending configs, like source address and gateway
1005 address etc., are specified in OverrideData.
1007 @param[in, out] IpIo Pointer to an IP_IO instance used for sending IP
1009 @param[in, out] Pkt Pointer to the IP packet to be sent.
1010 @param[in] Sender The IP protocol instance used for sending.
1011 @param[in] Context Optional context data.
1012 @param[in] NotifyData Optional notify data.
1013 @param[in] Dest The destination IP address to send this packet to.
1014 @param[in] OverrideData The data to override some configuration of the IP
1015 instance used for sending.
1017 @retval EFI_SUCCESS The operation is completed successfully.
1018 @retval EFI_NOT_STARTED The IpIo is not configured.
1019 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
1026 IN OUT NET_BUF
*Pkt
,
1027 IN IP_IO_IP_INFO
*Sender OPTIONAL
,
1028 IN VOID
*Context OPTIONAL
,
1029 IN VOID
*NotifyData OPTIONAL
,
1031 IN IP_IO_OVERRIDE
*OverrideData OPTIONAL
1035 EFI_IP4_PROTOCOL
*Ip
;
1036 IP_IO_SEND_ENTRY
*SndEntry
;
1038 if (!IpIo
->IsConfigured
) {
1039 return EFI_NOT_STARTED
;
1042 Ip
= (NULL
== Sender
) ? IpIo
->Ip
: Sender
->Ip
;
1045 // create a new SndEntry
1047 SndEntry
= IpIoCreateSndEntry (IpIo
, Pkt
, Ip
, Context
, NotifyData
, Dest
, OverrideData
);
1048 if (NULL
== SndEntry
) {
1049 return EFI_OUT_OF_RESOURCES
;
1055 Status
= Ip
->Transmit (Ip
, SndEntry
->SndToken
);
1056 if (EFI_ERROR (Status
)) {
1057 IpIoDestroySndEntry (SndEntry
);
1065 Cancel the IP transmit token which wraps this Packet.
1067 @param[in] IpIo Pointer to the IP_IO instance.
1068 @param[in] Packet Pointer to the packet of NET_BUF to cancel.
1079 IP_IO_SEND_ENTRY
*SndEntry
;
1080 EFI_IP4_PROTOCOL
*Ip
;
1082 ASSERT ((IpIo
)!= NULL
&& (Packet
)!= NULL
);
1084 NET_LIST_FOR_EACH (Node
, &IpIo
->PendingSndList
) {
1086 SndEntry
= NET_LIST_USER_STRUCT (Node
, IP_IO_SEND_ENTRY
, Entry
);
1088 if (SndEntry
->Pkt
== Packet
) {
1091 Ip
->Cancel (Ip
, SndEntry
->SndToken
);
1101 Add a new IP instance for sending data.
1103 The function is used to add the IP_IO to the IP_IO sending list. The caller
1104 can later use IpIoFindSender() to get the IP_IO and call IpIoSend() to send
1107 @param[in, out] IpIo Pointer to a IP_IO instance to add a new IP
1108 instance for sending purpose.
1110 @return Pointer to the created IP_IO_IP_INFO structure, NULL if failed.
1120 IP_IO_IP_INFO
*IpInfo
;
1122 ASSERT (IpIo
!= NULL
);
1124 IpInfo
= AllocatePool (sizeof (IP_IO_IP_INFO
));
1125 if (IpInfo
== NULL
) {
1130 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1133 InitializeListHead (&IpInfo
->Entry
);
1134 IpInfo
->ChildHandle
= NULL
;
1136 IpInfo
->SubnetMask
= 0;
1140 // Create the IP instance and open the Ip4 protocol.
1142 Status
= IpIoCreateIpChildOpenProtocol (
1145 &IpInfo
->ChildHandle
,
1146 (VOID
**) &IpInfo
->Ip
1148 if (EFI_ERROR (Status
)) {
1153 // Create the event for the DummyRcvToken.
1155 Status
= gBS
->CreateEvent (
1160 &IpInfo
->DummyRcvToken
.Event
1162 if (EFI_ERROR (Status
)) {
1163 goto ReleaseIpChild
;
1167 // Link this IpInfo into the IpIo.
1169 InsertTailList (&IpIo
->IpList
, &IpInfo
->Entry
);
1175 IpIoCloseProtocolDestroyIpChild (
1183 gBS
->FreePool (IpInfo
);
1190 Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1193 @param[in, out] IpInfo Pointer to the IP_IO_IP_INFO instance.
1194 @param[in, out] Ip4ConfigData The IP4 configure data used to configure the IP
1195 instance, if NULL the IP instance is reset. If
1196 UseDefaultAddress is set to TRUE, and the configure
1197 operation succeeds, the default address information
1198 is written back in this Ip4ConfigData.
1200 @retval EFI_SUCCESS The IP instance of this IpInfo is configured successfully
1201 or no need to reconfigure it.
1202 @retval Others Configuration fails.
1208 IN OUT IP_IO_IP_INFO
*IpInfo
,
1209 IN OUT EFI_IP4_CONFIG_DATA
*Ip4ConfigData OPTIONAL
1213 EFI_IP4_PROTOCOL
*Ip
;
1214 EFI_IP4_MODE_DATA Ip4ModeData
;
1216 ASSERT (IpInfo
!= NULL
);
1218 if (IpInfo
->RefCnt
> 1) {
1220 // This IP instance is shared, don't reconfigure it until it has only one
1221 // consumer. Currently, only the tcp children cloned from their passive parent
1222 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1223 // let the last consumer clean the IP instance.
1230 Status
= Ip
->Configure (Ip
, Ip4ConfigData
);
1231 if (EFI_ERROR (Status
)) {
1235 if (Ip4ConfigData
!= NULL
) {
1237 if (Ip4ConfigData
->UseDefaultAddress
) {
1238 Ip
->GetModeData (Ip
, &Ip4ModeData
, NULL
, NULL
);
1240 Ip4ConfigData
->StationAddress
= Ip4ModeData
.ConfigData
.StationAddress
;
1241 Ip4ConfigData
->SubnetMask
= Ip4ModeData
.ConfigData
.SubnetMask
;
1244 CopyMem (&IpInfo
->Addr
, &Ip4ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
1245 CopyMem (&IpInfo
->SubnetMask
, &Ip4ConfigData
->SubnetMask
, sizeof (IP4_ADDR
));
1247 Status
= Ip
->Receive (Ip
, &IpInfo
->DummyRcvToken
);
1248 if (EFI_ERROR (Status
)) {
1249 Ip
->Configure (Ip
, NULL
);
1254 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1257 IpInfo
->SubnetMask
=0;
1267 Destroy an IP instance maintained in IpIo->IpList for
1270 This function pairs with IpIoAddIp(). The IpInfo is previously created by
1271 IpIoAddIp(). The IP_IO_IP_INFO::RefCnt is decremented and the IP instance
1272 will be dstroyed if the RefCnt is zero.
1274 @param[in] IpIo Pointer to the IP_IO instance.
1275 @param[in] IpInfo Pointer to the IpInfo to be removed.
1282 IN IP_IO_IP_INFO
*IpInfo
1285 ASSERT (IpInfo
->RefCnt
> 0);
1287 NET_PUT_REF (IpInfo
);
1289 if (IpInfo
->RefCnt
> 0) {
1294 RemoveEntryList (&IpInfo
->Entry
);
1296 IpInfo
->Ip
->Configure (IpInfo
->Ip
, NULL
);
1298 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpInfo
->ChildHandle
);
1300 gBS
->CloseEvent (IpInfo
->DummyRcvToken
.Event
);
1302 gBS
->FreePool (IpInfo
);
1307 Find the first IP protocol maintained in IpIo whose local
1308 address is the same with Src.
1310 This function is called when the caller needs the IpIo to send data to the
1311 specified Src. The IpIo was added previously by IpIoAddIp().
1313 @param[in, out] IpIo Pointer to the pointer of the IP_IO instance.
1314 @param[in] Src The local IP address.
1316 @return Pointer to the IP protocol can be used for sending purpose and its local
1317 @return address is the same with Src.
1323 IN OUT IP_IO
**IpIo
,
1327 LIST_ENTRY
*IpIoEntry
;
1329 LIST_ENTRY
*IpInfoEntry
;
1330 IP_IO_IP_INFO
*IpInfo
;
1332 NET_LIST_FOR_EACH (IpIoEntry
, &mActiveIpIoList
) {
1333 IpIoPtr
= NET_LIST_USER_STRUCT (IpIoEntry
, IP_IO
, Entry
);
1335 if ((*IpIo
!= NULL
) && (*IpIo
!= IpIoPtr
)) {
1339 NET_LIST_FOR_EACH (IpInfoEntry
, &IpIoPtr
->IpList
) {
1340 IpInfo
= NET_LIST_USER_STRUCT (IpInfoEntry
, IP_IO_IP_INFO
, Entry
);
1342 if (IpInfo
->Addr
== Src
) {
1357 Get the ICMP error map information.
1359 The ErrorStatus will be returned. The IsHard and Notify are optional. If they
1360 are not NULL, this routine will fill them.
1362 @param[in] IcmpError IcmpError Type.
1363 @param[out] IsHard Whether it is a hard error.
1364 @param[out] Notify Whether it need to notify SockError.
1366 @return ICMP Error Status, such as EFI_NETWORK_UNREACHABLE.
1371 IpIoGetIcmpErrStatus (
1372 IN ICMP_ERROR IcmpError
,
1373 OUT BOOLEAN
*IsHard OPTIONAL
,
1374 OUT BOOLEAN
*Notify OPTIONAL
1377 ASSERT ((IcmpError
>= ICMP_ERR_UNREACH_NET
) && (IcmpError
<= ICMP_ERR_PARAMPROB
));
1379 if (IsHard
!= NULL
) {
1380 *IsHard
= mIcmpErrMap
[IcmpError
].IsHard
;
1383 if (Notify
!= NULL
) {
1384 *Notify
= mIcmpErrMap
[IcmpError
].Notify
;
1387 switch (IcmpError
) {
1388 case ICMP_ERR_UNREACH_NET
:
1389 return EFI_NETWORK_UNREACHABLE
;
1391 case ICMP_ERR_TIMXCEED_INTRANS
:
1392 case ICMP_ERR_TIMXCEED_REASS
:
1393 case ICMP_ERR_UNREACH_HOST
:
1394 return EFI_HOST_UNREACHABLE
;
1396 case ICMP_ERR_UNREACH_PROTOCOL
:
1397 return EFI_PROTOCOL_UNREACHABLE
;
1399 case ICMP_ERR_UNREACH_PORT
:
1400 return EFI_PORT_UNREACHABLE
;
1402 case ICMP_ERR_MSGSIZE
:
1403 case ICMP_ERR_UNREACH_SRCFAIL
:
1404 case ICMP_ERR_QUENCH
:
1405 case ICMP_ERR_PARAMPROB
:
1406 return EFI_ICMP_ERROR
;
1410 // will never run here!
1413 return EFI_UNSUPPORTED
;