summaryrefslogtreecommitdiff
path: root/StdLib
diff options
context:
space:
mode:
authorlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>2012-10-08 21:39:35 +0000
committerlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>2012-10-08 21:39:35 +0000
commit4652be0c5a106d0604c2d3274803fc0f844b0433 (patch)
treebe8f424d6afb3baad4753ed03d4ec3f8234a6dcb /StdLib
parente06a4cd134064590aa1a855ff4b973023279e805 (diff)
Fixed close for socket to properly release the socket context structure and the handle.
Signed-off-by: lpleahy git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13802 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'StdLib')
-rw-r--r--StdLib/BsdSocketLib/close.c17
-rw-r--r--StdLib/EfiSocketLib/DxeSupport.c98
-rw-r--r--StdLib/EfiSocketLib/Socket.c162
-rw-r--r--StdLib/EfiSocketLib/Socket.h22
-rw-r--r--StdLib/EfiSocketLib/UseEfiSocketLib.c34
-rw-r--r--StdLib/Include/Protocol/EfiSocket.h20
-rw-r--r--StdLib/UseSocketDxe/UseSocketDxe.c53
7 files changed, 295 insertions, 111 deletions
diff --git a/StdLib/BsdSocketLib/close.c b/StdLib/BsdSocketLib/close.c
index f3f7e98cb..01eb48ecb 100644
--- a/StdLib/BsdSocketLib/close.c
+++ b/StdLib/BsdSocketLib/close.c
@@ -31,7 +31,6 @@ BslSocketCloseWork (
IN int * pErrno
)
{
- EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
EFI_STATUS Status;
//
@@ -50,21 +49,9 @@ BslSocketCloseWork (
}
if ( !EFI_ERROR ( Status )) {
//
- // Locate the socket protocol
+ // Release the socket resources
//
- Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,
- NULL,
- (VOID **) &pServiceBinding );
- if ( !EFI_ERROR ( Status )) {
- //
- // Release the handle
- //
- Status = pServiceBinding->DestroyChild ( pServiceBinding,
- pSocketProtocol->SocketHandle );
- }
- if ( EFI_ERROR ( Status )) {
- *pErrno = EIO;
- }
+ *pErrno = EslServiceFreeProtocol ( pSocketProtocol );
}
else {
DEBUG (( DEBUG_ERROR,
diff --git a/StdLib/EfiSocketLib/DxeSupport.c b/StdLib/EfiSocketLib/DxeSupport.c
index 284fa9cdf..808b710d2 100644
--- a/StdLib/EfiSocketLib/DxeSupport.c
+++ b/StdLib/EfiSocketLib/DxeSupport.c
@@ -91,11 +91,8 @@ EslDxeDestroyChild (
)
{
ESL_LAYER * pLayer;
- ESL_SOCKET * pSocket;
- ESL_SOCKET * pSocketPrevious;
EFI_SOCKET_PROTOCOL * pSocketProtocol;
EFI_STATUS Status;
- EFI_TPL TplPrevious;
DBG_ENTER ( );
@@ -112,101 +109,10 @@ EslDxeDestroyChild (
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if ( !EFI_ERROR ( Status )) {
- pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
-
- //
- // Synchronize with the socket layer
- //
- RAISE_TPL ( TplPrevious, TPL_SOCKETS );
-
- //
- // Walk the socket list
- //
- pSocketPrevious = pLayer->pSocketList;
- if ( NULL != pSocketPrevious ) {
- if ( pSocket == pSocketPrevious ) {
- //
- // Remove the socket from the head of the list
- //
- pLayer->pSocketList = pSocket->pNext;
- }
- else {
- //
- // Find the socket in the middle of the list
- //
- while (( NULL != pSocketPrevious )
- && ( pSocket != pSocketPrevious->pNext )) {
- //
- // Set the next socket
- //
- pSocketPrevious = pSocketPrevious->pNext;
- }
- if ( NULL != pSocketPrevious ) {
- //
- // Remove the socket from the middle of the list
- //
- pSocketPrevious = pSocket->pNext;
- }
- }
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_POOL,
- "ERROR - Socket list is empty!\r\n" ));
- }
-
- //
- // Release the socket layer synchronization
- //
- RESTORE_TPL ( TplPrevious );
-
//
- // Determine if the socket was found
+ // Free the socket resources
//
- if ( NULL != pSocketPrevious ) {
- pSocket->pNext = NULL;
-
- //
- // Remove the socket protocol
- //
- Status = gBS->UninstallMultipleProtocolInterfaces (
- ChildHandle,
- &gEfiSocketProtocolGuid,
- &pSocket->SocketProtocol,
- NULL );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_POOL | DEBUG_INFO,
- "Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",
- ChildHandle ));
-
- //
- // Free the socket structure
- //
- Status = gBS->FreePool ( pSocket );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_POOL,
- "0x%08x: Free pSocket, %d bytes\r\n",
- pSocket,
- sizeof ( *pSocket )));
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_POOL,
- "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",
- pSocket,
- Status ));
- }
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,
- "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",
- ChildHandle,
- Status ));
- }
- }
- else {
- DEBUG (( DEBUG_ERROR | DEBUG_INFO,
- "ERROR - The socket was not in the socket list!\r\n" ));
- Status = EFI_NOT_FOUND;
- }
+ Status = EslSocketFree ( pSocketProtocol, NULL );
}
else {
DEBUG (( DEBUG_ERROR,
diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c
index e718e9bdf..52e5f2948 100644
--- a/StdLib/EfiSocketLib/Socket.c
+++ b/StdLib/EfiSocketLib/Socket.c
@@ -1946,6 +1946,168 @@ EslSocketCopyFragmentedBuffer (
/**
+ Free the socket.
+
+ This routine frees the socket structure and handle resources.
+
+ The ::close routine calls EslServiceFreeProtocol which then calls
+ this routine to free the socket context structure and close the
+ handle.
+
+ @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS The socket resources were returned successfully.
+
+ **/
+EFI_STATUS
+EslSocketFree (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ )
+{
+ EFI_HANDLE ChildHandle;
+ int errno;
+ ESL_LAYER * pLayer;
+ ESL_SOCKET * pSocket;
+ ESL_SOCKET * pSocketPrevious;
+ EFI_STATUS Status;
+ EFI_TPL TplPrevious;
+
+ DBG_ENTER ( );
+
+ //
+ // Assume failure
+ //
+ errno = EIO;
+ pSocket = NULL;
+ Status = EFI_INVALID_PARAMETER;
+
+ //
+ // Validate the socket
+ //
+ pLayer = &mEslLayer;
+ if ( NULL != pSocketProtocol ) {
+ pSocket = SOCKET_FROM_PROTOCOL ( pSocketProtocol );
+
+ //
+ // Synchronize with the socket layer
+ //
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+
+ //
+ // Walk the socket list
+ //
+ pSocketPrevious = pLayer->pSocketList;
+ if ( NULL != pSocketPrevious ) {
+ if ( pSocket == pSocketPrevious ) {
+ //
+ // Remove the socket from the head of the list
+ //
+ pLayer->pSocketList = pSocket->pNext;
+ }
+ else {
+ //
+ // Find the socket in the middle of the list
+ //
+ while (( NULL != pSocketPrevious )
+ && ( pSocket != pSocketPrevious->pNext )) {
+ //
+ // Set the next socket
+ //
+ pSocketPrevious = pSocketPrevious->pNext;
+ }
+ if ( NULL != pSocketPrevious ) {
+ //
+ // Remove the socket from the middle of the list
+ //
+ pSocketPrevious = pSocket->pNext;
+ }
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+ "ERROR - Socket list is empty!\r\n" ));
+ }
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+
+ //
+ // Determine if the socket was found
+ //
+ if ( NULL != pSocketPrevious ) {
+ pSocket->pNext = NULL;
+
+ //
+ // Remove the socket protocol
+ //
+ ChildHandle = pSocket->SocketProtocol.SocketHandle;
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiSocketProtocolGuid,
+ &pSocket->SocketProtocol,
+ NULL );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL | DEBUG_INFO,
+ "Removed: gEfiSocketProtocolGuid from 0x%08x\r\n",
+ ChildHandle ));
+
+ //
+ // Free the socket structure
+ //
+ Status = gBS->FreePool ( pSocket );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( DEBUG_POOL,
+ "0x%08x: Free pSocket, %d bytes\r\n",
+ pSocket,
+ sizeof ( *pSocket )));
+ errno = 0;
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL,
+ "ERROR - Failed to free pSocket 0x%08x, Status: %r\r\n",
+ pSocket,
+ Status ));
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INFO,
+ "ERROR - Failed to remove gEfiSocketProtocolGuid from 0x%08x, Status: %r\r\n",
+ ChildHandle,
+ Status ));
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_INFO,
+ "ERROR - The socket was not in the socket list!\r\n" ));
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR,
+ "ERROR - Invalid parameter pSocketProtocol is NULL\r\n" ));
+ }
+
+ //
+ // Return the errno value if possible
+ //
+ if ( NULL != pErrno ) {
+ *pErrno = errno;
+ }
+
+ //
+ // Return the operation status
+ //
+ DBG_EXIT_STATUS ( Status );
+ return Status;
+}
+
+
+/**
Get the local address.
This routine calls the network specific layer to get the network
diff --git a/StdLib/EfiSocketLib/Socket.h b/StdLib/EfiSocketLib/Socket.h
index f2fbdb57b..43a7084f9 100644
--- a/StdLib/EfiSocketLib/Socket.h
+++ b/StdLib/EfiSocketLib/Socket.h
@@ -1188,6 +1188,28 @@ EslSocketCopyFragmentedBuffer (
);
/**
+ Free the socket.
+
+ This routine frees the socket structure and handle resources.
+
+ The ::close routine calls EslServiceFreeProtocol which then calls
+ this routine to free the socket context structure and close the
+ handle.
+
+ @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL structure.
+
+ @param [out] pErrno Address to receive the errno value upon completion.
+
+ @retval EFI_SUCCESS The socket resources were returned successfully.
+
+ **/
+EFI_STATUS
+EslSocketFree (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol,
+ IN int * pErrno
+ );
+
+/**
Free the ESL_IO_MGMT event and structure
This support routine walks the free list to close the event in
diff --git a/StdLib/EfiSocketLib/UseEfiSocketLib.c b/StdLib/EfiSocketLib/UseEfiSocketLib.c
index e44a72043..060598af3 100644
--- a/StdLib/EfiSocketLib/UseEfiSocketLib.c
+++ b/StdLib/EfiSocketLib/UseEfiSocketLib.c
@@ -69,6 +69,40 @@ CONST EFI_GUID mEslUdp6ServiceGuid __attribute__((weak)) = {
/**
+ Free the socket resources
+
+ This releases the socket resources allocated by calling
+ EslServiceGetProtocol.
+
+ This routine is called from the ::close routine in BsdSocketLib
+ to release the socket resources.
+
+ @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL
+ structure
+
+ @return Value for ::errno, zero (0) indicates success.
+
+ **/
+int
+EslServiceFreeProtocol (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol
+ )
+{
+ int RetVal;
+
+ //
+ // Release the socket resources
+ //
+ EslSocketFree ( pSocketProtocol, &RetVal );
+
+ //
+ // Return the operation status
+ //
+ return RetVal;
+}
+
+
+/**
Connect to the EFI socket library
This routine creates the ::ESL_SOCKET structure and returns
diff --git a/StdLib/Include/Protocol/EfiSocket.h b/StdLib/Include/Protocol/EfiSocket.h
index 2664f01bd..022a6a5f2 100644
--- a/StdLib/Include/Protocol/EfiSocket.h
+++ b/StdLib/Include/Protocol/EfiSocket.h
@@ -613,6 +613,26 @@ AcceptNB (
);
/**
+ Free the socket resources
+
+ This releases the socket resources allocated by calling
+ EslServiceGetProtocol.
+
+ This routine is called from the ::close routine in BsdSocketLib
+ to release the socket resources.
+
+ @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL
+ structure
+
+ @return Value for ::errno, zero (0) indicates success.
+
+ **/
+int
+EslServiceFreeProtocol (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol
+ );
+
+/**
Connect to the EFI socket library
@param [in] ppSocketProtocol Address to receive the socket protocol address
diff --git a/StdLib/UseSocketDxe/UseSocketDxe.c b/StdLib/UseSocketDxe/UseSocketDxe.c
index 607414326..423419c23 100644
--- a/StdLib/UseSocketDxe/UseSocketDxe.c
+++ b/StdLib/UseSocketDxe/UseSocketDxe.c
@@ -23,6 +23,59 @@
/**
+ Free the socket resources
+
+ This releases the socket resources allocated by calling
+ EslServiceGetProtocol.
+
+ This routine is called from the ::close routine in BsdSocketLib
+ to release the socket resources.
+
+ @param [in] pSocketProtocol Address of an ::EFI_SOCKET_PROTOCOL
+ structure
+
+ @return Value for ::errno, zero (0) indicates success.
+
+ **/
+int
+EslServiceFreeProtocol (
+ IN EFI_SOCKET_PROTOCOL * pSocketProtocol
+ )
+{
+ EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
+ int RetVal;
+ EFI_STATUS Status;
+
+ //
+ // Assume success
+ //
+ RetVal = 0;
+
+ //
+ // Locate the socket protocol
+ //
+ Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid,
+ NULL,
+ (VOID **) &pServiceBinding );
+ if ( !EFI_ERROR ( Status )) {
+ //
+ // Release the handle
+ //
+ Status = pServiceBinding->DestroyChild ( pServiceBinding,
+ pSocketProtocol->SocketHandle );
+ }
+ if ( EFI_ERROR ( Status )) {
+ RetVal = EIO;
+ }
+
+ //
+ // Return the operation status
+ //
+ return RetVal;
+}
+
+
+/**
Connect to the EFI socket library
This routine establishes a connection to the socket driver