mirror of https://github.com/acidanthera/audk.git
1533 lines
50 KiB
C
1533 lines
50 KiB
C
/** @file
|
|
The driver binding and service binding protocol for DnsDxe driver.
|
|
|
|
Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include "DnsImpl.h"
|
|
|
|
EFI_DRIVER_BINDING_PROTOCOL gDns4DriverBinding = {
|
|
Dns4DriverBindingSupported,
|
|
Dns4DriverBindingStart,
|
|
Dns4DriverBindingStop,
|
|
DNS_VERSION,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
EFI_DRIVER_BINDING_PROTOCOL gDns6DriverBinding = {
|
|
Dns6DriverBindingSupported,
|
|
Dns6DriverBindingStart,
|
|
Dns6DriverBindingStop,
|
|
DNS_VERSION,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
EFI_SERVICE_BINDING_PROTOCOL mDns4ServiceBinding = {
|
|
Dns4ServiceBindingCreateChild,
|
|
Dns4ServiceBindingDestroyChild
|
|
};
|
|
|
|
EFI_SERVICE_BINDING_PROTOCOL mDns6ServiceBinding = {
|
|
Dns6ServiceBindingCreateChild,
|
|
Dns6ServiceBindingDestroyChild
|
|
};
|
|
|
|
DNS_DRIVER_DATA *mDriverData = NULL;
|
|
|
|
/**
|
|
Destroy the DNS instance and recycle the resources.
|
|
|
|
@param[in] Instance The pointer to the DNS instance.
|
|
|
|
**/
|
|
VOID
|
|
DnsDestroyInstance (
|
|
IN DNS_INSTANCE *Instance
|
|
)
|
|
{
|
|
ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA));
|
|
|
|
ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA));
|
|
|
|
if (!NetMapIsEmpty (&Instance->Dns4TxTokens)) {
|
|
Dns4InstanceCancelToken (Instance, NULL);
|
|
}
|
|
|
|
if (!NetMapIsEmpty (&Instance->Dns6TxTokens)) {
|
|
Dns6InstanceCancelToken (Instance, NULL);
|
|
}
|
|
|
|
if (Instance->UdpIo!= NULL) {
|
|
UdpIoFreeIo (Instance->UdpIo);
|
|
}
|
|
|
|
FreePool (Instance);
|
|
}
|
|
|
|
/**
|
|
Create the DNS instance and initialize it.
|
|
|
|
@param[in] Service The pointer to the DNS service.
|
|
@param[out] Instance The pointer to the DNS instance.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
|
|
@retval EFI_SUCCESS The DNS instance is created.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DnsCreateInstance (
|
|
IN DNS_SERVICE *Service,
|
|
OUT DNS_INSTANCE **Instance
|
|
)
|
|
{
|
|
DNS_INSTANCE *DnsIns;
|
|
|
|
*Instance = NULL;
|
|
|
|
DnsIns = AllocateZeroPool (sizeof (DNS_INSTANCE));
|
|
if (DnsIns == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
DnsIns->Signature = DNS_INSTANCE_SIGNATURE;
|
|
InitializeListHead (&DnsIns->Link);
|
|
DnsIns->State = DNS_STATE_UNCONFIGED;
|
|
DnsIns->InDestroy = FALSE;
|
|
DnsIns->Service = Service;
|
|
|
|
if (Service->IpVersion == IP_VERSION_4) {
|
|
CopyMem (&DnsIns->Dns4, &mDns4Protocol, sizeof (DnsIns->Dns4));
|
|
NetMapInit (&DnsIns->Dns4TxTokens);
|
|
} else {
|
|
CopyMem (&DnsIns->Dns6, &mDns6Protocol, sizeof (DnsIns->Dns6));
|
|
NetMapInit (&DnsIns->Dns6TxTokens);
|
|
}
|
|
|
|
DnsIns->UdpIo = UdpIoCreateIo (
|
|
Service->ControllerHandle, /// NicHandle
|
|
Service->ImageHandle,
|
|
DnsConfigNullUdp,
|
|
Service->IpVersion,
|
|
DnsIns
|
|
);
|
|
if (DnsIns->UdpIo == NULL) {
|
|
FreePool (DnsIns);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
*Instance = DnsIns;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Callback function which provided by user to remove one node in NetDestroyLinkList process.
|
|
|
|
@param[in] Entry The entry to be removed.
|
|
@param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
|
|
|
|
@retval EFI_SUCCESS The entry has been removed successfully.
|
|
@retval Others Fail to remove the entry.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DnsDestroyChildEntryInHandleBuffer (
|
|
IN LIST_ENTRY *Entry,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
DNS_INSTANCE *Instance;
|
|
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
|
UINTN NumberOfChildren;
|
|
EFI_HANDLE *ChildHandleBuffer;
|
|
|
|
if (Entry == NULL || Context == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Instance = NET_LIST_USER_STRUCT_S (Entry, DNS_INSTANCE, Link, DNS_INSTANCE_SIGNATURE);
|
|
ServiceBinding = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
|
|
NumberOfChildren = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
|
|
ChildHandleBuffer = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
|
|
|
|
if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
|
|
}
|
|
|
|
/**
|
|
Config a NULL UDP that is used to keep the connection between UDP and DNS.
|
|
|
|
Just leave the Udp child unconfigured. When UDP is unloaded,
|
|
DNS will be informed with DriverBinding Stop.
|
|
|
|
@param UdpIo The UDP_IO to configure
|
|
@param Context The opaque parameter to the callback
|
|
|
|
@retval EFI_SUCCESS It always return EFI_SUCCESS directly.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DnsConfigNullUdp (
|
|
IN UDP_IO *UdpIo,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Release all the resource used the DNS service binding instance.
|
|
|
|
@param DnsSb The Dns service binding instance.
|
|
|
|
**/
|
|
VOID
|
|
DnsDestroyService (
|
|
IN DNS_SERVICE *DnsSb
|
|
)
|
|
{
|
|
UdpIoFreeIo (DnsSb->ConnectUdp);
|
|
|
|
if (DnsSb->TimerToGetMap != NULL){
|
|
gBS->CloseEvent (DnsSb->TimerToGetMap);
|
|
}
|
|
|
|
if (DnsSb->Timer != NULL){
|
|
gBS->CloseEvent (DnsSb->Timer);
|
|
}
|
|
|
|
FreePool (DnsSb);
|
|
}
|
|
|
|
/**
|
|
Create then initialize a Dns service binding instance.
|
|
|
|
@param Controller The controller to install the DNS service
|
|
binding on
|
|
@param Image The driver binding image of the DNS driver
|
|
@param IpVersion IpVersion for this service
|
|
@param Service The variable to receive the created service
|
|
binding instance.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
|
|
@retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
|
|
connection with UDP.
|
|
@retval EFI_SUCCESS The service instance is created for the
|
|
controller.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
DnsCreateService (
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_HANDLE Image,
|
|
IN UINT8 IpVersion,
|
|
OUT DNS_SERVICE **Service
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DNS_SERVICE *DnsSb;
|
|
|
|
Status = EFI_SUCCESS;
|
|
DnsSb = NULL;
|
|
|
|
*Service = NULL;
|
|
|
|
DnsSb = AllocateZeroPool (sizeof (DNS_SERVICE));
|
|
if (DnsSb == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
DnsSb->Signature = DNS_SERVICE_SIGNATURE;
|
|
|
|
if (IpVersion == IP_VERSION_4) {
|
|
DnsSb->ServiceBinding = mDns4ServiceBinding;
|
|
} else {
|
|
DnsSb->ServiceBinding = mDns6ServiceBinding;
|
|
}
|
|
|
|
DnsSb->Dns4ChildrenNum = 0;
|
|
InitializeListHead (&DnsSb->Dns4ChildrenList);
|
|
|
|
DnsSb->Dns6ChildrenNum = 0;
|
|
InitializeListHead (&DnsSb->Dns6ChildrenList);
|
|
|
|
DnsSb->ControllerHandle = Controller;
|
|
DnsSb->ImageHandle = Image;
|
|
|
|
DnsSb->TimerToGetMap = NULL;
|
|
|
|
DnsSb->Timer = NULL;
|
|
|
|
DnsSb->IpVersion = IpVersion;
|
|
|
|
//
|
|
// Create the timer used to time out the procedure which is used to
|
|
// get the default IP address.
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_TIMER,
|
|
TPL_CALLBACK,
|
|
NULL,
|
|
NULL,
|
|
&DnsSb->TimerToGetMap
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (DnsSb);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Create the timer to retransmit packets.
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
|
TPL_CALLBACK,
|
|
DnsOnTimerRetransmit,
|
|
DnsSb,
|
|
&DnsSb->Timer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
if (DnsSb->TimerToGetMap != NULL) {
|
|
gBS->CloseEvent (DnsSb->TimerToGetMap);
|
|
}
|
|
FreePool (DnsSb);
|
|
return Status;
|
|
}
|
|
|
|
DnsSb->ConnectUdp = NULL;
|
|
DnsSb->ConnectUdp = UdpIoCreateIo (
|
|
Controller,
|
|
Image,
|
|
DnsConfigNullUdp,
|
|
DnsSb->IpVersion,
|
|
NULL
|
|
);
|
|
if (DnsSb->ConnectUdp == NULL) {
|
|
if (DnsSb->TimerToGetMap != NULL) {
|
|
gBS->CloseEvent (DnsSb->TimerToGetMap);
|
|
}
|
|
gBS->CloseEvent (DnsSb->Timer);
|
|
FreePool (DnsSb);
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
*Service = DnsSb;
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Unloads an image.
|
|
|
|
@param ImageHandle Handle that identifies the image to be unloaded.
|
|
|
|
@retval EFI_SUCCESS The image has been unloaded.
|
|
@retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DnsUnload (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
LIST_ENTRY *Entry;
|
|
DNS4_CACHE *ItemCache4;
|
|
DNS4_SERVER_IP *ItemServerIp4;
|
|
DNS6_CACHE *ItemCache6;
|
|
DNS6_SERVER_IP *ItemServerIp6;
|
|
|
|
ItemCache4 = NULL;
|
|
ItemServerIp4 = NULL;
|
|
ItemCache6 = NULL;
|
|
ItemServerIp6 = NULL;
|
|
|
|
//
|
|
// Disconnect the driver specified by ImageHandle
|
|
//
|
|
Status = NetLibDefaultUnload(ImageHandle);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Free mDriverData.
|
|
//
|
|
if (mDriverData != NULL) {
|
|
if (mDriverData->Timer != NULL) {
|
|
gBS->CloseEvent (mDriverData->Timer);
|
|
}
|
|
|
|
while (!IsListEmpty (&mDriverData->Dns4CacheList)) {
|
|
Entry = NetListRemoveHead (&mDriverData->Dns4CacheList);
|
|
ASSERT (Entry != NULL);
|
|
ItemCache4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
|
|
FreePool (ItemCache4->DnsCache.HostName);
|
|
FreePool (ItemCache4->DnsCache.IpAddress);
|
|
FreePool (ItemCache4);
|
|
}
|
|
|
|
while (!IsListEmpty (&mDriverData->Dns4ServerList)) {
|
|
Entry = NetListRemoveHead (&mDriverData->Dns4ServerList);
|
|
ASSERT (Entry != NULL);
|
|
ItemServerIp4 = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
|
|
FreePool (ItemServerIp4);
|
|
}
|
|
|
|
while (!IsListEmpty (&mDriverData->Dns6CacheList)) {
|
|
Entry = NetListRemoveHead (&mDriverData->Dns6CacheList);
|
|
ASSERT (Entry != NULL);
|
|
ItemCache6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
|
|
FreePool (ItemCache6->DnsCache.HostName);
|
|
FreePool (ItemCache6->DnsCache.IpAddress);
|
|
FreePool (ItemCache6);
|
|
}
|
|
|
|
while (!IsListEmpty (&mDriverData->Dns6ServerList)) {
|
|
Entry = NetListRemoveHead (&mDriverData->Dns6ServerList);
|
|
ASSERT (Entry != NULL);
|
|
ItemServerIp6 = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
|
|
FreePool (ItemServerIp6);
|
|
}
|
|
|
|
FreePool (mDriverData);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
This is the declaration of an EFI image entry point. This entry point is
|
|
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
|
|
both device drivers and bus drivers.
|
|
|
|
@param ImageHandle The firmware allocated handle for the UEFI image.
|
|
@param SystemTable A pointer to the EFI System Table.
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval Others An unexpected error occurred.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DnsDriverEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = EFI_SUCCESS;
|
|
|
|
//
|
|
// Install the Dns4 Driver Binding Protocol.
|
|
//
|
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&gDns4DriverBinding,
|
|
ImageHandle,
|
|
&gDnsComponentName,
|
|
&gDnsComponentName2
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Install the Dns6 Driver Binding Protocol.
|
|
//
|
|
Status = EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&gDns6DriverBinding,
|
|
NULL,
|
|
&gDnsComponentName,
|
|
&gDnsComponentName2
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Error1;
|
|
}
|
|
|
|
//
|
|
// Create the driver data structures.
|
|
//
|
|
mDriverData = AllocateZeroPool (sizeof (DNS_DRIVER_DATA));
|
|
if (mDriverData == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto Error2;
|
|
}
|
|
|
|
//
|
|
// Create the timer event to update DNS cache list.
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
|
TPL_CALLBACK,
|
|
DnsOnTimerUpdate,
|
|
NULL,
|
|
&mDriverData->Timer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Error3;
|
|
}
|
|
|
|
Status = gBS->SetTimer (mDriverData->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
|
if (EFI_ERROR (Status)) {
|
|
goto Error4;
|
|
}
|
|
|
|
InitializeListHead (&mDriverData->Dns4CacheList);
|
|
InitializeListHead (&mDriverData->Dns4ServerList);
|
|
InitializeListHead (&mDriverData->Dns6CacheList);
|
|
InitializeListHead (&mDriverData->Dns6ServerList);
|
|
|
|
return Status;
|
|
|
|
Error4:
|
|
gBS->CloseEvent (mDriverData->Timer);
|
|
|
|
Error3:
|
|
FreePool (mDriverData);
|
|
|
|
Error2:
|
|
EfiLibUninstallDriverBindingComponentName2 (
|
|
&gDns6DriverBinding,
|
|
&gDnsComponentName,
|
|
&gDnsComponentName2
|
|
);
|
|
|
|
Error1:
|
|
EfiLibUninstallDriverBindingComponentName2 (
|
|
&gDns4DriverBinding,
|
|
&gDnsComponentName,
|
|
&gDnsComponentName2
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Tests to see if this driver supports a given controller. If a child device is provided,
|
|
it further tests to see if this driver supports creating a handle for the specified child device.
|
|
|
|
This function checks to see if the driver specified by This supports the device specified by
|
|
ControllerHandle. Drivers will typically use the device path attached to
|
|
ControllerHandle and/or the services from the bus I/O abstraction attached to
|
|
ControllerHandle to determine if the driver supports ControllerHandle. This function
|
|
may be called many times during platform initialization. In order to reduce boot times, the tests
|
|
performed by this function must be very small, and take as little time as possible to execute. This
|
|
function must not change the state of any hardware devices, and this function must be aware that the
|
|
device specified by ControllerHandle may already be managed by the same driver or a
|
|
different driver. This function must match its calls to AllocatePages() with FreePages(),
|
|
AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
|
|
Because ControllerHandle may have been previously started by the same driver, if a protocol is
|
|
already in the opened state, then it must not be closed with CloseProtocol(). This is required
|
|
to guarantee the state of ControllerHandle is not modified by this function.
|
|
|
|
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param[in] ControllerHandle The handle of the controller to test. This handle
|
|
must support a protocol interface that supplies
|
|
an I/O abstraction to the driver.
|
|
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
|
parameter is ignored by device drivers, and is optional for bus
|
|
drivers. For bus drivers, if this parameter is not NULL, then
|
|
the bus driver must determine if the bus controller specified
|
|
by ControllerHandle and the child controller specified
|
|
by RemainingDevicePath are both supported by this
|
|
bus driver.
|
|
|
|
@retval EFI_SUCCESS The device specified by ControllerHandle and
|
|
RemainingDevicePath is supported by the driver specified by This.
|
|
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
|
|
RemainingDevicePath is already being managed by the driver
|
|
specified by This.
|
|
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
|
|
RemainingDevicePath is already being managed by a different
|
|
driver or an application that requires exclusive access.
|
|
Currently not implemented.
|
|
@retval EFI_UNSUPPORTED The device specified by ControllerHandle and
|
|
RemainingDevicePath is not supported by the driver specified by This.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns4DriverBindingSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Test for the Dns4ServiceBinding Protocol.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiDns4ServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
//
|
|
// Test for the Udp4ServiceBinding Protocol.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiUdp4ServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Starts a device controller or a bus controller.
|
|
|
|
The Start() function is designed to be invoked from the EFI boot service ConnectController().
|
|
As a result, much of the error checking on the parameters to Start() has been moved into this
|
|
common boot service. It is legal to call Start() from other locations,
|
|
but the following calling restrictions must be followed, or the system behavior will not be deterministic.
|
|
1. ControllerHandle must be a valid EFI_HANDLE.
|
|
2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
|
|
EFI_DEVICE_PATH_PROTOCOL.
|
|
3. Prior to calling Start(), the Supported() function for the driver specified by This must
|
|
have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
|
|
|
|
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param[in] ControllerHandle The handle of the controller to start. This handle
|
|
must support a protocol interface that supplies
|
|
an I/O abstraction to the driver.
|
|
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
|
parameter is ignored by device drivers, and is optional for bus
|
|
drivers. For a bus driver, if this parameter is NULL, then handles
|
|
for all the children of Controller are created by this driver.
|
|
If this parameter is not NULL and the first Device Path Node is
|
|
not the End of Device Path Node, then only the handle for the
|
|
child device specified by the first Device Path Node of
|
|
RemainingDevicePath is created by this driver.
|
|
If the first Device Path Node of RemainingDevicePath is
|
|
the End of Device Path Node, no child handle is created by this
|
|
driver.
|
|
|
|
@retval EFI_SUCCESS The device was started.
|
|
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
|
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
|
@retval Others The driver failded to start the device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns4DriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
DNS_SERVICE *DnsSb;
|
|
EFI_STATUS Status;
|
|
|
|
Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4, &DnsSb);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
ASSERT (DnsSb != NULL);
|
|
|
|
Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Install the Dns4ServiceBinding Protocol onto ControllerHandle.
|
|
//
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&ControllerHandle,
|
|
&gEfiDns4ServiceBindingProtocolGuid,
|
|
&DnsSb->ServiceBinding,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
ON_ERROR:
|
|
DnsDestroyService (DnsSb);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Stops a device controller or a bus controller.
|
|
|
|
The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
|
|
As a result, much of the error checking on the parameters to Stop() has been moved
|
|
into this common boot service. It is legal to call Stop() from other locations,
|
|
but the following calling restrictions must be followed, or the system behavior will not be deterministic.
|
|
1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
|
|
same driver's Start() function.
|
|
2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
|
|
EFI_HANDLE. In addition, all of these handles must have been created in this driver's
|
|
Start() function, and the Start() function must have called OpenProtocol() on
|
|
ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
|
|
|
|
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param[in] ControllerHandle A handle to the device being stopped. The handle must
|
|
support a bus specific I/O protocol for the driver
|
|
to use to stop the device.
|
|
@param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
|
|
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
|
|
if NumberOfChildren is 0.
|
|
|
|
@retval EFI_SUCCESS The device was stopped.
|
|
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns4DriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
|
|
)
|
|
{
|
|
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
|
DNS_SERVICE *DnsSb;
|
|
EFI_HANDLE NicHandle;
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *List;
|
|
DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
|
|
|
|
//
|
|
// DNS driver opens UDP child, So, Controller is a UDP
|
|
// child handle. Locate the Nic handle first. Then get the
|
|
// DNS private data back.
|
|
//
|
|
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
|
|
|
|
if (NicHandle == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = gBS->OpenProtocol (
|
|
NicHandle,
|
|
&gEfiDns4ServiceBindingProtocolGuid,
|
|
(VOID **) &ServiceBinding,
|
|
This->DriverBindingHandle,
|
|
NicHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding);
|
|
|
|
if (!IsListEmpty (&DnsSb->Dns4ChildrenList)) {
|
|
//
|
|
// Destroy the Dns child instance in ChildHandleBuffer.
|
|
//
|
|
List = &DnsSb->Dns4ChildrenList;
|
|
Context.ServiceBinding = ServiceBinding;
|
|
Context.NumberOfChildren = NumberOfChildren;
|
|
Context.ChildHandleBuffer = ChildHandleBuffer;
|
|
Status = NetDestroyLinkList (
|
|
List,
|
|
DnsDestroyChildEntryInHandleBuffer,
|
|
&Context,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if (NumberOfChildren == 0 && IsListEmpty (&DnsSb->Dns4ChildrenList)) {
|
|
gBS->UninstallProtocolInterface (
|
|
NicHandle,
|
|
&gEfiDns4ServiceBindingProtocolGuid,
|
|
ServiceBinding
|
|
);
|
|
|
|
DnsDestroyService (DnsSb);
|
|
|
|
if (gDnsControllerNameTable != NULL) {
|
|
FreeUnicodeStringTable (gDnsControllerNameTable);
|
|
gDnsControllerNameTable = NULL;
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Tests to see if this driver supports a given controller. If a child device is provided,
|
|
it further tests to see if this driver supports creating a handle for the specified child device.
|
|
|
|
This function checks to see if the driver specified by This supports the device specified by
|
|
ControllerHandle. Drivers will typically use the device path attached to
|
|
ControllerHandle and/or the services from the bus I/O abstraction attached to
|
|
ControllerHandle to determine if the driver supports ControllerHandle. This function
|
|
may be called many times during platform initialization. In order to reduce boot times, the tests
|
|
performed by this function must be very small, and take as little time as possible to execute. This
|
|
function must not change the state of any hardware devices, and this function must be aware that the
|
|
device specified by ControllerHandle may already be managed by the same driver or a
|
|
different driver. This function must match its calls to AllocatePages() with FreePages(),
|
|
AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
|
|
Because ControllerHandle may have been previously started by the same driver, if a protocol is
|
|
already in the opened state, then it must not be closed with CloseProtocol(). This is required
|
|
to guarantee the state of ControllerHandle is not modified by this function.
|
|
|
|
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param[in] ControllerHandle The handle of the controller to test. This handle
|
|
must support a protocol interface that supplies
|
|
an I/O abstraction to the driver.
|
|
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
|
parameter is ignored by device drivers, and is optional for bus
|
|
drivers. For bus drivers, if this parameter is not NULL, then
|
|
the bus driver must determine if the bus controller specified
|
|
by ControllerHandle and the child controller specified
|
|
by RemainingDevicePath are both supported by this
|
|
bus driver.
|
|
|
|
@retval EFI_SUCCESS The device specified by ControllerHandle and
|
|
RemainingDevicePath is supported by the driver specified by This.
|
|
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
|
|
RemainingDevicePath is already being managed by the driver
|
|
specified by This.
|
|
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
|
|
RemainingDevicePath is already being managed by a different
|
|
driver or an application that requires exclusive access.
|
|
Currently not implemented.
|
|
@retval EFI_UNSUPPORTED The device specified by ControllerHandle and
|
|
RemainingDevicePath is not supported by the driver specified by This.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns6DriverBindingSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Test for the Dns6ServiceBinding Protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiDns6ServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
//
|
|
// Test for the Udp6ServiceBinding Protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiUdp6ServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Starts a device controller or a bus controller.
|
|
|
|
The Start() function is designed to be invoked from the EFI boot service ConnectController().
|
|
As a result, much of the error checking on the parameters to Start() has been moved into this
|
|
common boot service. It is legal to call Start() from other locations,
|
|
but the following calling restrictions must be followed, or the system behavior will not be deterministic.
|
|
1. ControllerHandle must be a valid EFI_HANDLE.
|
|
2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
|
|
EFI_DEVICE_PATH_PROTOCOL.
|
|
3. Prior to calling Start(), the Supported() function for the driver specified by This must
|
|
have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
|
|
|
|
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param[in] ControllerHandle The handle of the controller to start. This handle
|
|
must support a protocol interface that supplies
|
|
an I/O abstraction to the driver.
|
|
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
|
parameter is ignored by device drivers, and is optional for bus
|
|
drivers. For a bus driver, if this parameter is NULL, then handles
|
|
for all the children of Controller are created by this driver.
|
|
If this parameter is not NULL and the first Device Path Node is
|
|
not the End of Device Path Node, then only the handle for the
|
|
child device specified by the first Device Path Node of
|
|
RemainingDevicePath is created by this driver.
|
|
If the first Device Path Node of RemainingDevicePath is
|
|
the End of Device Path Node, no child handle is created by this
|
|
driver.
|
|
|
|
@retval EFI_SUCCESS The device was started.
|
|
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
|
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
|
@retval Others The driver failded to start the device.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns6DriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
DNS_SERVICE *DnsSb;
|
|
EFI_STATUS Status;
|
|
|
|
Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6, &DnsSb);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
ASSERT (DnsSb != NULL);
|
|
|
|
Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Install the Dns6ServiceBinding Protocol onto ControllerHandle
|
|
//
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&ControllerHandle,
|
|
&gEfiDns6ServiceBindingProtocolGuid,
|
|
&DnsSb->ServiceBinding,
|
|
NULL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
ON_ERROR:
|
|
DnsDestroyService (DnsSb);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Stops a device controller or a bus controller.
|
|
|
|
The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
|
|
As a result, much of the error checking on the parameters to Stop() has been moved
|
|
into this common boot service. It is legal to call Stop() from other locations,
|
|
but the following calling restrictions must be followed, or the system behavior will not be deterministic.
|
|
1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
|
|
same driver's Start() function.
|
|
2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
|
|
EFI_HANDLE. In addition, all of these handles must have been created in this driver's
|
|
Start() function, and the Start() function must have called OpenProtocol() on
|
|
ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
|
|
|
|
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
|
@param[in] ControllerHandle A handle to the device being stopped. The handle must
|
|
support a bus specific I/O protocol for the driver
|
|
to use to stop the device.
|
|
@param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
|
|
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
|
|
if NumberOfChildren is 0.
|
|
|
|
@retval EFI_SUCCESS The device was stopped.
|
|
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns6DriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
|
|
)
|
|
{
|
|
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
|
|
DNS_SERVICE *DnsSb;
|
|
EFI_HANDLE NicHandle;
|
|
EFI_STATUS Status;
|
|
LIST_ENTRY *List;
|
|
DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
|
|
|
|
//
|
|
// DNS driver opens UDP child, So, Controller is a UDP
|
|
// child handle. Locate the Nic handle first. Then get the
|
|
// DNS private data back.
|
|
//
|
|
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
|
|
|
|
if (NicHandle == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = gBS->OpenProtocol (
|
|
NicHandle,
|
|
&gEfiDns6ServiceBindingProtocolGuid,
|
|
(VOID **) &ServiceBinding,
|
|
This->DriverBindingHandle,
|
|
NicHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
|
|
DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding);
|
|
|
|
if (!IsListEmpty (&DnsSb->Dns6ChildrenList)) {
|
|
//
|
|
// Destroy the Dns child instance in ChildHandleBuffer.
|
|
//
|
|
List = &DnsSb->Dns6ChildrenList;
|
|
Context.ServiceBinding = ServiceBinding;
|
|
Context.NumberOfChildren = NumberOfChildren;
|
|
Context.ChildHandleBuffer = ChildHandleBuffer;
|
|
Status = NetDestroyLinkList (
|
|
List,
|
|
DnsDestroyChildEntryInHandleBuffer,
|
|
&Context,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
if (NumberOfChildren == 0 && IsListEmpty (&DnsSb->Dns6ChildrenList)) {
|
|
gBS->UninstallProtocolInterface (
|
|
NicHandle,
|
|
&gEfiDns6ServiceBindingProtocolGuid,
|
|
ServiceBinding
|
|
);
|
|
|
|
DnsDestroyService (DnsSb);
|
|
|
|
if (gDnsControllerNameTable != NULL) {
|
|
FreeUnicodeStringTable (gDnsControllerNameTable);
|
|
gDnsControllerNameTable = NULL;
|
|
}
|
|
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Creates a child handle and installs a protocol.
|
|
|
|
The CreateChild() function installs a protocol on ChildHandle.
|
|
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
|
|
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
|
|
|
|
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
|
@param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
|
|
then a new handle is created. If it is a pointer to an existing UEFI handle,
|
|
then the protocol is added to the existing UEFI handle.
|
|
|
|
@retval EFI_SUCCES The protocol was added to ChildHandle.
|
|
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
|
|
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
|
|
the child
|
|
@retval other The child handle was not created
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns4ServiceBindingCreateChild (
|
|
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE *ChildHandle
|
|
)
|
|
{
|
|
DNS_SERVICE *DnsSb;
|
|
DNS_INSTANCE *Instance;
|
|
EFI_STATUS Status;
|
|
EFI_TPL OldTpl;
|
|
VOID *Udp4;
|
|
|
|
if ((This == NULL) || (ChildHandle == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
DnsSb = DNS_SERVICE_FROM_THIS (This);
|
|
|
|
Status = DnsCreateInstance (DnsSb, &Instance);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
ASSERT (Instance != NULL);
|
|
|
|
//
|
|
// Install the DNS protocol onto ChildHandle
|
|
//
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
ChildHandle,
|
|
&gEfiDns4ProtocolGuid,
|
|
&Instance->Dns4,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Instance->ChildHandle = *ChildHandle;
|
|
|
|
//
|
|
// Open the Udp4 protocol BY_CHILD.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
DnsSb->ConnectUdp->UdpHandle,
|
|
&gEfiUdp4ProtocolGuid,
|
|
(VOID **) &Udp4,
|
|
gDns4DriverBinding.DriverBindingHandle,
|
|
Instance->ChildHandle,
|
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Instance->ChildHandle,
|
|
&gEfiDns4ProtocolGuid,
|
|
&Instance->Dns4,
|
|
NULL
|
|
);
|
|
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Open the Udp4 protocol by child.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Instance->UdpIo->UdpHandle,
|
|
&gEfiUdp4ProtocolGuid,
|
|
(VOID **) &Udp4,
|
|
gDns4DriverBinding.DriverBindingHandle,
|
|
Instance->ChildHandle,
|
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Close the Udp4 protocol.
|
|
//
|
|
gBS->CloseProtocol (
|
|
DnsSb->ConnectUdp->UdpHandle,
|
|
&gEfiUdp4ProtocolGuid,
|
|
gDns4DriverBinding.DriverBindingHandle,
|
|
*ChildHandle
|
|
);
|
|
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Instance->ChildHandle,
|
|
&gEfiDns4ProtocolGuid,
|
|
&Instance->Dns4,
|
|
NULL
|
|
);
|
|
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Add it to the parent's child list.
|
|
//
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
InsertTailList (&DnsSb->Dns4ChildrenList, &Instance->Link);
|
|
DnsSb->Dns4ChildrenNum++;
|
|
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
ON_ERROR:
|
|
|
|
DnsDestroyInstance (Instance);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Destroys a child handle with a protocol installed on it.
|
|
|
|
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
|
|
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
|
|
last protocol on ChildHandle, then ChildHandle is destroyed.
|
|
|
|
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
|
@param[in] ChildHandle Handle of the child to destroy
|
|
|
|
@retval EFI_SUCCES The protocol was removed from ChildHandle.
|
|
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
|
|
@retval EFI_INVALID_PARAMETER Child handle is NULL.
|
|
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
|
|
because its services are being used.
|
|
@retval other The child handle was not destroyed
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns4ServiceBindingDestroyChild (
|
|
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ChildHandle
|
|
)
|
|
{
|
|
DNS_SERVICE *DnsSb;
|
|
DNS_INSTANCE *Instance;
|
|
|
|
EFI_DNS4_PROTOCOL *Dns4;
|
|
EFI_STATUS Status;
|
|
EFI_TPL OldTpl;
|
|
|
|
if ((This == NULL) || (ChildHandle == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Retrieve the private context data structures
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
ChildHandle,
|
|
&gEfiDns4ProtocolGuid,
|
|
(VOID **) &Dns4,
|
|
gDns4DriverBinding.DriverBindingHandle,
|
|
ChildHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (Dns4);
|
|
DnsSb = DNS_SERVICE_FROM_THIS (This);
|
|
|
|
if (Instance->Service != DnsSb) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Instance->InDestroy) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
Instance->InDestroy = TRUE;
|
|
|
|
//
|
|
// Close the Udp4 protocol.
|
|
//
|
|
gBS->CloseProtocol (
|
|
DnsSb->ConnectUdp->UdpHandle,
|
|
&gEfiUdp4ProtocolGuid,
|
|
gDns4DriverBinding.DriverBindingHandle,
|
|
ChildHandle
|
|
);
|
|
|
|
gBS->CloseProtocol (
|
|
Instance->UdpIo->UdpHandle,
|
|
&gEfiUdp4ProtocolGuid,
|
|
gDns4DriverBinding.DriverBindingHandle,
|
|
ChildHandle
|
|
);
|
|
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
//
|
|
// Uninstall the DNS protocol first to enable a top down destruction.
|
|
//
|
|
Status = gBS->UninstallProtocolInterface (
|
|
ChildHandle,
|
|
&gEfiDns4ProtocolGuid,
|
|
Dns4
|
|
);
|
|
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
Instance->InDestroy = FALSE;
|
|
gBS->RestoreTPL (OldTpl);
|
|
return Status;
|
|
}
|
|
|
|
RemoveEntryList (&Instance->Link);
|
|
DnsSb->Dns4ChildrenNum--;
|
|
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
DnsDestroyInstance (Instance);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Creates a child handle and installs a protocol.
|
|
|
|
The CreateChild() function installs a protocol on ChildHandle.
|
|
If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
|
|
If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
|
|
|
|
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
|
@param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
|
|
then a new handle is created. If it is a pointer to an existing UEFI handle,
|
|
then the protocol is added to the existing UEFI handle.
|
|
|
|
@retval EFI_SUCCES The protocol was added to ChildHandle.
|
|
@retval EFI_INVALID_PARAMETER ChildHandle is NULL.
|
|
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
|
|
the child
|
|
@retval other The child handle was not created
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns6ServiceBindingCreateChild (
|
|
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE *ChildHandle
|
|
)
|
|
{
|
|
DNS_SERVICE *DnsSb;
|
|
DNS_INSTANCE *Instance;
|
|
EFI_STATUS Status;
|
|
EFI_TPL OldTpl;
|
|
VOID *Udp6;
|
|
|
|
if ((This == NULL) || (ChildHandle == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
DnsSb = DNS_SERVICE_FROM_THIS (This);
|
|
|
|
Status = DnsCreateInstance (DnsSb, &Instance);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
ASSERT (Instance != NULL);
|
|
|
|
//
|
|
// Install the DNS protocol onto ChildHandle
|
|
//
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
ChildHandle,
|
|
&gEfiDns6ProtocolGuid,
|
|
&Instance->Dns6,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Instance->ChildHandle = *ChildHandle;
|
|
|
|
//
|
|
// Open the Udp6 protocol BY_CHILD.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
DnsSb->ConnectUdp->UdpHandle,
|
|
&gEfiUdp6ProtocolGuid,
|
|
(VOID **) &Udp6,
|
|
gDns6DriverBinding.DriverBindingHandle,
|
|
Instance->ChildHandle,
|
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Instance->ChildHandle,
|
|
&gEfiDns6ProtocolGuid,
|
|
&Instance->Dns6,
|
|
NULL
|
|
);
|
|
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Open the Udp6 protocol by child.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Instance->UdpIo->UdpHandle,
|
|
&gEfiUdp6ProtocolGuid,
|
|
(VOID **) &Udp6,
|
|
gDns6DriverBinding.DriverBindingHandle,
|
|
Instance->ChildHandle,
|
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
//
|
|
// Close the Udp6 protocol.
|
|
//
|
|
gBS->CloseProtocol (
|
|
DnsSb->ConnectUdp->UdpHandle,
|
|
&gEfiUdp6ProtocolGuid,
|
|
gDns6DriverBinding.DriverBindingHandle,
|
|
*ChildHandle
|
|
);
|
|
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
Instance->ChildHandle,
|
|
&gEfiDns6ProtocolGuid,
|
|
&Instance->Dns6,
|
|
NULL
|
|
);
|
|
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Add it to the parent's child list.
|
|
//
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
InsertTailList (&DnsSb->Dns6ChildrenList, &Instance->Link);
|
|
DnsSb->Dns6ChildrenNum++;
|
|
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
ON_ERROR:
|
|
|
|
DnsDestroyInstance (Instance);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Destroys a child handle with a protocol installed on it.
|
|
|
|
The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
|
|
that was installed by CreateChild() from ChildHandle. If the removed protocol is the
|
|
last protocol on ChildHandle, then ChildHandle is destroyed.
|
|
|
|
@param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
|
|
@param[in] ChildHandle Handle of the child to destroy
|
|
|
|
@retval EFI_SUCCES The protocol was removed from ChildHandle.
|
|
@retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
|
|
@retval EFI_INVALID_PARAMETER Child handle is NULL.
|
|
@retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
|
|
because its services are being used.
|
|
@retval other The child handle was not destroyed
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Dns6ServiceBindingDestroyChild (
|
|
IN EFI_SERVICE_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ChildHandle
|
|
)
|
|
{
|
|
DNS_SERVICE *DnsSb;
|
|
DNS_INSTANCE *Instance;
|
|
|
|
EFI_DNS6_PROTOCOL *Dns6;
|
|
EFI_STATUS Status;
|
|
EFI_TPL OldTpl;
|
|
|
|
if ((This == NULL) || (ChildHandle == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Retrieve the private context data structures
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
ChildHandle,
|
|
&gEfiDns6ProtocolGuid,
|
|
(VOID **) &Dns6,
|
|
gDns6DriverBinding.DriverBindingHandle,
|
|
ChildHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (Dns6);
|
|
DnsSb = DNS_SERVICE_FROM_THIS (This);
|
|
|
|
if (Instance->Service != DnsSb) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Instance->InDestroy) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
Instance->InDestroy = TRUE;
|
|
|
|
//
|
|
// Close the Udp6 protocol.
|
|
//
|
|
gBS->CloseProtocol (
|
|
DnsSb->ConnectUdp->UdpHandle,
|
|
&gEfiUdp6ProtocolGuid,
|
|
gDns6DriverBinding.DriverBindingHandle,
|
|
ChildHandle
|
|
);
|
|
|
|
gBS->CloseProtocol (
|
|
Instance->UdpIo->UdpHandle,
|
|
&gEfiUdp6ProtocolGuid,
|
|
gDns6DriverBinding.DriverBindingHandle,
|
|
ChildHandle
|
|
);
|
|
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
//
|
|
// Uninstall the DNS protocol first to enable a top down destruction.
|
|
//
|
|
Status = gBS->UninstallProtocolInterface (
|
|
ChildHandle,
|
|
&gEfiDns6ProtocolGuid,
|
|
Dns6
|
|
);
|
|
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
Instance->InDestroy = FALSE;
|
|
gBS->RestoreTPL (OldTpl);
|
|
return Status;
|
|
}
|
|
|
|
RemoveEntryList (&Instance->Link);
|
|
DnsSb->Dns6ChildrenNum--;
|
|
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
DnsDestroyInstance (Instance);
|
|
return EFI_SUCCESS;
|
|
}
|