2 Implement the UDP4 driver support for the socket layer.
4 Copyright (c) 2011 - 2015, Intel Corporation
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.
19 Get the local socket address
21 This routine returns the IPv4 address and UDP port number associated
22 with the local socket.
24 This routine is called by ::EslSocketGetLocalAddress to determine the
25 network address for the SOCK_DGRAM socket.
27 @param [in] pPort Address of an ::ESL_PORT structure.
29 @param [out] pSockAddr Network address to receive the local system address
33 EslUdp4LocalAddressGet (
35 OUT
struct sockaddr
* pSockAddr
38 struct sockaddr_in
* pLocalAddress
;
39 ESL_UDP4_CONTEXT
* pUdp4
;
44 // Return the local address
46 pUdp4
= &pPort
->Context
.Udp4
;
47 pLocalAddress
= (struct sockaddr_in
*)pSockAddr
;
48 pLocalAddress
->sin_family
= AF_INET
;
49 pLocalAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.StationPort
);
50 CopyMem ( &pLocalAddress
->sin_addr
,
51 &pUdp4
->ConfigData
.StationAddress
.Addr
[0],
52 sizeof ( pLocalAddress
->sin_addr
));
59 Set the local port address.
61 This routine sets the local port address.
63 This support routine is called by ::EslSocketPortAllocate.
65 @param [in] pPort Address of an ESL_PORT structure
66 @param [in] pSockAddr Address of a sockaddr structure that contains the
67 connection point on the local machine. An IPv4 address
68 of INADDR_ANY specifies that the connection is made to
69 all of the network stacks on the platform. Specifying a
70 specific IPv4 address restricts the connection to the
71 network stack supporting that address. Specifying zero
72 for the port causes the network layer to assign a port
73 number from the dynamic range. Specifying a specific
74 port number causes the network layer to use that port.
76 @param [in] bBindTest TRUE = run bind testing
78 @retval EFI_SUCCESS The operation was successful
82 EslUdp4LocalAddressSet (
84 IN CONST
struct sockaddr
* pSockAddr
,
88 EFI_UDP4_CONFIG_DATA
* pConfig
;
89 CONST
struct sockaddr_in
* pIpAddress
;
90 CONST UINT8
* pIpv4Address
;
96 // Validate the address
98 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
99 if ( INADDR_BROADCAST
== pIpAddress
->sin_addr
.s_addr
) {
101 // The local address must not be the broadcast address
103 Status
= EFI_INVALID_PARAMETER
;
104 pPort
->pSocket
->errno
= EADDRNOTAVAIL
;
108 // Set the local address
110 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
111 pIpv4Address
= (UINT8
*)&pIpAddress
->sin_addr
.s_addr
;
112 pConfig
= &pPort
->Context
.Udp4
.ConfigData
;
113 pConfig
->StationAddress
.Addr
[0] = pIpv4Address
[0];
114 pConfig
->StationAddress
.Addr
[1] = pIpv4Address
[1];
115 pConfig
->StationAddress
.Addr
[2] = pIpv4Address
[2];
116 pConfig
->StationAddress
.Addr
[3] = pIpv4Address
[3];
119 // Determine if the default address is used
121 pConfig
->UseDefaultAddress
= (BOOLEAN
)( 0 == pIpAddress
->sin_addr
.s_addr
);
124 // Set the subnet mask
126 if ( pConfig
->UseDefaultAddress
) {
127 pConfig
->SubnetMask
.Addr
[0] = 0;
128 pConfig
->SubnetMask
.Addr
[1] = 0;
129 pConfig
->SubnetMask
.Addr
[2] = 0;
130 pConfig
->SubnetMask
.Addr
[3] = 0;
133 pConfig
->SubnetMask
.Addr
[0] = 0xff;
134 pConfig
->SubnetMask
.Addr
[1] = ( 128 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
135 pConfig
->SubnetMask
.Addr
[2] = ( 192 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
136 pConfig
->SubnetMask
.Addr
[3] = ( 224 <= pConfig
->StationAddress
.Addr
[0]) ? 0xff : 0;
140 // Validate the IP address
142 pConfig
->StationPort
= 0;
143 Status
= bBindTest
? EslSocketBindTest ( pPort
, EADDRNOTAVAIL
)
145 if ( !EFI_ERROR ( Status
)) {
147 // Set the port number
149 pConfig
->StationPort
= SwapBytes16 ( pIpAddress
->sin_port
);
152 // Display the local address
155 "0x%08x: Port, Local UDP4 Address: %d.%d.%d.%d:%d\r\n",
157 pConfig
->StationAddress
.Addr
[0],
158 pConfig
->StationAddress
.Addr
[1],
159 pConfig
->StationAddress
.Addr
[2],
160 pConfig
->StationAddress
.Addr
[3],
161 pConfig
->StationPort
));
166 // Return the operation status
168 DBG_EXIT_STATUS ( Status
);
174 Free a receive packet
176 This routine performs the network specific operations necessary
177 to free a receive packet.
179 This routine is called by ::EslSocketPortCloseTxDone to free a
182 @param [in] pPacket Address of an ::ESL_PACKET structure.
183 @param [in, out] pRxBytes Address of the count of RX bytes
188 IN ESL_PACKET
* pPacket
,
189 IN OUT
size_t * pRxBytes
192 EFI_UDP4_RECEIVE_DATA
* pRxData
;
197 // Account for the receive bytes
199 pRxData
= pPacket
->Op
.Udp4Rx
.pRxData
;
200 *pRxBytes
-= pRxData
->DataLength
;
203 // Disconnect the buffer from the packet
205 pPacket
->Op
.Udp4Rx
.pRxData
= NULL
;
208 // Return the buffer to the UDP4 driver
210 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
216 Initialize the network specific portions of an ::ESL_PORT structure.
218 This routine initializes the network specific portions of an
219 ::ESL_PORT structure for use by the socket.
221 This support routine is called by ::EslSocketPortAllocate
222 to connect the socket with the underlying network adapter
223 running the UDPv4 protocol.
225 @param [in] pPort Address of an ESL_PORT structure
226 @param [in] DebugFlags Flags for debug messages
228 @retval EFI_SUCCESS - Socket successfully created
232 EslUdp4PortAllocate (
237 EFI_UDP4_CONFIG_DATA
* pConfig
;
238 ESL_SOCKET
* pSocket
;
244 // Initialize the port
246 pSocket
= pPort
->pSocket
;
247 pSocket
->TxPacketOffset
= OFFSET_OF ( ESL_PACKET
, Op
.Udp4Tx
.TxData
);
248 pSocket
->TxTokenEventOffset
= OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp4Tx
.Event
);
249 pSocket
->TxTokenOffset
= OFFSET_OF ( EFI_UDP4_COMPLETION_TOKEN
, Packet
.TxData
);
252 // Save the cancel, receive and transmit addresses
254 pPort
->pfnConfigure
= (PFN_NET_CONFIGURE
)pPort
->pProtocol
.UDPv4
->Configure
;
255 pPort
->pfnRxCancel
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Cancel
;
256 pPort
->pfnRxPoll
= (PFN_NET_POLL
)pPort
->pProtocol
.UDPv4
->Poll
;
257 pPort
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Receive
;
258 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Transmit
;
261 // Set the configuration flags
263 pConfig
= &pPort
->Context
.Udp4
.ConfigData
;
264 pConfig
->TimeToLive
= 255;
265 pConfig
->AcceptAnyPort
= FALSE
;
266 pConfig
->AcceptBroadcast
= FALSE
;
267 pConfig
->AcceptPromiscuous
= FALSE
;
268 pConfig
->AllowDuplicatePort
= TRUE
;
269 pConfig
->DoNotFragment
= FALSE
;
270 Status
= EFI_SUCCESS
;
273 // Return the operation status
275 DBG_EXIT_STATUS ( Status
);
281 Receive data from a network connection.
283 This routine attempts to return buffered data to the caller. The
284 data is removed from the urgent queue if the message flag MSG_OOB
285 is specified, otherwise data is removed from the normal queue.
286 See the \ref ReceiveEngine section.
288 This routine is called by ::EslSocketReceive to handle the network
289 specific receive operation to support SOCK_DGRAM sockets.
291 @param [in] pPort Address of an ::ESL_PORT structure.
293 @param [in] pPacket Address of an ::ESL_PACKET structure.
295 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
297 @param [in] BufferLength Length of the the buffer
299 @param [in] pBuffer Address of a buffer to receive the data.
301 @param [in] pDataLength Number of received data bytes in the buffer.
303 @param [out] pAddress Network address to receive the remote system address
305 @param [out] pSkipBytes Address to receive the number of bytes skipped
307 @return Returns the address of the next free byte in the buffer.
313 IN ESL_PACKET
* pPacket
,
314 IN BOOLEAN
* pbConsumePacket
,
315 IN
size_t BufferLength
,
317 OUT
size_t * pDataLength
,
318 OUT
struct sockaddr
* pAddress
,
319 OUT
size_t * pSkipBytes
323 struct sockaddr_in
* pRemoteAddress
;
324 EFI_UDP4_RECEIVE_DATA
* pRxData
;
328 pRxData
= pPacket
->Op
.Udp4Rx
.pRxData
;
330 // Return the remote system address if requested
332 if ( NULL
!= pAddress
) {
334 // Build the remote address
337 "Getting packet remote address: %d.%d.%d.%d:%d\r\n",
338 pRxData
->UdpSession
.SourceAddress
.Addr
[0],
339 pRxData
->UdpSession
.SourceAddress
.Addr
[1],
340 pRxData
->UdpSession
.SourceAddress
.Addr
[2],
341 pRxData
->UdpSession
.SourceAddress
.Addr
[3],
342 pRxData
->UdpSession
.SourcePort
));
343 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
344 CopyMem ( &pRemoteAddress
->sin_addr
,
345 &pRxData
->UdpSession
.SourceAddress
.Addr
[0],
346 sizeof ( pRemoteAddress
->sin_addr
));
347 pRemoteAddress
->sin_port
= SwapBytes16 ( pRxData
->UdpSession
.SourcePort
);
351 // Copy the received data
353 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
354 (EFI_IP4_FRAGMENT_DATA
*)&pRxData
->FragmentTable
[0],
360 // Determine if the data is being read
362 if ( *pbConsumePacket
) {
364 // Display for the bytes consumed
367 "0x%08x: Port account for 0x%08x bytes\r\n",
372 // Account for any discarded data
374 *pSkipBytes
= pRxData
->DataLength
- DataBytes
;
378 // Return the data length and the buffer address
380 *pDataLength
= DataBytes
;
381 DBG_EXIT_HEX ( pBuffer
);
387 Get the remote socket address
389 This routine returns the address of the remote connection point
390 associated with the SOCK_DGRAM socket.
392 This routine is called by ::EslSocketGetPeerAddress to detemine
393 the UDPv4 address and port number associated with the network adapter.
395 @param [in] pPort Address of an ::ESL_PORT structure.
397 @param [out] pAddress Network address to receive the remote system address
401 EslUdp4RemoteAddressGet (
403 OUT
struct sockaddr
* pAddress
406 struct sockaddr_in
* pRemoteAddress
;
407 ESL_UDP4_CONTEXT
* pUdp4
;
412 // Return the remote address
414 pUdp4
= &pPort
->Context
.Udp4
;
415 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
416 pRemoteAddress
->sin_family
= AF_INET
;
417 pRemoteAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.RemotePort
);
418 CopyMem ( &pRemoteAddress
->sin_addr
,
419 &pUdp4
->ConfigData
.RemoteAddress
.Addr
[0],
420 sizeof ( pRemoteAddress
->sin_addr
));
427 Set the remote address
429 This routine sets the remote address in the port.
431 This routine is called by ::EslSocketConnect to specify the
432 remote network address.
434 @param [in] pPort Address of an ::ESL_PORT structure.
436 @param [in] pSockAddr Network address of the remote system.
438 @param [in] SockAddrLength Length in bytes of the network address.
440 @retval EFI_SUCCESS The operation was successful
444 EslUdp4RemoteAddressSet (
446 IN CONST
struct sockaddr
* pSockAddr
,
447 IN socklen_t SockAddrLength
450 CONST
struct sockaddr_in
* pRemoteAddress
;
451 ESL_UDP4_CONTEXT
* pUdp4
;
457 // Set the remote address
459 pUdp4
= &pPort
->Context
.Udp4
;
460 pRemoteAddress
= (struct sockaddr_in
*)pSockAddr
;
461 pUdp4
->ConfigData
.RemoteAddress
.Addr
[0] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
);
462 pUdp4
->ConfigData
.RemoteAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
463 pUdp4
->ConfigData
.RemoteAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
464 pUdp4
->ConfigData
.RemoteAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
465 pUdp4
->ConfigData
.RemotePort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
466 pPort
->pSocket
->bAddressSet
= TRUE
;
467 Status
= EFI_SUCCESS
;
470 // Return the operation status
472 DBG_EXIT_STATUS ( Status
);
478 Process the receive completion
480 This routine keeps the UDPv4 driver's buffer and queues it in
481 in FIFO order to the data queue. The UDP4 driver's buffer will
482 be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone.
483 See the \ref ReceiveEngine section.
485 This routine is called by the UDPv4 driver when data is
488 @param [in] Event The receive completion event
490 @param [in] pIo Address of an ::ESL_IO_MGMT structure
499 size_t LengthInBytes
;
500 ESL_PACKET
* pPacket
;
501 EFI_UDP4_RECEIVE_DATA
* pRxData
;
507 // Get the operation status.
509 Status
= pIo
->Token
.Udp4Rx
.Status
;
512 // Get the packet length
514 pRxData
= pIo
->Token
.Udp4Rx
.Packet
.RxData
;
515 LengthInBytes
= pRxData
->DataLength
;
518 // +--------------------+ +-----------------------+
519 // | ESL_IO_MGMT | | Data Buffer |
520 // | | | (Driver owned) |
521 // | +---------------+ +-----------------------+
524 // | | | +-----------------------+
525 // | | RxData --> | EFI_UDP4_RECEIVE_DATA |
526 // +----+---------------+ | (Driver owned) |
527 // +-----------------------+
528 // +--------------------+ ^
531 // | +---------------+ .
532 // | | pRxData --> NULL .......
533 // +----+---------------+
536 // Save the data in the packet
538 pPacket
= pIo
->pPacket
;
539 pPacket
->Op
.Udp4Rx
.pRxData
= pRxData
;
542 // Complete this request
544 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, FALSE
);
550 Determine if the socket is configured.
552 This routine uses the flag ESL_SOCKET::bConfigured to determine
553 if the network layer's configuration routine has been called.
554 This routine calls the bind and configuration routines if they
555 were not already called. After the port is configured, the
556 \ref ReceiveEngine is started.
558 This routine is called by EslSocketIsConfigured to verify
559 that the socket is configured.
561 @param [in] pSocket Address of an ::ESL_SOCKET structure
563 @retval EFI_SUCCESS - The port is connected
564 @retval EFI_NOT_STARTED - The port is not connected
568 EslUdp4SocketIsConfigured (
569 IN ESL_SOCKET
* pSocket
572 EFI_UDP4_CONFIG_DATA
* pConfigData
;
574 ESL_PORT
* pNextPort
;
575 ESL_UDP4_CONTEXT
* pUdp4
;
576 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
578 struct sockaddr_in LocalAddress
;
585 Status
= EFI_SUCCESS
;
588 // Configure the port if necessary
590 if ( !pSocket
->bConfigured
) {
592 // Fill in the port list if necessary
594 pSocket
->errno
= ENETDOWN
;
595 if ( NULL
== pSocket
->pPortList
) {
596 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
597 LocalAddress
.sin_family
= AF_INET
;
598 LocalAddress
.sin_addr
.s_addr
= 0;
599 LocalAddress
.sin_port
= 0;
600 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
601 (struct sockaddr
*)&LocalAddress
,
602 LocalAddress
.sin_len
,
607 // Walk the port list
609 pPort
= pSocket
->pPortList
;
610 while ( NULL
!= pPort
) {
612 // Attempt to configure the port
614 pNextPort
= pPort
->pLinkSocket
;
615 pUdp4
= &pPort
->Context
.Udp4
;
616 pUdp4Protocol
= pPort
->pProtocol
.UDPv4
;
617 pConfigData
= &pUdp4
->ConfigData
;
619 "0x%08x: pPort Configuring for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
621 pConfigData
->StationAddress
.Addr
[0],
622 pConfigData
->StationAddress
.Addr
[1],
623 pConfigData
->StationAddress
.Addr
[2],
624 pConfigData
->StationAddress
.Addr
[3],
625 pConfigData
->StationPort
,
626 pConfigData
->RemoteAddress
.Addr
[0],
627 pConfigData
->RemoteAddress
.Addr
[1],
628 pConfigData
->RemoteAddress
.Addr
[2],
629 pConfigData
->RemoteAddress
.Addr
[3],
630 pConfigData
->RemotePort
));
631 Status
= pUdp4Protocol
->Configure ( pUdp4Protocol
,
633 if ( !EFI_ERROR ( Status
)) {
635 // Update the configuration data
637 Status
= pUdp4Protocol
->GetModeData ( pUdp4Protocol
,
643 if ( EFI_ERROR ( Status
)) {
644 if ( !pSocket
->bConfigured
) {
645 DEBUG (( DEBUG_LISTEN
,
646 "ERROR - Failed to configure the Udp4 port, Status: %r\r\n",
649 case EFI_ACCESS_DENIED
:
650 pSocket
->errno
= EACCES
;
654 case EFI_DEVICE_ERROR
:
655 pSocket
->errno
= EIO
;
658 case EFI_INVALID_PARAMETER
:
659 pSocket
->errno
= EADDRNOTAVAIL
;
663 pSocket
->errno
= EAFNOSUPPORT
;
666 case EFI_OUT_OF_RESOURCES
:
667 pSocket
->errno
= ENOBUFS
;
670 case EFI_UNSUPPORTED
:
671 pSocket
->errno
= EOPNOTSUPP
;
678 "0x%08x: pPort Configured for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
680 pConfigData
->StationAddress
.Addr
[0],
681 pConfigData
->StationAddress
.Addr
[1],
682 pConfigData
->StationAddress
.Addr
[2],
683 pConfigData
->StationAddress
.Addr
[3],
684 pConfigData
->StationPort
,
685 pConfigData
->RemoteAddress
.Addr
[0],
686 pConfigData
->RemoteAddress
.Addr
[1],
687 pConfigData
->RemoteAddress
.Addr
[2],
688 pConfigData
->RemoteAddress
.Addr
[3],
689 pConfigData
->RemotePort
));
690 pPort
->bConfigured
= TRUE
;
691 pSocket
->bConfigured
= TRUE
;
694 // Start the first read on the port
696 EslSocketRxStart ( pPort
);
699 // The socket is connected
701 pSocket
->State
= SOCKET_STATE_CONNECTED
;
713 // Determine the socket configuration status
715 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
718 // Return the port connected state.
720 DBG_EXIT_STATUS ( Status
);
726 Buffer data for transmission over a network connection.
728 This routine buffers data for the transmit engine in the normal
729 data queue. When the \ref TransmitEngine has resources, this
730 routine will start the transmission of the next buffer on the
733 This routine is called by ::EslSocketTransmit to buffer
734 data for transmission. The data is copied into a local buffer
735 freeing the application buffer for reuse upon return. When
736 necessary, this routine starts the transmit engine that
737 performs the data transmission on the network connection. The
738 transmit engine transmits the data a packet at a time over the
741 Transmission errors are returned during the next transmission or
742 during the close operation. Only buffering errors are returned
743 during the current transmission attempt.
745 @param [in] pSocket Address of an ::ESL_SOCKET structure
747 @param [in] Flags Message control flags
749 @param [in] BufferLength Length of the the buffer
751 @param [in] pBuffer Address of a buffer to receive the data.
753 @param [in] pDataLength Number of received data bytes in the buffer.
755 @param [in] pAddress Network address of the remote system address
757 @param [in] AddressLength Length of the remote network address structure
759 @retval EFI_SUCCESS - Socket data successfully buffered
764 IN ESL_SOCKET
* pSocket
,
766 IN
size_t BufferLength
,
767 IN CONST UINT8
* pBuffer
,
768 OUT
size_t * pDataLength
,
769 IN
const struct sockaddr
* pAddress
,
770 IN socklen_t AddressLength
773 ESL_PACKET
* pPacket
;
774 ESL_PACKET
* pPreviousPacket
;
776 const struct sockaddr_in
* pRemoteAddress
;
777 ESL_UDP4_CONTEXT
* pUdp4
;
779 ESL_UDP4_TX_DATA
* pTxData
;
788 Status
= EFI_UNSUPPORTED
;
789 pSocket
->errno
= ENOTCONN
;
793 // Verify that the socket is connected
795 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
797 // Verify that there is enough room to buffer another
798 // transmit operation
800 pTxBytes
= &pSocket
->TxBytes
;
801 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
805 pPort
= pSocket
->pPortList
;
806 while ( NULL
!= pPort
) {
808 // Determine the queue head
810 pUdp4
= &pPort
->Context
.Udp4
;
813 // Attempt to allocate the packet
815 Status
= EslSocketPacketAllocate ( &pPacket
,
816 sizeof ( pPacket
->Op
.Udp4Tx
)
817 - sizeof ( pPacket
->Op
.Udp4Tx
.Buffer
)
821 if ( !EFI_ERROR ( Status
)) {
823 // Initialize the transmit operation
825 pTxData
= &pPacket
->Op
.Udp4Tx
;
826 pTxData
->TxData
.GatewayAddress
= NULL
;
827 pTxData
->TxData
.UdpSessionData
= NULL
;
828 pTxData
->TxData
.DataLength
= (UINT32
) BufferLength
;
829 pTxData
->TxData
.FragmentCount
= 1;
830 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
831 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Udp4Tx
.Buffer
[0];
832 pTxData
->RetransmitCount
= 0;
835 // Set the remote system address if necessary
837 pTxData
->TxData
.UdpSessionData
= NULL
;
838 if ( NULL
!= pAddress
) {
839 pRemoteAddress
= (const struct sockaddr_in
*)pAddress
;
840 pTxData
->Session
.SourceAddress
.Addr
[0] = pUdp4
->ConfigData
.StationAddress
.Addr
[0];
841 pTxData
->Session
.SourceAddress
.Addr
[1] = pUdp4
->ConfigData
.StationAddress
.Addr
[1];
842 pTxData
->Session
.SourceAddress
.Addr
[2] = pUdp4
->ConfigData
.StationAddress
.Addr
[2];
843 pTxData
->Session
.SourceAddress
.Addr
[3] = pUdp4
->ConfigData
.StationAddress
.Addr
[3];
844 pTxData
->Session
.SourcePort
= 0;
845 pTxData
->Session
.DestinationAddress
.Addr
[0] = (UINT8
)pRemoteAddress
->sin_addr
.s_addr
;
846 pTxData
->Session
.DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
847 pTxData
->Session
.DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
848 pTxData
->Session
.DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
849 pTxData
->Session
.DestinationPort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
852 // Use the remote system address when sending this packet
854 pTxData
->TxData
.UdpSessionData
= &pTxData
->Session
;
858 // Copy the data into the buffer
860 CopyMem ( &pPacket
->Op
.Udp4Tx
.Buffer
[0],
865 // Synchronize with the socket layer
867 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
870 // Display the request
873 "Send %d bytes from 0x%08x to %d.%d.%d.%d:%d\r\n",
876 pTxData
->Session
.DestinationAddress
.Addr
[0],
877 pTxData
->Session
.DestinationAddress
.Addr
[1],
878 pTxData
->Session
.DestinationAddress
.Addr
[2],
879 pTxData
->Session
.DestinationAddress
.Addr
[3],
880 pTxData
->Session
.DestinationPort
));
883 // Queue the data for transmission
885 pPacket
->pNext
= NULL
;
886 pPreviousPacket
= pSocket
->pTxPacketListTail
;
887 if ( NULL
== pPreviousPacket
) {
888 pSocket
->pTxPacketListHead
= pPacket
;
891 pPreviousPacket
->pNext
= pPacket
;
893 pSocket
->pTxPacketListTail
= pPacket
;
895 "0x%08x: Packet on transmit list\r\n",
899 // Account for the buffered data
901 *pTxBytes
+= BufferLength
;
902 *pDataLength
= BufferLength
;
905 // Start the transmit engine if it is idle
907 if ( NULL
!= pPort
->pTxFree
) {
908 pPacket
= pSocket
->pTxPacketListHead
;
909 EslSocketTxStart ( pPort
,
910 &pSocket
->pTxPacketListHead
,
911 &pSocket
->pTxPacketListTail
,
916 // Ignore any transmit error
918 if ( EFI_ERROR ( pSocket
->TxError
)) {
920 "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
925 pSocket
->TxError
= EFI_SUCCESS
;
929 // Release the socket layer synchronization
931 RESTORE_TPL ( TplPrevious
);
935 // Packet allocation failed
937 pSocket
->errno
= ENOMEM
;
944 pPort
= pPort
->pLinkSocket
;
949 // Not enough buffer space available
951 pSocket
->errno
= EAGAIN
;
952 Status
= EFI_NOT_READY
;
957 // Return the operation status
959 DBG_EXIT_STATUS ( Status
);
965 Process the transmit completion
967 This routine use ::EslSocketTxComplete to perform the transmit
968 completion processing for data packets.
970 This routine is called by the UDPv4 network layer when a data
971 transmit request completes.
973 @param [in] Event The normal transmit completion event
975 @param [in] pIo Address of an ::ESL_IO_MGMT structure
984 UINT32 LengthInBytes
;
986 ESL_PACKET
* pPacket
;
987 ESL_SOCKET
* pSocket
;
993 // Locate the active transmit packet
995 pPacket
= pIo
->pPacket
;
997 pSocket
= pPort
->pSocket
;
1000 // Get the transmit length and status
1002 LengthInBytes
= pPacket
->Op
.Udp4Tx
.TxData
.DataLength
;
1003 pSocket
->TxBytes
-= LengthInBytes
;
1004 Status
= pIo
->Token
.Udp4Tx
.Status
;
1007 // Ignore the transmit error
1009 if ( EFI_ERROR ( Status
)) {
1011 "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
1015 Status
= EFI_SUCCESS
;
1019 // Complete the transmit operation
1021 EslSocketTxComplete ( pIo
,
1025 &pSocket
->pTxPacketListHead
,
1026 &pSocket
->pTxPacketListTail
,
1034 Verify the adapter's IP address
1036 This support routine is called by EslSocketBindTest.
1038 @param [in] pPort Address of an ::ESL_PORT structure.
1039 @param [in] pConfigData Address of the configuration data
1041 @retval EFI_SUCCESS - The IP address is valid
1042 @retval EFI_NOT_STARTED - The IP address is invalid
1046 EslUdp4VerifyLocalIpAddress (
1047 IN ESL_PORT
* pPort
,
1048 IN EFI_UDP4_CONFIG_DATA
* pConfigData
1052 EFI_IP4_CONFIG2_INTERFACE_INFO
* pIfInfo
;
1053 EFI_IP4_CONFIG2_PROTOCOL
* pIpConfig2Protocol
;
1054 ESL_SERVICE
* pService
;
1060 // Use break instead of goto
1065 // Determine if the IP address is specified
1067 DEBUG (( DEBUG_BIND
,
1068 "UseDefaultAddress: %s\r\n",
1069 pConfigData
->UseDefaultAddress
? L
"TRUE" : L
"FALSE" ));
1070 DEBUG (( DEBUG_BIND
,
1071 "Requested IP address: %d.%d.%d.%d\r\n",
1072 pConfigData
->StationAddress
.Addr
[ 0 ],
1073 pConfigData
->StationAddress
.Addr
[ 1 ],
1074 pConfigData
->StationAddress
.Addr
[ 2 ],
1075 pConfigData
->StationAddress
.Addr
[ 3 ]));
1076 if ( pConfigData
->UseDefaultAddress
1077 || (( 0 == pConfigData
->StationAddress
.Addr
[ 0 ])
1078 && ( 0 == pConfigData
->StationAddress
.Addr
[ 1 ])
1079 && ( 0 == pConfigData
->StationAddress
.Addr
[ 2 ])
1080 && ( 0 == pConfigData
->StationAddress
.Addr
[ 3 ])))
1082 Status
= EFI_SUCCESS
;
1087 // Open the configuration protocol
1089 pService
= pPort
->pService
;
1090 Status
= gBS
->OpenProtocol (
1091 pService
->Controller
,
1092 &gEfiIp4Config2ProtocolGuid
,
1093 (VOID
**)&pIpConfig2Protocol
,
1096 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1098 if ( EFI_ERROR ( Status
)) {
1099 DEBUG (( DEBUG_ERROR
,
1100 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
1106 // Get the interface information size
1109 Status
= pIpConfig2Protocol
->GetData (
1111 Ip4Config2DataTypeInterfaceInfo
,
1115 if ( EFI_BUFFER_TOO_SMALL
!= Status
) {
1116 DEBUG (( DEBUG_ERROR
,
1117 "ERROR - Failed to get the interface information size, Status: %r\r\n",
1123 // Allocate the interface information buffer
1125 pIfInfo
= AllocatePool ( DataSize
);
1126 if ( NULL
== pIfInfo
) {
1127 DEBUG (( DEBUG_ERROR
,
1128 "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));
1129 Status
= EFI_OUT_OF_RESOURCES
;
1134 // Get the interface info.
1136 Status
= pIpConfig2Protocol
->GetData (
1138 Ip4Config2DataTypeInterfaceInfo
,
1142 if ( EFI_ERROR ( Status
)) {
1143 DEBUG (( DEBUG_ERROR
,
1144 "ERROR - Failed to return the interface info, Status: %r\r\n",
1150 // Display the current configuration
1152 DEBUG (( DEBUG_BIND
,
1153 "Actual adapter IP address: %d.%d.%d.%d\r\n",
1154 pIfInfo
->StationAddress
.Addr
[ 0 ],
1155 pIfInfo
->StationAddress
.Addr
[ 1 ],
1156 pIfInfo
->StationAddress
.Addr
[ 2 ],
1157 pIfInfo
->StationAddress
.Addr
[ 3 ]));
1160 // Assume the port is not configured
1162 Status
= EFI_SUCCESS
;
1163 if (( pConfigData
->StationAddress
.Addr
[ 0 ] == pIfInfo
->StationAddress
.Addr
[ 0 ])
1164 && ( pConfigData
->StationAddress
.Addr
[ 1 ] == pIfInfo
->StationAddress
.Addr
[ 1 ])
1165 && ( pConfigData
->StationAddress
.Addr
[ 2 ] == pIfInfo
->StationAddress
.Addr
[ 2 ])
1166 && ( pConfigData
->StationAddress
.Addr
[ 3 ] == pIfInfo
->StationAddress
.Addr
[ 3 ])) {
1171 // The IP address did not match
1173 Status
= EFI_NOT_STARTED
;
1178 // Free the buffer if necessary
1180 if ( NULL
!= pIfInfo
) {
1181 FreePool ( pIfInfo
);
1185 // Return the IP address status
1187 DBG_EXIT_STATUS ( Status
);
1193 Interface between the socket layer and the network specific
1194 code that supports SOCK_DGRAM sockets over UDPv4.
1196 CONST ESL_PROTOCOL_API cEslUdp4Api
= {
1199 OFFSET_OF ( ESL_PORT
, Context
.Udp4
.ConfigData
),
1200 OFFSET_OF ( ESL_LAYER
, pUdp4List
),
1201 OFFSET_OF ( struct sockaddr_in
, sin_zero
),
1202 sizeof ( struct sockaddr_in
),
1204 sizeof (((ESL_PACKET
*)0 )->Op
.Udp4Rx
),
1205 sizeof (((ESL_PACKET
*)0 )->Op
.Udp4Rx
),
1206 OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp4Rx
.Packet
.RxData
),
1210 NULL
, // ConnectPoll
1211 NULL
, // ConnectStart
1212 EslUdp4SocketIsConfigured
,
1213 EslUdp4LocalAddressGet
,
1214 EslUdp4LocalAddressSet
,
1219 EslUdp4PortAllocate
,
1221 NULL
, // PortCloseOp
1224 EslUdp4RemoteAddressGet
,
1225 EslUdp4RemoteAddressSet
,
1230 NULL
, // TxOobComplete
1231 (PFN_API_VERIFY_LOCAL_IP_ADDRESS
)EslUdp4VerifyLocalIpAddress