mirror of https://github.com/acidanthera/audk.git
495 lines
13 KiB
C
495 lines
13 KiB
C
/** @file
|
|
The driver binding for IP4 CONFIG protocol.
|
|
|
|
Copyright (c) 2006 - 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<BR>
|
|
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 "Ip4Config.h"
|
|
#include "Ip4ConfigNv.h"
|
|
#include "NicIp4Variable.h"
|
|
|
|
EFI_DRIVER_BINDING_PROTOCOL gIp4ConfigDriverBinding = {
|
|
Ip4ConfigDriverBindingSupported,
|
|
Ip4ConfigDriverBindingStart,
|
|
Ip4ConfigDriverBindingStop,
|
|
0xa,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
//
|
|
// The intance of template of IP4 Config private data
|
|
//
|
|
IP4_CONFIG_INSTANCE mIp4ConfigTemplate = {
|
|
IP4_CONFIG_INSTANCE_SIGNATURE,
|
|
NULL,
|
|
NULL,
|
|
(EFI_DEVICE_PATH_PROTOCOL *) NULL,
|
|
{
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
},
|
|
{
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
},
|
|
NULL,
|
|
(EFI_DEVICE_PATH_PROTOCOL *) NULL,
|
|
NULL,
|
|
{
|
|
FALSE,
|
|
FALSE,
|
|
{
|
|
0
|
|
},
|
|
{
|
|
0
|
|
},
|
|
{
|
|
0
|
|
}
|
|
},
|
|
0,
|
|
(EFI_MANAGED_NETWORK_PROTOCOL *) NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
EFI_NOT_READY,
|
|
{
|
|
0,
|
|
0,
|
|
{
|
|
0
|
|
}
|
|
},
|
|
(CHAR16 *) NULL,
|
|
(NIC_IP4_CONFIG_INFO *) NULL,
|
|
(EFI_DHCP4_PROTOCOL *) NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
TRUE
|
|
};
|
|
|
|
/**
|
|
The entry point for IP4 config driver which install the driver
|
|
binding and component name protocol on its image.
|
|
|
|
@param ImageHandle The image handle of the driver.
|
|
@param SystemTable The system table.
|
|
|
|
@retval EFI_SUCCES All the related protocols are installed on the driver.
|
|
@retval Others Failed to install protocols.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Ip4ConfigDriverEntryPoint (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
return EfiLibInstallDriverBindingComponentName2 (
|
|
ImageHandle,
|
|
SystemTable,
|
|
&gIp4ConfigDriverBinding,
|
|
ImageHandle,
|
|
&gIp4ConfigComponentName,
|
|
&gIp4ConfigComponentName2
|
|
);
|
|
}
|
|
|
|
|
|
/**
|
|
Test to see if this driver supports ControllerHandle.
|
|
|
|
@param This Protocol instance pointer.
|
|
@param ControllerHandle Handle of device to test
|
|
@param RemainingDevicePath Optional parameter use to pick a specific child
|
|
device to start.
|
|
|
|
@retval EFI_SUCCES 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
|
|
Ip4ConfigDriverBindingSupported (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
NULL,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Start this driver on ControllerHandle.
|
|
|
|
@param This Protocol instance pointer.
|
|
@param ControllerHandle Handle of device to bind driver to
|
|
@param RemainingDevicePath Optional parameter use to pick a specific child
|
|
device to start.
|
|
|
|
@retval EFI_SUCCES 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
|
|
Ip4ConfigDriverBindingStart (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
|
)
|
|
{
|
|
EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
|
|
EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
|
|
EFI_HANDLE MnpHandle;
|
|
IP4_CONFIG_INSTANCE *Instance;
|
|
EFI_SIMPLE_NETWORK_MODE SnpMode;
|
|
NIC_IP4_CONFIG_INFO *NicConfig;
|
|
EFI_STATUS Status;
|
|
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
|
|
|
Status = gBS->HandleProtocol (
|
|
ControllerHandle,
|
|
&gEfiDevicePathProtocolGuid,
|
|
(VOID **) &ParentDevicePath
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Check for multiple start.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
ControllerHandle,
|
|
&gEfiIp4ConfigProtocolGuid,
|
|
(VOID **) &Ip4Config,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
//
|
|
// Create a MNP child
|
|
//
|
|
Mnp = NULL;
|
|
MnpHandle = NULL;
|
|
Instance = NULL;
|
|
|
|
Status = NetLibCreateServiceChild (
|
|
ControllerHandle,
|
|
This->DriverBindingHandle,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
&MnpHandle
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = gBS->OpenProtocol (
|
|
MnpHandle,
|
|
&gEfiManagedNetworkProtocolGuid,
|
|
(VOID **) &Mnp,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Allocate an instance then initialize it
|
|
//
|
|
Instance = AllocateCopyPool (sizeof (IP4_CONFIG_INSTANCE), &mIp4ConfigTemplate);
|
|
|
|
if (Instance == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Instance->Controller = ControllerHandle;
|
|
Instance->Image = This->DriverBindingHandle;
|
|
Instance->ParentDevicePath = ParentDevicePath;
|
|
|
|
CopyMem (&Instance->Ip4ConfigProtocol, &mIp4ConfigProtocolTemplate, sizeof (mIp4ConfigProtocolTemplate));
|
|
|
|
Instance->State = IP4_CONFIG_STATE_IDLE;
|
|
Instance->Mnp = Mnp;
|
|
Instance->MnpHandle = MnpHandle;
|
|
|
|
Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
|
|
|
|
if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Instance->NicAddr.Type = (UINT16) SnpMode.IfType;
|
|
Instance->NicAddr.Len = (UINT8) SnpMode.HwAddressSize;
|
|
CopyMem (&Instance->NicAddr.MacAddr, &SnpMode.CurrentAddress, Instance->NicAddr.Len);
|
|
|
|
//
|
|
// Add it to the global list, and compose the name
|
|
//
|
|
Status = NetLibGetMacString (Instance->Controller, Instance->Image, &Instance->MacString);
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Status = Ip4ConfigDeviceInit (Instance);
|
|
|
|
//
|
|
// Install the IP4_CONFIG protocols
|
|
//
|
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
|
&ControllerHandle,
|
|
&gEfiIp4ConfigProtocolGuid,
|
|
&Instance->Ip4ConfigProtocol,
|
|
NULL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// A dedicated timer is used to poll underlying media status.
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL | EVT_TIMER,
|
|
TPL_CALLBACK,
|
|
MediaChangeDetect,
|
|
Instance,
|
|
&Instance->Timer
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Get the previous configure parameters. If an error happend here,
|
|
// just ignore it because the driver should be able to operate.
|
|
//
|
|
NicConfig = Ip4ConfigReadVariable (Instance);
|
|
if (NicConfig != NULL) {
|
|
if (!NicConfig->Perment) {
|
|
//
|
|
// Delete the non-permanent configuration.
|
|
//
|
|
Ip4ConfigWriteVariable (Instance, NULL);
|
|
}
|
|
|
|
FreePool (NicConfig);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
ON_ERROR:
|
|
if (Instance != NULL) {
|
|
FreePool (Instance);
|
|
}
|
|
|
|
if (Mnp != NULL) {
|
|
gBS->CloseProtocol (
|
|
MnpHandle,
|
|
&gEfiManagedNetworkProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle
|
|
);
|
|
}
|
|
|
|
NetLibDestroyServiceChild (
|
|
ControllerHandle,
|
|
This->DriverBindingHandle,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
MnpHandle
|
|
);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Stop this driver on ControllerHandle.
|
|
|
|
@param This Protocol instance pointer.
|
|
@param ControllerHandle Handle of device to stop driver on
|
|
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
|
children is zero stop the entire bus driver.
|
|
@param ChildHandleBuffer List of Child Handles to Stop.
|
|
|
|
@retval EFI_SUCCES This driver is removed ControllerHandle
|
|
@retval other This driver was not removed from this device
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
Ip4ConfigDriverBindingStop (
|
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
|
IN EFI_HANDLE ControllerHandle,
|
|
IN UINTN NumberOfChildren,
|
|
IN EFI_HANDLE *ChildHandleBuffer
|
|
)
|
|
{
|
|
IP4_CONFIG_INSTANCE *Instance;
|
|
EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
|
|
EFI_HANDLE NicHandle;
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// IP4_CONFIG instance opens an MNP child. It may also create and open
|
|
// a DHCP child. If this is the DHCP handle, stop the DHCP process. If
|
|
// it is the MNP child, stop the whole driver.
|
|
//
|
|
//
|
|
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
|
|
|
|
if (NicHandle != NULL) {
|
|
//
|
|
// Get our context back then clean the DHCP up. Notify the user if necessary.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
NicHandle,
|
|
&gEfiIp4ConfigProtocolGuid,
|
|
(VOID **) &Ip4Config,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (Ip4Config);
|
|
ASSERT (ControllerHandle == Instance->Dhcp4Handle);
|
|
|
|
Ip4ConfigCleanDhcp4 (Instance);
|
|
|
|
Instance->State = IP4_CONFIG_STATE_CONFIGURED;
|
|
Instance->Result = EFI_DEVICE_ERROR;
|
|
|
|
if (Instance->DoneEvent != NULL) {
|
|
gBS->SignalEvent (Instance->DoneEvent);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// This is a MNP handle, stop the whole driver
|
|
//
|
|
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
|
|
|
|
if (NicHandle == NULL) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Get our context back.
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
NicHandle,
|
|
&gEfiIp4ConfigProtocolGuid,
|
|
(VOID **) &Ip4Config,
|
|
This->DriverBindingHandle,
|
|
ControllerHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (Ip4Config);
|
|
|
|
Ip4ConfigDeviceUnload (Instance);
|
|
|
|
//
|
|
// Unload the protocols first to inform the top drivers
|
|
//
|
|
Status = gBS->UninstallMultipleProtocolInterfaces (
|
|
NicHandle,
|
|
&gEfiIp4ConfigProtocolGuid,
|
|
&Instance->Ip4ConfigProtocol,
|
|
NULL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Release all the resources
|
|
//
|
|
if (Instance->MnpHandle != NULL) {
|
|
gBS->CloseProtocol (
|
|
Instance->MnpHandle,
|
|
&gEfiManagedNetworkProtocolGuid,
|
|
This->DriverBindingHandle,
|
|
NicHandle
|
|
);
|
|
|
|
NetLibDestroyServiceChild (
|
|
NicHandle,
|
|
Instance->Image,
|
|
&gEfiManagedNetworkServiceBindingProtocolGuid,
|
|
Instance->MnpHandle
|
|
);
|
|
|
|
Instance->Mnp = NULL;
|
|
Instance->MnpHandle = NULL;
|
|
}
|
|
|
|
if (Instance->MacString != NULL) {
|
|
FreePool (Instance->MacString);
|
|
}
|
|
|
|
if (Instance->Timer != NULL) {
|
|
gBS->SetTimer (Instance->Timer, TimerCancel, 0);
|
|
gBS->CloseEvent (Instance->Timer);
|
|
Instance->Timer = NULL;
|
|
}
|
|
|
|
Ip4ConfigCleanConfig (Instance);
|
|
FreePool (Instance);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|