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 Bind a name to a socket.
21 The ::UdpBind4 routine connects a name to a UDP4 stack on the local machine.
23 The configure call to the UDP4 driver occurs on the first poll, recv, recvfrom,
24 send or sentto call. Until then, all changes are made in the local UDP context
27 @param [in] pSocket Address of the socket structure.
29 @param [in] pSockAddr Address of a sockaddr structure that contains the
30 connection point on the local machine. An IPv4 address
31 of INADDR_ANY specifies that the connection is made to
32 all of the network stacks on the platform. Specifying a
33 specific IPv4 address restricts the connection to the
34 network stack supporting that address. Specifying zero
35 for the port causes the network layer to assign a port
36 number from the dynamic range. Specifying a specific
37 port number causes the network layer to use that port.
39 @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
41 @retval EFI_SUCCESS - Socket successfully created
46 IN DT_SOCKET
* pSocket
,
47 IN
const struct sockaddr
* pSockAddr
,
48 IN socklen_t SockAddrLength
51 EFI_HANDLE ChildHandle
;
54 DT_SERVICE
* pService
;
55 CONST
struct sockaddr_in
* pIp4Address
;
56 EFI_SERVICE_BINDING_PROTOCOL
* pUdp4Service
;
58 EFI_STATUS TempStatus
;
63 // Verify the socket layer synchronization
65 VERIFY_TPL ( TPL_SOCKETS
);
74 // Validate the address length
76 pIp4Address
= (CONST
struct sockaddr_in
*) pSockAddr
;
77 if ( SockAddrLength
>= ( sizeof ( *pIp4Address
)
78 - sizeof ( pIp4Address
->sin_zero
))) {
81 // Walk the list of services
84 pService
= pLayer
->pUdp4List
;
85 while ( NULL
!= pService
) {
88 // Create the UDP port
90 pUdp4Service
= pService
->pInterface
;
92 Status
= pUdp4Service
->CreateChild ( pUdp4Service
,
94 if ( !EFI_ERROR ( Status
)) {
95 DEBUG (( DEBUG_BIND
| DEBUG_POOL
,
96 "0x%08x: Udp4 port handle created\r\n",
102 Status
= EslUdpPortAllocate4 ( pSocket
,
105 (UINT8
*) &pIp4Address
->sin_addr
.s_addr
,
106 SwapBytes16 ( pIp4Address
->sin_port
),
111 DEBUG (( DEBUG_BIND
| DEBUG_POOL
,
112 "ERROR - Failed to open Udp4 port handle, Status: %r\r\n",
118 // Close the port if necessary
120 if (( EFI_ERROR ( Status
)) && ( NULL
!= ChildHandle
)) {
121 TempStatus
= pUdp4Service
->DestroyChild ( pUdp4Service
,
123 if ( !EFI_ERROR ( TempStatus
)) {
124 DEBUG (( DEBUG_BIND
| DEBUG_POOL
,
125 "0x%08x: Udp4 port handle destroyed\r\n",
129 DEBUG (( DEBUG_ERROR
| DEBUG_BIND
| DEBUG_POOL
,
130 "ERROR - Failed to destroy the Udp4 port handle 0x%08x, Status: %r\r\n",
133 ASSERT ( EFI_SUCCESS
== TempStatus
);
138 // Set the next service
140 pService
= pService
->pNext
;
144 // Verify that at least one network connection was found
146 if ( NULL
== pSocket
->pPortList
) {
147 DEBUG (( DEBUG_BIND
| DEBUG_POOL
| DEBUG_INIT
,
148 "Socket address %d.%d.%d.%d (0x%08x) is not available!\r\n",
149 ( pIp4Address
->sin_addr
.s_addr
>> 24 ) & 0xff,
150 ( pIp4Address
->sin_addr
.s_addr
>> 16 ) & 0xff,
151 ( pIp4Address
->sin_addr
.s_addr
>> 8 ) & 0xff,
152 pIp4Address
->sin_addr
.s_addr
& 0xff,
153 pIp4Address
->sin_addr
.s_addr
));
154 pSocket
->errno
= EADDRNOTAVAIL
;
155 Status
= EFI_INVALID_PARAMETER
;
160 "ERROR - Invalid Udp4 address length: %d\r\n",
162 Status
= EFI_INVALID_PARAMETER
;
163 pSocket
->errno
= EINVAL
;
167 // Return the operation status
169 DBG_EXIT_STATUS ( Status
);
175 Initialize the UDP4 service.
177 This routine initializes the UDP4 service after its service binding
178 protocol was located on a controller.
180 @param [in] pService DT_SERVICE structure address
182 @retval EFI_SUCCESS The service was properly initialized
183 @retval other A failure occurred during the service initialization
189 IN DT_SERVICE
* pService
198 // Identify the service
200 pService
->NetworkType
= NETWORK_TYPE_UDP4
;
203 // Connect this service to the service list
206 pService
->pNext
= pLayer
->pUdp4List
;
207 pLayer
->pUdp4List
= pService
;
210 // Assume the list is empty
212 Status
= EFI_SUCCESS
;
215 // Return the initialization status
217 DBG_EXIT_STATUS ( Status
);
223 Allocate and initialize a DT_PORT structure.
225 @param [in] pSocket Address of the socket structure.
226 @param [in] pService Address of the DT_SERVICE structure.
227 @param [in] ChildHandle Udp4 child handle
228 @param [in] pIpAddress Buffer containing IP4 network address of the local host
229 @param [in] PortNumber Udp4 port number
230 @param [in] DebugFlags Flags for debug messages
231 @param [out] ppPort Buffer to receive new DT_PORT structure address
233 @retval EFI_SUCCESS - Socket successfully created
237 EslUdpPortAllocate4 (
238 IN DT_SOCKET
* pSocket
,
239 IN DT_SERVICE
* pService
,
240 IN EFI_HANDLE ChildHandle
,
241 IN CONST UINT8
* pIpAddress
,
242 IN UINT16 PortNumber
,
244 OUT DT_PORT
** ppPort
248 EFI_UDP4_CONFIG_DATA
* pConfig
;
251 DT_UDP4_CONTEXT
* pUdp4
;
257 // Use for/break instead of goto
260 // Allocate a port structure
263 LengthInBytes
= sizeof ( *pPort
);
264 Status
= gBS
->AllocatePool ( EfiRuntimeServicesData
,
267 if ( EFI_ERROR ( Status
)) {
268 DEBUG (( DEBUG_ERROR
| DebugFlags
| DEBUG_POOL
| DEBUG_INIT
,
269 "ERROR - Failed to allocate the port structure, Status: %r\r\n",
271 pSocket
->errno
= ENOMEM
;
275 DEBUG (( DebugFlags
| DEBUG_POOL
| DEBUG_INIT
,
276 "0x%08x: Allocate pPort, %d bytes\r\n",
281 // Initialize the port
283 ZeroMem ( pPort
, LengthInBytes
);
284 pPort
->Signature
= PORT_SIGNATURE
;
285 pPort
->pService
= pService
;
286 pPort
->pSocket
= pSocket
;
287 pPort
->pfnCloseStart
= EslUdpPortCloseStart4
;
288 pPort
->DebugFlags
= DebugFlags
;
291 // Allocate the receive event
293 pUdp4
= &pPort
->Context
.Udp4
;
294 Status
= gBS
->CreateEvent ( EVT_NOTIFY_SIGNAL
,
296 (EFI_EVENT_NOTIFY
)EslUdpRxComplete4
,
298 &pUdp4
->RxToken
.Event
);
299 if ( EFI_ERROR ( Status
)) {
300 DEBUG (( DEBUG_ERROR
| DebugFlags
,
301 "ERROR - Failed to create the receive event, Status: %r\r\n",
303 pSocket
->errno
= ENOMEM
;
306 DEBUG (( DEBUG_RX
| DEBUG_POOL
,
307 "0x%08x: Created receive event\r\n",
308 pUdp4
->RxToken
.Event
));
311 // Allocate the transmit event
313 Status
= gBS
->CreateEvent ( EVT_NOTIFY_SIGNAL
,
315 (EFI_EVENT_NOTIFY
)EslUdpTxComplete4
,
317 &pUdp4
->TxToken
.Event
);
318 if ( EFI_ERROR ( Status
)) {
319 DEBUG (( DEBUG_ERROR
| DebugFlags
,
320 "ERROR - Failed to create the transmit event, Status: %r\r\n",
322 pSocket
->errno
= ENOMEM
;
325 DEBUG (( DEBUG_CLOSE
| DEBUG_POOL
,
326 "0x%08x: Created transmit event\r\n",
327 pUdp4
->TxToken
.Event
));
330 // Open the port protocol
332 Status
= gBS
->OpenProtocol (
334 &gEfiUdp4ProtocolGuid
,
335 (VOID
**) &pUdp4
->pProtocol
,
338 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
339 if ( EFI_ERROR ( Status
)) {
340 DEBUG (( DEBUG_ERROR
| DebugFlags
,
341 "ERROR - Failed to open gEfiUdp4ProtocolGuid on controller 0x%08x\r\n",
343 pSocket
->errno
= EEXIST
;
347 "0x%08x: gEfiUdp4ProtocolGuid opened on controller 0x%08x\r\n",
352 // Set the port address
354 pUdp4
->Handle
= ChildHandle
;
355 pConfig
= &pPort
->Context
.Udp4
.ConfigData
;
356 pConfig
->StationPort
= PortNumber
;
357 if (( 0 == pIpAddress
[0])
358 && ( 0 == pIpAddress
[1])
359 && ( 0 == pIpAddress
[2])
360 && ( 0 == pIpAddress
[3])) {
361 pConfig
->UseDefaultAddress
= TRUE
;
364 pConfig
->StationAddress
.Addr
[0] = pIpAddress
[0];
365 pConfig
->StationAddress
.Addr
[1] = pIpAddress
[1];
366 pConfig
->StationAddress
.Addr
[2] = pIpAddress
[2];
367 pConfig
->StationAddress
.Addr
[3] = pIpAddress
[3];
368 pConfig
->SubnetMask
.Addr
[0] = 0xff;
369 pConfig
->SubnetMask
.Addr
[1] = 0xff;
370 pConfig
->SubnetMask
.Addr
[2] = 0xff;
371 pConfig
->SubnetMask
.Addr
[3] = 0xff;
373 pConfig
->TimeToLive
= 255;
374 pConfig
->AcceptAnyPort
= FALSE
;
375 pConfig
->AcceptBroadcast
= FALSE
;
376 pConfig
->AcceptPromiscuous
= FALSE
;
377 pConfig
->AllowDuplicatePort
= TRUE
;
378 pConfig
->DoNotFragment
= TRUE
;
381 // Verify the socket layer synchronization
383 VERIFY_TPL ( TPL_SOCKETS
);
386 // Add this port to the socket
388 pPort
->pLinkSocket
= pSocket
->pPortList
;
389 pSocket
->pPortList
= pPort
;
391 "0x%08x: Socket adding port: 0x%08x\r\n",
396 // Add this port to the service
398 pPort
->pLinkService
= pService
->pPortList
;
399 pService
->pPortList
= pPort
;
409 // Clean up after the error if necessary
411 if (( EFI_ERROR ( Status
)) && ( NULL
!= pPort
)) {
415 EslUdpPortClose4 ( pPort
);
418 // Return the operation status
420 DBG_EXIT_STATUS ( Status
);
428 This routine releases the resources allocated by
429 ::UdpPortAllocate4().
431 @param [in] pPort Address of the port structure.
433 @retval EFI_SUCCESS The port is closed
434 @retval other Port close error
445 DT_PORT
* pPreviousPort
;
446 DT_SERVICE
* pService
;
448 EFI_SERVICE_BINDING_PROTOCOL
* pUdp4Service
;
449 DT_UDP4_CONTEXT
* pUdp4
;
455 // Verify the socket layer synchronization
457 VERIFY_TPL ( TPL_SOCKETS
);
462 Status
= EFI_SUCCESS
;
463 pSocket
= pPort
->pSocket
;
467 // Locate the port in the socket list
470 DebugFlags
= pPort
->DebugFlags
;
471 pPreviousPort
= pSocket
->pPortList
;
472 if ( pPreviousPort
== pPort
) {
474 // Remove this port from the head of the socket list
476 pSocket
->pPortList
= pPort
->pLinkSocket
;
480 // Locate the port in the middle of the socket list
482 while (( NULL
!= pPreviousPort
)
483 && ( pPreviousPort
->pLinkSocket
!= pPort
)) {
484 pPreviousPort
= pPreviousPort
->pLinkSocket
;
486 if ( NULL
!= pPreviousPort
) {
488 // Remove the port from the middle of the socket list
490 pPreviousPort
->pLinkSocket
= pPort
->pLinkSocket
;
495 // Locate the port in the service list
497 pService
= pPort
->pService
;
498 pPreviousPort
= pService
->pPortList
;
499 if ( pPreviousPort
== pPort
) {
501 // Remove this port from the head of the service list
503 pService
->pPortList
= pPort
->pLinkService
;
507 // Locate the port in the middle of the service list
509 while (( NULL
!= pPreviousPort
)
510 && ( pPreviousPort
->pLinkService
!= pPort
)) {
511 pPreviousPort
= pPreviousPort
->pLinkService
;
513 if ( NULL
!= pPreviousPort
) {
515 // Remove the port from the middle of the service list
517 pPreviousPort
->pLinkService
= pPort
->pLinkService
;
522 // Empty the receive queue
524 ASSERT ( NULL
== pSocket
->pRxPacketListHead
);
525 ASSERT ( NULL
== pSocket
->pRxPacketListTail
);
526 ASSERT ( 0 == pSocket
->RxBytes
);
529 // Empty the receive free queue
531 while ( NULL
!= pSocket
->pRxFree
) {
532 pPacket
= pSocket
->pRxFree
;
533 pSocket
->pRxFree
= pPacket
->pNext
;
534 EslSocketPacketFree ( pPacket
, DEBUG_RX
);
538 // Done with the receive event
540 pUdp4
= &pPort
->Context
.Udp4
;
541 if ( NULL
!= pUdp4
->RxToken
.Event
) {
542 Status
= gBS
->CloseEvent ( pUdp4
->RxToken
.Event
);
543 if ( !EFI_ERROR ( Status
)) {
544 DEBUG (( DebugFlags
| DEBUG_POOL
,
545 "0x%08x: Closed receive event\r\n",
546 pUdp4
->RxToken
.Event
));
549 DEBUG (( DEBUG_ERROR
| DebugFlags
,
550 "ERROR - Failed to close the receive event, Status: %r\r\n",
552 ASSERT ( EFI_SUCCESS
== Status
);
557 // Done with the transmit event
559 if ( NULL
!= pUdp4
->TxToken
.Event
) {
560 Status
= gBS
->CloseEvent ( pUdp4
->TxToken
.Event
);
561 if ( !EFI_ERROR ( Status
)) {
562 DEBUG (( DebugFlags
| DEBUG_POOL
,
563 "0x%08x: Closed normal transmit event\r\n",
564 pUdp4
->TxToken
.Event
));
567 DEBUG (( DEBUG_ERROR
| DebugFlags
,
568 "ERROR - Failed to close the normal transmit event, Status: %r\r\n",
570 ASSERT ( EFI_SUCCESS
== Status
);
575 // Done with the UDP protocol
577 pUdp4Service
= pService
->pInterface
;
578 if ( NULL
!= pUdp4
->pProtocol
) {
579 Status
= gBS
->CloseProtocol ( pUdp4
->Handle
,
580 &gEfiUdp4ProtocolGuid
,
583 if ( !EFI_ERROR ( Status
)) {
585 "0x%08x: gEfiUdp4ProtocolGuid closed on controller 0x%08x\r\n",
590 DEBUG (( DEBUG_ERROR
| DebugFlags
,
591 "ERROR - Failed to close gEfiUdp4ProtocolGuid opened on controller 0x%08x, Status: %r\r\n",
594 ASSERT ( EFI_SUCCESS
== Status
);
599 // Done with the UDP port
601 if ( NULL
!= pUdp4
->Handle
) {
602 Status
= pUdp4Service
->DestroyChild ( pUdp4Service
,
604 if ( !EFI_ERROR ( Status
)) {
605 DEBUG (( DebugFlags
| DEBUG_POOL
,
606 "0x%08x: Udp4 port handle destroyed\r\n",
610 DEBUG (( DEBUG_ERROR
| DebugFlags
| DEBUG_POOL
,
611 "ERROR - Failed to destroy the Udp4 port handle, Status: %r\r\n",
613 ASSERT ( EFI_SUCCESS
== Status
);
618 // Release the port structure
620 Status
= gBS
->FreePool ( pPort
);
621 if ( !EFI_ERROR ( Status
)) {
622 DEBUG (( DebugFlags
| DEBUG_POOL
,
623 "0x%08x: Free pPort, %d bytes\r\n",
628 DEBUG (( DEBUG_ERROR
| DebugFlags
| DEBUG_POOL
,
629 "ERROR - Failed to free pPort: 0x%08x, Status: %r\r\n",
632 ASSERT ( EFI_SUCCESS
== Status
);
636 // Mark the socket as closed if necessary
638 if ( NULL
== pSocket
->pPortList
) {
639 pSocket
->State
= SOCKET_STATE_CLOSED
;
640 DEBUG (( DEBUG_CLOSE
| DEBUG_INFO
,
641 "0x%08x: Socket State: SOCKET_STATE_CLOSED\r\n",
646 // Return the operation status
648 DBG_EXIT_STATUS ( Status
);
654 Start the close operation on a UDP4 port, state 1.
656 Closing a port goes through the following states:
657 1. Port close starting - Mark the port as closing and wait for transmission to complete
658 2. Port TX close done - Transmissions complete, close the port and abort the receives
659 3. Port RX close done - Receive operations complete, close the port
660 4. Port closed - Release the port resources
662 @param [in] pPort Address of the port structure.
663 @param [in] bCloseNow Set TRUE to abort active transfers
664 @param [in] DebugFlags Flags for debug messages
666 @retval EFI_SUCCESS The port is closed, not normally returned
667 @retval EFI_NOT_READY The port has started the closing process
668 @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
669 most likely the routine was called already.
673 EslUdpPortCloseStart4 (
675 IN BOOLEAN bCloseNow
,
685 // Verify the socket layer synchronization
687 VERIFY_TPL ( TPL_SOCKETS
);
690 // Mark the port as closing
692 Status
= EFI_ALREADY_STARTED
;
693 pSocket
= pPort
->pSocket
;
694 pSocket
->errno
= EALREADY
;
695 if ( PORT_STATE_CLOSE_STARTED
> pPort
->State
) {
698 // Update the port state
700 pPort
->State
= PORT_STATE_CLOSE_STARTED
;
701 DEBUG (( DEBUG_CLOSE
| DEBUG_INFO
,
702 "0x%08x: Port Close State: PORT_STATE_CLOSE_STARTED\r\n",
704 pPort
->bCloseNow
= bCloseNow
;
705 pPort
->DebugFlags
= DebugFlags
;
708 // Determine if transmits are complete
710 Status
= EslUdpPortCloseTxDone4 ( pPort
);
714 // Return the operation status
716 DBG_EXIT_STATUS ( Status
);
724 Continue the close operation after the receive is complete.
726 @param [in] pPort Address of the port structure.
728 @retval EFI_SUCCESS The port is closed
729 @retval EFI_NOT_READY The port is still closing
730 @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
731 most likely the routine was called already.
735 EslUdpPortCloseRxDone4 (
739 PORT_STATE PortState
;
741 DT_UDP4_CONTEXT
* pUdp4
;
747 // Verify the socket layer synchronization
749 VERIFY_TPL ( TPL_SOCKETS
);
752 // Verify that the port is closing
754 Status
= EFI_ALREADY_STARTED
;
755 pSocket
= pPort
->pSocket
;
756 pSocket
->errno
= EALREADY
;
757 PortState
= pPort
->State
;
758 if (( PORT_STATE_CLOSE_TX_DONE
== PortState
)
759 || ( PORT_STATE_CLOSE_DONE
== PortState
)) {
761 // Determine if the receive operation is pending
763 Status
= EFI_NOT_READY
;
764 pSocket
->errno
= EAGAIN
;
765 pUdp4
= &pPort
->Context
.Udp4
;
766 if ( NULL
== pUdp4
->pReceivePending
) {
768 // The receive operation is complete
769 // Update the port state
771 pPort
->State
= PORT_STATE_CLOSE_RX_DONE
;
772 DEBUG (( DEBUG_CLOSE
| DEBUG_INFO
,
773 "0x%08x: Port Close State: PORT_STATE_CLOSE_RX_DONE\r\n",
777 // The close operation has completed
778 // Release the port resources
780 Status
= EslUdpPortClose4 ( pPort
);
783 DEBUG (( DEBUG_CLOSE
| DEBUG_INFO
,
784 "0x%08x: Port Close: Receive still pending!\r\n",
790 // Return the operation status
792 DBG_EXIT_STATUS ( Status
);
800 Continue the close operation after the transmission is complete.
802 @param [in] pPort Address of the port structure.
804 @retval EFI_SUCCESS The port is closed, not normally returned
805 @retval EFI_NOT_READY The port is still closing
806 @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
807 most likely the routine was called already.
811 EslUdpPortCloseTxDone4 (
817 DT_UDP4_CONTEXT
* pUdp4
;
818 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
824 // Verify the socket layer synchronization
826 VERIFY_TPL ( TPL_SOCKETS
);
829 // All transmissions are complete or must be stopped
830 // Mark the port as TX complete
832 Status
= EFI_ALREADY_STARTED
;
833 if ( PORT_STATE_CLOSE_STARTED
== pPort
->State
) {
835 // Verify that the transmissions are complete
837 pSocket
= pPort
->pSocket
;
838 if ( pPort
->bCloseNow
839 || ( EFI_SUCCESS
!= pSocket
->TxError
)
840 || ( 0 == pSocket
->TxBytes
)) {
842 // Start the close operation on the port
844 pUdp4
= &pPort
->Context
.Udp4
;
845 pUdp4Protocol
= pUdp4
->pProtocol
;
846 if ( !pUdp4
->bConfigured
) {
848 // Skip the close operation since the port is not
851 // Update the port state
853 pPort
->State
= PORT_STATE_CLOSE_DONE
;
854 DEBUG (( DEBUG_CLOSE
| DEBUG_INFO
,
855 "0x%08x: Port Close State: PORT_STATE_CLOSE_DONE\r\n",
857 Status
= EFI_SUCCESS
;
861 // Update the port state
863 pPort
->State
= PORT_STATE_CLOSE_TX_DONE
;
864 DEBUG (( DEBUG_CLOSE
| DEBUG_INFO
,
865 "0x%08x: Port Close State: PORT_STATE_CLOSE_TX_DONE\r\n",
869 // Empty the receive queue
871 while ( NULL
!= pSocket
->pRxPacketListHead
) {
872 pPacket
= pSocket
->pRxPacketListHead
;
873 pSocket
->pRxPacketListHead
= pPacket
->pNext
;
874 pSocket
->RxBytes
-= pPacket
->Op
.Udp4Rx
.pRxData
->DataLength
;
877 // Return the buffer to the UDP4 driver
879 gBS
->SignalEvent ( pPacket
->Op
.Udp4Rx
.pRxData
->RecycleSignal
);
882 // Done with this packet
884 EslSocketPacketFree ( pPacket
, DEBUG_RX
);
886 pSocket
->pRxPacketListTail
= NULL
;
887 ASSERT ( 0 == pSocket
->RxBytes
);
890 // Reset the port, cancel the outstanding receive
892 Status
= pUdp4Protocol
->Configure ( pUdp4Protocol
,
894 if ( !EFI_ERROR ( Status
)) {
895 DEBUG (( pPort
->DebugFlags
| DEBUG_CLOSE
| DEBUG_INFO
,
896 "0x%08x: Port reset\r\n",
900 // Free the receive packet
902 Status
= gBS
->CheckEvent ( pUdp4
->RxToken
.Event
);
903 if ( EFI_SUCCESS
!= Status
) {
904 EslSocketPacketFree ( pUdp4
->pReceivePending
, DEBUG_CLOSE
);
905 pUdp4
->pReceivePending
= NULL
;
906 Status
= EFI_SUCCESS
;
910 DEBUG (( DEBUG_ERROR
| pPort
->DebugFlags
| DEBUG_CLOSE
| DEBUG_INFO
,
911 "ERROR - Port 0x%08x reset failed, Status: %r\r\n",
914 ASSERT ( EFI_SUCCESS
== Status
);
919 // Determine if the receive operation is pending
921 if ( !EFI_ERROR ( Status
)) {
922 Status
= EslUdpPortCloseRxDone4 ( pPort
);
927 // Transmissions are still active, exit
929 DEBUG (( DEBUG_CLOSE
| DEBUG_INFO
,
930 "0x%08x: Port Close: Transmits are still pending!\r\n",
932 Status
= EFI_NOT_READY
;
933 pSocket
->errno
= EAGAIN
;
938 // Return the operation status
940 DBG_EXIT_STATUS ( Status
);
946 Connect to a remote system via the network.
948 The ::UdpConnectStart4= routine sets the remote address for the connection.
950 @param [in] pSocket Address of the socket structure.
952 @param [in] pSockAddr Network address of the remote system.
954 @param [in] SockAddrLength Length in bytes of the network address.
956 @retval EFI_SUCCESS The connection was successfully established.
957 @retval EFI_NOT_READY The connection is in progress, call this routine again.
958 @retval Others The connection attempt failed.
963 IN DT_SOCKET
* pSocket
,
964 IN
const struct sockaddr
* pSockAddr
,
965 IN socklen_t SockAddrLength
968 struct sockaddr_in LocalAddress
;
970 struct sockaddr_in
* pRemoteAddress
;
971 DT_UDP4_CONTEXT
* pUdp4
;
979 Status
= EFI_NETWORK_UNREACHABLE
;
980 pSocket
->errno
= ENETUNREACH
;
985 pRemoteAddress
= (struct sockaddr_in
*)pSockAddr
;
988 // Validate the address length
990 if ( SockAddrLength
>= ( sizeof ( *pRemoteAddress
)
991 - sizeof ( pRemoteAddress
->sin_zero
))) {
993 // Determine if BIND was already called
995 if ( NULL
== pSocket
->pPortList
) {
997 // Allow any local port
999 ZeroMem ( &LocalAddress
, sizeof ( LocalAddress
));
1000 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
1001 LocalAddress
.sin_family
= AF_INET
;
1002 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
1003 (struct sockaddr
*)&LocalAddress
,
1004 LocalAddress
.sin_len
,
1009 // Walk the list of ports
1011 pPort
= pSocket
->pPortList
;
1012 while ( NULL
!= pPort
) {
1014 // Set the remote address
1016 pUdp4
= &pPort
->Context
.Udp4
;
1017 pUdp4
->ConfigData
.RemoteAddress
.Addr
[0] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
);
1018 pUdp4
->ConfigData
.RemoteAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
1019 pUdp4
->ConfigData
.RemoteAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
1020 pUdp4
->ConfigData
.RemoteAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
1021 pUdp4
->ConfigData
.RemotePort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
1024 // At least one path exists
1026 Status
= EFI_SUCCESS
;
1030 // Set the next port
1032 pPort
= pPort
->pLinkSocket
;
1036 DEBUG (( DEBUG_CONNECT
,
1037 "ERROR - Invalid UDP4 address length: %d\r\n",
1039 Status
= EFI_INVALID_PARAMETER
;
1040 pSocket
->errno
= EINVAL
;
1044 // Return the connect status
1046 DBG_EXIT_STATUS ( Status
);
1052 Get the local socket address
1054 @param [in] pSocket Address of the socket structure.
1056 @param [out] pAddress Network address to receive the local system address
1058 @param [in,out] pAddressLength Length of the local network address structure
1060 @retval EFI_SUCCESS - Address available
1061 @retval Other - Failed to get the address
1065 EslUdpGetLocalAddress4 (
1066 IN DT_SOCKET
* pSocket
,
1067 OUT
struct sockaddr
* pAddress
,
1068 IN OUT socklen_t
* pAddressLength
1071 socklen_t LengthInBytes
;
1073 struct sockaddr_in
* pLocalAddress
;
1074 DT_UDP4_CONTEXT
* pUdp4
;
1080 // Verify the socket layer synchronization
1082 VERIFY_TPL ( TPL_SOCKETS
);
1085 // Verify that there is just a single connection
1087 pPort
= pSocket
->pPortList
;
1088 if (( NULL
!= pPort
) && ( NULL
== pPort
->pLinkSocket
)) {
1090 // Verify the address length
1092 LengthInBytes
= sizeof ( struct sockaddr_in
);
1093 if ( LengthInBytes
<= * pAddressLength
) {
1095 // Return the local address
1097 pUdp4
= &pPort
->Context
.Udp4
;
1098 pLocalAddress
= (struct sockaddr_in
*)pAddress
;
1099 ZeroMem ( pLocalAddress
, LengthInBytes
);
1100 pLocalAddress
->sin_family
= AF_INET
;
1101 pLocalAddress
->sin_len
= (uint8_t)LengthInBytes
;
1102 pLocalAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.StationPort
);
1103 CopyMem ( &pLocalAddress
->sin_addr
,
1104 &pUdp4
->ConfigData
.StationAddress
.Addr
[0],
1105 sizeof ( pLocalAddress
->sin_addr
));
1107 Status
= EFI_SUCCESS
;
1110 pSocket
->errno
= EINVAL
;
1111 Status
= EFI_INVALID_PARAMETER
;
1115 pSocket
->errno
= ENOTCONN
;
1116 Status
= EFI_NOT_STARTED
;
1120 // Return the operation status
1122 DBG_EXIT_STATUS ( Status
);
1128 Get the remote socket address
1130 @param [in] pSocket Address of the socket structure.
1132 @param [out] pAddress Network address to receive the remote system address
1134 @param [in,out] pAddressLength Length of the remote network address structure
1136 @retval EFI_SUCCESS - Address available
1137 @retval Other - Failed to get the address
1141 EslUdpGetRemoteAddress4 (
1142 IN DT_SOCKET
* pSocket
,
1143 OUT
struct sockaddr
* pAddress
,
1144 IN OUT socklen_t
* pAddressLength
1147 socklen_t LengthInBytes
;
1149 struct sockaddr_in
* pRemoteAddress
;
1150 DT_UDP4_CONTEXT
* pUdp4
;
1156 // Verify the socket layer synchronization
1158 VERIFY_TPL ( TPL_SOCKETS
);
1161 // Verify that there is just a single connection
1163 pPort
= pSocket
->pPortList
;
1164 if (( NULL
!= pPort
) && ( NULL
== pPort
->pLinkSocket
)) {
1166 // Verify the address length
1168 LengthInBytes
= sizeof ( struct sockaddr_in
);
1169 if ( LengthInBytes
<= * pAddressLength
) {
1171 // Return the local address
1173 pUdp4
= &pPort
->Context
.Udp4
;
1174 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
1175 ZeroMem ( pRemoteAddress
, LengthInBytes
);
1176 pRemoteAddress
->sin_family
= AF_INET
;
1177 pRemoteAddress
->sin_len
= (uint8_t)LengthInBytes
;
1178 pRemoteAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.RemotePort
);
1179 CopyMem ( &pRemoteAddress
->sin_addr
,
1180 &pUdp4
->ConfigData
.RemoteAddress
.Addr
[0],
1181 sizeof ( pRemoteAddress
->sin_addr
));
1183 Status
= EFI_SUCCESS
;
1186 pSocket
->errno
= EINVAL
;
1187 Status
= EFI_INVALID_PARAMETER
;
1191 pSocket
->errno
= ENOTCONN
;
1192 Status
= EFI_NOT_STARTED
;
1196 // Return the operation status
1198 DBG_EXIT_STATUS ( Status
);
1204 Receive data from a network connection.
1206 To minimize the number of buffer copies, the ::UdpRxComplete4
1207 routine queues the UDP4 driver's buffer to a list of datagrams
1208 waiting to be received. The socket driver holds on to the
1209 buffers from the UDP4 driver until the application layer requests
1210 the data or the socket is closed.
1212 The application calls this routine in the socket layer to
1213 receive datagrams from one or more remote systems. This routine
1214 removes the next available datagram from the list of datagrams
1215 and copies the data from the UDP4 driver's buffer into the
1216 application's buffer. The UDP4 driver's buffer is then returned.
1218 @param [in] pSocket Address of a DT_SOCKET structure
1220 @param [in] Flags Message control flags
1222 @param [in] BufferLength Length of the the buffer
1224 @param [in] pBuffer Address of a buffer to receive the data.
1226 @param [in] pDataLength Number of received data bytes in the buffer.
1228 @param [out] pAddress Network address to receive the remote system address
1230 @param [in,out] pAddressLength Length of the remote network address structure
1232 @retval EFI_SUCCESS - Socket data successfully received
1237 IN DT_SOCKET
* pSocket
,
1239 IN
size_t BufferLength
,
1241 OUT
size_t * pDataLength
,
1242 OUT
struct sockaddr
* pAddress
,
1243 IN OUT socklen_t
* pAddressLength
1246 socklen_t AddressLength
;
1250 in_addr_t IpAddress
;
1251 size_t LengthInBytes
;
1253 DT_PACKET
* pPacket
;
1255 struct sockaddr_in
* pRemoteAddress
;
1256 EFI_UDP4_RECEIVE_DATA
* pRxData
;
1257 DT_UDP4_CONTEXT
* pUdp4
;
1258 struct sockaddr_in RemoteAddress
;
1266 Status
= EFI_UNSUPPORTED
;
1267 pSocket
->errno
= ENOTCONN
;
1270 // Verify that the socket is connected
1272 if (( SOCKET_STATE_CONNECTED
== pSocket
->State
)
1273 || ( PORT_STATE_RX_ERROR
== pSocket
->State
)) {
1277 pPort
= pSocket
->pPortList
;
1278 if ( NULL
!= pPort
) {
1280 // Determine if there is any data on the queue
1282 pUdp4
= &pPort
->Context
.Udp4
;
1283 pPacket
= pSocket
->pRxPacketListHead
;
1284 if ( NULL
!= pPacket
) {
1286 // Validate the return address parameters
1288 pRxData
= pPacket
->Op
.Udp4Rx
.pRxData
;
1289 if (( NULL
== pAddress
) || ( NULL
!= pAddressLength
)) {
1291 // Return the remote system address if requested
1293 if ( NULL
!= pAddress
) {
1295 // Build the remote address
1298 "Getting packet source address: %d.%d.%d.%d:%d\r\n",
1299 pRxData
->UdpSession
.SourceAddress
.Addr
[0],
1300 pRxData
->UdpSession
.SourceAddress
.Addr
[1],
1301 pRxData
->UdpSession
.SourceAddress
.Addr
[2],
1302 pRxData
->UdpSession
.SourceAddress
.Addr
[3],
1303 pRxData
->UdpSession
.SourcePort
));
1304 ZeroMem ( &RemoteAddress
, sizeof ( RemoteAddress
));
1305 RemoteAddress
.sin_len
= sizeof ( RemoteAddress
);
1306 RemoteAddress
.sin_family
= AF_INET
;
1307 IpAddress
= pRxData
->UdpSession
.SourceAddress
.Addr
[3];
1309 IpAddress
|= pRxData
->UdpSession
.SourceAddress
.Addr
[2];
1311 IpAddress
|= pRxData
->UdpSession
.SourceAddress
.Addr
[1];
1313 IpAddress
|= pRxData
->UdpSession
.SourceAddress
.Addr
[0];
1314 RemoteAddress
.sin_addr
.s_addr
= IpAddress
;
1315 RemoteAddress
.sin_port
= SwapBytes16 ( pRxData
->UdpSession
.SourcePort
);
1320 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
1321 AddressLength
= sizeof ( *pRemoteAddress
);
1322 if ( AddressLength
> *pAddressLength
) {
1323 AddressLength
= *pAddressLength
;
1325 CopyMem ( pRemoteAddress
,
1330 // Update the address length
1332 *pAddressLength
= AddressLength
;
1336 // Reduce the buffer length if necessary
1338 DataBytes
= pRxData
->DataLength
;
1339 if ( DataBytes
< BufferLength
) {
1340 BufferLength
= DataBytes
;
1344 // Copy the received data
1350 // Determine the amount of received data
1352 pData
= pRxData
->FragmentTable
[Fragment
].FragmentBuffer
;
1353 BytesToCopy
= pRxData
->FragmentTable
[Fragment
].FragmentLength
;
1354 if (( BufferLength
- LengthInBytes
) < BytesToCopy
) {
1355 BytesToCopy
= BufferLength
- LengthInBytes
;
1357 LengthInBytes
+= BytesToCopy
;
1360 // Move the data into the buffer
1363 "0x%08x: Port copy packet 0x%08x data into 0x%08x, 0x%08x bytes\r\n",
1368 CopyMem ( pBuffer
, pData
, BytesToCopy
);
1369 } while ( BufferLength
> LengthInBytes
);
1372 // Determine if the data is being read
1374 if ( 0 == ( Flags
& MSG_PEEK
)) {
1376 // Display for the bytes consumed
1379 "0x%08x: Port account for 0x%08x bytes\r\n",
1384 // All done with this packet
1385 // Account for any discarded data
1387 pSocket
->RxBytes
-= DataBytes
;
1388 if ( 0 != ( DataBytes
- BufferLength
)) {
1390 "0x%08x: Port, packet read, skipping over 0x%08x bytes\r\n",
1392 DataBytes
- BufferLength
));
1396 // Remove this packet from the queue
1398 pSocket
->pRxPacketListHead
= pPacket
->pNext
;
1399 if ( NULL
== pSocket
->pRxPacketListHead
) {
1400 pSocket
->pRxPacketListTail
= NULL
;
1404 // Return this packet to the UDP4 driver
1406 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
1409 // Move the packet to the free queue
1411 pPacket
->pNext
= pSocket
->pRxFree
;
1412 pSocket
->pRxFree
= pPacket
;
1414 "0x%08x: Port freeing packet 0x%08x\r\n",
1419 // Restart this receive operation if necessary
1421 if (( NULL
== pUdp4
->pReceivePending
)
1422 && ( MAX_RX_DATA
> pSocket
->RxBytes
)) {
1423 EslUdpRxStart4 ( pPort
);
1428 // Return the data length
1430 *pDataLength
= LengthInBytes
;
1433 // Successful operation
1435 Status
= EFI_SUCCESS
;
1440 // Bad return address pointer and length
1442 Status
= EFI_INVALID_PARAMETER
;
1443 pSocket
->errno
= EINVAL
;
1448 // The queue is empty
1449 // Determine if it is time to return the receive error
1451 if ( EFI_ERROR ( pSocket
->RxError
)) {
1452 Status
= pSocket
->RxError
;
1455 pSocket
->errno
= EIO
;
1458 case EFI_HOST_UNREACHABLE
:
1459 pSocket
->errno
= EHOSTUNREACH
;
1462 case EFI_NETWORK_UNREACHABLE
:
1463 pSocket
->errno
= ENETUNREACH
;
1466 case EFI_PORT_UNREACHABLE
:
1467 pSocket
->errno
= EPROTONOSUPPORT
;
1470 case EFI_PROTOCOL_UNREACHABLE
:
1471 pSocket
->errno
= ENOPROTOOPT
;
1474 pSocket
->RxError
= EFI_SUCCESS
;
1477 Status
= EFI_NOT_READY
;
1478 pSocket
->errno
= EAGAIN
;
1485 // Return the operation status
1487 DBG_EXIT_STATUS ( Status
);
1493 Cancel the receive operations
1495 @param [in] pSocket Address of a DT_SOCKET structure
1497 @retval EFI_SUCCESS - The cancel was successful
1502 IN DT_SOCKET
* pSocket
1505 DT_PACKET
* pPacket
;
1507 DT_UDP4_CONTEXT
* pUdp4
;
1508 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
1516 Status
= EFI_NOT_FOUND
;
1521 pPort
= pSocket
->pPortList
;
1522 if ( NULL
!= pPort
) {
1524 // Determine if a receive is pending
1526 pUdp4
= &pPort
->Context
.Udp4
;
1527 pPacket
= pUdp4
->pReceivePending
;
1528 if ( NULL
!= pPacket
) {
1530 // Attempt to cancel the receive operation
1532 pUdp4Protocol
= pUdp4
->pProtocol
;
1533 Status
= pUdp4Protocol
->Cancel ( pUdp4Protocol
,
1535 if ( EFI_NOT_FOUND
== Status
) {
1537 // The receive is complete
1539 Status
= EFI_SUCCESS
;
1545 // Return the operation status
1547 DBG_EXIT_STATUS ( Status
);
1553 Process the receive completion
1555 Keep the UDP4 driver's buffer and append it to the list of
1556 datagrams for the application to receive. The UDP4 driver's
1557 buffer will be returned by either ::UdpReceive4 or
1558 ::UdpPortCloseTxDone4.
1560 @param Event The receive completion event
1562 @param pPort The DT_PORT structure address
1571 size_t LengthInBytes
;
1572 DT_PACKET
* pPacket
;
1573 DT_PACKET
* pPrevious
;
1574 EFI_UDP4_RECEIVE_DATA
* pRxData
;
1575 DT_SOCKET
* pSocket
;
1576 DT_UDP4_CONTEXT
* pUdp4
;
1582 // Mark this receive complete
1584 pUdp4
= &pPort
->Context
.Udp4
;
1585 pPacket
= pUdp4
->pReceivePending
;
1586 pUdp4
->pReceivePending
= NULL
;
1589 // Determine if this receive was successful
1591 pSocket
= pPort
->pSocket
;
1592 Status
= pUdp4
->RxToken
.Status
;
1593 if (( !EFI_ERROR ( Status
)) && ( !pSocket
->bRxDisable
)) {
1594 pRxData
= pUdp4
->RxToken
.Packet
.RxData
;
1595 if ( PORT_STATE_CLOSE_STARTED
>= pPort
->State
) {
1597 // Save the data in the packet
1599 pPacket
->Op
.Udp4Rx
.pRxData
= pRxData
;
1602 // Queue this packet
1604 pPrevious
= pSocket
->pRxPacketListTail
;
1605 if ( NULL
== pPrevious
) {
1606 pSocket
->pRxPacketListHead
= pPacket
;
1609 pPrevious
->pNext
= pPacket
;
1611 pSocket
->pRxPacketListTail
= pPacket
;
1614 // Account for the normal data
1616 LengthInBytes
= pRxData
->DataLength
;
1617 pSocket
->RxBytes
+= LengthInBytes
;
1620 // Log the received data
1622 DEBUG (( DEBUG_RX
| DEBUG_INFO
,
1623 "Received packet from: %d.%d.%d.%d:%d\r\n",
1624 pRxData
->UdpSession
.SourceAddress
.Addr
[0],
1625 pRxData
->UdpSession
.SourceAddress
.Addr
[1],
1626 pRxData
->UdpSession
.SourceAddress
.Addr
[2],
1627 pRxData
->UdpSession
.SourceAddress
.Addr
[3],
1628 pRxData
->UdpSession
.SourcePort
));
1629 DEBUG (( DEBUG_RX
| DEBUG_INFO
,
1630 "Received packet sent to: %d.%d.%d.%d:%d\r\n",
1631 pRxData
->UdpSession
.DestinationAddress
.Addr
[0],
1632 pRxData
->UdpSession
.DestinationAddress
.Addr
[1],
1633 pRxData
->UdpSession
.DestinationAddress
.Addr
[2],
1634 pRxData
->UdpSession
.DestinationAddress
.Addr
[3],
1635 pRxData
->UdpSession
.DestinationPort
));
1636 DEBUG (( DEBUG_RX
| DEBUG_INFO
,
1637 "0x%08x: Packet queued on port 0x%08x with 0x%08x bytes of data\r\n",
1643 // Attempt to restart this receive operation
1645 if ( pSocket
->MaxRxBuf
> pSocket
->RxBytes
) {
1646 EslUdpRxStart4 ( pPort
);
1650 "0x%08x: Port RX suspended, 0x%08x bytes queued\r\n",
1652 pSocket
->RxBytes
));
1657 // The port is being closed
1658 // Return the buffer to the UDP4 driver
1660 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
1665 EslSocketPacketFree ( pPacket
, DEBUG_RX
);
1670 DEBUG (( DEBUG_RX
| DEBUG_INFO
,
1671 "ERROR - Receiving packet 0x%08x, on port 0x%08x, Status:%r\r\n",
1677 // Receive error, free the packet save the error
1679 EslSocketPacketFree ( pPacket
, DEBUG_RX
);
1680 if ( !EFI_ERROR ( pSocket
->RxError
)) {
1681 pSocket
->RxError
= Status
;
1685 // Update the port state
1687 if ( PORT_STATE_CLOSE_STARTED
<= pPort
->State
) {
1688 EslUdpPortCloseRxDone4 ( pPort
);
1691 if ( EFI_ERROR ( Status
)) {
1692 pPort
->State
= PORT_STATE_RX_ERROR
;
1702 Start a receive operation
1704 @param [in] pPort Address of the DT_PORT structure.
1712 DT_PACKET
* pPacket
;
1713 DT_SOCKET
* pSocket
;
1714 DT_UDP4_CONTEXT
* pUdp4
;
1715 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
1721 // Determine if a receive is already pending
1723 Status
= EFI_SUCCESS
;
1725 pSocket
= pPort
->pSocket
;
1726 pUdp4
= &pPort
->Context
.Udp4
;
1727 if ( !EFI_ERROR ( pPort
->pSocket
->RxError
)) {
1728 if (( NULL
== pUdp4
->pReceivePending
)
1729 && ( PORT_STATE_CLOSE_STARTED
> pPort
->State
)) {
1731 // Determine if there are any free packets
1733 pPacket
= pSocket
->pRxFree
;
1734 if ( NULL
!= pPacket
) {
1736 // Remove this packet from the free list
1738 pSocket
->pRxFree
= pPacket
->pNext
;
1740 "0x%08x: Port removed packet 0x%08x from free list\r\n",
1746 // Allocate a packet structure
1748 Status
= EslSocketPacketAllocate ( &pPacket
,
1749 sizeof ( pPacket
->Op
.Udp4Rx
),
1751 if ( EFI_ERROR ( Status
)) {
1753 DEBUG (( DEBUG_ERROR
| DEBUG_RX
,
1754 "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",
1761 // Determine if a packet is available
1763 if ( NULL
!= pPacket
) {
1765 // Initialize the buffer for receive
1767 pPacket
->pNext
= NULL
;
1768 pPacket
->Op
.Udp4Rx
.pRxData
= NULL
;
1769 pUdp4
->RxToken
.Packet
.RxData
= NULL
;
1770 pUdp4
->pReceivePending
= pPacket
;
1773 // Start the receive on the packet
1775 pUdp4Protocol
= pUdp4
->pProtocol
;
1776 Status
= pUdp4Protocol
->Receive ( pUdp4Protocol
,
1778 if ( !EFI_ERROR ( Status
)) {
1779 DEBUG (( DEBUG_RX
| DEBUG_INFO
,
1780 "0x%08x: Packet receive pending on port 0x%08x\r\n",
1785 DEBUG (( DEBUG_RX
| DEBUG_INFO
,
1786 "ERROR - Failed to post a receive on port 0x%08x, Status: %r\r\n",
1789 if ( !EFI_ERROR ( pSocket
->RxError
)) {
1791 // Save the error status
1793 pSocket
->RxError
= Status
;
1799 pUdp4
->pReceivePending
= NULL
;
1800 pPacket
->pNext
= pSocket
->pRxFree
;
1801 pSocket
->pRxFree
= pPacket
;
1812 Shutdown the UDP4 service.
1814 This routine undoes the work performed by ::UdpInitialize4.
1816 @param [in] pService DT_SERVICE structure address
1822 IN DT_SERVICE
* pService
1827 DT_SERVICE
* pPreviousService
;
1832 // Verify the socket layer synchronization
1834 VERIFY_TPL ( TPL_SOCKETS
);
1837 // Walk the list of ports
1840 pPort
= pService
->pPortList
;
1841 if ( NULL
!= pPort
) {
1843 // Remove the port from the port list
1845 pService
->pPortList
= pPort
->pLinkService
;
1851 // pPort->pfnClosePort ( pPort, 0 );
1853 } while ( NULL
!= pPort
);
1856 // Remove the service from the service list
1858 pLayer
= &mEslLayer
;
1859 pPreviousService
= pLayer
->pUdp4List
;
1860 if ( pService
== pPreviousService
) {
1862 // Remove the service from the beginning of the list
1864 pLayer
->pUdp4List
= pService
->pNext
;
1868 // Remove the service from the middle of the list
1870 while ( NULL
!= pPreviousService
) {
1871 if ( pService
== pPreviousService
->pNext
) {
1872 pPreviousService
->pNext
= pService
->pNext
;
1883 Determine if the sockedt is configured.
1886 @param [in] pSocket Address of a DT_SOCKET structure
1888 @retval EFI_SUCCESS - The port is connected
1889 @retval EFI_NOT_STARTED - The port is not connected
1893 EslUdpSocketIsConfigured4 (
1894 IN DT_SOCKET
* pSocket
1898 DT_PORT
* pNextPort
;
1899 DT_UDP4_CONTEXT
* pUdp4
;
1900 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
1902 struct sockaddr_in LocalAddress
;
1909 Status
= EFI_SUCCESS
;
1912 // Configure the port if necessary
1914 if ( !pSocket
->bConfigured
) {
1916 // Fill in the port list if necessary
1918 if ( NULL
== pSocket
->pPortList
) {
1919 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
1920 LocalAddress
.sin_family
= AF_INET
;
1921 LocalAddress
.sin_addr
.s_addr
= 0;
1922 LocalAddress
.sin_port
= 0;
1923 Status
= EslUdpBind4 ( pSocket
,
1924 (struct sockaddr
*)&LocalAddress
,
1925 LocalAddress
.sin_len
);
1929 // Walk the port list
1931 pPort
= pSocket
->pPortList
;
1932 while ( NULL
!= pPort
) {
1934 // Attempt to configure the port
1936 pNextPort
= pPort
->pLinkSocket
;
1937 pUdp4
= &pPort
->Context
.Udp4
;
1938 pUdp4Protocol
= pUdp4
->pProtocol
;
1939 Status
= pUdp4Protocol
->Configure ( pUdp4Protocol
,
1940 &pUdp4
->ConfigData
);
1941 if ( EFI_ERROR ( Status
)) {
1942 DEBUG (( DEBUG_LISTEN
,
1943 "ERROR - Failed to configure the Udp4 port, Status: %r\r\n",
1946 case EFI_ACCESS_DENIED
:
1947 pSocket
->errno
= EACCES
;
1951 case EFI_DEVICE_ERROR
:
1952 pSocket
->errno
= EIO
;
1955 case EFI_INVALID_PARAMETER
:
1956 pSocket
->errno
= EADDRNOTAVAIL
;
1959 case EFI_NO_MAPPING
:
1960 pSocket
->errno
= EAFNOSUPPORT
;
1963 case EFI_OUT_OF_RESOURCES
:
1964 pSocket
->errno
= ENOBUFS
;
1967 case EFI_UNSUPPORTED
:
1968 pSocket
->errno
= EOPNOTSUPP
;
1973 DEBUG (( DEBUG_LISTEN
,
1974 "0x%08x: Port configured\r\n",
1976 pUdp4
->bConfigured
= TRUE
;
1979 // Start the first read on the port
1981 EslUdpRxStart4 ( pPort
);
1984 // The socket is connected
1986 pSocket
->State
= SOCKET_STATE_CONNECTED
;
1990 // Set the next port
1996 // Determine the configuration status
1998 if ( NULL
!= pSocket
->pPortList
) {
1999 pSocket
->bConfigured
= TRUE
;
2004 // Determine the socket configuration status
2006 if ( !EFI_ERROR ( Status
)) {
2007 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
2011 // Return the port connected state.
2013 DBG_EXIT_STATUS ( Status
);
2019 Buffer data for transmission over a network connection.
2021 This routine is called by the socket layer API to buffer
2022 data for transmission. The data is copied into a local buffer
2023 freeing the application buffer for reuse upon return. When
2024 necessary, this routine will start the transmit engine that
2025 performs the data transmission on the network connection. The
2026 transmit engine transmits the data a packet at a time over the
2029 Transmission errors are returned during the next transmission or
2030 during the close operation. Only buffering errors are returned
2031 during the current transmission attempt.
2033 @param [in] pSocket Address of a DT_SOCKET structure
2035 @param [in] Flags Message control flags
2037 @param [in] BufferLength Length of the the buffer
2039 @param [in] pBuffer Address of a buffer to receive the data.
2041 @param [in] pDataLength Number of received data bytes in the buffer.
2043 @param [in] pAddress Network address of the remote system address
2045 @param [in] AddressLength Length of the remote network address structure
2047 @retval EFI_SUCCESS - Socket data successfully buffered
2052 IN DT_SOCKET
* pSocket
,
2054 IN
size_t BufferLength
,
2055 IN CONST UINT8
* pBuffer
,
2056 OUT
size_t * pDataLength
,
2057 IN
const struct sockaddr
* pAddress
,
2058 IN socklen_t AddressLength
2061 DT_PACKET
* pPacket
;
2062 DT_PACKET
* pPreviousPacket
;
2063 DT_PACKET
** ppPacket
;
2065 const struct sockaddr_in
* pRemoteAddress
;
2066 DT_UDP4_CONTEXT
* pUdp4
;
2067 EFI_UDP4_COMPLETION_TOKEN
* pToken
;
2069 DT_UDP4_TX_DATA
* pTxData
;
2071 EFI_TPL TplPrevious
;
2078 Status
= EFI_UNSUPPORTED
;
2079 pSocket
->errno
= ENOTCONN
;
2083 // Verify that the socket is connected
2085 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
2089 pPort
= pSocket
->pPortList
;
2090 if ( NULL
!= pPort
) {
2092 // Determine the queue head
2094 pUdp4
= &pPort
->Context
.Udp4
;
2095 ppPacket
= &pUdp4
->pTxPacket
;
2096 pToken
= &pUdp4
->TxToken
;
2097 pTxBytes
= &pSocket
->TxBytes
;
2100 // Verify that there is enough room to buffer another
2101 // transmit operation
2103 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
2105 // Attempt to allocate the packet
2107 Status
= EslSocketPacketAllocate ( &pPacket
,
2108 sizeof ( pPacket
->Op
.Udp4Tx
)
2109 - sizeof ( pPacket
->Op
.Udp4Tx
.Buffer
)
2112 if ( !EFI_ERROR ( Status
)) {
2114 // Initialize the transmit operation
2116 pTxData
= &pPacket
->Op
.Udp4Tx
;
2117 pTxData
->TxData
.GatewayAddress
= NULL
;
2118 pTxData
->TxData
.UdpSessionData
= NULL
;
2119 pTxData
->TxData
.DataLength
= (UINT32
) BufferLength
;
2120 pTxData
->TxData
.FragmentCount
= 1;
2121 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
2122 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Udp4Tx
.Buffer
[0];
2125 // Set the remote system address if necessary
2127 if ( NULL
!= pAddress
) {
2128 pRemoteAddress
= (const struct sockaddr_in
*)pAddress
;
2129 pTxData
->Session
.SourceAddress
.Addr
[0] = 0;
2130 pTxData
->Session
.SourceAddress
.Addr
[1] = 0;
2131 pTxData
->Session
.SourceAddress
.Addr
[2] = 0;
2132 pTxData
->Session
.SourceAddress
.Addr
[3] = 0;
2133 pTxData
->Session
.SourcePort
= 0;
2134 pTxData
->Session
.DestinationAddress
.Addr
[0] = (UINT8
)pRemoteAddress
->sin_addr
.s_addr
;
2135 pTxData
->Session
.DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
2136 pTxData
->Session
.DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
2137 pTxData
->Session
.DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
2138 pTxData
->Session
.DestinationPort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
2141 // Use the remote system address when sending this packet
2143 pTxData
->TxData
.UdpSessionData
= &pTxData
->Session
;
2147 // Copy the data into the buffer
2149 CopyMem ( &pPacket
->Op
.Udp4Tx
.Buffer
[0],
2154 // Synchronize with the socket layer
2156 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
2159 // Stop transmission after an error
2161 if ( !EFI_ERROR ( pSocket
->TxError
)) {
2163 // Display the request
2166 "Send %d %s bytes from 0x%08x\r\n",
2171 // Queue the data for transmission
2173 pPacket
->pNext
= NULL
;
2174 pPreviousPacket
= pSocket
->pTxPacketListTail
;
2175 if ( NULL
== pPreviousPacket
) {
2176 pSocket
->pTxPacketListHead
= pPacket
;
2179 pPreviousPacket
->pNext
= pPacket
;
2181 pSocket
->pTxPacketListTail
= pPacket
;
2183 "0x%08x: Packet on transmit list\r\n",
2187 // Account for the buffered data
2189 *pTxBytes
+= BufferLength
;
2190 *pDataLength
= BufferLength
;
2193 // Start the transmit engine if it is idle
2195 if ( NULL
== pUdp4
->pTxPacket
) {
2196 EslUdpTxStart4 ( pSocket
->pPortList
);
2201 // Previous transmit error
2202 // Stop transmission
2204 Status
= pSocket
->TxError
;
2205 pSocket
->errno
= EIO
;
2210 EslSocketPacketFree ( pPacket
, DEBUG_TX
);
2214 // Release the socket layer synchronization
2216 RESTORE_TPL ( TplPrevious
);
2220 // Packet allocation failed
2222 pSocket
->errno
= ENOMEM
;
2227 // Not enough buffer space available
2229 pSocket
->errno
= EAGAIN
;
2230 Status
= EFI_NOT_READY
;
2236 // Return the operation status
2238 DBG_EXIT_STATUS ( Status
);
2244 Process the transmit completion
2246 @param Event The normal transmit completion event
2248 @param pPort The DT_PORT structure address
2257 UINT32 LengthInBytes
;
2258 DT_PACKET
* pCurrentPacket
;
2259 DT_PACKET
* pNextPacket
;
2260 DT_PACKET
* pPacket
;
2261 DT_SOCKET
* pSocket
;
2262 DT_UDP4_CONTEXT
* pUdp4
;
2268 // Locate the active transmit packet
2270 pSocket
= pPort
->pSocket
;
2271 pUdp4
= &pPort
->Context
.Udp4
;
2272 pPacket
= pUdp4
->pTxPacket
;
2275 // Mark this packet as complete
2277 pUdp4
->pTxPacket
= NULL
;
2278 LengthInBytes
= pPacket
->Op
.Udp4Tx
.TxData
.DataLength
;
2279 pSocket
->TxBytes
-= LengthInBytes
;
2282 // Save any transmit error
2284 Status
= pUdp4
->TxToken
.Status
;
2285 if ( EFI_ERROR ( Status
)) {
2286 if ( !EFI_ERROR ( pSocket
->TxError
)) {
2287 pSocket
->TxError
= Status
;
2289 DEBUG (( DEBUG_TX
| DEBUG_INFO
,
2290 "ERROR - Transmit failure for packet 0x%08x, Status: %r\r\n",
2295 // Empty the normal transmit list
2297 pCurrentPacket
= pPacket
;
2298 pNextPacket
= pSocket
->pTxPacketListHead
;
2299 while ( NULL
!= pNextPacket
) {
2300 pPacket
= pNextPacket
;
2301 pNextPacket
= pPacket
->pNext
;
2302 EslSocketPacketFree ( pPacket
, DEBUG_TX
);
2304 pSocket
->pTxPacketListHead
= NULL
;
2305 pSocket
->pTxPacketListTail
= NULL
;
2306 pPacket
= pCurrentPacket
;
2310 DEBUG (( DEBUG_TX
| DEBUG_INFO
,
2311 "0x%08x: Packet transmitted %d bytes successfully\r\n",
2316 // Verify the transmit engine is still running
2318 if ( !pPort
->bCloseNow
) {
2320 // Start the next packet transmission
2322 EslUdpTxStart4 ( pPort
);
2327 // Release this packet
2329 EslSocketPacketFree ( pPacket
, DEBUG_TX
);
2332 // Finish the close operation if necessary
2334 if (( PORT_STATE_CLOSE_STARTED
<= pPort
->State
)
2335 && ( NULL
== pSocket
->pTxPacketListHead
)
2336 && ( NULL
== pUdp4
->pTxPacket
)) {
2338 // Indicate that the transmit is complete
2340 EslUdpPortCloseTxDone4 ( pPort
);
2347 Transmit data using a network connection.
2349 @param [in] pPort Address of a DT_PORT structure
2357 DT_PACKET
* pNextPacket
;
2358 DT_PACKET
* pPacket
;
2359 DT_SOCKET
* pSocket
;
2360 DT_UDP4_CONTEXT
* pUdp4
;
2361 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
2369 Status
= EFI_SUCCESS
;
2372 // Get the packet from the queue head
2374 pSocket
= pPort
->pSocket
;
2375 pPacket
= pSocket
->pTxPacketListHead
;
2376 if ( NULL
!= pPacket
) {
2378 // Remove the packet from the queue
2380 pNextPacket
= pPacket
->pNext
;
2381 pSocket
->pTxPacketListHead
= pNextPacket
;
2382 if ( NULL
== pNextPacket
) {
2383 pSocket
->pTxPacketListTail
= NULL
;
2387 // Set the packet as active
2389 pUdp4
= &pPort
->Context
.Udp4
;
2390 pUdp4
->pTxPacket
= pPacket
;
2393 // Start the transmit operation
2395 pUdp4Protocol
= pUdp4
->pProtocol
;
2396 pUdp4
->TxToken
.Packet
.TxData
= &pPacket
->Op
.Udp4Tx
.TxData
;
2397 Status
= pUdp4Protocol
->Transmit ( pUdp4Protocol
, &pUdp4
->TxToken
);
2398 if ( EFI_ERROR ( Status
)) {
2399 pSocket
= pPort
->pSocket
;
2400 if ( EFI_SUCCESS
== pSocket
->TxError
) {
2401 pSocket
->TxError
= Status
;