/** @file
Driver Binding functions implementation for UefiPxeBc Driver.
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.
Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.
Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PxeBcImpl.h"
EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp4DriverBinding = {
PxeBcIp4DriverBindingSupported,
PxeBcIp4DriverBindingStart,
PxeBcIp4DriverBindingStop,
0xa,
NULL,
NULL
};
EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp6DriverBinding = {
PxeBcIp6DriverBindingSupported,
PxeBcIp6DriverBindingStart,
PxeBcIp6DriverBindingStop,
0xa,
NULL,
NULL
};
/**
Get the Nic handle using any child handle in the IPv4 stack.
@param[in] ControllerHandle Pointer to child handle over IPv4.
@return NicHandle The pointer to the Nic handle.
**/
EFI_HANDLE
PxeBcGetNicByIp4Children (
IN EFI_HANDLE ControllerHandle
)
{
EFI_HANDLE NicHandle;
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
if (NicHandle == NULL) {
return NULL;
}
}
}
}
}
return NicHandle;
}
/**
Get the Nic handle using any child handle in the IPv6 stack.
@param[in] ControllerHandle Pointer to child handle over IPv6.
@return NicHandle The pointer to the Nic handle.
**/
EFI_HANDLE
PxeBcGetNicByIp6Children (
IN EFI_HANDLE ControllerHandle
)
{
EFI_HANDLE NicHandle;
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp6ProtocolGuid);
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp6ProtocolGuid);
if (NicHandle == NULL) {
return NULL;
}
}
}
}
return NicHandle;
}
/**
Destroy the opened instances based on IPv4.
@param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
@param[in] Private Pointer to PXEBC_PRIVATE_DATA.
**/
VOID
PxeBcDestroyIp4Children (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN PXEBC_PRIVATE_DATA *Private
)
{
ASSERT (Private != NULL);
if (Private->ArpChild != NULL) {
//
// Close Arp for PxeBc->Arp and destroy the instance.
//
gBS->CloseProtocol (
Private->ArpChild,
&gEfiArpProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiArpServiceBindingProtocolGuid,
Private->ArpChild
);
}
if (Private->Ip4Child != NULL) {
//
// Close Ip4 for background ICMP error message and destroy the instance.
//
gBS->CloseProtocol (
Private->Ip4Child,
&gEfiIp4ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiIp4ServiceBindingProtocolGuid,
Private->Ip4Child
);
}
if (Private->Udp4WriteChild != NULL) {
//
// Close Udp4 for PxeBc->UdpWrite and destroy the instance.
//
gBS->CloseProtocol (
Private->Udp4WriteChild,
&gEfiUdp4ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
Private->Udp4WriteChild
);
}
if (Private->Udp4ReadChild != NULL) {
//
// Close Udp4 for PxeBc->UdpRead and destroy the instance.
//
gBS->CloseProtocol (
Private->Udp4ReadChild,
&gEfiUdp4ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
Private->Udp4ReadChild
);
}
if (Private->Mtftp4Child != NULL) {
//
// Close Mtftp4 for PxeBc->Mtftp4 and destroy the instance.
//
gBS->CloseProtocol (
Private->Mtftp4Child,
&gEfiMtftp4ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiMtftp4ServiceBindingProtocolGuid,
Private->Mtftp4Child
);
}
if (Private->Dhcp4Child != NULL) {
//
// Close Dhcp4 for PxeBc->Dhcp4 and destroy the instance.
//
gBS->CloseProtocol (
Private->Dhcp4Child,
&gEfiDhcp4ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiDhcp4ServiceBindingProtocolGuid,
Private->Dhcp4Child
);
}
if (Private->Ip4Nic != NULL) {
//
// Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
//
gBS->CloseProtocol (
Private->Controller,
&gEfiCallerIdGuid,
This->DriverBindingHandle,
Private->Ip4Nic->Controller
);
gBS->UninstallMultipleProtocolInterfaces (
Private->Ip4Nic->Controller,
&gEfiDevicePathProtocolGuid,
Private->Ip4Nic->DevicePath,
&gEfiLoadFileProtocolGuid,
&Private->Ip4Nic->LoadFile,
&gEfiPxeBaseCodeProtocolGuid,
&Private->PxeBc,
NULL
);
FreePool (Private->Ip4Nic->DevicePath);
if (Private->Snp != NULL) {
//
// Close SNP from the child virtual handle
//
gBS->CloseProtocol (
Private->Ip4Nic->Controller,
&gEfiSimpleNetworkProtocolGuid,
This->DriverBindingHandle,
Private->Ip4Nic->Controller
);
gBS->UninstallProtocolInterface (
Private->Ip4Nic->Controller,
&gEfiSimpleNetworkProtocolGuid,
Private->Snp
);
}
FreePool (Private->Ip4Nic);
}
Private->ArpChild = NULL;
Private->Ip4Child = NULL;
Private->Udp4WriteChild = NULL;
Private->Udp4ReadChild = NULL;
Private->Mtftp4Child = NULL;
Private->Dhcp4Child = NULL;
Private->Ip4Nic = NULL;
}
/**
Destroy the opened instances based on IPv6.
@param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
@param[in] Private Pointer to PXEBC_PRIVATE_DATA.
**/
VOID
PxeBcDestroyIp6Children (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN PXEBC_PRIVATE_DATA *Private
)
{
ASSERT (Private != NULL);
if (Private->Ip6Child != NULL) {
//
// Close Ip6 for Ip6->Ip6Config and destroy the instance.
//
gBS->CloseProtocol (
Private->Ip6Child,
&gEfiIp6ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiIp6ServiceBindingProtocolGuid,
Private->Ip6Child
);
}
if (Private->Udp6WriteChild != NULL) {
//
// Close Udp6 for PxeBc->UdpWrite and destroy the instance.
//
gBS->CloseProtocol (
Private->Udp6WriteChild,
&gEfiUdp6ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiUdp6ServiceBindingProtocolGuid,
Private->Udp6WriteChild
);
}
if (Private->Udp6ReadChild != NULL) {
//
// Close Udp6 for PxeBc->UdpRead and destroy the instance.
//
gBS->CloseProtocol (
Private->Udp6ReadChild,
&gEfiUdp6ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiUdp6ServiceBindingProtocolGuid,
Private->Udp6ReadChild
);
}
if (Private->Mtftp6Child != NULL) {
//
// Close Mtftp6 for PxeBc->Mtftp and destroy the instance.
//
gBS->CloseProtocol (
Private->Mtftp6Child,
&gEfiMtftp6ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiMtftp6ServiceBindingProtocolGuid,
Private->Mtftp6Child
);
}
if (Private->Dhcp6Child != NULL) {
//
// Close Dhcp6 for PxeBc->Dhcp and destroy the instance.
//
gBS->CloseProtocol (
Private->Dhcp6Child,
&gEfiDhcp6ProtocolGuid,
This->DriverBindingHandle,
Private->Controller
);
NetLibDestroyServiceChild (
Private->Controller,
This->DriverBindingHandle,
&gEfiDhcp6ServiceBindingProtocolGuid,
Private->Dhcp6Child
);
}
if (Private->Ip6Nic != NULL) {
//
// Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
//
gBS->CloseProtocol (
Private->Controller,
&gEfiCallerIdGuid,
This->DriverBindingHandle,
Private->Ip6Nic->Controller
);
gBS->UninstallMultipleProtocolInterfaces (
Private->Ip6Nic->Controller,
&gEfiDevicePathProtocolGuid,
Private->Ip6Nic->DevicePath,
&gEfiLoadFileProtocolGuid,
&Private->Ip6Nic->LoadFile,
&gEfiPxeBaseCodeProtocolGuid,
&Private->PxeBc,
NULL
);
FreePool (Private->Ip6Nic->DevicePath);
if (Private->Snp != NULL) {
//
// Close SNP from the child virtual handle
//
gBS->CloseProtocol (
Private->Ip6Nic->Controller,
&gEfiSimpleNetworkProtocolGuid,
This->DriverBindingHandle,
Private->Ip6Nic->Controller
);
gBS->UninstallProtocolInterface (
Private->Ip6Nic->Controller,
&gEfiSimpleNetworkProtocolGuid,
Private->Snp
);
}
FreePool (Private->Ip6Nic);
}
Private->Ip6Child = NULL;
Private->Udp6WriteChild = NULL;
Private->Udp6ReadChild = NULL;
Private->Mtftp6Child = NULL;
Private->Dhcp6Child = NULL;
Private->Ip6Nic = NULL;
Private->Mode.Ipv6Available = FALSE;
}
/**
Check whether UNDI protocol supports IPv6.
@param[in] ControllerHandle Controller handle.
@param[in] Private Pointer to PXEBC_PRIVATE_DATA.
@param[out] Ipv6Support TRUE if UNDI supports IPv6.
@retval EFI_SUCCESS Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.
@retval EFI_NOT_FOUND Don't know whether UNDI supports IPv6 since NII or AIP is not available.
**/
EFI_STATUS
PxeBcCheckIpv6Support (
IN EFI_HANDLE ControllerHandle,
IN PXEBC_PRIVATE_DATA *Private,
OUT BOOLEAN *Ipv6Support
)
{
EFI_HANDLE Handle;
EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
EFI_STATUS Status;
EFI_GUID *InfoTypesBuffer;
UINTN InfoTypeBufferCount;
UINTN TypeIndex;
BOOLEAN Supported;
VOID *InfoBlock;
UINTN InfoBlockSize;
ASSERT (Private != NULL && Ipv6Support != NULL);
//
// Check whether the UNDI supports IPv6 by NII protocol.
//
if (Private->Nii != NULL) {
*Ipv6Support = Private->Nii->Ipv6Supported;
return EFI_SUCCESS;
}
//
// Check whether the UNDI supports IPv6 by AIP protocol.
//
//
// Get the NIC handle by SNP protocol.
//
Handle = NetLibGetSnpHandle (ControllerHandle, NULL);
if (Handle == NULL) {
return EFI_NOT_FOUND;
}
Aip = NULL;
Status = gBS->HandleProtocol (
Handle,
&gEfiAdapterInformationProtocolGuid,
(VOID *)&Aip
);
if (EFI_ERROR (Status) || (Aip == NULL)) {
return EFI_NOT_FOUND;
}
InfoTypesBuffer = NULL;
InfoTypeBufferCount = 0;
Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);
if (EFI_ERROR (Status) || (InfoTypesBuffer == NULL)) {
FreePool (InfoTypesBuffer);
return EFI_NOT_FOUND;
}
Supported = FALSE;
for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {
Supported = TRUE;
break;
}
}
FreePool (InfoTypesBuffer);
if (!Supported) {
return EFI_NOT_FOUND;
}
//
// We now have adapter information block.
//
InfoBlock = NULL;
InfoBlockSize = 0;
Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);
if (EFI_ERROR (Status) || (InfoBlock == NULL)) {
FreePool (InfoBlock);
return EFI_NOT_FOUND;
}
*Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *)InfoBlock)->Ipv6Support;
FreePool (InfoBlock);
return EFI_SUCCESS;
}
/**
Create the opened instances based on IPv4.
@param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL.
@param[in] ControllerHandle Handle of the child to destroy.
@param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA.
@retval EFI_SUCCESS The instances based on IPv4 were all created successfully.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
PxeBcCreateIp4Children (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN PXEBC_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
IPv4_DEVICE_PATH Ip4Node;
EFI_PXE_BASE_CODE_MODE *Mode;
EFI_UDP4_CONFIG_DATA *Udp4CfgData;
EFI_IP4_CONFIG_DATA *Ip4CfgData;
EFI_IP4_MODE_DATA Ip4ModeData;
PXEBC_PRIVATE_PROTOCOL *Id;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
if (Private->Ip4Nic != NULL) {
//
// Already created before.
//
return EFI_SUCCESS;
}
//
// Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiDhcp4ServiceBindingProtocolGuid,
&Private->Dhcp4Child
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Dhcp4Child,
&gEfiDhcp4ProtocolGuid,
(VOID **)&Private->Dhcp4,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiMtftp4ServiceBindingProtocolGuid,
&Private->Mtftp4Child
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Mtftp4Child,
&gEfiMtftp4ProtocolGuid,
(VOID **)&Private->Mtftp4,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
&Private->Udp4ReadChild
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Udp4ReadChild,
&gEfiUdp4ProtocolGuid,
(VOID **)&Private->Udp4Read,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
&Private->Udp4WriteChild
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Udp4WriteChild,
&gEfiUdp4ProtocolGuid,
(VOID **)&Private->Udp4Write,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create Arp child and open Arp protocol for PxeBc->Arp.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiArpServiceBindingProtocolGuid,
&Private->ArpChild
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->ArpChild,
&gEfiArpProtocolGuid,
(VOID **)&Private->Arp,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create Ip4 child and open Ip4 protocol for background ICMP packets.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiIp4ServiceBindingProtocolGuid,
&Private->Ip4Child
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Ip4Child,
&gEfiIp4ProtocolGuid,
(VOID **)&Private->Ip4,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Get max packet size from Ip4 to calculate block size for Tftp later.
//
Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;
Private->Ip4Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
if (Private->Ip4Nic == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Private->Ip4Nic->Private = Private;
Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;
//
// Locate Ip4->Ip4Config2 and store it for set IPv4 Policy.
//
Status = gBS->HandleProtocol (
ControllerHandle,
&gEfiIp4Config2ProtocolGuid,
(VOID **)&Private->Ip4Config2
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create a device path node for Ipv4 virtual nic, and append it.
//
ZeroMem (&Ip4Node, sizeof (IPv4_DEVICE_PATH));
Ip4Node.Header.Type = MESSAGING_DEVICE_PATH;
Ip4Node.Header.SubType = MSG_IPv4_DP;
Ip4Node.StaticIpAddress = FALSE;
SetDevicePathNodeLength (&Ip4Node.Header, sizeof (Ip4Node));
Private->Ip4Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip4Node.Header);
if (Private->Ip4Nic->DevicePath == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
}
CopyMem (
&Private->Ip4Nic->LoadFile,
&gLoadFileProtocolTemplate,
sizeof (EFI_LOAD_FILE_PROTOCOL)
);
//
// Create a new handle for IPv4 virtual nic,
// and install PxeBaseCode, LoadFile and DevicePath protocols.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->Ip4Nic->Controller,
&gEfiDevicePathProtocolGuid,
Private->Ip4Nic->DevicePath,
&gEfiLoadFileProtocolGuid,
&Private->Ip4Nic->LoadFile,
&gEfiPxeBaseCodeProtocolGuid,
&Private->PxeBc,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
if (Private->Snp != NULL) {
//
// Install SNP protocol on purpose is for some OS loader backward
// compatibility consideration.
//
Status = gBS->InstallProtocolInterface (
&Private->Ip4Nic->Controller,
&gEfiSimpleNetworkProtocolGuid,
EFI_NATIVE_INTERFACE,
Private->Snp
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Open SNP on the child handle BY_DRIVER|EXCLUSIVE. It will prevent any additionally
// layering to perform the experiment.
//
Status = gBS->OpenProtocol (
Private->Ip4Nic->Controller,
&gEfiSimpleNetworkProtocolGuid,
(VOID **)&Snp,
This->DriverBindingHandle,
Private->Ip4Nic->Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
}
//
// Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
// real NIC handle and the virtual IPv4 NIC handle.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiCallerIdGuid,
(VOID **)&Id,
This->DriverBindingHandle,
Private->Ip4Nic->Controller,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Set default configure data for Udp4Read and Ip4 instance.
//
Mode = Private->PxeBc.Mode;
Udp4CfgData = &Private->Udp4CfgData;
Ip4CfgData = &Private->Ip4CfgData;
Udp4CfgData->AcceptBroadcast = FALSE;
Udp4CfgData->AcceptAnyPort = TRUE;
Udp4CfgData->AllowDuplicatePort = TRUE;
Udp4CfgData->TypeOfService = Mode->ToS;
Udp4CfgData->TimeToLive = Mode->TTL;
Udp4CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;
Udp4CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;
Ip4CfgData->AcceptIcmpErrors = TRUE;
Ip4CfgData->DefaultProtocol = EFI_IP_PROTO_ICMP;
Ip4CfgData->TypeOfService = Mode->ToS;
Ip4CfgData->TimeToLive = Mode->TTL;
Ip4CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;
Ip4CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;
return EFI_SUCCESS;
ON_ERROR:
PxeBcDestroyIp4Children (This, Private);
return Status;
}
/**
Create the opened instances based on IPv6.
@param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL.
@param[in] ControllerHandle Handle of the child to destroy.
@param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA.
@retval EFI_SUCCESS The instances based on IPv6 were all created successfully.
@retval Others An unexpected error occurred.
**/
EFI_STATUS
PxeBcCreateIp6Children (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN PXEBC_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
IPv6_DEVICE_PATH Ip6Node;
EFI_UDP6_CONFIG_DATA *Udp6CfgData;
EFI_IP6_CONFIG_DATA *Ip6CfgData;
EFI_IP6_MODE_DATA Ip6ModeData;
PXEBC_PRIVATE_PROTOCOL *Id;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
UINTN Index;
UINT32 Random;
Status = PseudoRandomU32 (&Random);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Failed to generate random number using EFI_RNG_PROTOCOL: %r\n", Status));
return Status;
}
if (Private->Ip6Nic != NULL) {
//
// Already created before.
//
return EFI_SUCCESS;
}
Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
if (Private->Ip6Nic == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Private->Ip6Nic->Private = Private;
Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;
//
// Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiDhcp6ServiceBindingProtocolGuid,
&Private->Dhcp6Child
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Dhcp6Child,
&gEfiDhcp6ProtocolGuid,
(VOID **)&Private->Dhcp6,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Set a random IAID for the Dhcp6 assigned address.
//
Private->IaId = Random;
if (Private->Snp != NULL) {
for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));
}
}
//
// Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiMtftp6ServiceBindingProtocolGuid,
&Private->Mtftp6Child
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Mtftp6Child,
&gEfiMtftp6ProtocolGuid,
(VOID **)&Private->Mtftp6,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiUdp6ServiceBindingProtocolGuid,
&Private->Udp6ReadChild
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Udp6ReadChild,
&gEfiUdp6ProtocolGuid,
(VOID **)&Private->Udp6Read,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiUdp6ServiceBindingProtocolGuid,
&Private->Udp6WriteChild
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Udp6WriteChild,
&gEfiUdp6ProtocolGuid,
(VOID **)&Private->Udp6Write,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create Ip6 child and open Ip6 protocol for background ICMP6 packets.
//
Status = NetLibCreateServiceChild (
ControllerHandle,
This->DriverBindingHandle,
&gEfiIp6ServiceBindingProtocolGuid,
&Private->Ip6Child
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->OpenProtocol (
Private->Ip6Child,
&gEfiIp6ProtocolGuid,
(VOID **)&Private->Ip6,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Get max packet size from Ip6 to calculate block size for Tftp later.
//
Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;
if (Ip6ModeData.AddressList != NULL) {
FreePool (Ip6ModeData.AddressList);
}
if (Ip6ModeData.GroupTable != NULL) {
FreePool (Ip6ModeData.GroupTable);
}
if (Ip6ModeData.RouteTable != NULL) {
FreePool (Ip6ModeData.RouteTable);
}
if (Ip6ModeData.NeighborCache != NULL) {
FreePool (Ip6ModeData.NeighborCache);
}
if (Ip6ModeData.PrefixTable != NULL) {
FreePool (Ip6ModeData.PrefixTable);
}
if (Ip6ModeData.IcmpTypeList != NULL) {
FreePool (Ip6ModeData.IcmpTypeList);
}
//
// Locate Ip6->Ip6Config and store it for set IPv6 address.
//
Status = gBS->HandleProtocol (
ControllerHandle,
&gEfiIp6ConfigProtocolGuid,
(VOID **)&Private->Ip6Cfg
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Create a device path node for Ipv6 virtual nic, and append it.
//
ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));
Ip6Node.Header.Type = MESSAGING_DEVICE_PATH;
Ip6Node.Header.SubType = MSG_IPv6_DP;
Ip6Node.PrefixLength = IP6_PREFIX_LENGTH;
SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));
Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header);
if (Private->Ip6Nic->DevicePath == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_ERROR;
}
CopyMem (
&Private->Ip6Nic->LoadFile,
&gLoadFileProtocolTemplate,
sizeof (EFI_LOAD_FILE_PROTOCOL)
);
//
// Create a new handle for IPv6 virtual nic,
// and install PxeBaseCode, LoadFile and DevicePath protocols.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&Private->Ip6Nic->Controller,
&gEfiDevicePathProtocolGuid,
Private->Ip6Nic->DevicePath,
&gEfiLoadFileProtocolGuid,
&Private->Ip6Nic->LoadFile,
&gEfiPxeBaseCodeProtocolGuid,
&Private->PxeBc,
NULL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
if (Private->Snp != NULL) {
//
// Install SNP protocol on purpose is for some OS loader backward
// compatibility consideration.
//
Status = gBS->InstallProtocolInterface (
&Private->Ip6Nic->Controller,
&gEfiSimpleNetworkProtocolGuid,
EFI_NATIVE_INTERFACE,
Private->Snp
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Open SNP on the child handle BY_DRIVER|EXCLUSIVE. It will prevent any additionally
// layering to perform the experiment.
//
Status = gBS->OpenProtocol (
Private->Ip6Nic->Controller,
&gEfiSimpleNetworkProtocolGuid,
(VOID **)&Snp,
This->DriverBindingHandle,
Private->Ip6Nic->Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
}
//
// Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
// real NIC handle and the virtual IPv6 NIC handle.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiCallerIdGuid,
(VOID **)&Id,
This->DriverBindingHandle,
Private->Ip6Nic->Controller,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Set IPv6 available flag and set default configure data for
// Udp6Read and Ip6 instance.
//
Status = PxeBcCheckIpv6Support (ControllerHandle, Private, &Private->Mode.Ipv6Available);
if (EFI_ERROR (Status)) {
//
// Fail to get the data whether UNDI supports IPv6. Set default value.
//
Private->Mode.Ipv6Available = TRUE;
}
if (!Private->Mode.Ipv6Available) {
goto ON_ERROR;
}
Udp6CfgData = &Private->Udp6CfgData;
Ip6CfgData = &Private->Ip6CfgData;
Udp6CfgData->AcceptAnyPort = TRUE;
Udp6CfgData->AllowDuplicatePort = TRUE;
Udp6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT;
Udp6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;
Udp6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;
Ip6CfgData->AcceptIcmpErrors = TRUE;
Ip6CfgData->DefaultProtocol = IP6_ICMP;
Ip6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT;
Ip6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;
Ip6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;
return EFI_SUCCESS;
ON_ERROR:
PxeBcDestroyIp6Children (This, Private);
return Status;
}
/**
The entry point for UefiPxeBc driver that installs the driver
binding and component name protocol on its image.
@param[in] ImageHandle The Image handle of the driver.
@param[in] SystemTable The system table.
@return EFI_SUCCESS
@return Others
**/
EFI_STATUS
EFIAPI
PxeBcDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
if ((PcdGet8 (PcdIPv4PXESupport) == PXE_DISABLED) && (PcdGet8 (PcdIPv6PXESupport) == PXE_DISABLED)) {
return EFI_UNSUPPORTED;
}
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gPxeBcIp4DriverBinding,
ImageHandle,
&gPxeBcComponentName,
&gPxeBcComponentName2
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gPxeBcIp6DriverBinding,
NULL,
&gPxeBcComponentName,
&gPxeBcComponentName2
);
if (EFI_ERROR (Status)) {
EfiLibUninstallDriverBindingComponentName2 (
&gPxeBcIp4DriverBinding,
&gPxeBcComponentName,
&gPxeBcComponentName2
);
}
return Status;
}
/**
Test to see if this driver supports ControllerHandle. This is the worker function for
PxeBcIp4(6)DriverBindingSupported.
@param[in] This The pointer to the driver binding protocol.
@param[in] ControllerHandle The handle of device to be tested.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to be started.
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_UNSUPPORTED This driver does not support this device.
**/
EFI_STATUS
EFIAPI
PxeBcSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
IN UINT8 IpVersion
)
{
EFI_STATUS Status;
EFI_GUID *DhcpServiceBindingGuid;
EFI_GUID *MtftpServiceBindingGuid;
if (IpVersion == IP_VERSION_4) {
if (PcdGet8 (PcdIPv4PXESupport) == PXE_DISABLED) {
return EFI_UNSUPPORTED;
}
DhcpServiceBindingGuid = &gEfiDhcp4ServiceBindingProtocolGuid;
MtftpServiceBindingGuid = &gEfiMtftp4ServiceBindingProtocolGuid;
} else {
if (PcdGet8 (PcdIPv6PXESupport) == PXE_DISABLED) {
return EFI_UNSUPPORTED;
}
DhcpServiceBindingGuid = &gEfiDhcp6ServiceBindingProtocolGuid;
MtftpServiceBindingGuid = &gEfiMtftp6ServiceBindingProtocolGuid;
}
//
// Try to open the Mtftp and Dhcp protocol to test whether IP stack is ready.
//
Status = gBS->OpenProtocol (
ControllerHandle,
DhcpServiceBindingGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
Status = gBS->OpenProtocol (
ControllerHandle,
MtftpServiceBindingGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
}
//
// It's unsupported case if IP stack are not ready.
//
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
/**
Start this driver on ControllerHandle. This is the worker function for
PxeBcIp4(6)DriverBindingStart.
@param[in] This The pointer to the driver binding protocol.
@param[in] ControllerHandle The handle of device to be started.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to be started.
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
@retval EFI_SUCCESS This driver is installed to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
PxeBcStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
IN UINT8 IpVersion
)
{
PXEBC_PRIVATE_DATA *Private;
EFI_STATUS Status;
PXEBC_PRIVATE_PROTOCOL *Id;
BOOLEAN FirstStart;
FirstStart = FALSE;
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiCallerIdGuid,
(VOID **)&Id,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (!EFI_ERROR (Status)) {
//
// Skip the initialization if the driver has been started already.
//
Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
} else {
FirstStart = TRUE;
//
// If the driver has not been started yet, it should do initialization.
//
Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
if (Private == NULL) {
return EFI_OUT_OF_RESOURCES;
}
CopyMem (
&Private->PxeBc,
&gPxeBcProtocolTemplate,
sizeof (EFI_PXE_BASE_CODE_PROTOCOL)
);
Private->Signature = PXEBC_PRIVATE_DATA_SIGNATURE;
Private->Controller = ControllerHandle;
Private->Image = This->ImageHandle;
Private->PxeBc.Mode = &Private->Mode;
Private->Mode.Ipv6Supported = TRUE;
Private->Mode.AutoArp = TRUE;
Private->Mode.TTL = DEFAULT_TTL;
Private->Mode.ToS = DEFAULT_ToS;
//
// Open device path to prepare for appending virtual NIC node.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDevicePathProtocolGuid,
(VOID **)&Private->DevicePath,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Get the NII interface if it exists, it's not required.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiNetworkInterfaceIdentifierProtocolGuid_31,
(VOID **)&Private->Nii,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
Private->Nii = NULL;
}
//
// Install PxeBaseCodePrivate protocol onto the real NIC handler.
// PxeBaseCodePrivate protocol is only used to keep the relationship between
// NIC handle and virtual child handles.
// gEfiCallerIdGuid will be used as its protocol guid.
//
Status = gBS->InstallProtocolInterface (
&ControllerHandle,
&gEfiCallerIdGuid,
EFI_NATIVE_INTERFACE,
&Private->Id
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Try to locate SNP protocol.
//
NetLibGetSnpHandle (ControllerHandle, &Private->Snp);
}
if (IpVersion == IP_VERSION_4) {
//
// Try to create virtual NIC handle for IPv4.
//
Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);
} else {
//
// Try to create virtual NIC handle for IPv6.
//
Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);
}
if (EFI_ERROR (Status)) {
//
// Failed to start PXE driver if IPv4 and IPv6 stack are both not available.
//
Status = EFI_DEVICE_ERROR;
goto ON_ERROR;
}
return EFI_SUCCESS;
ON_ERROR:
if (FirstStart) {
gBS->UninstallProtocolInterface (
ControllerHandle,
&gEfiCallerIdGuid,
&Private->Id
);
}
if (IpVersion == IP_VERSION_4) {
PxeBcDestroyIp4Children (This, Private);
} else {
PxeBcDestroyIp6Children (This, Private);
}
if (FirstStart && (Private != NULL)) {
FreePool (Private);
}
return Status;
}
/**
Stop this driver on ControllerHandle. This is the worker function for
PxeBcIp4(6)DriverBindingStop.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on.
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
children is zero stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
@retval EFI_SUCCESS This driver was removed ControllerHandle.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval Others This driver was not removed from this device
**/
EFI_STATUS
EFIAPI
PxeBcStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer,
IN UINT8 IpVersion
)
{
PXEBC_PRIVATE_DATA *Private;
PXEBC_VIRTUAL_NIC *VirtualNic;
EFI_LOAD_FILE_PROTOCOL *LoadFile;
EFI_STATUS Status;
EFI_HANDLE NicHandle;
PXEBC_PRIVATE_PROTOCOL *Id;
Private = NULL;
NicHandle = NULL;
VirtualNic = NULL;
LoadFile = NULL;
Id = NULL;
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiLoadFileProtocolGuid,
(VOID **)&LoadFile,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
//
// Get the Nic handle by any pass-over service child handle.
//
if (IpVersion == IP_VERSION_4) {
NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);
} else {
NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);
}
if (NicHandle == NULL) {
return EFI_SUCCESS;
}
//
// Try to retrieve the private data by PxeBcPrivate protocol.
//
Status = gBS->OpenProtocol (
NicHandle,
&gEfiCallerIdGuid,
(VOID **)&Id,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
} else {
//
// It's a virtual handle with LoadFileProtocol.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiLoadFileProtocolGuid,
(VOID **)&LoadFile,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);
Private = VirtualNic->Private;
NicHandle = Private->Controller;
}
//
// Stop functionality of PXE Base Code protocol
//
Status = Private->PxeBc.Stop (&Private->PxeBc);
if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_STARTED)) {
return Status;
}
if ((Private->Ip4Nic != NULL) && (IpVersion == IP_VERSION_4)) {
PxeBcDestroyIp4Children (This, Private);
}
if ((Private->Ip6Nic != NULL) && (IpVersion == IP_VERSION_6)) {
PxeBcDestroyIp6Children (This, Private);
}
if ((Private->Ip4Nic == NULL) && (Private->Ip6Nic == NULL)) {
gBS->UninstallProtocolInterface (
NicHandle,
&gEfiCallerIdGuid,
&Private->Id
);
FreePool (Private);
}
return EFI_SUCCESS;
}
/**
Test to see if this driver supports ControllerHandle. This service
is called by the EFI boot service ConnectController(). In
order to make drivers as small as possible, there are a few calling
restrictions for this service. ConnectController() must
follow these calling restrictions. If any other agent wishes to call
Supported() it must also follow these calling restrictions.
@param[in] This The pointer to the driver binding protocol.
@param[in] ControllerHandle The handle of device to be tested.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to be started.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_UNSUPPORTED This driver does not support this device.
**/
EFI_STATUS
EFIAPI
PxeBcIp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
return PxeBcSupported (
This,
ControllerHandle,
RemainingDevicePath,
IP_VERSION_4
);
}
/**
Start this driver on ControllerHandle. This service is called by the
EFI boot service ConnectController(). In order to make
drivers as small as possible, there are a few calling restrictions for
this service. ConnectController() must follow these
calling restrictions. If any other agent wishes to call Start() it
must also follow these calling restrictions.
@param[in] This The pointer to the driver binding protocol.
@param[in] ControllerHandle The handle of device to be started.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to be started.
@retval EFI_SUCCESS This driver is installed to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
PxeBcIp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
return PxeBcStart (
This,
ControllerHandle,
RemainingDevicePath,
IP_VERSION_4
);
}
/**
Stop this driver on ControllerHandle. This service is called by the
EFI boot service DisconnectController(). In order to
make drivers as small as possible, there are a few calling
restrictions for this service. DisconnectController()
must follow these calling restrictions. If any other agent wishes
to call Stop() it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
children is zero stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCESS This driver is removed ControllerHandle
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval Others This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
PxeBcIp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
return PxeBcStop (
This,
ControllerHandle,
NumberOfChildren,
ChildHandleBuffer,
IP_VERSION_4
);
}
/**
Test to see if this driver supports ControllerHandle. This service
is called by the EFI boot service ConnectController(). In
order to make drivers as small as possible, there are a few calling
restrictions for this service. ConnectController() must
follow these calling restrictions. If any other agent wishes to call
Supported() it must also follow these calling restrictions.
@param[in] This The pointer to the driver binding protocol.
@param[in] ControllerHandle The handle of device to be tested.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to be started.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_UNSUPPORTED This driver does not support this device.
**/
EFI_STATUS
EFIAPI
PxeBcIp6DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
return PxeBcSupported (
This,
ControllerHandle,
RemainingDevicePath,
IP_VERSION_6
);
}
/**
Start this driver on ControllerHandle. This service is called by the
EFI boot service ConnectController(). In order to make
drivers as small as possible, there are a few calling restrictions for
this service. ConnectController() must follow these
calling restrictions. If any other agent wishes to call Start() it
must also follow these calling restrictions.
@param[in] This The pointer to the driver binding protocol.
@param[in] ControllerHandle The handle of device to be started.
@param[in] RemainingDevicePath Optional parameter used to pick a specific child
device to be started.
@retval EFI_SUCCESS This driver is installed to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
PxeBcIp6DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
return PxeBcStart (
This,
ControllerHandle,
RemainingDevicePath,
IP_VERSION_6
);
}
/**
Stop this driver on ControllerHandle. This service is called by the
EFI boot service DisconnectController(). In order to
make drivers as small as possible, there are a few calling
restrictions for this service. DisconnectController()
must follow these calling restrictions. If any other agent wishes
to call Stop() it must also follow these calling restrictions.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
children is zero stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCESS This driver is removed ControllerHandle
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval Others This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
PxeBcIp6DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
return PxeBcStop (
This,
ControllerHandle,
NumberOfChildren,
ChildHandleBuffer,
IP_VERSION_6
);
}