/** @file | |
Implement the connection to the socket driver | |
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 <Uefi.h> | |
#include <Library/DebugLib.h> | |
#include <Library/UefiBootServicesTableLib.h> | |
#include <Library/UefiLib.h> | |
#include <Protocol/EfiSocket.h> | |
#include <Protocol/ServiceBinding.h> | |
/** | |
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 | |
and returns the API (::EFI_SOCKET_PROTOCOL address) to the | |
socket file system layer in BsdSocketLib. This routine looks for | |
the gEfiSocketServiceBindingProtocolGuid to locate the socket | |
driver. This routine then creates a child handle and locates | |
the gEfiSocketProtocolGuid protocol on that handle to get the | |
::EFI_SOCKET_PROTOCOL structure address. | |
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 UseSocketDxe. | |
@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_SERVICE_BINDING_PROTOCOL * pServiceBinding; | |
int RetVal; | |
EFI_HANDLE SocketHandle; | |
EFI_STATUS Status; | |
// | |
// Locate the socket protocol | |
// | |
Status = gBS->LocateProtocol ( &gEfiSocketServiceBindingProtocolGuid, | |
NULL, | |
(VOID **)&pServiceBinding ); | |
if ( !EFI_ERROR ( Status )) { | |
// | |
// Create a new socket | |
// | |
SocketHandle = NULL; | |
Status = pServiceBinding->CreateChild ( pServiceBinding, | |
&SocketHandle ); | |
if ( !EFI_ERROR ( Status )) { | |
// | |
// Get the socket protocol | |
// | |
Status = gBS->OpenProtocol ( SocketHandle, | |
&gEfiSocketProtocolGuid, | |
(VOID **)ppSocketProtocol, | |
NULL, | |
NULL, | |
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL ); | |
if ( !EFI_ERROR ( Status )) { | |
// | |
// Success! | |
// | |
RetVal = 0; | |
} | |
else { | |
DEBUG (( DEBUG_ERROR, | |
"ERROR - No socket protocol on 0x%08x, Status: %r\r\n", | |
SocketHandle, | |
Status )); | |
RetVal = ENODEV; | |
} | |
} | |
else { | |
// | |
// Translate the error | |
// | |
DEBUG (( DEBUG_ERROR, | |
"ERROR - CreateChild failed, Status: %r\r\n", | |
Status )); | |
switch ( Status ) { | |
case EFI_SUCCESS: | |
RetVal = 0; | |
break; | |
case EFI_ACCESS_DENIED: | |
case EFI_WRITE_PROTECTED: | |
RetVal = EACCES; | |
break; | |
case EFI_NO_RESPONSE: | |
RetVal = EHOSTUNREACH; | |
break; | |
case EFI_BAD_BUFFER_SIZE: | |
case EFI_BUFFER_TOO_SMALL: | |
case EFI_INVALID_PARAMETER: | |
RetVal = EINVAL; | |
break; | |
case EFI_DEVICE_ERROR: | |
case EFI_MEDIA_CHANGED: | |
case EFI_NO_MEDIA: | |
case EFI_VOLUME_CORRUPTED: | |
RetVal = EIO; | |
break; | |
case EFI_NOT_FOUND: | |
RetVal = ENOENT; | |
break; | |
default: | |
case EFI_OUT_OF_RESOURCES: | |
RetVal = ENOMEM; | |
break; | |
case EFI_VOLUME_FULL: | |
RetVal = ENOSPC; | |
break; | |
case EFI_UNSUPPORTED: | |
RetVal = ENOSYS; | |
break; | |
case EFI_NO_MAPPING: | |
RetVal = ENXIO; | |
break; | |
case EFI_LOAD_ERROR: | |
RetVal = ESRCH; | |
break; | |
case EFI_TIMEOUT: | |
RetVal = ETIMEDOUT; | |
break; | |
case EFI_NOT_READY: | |
RetVal = EWOULDBLOCK; | |
break; | |
} | |
} | |
} | |
else { | |
DEBUG (( DEBUG_ERROR, | |
"ERROR - Socket driver not loaded, Status: %r\r\n", | |
Status )); | |
RetVal = ENODEV; | |
} | |
// | |
// Return the operation status | |
// | |
return RetVal; | |
} |