2 Implement the UDP4 driver support for the socket layer.
4 Copyright (c) 2011, 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] = 0xff;
135 pConfig
->SubnetMask
.Addr
[2] = 0xff;
136 pConfig
->SubnetMask
.Addr
[3] = 0xff;
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
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Receive
;
257 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Transmit
;
260 // Set the configuration flags
262 pConfig
= &pPort
->Context
.Udp4
.ConfigData
;
263 pConfig
->TimeToLive
= 255;
264 pConfig
->AcceptAnyPort
= FALSE
;
265 pConfig
->AcceptBroadcast
= FALSE
;
266 pConfig
->AcceptPromiscuous
= FALSE
;
267 pConfig
->AllowDuplicatePort
= TRUE
;
268 pConfig
->DoNotFragment
= TRUE
;
269 Status
= EFI_SUCCESS
;
272 // Return the operation status
274 DBG_EXIT_STATUS ( Status
);
280 Receive data from a network connection.
282 This routine attempts to return buffered data to the caller. The
283 data is removed from the urgent queue if the message flag MSG_OOB
284 is specified, otherwise data is removed from the normal queue.
285 See the \ref ReceiveEngine section.
287 This routine is called by ::EslSocketReceive to handle the network
288 specific receive operation to support SOCK_DGRAM sockets.
290 @param [in] pPort Address of an ::ESL_PORT structure.
292 @param [in] pPacket Address of an ::ESL_PACKET structure.
294 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
296 @param [in] BufferLength Length of the the buffer
298 @param [in] pBuffer Address of a buffer to receive the data.
300 @param [in] pDataLength Number of received data bytes in the buffer.
302 @param [out] pAddress Network address to receive the remote system address
304 @param [out] pSkipBytes Address to receive the number of bytes skipped
306 @return Returns the address of the next free byte in the buffer.
312 IN ESL_PACKET
* pPacket
,
313 IN BOOLEAN
* pbConsumePacket
,
314 IN
size_t BufferLength
,
316 OUT
size_t * pDataLength
,
317 OUT
struct sockaddr
* pAddress
,
318 OUT
size_t * pSkipBytes
322 struct sockaddr_in
* pRemoteAddress
;
323 EFI_UDP4_RECEIVE_DATA
* pRxData
;
327 pRxData
= pPacket
->Op
.Udp4Rx
.pRxData
;
329 // Return the remote system address if requested
331 if ( NULL
!= pAddress
) {
333 // Build the remote address
336 "Getting packet remote address: %d.%d.%d.%d:%d\r\n",
337 pRxData
->UdpSession
.SourceAddress
.Addr
[0],
338 pRxData
->UdpSession
.SourceAddress
.Addr
[1],
339 pRxData
->UdpSession
.SourceAddress
.Addr
[2],
340 pRxData
->UdpSession
.SourceAddress
.Addr
[3],
341 pRxData
->UdpSession
.SourcePort
));
342 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
343 CopyMem ( &pRemoteAddress
->sin_addr
,
344 &pRxData
->UdpSession
.SourceAddress
.Addr
[0],
345 sizeof ( pRemoteAddress
->sin_addr
));
346 pRemoteAddress
->sin_port
= SwapBytes16 ( pRxData
->UdpSession
.SourcePort
);
350 // Copy the received data
352 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
353 (EFI_IP4_FRAGMENT_DATA
*)&pRxData
->FragmentTable
[0],
359 // Determine if the data is being read
361 if ( *pbConsumePacket
) {
363 // Display for the bytes consumed
366 "0x%08x: Port account for 0x%08x bytes\r\n",
371 // Account for any discarded data
373 *pSkipBytes
= pRxData
->DataLength
- DataBytes
;
377 // Return the data length and the buffer address
379 *pDataLength
= DataBytes
;
380 DBG_EXIT_HEX ( pBuffer
);
386 Get the remote socket address
388 This routine returns the address of the remote connection point
389 associated with the SOCK_DGRAM socket.
391 This routine is called by ::EslSocketGetPeerAddress to detemine
392 the UDPv4 address and port number associated with the network adapter.
394 @param [in] pPort Address of an ::ESL_PORT structure.
396 @param [out] pAddress Network address to receive the remote system address
400 EslUdp4RemoteAddressGet (
402 OUT
struct sockaddr
* pAddress
405 struct sockaddr_in
* pRemoteAddress
;
406 ESL_UDP4_CONTEXT
* pUdp4
;
411 // Return the remote address
413 pUdp4
= &pPort
->Context
.Udp4
;
414 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
415 pRemoteAddress
->sin_family
= AF_INET
;
416 pRemoteAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.RemotePort
);
417 CopyMem ( &pRemoteAddress
->sin_addr
,
418 &pUdp4
->ConfigData
.RemoteAddress
.Addr
[0],
419 sizeof ( pRemoteAddress
->sin_addr
));
426 Set the remote address
428 This routine sets the remote address in the port.
430 This routine is called by ::EslSocketConnect to specify the
431 remote network address.
433 @param [in] pPort Address of an ::ESL_PORT structure.
435 @param [in] pSockAddr Network address of the remote system.
437 @param [in] SockAddrLength Length in bytes of the network address.
439 @retval EFI_SUCCESS The operation was successful
443 EslUdp4RemoteAddressSet (
445 IN CONST
struct sockaddr
* pSockAddr
,
446 IN socklen_t SockAddrLength
449 CONST
struct sockaddr_in
* pRemoteAddress
;
450 ESL_UDP4_CONTEXT
* pUdp4
;
456 // Set the remote address
458 pUdp4
= &pPort
->Context
.Udp4
;
459 pRemoteAddress
= (struct sockaddr_in
*)pSockAddr
;
460 pUdp4
->ConfigData
.RemoteAddress
.Addr
[0] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
);
461 pUdp4
->ConfigData
.RemoteAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
462 pUdp4
->ConfigData
.RemoteAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
463 pUdp4
->ConfigData
.RemoteAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
464 pUdp4
->ConfigData
.RemotePort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
465 Status
= EFI_SUCCESS
;
468 // Return the operation status
470 DBG_EXIT_STATUS ( Status
);
476 Process the receive completion
478 This routine keeps the UDPv4 driver's buffer and queues it in
479 in FIFO order to the data queue. The UDP4 driver's buffer will
480 be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone.
481 See the \ref ReceiveEngine section.
483 This routine is called by the UDPv4 driver when data is
486 @param [in] Event The receive completion event
488 @param [in] pIo Address of an ::ESL_IO_MGMT structure
497 size_t LengthInBytes
;
498 ESL_PACKET
* pPacket
;
499 EFI_UDP4_RECEIVE_DATA
* pRxData
;
505 // Get the operation status.
507 Status
= pIo
->Token
.Udp4Rx
.Status
;
510 // Get the packet length
512 pRxData
= pIo
->Token
.Udp4Rx
.Packet
.RxData
;
513 LengthInBytes
= pRxData
->DataLength
;
516 // +--------------------+ +-----------------------+
517 // | ESL_IO_MGMT | | Data Buffer |
518 // | | | (Driver owned) |
519 // | +---------------+ +-----------------------+
522 // | | | +-----------------------+
523 // | | RxData --> | EFI_UDP4_RECEIVE_DATA |
524 // +----+---------------+ | (Driver owned) |
525 // +-----------------------+
526 // +--------------------+ ^
529 // | +---------------+ .
530 // | | pRxData --> NULL .......
531 // +----+---------------+
534 // Save the data in the packet
536 pPacket
= pIo
->pPacket
;
537 pPacket
->Op
.Udp4Rx
.pRxData
= pRxData
;
540 // Complete this request
542 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, FALSE
);
548 Determine if the socket is configured.
550 This routine uses the flag ESL_SOCKET::bConfigured to determine
551 if the network layer's configuration routine has been called.
552 This routine calls the bind and configuration routines if they
553 were not already called. After the port is configured, the
554 \ref ReceiveEngine is started.
556 This routine is called by EslSocketIsConfigured to verify
557 that the socket is configured.
559 @param [in] pSocket Address of an ::ESL_SOCKET structure
561 @retval EFI_SUCCESS - The port is connected
562 @retval EFI_NOT_STARTED - The port is not connected
566 EslUdp4SocketIsConfigured (
567 IN ESL_SOCKET
* pSocket
570 EFI_UDP4_CONFIG_DATA
* pConfigData
;
572 ESL_PORT
* pNextPort
;
573 ESL_UDP4_CONTEXT
* pUdp4
;
574 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
576 struct sockaddr_in LocalAddress
;
583 Status
= EFI_SUCCESS
;
586 // Configure the port if necessary
588 if ( !pSocket
->bConfigured
) {
590 // Fill in the port list if necessary
592 if ( NULL
== pSocket
->pPortList
) {
593 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
594 LocalAddress
.sin_family
= AF_INET
;
595 LocalAddress
.sin_addr
.s_addr
= 0;
596 LocalAddress
.sin_port
= 0;
597 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
598 (struct sockaddr
*)&LocalAddress
,
599 LocalAddress
.sin_len
,
604 // Walk the port list
606 pPort
= pSocket
->pPortList
;
607 while ( NULL
!= pPort
) {
609 // Attempt to configure the port
611 pNextPort
= pPort
->pLinkSocket
;
612 pUdp4
= &pPort
->Context
.Udp4
;
613 pUdp4Protocol
= pPort
->pProtocol
.UDPv4
;
614 pConfigData
= &pUdp4
->ConfigData
;
616 "0x%08x: pPort Configuring for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
618 pConfigData
->StationAddress
.Addr
[0],
619 pConfigData
->StationAddress
.Addr
[1],
620 pConfigData
->StationAddress
.Addr
[2],
621 pConfigData
->StationAddress
.Addr
[3],
622 pConfigData
->StationPort
,
623 pConfigData
->RemoteAddress
.Addr
[0],
624 pConfigData
->RemoteAddress
.Addr
[1],
625 pConfigData
->RemoteAddress
.Addr
[2],
626 pConfigData
->RemoteAddress
.Addr
[3],
627 pConfigData
->RemotePort
));
628 Status
= pUdp4Protocol
->Configure ( pUdp4Protocol
,
630 if ( !EFI_ERROR ( Status
)) {
632 // Update the configuration data
634 Status
= pUdp4Protocol
->GetModeData ( pUdp4Protocol
,
640 if ( EFI_ERROR ( Status
)) {
641 DEBUG (( DEBUG_LISTEN
,
642 "ERROR - Failed to configure the Udp4 port, Status: %r\r\n",
645 case EFI_ACCESS_DENIED
:
646 pSocket
->errno
= EACCES
;
650 case EFI_DEVICE_ERROR
:
651 pSocket
->errno
= EIO
;
654 case EFI_INVALID_PARAMETER
:
655 pSocket
->errno
= EADDRNOTAVAIL
;
659 pSocket
->errno
= EAFNOSUPPORT
;
662 case EFI_OUT_OF_RESOURCES
:
663 pSocket
->errno
= ENOBUFS
;
666 case EFI_UNSUPPORTED
:
667 pSocket
->errno
= EOPNOTSUPP
;
673 "0x%08x: pPort Configured for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
675 pConfigData
->StationAddress
.Addr
[0],
676 pConfigData
->StationAddress
.Addr
[1],
677 pConfigData
->StationAddress
.Addr
[2],
678 pConfigData
->StationAddress
.Addr
[3],
679 pConfigData
->StationPort
,
680 pConfigData
->RemoteAddress
.Addr
[0],
681 pConfigData
->RemoteAddress
.Addr
[1],
682 pConfigData
->RemoteAddress
.Addr
[2],
683 pConfigData
->RemoteAddress
.Addr
[3],
684 pConfigData
->RemotePort
));
685 pPort
->bConfigured
= TRUE
;
688 // Start the first read on the port
690 EslSocketRxStart ( pPort
);
693 // The socket is connected
695 pSocket
->State
= SOCKET_STATE_CONNECTED
;
705 // Determine the configuration status
707 if ( NULL
!= pSocket
->pPortList
) {
708 pSocket
->bConfigured
= TRUE
;
713 // Determine the socket configuration status
715 if ( !EFI_ERROR ( Status
)) {
716 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
720 // Return the port connected state.
722 DBG_EXIT_STATUS ( Status
);
728 Buffer data for transmission over a network connection.
730 This routine buffers data for the transmit engine in the normal
731 data queue. When the \ref TransmitEngine has resources, this
732 routine will start the transmission of the next buffer on the
735 This routine is called by ::EslSocketTransmit to buffer
736 data for transmission. The data is copied into a local buffer
737 freeing the application buffer for reuse upon return. When
738 necessary, this routine starts the transmit engine that
739 performs the data transmission on the network connection. The
740 transmit engine transmits the data a packet at a time over the
743 Transmission errors are returned during the next transmission or
744 during the close operation. Only buffering errors are returned
745 during the current transmission attempt.
747 @param [in] pSocket Address of an ::ESL_SOCKET structure
749 @param [in] Flags Message control flags
751 @param [in] BufferLength Length of the the buffer
753 @param [in] pBuffer Address of a buffer to receive the data.
755 @param [in] pDataLength Number of received data bytes in the buffer.
757 @param [in] pAddress Network address of the remote system address
759 @param [in] AddressLength Length of the remote network address structure
761 @retval EFI_SUCCESS - Socket data successfully buffered
766 IN ESL_SOCKET
* pSocket
,
768 IN
size_t BufferLength
,
769 IN CONST UINT8
* pBuffer
,
770 OUT
size_t * pDataLength
,
771 IN
const struct sockaddr
* pAddress
,
772 IN socklen_t AddressLength
775 ESL_PACKET
* pPacket
;
776 ESL_PACKET
* pPreviousPacket
;
778 const struct sockaddr_in
* pRemoteAddress
;
779 ESL_UDP4_CONTEXT
* pUdp4
;
781 ESL_UDP4_TX_DATA
* pTxData
;
790 Status
= EFI_UNSUPPORTED
;
791 pSocket
->errno
= ENOTCONN
;
795 // Verify that the socket is connected
797 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
801 pPort
= pSocket
->pPortList
;
802 if ( NULL
!= pPort
) {
804 // Determine the queue head
806 pUdp4
= &pPort
->Context
.Udp4
;
807 pTxBytes
= &pSocket
->TxBytes
;
810 // Verify that there is enough room to buffer another
811 // transmit operation
813 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
815 // Attempt to allocate the packet
817 Status
= EslSocketPacketAllocate ( &pPacket
,
818 sizeof ( pPacket
->Op
.Udp4Tx
)
819 - sizeof ( pPacket
->Op
.Udp4Tx
.Buffer
)
823 if ( !EFI_ERROR ( Status
)) {
825 // Initialize the transmit operation
827 pTxData
= &pPacket
->Op
.Udp4Tx
;
828 pTxData
->TxData
.GatewayAddress
= NULL
;
829 pTxData
->TxData
.UdpSessionData
= NULL
;
830 pTxData
->TxData
.DataLength
= (UINT32
) BufferLength
;
831 pTxData
->TxData
.FragmentCount
= 1;
832 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
833 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Udp4Tx
.Buffer
[0];
834 pTxData
->RetransmitCount
= 0;
837 // Set the remote system address if necessary
839 pTxData
->TxData
.UdpSessionData
= NULL
;
840 if ( NULL
!= pAddress
) {
841 pRemoteAddress
= (const struct sockaddr_in
*)pAddress
;
842 pTxData
->Session
.SourceAddress
.Addr
[0] = pUdp4
->ConfigData
.StationAddress
.Addr
[0];
843 pTxData
->Session
.SourceAddress
.Addr
[1] = pUdp4
->ConfigData
.StationAddress
.Addr
[1];
844 pTxData
->Session
.SourceAddress
.Addr
[2] = pUdp4
->ConfigData
.StationAddress
.Addr
[2];
845 pTxData
->Session
.SourceAddress
.Addr
[3] = pUdp4
->ConfigData
.StationAddress
.Addr
[3];
846 pTxData
->Session
.SourcePort
= 0;
847 pTxData
->Session
.DestinationAddress
.Addr
[0] = (UINT8
)pRemoteAddress
->sin_addr
.s_addr
;
848 pTxData
->Session
.DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
849 pTxData
->Session
.DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
850 pTxData
->Session
.DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
851 pTxData
->Session
.DestinationPort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
854 // Use the remote system address when sending this packet
856 pTxData
->TxData
.UdpSessionData
= &pTxData
->Session
;
860 // Copy the data into the buffer
862 CopyMem ( &pPacket
->Op
.Udp4Tx
.Buffer
[0],
867 // Synchronize with the socket layer
869 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
872 // Stop transmission after an error
874 if ( !EFI_ERROR ( pSocket
->TxError
)) {
876 // Display the request
879 "Send %d %s bytes from 0x%08x\r\n",
884 // Queue the data for transmission
886 pPacket
->pNext
= NULL
;
887 pPreviousPacket
= pSocket
->pTxPacketListTail
;
888 if ( NULL
== pPreviousPacket
) {
889 pSocket
->pTxPacketListHead
= pPacket
;
892 pPreviousPacket
->pNext
= pPacket
;
894 pSocket
->pTxPacketListTail
= pPacket
;
896 "0x%08x: Packet on transmit list\r\n",
900 // Account for the buffered data
902 *pTxBytes
+= BufferLength
;
903 *pDataLength
= BufferLength
;
906 // Start the transmit engine if it is idle
908 if ( NULL
!= pPort
->pTxFree
) {
909 EslSocketTxStart ( pPort
,
910 &pSocket
->pTxPacketListHead
,
911 &pSocket
->pTxPacketListTail
,
918 // Previous transmit error
921 Status
= pSocket
->TxError
;
922 pSocket
->errno
= EIO
;
927 EslSocketPacketFree ( pPacket
, DEBUG_TX
);
931 // Release the socket layer synchronization
933 RESTORE_TPL ( TplPrevious
);
937 // Packet allocation failed
939 pSocket
->errno
= ENOMEM
;
944 // Not enough buffer space available
946 pSocket
->errno
= EAGAIN
;
947 Status
= EFI_NOT_READY
;
953 // Return the operation status
955 DBG_EXIT_STATUS ( Status
);
961 Process the transmit completion
963 This routine use ::EslSocketTxComplete to perform the transmit
964 completion processing for data packets.
966 This routine is called by the UDPv4 network layer when a data
967 transmit request completes.
969 @param [in] Event The normal transmit completion event
971 @param [in] pIo Address of an ::ESL_IO_MGMT structure
980 UINT32 LengthInBytes
;
982 ESL_PACKET
* pPacket
;
983 ESL_SOCKET
* pSocket
;
989 // Locate the active transmit packet
991 pPacket
= pIo
->pPacket
;
993 pSocket
= pPort
->pSocket
;
996 // Get the transmit length and status
998 LengthInBytes
= pPacket
->Op
.Udp4Tx
.TxData
.DataLength
;
999 pSocket
->TxBytes
-= LengthInBytes
;
1000 Status
= pIo
->Token
.Udp4Tx
.Status
;
1003 // Complete the transmit operation
1005 EslSocketTxComplete ( pIo
,
1009 &pSocket
->pTxPacketListHead
,
1010 &pSocket
->pTxPacketListTail
,
1018 Interface between the socket layer and the network specific
1019 code that supports SOCK_DGRAM sockets over UDPv4.
1021 CONST ESL_PROTOCOL_API cEslUdp4Api
= {
1024 OFFSET_OF ( ESL_PORT
, Context
.Udp4
.ConfigData
),
1025 OFFSET_OF ( ESL_LAYER
, pUdp4List
),
1026 OFFSET_OF ( struct sockaddr_in
, sin_zero
),
1027 sizeof ( struct sockaddr_in
),
1029 sizeof (((ESL_PACKET
*)0 )->Op
.Udp4Rx
),
1030 sizeof (((ESL_PACKET
*)0 )->Op
.Udp4Rx
),
1031 OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp4Rx
.Packet
.RxData
),
1035 NULL
, // ConnectPoll
1036 NULL
, // ConnectStart
1037 EslUdp4SocketIsConfigured
,
1038 EslUdp4LocalAddressGet
,
1039 EslUdp4LocalAddressSet
,
1044 EslUdp4PortAllocate
,
1046 NULL
, // PortCloseOp
1049 EslUdp4RemoteAddressGet
,
1050 EslUdp4RemoteAddressSet
,
1055 NULL
// TxOobComplete