Signed-off-by: lpleahy git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13802 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			377 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			377 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Implement the connection to the EFI socket library
 | |
| 
 | |
|   Copyright (c) 2011, Intel Corporation
 | |
|   All rights reserved. This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Socket.h"
 | |
| 
 | |
| 
 | |
| /**
 | |
|   The following GUID values are only used when an application links
 | |
|   against EfiSocketLib.  An alternative set of values exists in
 | |
|   SocketDxe\EntryUnload.c which the SocketDxe driver uses to coexist
 | |
|   with socket applications.
 | |
|   
 | |
|   Tag GUID - IPv4 in use by an application using EfiSocketLib
 | |
| **/
 | |
| CONST EFI_GUID mEslIp4ServiceGuid __attribute__((weak)) = {
 | |
|   0x9c756011, 0x5d44, 0x4ee0, { 0xbc, 0xe7, 0xc3, 0x82, 0x18, 0xfe, 0x39, 0x8d }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Tag GUID - IPv6 in use by an application using EfiSocketLib
 | |
| **/
 | |
| CONST EFI_GUID mEslIp6ServiceGuid __attribute__((weak)) = {
 | |
|   0xc51b2761, 0xc476, 0x45fe, { 0xbe, 0x61, 0xba, 0x4b, 0xcc, 0x32, 0xf2, 0x34 }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Tag GUID - TCPv4 in use by an application using EfiSocketLib
 | |
| **/
 | |
| CONST EFI_GUID mEslTcp4ServiceGuid __attribute__((weak)) = {
 | |
|   0xffc659c2, 0x4ef2, 0x4532, { 0xb8, 0x75, 0xcd, 0x9a, 0xa4, 0x27, 0x4c, 0xde }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Tag GUID - TCPv6 in use by an application using EfiSocketLib
 | |
| **/
 | |
| CONST EFI_GUID mEslTcp6ServiceGuid __attribute__((weak)) = {
 | |
|   0x279858a4, 0x4e9e, 0x4e53, { 0x93, 0x22, 0xf2, 0x54, 0xe0, 0x7e, 0xef, 0xd4 }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Tag GUID - UDPv4 in use by an application using EfiSocketLib
 | |
| **/
 | |
| CONST EFI_GUID mEslUdp4ServiceGuid __attribute__((weak)) = {
 | |
|   0x44e03a55, 0x8d97, 0x4511, { 0xbf, 0xef, 0xa, 0x8b, 0xc6, 0x2c, 0x25, 0xae }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Tag GUID - UDPv6 in use by an application using EfiSocketLib
 | |
| **/
 | |
| CONST EFI_GUID mEslUdp6ServiceGuid __attribute__((weak)) = {
 | |
|   0xaa4af677, 0x6efe, 0x477c, { 0x96, 0x68, 0xe8, 0x13, 0x9d, 0x2, 0xfd, 0x9b }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   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
 | |
|   the API (::EFI_SOCKET_PROTOCOL address) to the socket file
 | |
|   system layer in BsdSocketLib.
 | |
| 
 | |
|   This routine is called from the ::socket routine in BsdSocketLib
 | |
|   to create the data structure and initialize the API for a socket.
 | |
|   Note that this implementation is only used by socket applications
 | |
|   that link directly to EslSocketLib.
 | |
| 
 | |
|   @param [in] ppSocketProtocol  Address to receive the ::EFI_SOCKET_PROTOCOL
 | |
|                                 structure address
 | |
| 
 | |
|   @return       Value for ::errno, zero (0) indicates success.
 | |
| 
 | |
|  **/
 | |
| int
 | |
| EslServiceGetProtocol (
 | |
|   IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol
 | |
|   )
 | |
| {
 | |
|   EFI_HANDLE ChildHandle;
 | |
|   ESL_SOCKET * pSocket;
 | |
|   int RetVal;
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   DBG_ENTER ( );
 | |
| 
 | |
|   //
 | |
|   //  Assume success
 | |
|   //
 | |
|   RetVal = 0;
 | |
| 
 | |
|   //
 | |
|   //  Locate the socket protocol
 | |
|   //
 | |
|   ChildHandle = NULL;
 | |
|   Status = EslSocketAllocate ( &ChildHandle,
 | |
|                                DEBUG_SOCKET,
 | |
|                                &pSocket );
 | |
|   if ( !EFI_ERROR ( Status )) {
 | |
|     *ppSocketProtocol = &pSocket->SocketProtocol;
 | |
|   }
 | |
|   else {
 | |
|     //
 | |
|     //  No resources
 | |
|     //
 | |
|     RetVal = ENOMEM;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the operation status
 | |
|   //
 | |
|   DBG_EXIT_DEC ( RetVal );
 | |
|   return RetVal;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Connect to the network layer
 | |
| 
 | |
|   This routine is the constructor for the EfiSocketLib when the
 | |
|   library is linked directly to an application.  This routine
 | |
|   walks the ::cEslSocketBinding table to create ::ESL_SERVICE
 | |
|   structures, associated with the network adapters, which this
 | |
|   routine links to the ::ESL_LAYER structure.
 | |
| 
 | |
|   This routine is called from ::EslConstructor as a result of the
 | |
|   constructor redirection in ::mpfnEslConstructor at the end of this
 | |
|   file.
 | |
| 
 | |
|   @retval EFI_SUCCESS   Successfully connected to the network layer
 | |
| 
 | |
|  **/
 | |
| EFI_STATUS
 | |
| EslServiceNetworkConnect (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   BOOLEAN bSomethingFound;
 | |
|   UINTN HandleCount;
 | |
|   UINTN Index;
 | |
|   CONST ESL_SOCKET_BINDING * pEnd;
 | |
|   EFI_HANDLE * pHandles;
 | |
|   CONST ESL_SOCKET_BINDING * pSocketBinding;
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   DBG_ENTER ( );
 | |
| 
 | |
|   //
 | |
|   //  Initialize the socket layer
 | |
|   //
 | |
|   Status = EFI_SUCCESS;
 | |
|   bSomethingFound = FALSE;
 | |
|   EslServiceLoad ( gImageHandle );
 | |
| 
 | |
|   //
 | |
|   //  Connect the network devices
 | |
|   //
 | |
|   pSocketBinding = &cEslSocketBinding[0];
 | |
|   pEnd = &pSocketBinding[ cEslSocketBindingEntries ];
 | |
|   while ( pEnd > pSocketBinding ) {
 | |
|     //
 | |
|     //  Attempt to locate the network adapters
 | |
|     //
 | |
|     HandleCount = 0;
 | |
|     pHandles = NULL;
 | |
|     Status = gBS->LocateHandleBuffer ( ByProtocol,
 | |
|                                        pSocketBinding->pNetworkBinding,
 | |
|                                        NULL,
 | |
|                                        &HandleCount,
 | |
|                                        &pHandles );
 | |
|     if ( EFI_ERROR ( Status )) {
 | |
|       DEBUG (( DEBUG_ERROR,
 | |
|                "ERROR with %s layer, Status: %r\r\n",
 | |
|                pSocketBinding->pName,
 | |
|                Status ));
 | |
|     }
 | |
|     else {
 | |
|       if ( NULL != pHandles ) {
 | |
|         //
 | |
|         //  Attempt to connect to this network adapter
 | |
|         //
 | |
|         for ( Index = 0; HandleCount > Index; Index++ ) {
 | |
|           Status = EslServiceConnect ( gImageHandle,
 | |
|                                        pHandles[ Index ]);
 | |
|           if ( !EFI_ERROR ( Status )) {
 | |
|             bSomethingFound = TRUE;
 | |
|           }
 | |
|           else {
 | |
|             if ( EFI_OUT_OF_RESOURCES == Status ) {
 | |
|               //
 | |
|               //  Pointless to continue without memory
 | |
|               //
 | |
|               break;
 | |
|             }
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         //  Done with the handles
 | |
|         //
 | |
|         gBS->FreePool ( pHandles );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     //  Set the next network protocol
 | |
|     //
 | |
|     pSocketBinding += 1;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the network connection status
 | |
|   //
 | |
|   if ( bSomethingFound ) {
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
|   DBG_EXIT_STATUS ( Status );
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Disconnect from the network layer
 | |
| 
 | |
|   Destructor for the EfiSocketLib when the library is linked
 | |
|   directly to an application.  This routine walks the
 | |
|   ::cEslSocketBinding table to remove the ::ESL_SERVICE
 | |
|   structures (network connections) from the ::ESL_LAYER structure.
 | |
| 
 | |
|   This routine is called from ::EslDestructor as a result of the
 | |
|   destructor redirection in ::mpfnEslDestructor at the end of this
 | |
|   file.
 | |
| 
 | |
|   @retval EFI_SUCCESS   Successfully disconnected from the network layer
 | |
| 
 | |
|  **/
 | |
| EFI_STATUS
 | |
| EslServiceNetworkDisconnect (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   UINTN HandleCount;
 | |
|   UINTN Index;
 | |
|   CONST ESL_SOCKET_BINDING * pEnd;
 | |
|   EFI_HANDLE * pHandles;
 | |
|   CONST ESL_SOCKET_BINDING * pSocketBinding;
 | |
|   EFI_STATUS Status;
 | |
| 
 | |
|   DBG_ENTER ( );
 | |
| 
 | |
|   //
 | |
|   //  Assume success
 | |
|   //
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   //  Disconnect the network devices
 | |
|   //
 | |
|   pSocketBinding = &cEslSocketBinding[0];
 | |
|   pEnd = &pSocketBinding[ cEslSocketBindingEntries ];
 | |
|   while ( pEnd > pSocketBinding ) {
 | |
|     //
 | |
|     //  Attempt to locate the network adapters
 | |
|     //
 | |
|     HandleCount = 0;
 | |
|     pHandles = NULL;
 | |
|     Status = gBS->LocateHandleBuffer ( ByProtocol,
 | |
|                                        pSocketBinding->pNetworkBinding,
 | |
|                                        NULL,
 | |
|                                        &HandleCount,
 | |
|                                        &pHandles );
 | |
|     if (( !EFI_ERROR ( Status ))
 | |
|       && ( NULL != pHandles )) {
 | |
|       //
 | |
|       //  Attempt to disconnect from this network adapter
 | |
|       //
 | |
|       for ( Index = 0; HandleCount > Index; Index++ ) {
 | |
|         Status = EslServiceDisconnect ( gImageHandle,
 | |
|                                         pHandles[ Index ]);
 | |
|         if ( EFI_ERROR ( Status )) {
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       //  Done with the handles
 | |
|       //
 | |
|       gBS->FreePool ( pHandles );
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     //  Set the next network protocol
 | |
|     //
 | |
|     pSocketBinding += 1;
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Finish the disconnect operation
 | |
|   //
 | |
|   if ( !EFI_ERROR ( Status )) {
 | |
|     EslServiceUnload ( );
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Return the network connection status
 | |
|   //
 | |
|   DBG_EXIT_STATUS ( Status );
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Socket layer's service binding protocol delcaration.
 | |
| **/
 | |
| CONST EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding __attribute__((weak)) = {
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   The following entries redirect the constructor and destructor
 | |
|   for any socket application that links against the EfiSocketLib.
 | |
|   Note that the SocketDxe driver uses different redirection.
 | |
| **/
 | |
| PFN_ESL_xSTRUCTOR mpfnEslConstructor __attribute__((weak)) = EslServiceNetworkConnect;    ///<  Constructor for EfiSocketLib
 | |
| PFN_ESL_xSTRUCTOR mpfnEslDestructor __attribute__((weak)) = EslServiceNetworkDisconnect;  ///<  Destructor for EfiSocketLib
 |