1351 lines
42 KiB
C
1351 lines
42 KiB
C
// @file
|
|
//;******************************************************************************
|
|
//;* Copyright (c) 1983-2021, Insyde Software Corp. All Rights Reserved.
|
|
//;*
|
|
//;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
//;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
//;* any part of this publication in any form, by any means, without the prior
|
|
//;* written permission of Insyde Software Corporation.
|
|
//;*
|
|
//;******************************************************************************
|
|
//;
|
|
|
|
|
|
#include "PxeDummy.h"
|
|
#include "DummyFunction.h"
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/UefiDriverEntryPoint.h>
|
|
#include <Library/InsydeNetworkLib.h>
|
|
#include <Library/NetLib.h>
|
|
#include <Guid/BdsHii.h>
|
|
|
|
EFI_GUID gEfiIp6CallerIdGuid = {0x5BEDB5CC, 0xD830, 0x4eb2, {0x87, 0x42, 0x2D, 0x4C, 0xC9, 0xB5, 0x4F, 0x2C}};
|
|
EFI_GUID gEfiNicIp4ConfigVariableGuid = {0xd8944553, 0xc4dd, 0x41f4, {0x9b, 0x30, 0xe1, 0x39, 0x7c, 0xfb, 0x26, 0x7b}};
|
|
|
|
DRIVER_INSTANCE *gDriverInstance;
|
|
NETWORK_LOCKER_PROTOCOL *gNetworkLocker;
|
|
NETWORK_STACK_CALLBACK gOldNetworkLockerCallback;
|
|
|
|
EFI_STATUS
|
|
CheckMacDevicePathValidation (
|
|
EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_DEVICE_PATH_PROTOCOL *TmpDPPtr;
|
|
MAC_ADDR_DEVICE_PATH *MacDP;
|
|
|
|
Status = EFI_UNSUPPORTED;
|
|
MacDP = NULL;
|
|
TmpDPPtr = UndiDevicePath;
|
|
while (!IsDevicePathEnd (TmpDPPtr)) {
|
|
if ((DevicePathType (TmpDPPtr) == MESSAGING_DEVICE_PATH) &&
|
|
(DevicePathSubType (TmpDPPtr) == MSG_MAC_ADDR_DP)) {
|
|
MacDP = (MAC_ADDR_DEVICE_PATH *)TmpDPPtr;
|
|
if (((MAC_ADDR_DEVICE_PATH *)TmpDPPtr)->IfType == 0x01 || ((MAC_ADDR_DEVICE_PATH *)TmpDPPtr)->IfType == 0x00) {
|
|
Status = EFI_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
TmpDPPtr = NextDevicePathNode (TmpDPPtr);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
BOOLEAN
|
|
CheckVlanConfigurationVariableExist (
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
BOOLEAN ReturnStatus;
|
|
UINTN VariableNameSize;
|
|
CHAR16 *VariableName;
|
|
UINTN BufferSize;
|
|
EFI_GUID SearchVariableNameGuid;
|
|
|
|
BufferSize = sizeof (CHAR16) * VARIAB_NAME_BUFFER_LENGTH;
|
|
VariableName = AllocateZeroPool (BufferSize);
|
|
if (VariableName == NULL) {
|
|
return TRUE;
|
|
}
|
|
ReturnStatus = FALSE;
|
|
ZeroMem (&SearchVariableNameGuid, sizeof (EFI_GUID));
|
|
while (TRUE) {
|
|
VariableNameSize = BufferSize;
|
|
Status = gRT->GetNextVariableName (&VariableNameSize, VariableName, &SearchVariableNameGuid);
|
|
if (Status == EFI_BUFFER_TOO_SMALL) {
|
|
VariableName = ReallocatePool (BufferSize, VariableNameSize, VariableName);
|
|
if (VariableName == NULL) {
|
|
ReturnStatus = TRUE;
|
|
goto FUNCTION_EXIT;
|
|
}
|
|
BufferSize = VariableNameSize;
|
|
Status = gRT->GetNextVariableName (&VariableNameSize, VariableName, &SearchVariableNameGuid);
|
|
}
|
|
if (EFI_ERROR (Status)) {
|
|
break;
|
|
}
|
|
if (!CompareGuid (&SearchVariableNameGuid, &gEfiVlanConfigProtocolGuid)) {
|
|
continue;
|
|
}
|
|
ReturnStatus = TRUE;
|
|
break;
|
|
}
|
|
FUNCTION_EXIT:
|
|
if (VariableName != NULL) {
|
|
FreePool (VariableName);
|
|
}
|
|
return ReturnStatus;
|
|
}
|
|
|
|
UINTN
|
|
FindSameBytesOfMem (
|
|
VOID *Mem1,
|
|
UINTN Mem1Len,
|
|
VOID *Mem2,
|
|
UINTN Mem2Len
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN SameBytes;
|
|
UINT8 *Ptr1;
|
|
UINT8 *Ptr2;
|
|
|
|
Ptr1 = Mem1;
|
|
Ptr2 = Mem2;
|
|
SameBytes = 0;
|
|
for (Index = 0; (Index < Mem1Len) && (Index < Mem2Len); Index++) {
|
|
if (Ptr1[Index] != Ptr2[Index]) {
|
|
return SameBytes;
|
|
}
|
|
SameBytes++;
|
|
}
|
|
return SameBytes;
|
|
}
|
|
|
|
VOID
|
|
DummyIpInstallFakeVlanConfig (
|
|
COMMON_INSTANCE *DummyInstance
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DUMMY_IP_INSTANCE *DummyIpInstance;
|
|
|
|
DummyIpInstance = &(DummyInstance->Ip);
|
|
DummyIpInstance->VlanConfig.VlanConfig.Set = PxeDummyDxeVlanConfigSet;
|
|
DummyIpInstance->VlanConfig.VlanConfig.Find = PxeDummyDxeVlanConfigFind;
|
|
DummyIpInstance->VlanConfig.VlanConfig.Remove = PxeDummyDxeVlanConfigRemove;
|
|
DummyIpInstance->VlanConfig.Instance = DummyInstance;
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&DummyInstance->UndiHandle,
|
|
&gEfiVlanConfigProtocolGuid,
|
|
&(DummyIpInstance->VlanConfig.VlanConfig),
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
VOID
|
|
DummyIpUninstallFakeVlanConfig (
|
|
COMMON_INSTANCE *DummyInstance
|
|
)
|
|
{
|
|
DUMMY_IP_INSTANCE *DummyIpInstance;
|
|
|
|
DummyIpInstance = &(DummyInstance->Ip);
|
|
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
DummyInstance->UndiHandle,
|
|
&gEfiVlanConfigProtocolGuid,
|
|
&(DummyIpInstance->VlanConfig.VlanConfig),
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
VOID
|
|
DummyIpInstallFakeMnp (
|
|
EFI_EVENT Event,
|
|
VOID *Context
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
COMMON_INSTANCE *DummyInstance;
|
|
DUMMY_IP_INSTANCE *DummyIpInstance;
|
|
FAKE_MNP_SB_INSATNCE *MnpSB;
|
|
|
|
DummyInstance = Context;
|
|
DummyIpInstance = &(DummyInstance->Ip);
|
|
MnpSB = &(DummyIpInstance->MnpSB);
|
|
|
|
gBS->CloseEvent (Event);
|
|
DummyIpInstance->MnpSB.ReadyToBootEvent = NULL;
|
|
MnpSB->Enabled = TRUE;
|
|
|
|
DummyIpInstance->MnpSB.MnpSB.CreateChild = FakeMnpCreateChild;
|
|
DummyIpInstance->MnpSB.MnpSB.DestroyChild = FakeMnpDestroyChild;
|
|
DummyIpInstance->MnpSB.Instance = DummyInstance;
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&DummyInstance->UndiHandle,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->MnpSB.MnpSB),
|
|
NULL
|
|
);
|
|
//
|
|
// Construct device path node for EFI HII Config Access protocol,
|
|
// which consists of controller physical device path and one hardware
|
|
// vendor guid node.
|
|
//
|
|
ZeroMem (&(MnpSB->Ip4VendorDeviceNode), sizeof (VENDOR_DEVICE_PATH));
|
|
MnpSB->Ip4VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH;
|
|
MnpSB->Ip4VendorDeviceNode.Header.SubType = HW_VENDOR_DP;
|
|
|
|
CopyGuid (&(MnpSB->Ip4VendorDeviceNode.Guid), &gEfiCallerIdGuid);
|
|
|
|
SetDevicePathNodeLength (&(MnpSB->Ip4VendorDeviceNode.Header), sizeof (VENDOR_DEVICE_PATH));
|
|
|
|
MnpSB->Ip4HiiVendorDevicePath = AppendDevicePathNode (
|
|
DummyInstance->UndiDevicePath,
|
|
(EFI_DEVICE_PATH_PROTOCOL *) &(MnpSB->Ip4VendorDeviceNode)
|
|
);
|
|
|
|
MnpSB->Ip4ChildHandle = NULL;
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&(MnpSB->Ip4ChildHandle),
|
|
&gEfiDevicePathProtocolGuid,
|
|
MnpSB->Ip4HiiVendorDevicePath,
|
|
NULL
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = gBS->OpenProtocol (
|
|
DummyInstance->UndiHandle,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
(VOID **) &(MnpSB->MnpSb),
|
|
DummyInstance->ImageHandle,
|
|
MnpSB->Ip4ChildHandle,
|
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
|
);
|
|
}
|
|
|
|
DummyIpInstallFakeVlanConfig (DummyInstance);
|
|
}
|
|
|
|
EFI_STATUS
|
|
DummyIpUninstallFakeMnp (
|
|
COMMON_INSTANCE *DummyInstance
|
|
)
|
|
{
|
|
DUMMY_IP_INSTANCE *DummyIpInstance;
|
|
FAKE_MNP_SB_INSATNCE *MnpSB;
|
|
|
|
DummyIpInstance = &(DummyInstance->Ip);
|
|
MnpSB = &(DummyIpInstance->MnpSB);
|
|
|
|
//
|
|
// ReadyToBoot event should be close, to avoid it will be called after PxeDummy was be disconnected.
|
|
//
|
|
if (DummyIpInstance->MnpSB.ReadyToBootEvent != NULL) {
|
|
gBS->CloseEvent (DummyIpInstance->MnpSB.ReadyToBootEvent);
|
|
DummyIpInstance->MnpSB.ReadyToBootEvent = NULL;
|
|
}
|
|
|
|
if (!MnpSB->Enabled) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
gBS->CloseProtocol (
|
|
DummyInstance->UndiHandle,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
DummyInstance->ImageHandle,
|
|
MnpSB->Ip4ChildHandle
|
|
);
|
|
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
DummyInstance->UndiHandle,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->MnpSB.MnpSB),
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
(MnpSB->Ip4ChildHandle),
|
|
&gEfiDevicePathProtocolGuid,
|
|
MnpSB->Ip4HiiVendorDevicePath,
|
|
NULL
|
|
);
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
DummyIpCreateFakeHandle (
|
|
COMMON_INSTANCE *DummyInstance,
|
|
UINTN IpCapability
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DUMMY_IP_INSTANCE *DummyIpInstance;
|
|
|
|
DummyIpInstance = &(DummyInstance->Ip);
|
|
if (IpCapability == PXE_IPv4) {
|
|
DummyIpInstance->Ip4SB.Ip4SB.CreateChild = FakeIp4CreateChild;
|
|
DummyIpInstance->Ip4SB.Ip4SB.DestroyChild = FakeIp4DestroyChild;
|
|
DummyIpInstance->Ip4SB.Instance = DummyInstance;
|
|
|
|
DummyIpInstance->Dhcp4SB.Dhcp4SB.CreateChild = FakeDhcp4CreateChild;
|
|
DummyIpInstance->Dhcp4SB.Dhcp4SB.DestroyChild = FakeDhcp4DestroyChild;
|
|
DummyIpInstance->Dhcp4SB.Instance = DummyInstance;
|
|
|
|
DummyIpInstance->Ip4Config.Ip4Config.GetData = FakeIp4ConfigGetData;
|
|
DummyIpInstance->Ip4Config.Ip4Config.Start = FakeIp4ConfigStart;
|
|
DummyIpInstance->Ip4Config.Ip4Config.Stop = FakeIp4ConfigStop;
|
|
DummyIpInstance->Ip4Config.Instance = DummyInstance;
|
|
|
|
DummyIpInstance->Ip4Config2.Ip4Config2.SetData = FakeIp4Config2SetData;
|
|
DummyIpInstance->Ip4Config2.Ip4Config2.GetData = FakeIp4Config2GetData;
|
|
DummyIpInstance->Ip4Config2.Ip4Config2.RegisterDataNotify = FakeIp4Config2RegisterDataNotify;
|
|
DummyIpInstance->Ip4Config2.Ip4Config2.UnregisterDataNotify = FakeIp4Config2UnregisterDataNotify;
|
|
DummyIpInstance->Ip4Config2.Instance = DummyInstance;
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&DummyInstance->UndiHandle,
|
|
&gEfiIp4ServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->Ip4SB.Ip4SB),
|
|
&gEfiDhcp4ServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->Dhcp4SB.Dhcp4SB),
|
|
&gEfiIp4ConfigProtocolGuid,
|
|
&(DummyIpInstance->Ip4Config.Ip4Config),
|
|
&gEfiIp4Config2ProtocolGuid,
|
|
&(DummyIpInstance->Ip4Config2.Ip4Config2),
|
|
NULL
|
|
);
|
|
|
|
} else if (IpCapability == PXE_IPv6) {
|
|
DummyIpInstance->Ip6SB.Ip6SB.CreateChild = FakeIp6CreateChild;
|
|
DummyIpInstance->Ip6SB.Ip6SB.DestroyChild = FakeIp6DestroyChild;
|
|
DummyIpInstance->Ip6SB.Instance = DummyInstance;
|
|
DummyIpInstance->Dhcp6SB.Dhcp6SB.CreateChild = FakeDhcp6CreateChild;
|
|
DummyIpInstance->Dhcp6SB.Dhcp6SB.DestroyChild = FakeDhcp6DestroyChild;
|
|
DummyIpInstance->Dhcp6SB.Instance = DummyInstance;
|
|
DummyIpInstance->Ip6Config.Ip6Config.SetData = FakeIp6ConfigSetData;
|
|
DummyIpInstance->Ip6Config.Ip6Config.GetData = FakeIp6ConfigGetData;
|
|
DummyIpInstance->Ip6Config.Ip6Config.RegisterDataNotify = FakeIp6ConfigRegisterDataNotify;
|
|
DummyIpInstance->Ip6Config.Ip6Config.UnregisterDataNotify = FakeIp6ConfigUnregisterDataNotify;
|
|
DummyIpInstance->Ip6Config.Instance = DummyInstance;
|
|
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&DummyInstance->UndiHandle,
|
|
&gEfiIp6ServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->Ip6SB.Ip6SB),
|
|
&gEfiDhcp6ServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->Dhcp6SB.Dhcp6SB),
|
|
&gEfiIp6ConfigProtocolGuid,
|
|
&(DummyIpInstance->Ip6Config.Ip6Config),
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
} else if (IpCapability == PXE_MNP) {
|
|
Status = gBS->CreateEventEx (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
DummyIpInstallFakeMnp,
|
|
DummyInstance,
|
|
&gEfiEventReadyToBootGuid,
|
|
&(DummyIpInstance->MnpSB.ReadyToBootEvent)
|
|
);
|
|
|
|
} else {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
DummyIpDestroyFakeHandle (
|
|
COMMON_INSTANCE *DummyInstance,
|
|
UINTN IpCapability
|
|
)
|
|
{
|
|
DUMMY_IP_INSTANCE *DummyIpInstance;
|
|
|
|
DummyIpInstance = &(DummyInstance->Ip);
|
|
if (IpCapability == PXE_IPv4) {
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
DummyInstance->UndiHandle,
|
|
&gEfiIp4ServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->Ip4SB.Ip4SB),
|
|
&gEfiDhcp4ServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->Dhcp4SB.Dhcp4SB),
|
|
&gEfiIp4ConfigProtocolGuid,
|
|
&(DummyIpInstance->Ip4Config.Ip4Config),
|
|
&gEfiIp4Config2ProtocolGuid,
|
|
&(DummyIpInstance->Ip4Config2.Ip4Config2),
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
} else if (IpCapability == PXE_IPv6) {
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
DummyInstance->UndiHandle,
|
|
&gEfiIp6ServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->Ip6SB.Ip6SB),
|
|
&gEfiDhcp6ServiceBindingProtocolGuid,
|
|
&(DummyIpInstance->Dhcp6SB.Dhcp6SB),
|
|
&gEfiIp6ConfigProtocolGuid,
|
|
&(DummyIpInstance->Ip6Config.Ip6Config),
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
} else {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
DummyPxeCreateFakeHandle (
|
|
COMMON_INSTANCE *DummyInstance,
|
|
UINTN PxeCapability
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DUMMY_PXE_INSTANCE *DummyPxeInstance;
|
|
EFI_DEVICE_PATH *FakePxeDevicePath;
|
|
EFI_DEVICE_PATH *FakeHttpDevicePath;
|
|
EFI_HANDLE FakePxeHandle;
|
|
IPv4_DEVICE_PATH *Ip4Node;
|
|
IPv6_DEVICE_PATH *Ip6Node;
|
|
URI_DEVICE_PATH *UriNode;
|
|
FAKE_LOAD_FILE_INSTANCE *Instance;
|
|
|
|
EFI_LOAD_FILE FakeLoadFilePtr;
|
|
|
|
Ip4Node = NULL;
|
|
Ip6Node = NULL;
|
|
FakePxeDevicePath = NULL;
|
|
UriNode = NULL;
|
|
FakeHttpDevicePath = NULL;
|
|
DummyPxeInstance = &(DummyInstance->Pxe);
|
|
FakeLoadFilePtr = FakePxeLoadFile;
|
|
if ((PxeCapability == PXE_IPv4) || (PxeCapability == HTTP_IPv4)) {
|
|
//
|
|
// Create a device path node for Ipv4 virtual nic, and append it.
|
|
//
|
|
Ip4Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));
|
|
if (Ip4Node == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Ip4Node->Header.Type = MESSAGING_DEVICE_PATH;
|
|
Ip4Node->Header.SubType = MSG_IPv4_DP;
|
|
Ip4Node->StaticIpAddress = FALSE;
|
|
SetDevicePathNodeLength (&(Ip4Node->Header), sizeof (IPv4_DEVICE_PATH));
|
|
FakePxeDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ip4Node;
|
|
if (PxeCapability == PXE_IPv4) {
|
|
Instance = &(DummyPxeInstance->Ip4);
|
|
Instance->IsPxe = TRUE;
|
|
} else {
|
|
Instance = &(DummyPxeInstance->Http4);
|
|
Instance->IsHttp = TRUE;
|
|
FakeLoadFilePtr = FakeHttpLoadFile;
|
|
}
|
|
Instance->IsIpv4 = TRUE;
|
|
} else if ((PxeCapability == PXE_IPv6) || (PxeCapability == HTTP_IPv6)) {
|
|
//
|
|
// Create a device path node for Ipv6 virtual nic, and append it.
|
|
//
|
|
Ip6Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH));
|
|
if (Ip6Node == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
Ip6Node->Header.Type = MESSAGING_DEVICE_PATH;
|
|
Ip6Node->Header.SubType = MSG_IPv6_DP;
|
|
Ip6Node->PrefixLength = 64;
|
|
SetDevicePathNodeLength (&(Ip6Node->Header), sizeof (IPv6_DEVICE_PATH));
|
|
FakePxeDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ip6Node;
|
|
if (PxeCapability == PXE_IPv6) {
|
|
Instance = &(DummyPxeInstance->Ip6);
|
|
Instance->IsPxe = TRUE;
|
|
} else {
|
|
Instance = &(DummyPxeInstance->Http6);
|
|
Instance->IsHttp = TRUE;
|
|
FakeLoadFilePtr = FakeHttpLoadFile;
|
|
}
|
|
Instance->IsIpv6 = TRUE;
|
|
}else {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Prepare DevicePath to provide PXE handle.
|
|
//
|
|
FakePxeDevicePath = AppendDevicePathNode (DummyInstance->UndiDevicePath, FakePxeDevicePath);
|
|
if (FakePxeDevicePath == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
|
|
//
|
|
// Append URI DevicePath at tail of PXE DevicePath, It's a HTTP boot handle.
|
|
//
|
|
if ((PxeCapability == HTTP_IPv4) || (PxeCapability == HTTP_IPv6)) {
|
|
UriNode = AllocateZeroPool (sizeof (URI_DEVICE_PATH));
|
|
if (UriNode == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
UriNode->Header.Type = MESSAGING_DEVICE_PATH;
|
|
UriNode->Header.SubType = MSG_URI_DP;
|
|
SetDevicePathNodeLength (&(UriNode->Header), sizeof (URI_DEVICE_PATH));
|
|
FakeHttpDevicePath = AppendDevicePathNode (FakePxeDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) UriNode);
|
|
if (FakeHttpDevicePath == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
gBS->FreePool (FakePxeDevicePath);
|
|
FakePxeDevicePath = FakeHttpDevicePath;
|
|
FakeHttpDevicePath = NULL;
|
|
}
|
|
|
|
Instance->LoadFile.LoadFile = FakeLoadFilePtr;
|
|
Instance->PxeCapability = PxeCapability;
|
|
Instance->Instance = DummyInstance;
|
|
|
|
//
|
|
// Install the CallerId GUID to FakePxeHandle
|
|
//
|
|
FakePxeHandle = NULL;
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&FakePxeHandle,
|
|
&gEfiCallerIdGuid,
|
|
NULL,
|
|
&gEfiDevicePathProtocolGuid,
|
|
FakePxeDevicePath,
|
|
&gEfiLoadFileProtocolGuid,
|
|
&(Instance->LoadFile),
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ERROR;
|
|
}
|
|
Instance->FakePxeHandle = FakePxeHandle;
|
|
Instance->FakePxeDevicePath = FakePxeDevicePath;
|
|
Instance->Enable = TRUE;
|
|
|
|
ERROR:
|
|
if (EFI_ERROR (Status)) {
|
|
if (FakePxeDevicePath != NULL) {
|
|
gBS->FreePool (FakePxeDevicePath);
|
|
}
|
|
if (FakeHttpDevicePath != NULL) {
|
|
gBS->FreePool (FakeHttpDevicePath);
|
|
}
|
|
}
|
|
if (Ip4Node != NULL) {
|
|
gBS->FreePool (Ip4Node);
|
|
}
|
|
if (Ip6Node != NULL) {
|
|
gBS->FreePool (Ip6Node);
|
|
}
|
|
if (UriNode != NULL) {
|
|
gBS->FreePool (UriNode);
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
DummyPxeDestroyFakeHandle (
|
|
COMMON_INSTANCE *DummyInstance,
|
|
UINTN PxeCapability
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DUMMY_PXE_INSTANCE *DummyPxeInstance;
|
|
EFI_HANDLE FakePxeHandle;
|
|
FAKE_LOAD_FILE_INSTANCE *Instance;
|
|
VOID *ProtocolPointer;
|
|
|
|
DummyPxeInstance = &(DummyInstance->Pxe);
|
|
if ((PxeCapability == PXE_IPv4) || (PxeCapability == HTTP_IPv4)) {
|
|
if (PxeCapability == PXE_IPv4) {
|
|
Instance = &(DummyPxeInstance->Ip4);
|
|
} else {
|
|
Instance = &(DummyPxeInstance->Http4);
|
|
}
|
|
} else if ((PxeCapability == PXE_IPv6) || (PxeCapability == HTTP_IPv6)) {
|
|
if (PxeCapability == PXE_IPv6) {
|
|
Instance = &(DummyPxeInstance->Ip6);
|
|
} else {
|
|
Instance = &(DummyPxeInstance->Http6);
|
|
}
|
|
}else {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Instance->Instance->DeviceConnected) {
|
|
Status = gBS->OpenProtocol (
|
|
Instance->FakePxeHandle,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
(VOID **) &ProtocolPointer,
|
|
Instance->Instance->ImageHandle,
|
|
Instance->FakePxeHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
gBS->CloseProtocol (
|
|
Instance->FakePxeHandle,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
Instance->Instance->ImageHandle,
|
|
Instance->FakePxeHandle
|
|
);
|
|
|
|
gBS->UninstallProtocolInterface (
|
|
Instance->FakePxeHandle,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
ProtocolPointer
|
|
);
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
Instance->FakePxeHandle,
|
|
&gEfiPxeBaseCodeProtocolGuid,
|
|
(VOID **) &ProtocolPointer
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
gBS->UninstallProtocolInterface (
|
|
Instance->FakePxeHandle,
|
|
&gEfiPxeBaseCodeProtocolGuid,
|
|
ProtocolPointer
|
|
);
|
|
}
|
|
|
|
//
|
|
// Try to find PxeBaseCode protocol from real handle and uninstall it.
|
|
//
|
|
if (Instance->RealPxeHandle != NULL) {
|
|
Status = gBS->HandleProtocol (
|
|
Instance->RealPxeHandle,
|
|
&gEfiPxeBaseCodeProtocolGuid,
|
|
(VOID **) &ProtocolPointer
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
gBS->UninstallProtocolInterface (
|
|
Instance->RealPxeHandle,
|
|
&gEfiPxeBaseCodeProtocolGuid,
|
|
ProtocolPointer
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DummyInstance->RealMnpSb != NULL) {
|
|
gBS->CloseProtocol (
|
|
DummyInstance->UndiHandle,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
DummyInstance->ImageHandle,
|
|
Instance->FakePxeHandle
|
|
);
|
|
DummyInstance->RealMnpSb = NULL;
|
|
}
|
|
|
|
//
|
|
// Uninstall the Dns Protocol onto ControlerHandle
|
|
//
|
|
FakePxeHandle = NULL;
|
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
|
Instance->FakePxeHandle,
|
|
&gEfiCallerIdGuid,
|
|
NULL,
|
|
&gEfiDevicePathProtocolGuid,
|
|
Instance->FakePxeDevicePath,
|
|
&gEfiLoadFileProtocolGuid,
|
|
&(Instance->LoadFile),
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (Instance->FakePxeDevicePath != NULL) {
|
|
FreePool (Instance->FakePxeDevicePath);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
EFI_STATUS
|
|
DummyPxeDestroyServices (
|
|
DRIVER_INSTANCE *Instance,
|
|
EFI_HANDLE ControllerHandle
|
|
)
|
|
{
|
|
UINTN Index;
|
|
COMMON_INSTANCE *DummyInstance;
|
|
|
|
//
|
|
// Find the connected device handle, It will be destroy if handle is the same.
|
|
//
|
|
DummyInstance = NULL;
|
|
for (Index = 0; Index < Instance->BindedCount; Index ++) {
|
|
if ((Instance->BindedList[Index] == NULL) ||
|
|
(Instance->BindedList[Index]->UndiHandle!= ControllerHandle)) {
|
|
continue;
|
|
}
|
|
DummyInstance = Instance->BindedList[Index];
|
|
Instance->BindedList[Index] = NULL;
|
|
break;
|
|
}
|
|
|
|
if (DummyInstance == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
gBS->CloseProtocol (
|
|
ControllerHandle,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
DummyInstance->ImageHandle,
|
|
ControllerHandle
|
|
);
|
|
|
|
//
|
|
// Install Fake LoadFile Protocol as boot entry.
|
|
//
|
|
if (Instance->IsPxeIpv4Enabled) {
|
|
DummyPxeDestroyFakeHandle (DummyInstance, PXE_IPv4);
|
|
}
|
|
|
|
if (Instance->IsPxeIpv6Enabled) {
|
|
DummyPxeDestroyFakeHandle (DummyInstance, PXE_IPv6);
|
|
}
|
|
|
|
if (Instance->IsHttpIpv4Enabled) {
|
|
DummyPxeDestroyFakeHandle (DummyInstance, HTTP_IPv4);
|
|
}
|
|
|
|
if (Instance->IsHttpIpv6Enabled) {
|
|
DummyPxeDestroyFakeHandle (DummyInstance, HTTP_IPv6);
|
|
}
|
|
|
|
//
|
|
// Install Fake IP Protocol for Network stack services
|
|
//
|
|
if (Instance->IsIpv4Enabled | Instance->IsIpv6Enabled) {
|
|
DummyIpUninstallFakeMnp (DummyInstance);
|
|
DummyIpUninstallFakeVlanConfig (DummyInstance);
|
|
|
|
if (Instance->IsIpv4Enabled) {
|
|
DummyIpDestroyFakeHandle (DummyInstance, PXE_IPv4);
|
|
}
|
|
if (Instance->IsIpv6Enabled) {
|
|
DummyIpDestroyFakeHandle (DummyInstance, PXE_IPv6);
|
|
}
|
|
}
|
|
FreePool (DummyInstance);
|
|
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 Protocol instance pointer.
|
|
@param[in] ControllerHandle Handle of device to test
|
|
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
|
device to start.
|
|
|
|
@retval EFI_SUCCESS This driver supports this device
|
|
@retval EFI_ALREADY_STARTED This driver is already running on this device
|
|
@retval other This driver does not support this device
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DummyPxeDriverBindingSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
|
|
|
|
if (gNetworkLocker == NULL) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
(VOID **) &Snp,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
gBS->CloseProtocol (
|
|
ControllerHandle,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
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 Protocol instance pointer.
|
|
@param[in] ControllerHandle Handle of device to bind driver to
|
|
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
|
|
device to start.
|
|
|
|
@retval EFI_SUCCESS This driver is added 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
|
|
DummyPxeDriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE UndiDeviceHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DRIVER_INSTANCE *Instance;
|
|
COMMON_INSTANCE *DummyInstance;
|
|
COMMON_INSTANCE **BindedList;
|
|
EFI_DEVICE_PATH *UndiDevicePath;
|
|
VOID *BindingPoint;
|
|
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
|
|
NETWORK_LOCKER_PROTOCOL *ControllerNetworkPolicy;
|
|
|
|
if (gNetworkLocker == NULL) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
ControllerNetworkPolicy = NULL;
|
|
Status = gBS->HandleProtocol (
|
|
UndiDeviceHandle,
|
|
&gNetworkLockerProtocolGuid,
|
|
(VOID **) &ControllerNetworkPolicy
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
/// If policy override, PxeDummyDxe will not handle this network device.
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
Status = gBS->OpenProtocol (
|
|
UndiDeviceHandle,
|
|
&gEfiCallerIdGuid,
|
|
NULL,
|
|
UndiDeviceHandle,
|
|
UndiDeviceHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
if (!EFI_ERROR (Status)) {
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
Status = gBS->OpenProtocol (
|
|
UndiDeviceHandle,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
(VOID **) &Snp,
|
|
This->DriverBindingHandle,
|
|
UndiDeviceHandle,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
DummyInstance = NULL;
|
|
Instance = DUMMY_PXE_INSTANCE_FROM_THIS (This);
|
|
if (Instance->Signature != DUMMY_PXE_DRIVER_INSTANCE_SIGNATURE) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Status = gBS->HandleProtocol (
|
|
UndiDeviceHandle,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &UndiDevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Check Device Path MAC IfType, if it's unable to handle, this device will be skip.
|
|
//
|
|
Status = CheckMacDevicePathValidation (UndiDevicePath);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
DummyInstance = AllocateZeroPool (sizeof (COMMON_INSTANCE));
|
|
if (DummyInstance == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
DummyInstance->Signature = DUMMY_PXE_INSTANCE_SIGNATURE;
|
|
DummyInstance->ImageHandle = Instance->ImageHandle;
|
|
DummyInstance->UndiHandle = UndiDeviceHandle;
|
|
DummyInstance->UndiDevicePath = UndiDevicePath;
|
|
DummyInstance->Interface = This;
|
|
|
|
//
|
|
// Install Fake LoadFile Protocol as boot entry.
|
|
//
|
|
if (Instance->IsPxeIpv4Enabled) {
|
|
Status = DummyPxeCreateFakeHandle (DummyInstance, PXE_IPv4);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
}
|
|
|
|
if (Instance->IsPxeIpv6Enabled) {
|
|
Status = DummyPxeCreateFakeHandle (DummyInstance, PXE_IPv6);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
}
|
|
|
|
if (Instance->IsHttpIpv4Enabled) {
|
|
Status = DummyPxeCreateFakeHandle (DummyInstance, HTTP_IPv4);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
}
|
|
|
|
if (Instance->IsHttpIpv6Enabled) {
|
|
Status = DummyPxeCreateFakeHandle (DummyInstance, HTTP_IPv6);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Install Fake IP Protocol for Network stack services
|
|
//
|
|
if (Instance->IsIpv4Enabled | Instance->IsIpv6Enabled) {
|
|
Status = DummyIpCreateFakeHandle (DummyInstance, PXE_MNP);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
if (Instance->IsIpv4Enabled) {
|
|
Status = DummyIpCreateFakeHandle (DummyInstance, PXE_IPv4);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
}
|
|
if (Instance->IsIpv6Enabled) {
|
|
Status = DummyIpCreateFakeHandle (DummyInstance, PXE_IPv6);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Install trap for device manager
|
|
//
|
|
if (gOldNewPackFunction == NULL) {
|
|
Status = gBS->LocateProtocol (&gEfiHiiDatabaseProtocolGuid, NULL, (VOID **) &(gHiiDataBaseProtocol));
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
gOldNewPackFunction = gHiiDataBaseProtocol->NewPackageList;
|
|
gHiiDataBaseProtocol->NewPackageList = FakeHiiDatabaseNewList;
|
|
}
|
|
|
|
//
|
|
// Record HANDLE address in instance.
|
|
//
|
|
BindedList = AllocateZeroPool (sizeof (COMMON_INSTANCE *) * (Instance->BindedCount + 1));
|
|
if (BindedList == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
BindedList[0] = (VOID *) DummyInstance;
|
|
if (Instance->BindedCount != 0) {
|
|
CopyMem ((BindedList + 1), Instance->BindedList, Instance->BindedCount * sizeof (COMMON_INSTANCE *));
|
|
gBS->FreePool (Instance->BindedList);
|
|
}
|
|
Instance->BindedList = BindedList;
|
|
Instance->BindedCount++;
|
|
|
|
Status = gBS->InstallProtocolInterface (
|
|
&UndiDeviceHandle,
|
|
&gEfiCallerIdGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
NULL
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Install CallerId and open it, to wait stop notify when disconnect processing.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
UndiDeviceHandle,
|
|
&gEfiCallerIdGuid,
|
|
&BindingPoint,
|
|
This->DriverBindingHandle,
|
|
UndiDeviceHandle,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
|
|
ON_ERROR:
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->CloseProtocol (
|
|
UndiDeviceHandle,
|
|
&gEfiSimpleNetworkProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
UndiDeviceHandle
|
|
);
|
|
if (DummyInstance != NULL) {
|
|
gBS->FreePool (DummyInstance);
|
|
}
|
|
}
|
|
|
|
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 is removed ControllerHandle
|
|
@retval other This driver was not removed from this device
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
DummyPxeDriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
DRIVER_INSTANCE *Instance;
|
|
|
|
Instance = DUMMY_PXE_INSTANCE_FROM_THIS (This);
|
|
if (Instance->Signature != DUMMY_PXE_DRIVER_INSTANCE_SIGNATURE) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
gBS->CloseProtocol (
|
|
ControllerHandle,
|
|
&gEfiCallerIdGuid,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle
|
|
);
|
|
|
|
//
|
|
// Disconnect ControllerHandle if it exist in binded device list.
|
|
//
|
|
Status = DummyPxeDestroyServices (Instance, ControllerHandle);
|
|
gBS->UninstallProtocolInterface (
|
|
ControllerHandle,
|
|
&gEfiCallerIdGuid,
|
|
NULL
|
|
);
|
|
gNetworkLocker->NetworkStackCallback = gOldNetworkLockerCallback;
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
This function returns whether the network stack is currently locked enabled(TRUE) for
|
|
the specified device or disabled (FALSE) for the specified device(s).
|
|
|
|
This function will scan and report the status of disabled devices.
|
|
If user wants to know the status of a specific on the specific device, use DeviceHandle to specify it.
|
|
|
|
For instance -
|
|
Device Status:
|
|
Device A - Enabled
|
|
Device B - Disabled
|
|
Device C - Enabled
|
|
|
|
Reported Status:
|
|
DeviceHandle A is specified - TRUE is returned.
|
|
DeviceHandle B is specified - FALSE is returned.
|
|
DeviceHandle C is specified - TRUE is returned.
|
|
If not specified (NULL), then this scenario will report TRUE (because Device A and Device C are enabled).
|
|
|
|
@param[in] DeviceHandle Handle that specifies the device to enable or disable.
|
|
If NULL, then it will report whether any device is enabled.
|
|
|
|
@retval TRUE Device(s) is enabled.
|
|
@retval FALSE Device(s) is disabled.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
NetworkConfigIsEnabled (
|
|
IN EFI_HANDLE DeviceHandle OPTIONAL
|
|
)
|
|
{
|
|
UINTN Index;
|
|
COMMON_INSTANCE *DeviceCommonInstance;
|
|
|
|
if (gDriverInstance->BindedCount == 0) {
|
|
return FALSE;
|
|
}
|
|
|
|
for (Index = 0; Index < gDriverInstance->BindedCount; Index++) {
|
|
if (gDriverInstance->BindedList[Index] == NULL) {
|
|
continue;
|
|
}
|
|
DeviceCommonInstance = gDriverInstance->BindedList[Index];
|
|
if (DeviceHandle != NULL) {
|
|
//
|
|
// User select the specific network device by DeviceHandle.
|
|
//
|
|
if (DeviceCommonInstance->UndiHandle != DeviceHandle) {
|
|
continue;
|
|
}
|
|
//
|
|
// Return the device connected status.
|
|
//
|
|
return DeviceCommonInstance->DeviceConnected;
|
|
}
|
|
|
|
if (!DeviceCommonInstance->DeviceConnected) {
|
|
continue;
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
This function will enable the device and bind the network protocols to the device.
|
|
If user wants to specify specific devices, use DeviceHandle.
|
|
|
|
@param[in] DeviceHandle Handle that specifies the device to enable or disable.
|
|
If NULL, then it will enable all devices.
|
|
|
|
@retval EFI_SUCCESS This function completed successfully.
|
|
@retval EFI_DEVICE_ERROR One or more network devices reported an error when enabled.
|
|
@retval EFI_ALREADY_STARTED The network stack was already enabled and cannot be disabled.
|
|
@retval EFI_UNSUPPORTED The network stack does not support configuration.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
NetworkConfigEnable (
|
|
EFI_HANDLE DeviceHandle OPTIONAL
|
|
)
|
|
{
|
|
UINTN Index;
|
|
COMMON_INSTANCE *DeviceCommonInstance;
|
|
|
|
if (gDriverInstance->BindedCount == 0) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
for (Index = 0; Index < gDriverInstance->BindedCount; Index++) {
|
|
//
|
|
// If device is already binded, skip it.
|
|
//
|
|
if (gDriverInstance->BindedList[Index] == NULL) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Find the specific device if user selected.
|
|
//
|
|
DeviceCommonInstance = gDriverInstance->BindedList[Index];
|
|
if (DeviceHandle != NULL) {
|
|
if (DeviceCommonInstance->UndiHandle != DeviceHandle) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
ConnectDevice (DeviceCommonInstance);
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PxeDummyUnload (
|
|
IN EFI_HANDLE ImageHandle
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (gDriverInstance == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (ImageHandle != gDriverInstance->ImageHandle) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
gBS->UninstallMultipleProtocolInterfaces (
|
|
ImageHandle,
|
|
&gEfiDhcp4ProtocolGuid,
|
|
(VOID **) &gDhcp4Dummy,
|
|
&gEfiDhcp6ProtocolGuid,
|
|
(VOID **) &gDhcp6Dummy,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
gNetworkLocker->NetworkStackCallback = gOldNetworkLockerCallback;
|
|
Status = NetLibDefaultUnload (ImageHandle);
|
|
|
|
if (gDriverInstance->BindedList != NULL) {
|
|
FreePool (gDriverInstance->BindedList);
|
|
gDriverInstance->BindedList = NULL;
|
|
}
|
|
|
|
if (gDriverInstance->ReadyToBootEventReleaseNetworkLocker != NULL) {
|
|
gBS->CloseEvent (gDriverInstance->ReadyToBootEventReleaseNetworkLocker);
|
|
}
|
|
|
|
if (gDriverInstance != NULL) {
|
|
FreePool (gDriverInstance);
|
|
gDriverInstance = NULL;
|
|
}
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
The Dummy PXE will hook network locker protocol to control network stack.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PxeDummyEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gBS->LocateProtocol (
|
|
&gNetworkLockerProtocolGuid,
|
|
NULL,
|
|
(VOID **) &gNetworkLocker
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// If MediaChanged, VLAN configuration is exist.
|
|
//
|
|
gDriverInstance = NULL;
|
|
if (CheckVlanConfigurationVariableExist ()) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
gDriverInstance = AllocateZeroPool (sizeof (DRIVER_INSTANCE));
|
|
if (gDriverInstance == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
if (!EFI_ERROR (gNetworkLocker->NetworkStackCallback (NetworkStackPxe4Callback))) {
|
|
gDriverInstance->IsPxeIpv4Enabled = TRUE;
|
|
}
|
|
if (!EFI_ERROR (gNetworkLocker->NetworkStackCallback (NetworkStackPxe6Callback))) {
|
|
gDriverInstance->IsPxeIpv6Enabled = TRUE;
|
|
}
|
|
if (!EFI_ERROR (gNetworkLocker->NetworkStackCallback (NetworkStackIp4Callback))) {
|
|
gDriverInstance->IsIpv4Enabled = TRUE;
|
|
}
|
|
if (!EFI_ERROR (gNetworkLocker->NetworkStackCallback (NetworkStackIp6Callback))) {
|
|
gDriverInstance->IsIpv6Enabled = TRUE;
|
|
}
|
|
if (!EFI_ERROR (gNetworkLocker->NetworkStackCallback (NetworkStackHttpBoot4Callback))) {
|
|
gDriverInstance->IsHttpIpv4Enabled = TRUE;
|
|
}
|
|
if (!EFI_ERROR (gNetworkLocker->NetworkStackCallback (NetworkStackHttpBoot6Callback))) {
|
|
gDriverInstance->IsHttpIpv6Enabled = TRUE;
|
|
}
|
|
|
|
gDriverInstance->Signature = DUMMY_PXE_DRIVER_INSTANCE_SIGNATURE;
|
|
gOldNetworkLockerCallback = gNetworkLocker->NetworkStackCallback;
|
|
gDriverInstance->ImageHandle = ImageHandle;
|
|
gDriverInstance->BindingProtocol.DriverBindingHandle = ImageHandle;
|
|
gDriverInstance->BindingProtocol.ImageHandle = ImageHandle;
|
|
gDriverInstance->BindingProtocol.Supported = DummyPxeDriverBindingSupported;
|
|
gDriverInstance->BindingProtocol.Start = DummyPxeDriverBindingStart;
|
|
gDriverInstance->BindingProtocol.Stop = DummyPxeDriverBindingStop;
|
|
/// This version should be higher then PxeDummyDxe's version in binding protocol.
|
|
gDriverInstance->BindingProtocol.Version = 0xAA;
|
|
|
|
gDriverInstance->NetworkConfig.IsEnabled = NetworkConfigIsEnabled;
|
|
gDriverInstance->NetworkConfig.Enable = NetworkConfigEnable;
|
|
|
|
gOldNewPackFunction = NULL;
|
|
gDeviceConnecting = FALSE;
|
|
|
|
// Install Fake DHCP4 and DHCP6 protocol.
|
|
gBS->InstallMultipleProtocolInterfaces (
|
|
&ImageHandle,
|
|
&gEfiDhcp4ProtocolGuid,
|
|
(VOID **) &gDhcp4Dummy,
|
|
&gEfiDhcp6ProtocolGuid,
|
|
(VOID **) &gDhcp6Dummy,
|
|
&gH2ONetworkConfigProtocolGuid,
|
|
(VOID **) &gDriverInstance->NetworkConfig,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
Status = gBS->InstallProtocolInterface (
|
|
&ImageHandle,
|
|
&gEfiDriverBindingProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&(gDriverInstance->BindingProtocol)
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
gBS->FreePool (gDriverInstance);
|
|
return Status;
|
|
}
|
|
gNetworkLocker->NetworkStackCallback = PxeNetworkStackCallback;
|
|
|
|
return Status;
|
|
}
|