4, // RX buffers\r
4, // TX buffers\r
4 }, // TX Oob buffers\r
+ { L"Tcp6",\r
+ &gEfiTcp6ServiceBindingProtocolGuid,\r
+ &gEfiTcp6ProtocolGuid,\r
+ &mEslTcp6ServiceGuid,\r
+ OFFSET_OF ( ESL_LAYER, pTcp6List ),\r
+ 4, // RX buffers\r
+ 4, // TX buffers\r
+ 4 }, // TX Oob buffers\r
{ L"Udp4",\r
&gEfiUdp4ServiceBindingProtocolGuid,\r
&gEfiUdp4ProtocolGuid,\r
OFFSET_OF ( ESL_LAYER, pUdp4List ),\r
4, // RX buffers\r
4, // TX buffers\r
+ 0 }, // TX Oob buffers\r
+ { L"Udp6",\r
+ &gEfiUdp6ServiceBindingProtocolGuid,\r
+ &gEfiUdp6ProtocolGuid,\r
+ &mEslUdp6ServiceGuid,\r
+ OFFSET_OF ( ESL_LAYER, pUdp6List ),\r
+ 4, // RX buffers\r
+ 4, // TX buffers\r
0 } // TX Oob buffers\r
};\r
\r
**/\r
CONST ESL_PROTOCOL_API * cEslAfInet6Api[] = {\r
NULL, // 0\r
- NULL, // SOCK_STREAM\r
- NULL, // SOCK_DGRAM\r
+ &cEslTcp6Api, // SOCK_STREAM\r
+ &cEslUdp6Api, // SOCK_DGRAM\r
NULL, // SOCK_RAW\r
NULL, // SOCK_RDM\r
- NULL // SOCK_SEQPACKET\r
+ &cEslTcp6Api // SOCK_SEQPACKET\r
};\r
\r
/**\r
// Validate the domain value\r
//\r
if (( AF_INET != domain )\r
+ && ( AF_INET6 != domain )\r
&& ( AF_LOCAL != domain )) {\r
DEBUG (( DEBUG_ERROR | DEBUG_SOCKET,\r
"ERROR - Invalid domain value\r\n" ));\r
//\r
// Verify that at least one network connection was found\r
//\r
- if ( NULL == pSocket->pPortList ) {\r
+ if ( NULL != pSocket->pPortList ) {\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ else {\r
if ( EADDRNOTAVAIL == pSocket->errno ) {\r
DEBUG (( DEBUG_BIND | DEBUG_POOL | DEBUG_INIT,\r
"ERROR - Socket address is not available!\r\n" ));\r
break;\r
\r
case SOCKET_STATE_CONNECTING:\r
+ //\r
+ // Poll the network adapter\r
+ //\r
+ EslSocketRxPoll ( pSocket );\r
+\r
//\r
// Poll for connection completion\r
//\r
if ( EFI_NOT_READY != Status ) {\r
if ( !EFI_ERROR ( Status )) {\r
pSocket->State = SOCKET_STATE_CONNECTED;\r
+\r
+ //\r
+ // Start the receive operations\r
+ //\r
+ EslSocketRxStart ( pSocket->pPortList );\r
}\r
else {\r
pSocket->State = SOCKET_STATE_BOUND;\r
}\r
\r
\r
+/**\r
+ Free the socket.\r
+\r
+ This routine frees the socket structure and handle resources.\r
+\r
+ The ::close routine calls EslServiceFreeProtocol which then calls\r
+ this routine to free the socket context structure and close the\r
+ handle.\r
+\r
+ @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.\r
+ \r
+ @param [out] pErrno Address to receive the errno value upon completion.\r
+\r
+ @retval EFI_SUCCESS The socket resources were returned successfully.\r
+\r
+ **/\r
+EFI_STATUS\r
+EslSocketFree (\r
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,\r
+ IN int * pErrno\r
+ )\r
+{\r
+ EFI_HANDLE ChildHandle;\r
+ int errno;\r
+ ESL_LAYER * pLayer;\r
+ ESL_SOCKET * pSocket;\r
+ ESL_SOCKET * pSocketPrevious;\r
+ EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
+\r
+ DBG_ENTER ( );\r
+\r
+ //\r
+ // Assume failure\r
+ //\r
+ errno = EIO;\r
+ pSocket = NULL;\r
+ Status = EFI_INVALID_PARAMETER;\r
+\r
+ //\r
+ // Validate the socket\r
+ //\r
+ pLayer = &mEslLayer;\r
+ if ( NULL != pSocketProtocol ) {\r
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );\r
+\r
+ //\r
+ // Synchronize with the socket layer\r
+ //\r
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+\r
+ //\r
+ // Walk the socket list\r
+ //\r
+ pSocketPrevious = pLayer->pSocketList;\r
+ if ( NULL != pSocketPrevious ) {\r
+ if ( pSocket == pSocketPrevious ) {\r
+ //\r
+ // Remove the socket from the head of the list\r
+ //\r
+ pLayer->pSocketList = pSocket->pNext;\r
+ }\r
+ else {\r
+ //\r
+ // Find the socket in the middle of the list\r
+ //\r
+ while (( NULL != pSocketPrevious )\r
+ && ( pSocket != pSocketPrevious->pNext )) {\r
+ //\r
+ // Set the next socket\r
+ //\r
+ pSocketPrevious = pSocketPrevious->pNext;\r
+ }\r
+ if ( NULL != pSocketPrevious ) {\r
+ //\r
+ // Remove the socket from the middle of the list\r
+ //\r
+ pSocketPrevious = pSocket->pNext;\r
+ }\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+ "ERROR - Socket list is empty!\r\n" ));\r
+ }\r
+\r
+ //\r
+ // Release the socket layer synchronization\r
+ //\r
+ RESTORE_TPL ( TplPrevious );\r
+\r
+ //\r
+ // Determine if the socket was found\r
+ //\r
+ if ( NULL != pSocketPrevious ) {\r
+ pSocket->pNext = NULL;\r
+\r
+ //\r
+ // Remove the socket protocol\r
+ //\r
+ ChildHandle = pSocket->SocketProtocol.SocketHandle;\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ ChildHandle,\r
+ &gEfiSocketProtocolGuid,\r
+ &pSocket->SocketProtocol,\r
+ NULL );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_POOL | DEBUG_INFO,\r
+ "Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",\r
+ ChildHandle ));\r
+\r
+ //\r
+ // Free the socket structure\r
+ //\r
+ Status = gBS->FreePool ( pSocket );\r
+ if ( !EFI_ERROR ( Status )) {\r
+ DEBUG (( DEBUG_POOL,\r
+ "0x%08x: Free pSocket, %d bytes\r\n",\r
+ pSocket,\r
+ sizeof ( *pSocket )));\r
+ errno = 0;\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,\r
+ "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",\r
+ pSocket,\r
+ Status ));\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,\r
+ "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",\r
+ ChildHandle,\r
+ Status ));\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,\r
+ "ERROR - The socket was not in the socket list!\r\n" ));\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+ }\r
+ else {\r
+ DEBUG (( DEBUG_ERROR,\r
+ "ERROR - Invalid parameter pSocketProtocol is NULL\r\n" ));\r
+ }\r
+\r
+ //\r
+ // Return the errno value if possible\r
+ //\r
+ if ( NULL != pErrno ) {\r
+ *pErrno = errno;\r
+ }\r
+\r
+ //\r
+ // Return the operation status\r
+ //\r
+ DBG_EXIT_STATUS ( Status );\r
+ return Status;\r
+}\r
+\r
+\r
/**\r
Get the local address.\r
\r
//\r
// Verify the socket state\r
//\r
- Status = EslSocketIsConfigured ( pSocket );\r
- if ( !EFI_ERROR ( Status )) {\r
+ EslSocketIsConfigured ( pSocket );\r
+ if ( pSocket->bAddressSet ) {\r
//\r
// Verify the address buffer and length address\r
//\r
if (( NULL != pAddress ) && ( NULL != pAddressLength )) {\r
//\r
- // Verify the socket state\r
+ // Verify the API\r
//\r
- if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
+ if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {\r
+ Status = EFI_UNSUPPORTED;\r
+ pSocket->errno = ENOTSUP;\r
+ }\r
+ else {\r
//\r
- // Verify the API\r
+ // Synchronize with the socket layer\r
//\r
- if ( NULL == pSocket->pApi->pfnLocalAddrGet ) {\r
- Status = EFI_UNSUPPORTED;\r
- pSocket->errno = ENOTSUP;\r
- }\r
- else {\r
- //\r
- // Synchronize with the socket layer\r
- //\r
- RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
\r
+ //\r
+ // Verify that there is just a single connection\r
+ //\r
+ pPort = pSocket->pPortList;\r
+ if ( NULL != pPort ) {\r
//\r
- // Verify that there is just a single connection\r
+ // Verify the address length\r
//\r
- pPort = pSocket->pPortList;\r
- if (( NULL != pPort ) && ( NULL == pPort->pLinkSocket )) {\r
+ LengthInBytes = pSocket->pApi->AddressLength;\r
+ if (( LengthInBytes <= *pAddressLength ) \r
+ && ( 255 >= LengthInBytes )) {\r
//\r
- // Verify the address length\r
+ // Return the local address and address length\r
//\r
- LengthInBytes = pSocket->pApi->AddressLength;\r
- if (( LengthInBytes <= *pAddressLength ) \r
- && ( 255 >= LengthInBytes )) {\r
- //\r
- // Return the local address and address length\r
- //\r
- ZeroMem ( pAddress, LengthInBytes );\r
- pAddress->sa_len = (uint8_t)LengthInBytes;\r
- *pAddressLength = pAddress->sa_len;\r
- pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress );\r
- pSocket->errno = 0;\r
- Status = EFI_SUCCESS;\r
- }\r
- else {\r
- pSocket->errno = EINVAL;\r
- Status = EFI_INVALID_PARAMETER;\r
- }\r
+ ZeroMem ( pAddress, LengthInBytes );\r
+ pAddress->sa_len = (uint8_t)LengthInBytes;\r
+ *pAddressLength = pAddress->sa_len;\r
+ pSocket->pApi->pfnLocalAddrGet ( pPort, pAddress );\r
+ pSocket->errno = 0;\r
+ Status = EFI_SUCCESS;\r
}\r
else {\r
- pSocket->errno = ENOTCONN;\r
- Status = EFI_NOT_STARTED;\r
+ pSocket->errno = EINVAL;\r
+ Status = EFI_INVALID_PARAMETER;\r
}\r
- \r
- //\r
- // Release the socket layer synchronization\r
- //\r
- RESTORE_TPL ( TplPrevious );\r
}\r
- }\r
- else {\r
- pSocket->errno = ENOTCONN;\r
- Status = EFI_NOT_STARTED;\r
+ else {\r
+ pSocket->errno = ENOTCONN;\r
+ Status = EFI_NOT_STARTED;\r
+ }\r
+ \r
+ //\r
+ // Release the socket layer synchronization\r
+ //\r
+ RESTORE_TPL ( TplPrevious );\r
}\r
}\r
else {\r
Status = EFI_INVALID_PARAMETER;\r
}\r
}\r
+ else {\r
+ //\r
+ // Address not set\r
+ //\r
+ Status = EFI_NOT_STARTED;\r
+ pSocket->errno = EADDRNOTAVAIL;\r
+ }\r
}\r
\r
//\r
IN ESL_IO_MGMT ** ppFreeQueue,\r
IN UINTN DebugFlags,\r
IN CHAR8 * pEventName,\r
- IN EFI_EVENT_NOTIFY pfnCompletion\r
+ IN PFN_API_IO_COMPLETE pfnCompletion\r
)\r
{\r
ESL_IO_MGMT * pEnd;\r
// Create the event for SocketAccept completion\r
//\r
Status = gBS->CreateEvent ( 0,\r
- TplPrevious,\r
+ TPL_SOCKETS,\r
NULL,\r
NULL,\r
&pSocket->WaitAccept );\r
int errno;\r
socklen_t LengthInBytes;\r
socklen_t MaxBytes;\r
- UINT8 * pOptionData;\r
+ CONST UINT8 * pOptionData;\r
ESL_SOCKET * pSocket;\r
EFI_STATUS Status;\r
\r
if ( pSocket->pApi->DefaultProtocol == level ) {\r
Status = pSocket->pApi->pfnOptionGet ( pSocket,\r
OptionName,\r
- &pOptionData,\r
+ (CONST void ** __restrict)&pOptionData,\r
&LengthInBytes );\r
errno = pSocket->errno;\r
break;\r
//\r
// Return the listen flag\r
//\r
- pOptionData = (UINT8 *)&pSocket->bListenCalled;\r
+ pOptionData = (CONST UINT8 *)&pSocket->bListenCalled;\r
LengthInBytes = sizeof ( pSocket->bListenCalled );\r
break;\r
\r
//\r
// Return the debug flags\r
//\r
- pOptionData = (UINT8 *)&pSocket->bOobInLine;\r
+ pOptionData = (CONST UINT8 *)&pSocket->bOobInLine;\r
LengthInBytes = sizeof ( pSocket->bOobInLine );\r
break;\r
\r
//\r
// Return the out-of-band inline flag\r
//\r
- pOptionData = (UINT8 *)&pSocket->bOobInLine;\r
+ pOptionData = (CONST UINT8 *)&pSocket->bOobInLine;\r
LengthInBytes = sizeof ( pSocket->bOobInLine );\r
break;\r
\r
//\r
// Return the receive timeout\r
//\r
- pOptionData = (UINT8 *)&pSocket->RxTimeout;\r
+ pOptionData = (CONST UINT8 *)&pSocket->RxTimeout;\r
LengthInBytes = sizeof ( pSocket->RxTimeout );\r
break;\r
\r
//\r
// Return the maximum receive buffer size\r
//\r
- pOptionData = (UINT8 *)&pSocket->MaxRxBuf;\r
+ pOptionData = (CONST UINT8 *)&pSocket->MaxRxBuf;\r
LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
break;\r
\r
+ case SO_REUSEADDR:\r
+ //\r
+ // Return the address reuse flag\r
+ //\r
+ pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
+ LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
+ break;\r
+ \r
case SO_SNDBUF:\r
//\r
// Return the maximum transmit buffer size\r
//\r
- pOptionData = (UINT8 *)&pSocket->MaxTxBuf;\r
+ pOptionData = (CONST UINT8 *)&pSocket->MaxTxBuf;\r
LengthInBytes = sizeof ( pSocket->MaxTxBuf );\r
break;\r
\r
//\r
// Return the socket type\r
//\r
- pOptionData = (UINT8 *)&pSocket->Type;\r
+ pOptionData = (CONST UINT8 *)&pSocket->Type;\r
LengthInBytes = sizeof ( pSocket->Type );\r
break;\r
}\r
LengthInBytes = sizeof ( pSocket->MaxRxBuf );\r
break;\r
\r
+ case SO_REUSEADDR:\r
+ //\r
+ // Return the address reuse flag\r
+ //\r
+ pOptionData = (UINT8 *)&pSocket->bReUseAddr;\r
+ LengthInBytes = sizeof ( pSocket->bReUseAddr );\r
+ break;\r
+\r
case SO_SNDBUF:\r
//\r
// Send buffer size\r
LengthInBytes,\r
(VOID **)&pPacket );\r
if ( !EFI_ERROR ( Status )) {\r
- DEBUG (( DebugFlags | DEBUG_POOL | DEBUG_INIT,\r
+ DEBUG (( DebugFlags | DEBUG_POOL,\r
"0x%08x: Allocate pPacket, %d bytes\r\n",\r
pPacket,\r
LengthInBytes ));\r
DBG_ENTER ( );\r
\r
//\r
- // Allocate a packet structure\r
+ // Free a packet structure\r
//\r
LengthInBytes = pPacket->PacketSize;\r
Status = gBS->FreePool ( pPacket );\r
short DetectedEvents;\r
ESL_SOCKET * pSocket;\r
EFI_STATUS Status;\r
+ EFI_TPL TplPrevious;\r
short ValidEvents;\r
\r
DEBUG (( DEBUG_POLL, "Entering SocketPoll\r\n" ));\r
Events & ( ~ValidEvents )));\r
}\r
else {\r
+ //\r
+ // Synchronize with the socket layer\r
+ //\r
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
+ \r
+ //\r
+ // Increase the network performance by extending the\r
+ // polling (idle) loop down into the LAN driver\r
+ //\r
+ EslSocketRxPoll ( pSocket );\r
+ \r
+ //\r
+ // Release the socket layer synchronization\r
+ //\r
+ RESTORE_TPL ( TplPrevious );\r
+\r
//\r
// Check for pending connections\r
//\r
// Verify that the socket is connected\r
//\r
if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
+ //\r
+ // Poll the network to increase performance\r
+ //\r
+ EslSocketRxPoll ( pSocket );\r
+\r
//\r
// Locate the port\r
//\r
}\r
\r
\r
+/**\r
+ Poll a socket for pending receive activity.\r
+\r
+ This routine is called at elivated TPL and extends the idle\r
+ loop which polls a socket down into the LAN driver layer to\r
+ determine if there is any receive activity.\r
+\r
+ The ::EslSocketPoll, ::EslSocketReceive and ::EslSocketTransmit\r
+ routines call this routine when there is nothing to do.\r
+\r
+ @param [in] pSocket Address of an ::EFI_SOCKET structure.\r
+\r
+ **/\r
+VOID\r
+EslSocketRxPoll (\r
+ IN ESL_SOCKET * pSocket\r
+ )\r
+{\r
+ ESL_PORT * pPort;\r
+\r
+ DEBUG (( DEBUG_POLL, "Entering EslSocketRxPoll\r\n" ));\r
+\r
+ //\r
+ // Increase the network performance by extending the\r
+ // polling (idle) loop down into the LAN driver\r
+ //\r
+ pPort = pSocket->pPortList;\r
+ while ( NULL != pPort ) {\r
+ //\r
+ // Poll the LAN adapter\r
+ //\r
+ pPort->pfnRxPoll ( pPort->pProtocol.v );\r
+\r
+ //\r
+ // Locate the next LAN adapter\r
+ //\r
+ pPort = pPort->pLinkSocket;\r
+ }\r
+\r
+ DEBUG (( DEBUG_POLL, "Exiting EslSocketRxPoll\r\n" ));\r
+}\r
+\r
+\r
/**\r
Start a receive operation\r
\r
//\r
RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
\r
+ //\r
+ // Poll the network to increase performance\r
+ //\r
+ EslSocketRxPoll ( pSocket );\r
+\r
//\r
// Attempt to buffer the packet for transmission\r
//\r