2 Implement the socket support for the socket layer.
5 * Bound - pSocket->PortList is not NULL
6 * Listen - AcceptWait event is not NULL
8 Copyright (c) 2011, Intel Corporation
9 All rights reserved. This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
23 Socket driver connection points
25 List the network stack connection points for the socket driver.
27 CONST DT_SOCKET_BINDING cEslSocketBinding
[] = {
29 &gEfiTcp4ServiceBindingProtocolGuid
,
34 &gEfiUdp4ServiceBindingProtocolGuid
,
40 CONST UINTN cEslSocketBindingEntries
= DIM ( cEslSocketBinding
);
46 Initialize an endpoint for network communication.
48 The ::Socket routine initializes the communication endpoint by providing
49 the support for the socket library function ::socket. The
50 <a href="http://www.linuxhowtos.org/manpages/2/socket.htm">Linux</a>,
51 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/socket.html">POSIX</a>
52 and <a href="http://msdn.microsoft.com/en-us/library/ms740506(v=VS.85).aspx">Windows</a>
53 documentation for the socket routine are available online for reference.
55 @param [in] pSocketProtocol Address of the socket protocol structure.
56 @param [in] domain Select the family of protocols for the client or server
59 @param [in] type Specifies how to make the network connection. The following values
63 SOCK_STREAM - Connect to TCP, provides a byte stream
64 that is manipluated by read, recv, send and write.
67 SOCK_SEQPACKET - Connect to TCP, provides sequenced packet stream
68 that is manipulated by read, recv, send and write.
71 SOCK_DGRAM - Connect to UDP, provides a datagram service that is
72 manipulated by recvfrom and sendto.
76 @param [in] protocol Specifies the lower layer protocol to use. The following
79 <li>IPPROTO_TCP</li> - This value must be combined with SOCK_STREAM.</li>
80 <li>IPPROTO_UDP</li> - This value must be combined with SOCK_DGRAM.</li>
83 @param [out] pErrno Address to receive the errno value upon completion.
85 @retval EFI_SUCCESS - Socket successfully created
86 @retval EFI_INVALID_PARAMETER - Invalid domain value, errno = EAFNOSUPPORT
87 @retval EFI_INVALID_PARAMETER - Invalid type value, errno = EINVAL
88 @retval EFI_INVALID_PARAMETER - Invalid protocol value, errno = EINVAL
93 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
109 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
112 // Set the default domain if necessary
114 if ( AF_UNSPEC
== domain
) {
122 Status
= EFI_SUCCESS
;
125 // Use break instead of goto
129 // Validate the domain value
131 if (( AF_INET
!= domain
)
132 && ( AF_LOCAL
!= domain
))
134 DEBUG (( DEBUG_ERROR
| DEBUG_SOCKET
,
135 "ERROR - Invalid domain value" ));
136 Status
= EFI_INVALID_PARAMETER
;
137 errno
= EAFNOSUPPORT
;
142 // Set the default type if necessary
149 // Validate the type value
151 if (( SOCK_STREAM
== type
)
152 || ( SOCK_SEQPACKET
== type
)) {
154 // Set the default protocol if necessary
156 if ( 0 == protocol
) {
157 protocol
= IPPROTO_TCP
;
160 else if ( SOCK_DGRAM
== type
) {
162 // Set the default protocol if necessary
164 if ( 0 == protocol
) {
165 protocol
= IPPROTO_UDP
;
169 DEBUG (( DEBUG_ERROR
| DEBUG_SOCKET
,
170 "ERROR - Invalid type value" ));
171 Status
= EFI_INVALID_PARAMETER
;
177 // Validate the protocol value
179 if (( IPPROTO_TCP
!= protocol
)
180 && ( IPPROTO_UDP
!= protocol
)) {
181 DEBUG (( DEBUG_ERROR
| DEBUG_SOCKET
,
182 "ERROR - Invalid protocol value" ));
183 Status
= EFI_INVALID_PARAMETER
;
189 // Save the socket attributes
191 pSocket
->Domain
= domain
;
192 pSocket
->Type
= type
;
193 pSocket
->Protocol
= protocol
;
202 // Return the operation status
204 if ( NULL
!= pErrno
) {
207 DBG_EXIT_STATUS ( Status
);
213 Accept a network connection.
215 The SocketAccept routine waits for a network connection to the socket.
216 It is able to return the remote network address to the caller if
219 @param [in] pSocketProtocol Address of the socket protocol structure.
221 @param [in] pSockAddr Address of a buffer to receive the remote
224 @param [in, out] pSockAddrLength Length in bytes of the address buffer.
225 On output specifies the length of the
226 remote network address.
228 @param [out] ppSocketProtocol Address of a buffer to receive the socket protocol
229 instance associated with the new socket.
231 @param [out] pErrno Address to receive the errno value upon completion.
233 @retval EFI_SUCCESS New connection successfully created
234 @retval EFI_NOT_READY No connection is available
239 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
240 IN
struct sockaddr
* pSockAddr
,
241 IN OUT socklen_t
* pSockAddrLength
,
242 IN EFI_SOCKET_PROTOCOL
** ppSocketProtocol
,
246 DT_SOCKET
* pNewSocket
;
256 Status
= EFI_SUCCESS
;
259 // Validate the socket
263 if ( NULL
!= pSocketProtocol
) {
264 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
267 // Validate the sockaddr
269 if (( NULL
!= pSockAddr
)
270 && ( NULL
== pSockAddrLength
)) {
271 DEBUG (( DEBUG_ACCEPT
,
272 "ERROR - pSockAddr is NULL!\r\n" ));
273 Status
= EFI_INVALID_PARAMETER
;
274 pSocket
->errno
= EFAULT
;
278 // Synchronize with the socket layer
280 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
283 // Verify that the socket is in the listen state
285 if ( SOCKET_STATE_LISTENING
!= pSocket
->State
) {
286 DEBUG (( DEBUG_ACCEPT
,
287 "ERROR - Socket is not listening!\r\n" ));
288 Status
= EFI_NOT_STARTED
;
289 pSocket
->errno
= EOPNOTSUPP
;
293 // Determine if a socket is available
295 if ( 0 == pSocket
->FifoDepth
) {
297 // No connections available
298 // Determine if any ports are available
300 if ( NULL
== pSocket
->pPortList
) {
302 // No ports available
304 Status
= EFI_DEVICE_ERROR
;
305 pSocket
->errno
= EINVAL
;
308 // Update the socket state
310 pSocket
->State
= SOCKET_STATE_NO_PORTS
;
314 // Ports are available
315 // No connection requests at this time
317 Status
= EFI_NOT_READY
;
318 pSocket
->errno
= EAGAIN
;
324 // Get the remote network address
326 pNewSocket
= pSocket
->pFifoHead
;
327 ASSERT ( NULL
!= pNewSocket
);
328 switch ( pSocket
->Domain
) {
330 DEBUG (( DEBUG_ACCEPT
,
331 "ERROR - Invalid socket address family: %d\r\n",
333 Status
= EFI_INVALID_PARAMETER
;
334 pSocket
->errno
= EADDRNOTAVAIL
;
339 // Determine the connection point within the network stack
341 switch ( pSocket
->Type
) {
343 DEBUG (( DEBUG_ACCEPT
,
344 "ERROR - Invalid socket type: %d\r\n",
346 Status
= EFI_INVALID_PARAMETER
;
347 pSocket
->errno
= EADDRNOTAVAIL
;
352 Status
= EslTcpAccept4 ( pNewSocket
,
359 Status = UdpAccept4 ( pSocket );
365 if ( !EFI_ERROR ( Status
)) {
367 // Remove the new socket from the list
369 pSocket
->pFifoHead
= pNewSocket
->pNextConnection
;
370 if ( NULL
== pSocket
->pFifoHead
) {
371 pSocket
->pFifoTail
= NULL
;
375 // Account for this socket
377 pSocket
->FifoDepth
-= 1;
380 // Update the new socket's state
382 pNewSocket
->State
= SOCKET_STATE_CONNECTED
;
383 pNewSocket
->bConfigured
= TRUE
;
384 DEBUG (( DEBUG_ACCEPT
,
385 "0x%08x: Socket connected\r\n",
392 // Release the socket layer synchronization
394 RESTORE_TPL ( TplPrevious
);
399 // Return the new socket
401 if (( NULL
!= ppSocketProtocol
)
402 && ( NULL
!= pNewSocket
)) {
403 *ppSocketProtocol
= &pNewSocket
->SocketProtocol
;
407 // Return the operation status
409 if ( NULL
!= pErrno
) {
410 if ( NULL
!= pSocket
) {
411 *pErrno
= pSocket
->errno
;
415 Status
= EFI_INVALID_PARAMETER
;
419 DBG_EXIT_STATUS ( Status
);
425 Allocate and initialize a DT_SOCKET structure.
427 The ::SocketAllocate() function allocates a DT_SOCKET structure
428 and installs a protocol on ChildHandle. If pChildHandle is a
429 pointer to NULL, then a new handle is created and returned in
430 pChildHandle. If pChildHandle is not a pointer to NULL, then
431 the protocol installs on the existing pChildHandle.
433 @param [in, out] pChildHandle Pointer to the handle of the child to create.
434 If it is NULL, then a new handle is created.
435 If it is a pointer to an existing UEFI handle,
436 then the protocol is added to the existing UEFI
438 @param [in] DebugFlags Flags for debug messages
439 @param [in, out] ppSocket The buffer to receive the DT_SOCKET structure address.
441 @retval EFI_SUCCESS The protocol was added to ChildHandle.
442 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
443 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
445 @retval other The child handle was not created
451 IN OUT EFI_HANDLE
* pChildHandle
,
453 IN OUT DT_SOCKET
** ppSocket
465 // Create a socket structure
467 LengthInBytes
= sizeof ( *pSocket
);
468 Status
= gBS
->AllocatePool (
469 EfiRuntimeServicesData
,
473 if ( !EFI_ERROR ( Status
)) {
474 DEBUG (( DebugFlags
| DEBUG_POOL
| DEBUG_INIT
,
475 "0x%08x: Allocate pSocket, %d bytes\r\n",
480 // Initialize the socket protocol
482 ZeroMem ( pSocket
, LengthInBytes
);
484 pSocket
->Signature
= SOCKET_SIGNATURE
;
485 pSocket
->SocketProtocol
.pfnAccept
= EslSocketAccept
;
486 pSocket
->SocketProtocol
.pfnBind
= EslSocketBind
;
487 pSocket
->SocketProtocol
.pfnClosePoll
= EslSocketClosePoll
;
488 pSocket
->SocketProtocol
.pfnCloseStart
= EslSocketCloseStart
;
489 pSocket
->SocketProtocol
.pfnConnect
= EslSocketConnect
;
490 pSocket
->SocketProtocol
.pfnGetLocal
= EslSocketGetLocalAddress
;
491 pSocket
->SocketProtocol
.pfnGetPeer
= EslSocketGetPeerAddress
;
492 pSocket
->SocketProtocol
.pfnListen
= EslSocketListen
;
493 pSocket
->SocketProtocol
.pfnOptionGet
= EslSocketOptionGet
;
494 pSocket
->SocketProtocol
.pfnOptionSet
= EslSocketOptionSet
;
495 pSocket
->SocketProtocol
.pfnPoll
= EslSocketPoll
;
496 pSocket
->SocketProtocol
.pfnReceive
= EslSocketReceive
;
497 pSocket
->SocketProtocol
.pfnSend
= EslSocketTransmit
;
498 pSocket
->SocketProtocol
.pfnShutdown
= EslSocketShutdown
;
499 pSocket
->SocketProtocol
.pfnSocket
= EslSocket
;
501 pSocket
->MaxRxBuf
= MAX_RX_DATA
;
502 pSocket
->MaxTxBuf
= MAX_TX_DATA
;
505 // Install the socket protocol on the specified handle
507 Status
= gBS
->InstallMultipleProtocolInterfaces (
509 &gEfiSocketProtocolGuid
,
510 &pSocket
->SocketProtocol
,
513 if ( !EFI_ERROR ( Status
)) {
514 DEBUG (( DebugFlags
| DEBUG_POOL
| DEBUG_INIT
| DEBUG_INFO
,
515 "Installed: gEfiSocketProtocolGuid on 0x%08x\r\n",
517 pSocket
->SocketProtocol
.SocketHandle
= *pChildHandle
;
520 // Synchronize with the socket layer
522 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
525 // Add this socket to the list
528 pSocket
->pNext
= pLayer
->pSocketList
;
529 pLayer
->pSocketList
= pSocket
;
532 // Release the socket layer synchronization
534 RESTORE_TPL ( TplPrevious
);
537 // Return the socket structure address
542 DEBUG (( DEBUG_ERROR
| DebugFlags
| DEBUG_POOL
| DEBUG_INIT
,
543 "ERROR - Failed to install gEfiSocketProtocolGuid on 0x%08x, Status: %r\r\n",
549 // Release the socket if necessary
551 if ( EFI_ERROR ( Status
)) {
552 gBS
->FreePool ( pSocket
);
553 DEBUG (( DebugFlags
| DEBUG_POOL
| DEBUG_INIT
,
554 "0x%08x: Free pSocket, %d bytes\r\n",
556 sizeof ( *pSocket
)));
561 DEBUG (( DEBUG_ERROR
| DebugFlags
| DEBUG_POOL
| DEBUG_INIT
,
562 "ERROR - Failed socket allocation, Status: %r\r\n",
567 // Return the operation status
569 DBG_EXIT_STATUS ( Status
);
575 Bind a name to a socket.
577 The ::SocketBind routine connects a name to a socket on the local machine. The
578 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html">POSIX</a>
579 documentation for the bind routine is available online for reference.
581 @param [in] pSocketProtocol Address of the socket protocol structure.
583 @param [in] pSockAddr Address of a sockaddr structure that contains the
584 connection point on the local machine. An IPv4 address
585 of INADDR_ANY specifies that the connection is made to
586 all of the network stacks on the platform. Specifying a
587 specific IPv4 address restricts the connection to the
588 network stack supporting that address. Specifying zero
589 for the port causes the network layer to assign a port
590 number from the dynamic range. Specifying a specific
591 port number causes the network layer to use that port.
593 @param [in] SockAddrLen Specifies the length in bytes of the sockaddr structure.
595 @param [out] pErrno Address to receive the errno value upon completion.
597 @retval EFI_SUCCESS - Socket successfully created
602 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
603 IN
const struct sockaddr
* pSockAddr
,
604 IN socklen_t SockAddrLength
,
617 Status
= EFI_SUCCESS
;
620 // Validate the socket
623 if ( NULL
!= pSocketProtocol
) {
624 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
627 // Validate the structure pointer
629 if ( NULL
== pSockAddr
) {
631 "ERROR - pSockAddr is NULL!\r\n" ));
632 Status
= EFI_INVALID_PARAMETER
;
633 pSocket
->errno
= EFAULT
;
637 // Validate the name length
639 if (( SockAddrLength
< ( sizeof ( struct sockaddr
) - sizeof ( pSockAddr
->sa_data
)))
640 || ( pSockAddr
->sa_len
< ( sizeof ( struct sockaddr
) - sizeof ( pSockAddr
->sa_data
)))) {
642 "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",
644 pSockAddr
->sa_len
));
645 Status
= EFI_INVALID_PARAMETER
;
646 pSocket
->errno
= EINVAL
;
650 // Set the socket address length
652 if ( SockAddrLength
> pSockAddr
->sa_len
) {
653 SockAddrLength
= pSockAddr
->sa_len
;
657 // Synchronize with the socket layer
659 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
662 // Validate the local address
664 switch ( pSockAddr
->sa_family
) {
667 "ERROR - Invalid bind address family: %d\r\n",
668 pSockAddr
->sa_family
));
669 Status
= EFI_INVALID_PARAMETER
;
670 pSocket
->errno
= EADDRNOTAVAIL
;
675 // Determine the connection point within the network stack
677 switch ( pSocket
->Type
) {
680 "ERROR - Invalid socket type: %d\r\n",
682 Status
= EFI_INVALID_PARAMETER
;
683 pSocket
->errno
= EADDRNOTAVAIL
;
688 Status
= EslTcpBind4 ( pSocket
,
694 Status
= EslUdpBind4 ( pSocket
,
703 // Mark this socket as bound if successful
705 if ( !EFI_ERROR ( Status
)) {
706 pSocket
->State
= SOCKET_STATE_BOUND
;
710 // Release the socket layer synchronization
712 RESTORE_TPL ( TplPrevious
);
718 // Return the operation status
720 if ( NULL
!= pErrno
) {
721 if ( NULL
!= pSocket
) {
722 *pErrno
= pSocket
->errno
;
726 Status
= EFI_INVALID_PARAMETER
;
730 DBG_EXIT_STATUS ( Status
);
736 Determine if the socket is closed
738 Reverses the operations of the ::SocketAllocate() routine.
740 @param [in] pSocketProtocol Address of the socket protocol structure.
741 @param [out] pErrno Address to receive the errno value upon completion.
743 @retval EFI_SUCCESS Socket successfully closed
744 @retval EFI_NOT_READY Close still in progress
745 @retval EFI_ALREADY Close operation already in progress
746 @retval Other Failed to close the socket
751 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
757 DT_SOCKET
* pNextSocket
;
768 Status
= EFI_SUCCESS
;
771 // Synchronize with the socket layer
773 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
779 pNextSocket
= pLayer
->pSocketList
;
780 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
781 while ( NULL
!= pNextSocket
) {
782 if ( pNextSocket
== pSocket
) {
784 // Determine if the socket is in the closing state
786 if ( SOCKET_STATE_CLOSED
== pSocket
->State
) {
788 // Walk the list of ports
790 if ( NULL
== pSocket
->pPortList
) {
792 // All the ports are closed
793 // Close the WaitAccept event if necessary
795 if ( NULL
!= pSocket
->WaitAccept
) {
796 Status
= gBS
->CloseEvent ( pSocket
->WaitAccept
);
797 if ( !EFI_ERROR ( Status
)) {
798 DEBUG (( DEBUG_SOCKET
| DEBUG_CLOSE
| DEBUG_POOL
,
799 "0x%08x: Closed WaitAccept event\r\n",
800 pSocket
->WaitAccept
));
802 // Return the transmit status
804 Status
= pSocket
->TxError
;
805 if ( EFI_ERROR ( Status
)) {
806 pSocket
->errno
= EIO
;
810 DEBUG (( DEBUG_ERROR
| DEBUG_SOCKET
| DEBUG_CLOSE
| DEBUG_POOL
,
811 "ERROR - Failed to close the WaitAccept event, Status: %r\r\n",
813 ASSERT ( EFI_SUCCESS
== Status
);
819 // At least one port is still open
821 Status
= EFI_NOT_READY
;
827 // SocketCloseStart was not called
829 Status
= EFI_NOT_STARTED
;
836 // Set the next socket
838 pNextSocket
= pNextSocket
->pNext
;
842 // Handle the error case where the socket was already closed
844 if ( NULL
== pSocket
) {
848 Status
= EFI_NOT_FOUND
;
853 // Release the socket layer synchronization
855 RESTORE_TPL ( TplPrevious
);
858 // Return the operation status
860 if ( NULL
!= pErrno
) {
863 DBG_EXIT_STATUS ( Status
);
869 Start the close operation on the socket
871 Start closing the socket by closing all of the ports. Upon
872 completion, the ::SocketPoll() routine finishes closing the
875 @param [in] pSocketProtocol Address of the socket protocol structure.
876 @param [in] bCloseNow Boolean to control close behavior
877 @param [out] pErrno Address to receive the errno value upon completion.
879 @retval EFI_SUCCESS Socket successfully closed
880 @retval EFI_NOT_READY Close still in progress
881 @retval EFI_ALREADY Close operation already in progress
882 @retval Other Failed to close the socket
886 EslSocketCloseStart (
887 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
888 IN BOOLEAN bCloseNow
,
904 Status
= EFI_SUCCESS
;
908 // Synchronize with the socket layer
910 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
913 // Determine if the socket is already closed
915 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
916 if ( SOCKET_STATE_CLOSED
> pSocket
->State
) {
918 // Update the socket state
920 pSocket
->State
= SOCKET_STATE_CLOSED
;
923 // Walk the list of ports
925 pPort
= pSocket
->pPortList
;
926 while ( NULL
!= pPort
) {
928 // Start closing the ports
930 pNextPort
= pPort
->pLinkSocket
;
931 Status
= pPort
->pfnCloseStart ( pPort
,
933 DEBUG_CLOSE
| DEBUG_LISTEN
| DEBUG_CONNECTION
);
934 if (( EFI_SUCCESS
!= Status
)
935 && ( EFI_NOT_READY
!= Status
)) {
947 // Attempt to finish closing the socket
949 if ( NULL
== pPort
) {
950 Status
= EslSocketClosePoll ( pSocketProtocol
, &errno
);
954 Status
= EFI_ALREADY_STARTED
;
959 // Release the socket layer synchronization
961 RESTORE_TPL ( TplPrevious
);
964 // Return the operation status
966 if ( NULL
!= pErrno
) {
969 DBG_EXIT_STATUS ( Status
);
975 Connect to a remote system via the network.
977 The ::SocketConnect routine attempts to establish a connection to a
978 socket on the local or remote system using the specified address.
980 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html">connect</a>
981 documentation is available online.
983 There are three states associated with a connection:
985 <li>Not connected</li>
986 <li>Connection in progress</li>
989 In the "Not connected" state, calls to ::connect start the connection
990 processing and update the state to "Connection in progress". During
991 the "Connection in progress" state, connect polls for connection completion
992 and moves the state to "Connected" after the connection is established.
993 Note that these states are only visible when the file descriptor is marked
994 with O_NONBLOCK. Also, the POLL_WRITE bit is set when the connection
995 completes and may be used by poll or select as an indicator to call
998 @param [in] pSocketProtocol Address of the socket protocol structure.
1000 @param [in] pSockAddr Network address of the remote system.
1002 @param [in] SockAddrLength Length in bytes of the network address.
1004 @param [out] pErrno Address to receive the errno value upon completion.
1006 @retval EFI_SUCCESS The connection was successfully established.
1007 @retval EFI_NOT_READY The connection is in progress, call this routine again.
1008 @retval Others The connection attempt failed.
1013 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
1014 IN
const struct sockaddr
* pSockAddr
,
1015 IN socklen_t SockAddrLength
,
1019 DT_SOCKET
* pSocket
;
1021 EFI_TPL TplPrevious
;
1023 DEBUG (( DEBUG_CONNECT
, "Entering SocketConnect\r\n" ));
1028 Status
= EFI_SUCCESS
;
1031 // Validate the socket
1034 if ( NULL
!= pSocketProtocol
) {
1035 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
1038 // Validate the name length
1040 if (( SockAddrLength
< ( sizeof ( struct sockaddr
) - sizeof ( pSockAddr
->sa_data
)))
1041 || ( pSockAddr
->sa_len
< ( sizeof ( struct sockaddr
) - sizeof ( pSockAddr
->sa_data
)))) {
1042 DEBUG (( DEBUG_CONNECT
,
1043 "ERROR - Invalid bind name length: %d, sa_len: %d\r\n",
1045 pSockAddr
->sa_len
));
1046 Status
= EFI_INVALID_PARAMETER
;
1047 pSocket
->errno
= EINVAL
;
1056 // Set the socket address length
1058 if ( SockAddrLength
> pSockAddr
->sa_len
) {
1059 SockAddrLength
= pSockAddr
->sa_len
;
1063 // Synchronize with the socket layer
1065 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
1068 // Validate the socket state
1070 switch ( pSocket
->State
) {
1073 // Wrong socket state
1075 pSocket
->errno
= EIO
;
1076 Status
= EFI_DEVICE_ERROR
;
1079 case SOCKET_STATE_NOT_CONFIGURED
:
1080 case SOCKET_STATE_BOUND
:
1082 // Validate the local address
1084 switch ( pSockAddr
->sa_family
) {
1086 DEBUG (( DEBUG_CONNECT
,
1087 "ERROR - Invalid bind address family: %d\r\n",
1088 pSockAddr
->sa_family
));
1089 Status
= EFI_INVALID_PARAMETER
;
1090 pSocket
->errno
= EADDRNOTAVAIL
;
1095 // Determine the connection point within the network stack
1097 switch ( pSocket
->Type
) {
1099 DEBUG (( DEBUG_CONNECT
,
1100 "ERROR - Invalid socket type: %d\r\n",
1102 Status
= EFI_INVALID_PARAMETER
;
1103 pSocket
->errno
= EADDRNOTAVAIL
;
1107 case SOCK_SEQPACKET
:
1109 // Start the connection processing
1111 Status
= EslTcpConnectStart4 ( pSocket
,
1116 // Set the next state if connecting
1118 if ( EFI_NOT_READY
== Status
) {
1119 pSocket
->State
= SOCKET_STATE_CONNECTING
;
1124 Status
= EslUdpConnect4 ( pSocket
,
1133 case SOCKET_STATE_CONNECTING
:
1135 // Validate the local address
1137 switch ( pSockAddr
->sa_family
) {
1139 DEBUG (( DEBUG_CONNECT
,
1140 "ERROR - Invalid bind address family: %d\r\n",
1141 pSockAddr
->sa_family
));
1142 Status
= EFI_INVALID_PARAMETER
;
1143 pSocket
->errno
= EADDRNOTAVAIL
;
1148 // Determine the connection point within the network stack
1150 switch ( pSocket
->Type
) {
1152 DEBUG (( DEBUG_CONNECT
,
1153 "ERROR - Invalid socket type: %d\r\n",
1155 Status
= EFI_INVALID_PARAMETER
;
1156 pSocket
->errno
= EADDRNOTAVAIL
;
1160 case SOCK_SEQPACKET
:
1162 // Determine if the connection processing is completed
1164 Status
= EslTcpConnectPoll4 ( pSocket
);
1167 // Set the next state if connected
1169 if ( EFI_NOT_READY
!= Status
) {
1170 if ( !EFI_ERROR ( Status
)) {
1171 pSocket
->State
= SOCKET_STATE_CONNECTED
;
1174 pSocket
->State
= SOCKET_STATE_BOUND
;
1181 // Already connected
1183 pSocket
->errno
= EISCONN
;
1184 Status
= EFI_ALREADY_STARTED
;
1191 case SOCKET_STATE_CONNECTED
:
1193 // Already connected
1195 pSocket
->errno
= EISCONN
;
1196 Status
= EFI_ALREADY_STARTED
;
1201 // Release the socket layer synchronization
1203 RESTORE_TPL ( TplPrevious
);
1208 // Return the operation status
1210 if ( NULL
!= pErrno
) {
1211 if ( NULL
!= pSocket
) {
1212 *pErrno
= pSocket
->errno
;
1217 // Bad socket protocol
1219 DEBUG (( DEBUG_ERROR
| DEBUG_CONNECT
,
1220 "ERROR - pSocketProtocol invalid!\r\n" ));
1221 Status
= EFI_INVALID_PARAMETER
;
1227 // Return the operation status
1229 DEBUG (( DEBUG_CONNECT
, "Exiting SocketConnect, Status: %r\r\n", Status
));
1235 Creates a child handle and installs a protocol.
1237 The CreateChild() function installs a protocol on ChildHandle.
1238 If pChildHandle is a pointer to NULL, then a new handle is created and returned in pChildHandle.
1239 If pChildHandle is not a pointer to NULL, then the protocol installs on the existing pChildHandle.
1241 @param [in] pThis Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1242 @param [in] pChildHandle Pointer to the handle of the child to create. If it is NULL,
1243 then a new handle is created. If it is a pointer to an existing UEFI handle,
1244 then the protocol is added to the existing UEFI handle.
1246 @retval EFI_SUCCESS The protocol was added to ChildHandle.
1247 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
1248 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
1250 @retval other The child handle was not created
1255 EslSocketCreateChild (
1256 IN EFI_SERVICE_BINDING_PROTOCOL
* pThis
,
1257 IN OUT EFI_HANDLE
* pChildHandle
1260 DT_SOCKET
* pSocket
;
1266 // Create a socket structure
1268 Status
= EslSocketAllocate ( pChildHandle
,
1273 // Return the operation status
1275 DBG_EXIT_STATUS ( Status
);
1281 Destroys a child handle with a protocol installed on it.
1283 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
1284 that was installed by CreateChild() from ChildHandle. If the removed protocol is the
1285 last protocol on ChildHandle, then ChildHandle is destroyed.
1287 @param [in] pThis Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
1288 @param [in] ChildHandle Handle of the child to destroy
1290 @retval EFI_SUCCESS The protocol was removed from ChildHandle.
1291 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
1292 @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.
1293 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
1294 because its services are being used.
1295 @retval other The child handle was not destroyed
1300 EslSocketDestroyChild (
1301 IN EFI_SERVICE_BINDING_PROTOCOL
* pThis
,
1302 IN EFI_HANDLE ChildHandle
1306 DT_SOCKET
* pSocket
;
1307 DT_SOCKET
* pSocketPrevious
;
1308 EFI_SOCKET_PROTOCOL
* pSocketProtocol
;
1310 EFI_TPL TplPrevious
;
1315 // Locate the socket control structure
1317 pLayer
= &mEslLayer
;
1318 Status
= gBS
->OpenProtocol (
1320 &gEfiSocketProtocolGuid
,
1321 (VOID
**)&pSocketProtocol
,
1322 pLayer
->ImageHandle
,
1324 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1326 if ( !EFI_ERROR ( Status
)) {
1327 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
1330 // Synchronize with the socket layer
1332 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
1335 // Walk the socket list
1337 pSocketPrevious
= pLayer
->pSocketList
;
1338 if ( NULL
!= pSocketPrevious
) {
1339 if ( pSocket
== pSocketPrevious
) {
1341 // Remove the socket from the head of the list
1343 pLayer
->pSocketList
= pSocket
->pNext
;
1347 // Find the socket in the middle of the list
1349 while (( NULL
!= pSocketPrevious
)
1350 && ( pSocket
!= pSocketPrevious
->pNext
)) {
1352 // Set the next socket
1354 pSocketPrevious
= pSocketPrevious
->pNext
;
1356 if ( NULL
!= pSocketPrevious
) {
1358 // Remove the socket from the middle of the list
1360 pSocketPrevious
= pSocket
->pNext
;
1365 DEBUG (( DEBUG_ERROR
| DEBUG_POOL
,
1366 "ERROR - Socket list is empty!\r\n" ));
1370 // Release the socket layer synchronization
1372 RESTORE_TPL ( TplPrevious
);
1375 // Determine if the socket was found
1377 if ( NULL
!= pSocketPrevious
) {
1378 pSocket
->pNext
= NULL
;
1381 // Remove the socket protocol
1383 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1385 &gEfiSocketProtocolGuid
,
1386 &pSocket
->SocketProtocol
,
1388 if ( !EFI_ERROR ( Status
)) {
1389 DEBUG (( DEBUG_POOL
| DEBUG_INFO
,
1390 "Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",
1394 // Free the socket structure
1396 Status
= gBS
->FreePool ( pSocket
);
1397 if ( !EFI_ERROR ( Status
)) {
1398 DEBUG (( DEBUG_POOL
,
1399 "0x%08x: Free pSocket, %d bytes\r\n",
1401 sizeof ( *pSocket
)));
1404 DEBUG (( DEBUG_ERROR
| DEBUG_POOL
,
1405 "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",
1411 DEBUG (( DEBUG_ERROR
| DEBUG_POOL
| DEBUG_INFO
,
1412 "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",
1418 DEBUG (( DEBUG_ERROR
| DEBUG_INFO
,
1419 "ERROR - The socket was not in the socket list!\r\n" ));
1420 Status
= EFI_NOT_FOUND
;
1424 DEBUG (( DEBUG_ERROR
,
1425 "ERROR - Failed to open socket protocol on 0x%08x, Status; %r\r\n",
1431 // Return the operation status
1433 DBG_EXIT_STATUS ( Status
);
1439 Get the local address.
1441 @param [in] pSocketProtocol Address of the socket protocol structure.
1443 @param [out] pAddress Network address to receive the local system address
1445 @param [in,out] pAddressLength Length of the local network address structure
1447 @param [out] pErrno Address to receive the errno value upon completion.
1449 @retval EFI_SUCCESS - Local address successfully returned
1453 EslSocketGetLocalAddress (
1454 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
1455 OUT
struct sockaddr
* pAddress
,
1456 IN OUT socklen_t
* pAddressLength
,
1460 DT_SOCKET
* pSocket
;
1462 EFI_TPL TplPrevious
;
1469 Status
= EFI_SUCCESS
;
1472 // Validate the socket
1475 if ( NULL
!= pSocketProtocol
) {
1476 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
1479 // Verify the address buffer and length address
1481 if (( NULL
!= pAddress
) && ( NULL
!= pAddressLength
)) {
1483 // Verify the socket state
1485 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
1487 // Synchronize with the socket layer
1489 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
1492 // Validate the local address
1494 switch ( pSocket
->Domain
) {
1497 "ERROR - Invalid socket address family: %d\r\n",
1499 Status
= EFI_INVALID_PARAMETER
;
1500 pSocket
->errno
= EADDRNOTAVAIL
;
1505 // Determine the connection point within the network stack
1507 switch ( pSocket
->Type
) {
1510 "ERROR - Invalid socket type: %d\r\n",
1512 Status
= EFI_INVALID_PARAMETER
;
1516 case SOCK_SEQPACKET
:
1518 // Get the local address
1520 Status
= EslTcpGetLocalAddress4 ( pSocket
,
1527 // Get the local address
1529 Status
= EslUdpGetLocalAddress4 ( pSocket
,
1538 // Release the socket layer synchronization
1540 RESTORE_TPL ( TplPrevious
);
1543 pSocket
->errno
= ENOTCONN
;
1544 Status
= EFI_NOT_STARTED
;
1548 pSocket
->errno
= EINVAL
;
1549 Status
= EFI_INVALID_PARAMETER
;
1554 // Return the operation status
1556 if ( NULL
!= pErrno
) {
1557 if ( NULL
!= pSocket
) {
1558 *pErrno
= pSocket
->errno
;
1562 Status
= EFI_INVALID_PARAMETER
;
1566 DBG_EXIT_STATUS ( Status
);
1572 Get the peer address.
1574 @param [in] pSocketProtocol Address of the socket protocol structure.
1576 @param [out] pAddress Network address to receive the remote system address
1578 @param [in,out] pAddressLength Length of the remote network address structure
1580 @param [out] pErrno Address to receive the errno value upon completion.
1582 @retval EFI_SUCCESS - Remote address successfully returned
1586 EslSocketGetPeerAddress (
1587 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
1588 OUT
struct sockaddr
* pAddress
,
1589 IN OUT socklen_t
* pAddressLength
,
1593 DT_SOCKET
* pSocket
;
1595 EFI_TPL TplPrevious
;
1602 Status
= EFI_SUCCESS
;
1605 // Validate the socket
1608 if ( NULL
!= pSocketProtocol
) {
1609 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
1612 // Verify the address buffer and length address
1614 if (( NULL
!= pAddress
) && ( NULL
!= pAddressLength
)) {
1616 // Verify the socket state
1618 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
1620 // Synchronize with the socket layer
1622 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
1625 // Validate the local address
1627 switch ( pSocket
->Domain
) {
1630 "ERROR - Invalid socket address family: %d\r\n",
1632 Status
= EFI_INVALID_PARAMETER
;
1633 pSocket
->errno
= EADDRNOTAVAIL
;
1638 // Determine the connection point within the network stack
1640 switch ( pSocket
->Type
) {
1643 "ERROR - Invalid socket type: %d\r\n",
1645 Status
= EFI_INVALID_PARAMETER
;
1649 case SOCK_SEQPACKET
:
1651 // Verify the port state
1653 Status
= EslTcpGetRemoteAddress4 ( pSocket
,
1660 // Verify the port state
1662 Status
= EslUdpGetRemoteAddress4 ( pSocket
,
1671 // Release the socket layer synchronization
1673 RESTORE_TPL ( TplPrevious
);
1676 pSocket
->errno
= ENOTCONN
;
1677 Status
= EFI_NOT_STARTED
;
1681 pSocket
->errno
= EINVAL
;
1682 Status
= EFI_INVALID_PARAMETER
;
1687 // Return the operation status
1689 if ( NULL
!= pErrno
) {
1690 if ( NULL
!= pSocket
) {
1691 *pErrno
= pSocket
->errno
;
1695 Status
= EFI_INVALID_PARAMETER
;
1699 DBG_EXIT_STATUS ( Status
);
1705 Establish the known port to listen for network connections.
1707 The ::SocketListen routine places the port into a state that enables connection
1708 attempts. Connections are placed into FIFO order in a queue to be serviced
1709 by the application. The application calls the ::SocketAccept routine to remove
1710 the next connection from the queue and get the associated socket. The
1711 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html">POSIX</a>
1712 documentation for the listen routine is available online for reference.
1714 @param [in] pSocketProtocol Address of the socket protocol structure.
1716 @param [in] Backlog Backlog specifies the maximum FIFO depth for
1717 the connections waiting for the application
1718 to call accept. Connection attempts received
1719 while the queue is full are refused.
1721 @param [out] pErrno Address to receive the errno value upon completion.
1723 @retval EFI_SUCCESS - Socket successfully created
1724 @retval Other - Failed to enable the socket for listen
1729 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
1734 DT_SOCKET
* pSocket
;
1736 EFI_STATUS TempStatus
;
1737 EFI_TPL TplPrevious
;
1744 Status
= EFI_SUCCESS
;
1747 // Validate the socket
1750 if ( NULL
!= pSocketProtocol
) {
1751 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
1756 pSocket
->Status
= EFI_SUCCESS
;
1760 // Verify that the bind operation was successful
1762 if ( SOCKET_STATE_BOUND
== pSocket
->State
) {
1764 // Synchronize with the socket layer
1766 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
1769 // Create the event for SocketAccept completion
1771 Status
= gBS
->CreateEvent ( 0,
1775 &pSocket
->WaitAccept
);
1776 if ( !EFI_ERROR ( Status
)) {
1777 DEBUG (( DEBUG_POOL
,
1778 "0x%08x: Created WaitAccept event\r\n",
1779 pSocket
->WaitAccept
));
1781 // Set the maximum FIFO depth
1783 if ( 0 >= Backlog
) {
1784 Backlog
= MAX_PENDING_CONNECTIONS
;
1787 if ( SOMAXCONN
< Backlog
) {
1788 Backlog
= SOMAXCONN
;
1791 pSocket
->MaxFifoDepth
= Backlog
;
1796 // Validate the local address
1798 switch ( pSocket
->Domain
) {
1800 DEBUG (( DEBUG_BIND
,
1801 "ERROR - Invalid socket address family: %d\r\n",
1803 Status
= EFI_INVALID_PARAMETER
;
1804 pSocket
->errno
= EADDRNOTAVAIL
;
1809 // Determine the connection point within the network stack
1811 switch ( pSocket
->Type
) {
1813 DEBUG (( DEBUG_BIND
,
1814 "ERROR - Invalid socket type: %d\r\n",
1816 Status
= EFI_INVALID_PARAMETER
;
1817 pSocket
->errno
= EADDRNOTAVAIL
;
1821 case SOCK_SEQPACKET
:
1822 Status
= EslTcpListen4 ( pSocket
);
1827 Status = UdpListen4 ( pSocket );
1835 // Place the socket in the listen state if successful
1837 if ( !EFI_ERROR ( Status
)) {
1838 pSocket
->State
= SOCKET_STATE_LISTENING
;
1842 // Not waiting for SocketAccept to complete
1844 TempStatus
= gBS
->CloseEvent ( pSocket
->WaitAccept
);
1845 if ( !EFI_ERROR ( TempStatus
)) {
1846 DEBUG (( DEBUG_POOL
,
1847 "0x%08x: Closed WaitAccept event\r\n",
1848 pSocket
->WaitAccept
));
1849 pSocket
->WaitAccept
= NULL
;
1852 DEBUG (( DEBUG_ERROR
| DEBUG_POOL
,
1853 "ERROR - Failed to close WaitAccept event, Status: %r\r\n",
1855 ASSERT ( EFI_SUCCESS
== TempStatus
);
1860 DEBUG (( DEBUG_ERROR
| DEBUG_LISTEN
,
1861 "ERROR - Failed to create the WaitAccept event, Status: %r\r\n",
1863 pSocket
->errno
= ENOMEM
;
1867 // Release the socket layer synchronization
1869 RESTORE_TPL ( TplPrevious
);
1872 DEBUG (( DEBUG_ERROR
| DEBUG_LISTEN
,
1873 "ERROR - Bind operation must be performed first!\r\n" ));
1874 pSocket
->errno
= EDESTADDRREQ
;
1879 // Return the operation status
1881 if ( NULL
!= pErrno
) {
1882 if ( NULL
!= pSocket
) {
1883 *pErrno
= pSocket
->errno
;
1887 Status
= EFI_INVALID_PARAMETER
;
1891 DBG_EXIT_STATUS ( Status
);
1897 Get the socket options
1899 Retrieve the socket options one at a time by name. The
1900 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html">POSIX</a>
1901 documentation is available online.
1903 @param [in] pSocketProtocol Address of the socket protocol structure.
1904 @param [in] level Option protocol level
1905 @param [in] OptionName Name of the option
1906 @param [out] pOptionValue Buffer to receive the option value
1907 @param [in,out] pOptionLength Length of the buffer in bytes,
1908 upon return length of the option value in bytes
1909 @param [out] pErrno Address to receive the errno value upon completion.
1911 @retval EFI_SUCCESS - Socket data successfully received
1915 EslSocketOptionGet (
1916 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
1919 OUT
void * __restrict pOptionValue
,
1920 IN OUT socklen_t
* __restrict pOptionLength
,
1925 socklen_t LengthInBytes
;
1927 UINT8
* pOptionData
;
1928 DT_SOCKET
* pSocket
;
1937 Status
= EFI_INVALID_PARAMETER
;
1940 // Validate the socket
1943 if (( NULL
!= pSocketProtocol
)
1944 && ( NULL
!= pOptionValue
)
1945 && ( NULL
!= pOptionLength
)) {
1946 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
1948 MaxBytes
= *pOptionLength
;
1953 // Protocol level not supported
1956 Status
= EFI_UNSUPPORTED
;
1960 switch ( OptionName
) {
1963 // Option not supported
1966 Status
= EFI_UNSUPPORTED
;
1971 // Return the receive timeout
1973 pOptionData
= (UINT8
*)&pSocket
->RxTimeout
;
1974 LengthInBytes
= sizeof ( pSocket
->RxTimeout
);
1979 // Return the maximum transmit buffer size
1981 pOptionData
= (UINT8
*)&pSocket
->MaxRxBuf
;
1982 LengthInBytes
= sizeof ( pSocket
->MaxRxBuf
);
1987 // Return the maximum transmit buffer size
1989 pOptionData
= (UINT8
*)&pSocket
->MaxTxBuf
;
1990 LengthInBytes
= sizeof ( pSocket
->MaxTxBuf
);
1995 // Return the socket type
1997 pOptionData
= (UINT8
*)&pSocket
->Type
;
1998 LengthInBytes
= sizeof ( pSocket
->Type
);
2005 // Return the option length
2007 *pOptionLength
= LengthInBytes
;
2010 // Return the option value
2012 if ( NULL
!= pOptionData
) {
2014 // Silently truncate the value length
2016 if ( LengthInBytes
> MaxBytes
) {
2017 LengthInBytes
= MaxBytes
;
2019 CopyMem ( pOptionValue
, pOptionData
, LengthInBytes
);
2021 Status
= EFI_SUCCESS
;
2026 // Return the operation status
2028 if ( NULL
!= pErrno
) {
2031 DBG_EXIT_STATUS ( Status
);
2037 Set the socket options
2039 Adjust the socket options one at a time by name. The
2040 <a href="http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html">POSIX</a>
2041 documentation is available online.
2043 @param [in] pSocketProtocol Address of the socket protocol structure.
2044 @param [in] level Option protocol level
2045 @param [in] OptionName Name of the option
2046 @param [in] pOptionValue Buffer containing the option value
2047 @param [in] OptionLength Length of the buffer in bytes
2048 @param [out] pErrno Address to receive the errno value upon completion.
2050 @retval EFI_SUCCESS - Socket data successfully received
2054 EslSocketOptionSet (
2055 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
2058 IN CONST
void * pOptionValue
,
2059 IN socklen_t OptionLength
,
2064 socklen_t LengthInBytes
;
2065 UINT8
* pOptionData
;
2066 DT_SOCKET
* pSocket
;
2075 Status
= EFI_INVALID_PARAMETER
;
2078 // Validate the socket
2081 if (( NULL
!= pSocketProtocol
)
2082 && ( NULL
!= pOptionValue
)) {
2083 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
2089 // Protocol level not supported
2092 Status
= EFI_UNSUPPORTED
;
2096 switch ( OptionName
) {
2099 // Option not supported
2102 Status
= EFI_UNSUPPORTED
;
2107 // Return the receive timeout
2109 pOptionData
= (UINT8
*)&pSocket
->RxTimeout
;
2110 LengthInBytes
= sizeof ( pSocket
->RxTimeout
);
2115 // Return the maximum transmit buffer size
2117 pOptionData
= (UINT8
*)&pSocket
->MaxRxBuf
;
2118 LengthInBytes
= sizeof ( pSocket
->MaxRxBuf
);
2126 // Return the maximum transmit buffer size
2128 pOptionData
= (UINT8
*)&pSocket
->MaxTxBuf
;
2129 LengthInBytes
= sizeof ( pSocket
->MaxTxBuf
);
2136 // Validate the option length
2138 if ( LengthInBytes
<= OptionLength
) {
2140 // Set the option value
2142 if ( NULL
!= pOptionData
) {
2143 CopyMem ( pOptionData
, pOptionValue
, LengthInBytes
);
2145 Status
= EFI_SUCCESS
;
2151 // Return the operation status
2153 if ( NULL
!= pErrno
) {
2156 DBG_EXIT_STATUS ( Status
);
2162 Allocate a packet for a receive or transmit operation
2164 @param [in] ppPacket Address to receive the DT_PACKET structure
2165 @param [in] LengthInBytes Length of the packet structure
2166 @param [in] DebugFlags Flags for debug messages
2168 @retval EFI_SUCCESS - The packet was allocated successfully
2172 EslSocketPacketAllocate (
2173 IN DT_PACKET
** ppPacket
,
2174 IN
size_t LengthInBytes
,
2178 DT_PACKET
* pPacket
;
2184 // Allocate a packet structure
2186 LengthInBytes
+= sizeof ( *pPacket
)
2187 - sizeof ( pPacket
->Op
);
2188 Status
= gBS
->AllocatePool ( EfiRuntimeServicesData
,
2190 (VOID
**)&pPacket
);
2191 if ( !EFI_ERROR ( Status
)) {
2192 DEBUG (( DebugFlags
| DEBUG_POOL
| DEBUG_INIT
,
2193 "0x%08x: Allocate pPacket, %d bytes\r\n",
2196 pPacket
->PacketSize
= LengthInBytes
;
2199 DEBUG (( DebugFlags
| DEBUG_POOL
| DEBUG_INFO
,
2200 "ERROR - Packet allocation failed for %d bytes, Status: %r\r\n",
2207 // Return the packet
2209 *ppPacket
= pPacket
;
2212 // Return the operation status
2214 DBG_EXIT_STATUS ( Status
);
2220 Free a packet used for receive or transmit operation
2222 @param [in] pPacket Address of the DT_PACKET structure
2223 @param [in] DebugFlags Flags for debug messages
2225 @retval EFI_SUCCESS - The packet was allocated successfully
2229 EslSocketPacketFree (
2230 IN DT_PACKET
* pPacket
,
2234 UINTN LengthInBytes
;
2240 // Allocate a packet structure
2242 LengthInBytes
= pPacket
->PacketSize
;
2243 Status
= gBS
->FreePool ( pPacket
);
2244 if ( !EFI_ERROR ( Status
)) {
2245 DEBUG (( DebugFlags
| DEBUG_POOL
,
2246 "0x%08x: Free pPacket, %d bytes\r\n",
2251 DEBUG (( DebugFlags
| DEBUG_POOL
| DEBUG_INFO
,
2252 "ERROR - Failed to free packet 0x%08x, Status: %r\r\n",
2258 // Return the operation status
2260 DBG_EXIT_STATUS ( Status
);
2266 Poll a socket for pending activity.
2268 The SocketPoll routine checks a socket for pending activity associated
2269 with the event mask. Activity is returned in the detected event buffer.
2271 @param [in] pSocketProtocol Address of the socket protocol structure.
2273 @param [in] Events Events of interest for this socket
2275 @param [in] pEvents Address to receive the detected events
2277 @param [out] pErrno Address to receive the errno value upon completion.
2279 @retval EFI_SUCCESS - Socket successfully polled
2280 @retval EFI_INVALID_PARAMETER - When pEvents is NULL
2285 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
2291 short DetectedEvents
;
2292 DT_SOCKET
* pSocket
;
2294 EFI_TPL TplPrevious
;
2297 DEBUG (( DEBUG_POLL
, "Entering SocketPoll\r\n" ));
2302 Status
= EFI_SUCCESS
;
2304 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
2308 // Verify the socket state
2310 if ( !pSocket
->bConfigured
) {
2312 // Synchronize with the socket layer
2314 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
2317 // Validate the local address
2319 switch ( pSocket
->Domain
) {
2322 "ERROR - Invalid socket address family: %d\r\n",
2324 Status
= EFI_INVALID_PARAMETER
;
2325 pSocket
->errno
= EADDRNOTAVAIL
;
2330 // Determine the connection point within the network stack
2332 switch ( pSocket
->Type
) {
2335 "ERROR - Invalid socket type: %d\r\n",
2337 Status
= EFI_INVALID_PARAMETER
;
2338 pSocket
->errno
= EADDRNOTAVAIL
;
2342 case SOCK_SEQPACKET
:
2344 // Verify the port state
2346 Status
= EslTcpSocketIsConfigured4 ( pSocket
);
2351 // Verify the port state
2353 Status
= EslUdpSocketIsConfigured4 ( pSocket
);
2360 // Release the socket layer synchronization
2362 RESTORE_TPL ( TplPrevious
);
2364 if ( !EFI_ERROR ( Status
)) {
2366 // Check for invalid events
2368 ValidEvents
= POLLIN
2370 | POLLOUT
| POLLWRNORM
2377 if ( 0 != ( Events
& ( ~ValidEvents
))) {
2378 DetectedEvents
|= POLLNVAL
;
2379 DEBUG (( DEBUG_INFO
| DEBUG_POLL
,
2380 "ERROR - Invalid event mask, Valid Events: 0x%04x, Invalid Events: 0x%04x\r\n",
2381 Events
& ValidEvents
,
2382 Events
& ( ~ValidEvents
)));
2386 // Check for pending connections
2388 if ( 0 != pSocket
->FifoDepth
) {
2390 // A connection is waiting for an accept call
2391 // See posix connect documentation at
2392 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.htm
2394 DetectedEvents
|= POLLIN
| POLLRDNORM
;
2396 if ( pSocket
->bConnected
) {
2398 // A connection is present
2399 // See posix connect documentation at
2400 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.htm
2402 DetectedEvents
|= POLLOUT
| POLLWRNORM
;
2406 // The following bits are set based upon the POSIX poll documentation at
2407 // http://pubs.opengroup.org/onlinepubs/9699919799/functions/poll.html
2411 // Check for urgent receive data
2413 if ( 0 < pSocket
->RxOobBytes
) {
2414 DetectedEvents
|= POLLRDBAND
| POLLPRI
| POLLIN
;
2418 // Check for normal receive data
2420 if (( 0 < pSocket
->RxBytes
)
2421 || ( EFI_SUCCESS
!= pSocket
->RxError
)) {
2422 DetectedEvents
|= POLLRDNORM
| POLLIN
;
2426 // Handle the receive errors
2428 if (( EFI_SUCCESS
!= pSocket
->RxError
)
2429 && ( 0 == ( DetectedEvents
& POLLIN
))) {
2430 DetectedEvents
|= POLLERR
| POLLIN
| POLLRDNORM
| POLLRDBAND
;
2434 // Check for urgent transmit data buffer space
2436 if (( MAX_TX_DATA
> pSocket
->TxOobBytes
)
2437 || ( EFI_SUCCESS
!= pSocket
->TxError
)) {
2438 DetectedEvents
|= POLLWRBAND
;
2442 // Check for normal transmit data buffer space
2444 if (( MAX_TX_DATA
> pSocket
->TxBytes
)
2445 || ( EFI_SUCCESS
!= pSocket
->TxError
)) {
2446 DetectedEvents
|= POLLWRNORM
;
2450 // Handle the transmit error
2452 if ( EFI_ERROR ( pSocket
->TxError
)) {
2453 DetectedEvents
|= POLLERR
;
2459 // Return the detected events
2461 *pEvents
= DetectedEvents
& ( Events
2467 // Return the operation status
2469 DEBUG (( DEBUG_POLL
, "Exiting SocketPoll, Status: %r\r\n", Status
));
2475 Receive data from a network connection.
2478 @param [in] pSocketProtocol Address of the socket protocol structure.
2480 @param [in] Flags Message control flags
2482 @param [in] BufferLength Length of the the buffer
2484 @param [in] pBuffer Address of a buffer to receive the data.
2486 @param [in] pDataLength Number of received data bytes in the buffer.
2488 @param [out] pAddress Network address to receive the remote system address
2490 @param [in,out] pAddressLength Length of the remote network address structure
2492 @param [out] pErrno Address to receive the errno value upon completion.
2494 @retval EFI_SUCCESS - Socket data successfully received
2499 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
2501 IN
size_t BufferLength
,
2503 OUT
size_t * pDataLength
,
2504 OUT
struct sockaddr
* pAddress
,
2505 IN OUT socklen_t
* pAddressLength
,
2509 DT_SOCKET
* pSocket
;
2511 EFI_TPL TplPrevious
;
2518 Status
= EFI_SUCCESS
;
2521 // Validate the socket
2524 if ( NULL
!= pSocketProtocol
) {
2525 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
2528 // Return the transmit error if necessary
2530 if ( EFI_SUCCESS
!= pSocket
->TxError
) {
2531 pSocket
->errno
= EIO
;
2532 Status
= pSocket
->TxError
;
2533 pSocket
->TxError
= EFI_SUCCESS
;
2537 // Verify the socket state
2539 if ( !pSocket
->bConfigured
) {
2541 // Synchronize with the socket layer
2543 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
2546 // Validate the local address
2548 switch ( pSocket
->Domain
) {
2551 "ERROR - Invalid socket address family: %d\r\n",
2553 Status
= EFI_INVALID_PARAMETER
;
2554 pSocket
->errno
= EADDRNOTAVAIL
;
2559 // Determine the connection point within the network stack
2561 switch ( pSocket
->Type
) {
2564 "ERROR - Invalid socket type: %d\r\n",
2566 Status
= EFI_INVALID_PARAMETER
;
2570 case SOCK_SEQPACKET
:
2572 // Verify the port state
2574 Status
= EslTcpSocketIsConfigured4 ( pSocket
);
2579 // Verify the port state
2581 Status
= EslUdpSocketIsConfigured4 ( pSocket
);
2588 // Release the socket layer synchronization
2590 RESTORE_TPL ( TplPrevious
);
2593 // Set errno if a failure occurs
2595 if ( EFI_ERROR ( Status
)) {
2596 pSocket
->errno
= EADDRNOTAVAIL
;
2599 if ( !EFI_ERROR ( Status
)) {
2601 // Validate the buffer length
2603 if (( NULL
== pDataLength
)
2604 && ( 0 > pDataLength
)
2605 && ( NULL
== pBuffer
)) {
2606 if ( NULL
== pDataLength
) {
2608 "ERROR - pDataLength is NULL!\r\n" ));
2610 else if ( NULL
== pBuffer
) {
2612 "ERROR - pBuffer is NULL!\r\n" ));
2616 "ERROR - Data length < 0!\r\n" ));
2618 Status
= EFI_INVALID_PARAMETER
;
2619 pSocket
->errno
= EFAULT
;
2623 // Synchronize with the socket layer
2625 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
2628 // Validate the local address
2630 switch ( pSocket
->Domain
) {
2633 "ERROR - Invalid socket address family: %d\r\n",
2635 Status
= EFI_INVALID_PARAMETER
;
2636 pSocket
->errno
= EADDRNOTAVAIL
;
2641 // Determine the connection point within the network stack
2643 switch ( pSocket
->Type
) {
2646 "ERROR - Invalid socket type: %d\r\n",
2648 Status
= EFI_INVALID_PARAMETER
;
2649 pSocket
->errno
= EADDRNOTAVAIL
;
2653 case SOCK_SEQPACKET
:
2654 Status
= EslTcpReceive4 ( pSocket
,
2664 Status
= EslUdpReceive4 ( pSocket
,
2677 // Release the socket layer synchronization
2679 RESTORE_TPL ( TplPrevious
);
2686 // Return the operation status
2688 if ( NULL
!= pErrno
) {
2689 if ( NULL
!= pSocket
) {
2690 *pErrno
= pSocket
->errno
;
2694 Status
= EFI_INVALID_PARAMETER
;
2698 DBG_EXIT_STATUS ( Status
);
2704 Shutdown the socket receive and transmit operations
2706 The SocketShutdown routine stops the socket receive and transmit
2709 @param [in] pSocketProtocol Address of the socket protocol structure.
2711 @param [in] How Which operations to stop
2713 @param [out] pErrno Address to receive the errno value upon completion.
2715 @retval EFI_SUCCESS - Socket operations successfully shutdown
2720 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
2725 DT_SOCKET
* pSocket
;
2727 EFI_TPL TplPrevious
;
2734 Status
= EFI_SUCCESS
;
2737 // Validate the socket
2740 if ( NULL
!= pSocketProtocol
) {
2741 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
2744 // Verify that the socket is connected
2746 if ( pSocket
->bConnected
) {
2748 // Validate the How value
2750 if (( SHUT_RD
<= How
) && ( SHUT_RDWR
>= How
)) {
2752 // Synchronize with the socket layer
2754 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
2757 // Disable the receiver if requested
2759 if (( SHUT_RD
== How
) || ( SHUT_RDWR
== How
)) {
2760 pSocket
->bRxDisable
= TRUE
;
2764 // Disable the transmitter if requested
2766 if (( SHUT_WR
== How
) || ( SHUT_RDWR
== How
)) {
2767 pSocket
->bTxDisable
= TRUE
;
2771 // Validate the local address
2773 switch ( pSocket
->Domain
) {
2776 "ERROR - Invalid socket address family: %d\r\n",
2778 Status
= EFI_INVALID_PARAMETER
;
2779 pSocket
->errno
= EADDRNOTAVAIL
;
2784 // Determine the connection point within the network stack
2786 switch ( pSocket
->Type
) {
2789 "ERROR - Invalid socket type: %d\r\n",
2791 Status
= EFI_INVALID_PARAMETER
;
2795 case SOCK_SEQPACKET
:
2797 // Cancel the pending receive operation
2799 Status
= EslTcpRxCancel4 ( pSocket
);
2804 // Cancel the pending receive operation
2806 Status
= EslUdpRxCancel4 ( pSocket
);
2813 // Release the socket layer synchronization
2815 RESTORE_TPL ( TplPrevious
);
2819 // The socket is not connected
2821 pSocket
->errno
= ENOTCONN
;
2822 Status
= EFI_NOT_STARTED
;
2827 // Invalid How value
2829 pSocket
->errno
= EINVAL
;
2830 Status
= EFI_INVALID_PARAMETER
;
2835 // Return the operation status
2837 if ( NULL
!= pErrno
) {
2838 if ( NULL
!= pSocket
) {
2839 *pErrno
= pSocket
->errno
;
2843 Status
= EFI_INVALID_PARAMETER
;
2847 DBG_EXIT_STATUS ( Status
);
2853 Send data using a network connection.
2855 The SocketTransmit routine queues the data for transmission to the
2856 remote network connection.
2858 @param [in] pSocketProtocol Address of the socket protocol structure.
2860 @param [in] Flags Message control flags
2862 @param [in] BufferLength Length of the the buffer
2864 @param [in] pBuffer Address of a buffer containing the data to send
2866 @param [in] pDataLength Address to receive the number of data bytes sent
2868 @param [in] pAddress Network address of the remote system address
2870 @param [in] AddressLength Length of the remote network address structure
2872 @param [out] pErrno Address to receive the errno value upon completion.
2874 @retval EFI_SUCCESS - Socket data successfully queued for transmit
2879 IN EFI_SOCKET_PROTOCOL
* pSocketProtocol
,
2881 IN
size_t BufferLength
,
2882 IN CONST UINT8
* pBuffer
,
2883 OUT
size_t * pDataLength
,
2884 IN
const struct sockaddr
* pAddress
,
2885 IN socklen_t AddressLength
,
2889 DT_SOCKET
* pSocket
;
2891 EFI_TPL TplPrevious
;
2898 Status
= EFI_SUCCESS
;
2901 // Validate the socket
2904 if ( NULL
!= pSocketProtocol
) {
2905 pSocket
= SOCKET_FROM_PROTOCOL ( pSocketProtocol
);
2908 // Return the transmit error if necessary
2910 if ( EFI_SUCCESS
!= pSocket
->TxError
) {
2911 pSocket
->errno
= EIO
;
2912 Status
= pSocket
->TxError
;
2913 pSocket
->TxError
= EFI_SUCCESS
;
2917 // Verify the socket state
2919 if ( !pSocket
->bConfigured
) {
2921 // Synchronize with the socket layer
2923 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
2926 // Validate the local address
2928 switch ( pSocket
->Domain
) {
2931 "ERROR - Invalid socket address family: %d\r\n",
2933 Status
= EFI_INVALID_PARAMETER
;
2934 pSocket
->errno
= EADDRNOTAVAIL
;
2939 // Determine the connection point within the network stack
2941 switch ( pSocket
->Type
) {
2944 "ERROR - Invalid socket type: %d\r\n",
2946 Status
= EFI_INVALID_PARAMETER
;
2950 case SOCK_SEQPACKET
:
2952 // Verify the port state
2954 Status
= EslTcpSocketIsConfigured4 ( pSocket
);
2959 // Verify the port state
2961 Status
= EslUdpSocketIsConfigured4 ( pSocket
);
2968 // Release the socket layer synchronization
2970 RESTORE_TPL ( TplPrevious
);
2973 // Set errno if a failure occurs
2975 if ( EFI_ERROR ( Status
)) {
2976 pSocket
->errno
= EADDRNOTAVAIL
;
2979 if ( !EFI_ERROR ( Status
)) {
2981 // Verify that transmit is still allowed
2983 if ( !pSocket
->bTxDisable
) {
2985 // Validate the buffer length
2987 if (( NULL
== pDataLength
)
2988 && ( 0 > pDataLength
)
2989 && ( NULL
== pBuffer
)) {
2990 if ( NULL
== pDataLength
) {
2992 "ERROR - pDataLength is NULL!\r\n" ));
2994 else if ( NULL
== pBuffer
) {
2996 "ERROR - pBuffer is NULL!\r\n" ));
3000 "ERROR - Data length < 0!\r\n" ));
3002 Status
= EFI_INVALID_PARAMETER
;
3003 pSocket
->errno
= EFAULT
;
3007 // Validate the remote network address
3009 if (( NULL
!= pAddress
)
3010 && ( AddressLength
< pAddress
->sa_len
)) {
3012 "ERROR - Invalid sin_len field in address\r\n" ));
3013 Status
= EFI_INVALID_PARAMETER
;
3014 pSocket
->errno
= EFAULT
;
3018 // Synchronize with the socket layer
3020 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
3023 // Validate the local address
3025 switch ( pSocket
->Domain
) {
3028 "ERROR - Invalid socket address family: %d\r\n",
3030 Status
= EFI_INVALID_PARAMETER
;
3031 pSocket
->errno
= EADDRNOTAVAIL
;
3036 // Determine the connection point within the network stack
3038 switch ( pSocket
->Type
) {
3041 "ERROR - Invalid socket type: %d\r\n",
3043 Status
= EFI_INVALID_PARAMETER
;
3044 pSocket
->errno
= EADDRNOTAVAIL
;
3048 case SOCK_SEQPACKET
:
3049 Status
= EslTcpTxBuffer4 ( pSocket
,
3057 Status
= EslUdpTxBuffer4 ( pSocket
,
3070 // Release the socket layer synchronization
3072 RESTORE_TPL ( TplPrevious
);
3078 // The transmitter was shutdown
3080 pSocket
->errno
= EPIPE
;
3081 Status
= EFI_NOT_STARTED
;
3088 // Return the operation status
3090 if ( NULL
!= pErrno
) {
3091 if ( NULL
!= pSocket
) {
3092 *pErrno
= pSocket
->errno
;
3096 Status
= EFI_INVALID_PARAMETER
;
3100 DBG_EXIT_STATUS ( Status
);
3106 Socket layer's service binding protocol delcaration.
3108 EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding
= {
3109 EslSocketCreateChild
,
3110 EslSocketDestroyChild