mirror of https://github.com/acidanthera/audk.git
530 lines
15 KiB
C
530 lines
15 KiB
C
/** @file
|
|
Connect to and disconnect from the various network layers
|
|
|
|
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"
|
|
|
|
EFI_TCP4_PROTOCOL * mpEfiTcpClose4 [ 1024 ];
|
|
|
|
|
|
/**
|
|
Connect to the network service bindings
|
|
|
|
Walk the network service protocols on the controller handle and
|
|
locate any that are not in use. Create service structures to
|
|
manage the service binding for the socket driver.
|
|
|
|
@param [in] BindingHandle Handle for protocol binding.
|
|
@param [in] Controller Handle of device to work with.
|
|
|
|
@retval EFI_SUCCESS This driver is added to Controller.
|
|
@retval other This driver does not support this device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EslServiceConnect (
|
|
IN EFI_HANDLE BindingHandle,
|
|
IN EFI_HANDLE Controller
|
|
)
|
|
{
|
|
BOOLEAN bInUse;
|
|
UINTN LengthInBytes;
|
|
CONST DT_SOCKET_BINDING * pEnd;
|
|
VOID * pJunk;
|
|
VOID * pInterface;
|
|
DT_SERVICE * pService;
|
|
CONST DT_SOCKET_BINDING * pSocketBinding;
|
|
EFI_STATUS Status;
|
|
EFI_TPL TplPrevious;
|
|
|
|
DBG_ENTER ( );
|
|
|
|
//
|
|
// Assume the list is empty
|
|
//
|
|
Status = EFI_UNSUPPORTED;
|
|
bInUse = FALSE;
|
|
|
|
//
|
|
// Walk the list of network connection points
|
|
//
|
|
pSocketBinding = &cEslSocketBinding[0];
|
|
pEnd = &pSocketBinding[ cEslSocketBindingEntries ];
|
|
while ( pEnd > pSocketBinding ) {
|
|
//
|
|
// Determine if the controller supports the network protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
pSocketBinding->pNetworkBinding,
|
|
&pInterface,
|
|
BindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if ( !EFI_ERROR ( Status )) {
|
|
//
|
|
// Determine if the socket layer is already connected
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
(EFI_GUID *)pSocketBinding->pTagGuid,
|
|
&pJunk,
|
|
BindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if ( EFI_UNSUPPORTED == Status ) {
|
|
//
|
|
// Allocate a service structure since the tag is not present
|
|
//
|
|
LengthInBytes = sizeof ( *pService );
|
|
Status = gBS->AllocatePool (
|
|
EfiRuntimeServicesData,
|
|
LengthInBytes,
|
|
(VOID **) &pService
|
|
);
|
|
if ( !EFI_ERROR ( Status )) {
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT,
|
|
"0x%08x: Allocate pService, %d bytes\r\n",
|
|
pService,
|
|
LengthInBytes ));
|
|
|
|
//
|
|
// Set the structure signature and service binding
|
|
//
|
|
ZeroMem ( pService, LengthInBytes );
|
|
pService->Signature = SERVICE_SIGNATURE;
|
|
pService->pSocketBinding = pSocketBinding;
|
|
pService->Controller = Controller;
|
|
pService->pInterface = pInterface;
|
|
|
|
//
|
|
// Mark the controller in use
|
|
//
|
|
if ( !bInUse ) {
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Controller,
|
|
&gEfiCallerIdGuid,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if ( !EFI_ERROR ( Status )) {
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
|
|
"Installed: gEfiCallerIdGuid on 0x%08x\r\n",
|
|
Controller ));
|
|
bInUse = TRUE;
|
|
}
|
|
else {
|
|
if ( EFI_INVALID_PARAMETER == Status ) {
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
if ( !EFI_ERROR ( Status )) {
|
|
//
|
|
// Mark the network service protocol in use
|
|
//
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&Controller,
|
|
pSocketBinding->pTagGuid,
|
|
pService,
|
|
NULL
|
|
);
|
|
if ( !EFI_ERROR ( Status )) {
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
|
|
"Installed: %s TagGuid on 0x%08x\r\n",
|
|
pSocketBinding->pName,
|
|
Controller ));
|
|
|
|
//
|
|
// Synchronize with the socket layer
|
|
//
|
|
RAISE_TPL ( TplPrevious, TPL_SOCKETS );
|
|
|
|
//
|
|
// Initialize the service
|
|
//
|
|
Status = pSocketBinding->pfnInitialize ( pService );
|
|
|
|
//
|
|
// Release the socket layer synchronization
|
|
//
|
|
RESTORE_TPL ( TplPrevious );
|
|
|
|
//
|
|
// Determine if the initialization was successful
|
|
//
|
|
if ( EFI_ERROR ( Status )) {
|
|
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
|
|
"ERROR - Failed to initialize service %s on 0x%08x, Status: %r\r\n",
|
|
pSocketBinding->pName,
|
|
Controller,
|
|
Status ));
|
|
|
|
//
|
|
// Free the network service binding if necessary
|
|
//
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Controller,
|
|
pSocketBinding->pTagGuid,
|
|
pService,
|
|
NULL );
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
|
|
"Removed: %s TagGuid from 0x%08x\r\n",
|
|
pSocketBinding->pName,
|
|
Controller ));
|
|
}
|
|
}
|
|
else {
|
|
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
|
|
"ERROR - Failed to install %s TagGuid on 0x%08x, Status: %r\r\n",
|
|
pSocketBinding->pName,
|
|
Controller,
|
|
Status ));
|
|
}
|
|
|
|
if ( EFI_ERROR ( Status )) {
|
|
//
|
|
// The controller is no longer in use
|
|
//
|
|
if ( bInUse ) {
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Controller,
|
|
&gEfiCallerIdGuid,
|
|
NULL,
|
|
NULL );
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
|
|
"Removed: gEfiCallerIdGuid from 0x%08x\r\n",
|
|
Controller ));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
DEBUG (( DEBUG_ERROR | DEBUG_INIT,
|
|
"ERROR - Failed to install gEfiCallerIdGuid on 0x%08x, Status: %r\r\n",
|
|
Controller,
|
|
Status ));
|
|
}
|
|
|
|
//
|
|
// Release the service if necessary
|
|
//
|
|
if ( EFI_ERROR ( Status )) {
|
|
gBS->FreePool ( pService );
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT,
|
|
"0x%08x: Free pService, %d bytes\r\n",
|
|
pService,
|
|
sizeof ( *pService )));
|
|
pService = NULL;
|
|
}
|
|
}
|
|
else {
|
|
DEBUG (( DEBUG_ERROR | DEBUG_INIT,
|
|
"ERROR - Failed service allocation, Status: %r\r\n",
|
|
Status ));
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the next network protocol
|
|
//
|
|
pSocketBinding += 1;
|
|
}
|
|
|
|
//
|
|
// Display the driver start status
|
|
//
|
|
DBG_EXIT_STATUS ( Status );
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Shutdown the network connections to this controller by removing
|
|
NetworkInterfaceIdentifier protocol and closing the DevicePath
|
|
and PciIo protocols on Controller.
|
|
|
|
@param [in] BindingHandle Handle for protocol binding.
|
|
@param [in] Controller Handle of device to stop driver on.
|
|
|
|
@retval EFI_SUCCESS This driver is removed Controller.
|
|
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
|
@retval other This driver was not removed from this device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EslServiceDisconnect (
|
|
IN EFI_HANDLE BindingHandle,
|
|
IN EFI_HANDLE Controller
|
|
)
|
|
{
|
|
CONST DT_SOCKET_BINDING * pEnd;
|
|
DT_SERVICE * pService;
|
|
CONST DT_SOCKET_BINDING * pSocketBinding;
|
|
EFI_STATUS Status;
|
|
EFI_TPL TplPrevious;
|
|
|
|
DBG_ENTER ( );
|
|
|
|
//
|
|
// Walk the list of network connection points in reverse order
|
|
//
|
|
pEnd = &cEslSocketBinding[0];
|
|
pSocketBinding = &pEnd[ cEslSocketBindingEntries ];
|
|
while ( pEnd < pSocketBinding ) {
|
|
//
|
|
// Set the next network protocol
|
|
//
|
|
pSocketBinding -= 1;
|
|
|
|
//
|
|
// Determine if the driver connected
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
(EFI_GUID *)pSocketBinding->pTagGuid,
|
|
(VOID **)&pService,
|
|
BindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if ( !EFI_ERROR ( Status )) {
|
|
|
|
//
|
|
// Synchronize with the socket layer
|
|
//
|
|
RAISE_TPL ( TplPrevious, TPL_SOCKETS );
|
|
|
|
//
|
|
// Shutdown the service
|
|
//
|
|
pSocketBinding->pfnShutdown ( pService );
|
|
|
|
//
|
|
// Release the socket layer synchronization
|
|
//
|
|
RESTORE_TPL ( TplPrevious );
|
|
|
|
//
|
|
// Break the driver connection
|
|
//
|
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
|
Controller,
|
|
pSocketBinding->pTagGuid,
|
|
pService,
|
|
NULL );
|
|
if ( !EFI_ERROR ( Status )) {
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT,
|
|
"Removed: %s TagGuid from 0x%08x\r\n",
|
|
pSocketBinding->pName,
|
|
Controller ));
|
|
}
|
|
else {
|
|
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
|
|
"ERROR - Failed to removed %s TagGuid from 0x%08x, Status: %r\r\n",
|
|
pSocketBinding->pName,
|
|
Controller,
|
|
Status ));
|
|
}
|
|
|
|
//
|
|
// Free the service structure
|
|
//
|
|
Status = gBS->FreePool ( pService );
|
|
if ( !EFI_ERROR ( Status )) {
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT,
|
|
"0x%08x: Free pService, %d bytes\r\n",
|
|
pService,
|
|
sizeof ( *pService )));
|
|
}
|
|
else {
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT,
|
|
"ERROR - Failed to free pService 0x%08x, Status: %r\r\n",
|
|
pService,
|
|
Status ));
|
|
}
|
|
pService = NULL;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The controller is no longer in use
|
|
//
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Controller,
|
|
&gEfiCallerIdGuid,
|
|
NULL,
|
|
NULL );
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
|
|
"Removed: gEfiCallerIdGuid from 0x%08x\r\n",
|
|
Controller ));
|
|
|
|
//
|
|
// The driver is disconnected from the network controller
|
|
//
|
|
Status = EFI_SUCCESS;
|
|
|
|
//
|
|
// Display the driver start status
|
|
//
|
|
DBG_EXIT_STATUS ( Status );
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
Install the socket service
|
|
|
|
@param [in] pImageHandle Address of the image handle
|
|
|
|
@retval EFI_SUCCESS Service installed successfully
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EslServiceInstall (
|
|
IN EFI_HANDLE * pImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Install the socket service binding protocol
|
|
//
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
pImageHandle,
|
|
&gEfiSocketServiceBindingProtocolGuid,
|
|
&mEslLayer.ServiceBinding,
|
|
NULL
|
|
);
|
|
if ( !EFI_ERROR ( Status )) {
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
|
|
"Installed: gEfiSocketServiceBindingProtocolGuid on 0x%08x\r\n",
|
|
*pImageHandle ));
|
|
}
|
|
else {
|
|
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
|
|
"ERROR - InstallMultipleProtocolInterfaces failed, Status: %r\r\n",
|
|
Status ));
|
|
}
|
|
|
|
//
|
|
// Return the operation status
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Initialize the service layer
|
|
|
|
@param [in] ImageHandle Handle for the image.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EslServiceLoad (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
{
|
|
DT_LAYER * pLayer;
|
|
|
|
//
|
|
// Save the image handle
|
|
//
|
|
pLayer = &mEslLayer;
|
|
pLayer->Signature = LAYER_SIGNATURE;
|
|
pLayer->ImageHandle = ImageHandle;
|
|
|
|
//
|
|
// Initialize the TCP4 close
|
|
//
|
|
pLayer->TcpCloseMax4 = DIM ( mpEfiTcpClose4 );
|
|
pLayer->ppTcpClose4 = mpEfiTcpClose4;
|
|
|
|
//
|
|
// Connect the service binding protocol to the image handle
|
|
//
|
|
pLayer->ServiceBinding.CreateChild = EslSocketCreateChild;
|
|
pLayer->ServiceBinding.DestroyChild = EslSocketDestroyChild;
|
|
}
|
|
|
|
|
|
/**
|
|
Uninstall the socket service
|
|
|
|
@param [in] ImageHandle Handle for the image.
|
|
|
|
@retval EFI_SUCCESS Service installed successfully
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EslServiceUninstall (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Install the socket service binding protocol
|
|
//
|
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
|
ImageHandle,
|
|
&gEfiSocketServiceBindingProtocolGuid,
|
|
&mEslLayer.ServiceBinding,
|
|
NULL
|
|
);
|
|
if ( !EFI_ERROR ( Status )) {
|
|
DEBUG (( DEBUG_POOL | DEBUG_INIT,
|
|
"Removed: gEfiSocketServiceBindingProtocolGuid from 0x%08x\r\n",
|
|
ImageHandle ));
|
|
}
|
|
else {
|
|
DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
|
|
"ERROR - Failed to remove gEfiSocketServiceBindingProtocolGuid from 0x%08x, Status: %r\r\n",
|
|
ImageHandle,
|
|
Status ));
|
|
}
|
|
|
|
//
|
|
// Return the operation status
|
|
//
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Shutdown the service layer
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
EslServiceUnload (
|
|
VOID
|
|
)
|
|
{
|
|
DT_LAYER * pLayer;
|
|
|
|
//
|
|
// Undo the work by ServiceLoad
|
|
//
|
|
pLayer = &mEslLayer;
|
|
pLayer->ImageHandle = NULL;
|
|
pLayer->ServiceBinding.CreateChild = NULL;
|
|
pLayer->ServiceBinding.DestroyChild = NULL;
|
|
}
|