| /** @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 |