mirror of https://github.com/acidanthera/audk.git
1465 lines
43 KiB
C
1465 lines
43 KiB
C
/** @file
|
|
Driver Binding functions implementationfor for UefiPxeBc Driver.
|
|
|
|
Copyright (c) 2007 - 2011, 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 gPxeBcDriverBinding = {
|
|
PxeBcDriverBindingSupported,
|
|
PxeBcDriverBindingStart,
|
|
PxeBcDriverBindingStop,
|
|
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;
|
|
|
|
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;
|
|
}
|
|
|
|
//
|
|
// 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
|
|
)
|
|
{
|
|
return EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&gPxeBcDriverBinding,
|
|
ImageHandle,
|
|
&gPxeBcComponentName,
|
|
&gPxeBcComponentName2
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
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
|
|
PxeBcDriverBindingSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Ip4Status;
|
|
EFI_STATUS Ip6Status;
|
|
|
|
//
|
|
// Try to open the Mtftp4 and Dhcp4 protocol to test whether IPv4 stack is ready.
|
|
//
|
|
Ip4Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiDhcp4ServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
if (!EFI_ERROR (Ip4Status)) {
|
|
Ip4Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiMtftp4ServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
}
|
|
|
|
//
|
|
// Try to open the Mtftp6 and Dhcp6 protocol to test whether IPv4 stack is ready.
|
|
//
|
|
Ip6Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiDhcp6ServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
if (!EFI_ERROR (Ip6Status)) {
|
|
Ip6Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiMtftp6ServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
}
|
|
|
|
//
|
|
// It's unsupported case if both stack are not ready.
|
|
//
|
|
if (EFI_ERROR (Ip4Status) && EFI_ERROR (Ip6Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
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
|
|
PxeBcDriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
PXEBC_PRIVATE_DATA *Private;
|
|
EFI_STATUS Status;
|
|
EFI_STATUS Ip4Status;
|
|
EFI_STATUS Ip6Status;
|
|
PXEBC_PRIVATE_PROTOCOL *Id;
|
|
|
|
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 {
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
//
|
|
// Try to create virtual NIC handle for IPv4.
|
|
//
|
|
Ip4Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);
|
|
|
|
//
|
|
// Try to create virtual NIC handle for IPv6.
|
|
//
|
|
Ip6Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);
|
|
|
|
if (EFI_ERROR (Ip4Status) && EFI_ERROR (Ip6Status)) {
|
|
//
|
|
// 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:
|
|
gBS->UninstallProtocolInterface (
|
|
ControllerHandle,
|
|
&gEfiCallerIdGuid,
|
|
&Private->Id
|
|
);
|
|
PxeBcDestroyIp4Children (This, Private);
|
|
PxeBcDestroyIp6Children (This, Private);
|
|
FreePool (Private);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
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 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
|
|
PxeBcDriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
)
|
|
{
|
|
PXEBC_PRIVATE_DATA *Private;
|
|
PXEBC_VIRTUAL_NIC *VirtualNic;
|
|
EFI_LOAD_FILE_PROTOCOL *LoadFile;
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE NicHandle;
|
|
BOOLEAN IsIpv6;
|
|
PXEBC_PRIVATE_PROTOCOL *Id;
|
|
|
|
Private = NULL;
|
|
NicHandle = NULL;
|
|
VirtualNic = NULL;
|
|
LoadFile = NULL;
|
|
Id = NULL;
|
|
IsIpv6 = FALSE;
|
|
|
|
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.
|
|
//
|
|
NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);
|
|
if (NicHandle == NULL) {
|
|
NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);
|
|
if (NicHandle == NULL) {
|
|
return EFI_DEVICE_ERROR;
|
|
} else {
|
|
IsIpv6 = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
|
|
if (Private->Ip6Nic == VirtualNic) {
|
|
IsIpv6 = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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 && !IsIpv6) {
|
|
PxeBcDestroyIp4Children (This, Private);
|
|
}
|
|
|
|
if (Private->Ip6Nic != NULL && IsIpv6) {
|
|
PxeBcDestroyIp6Children (This, Private);
|
|
}
|
|
|
|
if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {
|
|
gBS->UninstallProtocolInterface (
|
|
NicHandle,
|
|
&gEfiCallerIdGuid,
|
|
&Private->Id
|
|
);
|
|
FreePool (Private);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|