+/** 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
+ @param[out] pErrno Address to receive the errno value upon completion.\r
+\r
+ @retval EFI_SUCCESS The socket resources were returned successfully.\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
+/** Get the local address.\r