blob: edd991b407b8ddfe56c1ea0178835d6a898d66b7 [file] [log] [blame]
/** @file
Implement the entry and unload for 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 "Socket.h"
/**
The following GUID values are only used by the SocketDxe driver. An
alternative set of values exists in EfiSocketLib\UseEfiSocketLib.c
which an application uses when it links against EfiSocketLib. These
two sets of values allow the SocketDxe driver to coexist with socket
applications.
Tag GUID - IPv4 in use by SocketDxe
**/
CONST EFI_GUID mEslIp4ServiceGuid = {
0x4e3a82e6, 0xe43f, 0x460a, { 0x86, 0x6e, 0x9b, 0x5a, 0xab, 0x80, 0x44, 0x48 }
};
/**
Tag GUID - IPv6 in use by SocketDxe
**/
CONST EFI_GUID mEslIp6ServiceGuid = {
0x2fc3b2d3, 0x6eba, 0x42b0, { 0xa4, 0xa7, 0x14, 0xc7, 0xa8, 0x4b, 0x5d, 0x22 }
};
/**
Tag GUID - TCPv4 in use by SocketDxe
**/
CONST EFI_GUID mEslTcp4ServiceGuid = {
0x4dcaab0a, 0x1990, 0x4352, { 0x8d, 0x2f, 0x2d, 0x8f, 0x13, 0x55, 0x98, 0xa5 }
};
/**
Tag GUID - TCPv6 in use by SocketDxe
**/
CONST EFI_GUID mEslTcp6ServiceGuid = {
0xdd455a69, 0xec75, 0x456c, { 0x84, 0xd2, 0x95, 0xca, 0xe7, 0xd3, 0xc6, 0xd3 }
};
/**
Tag GUID - UDPv4 in use by SocketDxe
**/
CONST EFI_GUID mEslUdp4ServiceGuid = {
0x43a110ce, 0x9ccd, 0x402b, { 0x8c, 0x29, 0x4a, 0x6d, 0x8a, 0xf7, 0x79, 0x90 }
};
/**
Tag GUID - UDPv6 in use by SocketDxe
**/
CONST EFI_GUID mEslUdp6ServiceGuid = {
0x32ff59cd, 0xc33, 0x48d0, { 0xa2, 0x44, 0x4b, 0xb8, 0x11, 0x33, 0x64, 0x3 }
};
/**
Socket driver unload routine.
@param [in] ImageHandle Handle for the image.
@retval EFI_SUCCESS Image may be unloaded
**/
EFI_STATUS
EFIAPI
DriverUnload (
IN EFI_HANDLE ImageHandle
)
{
UINTN BufferSize;
UINTN Index;
UINTN Max;
EFI_HANDLE * pHandle;
EFI_STATUS Status;
//
// Determine which devices are using this driver
//
BufferSize = 0;
pHandle = NULL;
Status = gBS->LocateHandle (
ByProtocol,
&gEfiCallerIdGuid,
NULL,
&BufferSize,
NULL );
if ( EFI_BUFFER_TOO_SMALL == Status ) {
for ( ; ; ) {
//
// One or more block IO devices are present
//
Status = gBS->AllocatePool (
EfiRuntimeServicesData,
BufferSize,
(VOID **) &pHandle
);
if ( EFI_ERROR ( Status )) {
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Insufficient memory, failed handle buffer allocation\r\n" ));
break;
}
//
// Locate the block IO devices
//
Status = gBS->LocateHandle (
ByProtocol,
&gEfiCallerIdGuid,
NULL,
&BufferSize,
pHandle );
if ( EFI_ERROR ( Status )) {
//
// Error getting handles
//
DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,
"Failure getting Telnet handles\r\n" ));
break;
}
//
// Remove any use of the driver
//
Max = BufferSize / sizeof ( pHandle[ 0 ]);
for ( Index = 0; Max > Index; Index++ ) {
Status = DriverStop ( &mDriverBinding,
pHandle[ Index ],
0,
NULL );
if ( EFI_ERROR ( Status )) {
DEBUG (( DEBUG_WARN | DEBUG_INIT | DEBUG_INFO,
"WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ]));
break;
}
}
break;
}
}
else {
if ( EFI_NOT_FOUND == Status ) {
//
// No devices were found
//
Status = EFI_SUCCESS;
}
}
//
// Free the handle array
//
if ( NULL != pHandle ) {
gBS->FreePool ( pHandle );
}
//
// Done with the socket layer
//
if ( !EFI_ERROR ( Status )) {
Status = EslDxeUninstall ( ImageHandle );
if ( !EFI_ERROR ( Status )) {
//
// Remove the protocols installed by the EntryPoint routine.
//
Status = gBS->UninstallMultipleProtocolInterfaces (
ImageHandle,
&gEfiDriverBindingProtocolGuid,
&mDriverBinding,
&gEfiComponentNameProtocolGuid,
&mComponentName,
&gEfiComponentName2ProtocolGuid,
&mComponentName2,
NULL
);
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
ImageHandle ));
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n",
ImageHandle ));
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
ImageHandle ));
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
"ERROR - Failed to remove gEfiDriverBindingProtocolGuid from 0x%08x, Status: %r\r\n",
ImageHandle,
Status ));
}
}
}
//
// Disconnect the network services
//
if ( !EFI_ERROR ( Status )) {
EslServiceUnload ( );
}
//
// Return the unload status
//
return Status;
}
/**
Socket driver entry point.
@param [in] ImageHandle Handle for the image.
@param [in] pSystemTable Address of the system table.
@retval EFI_SUCCESS Image successfully loaded.
**/
EFI_STATUS
EFIAPI
EntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE * pSystemTable
)
{
EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage;
EFI_STATUS Status;
DBG_ENTER ( );
//
// Display the image handle
//
DEBUG (( DEBUG_INFO,
"ImageHandle: 0x%08x\r\n",
ImageHandle ));
//
// Enable unload support
//
Status = gBS->HandleProtocol (
gImageHandle,
&gEfiLoadedImageProtocolGuid,
(VOID **)&pLoadedImage
);
if (!EFI_ERROR (Status)) {
pLoadedImage->Unload = DriverUnload;
//
// Add the driver to the list of drivers
//
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
pSystemTable,
&mDriverBinding,
ImageHandle,
&mComponentName,
&mComponentName2
);
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Installed: gEfiDriverBindingProtocolGuid on 0x%08x\r\n",
ImageHandle ));
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Installed: gEfiComponentNameProtocolGuid on 0x%08x\r\n",
ImageHandle ));
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Installed: gEfiComponentName2ProtocolGuid on 0x%08x\r\n",
ImageHandle ));
//
// Initialize the service layer
//
EslServiceLoad ( ImageHandle );
//
// Make the socket serivces available to other drivers
// and applications
//
Status = EslDxeInstall ( &ImageHandle );
if ( EFI_ERROR ( Status )) {
//
// Disconnect from the network
//
EslServiceUnload ( );
//
// Remove the driver bindings
//
gBS->UninstallMultipleProtocolInterfaces (
ImageHandle,
&gEfiDriverBindingProtocolGuid,
&mDriverBinding,
&gEfiComponentNameProtocolGuid,
&mComponentName,
&gEfiComponentName2ProtocolGuid,
&mComponentName2,
NULL
);
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Removed: gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
ImageHandle ));
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Removed: gEfiComponentNameProtocolGuid from 0x%08x\r\n",
ImageHandle ));
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
"Removed: gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
ImageHandle ));
}
}
else {
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
"ERROR - EfiLibInstallDriverBindingComponentName2 failed, Status: %r\r\n",
Status ));
}
}
DBG_EXIT_STATUS ( Status );
return Status;
}
/**
Socket layer's service binding protocol delcaration.
**/
CONST EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding = {
EslDxeCreateChild,
EslDxeDestroyChild
};
/**
The following entries disable the constructor and destructor
for the SocketDxe driver. Note that socket applications linking
against EfiSocketLib use different redirection.
**/
PFN_ESL_xSTRUCTOR mpfnEslConstructor = NULL; ///< No EfiSocketLib constructor needed for SocketDxe
PFN_ESL_xSTRUCTOR mpfnEslDestructor = NULL; ///< No EfiSocketLib destructor needed for SocketDxe