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 NET_LIST_ENTRY mActiveIpIoList
= {
44 EFI_IP4_CONFIG_DATA mIpIoDefaultIpConfigData
= {
61 STATIC ICMP_ERROR_INFO mIcmpErrMap
[10] = {
77 IpIoTransmitHandlerDpc (
91 This function create an ip child ,open the IP protocol, return the opened
92 Ip protocol to Interface.
94 @param ControllerHandle The controller handle.
95 @param ImageHandle The image handle.
96 @param ChildHandle Pointer to the buffer to save the ip child handle.
97 @param 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 other The required operation failed.
106 IpIoCreateIpChildOpenProtocol (
107 IN EFI_HANDLE ControllerHandle
,
108 IN EFI_HANDLE ImageHandle
,
109 IN EFI_HANDLE
*ChildHandle
,
116 // Create an ip child.
118 Status
= NetLibCreateServiceChild (
121 &gEfiIp4ServiceBindingProtocolGuid
,
124 if (EFI_ERROR (Status
)) {
129 // Open the ip protocol installed on the *ChildHandle.
131 Status
= gBS
->OpenProtocol (
133 &gEfiIp4ProtocolGuid
,
137 EFI_OPEN_PROTOCOL_BY_DRIVER
139 if (EFI_ERROR (Status
)) {
141 // On failure, destroy the ip child.
143 NetLibDestroyServiceChild (
146 &gEfiIp4ServiceBindingProtocolGuid
,
156 This function close the previously openned ip protocol and destroy the ip child.
158 @param ControllerHandle The controller handle.
159 @param ImageHandle the image handle.
160 @param ChildHandle The child handle of the ip child.
162 @retval EFI_SUCCESS The ip protocol is closed and the relevant ip child
164 @retval other The required operation failed.
169 IpIoCloseProtocolDestroyIpChild (
170 IN EFI_HANDLE ControllerHandle
,
171 IN EFI_HANDLE ImageHandle
,
172 IN EFI_HANDLE ChildHandle
178 // Close the previously openned ip protocol.
182 &gEfiIp4ProtocolGuid
,
188 // Destroy the ip child.
190 Status
= NetLibDestroyServiceChild (
193 &gEfiIp4ServiceBindingProtocolGuid
,
204 @param IpIo Pointer to the IP_IO instance.
205 @param Pkt Pointer to the ICMP packet.
206 @param Session Pointer to the net session of this ICMP packet.
208 @retval EFI_SUCCESS The ICMP packet is handled successfully.
209 @retval EFI_ABORTED This type of ICMP packet is not supported.
217 IN EFI_NET_SESSION_DATA
*Session
220 IP4_ICMP_ERROR_HEAD
*IcmpHdr
;
221 EFI_IP4_HEADER
*IpHdr
;
228 IcmpHdr
= NET_PROTO_HDR (Pkt
, IP4_ICMP_ERROR_HEAD
);
229 IpHdr
= (EFI_IP4_HEADER
*) (&IcmpHdr
->IpHead
);
232 // Check the ICMP packet length.
234 if (Pkt
->TotalSize
< ICMP_ERRLEN (IpHdr
)) {
239 Type
= IcmpHdr
->Head
.Type
;
240 Code
= IcmpHdr
->Head
.Code
;
243 // Analyze the ICMP Error in this ICMP pkt
246 case ICMP_TYPE_UNREACH
:
248 case ICMP_CODE_UNREACH_NET
:
249 case ICMP_CODE_UNREACH_HOST
:
250 case ICMP_CODE_UNREACH_PROTOCOL
:
251 case ICMP_CODE_UNREACH_PORT
:
252 case ICMP_CODE_UNREACH_SRCFAIL
:
253 IcmpErr
= (ICMP_ERROR
) (ICMP_ERR_UNREACH_NET
+ Code
);
257 case ICMP_CODE_UNREACH_NEEDFRAG
:
258 IcmpErr
= ICMP_ERR_MSGSIZE
;
262 case ICMP_CODE_UNREACH_NET_UNKNOWN
:
263 case ICMP_CODE_UNREACH_NET_PROHIB
:
264 case ICMP_CODE_UNREACH_TOSNET
:
265 IcmpErr
= ICMP_ERR_UNREACH_NET
;
269 case ICMP_CODE_UNREACH_HOST_UNKNOWN
:
270 case ICMP_CODE_UNREACH_ISOLATED
:
271 case ICMP_CODE_UNREACH_HOST_PROHIB
:
272 case ICMP_CODE_UNREACH_TOSHOST
:
273 IcmpErr
= ICMP_ERR_UNREACH_HOST
;
285 case ICMP_TYPE_TIMXCEED
:
290 IcmpErr
= (ICMP_ERROR
) (Code
+ ICMP_ERR_TIMXCEED_INTRANS
);
294 case ICMP_TYPE_PARAMPROB
:
299 IcmpErr
= ICMP_ERR_PARAMPROB
;
303 case ICMP_TYPE_SOURCEQUENCH
:
308 IcmpErr
= ICMP_ERR_QUENCH
;
319 // Notify user the ICMP pkt only containing payload except
320 // IP and ICMP header
322 PayLoadHdr
= (UINT8
*) ((UINT8
*) IpHdr
+ EFI_IP4_HEADER_LEN (IpHdr
));
323 TrimBytes
= (UINT32
) (PayLoadHdr
- (UINT8
*) IcmpHdr
);
325 NetbufTrim (Pkt
, TrimBytes
, TRUE
);
327 IpIo
->PktRcvdNotify (EFI_ICMP_ERROR
, IcmpErr
, Session
, Pkt
, IpIo
->RcvdContext
);
334 Ext free function for net buffer. This function is
335 called when the net buffer is freed. It is used to
336 signal the recycle event to notify IP to recycle the
339 @param Event The event to be signaled.
350 gBS
->SignalEvent ((EFI_EVENT
) Event
);
355 Create a send entry to wrap a packet before sending
358 @param IpIo Pointer to the IP_IO instance.
359 @param Pkt Pointer to the packet.
360 @param Sender Pointer to the IP sender.
361 @param NotifyData Pointer to the notify data.
362 @param Dest Pointer to the destination IP address.
363 @param Override Pointer to the overriden IP_IO data.
365 @return Pointer to the data structure created to wrap the packet. If NULL,
366 @return resource limit occurred.
374 IN EFI_IP4_PROTOCOL
*Sender
,
375 IN VOID
*Context OPTIONAL
,
376 IN VOID
*NotifyData OPTIONAL
,
378 IN IP_IO_OVERRIDE
*Override
381 IP_IO_SEND_ENTRY
*SndEntry
;
382 EFI_IP4_COMPLETION_TOKEN
*SndToken
;
383 EFI_IP4_TRANSMIT_DATA
*TxData
;
385 EFI_IP4_OVERRIDE_DATA
*OverrideData
;
386 volatile UINT32 Index
;
389 // Allocate resource for SndEntry
391 SndEntry
= NetAllocatePool (sizeof (IP_IO_SEND_ENTRY
));
392 if (NULL
== SndEntry
) {
397 // Allocate resource for SndToken
399 SndToken
= NetAllocatePool (sizeof (EFI_IP4_COMPLETION_TOKEN
));
400 if (NULL
== SndToken
) {
401 goto ReleaseSndEntry
;
404 Status
= gBS
->CreateEvent (
411 if (EFI_ERROR (Status
)) {
412 goto ReleaseSndToken
;
416 // Allocate resource for TxData
418 TxData
= NetAllocatePool (
419 sizeof (EFI_IP4_TRANSMIT_DATA
) +
420 sizeof (EFI_IP4_FRAGMENT_DATA
) * (Pkt
->BlockOpNum
- 1)
423 if (NULL
== TxData
) {
428 // Allocate resource for OverrideData if needed
431 if (NULL
!= Override
) {
433 OverrideData
= NetAllocatePool (sizeof (EFI_IP4_OVERRIDE_DATA
));
434 if (NULL
== OverrideData
) {
435 goto ReleaseResource
;
438 // Set the fields of OverrideData
440 CopyMem (OverrideData
, Override
, sizeof (*OverrideData
));
444 // Set the fields of TxData
446 NetCopyMem (&TxData
->DestinationAddress
, &Dest
, sizeof (EFI_IPv4_ADDRESS
));
447 TxData
->OverrideData
= OverrideData
;
448 TxData
->OptionsLength
= 0;
449 TxData
->OptionsBuffer
= NULL
;
450 TxData
->TotalDataLength
= Pkt
->TotalSize
;
451 TxData
->FragmentCount
= Pkt
->BlockOpNum
;
454 for (Index
= 0; Index
< Pkt
->BlockOpNum
; Index
++) {
455 TxData
->FragmentTable
[Index
].FragmentBuffer
= Pkt
->BlockOp
[Index
].Head
;
456 TxData
->FragmentTable
[Index
].FragmentLength
= Pkt
->BlockOp
[Index
].Size
;
460 // Set the fields of SndToken
462 SndToken
->Packet
.TxData
= TxData
;
465 // Set the fields of SndEntry
467 SndEntry
->IpIo
= IpIo
;
468 SndEntry
->Ip
= Sender
;
469 SndEntry
->Context
= Context
;
470 SndEntry
->NotifyData
= NotifyData
;
475 SndEntry
->SndToken
= SndToken
;
477 NetListInsertTail (&IpIo
->PendingSndList
, &SndEntry
->Entry
);
482 NetFreePool (TxData
);
485 gBS
->CloseEvent (SndToken
->Event
);
488 NetFreePool (SndToken
);
491 NetFreePool (SndEntry
);
498 Destroy the SndEntry.
500 @param SndEntry Pointer to the send entry to be destroyed.
507 IpIoDestroySndEntry (
508 IN IP_IO_SEND_ENTRY
*SndEntry
511 EFI_IP4_TRANSMIT_DATA
*TxData
;
513 TxData
= SndEntry
->SndToken
->Packet
.TxData
;
515 if (NULL
!= TxData
->OverrideData
) {
516 NetFreePool (TxData
->OverrideData
);
519 NetFreePool (TxData
);
520 NetbufFree (SndEntry
->Pkt
);
521 gBS
->CloseEvent (SndEntry
->SndToken
->Event
);
523 NetFreePool (SndEntry
->SndToken
);
524 NetListRemoveEntry (&SndEntry
->Entry
);
526 NetFreePool (SndEntry
);
531 Notify function for IP transmit token.
533 @param Context The context passed in by the event notifier.
541 IpIoTransmitHandlerDpc (
546 IP_IO_SEND_ENTRY
*SndEntry
;
548 SndEntry
= (IP_IO_SEND_ENTRY
*) Context
;
550 IpIo
= SndEntry
->IpIo
;
552 if (IpIo
->PktSentNotify
&& SndEntry
->NotifyData
) {
553 IpIo
->PktSentNotify (
554 SndEntry
->SndToken
->Status
,
561 IpIoDestroySndEntry (SndEntry
);
565 Notify function for IP transmit token.
567 @param Event The event signaled.
568 @param Context The context passed in by the event notifier.
577 IpIoTransmitHandler (
583 // Request IpIoTransmitHandlerDpc as a DPC at TPL_CALLBACK
585 NetLibQueueDpc (TPL_CALLBACK
, IpIoTransmitHandlerDpc
, Context
);
590 The dummy handler for the dummy IP receive token.
592 @param Context The context passed in by the event notifier.
600 IpIoDummyHandlerDpc (
604 IP_IO_IP_INFO
*IpInfo
;
605 EFI_IP4_COMPLETION_TOKEN
*DummyToken
;
607 IpInfo
= (IP_IO_IP_INFO
*) Context
;
608 DummyToken
= &(IpInfo
->DummyRcvToken
);
610 if (EFI_ABORTED
== DummyToken
->Status
) {
612 // The reception is actively aborted by the consumer, directly return.
615 } else if (EFI_SUCCESS
== DummyToken
->Status
) {
616 ASSERT (DummyToken
->Packet
.RxData
);
618 gBS
->SignalEvent (DummyToken
->Packet
.RxData
->RecycleSignal
);
621 IpInfo
->Ip
->Receive (IpInfo
->Ip
, DummyToken
);
626 Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK.
628 @param Event The event signaled.
629 @param Context The context passed in by the event notifier.
643 // Request IpIoDummyHandlerDpc as a DPC at TPL_CALLBACK
645 NetLibQueueDpc (TPL_CALLBACK
, IpIoDummyHandlerDpc
, Context
);
650 Notify function for the IP receive token, used to process
651 the received IP packets.
653 @param Context The context passed in by the event notifier.
661 IpIoListenHandlerDpc (
667 EFI_IP4_RECEIVE_DATA
*RxData
;
668 EFI_IP4_PROTOCOL
*Ip
;
669 EFI_NET_SESSION_DATA Session
;
672 IpIo
= (IP_IO
*) Context
;
675 Status
= IpIo
->RcvToken
.Status
;
676 RxData
= IpIo
->RcvToken
.Packet
.RxData
;
678 if (EFI_ABORTED
== Status
) {
680 // The reception is actively aborted by the consumer, directly return.
685 if (((EFI_SUCCESS
!= Status
) && (EFI_ICMP_ERROR
!= Status
)) || (NULL
== RxData
)) {
687 // Only process the normal packets and the icmp error packets, if RxData is NULL
688 // with Status == EFI_SUCCESS or EFI_ICMP_ERROR, just resume the receive although
689 // this should be a bug of the low layer (IP).
694 if (NULL
== IpIo
->PktRcvdNotify
) {
698 if ((EFI_IP4 (RxData
->Header
->SourceAddress
) != 0) &&
699 !Ip4IsUnicast (EFI_NTOHL (RxData
->Header
->SourceAddress
), 0)) {
701 // The source address is not zero and it's not a unicast IP address, discard it.
707 // Create a netbuffer representing packet
709 Pkt
= NetbufFromExt (
710 (NET_FRAGMENT
*) RxData
->FragmentTable
,
711 RxData
->FragmentCount
,
715 RxData
->RecycleSignal
722 // Create a net session
724 Session
.Source
= EFI_IP4 (RxData
->Header
->SourceAddress
);
725 Session
.Dest
= EFI_IP4 (RxData
->Header
->DestinationAddress
);
726 Session
.IpHdr
= RxData
->Header
;
728 if (EFI_SUCCESS
== Status
) {
730 IpIo
->PktRcvdNotify (EFI_SUCCESS
, (ICMP_ERROR
) 0, &Session
, Pkt
, IpIo
->RcvdContext
);
733 // Status is EFI_ICMP_ERROR
735 Status
= IpIoIcmpHandler (IpIo
, Pkt
, &Session
);
736 if (EFI_ERROR (Status
)) {
744 gBS
->SignalEvent (RxData
->RecycleSignal
);
747 Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
752 Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
754 @param Event The event signaled.
755 @param Context The context passed in by the event notifier.
769 // Request IpIoListenHandlerDpc as a DPC at TPL_CALLBACK
771 NetLibQueueDpc (TPL_CALLBACK
, IpIoListenHandlerDpc
, Context
);
776 Create a new IP_IO instance.
778 @param Image The image handle of an IP_IO consumer protocol.
779 @param Controller The controller handle of an IP_IO consumer protocol
782 @return Pointer to a newly created IP_IO instance.
788 IN EFI_HANDLE Controller
794 IpIo
= NetAllocateZeroPool (sizeof (IP_IO
));
799 NetListInit (&(IpIo
->PendingSndList
));
800 NetListInit (&(IpIo
->IpList
));
801 IpIo
->Controller
= Controller
;
804 Status
= gBS
->CreateEvent (
809 &(IpIo
->RcvToken
.Event
)
811 if (EFI_ERROR (Status
)) {
816 // Create an IP child and open IP protocol
818 Status
= IpIoCreateIpChildOpenProtocol (
824 if (EFI_ERROR (Status
)) {
832 if (NULL
!= IpIo
->RcvToken
.Event
) {
833 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
843 Open an IP_IO instance for use.
845 @param IpIo Pointer to an IP_IO instance that needs to open.
846 @param OpenData The configuration data for the IP_IO instance.
848 @retval EFI_SUCCESS The IP_IO instance opened with OpenData
850 @retval other Error condition occurred.
856 IN IP_IO_OPEN_DATA
*OpenData
860 EFI_IP4_PROTOCOL
*Ip
;
862 if (IpIo
->IsConfigured
) {
863 return EFI_ACCESS_DENIED
;
871 Status
= Ip
->Configure (Ip
, &OpenData
->IpConfigData
);
872 if (EFI_ERROR (Status
)) {
877 // bugbug: to delete the default route entry in this Ip, if it is:
878 // (0.0.0.0, 0.0.0.0, 0.0.0.0). Delete this statement if Ip modified
881 Status
= Ip
->Routes (Ip
, TRUE
, &mZeroIp4Addr
, &mZeroIp4Addr
, &mZeroIp4Addr
);
883 if (EFI_ERROR (Status
) && (EFI_NOT_FOUND
!= Status
)) {
887 IpIo
->PktRcvdNotify
= OpenData
->PktRcvdNotify
;
888 IpIo
->PktSentNotify
= OpenData
->PktSentNotify
;
890 IpIo
->RcvdContext
= OpenData
->RcvdContext
;
891 IpIo
->SndContext
= OpenData
->SndContext
;
893 IpIo
->Protocol
= OpenData
->IpConfigData
.DefaultProtocol
;
896 // start to listen incoming packet
898 Status
= Ip
->Receive (Ip
, &(IpIo
->RcvToken
));
899 if (EFI_ERROR (Status
)) {
900 Ip
->Configure (Ip
, NULL
);
904 IpIo
->IsConfigured
= TRUE
;
905 NetListInsertTail (&mActiveIpIoList
, &IpIo
->Entry
);
914 Stop an IP_IO instance.
916 @param IpIo Pointer to the IP_IO instance that needs to stop.
918 @retval EFI_SUCCESS The IP_IO instance stopped successfully.
919 @retval other Error condition occurred.
928 EFI_IP4_PROTOCOL
*Ip
;
929 IP_IO_IP_INFO
*IpInfo
;
931 if (!IpIo
->IsConfigured
) {
936 // Remove the IpIo from the active IpIo list.
938 NetListRemoveEntry (&IpIo
->Entry
);
945 Status
= Ip
->Configure (Ip
, NULL
);
946 if (EFI_ERROR (Status
)) {
950 IpIo
->IsConfigured
= FALSE
;
953 // Detroy the Ip List used by IpIo
956 while (!NetListIsEmpty (&(IpIo
->IpList
))) {
957 IpInfo
= NET_LIST_HEAD (&(IpIo
->IpList
), IP_IO_IP_INFO
, Entry
);
959 IpIoRemoveIp (IpIo
, IpInfo
);
963 // All pending snd tokens should be flushed by reseting the IP instances.
965 ASSERT (NetListIsEmpty (&IpIo
->PendingSndList
));
968 // Close the receive event.
970 gBS
->CloseEvent (IpIo
->RcvToken
.Event
);
977 Destroy an IP_IO instance.
979 @param IpIo Pointer to the IP_IO instance that needs to
982 @retval EFI_SUCCESS The IP_IO instance destroyed successfully.
983 @retval other Error condition occurred.
997 // Close the IP protocol and destroy the child.
999 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpIo
->ChildHandle
);
1008 Send out an IP packet.
1010 @param IpIo Pointer to an IP_IO instance used for sending IP
1012 @param Pkt Pointer to the IP packet to be sent.
1013 @param Sender The IP protocol instance used for sending.
1015 @param Dest The destination IP address to send this packet to.
1016 @param OverrideData The data to override some configuration of the IP
1017 instance used for sending.
1019 @retval EFI_SUCCESS The operation is completed successfully.
1020 @retval EFI_NOT_STARTED The IpIo is not configured.
1021 @retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
1028 IN IP_IO_IP_INFO
*Sender
,
1029 IN VOID
*Context OPTIONAL
,
1030 IN VOID
*NotifyData OPTIONAL
,
1032 IN IP_IO_OVERRIDE
*OverrideData
1036 EFI_IP4_PROTOCOL
*Ip
;
1037 IP_IO_SEND_ENTRY
*SndEntry
;
1039 if (!IpIo
->IsConfigured
) {
1040 return EFI_NOT_STARTED
;
1043 Ip
= (NULL
== Sender
) ? IpIo
->Ip
: Sender
->Ip
;
1046 // create a new SndEntry
1048 SndEntry
= IpIoCreateSndEntry (IpIo
, Pkt
, Ip
, Context
, NotifyData
, Dest
, OverrideData
);
1049 if (NULL
== SndEntry
) {
1050 return EFI_OUT_OF_RESOURCES
;
1056 Status
= Ip
->Transmit (Ip
, SndEntry
->SndToken
);
1057 if (EFI_ERROR (Status
)) {
1058 IpIoDestroySndEntry (SndEntry
);
1066 Cancel the IP transmit token which wraps this Packet.
1068 @param IpIo Pointer to the IP_IO instance.
1069 @param Packet Pointer to the packet to cancel.
1080 NET_LIST_ENTRY
*Node
;
1081 IP_IO_SEND_ENTRY
*SndEntry
;
1082 EFI_IP4_PROTOCOL
*Ip
;
1084 ASSERT (IpIo
&& Packet
);
1086 NET_LIST_FOR_EACH (Node
, &IpIo
->PendingSndList
) {
1088 SndEntry
= NET_LIST_USER_STRUCT (Node
, IP_IO_SEND_ENTRY
, Entry
);
1090 if (SndEntry
->Pkt
== Packet
) {
1093 Ip
->Cancel (Ip
, SndEntry
->SndToken
);
1103 Add a new IP instance for sending data.
1105 @param IpIo Pointer to a IP_IO instance to add a new IP
1106 instance for sending purpose.
1108 @return Pointer to the created IP_IO_IP_INFO structure, NULL is failed.
1117 IP_IO_IP_INFO
*IpInfo
;
1121 IpInfo
= NetAllocatePool (sizeof (IP_IO_IP_INFO
));
1122 if (IpInfo
== NULL
) {
1127 // Init this IpInfo, set the Addr and SubnetMask to 0 before we configure the IP
1130 NetListInit (&IpInfo
->Entry
);
1131 IpInfo
->ChildHandle
= NULL
;
1133 IpInfo
->SubnetMask
= 0;
1137 // Create the IP instance and open the Ip4 protocol.
1139 Status
= IpIoCreateIpChildOpenProtocol (
1142 &IpInfo
->ChildHandle
,
1143 (VOID
**) &IpInfo
->Ip
1145 if (EFI_ERROR (Status
)) {
1150 // Create the event for the DummyRcvToken.
1152 Status
= gBS
->CreateEvent (
1157 &IpInfo
->DummyRcvToken
.Event
1159 if (EFI_ERROR (Status
)) {
1160 goto ReleaseIpChild
;
1164 // Link this IpInfo into the IpIo.
1166 NetListInsertTail (&IpIo
->IpList
, &IpInfo
->Entry
);
1172 IpIoCloseProtocolDestroyIpChild (
1180 NetFreePool (IpInfo
);
1187 Configure the IP instance of this IpInfo and start the receiving if Ip4ConfigData
1190 @param IpInfo Pointer to the IP_IO_IP_INFO instance.
1191 @param Ip4ConfigData The IP4 configure data used to configure the ip
1192 instance, if NULL the ip instance is reseted. If
1193 UseDefaultAddress is set to TRUE, and the configure
1194 operation succeeds, the default address information
1195 is written back in this Ip4ConfigData.
1197 @retval EFI_STATUS The status returned by IP4->Configure or
1203 IN IP_IO_IP_INFO
*IpInfo
,
1204 IN OUT EFI_IP4_CONFIG_DATA
*Ip4ConfigData OPTIONAL
1208 EFI_IP4_PROTOCOL
*Ip
;
1209 EFI_IP4_MODE_DATA Ip4ModeData
;
1213 if (IpInfo
->RefCnt
> 1) {
1215 // This IP instance is shared, don't reconfigure it until it has only one
1216 // consumer. Currently, only the tcp children cloned from their passive parent
1217 // will share the same IP. So this cases only happens while Ip4ConfigData is NULL,
1218 // let the last consumer clean the IP instance.
1225 Status
= Ip
->Configure (Ip
, Ip4ConfigData
);
1226 if (EFI_ERROR (Status
)) {
1230 if (Ip4ConfigData
!= NULL
) {
1232 if (Ip4ConfigData
->UseDefaultAddress
) {
1233 Ip
->GetModeData (Ip
, &Ip4ModeData
, NULL
, NULL
);
1235 Ip4ConfigData
->StationAddress
= Ip4ModeData
.ConfigData
.StationAddress
;
1236 Ip4ConfigData
->SubnetMask
= Ip4ModeData
.ConfigData
.SubnetMask
;
1239 NetCopyMem (&IpInfo
->Addr
, &Ip4ConfigData
->StationAddress
, sizeof (IP4_ADDR
));
1240 NetCopyMem (&IpInfo
->SubnetMask
, &Ip4ConfigData
->SubnetMask
, sizeof (IP4_ADDR
));
1242 Status
= Ip
->Receive (Ip
, &IpInfo
->DummyRcvToken
);
1243 if (EFI_ERROR (Status
)) {
1244 Ip
->Configure (Ip
, NULL
);
1249 // The IP instance is reseted, set the stored Addr and SubnetMask to zero.
1252 IpInfo
->SubnetMask
=0;
1262 Destroy an IP instance maintained in IpIo->IpList for
1265 @param IpIo Pointer to the IP_IO instance.
1266 @param IpInfo Pointer to the IpInfo to be removed.
1274 IN IP_IO_IP_INFO
*IpInfo
1277 ASSERT (IpInfo
->RefCnt
> 0);
1279 NET_PUT_REF (IpInfo
);
1281 if (IpInfo
->RefCnt
> 0) {
1286 NetListRemoveEntry (&IpInfo
->Entry
);
1288 IpInfo
->Ip
->Configure (IpInfo
->Ip
, NULL
);
1290 IpIoCloseProtocolDestroyIpChild (IpIo
->Controller
, IpIo
->Image
, IpInfo
->ChildHandle
);
1292 gBS
->CloseEvent (IpInfo
->DummyRcvToken
.Event
);
1294 NetFreePool (IpInfo
);
1299 Find the first IP protocol maintained in IpIo whose local
1300 address is the same with Src.
1302 @param IpIo Pointer to the pointer of the IP_IO instance.
1303 @param Src The local IP address.
1305 @return Pointer to the IP protocol can be used for sending purpose and its local
1306 @return address is the same with Src.
1311 IN OUT IP_IO
**IpIo
,
1315 NET_LIST_ENTRY
*IpIoEntry
;
1317 NET_LIST_ENTRY
*IpInfoEntry
;
1318 IP_IO_IP_INFO
*IpInfo
;
1320 NET_LIST_FOR_EACH (IpIoEntry
, &mActiveIpIoList
) {
1321 IpIoPtr
= NET_LIST_USER_STRUCT (IpIoEntry
, IP_IO
, Entry
);
1323 if ((*IpIo
!= NULL
) && (*IpIo
!= IpIoPtr
)) {
1327 NET_LIST_FOR_EACH (IpInfoEntry
, &IpIoPtr
->IpList
) {
1328 IpInfo
= NET_LIST_USER_STRUCT (IpInfoEntry
, IP_IO_IP_INFO
, Entry
);
1330 if (IpInfo
->Addr
== Src
) {
1345 Get the ICMP error map information, the ErrorStatus will be returned.
1346 The IsHard and Notify are optional. If they are not NULL, this rouine will
1348 We move IcmpErrMap[] to local variable to enable EBC build.
1350 @param IcmpError IcmpError Type
1351 @param IsHard Whether it is a hard error
1352 @param Notify Whether it need to notify SockError
1354 @return ICMP Error Status
1358 IpIoGetIcmpErrStatus (
1359 IN ICMP_ERROR IcmpError
,
1360 OUT BOOLEAN
*IsHard
, OPTIONAL
1361 OUT BOOLEAN
*Notify OPTIONAL
1364 ASSERT ((IcmpError
>= ICMP_ERR_UNREACH_NET
) && (IcmpError
<= ICMP_ERR_PARAMPROB
));
1366 if (IsHard
!= NULL
) {
1367 *IsHard
= mIcmpErrMap
[IcmpError
].IsHard
;
1370 if (Notify
!= NULL
) {
1371 *Notify
= mIcmpErrMap
[IcmpError
].Notify
;
1374 switch (IcmpError
) {
1375 case ICMP_ERR_UNREACH_NET
:
1376 return EFI_NETWORK_UNREACHABLE
;
1378 case ICMP_ERR_TIMXCEED_INTRANS
:
1379 case ICMP_ERR_TIMXCEED_REASS
:
1380 case ICMP_ERR_UNREACH_HOST
:
1381 return EFI_HOST_UNREACHABLE
;
1383 case ICMP_ERR_UNREACH_PROTOCOL
:
1384 return EFI_PROTOCOL_UNREACHABLE
;
1386 case ICMP_ERR_UNREACH_PORT
:
1387 return EFI_PORT_UNREACHABLE
;
1389 case ICMP_ERR_MSGSIZE
:
1390 case ICMP_ERR_UNREACH_SRCFAIL
:
1391 case ICMP_ERR_QUENCH
:
1392 case ICMP_ERR_PARAMPROB
:
1393 return EFI_ICMP_ERROR
;
1397 // will never run here!
1400 return EFI_UNSUPPORTED
;