2 Misc support routines for TCP driver.
4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 LIST_ENTRY mTcpRunQue
= {
24 LIST_ENTRY mTcpListenQue
= {
29 TCP_SEQNO mTcpGlobalIss
= TCP_BASE_ISS
;
31 CHAR16
*mTcpStateName
[] = {
47 Initialize the Tcb local related members.
49 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
58 // Compute the checksum of the fixed parts of pseudo header
60 if (Tcb
->Sk
->IpVersion
== IP_VERSION_4
) {
61 Tcb
->HeadSum
= NetPseudoHeadChecksum (
62 Tcb
->LocalEnd
.Ip
.Addr
[0],
63 Tcb
->RemoteEnd
.Ip
.Addr
[0],
68 Tcb
->HeadSum
= NetIp6PseudoHeadChecksum (
70 &Tcb
->RemoteEnd
.Ip
.v6
,
76 Tcb
->Iss
= TcpGetIss ();
77 Tcb
->SndUna
= Tcb
->Iss
;
78 Tcb
->SndNxt
= Tcb
->Iss
;
80 Tcb
->SndWl2
= Tcb
->Iss
;
83 Tcb
->RcvWnd
= GET_RCV_BUFFSIZE (Tcb
->Sk
);
86 // First window size is never scaled
89 Tcb
->RetxmitSeqMax
= 0;
91 Tcb
->ProbeTimerOn
= FALSE
;
95 Initialize the peer related members.
97 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
98 @param[in] Seg Pointer to the segment that contains the peer's intial info.
99 @param[in] Opt Pointer to the options announced by the peer.
111 ASSERT ((Tcb
!= NULL
) && (Seg
!= NULL
) && (Opt
!= NULL
));
112 ASSERT (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
));
114 Tcb
->SndWnd
= Seg
->Wnd
;
115 Tcb
->SndWndMax
= Tcb
->SndWnd
;
116 Tcb
->SndWl1
= Seg
->Seq
;
118 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_ACK
)) {
119 Tcb
->SndWl2
= Seg
->Ack
;
121 Tcb
->SndWl2
= Tcb
->Iss
+ 1;
124 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_MSS
)) {
125 Tcb
->SndMss
= (UINT16
) MAX (64, Opt
->Mss
);
127 RcvMss
= TcpGetRcvMss (Tcb
->Sk
);
128 if (Tcb
->SndMss
> RcvMss
) {
129 Tcb
->SndMss
= RcvMss
;
134 // One end doesn't support MSS option, use default.
139 Tcb
->CWnd
= Tcb
->SndMss
;
142 Tcb
->RcvNxt
= Tcb
->Irs
+ 1;
144 Tcb
->RcvWl2
= Tcb
->RcvNxt
;
146 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_WS
) && !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_WS
)) {
148 Tcb
->SndWndScale
= Opt
->WndScale
;
150 Tcb
->RcvWndScale
= TcpComputeScale (Tcb
);
151 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_WS
);
155 // One end doesn't support window scale option. use zero.
157 Tcb
->RcvWndScale
= 0;
160 if (TCP_FLG_ON (Opt
->Flag
, TCP_OPTION_RCVD_TS
) && !TCP_FLG_ON (Tcb
->CtrlFlag
, TCP_CTRL_NO_TS
)) {
162 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_SND_TS
);
163 TCP_SET_FLG (Tcb
->CtrlFlag
, TCP_CTRL_RCVD_TS
);
165 Tcb
->TsRecent
= Opt
->TSVal
;
168 // Compute the effective SndMss per RFC1122
169 // section 4.2.2.6. If timestamp option is
170 // enabled, it will always occupy 12 bytes.
172 Tcb
->SndMss
-= TCP_OPTION_TS_ALIGNED_LEN
;
177 Check whether one IP address equals the other.
179 @param[in] Ip1 Pointer to IP address to be checked.
180 @param[in] Ip2 Pointer to IP address to be checked.
181 @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
182 IP_VERSION_6 indicates the IP address is an IPv6 address.
184 @retval TRUE Ip1 equals Ip2.
185 @retval FALSE Ip1 does not equal Ip2.
190 IN EFI_IP_ADDRESS
*Ip1
,
191 IN EFI_IP_ADDRESS
*Ip2
,
195 ASSERT ((Version
== IP_VERSION_4
) || (Version
== IP_VERSION_6
));
197 if (Version
== IP_VERSION_4
) {
198 return (BOOLEAN
) (Ip1
->Addr
[0] == Ip2
->Addr
[0]);
200 return (BOOLEAN
) EFI_IP6_EQUAL (&Ip1
->v6
, &Ip2
->v6
);
205 Check whether one IP address is filled with ZERO.
207 @param[in] Ip Pointer to the IP address to be checked.
208 @param[in] Version IP_VERSION_4 indicates the IP address is an IPv4 address,
209 IP_VERSION_6 indicates the IP address is an IPv6 address.
211 @retval TRUE Ip is all zero address.
212 @retval FALSE Ip is not all zero address.
217 IN EFI_IP_ADDRESS
*Ip
,
221 ASSERT ((Version
== IP_VERSION_4
) || (Version
== IP_VERSION_6
));
223 if (Version
== IP_VERSION_4
) {
224 return (BOOLEAN
) (Ip
->Addr
[0] == 0);
226 return (BOOLEAN
) ((Ip
->Addr
[0] == 0) && (Ip
->Addr
[1] == 0) &&
227 (Ip
->Addr
[2] == 0) && (Ip
->Addr
[3] == 0));
232 Locate a listen TCB that matchs the Local and Remote.
234 @param[in] Local Pointer to the local (IP, Port).
235 @param[in] Remote Pointer to the remote (IP, Port).
236 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
237 IP_VERSION_6 indicates TCP is running on IP6 stack.
239 @return Pointer to the TCP_CB with the least number of wildcards,
240 if NULL no match is found.
259 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
260 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
262 if ((Version
!= Node
->Sk
->IpVersion
) ||
263 (Local
->Port
!= Node
->LocalEnd
.Port
) ||
264 !TCP_PEER_MATCH (Remote
, &Node
->RemoteEnd
, Version
) ||
265 !TCP_PEER_MATCH (Local
, &Node
->LocalEnd
, Version
)
272 // Compute the number of wildcard
275 if (TcpIsIpZero (&Node
->RemoteEnd
.Ip
, Version
)) {
279 if (Node
->RemoteEnd
.Port
== 0) {
283 if (TcpIsIpZero (&Node
->LocalEnd
.Ip
, Version
)) {
301 Try to find one Tcb whose <Ip, Port> equals to <IN Addr, IN Port>.
303 @param[in] Addr Pointer to the IP address needs to match.
304 @param[in] Port The port number needs to match.
305 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
306 IP_VERSION_6 indicates TCP is running on IP6 stack.
309 @retval TRUE The Tcb which matches the <Addr Port> pair exists.
310 @retval FALSE Otherwise
315 IN EFI_IP_ADDRESS
*Addr
,
320 TCP_PORTNO LocalPort
;
324 ASSERT ((Addr
!= NULL
) && (Port
!= 0));
326 LocalPort
= HTONS (Port
);
328 NET_LIST_FOR_EACH (Entry
, &mTcpListenQue
) {
329 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
331 if ((Version
== Tcb
->Sk
->IpVersion
) &&
332 TcpIsIpEqual (Addr
, &Tcb
->LocalEnd
.Ip
, Version
) &&
333 (LocalPort
== Tcb
->LocalEnd
.Port
)
340 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
341 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
343 if ((Version
== Tcb
->Sk
->IpVersion
) &&
344 TcpIsIpEqual (Addr
, &Tcb
->LocalEnd
.Ip
, Version
) &&
345 (LocalPort
== Tcb
->LocalEnd
.Port
)
356 Locate the TCP_CB related to the socket pair.
358 @param[in] LocalPort The local port number.
359 @param[in] LocalIp The local IP address.
360 @param[in] RemotePort The remote port number.
361 @param[in] RemoteIp The remote IP address.
362 @param[in] Version IP_VERSION_4 indicates TCP is running on IP4 stack,
363 IP_VERSION_6 indicates TCP is running on IP6 stack.
364 @param[in] Syn If TRUE, the listen sockets are searched.
366 @return Pointer to the related TCP_CB. If NULL, no match is found.
371 IN TCP_PORTNO LocalPort
,
372 IN EFI_IP_ADDRESS
*LocalIp
,
373 IN TCP_PORTNO RemotePort
,
374 IN EFI_IP_ADDRESS
*RemoteIp
,
384 Local
.Port
= LocalPort
;
385 Remote
.Port
= RemotePort
;
387 CopyMem (&Local
.Ip
, LocalIp
, sizeof (EFI_IP_ADDRESS
));
388 CopyMem (&Remote
.Ip
, RemoteIp
, sizeof (EFI_IP_ADDRESS
));
391 // First check for exact match.
393 NET_LIST_FOR_EACH (Entry
, &mTcpRunQue
) {
394 Tcb
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
396 if ((Version
== Tcb
->Sk
->IpVersion
) &&
397 TCP_PEER_EQUAL (&Remote
, &Tcb
->RemoteEnd
, Version
) &&
398 TCP_PEER_EQUAL (&Local
, &Tcb
->LocalEnd
, Version
)
401 RemoveEntryList (&Tcb
->List
);
402 InsertHeadList (&mTcpRunQue
, &Tcb
->List
);
409 // Only check the listen queue when the SYN flag is on.
412 return TcpLocateListenTcb (&Local
, &Remote
, Version
);
419 Insert a Tcb into the proper queue.
421 @param[in] Tcb Pointer to the TCP_CB to be inserted.
423 @retval 0 The Tcb was inserted successfully.
424 @retval -1 Error condition occurred.
439 (Tcb
->State
== TCP_LISTEN
) ||
440 (Tcb
->State
== TCP_SYN_SENT
) ||
441 (Tcb
->State
== TCP_SYN_RCVD
) ||
442 (Tcb
->State
== TCP_CLOSED
)
446 if (Tcb
->LocalEnd
.Port
== 0) {
452 if (Tcb
->State
== TCP_LISTEN
) {
453 Head
= &mTcpListenQue
;
457 // Check that the Tcb isn't already on the list.
459 NET_LIST_FOR_EACH (Entry
, Head
) {
460 Node
= NET_LIST_USER_STRUCT (Entry
, TCP_CB
, List
);
462 if (TCP_PEER_EQUAL (&Tcb
->LocalEnd
, &Node
->LocalEnd
, Tcb
->Sk
->IpVersion
) &&
463 TCP_PEER_EQUAL (&Tcb
->RemoteEnd
, &Node
->RemoteEnd
, Tcb
->Sk
->IpVersion
)
470 InsertHeadList (Head
, &Tcb
->List
);
477 Clone a TCP_CB from Tcb.
479 @param[in] Tcb Pointer to the TCP_CB to be cloned.
481 @return Pointer to the new cloned TCP_CB; if NULL, error condition occurred.
491 Clone
= AllocateZeroPool (sizeof (TCP_CB
));
497 CopyMem (Clone
, Tcb
, sizeof (TCP_CB
));
500 // Increase the reference count of the shared IpInfo.
502 NET_GET_REF (Tcb
->IpInfo
);
504 InitializeListHead (&Clone
->List
);
505 InitializeListHead (&Clone
->SndQue
);
506 InitializeListHead (&Clone
->RcvQue
);
508 Clone
->Sk
= SockClone (Tcb
->Sk
);
509 if (Clone
->Sk
== NULL
) {
510 DEBUG ((EFI_D_ERROR
, "TcpCloneTcb: failed to clone a sock\n"));
515 ((TCP_PROTO_DATA
*) (Clone
->Sk
->ProtoReserved
))->TcpPcb
= Clone
;
521 Compute an ISS to be used by a new connection.
523 @return The resulting ISS.
531 mTcpGlobalIss
+= TCP_ISS_INCREMENT_1
;
532 return mTcpGlobalIss
;
538 @param[in] Sock Pointer to the socket to get mss.
540 @return The mss size.
548 EFI_IP4_MODE_DATA Ip4Mode
;
549 EFI_IP6_MODE_DATA Ip6Mode
;
550 EFI_IP4_PROTOCOL
*Ip4
;
551 EFI_IP6_PROTOCOL
*Ip6
;
552 TCP_PROTO_DATA
*TcpProto
;
554 ASSERT (Sock
!= NULL
);
556 ZeroMem (&Ip4Mode
, sizeof (EFI_IP4_MODE_DATA
));
557 ZeroMem (&Ip6Mode
, sizeof (EFI_IP6_MODE_DATA
));
559 TcpProto
= (TCP_PROTO_DATA
*) Sock
->ProtoReserved
;
561 if (Sock
->IpVersion
== IP_VERSION_4
) {
562 Ip4
= TcpProto
->TcpService
->IpIo
->Ip
.Ip4
;
563 ASSERT (Ip4
!= NULL
);
564 Ip4
->GetModeData (Ip4
, &Ip4Mode
, NULL
, NULL
);
566 return (UINT16
) (Ip4Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
568 Ip6
= TcpProto
->TcpService
->IpIo
->Ip
.Ip6
;
569 ASSERT (Ip6
!= NULL
);
570 if (!EFI_ERROR (Ip6
->GetModeData (Ip6
, &Ip6Mode
, NULL
, NULL
))) {
571 if (Ip6Mode
.AddressList
!= NULL
) {
572 FreePool (Ip6Mode
.AddressList
);
575 if (Ip6Mode
.GroupTable
!= NULL
) {
576 FreePool (Ip6Mode
.GroupTable
);
579 if (Ip6Mode
.RouteTable
!= NULL
) {
580 FreePool (Ip6Mode
.RouteTable
);
583 if (Ip6Mode
.NeighborCache
!= NULL
) {
584 FreePool (Ip6Mode
.NeighborCache
);
587 if (Ip6Mode
.PrefixTable
!= NULL
) {
588 FreePool (Ip6Mode
.PrefixTable
);
591 if (Ip6Mode
.IcmpTypeList
!= NULL
) {
592 FreePool (Ip6Mode
.IcmpTypeList
);
596 return (UINT16
) (Ip6Mode
.MaxPacketSize
- sizeof (TCP_HEAD
));
603 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
604 @param[in] State The state to be set.
613 ASSERT (Tcb
->State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
614 ASSERT (State
< (sizeof (mTcpStateName
) / sizeof (CHAR16
*)));
618 "Tcb (%p) state %s --> %s\n",
620 mTcpStateName
[Tcb
->State
],
621 mTcpStateName
[State
])
627 case TCP_ESTABLISHED
:
629 SockConnEstablished (Tcb
->Sk
);
631 if (Tcb
->Parent
!= NULL
) {
633 // A new connection is accepted by a listening socket. Install
636 TcpInstallDevicePath (Tcb
->Sk
);
643 SockConnClosed (Tcb
->Sk
);
652 Compute the TCP segment's checksum.
654 @param[in] Nbuf Pointer to the buffer that contains the TCP segment.
655 @param[in] HeadSum The checksum value of the fixed part of pseudo header.
657 @return The checksum value.
668 Checksum
= NetbufChecksum (Nbuf
);
669 Checksum
= NetAddChecksum (Checksum
, HeadSum
);
671 Checksum
= NetAddChecksum (
673 HTONS ((UINT16
) Nbuf
->TotalSize
)
676 return (UINT16
) (~Checksum
);
680 Translate the information from the head of the received TCP
681 segment Nbuf contents and fill it into a TCP_SEG structure.
683 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
684 @param[in, out] Nbuf Pointer to the buffer contains the TCP segment.
686 @return Pointer to the TCP_SEG that contains the translated TCP head information.
698 Seg
= TCPSEG_NETBUF (Nbuf
);
699 Head
= (TCP_HEAD
*) NetbufGetByte (Nbuf
, 0, NULL
);
700 ASSERT (Head
!= NULL
);
704 Seg
->Seq
= NTOHL (Head
->Seq
);
705 Seg
->Ack
= NTOHL (Head
->Ack
);
706 Seg
->End
= Seg
->Seq
+ (Nbuf
->TotalSize
- (Head
->HeadLen
<< 2));
708 Seg
->Urg
= NTOHS (Head
->Urg
);
709 Seg
->Wnd
= (NTOHS (Head
->Wnd
) << Tcb
->SndWndScale
);
710 Seg
->Flag
= Head
->Flag
;
713 // SYN and FIN flag occupy one sequence space each.
715 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_SYN
)) {
717 // RFC requires that the initial window not be scaled.
719 Seg
->Wnd
= NTOHS (Head
->Wnd
);
723 if (TCP_FLG_ON (Seg
->Flag
, TCP_FLG_FIN
)) {
731 Initialize an active connection.
733 @param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
742 TcpInitTcbLocal (Tcb
);
743 TcpSetState (Tcb
, TCP_SYN_SENT
);
745 TcpSetTimer (Tcb
, TCP_TIMER_CONNECT
, Tcb
->ConnectTimeout
);
746 TcpToSendData (Tcb
, 1);
750 Initiate the connection close procedure, called when
751 applications want to close the connection.
753 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
761 ASSERT (Tcb
!= NULL
);
763 if (!IsListEmpty (&Tcb
->RcvQue
) || GET_RCV_DATASIZE (Tcb
->Sk
) != 0) {
767 "TcpOnAppClose: connection reset because data is lost for TCB %p\n",
771 TcpResetConnection (Tcb
);
776 switch (Tcb
->State
) {
780 TcpSetState (Tcb
, TCP_CLOSED
);
784 case TCP_ESTABLISHED
:
785 TcpSetState (Tcb
, TCP_FIN_WAIT_1
);
789 TcpSetState (Tcb
, TCP_LAST_ACK
);
795 TcpToSendData (Tcb
, 1);
799 Check whether the application's newly delivered data can be sent out.
801 @param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
803 @retval 0 The data has been sent out successfully.
804 @retval -1 The Tcb is not in a state that data is permitted to
814 switch (Tcb
->State
) {
825 case TCP_ESTABLISHED
:
827 TcpToSendData (Tcb
, 0);
845 Application has consumed some data. Check whether
846 to send a window update ack or a delayed ack.
848 @param[in] Tcb Pointer to the TCP_CB of this TCP instance.
858 switch (Tcb
->State
) {
859 case TCP_ESTABLISHED
:
860 TcpOld
= TcpRcvWinOld (Tcb
);
861 if (TcpRcvWinNow (Tcb
) > TcpOld
) {
863 if (TcpOld
< Tcb
->RcvMss
) {
867 "TcpOnAppConsume: send a window update for a window closed Tcb %p\n",
872 } else if (Tcb
->DelayedAck
== 0) {
876 "TcpOnAppConsume: scheduled a delayed ACK to update window for Tcb %p\n",
892 Abort the connection by sending a reset segment. Called
893 when the application wants to abort the connection.
895 @param[in] Tcb Pointer to the TCP_CB of the TCP instance.
905 "TcpOnAppAbort: connection reset issued by application for TCB %p\n",
909 switch (Tcb
->State
) {
911 case TCP_ESTABLISHED
:
915 TcpResetConnection (Tcb
);
921 TcpSetState (Tcb
, TCP_CLOSED
);
925 Reset the connection related with Tcb.
927 @param[in] Tcb Pointer to the TCP_CB of the connection to be reset.
938 Nbuf
= NetbufAlloc (TCP_MAX_HEAD
);
944 Nhead
= (TCP_HEAD
*) NetbufAllocSpace (
950 ASSERT (Nhead
!= NULL
);
954 Nhead
->Flag
= TCP_FLG_RST
;
955 Nhead
->Seq
= HTONL (Tcb
->SndNxt
);
956 Nhead
->Ack
= HTONL (Tcb
->RcvNxt
);
957 Nhead
->SrcPort
= Tcb
->LocalEnd
.Port
;
958 Nhead
->DstPort
= Tcb
->RemoteEnd
.Port
;
959 Nhead
->HeadLen
= (UINT8
) (sizeof (TCP_HEAD
) >> 2);
961 Nhead
->Wnd
= HTONS (0xFFFF);
964 Nhead
->Checksum
= TcpChecksum (Nbuf
, Tcb
->HeadSum
);
966 TcpSendIpPacket (Tcb
, Nbuf
, &Tcb
->LocalEnd
.Ip
, &Tcb
->RemoteEnd
.Ip
, Tcb
->Sk
->IpVersion
);
972 Install the device path protocol on the TCP instance.
974 @param[in] Sock Pointer to the socket representing the TCP instance.
976 @retval EFI_SUCCESS The device path protocol was installed.
977 @retval other Failed to install the device path protocol.
981 TcpInstallDevicePath (
985 TCP_PROTO_DATA
*TcpProto
;
986 TCP_SERVICE_DATA
*TcpService
;
988 IPv4_DEVICE_PATH Ip4DPathNode
;
989 IPv6_DEVICE_PATH Ip6DPathNode
;
990 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
992 TCP_PORTNO LocalPort
;
993 TCP_PORTNO RemotePort
;
995 TcpProto
= (TCP_PROTO_DATA
*) Sock
->ProtoReserved
;
996 TcpService
= TcpProto
->TcpService
;
997 Tcb
= TcpProto
->TcpPcb
;
999 LocalPort
= NTOHS (Tcb
->LocalEnd
.Port
);
1000 RemotePort
= NTOHS (Tcb
->RemoteEnd
.Port
);
1001 if (Sock
->IpVersion
== IP_VERSION_4
) {
1002 NetLibCreateIPv4DPathNode (
1004 TcpService
->ControllerHandle
,
1005 Tcb
->LocalEnd
.Ip
.Addr
[0],
1007 Tcb
->RemoteEnd
.Ip
.Addr
[0],
1013 IP4_COPY_ADDRESS (&Ip4DPathNode
.SubnetMask
, &Tcb
->SubnetMask
);
1015 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) &Ip4DPathNode
;
1017 NetLibCreateIPv6DPathNode (
1019 TcpService
->ControllerHandle
,
1020 &Tcb
->LocalEnd
.Ip
.v6
,
1022 &Tcb
->RemoteEnd
.Ip
.v6
,
1027 DevicePath
= (EFI_DEVICE_PATH_PROTOCOL
*) &Ip6DPathNode
;
1030 Sock
->DevicePath
= AppendDevicePathNode (Sock
->ParentDevicePath
, DevicePath
);
1031 if (Sock
->DevicePath
== NULL
) {
1032 return EFI_OUT_OF_RESOURCES
;
1035 Status
= gBS
->InstallProtocolInterface (
1037 &gEfiDevicePathProtocolGuid
,
1038 EFI_NATIVE_INTERFACE
,
1041 if (EFI_ERROR (Status
)) {
1042 FreePool (Sock
->DevicePath
);
1043 Sock
->DevicePath
= NULL
;