/** @file | |
Driver Binding functions implementationfor for UefiPxeBc Driver. | |
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR> | |
Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR> | |
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 "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 | |
); | |
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 | |
); | |
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; | |
} | |
/** | |
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; | |
// | |
// 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. 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 | |
); | |
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; | |
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; | |
} | |
// | |
// Generate a random IAID for the Dhcp6 assigned address. | |
// | |
Private->IaId = NET_RANDOM (NetRandomInitSeed ()); | |
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; | |
// | |
// 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. 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 | |
); | |
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 avaiable flag and set default configure data for | |
// Udp6Read and Ip6 instance. | |
// | |
Private->Mode.Ipv6Available = TRUE; | |
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; | |
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)) { | |
gBS->UninstallMultipleProtocolInterfaces ( | |
ImageHandle, | |
&gEfiDriverBindingProtocolGuid, | |
&gPxeBcIp4DriverBinding, | |
&gEfiComponentName2ProtocolGuid, | |
&gPxeBcComponentName2, | |
&gEfiComponentNameProtocolGuid, | |
&gPxeBcComponentName, | |
NULL | |
); | |
} | |
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) { | |
DhcpServiceBindingGuid = &gEfiDhcp4ServiceBindingProtocolGuid; | |
MtftpServiceBindingGuid = &gEfiMtftp4ServiceBindingProtocolGuid; | |
} else { | |
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 | |
); | |
} |