mirror of https://github.com/acidanthera/audk.git
745 lines
22 KiB
C
745 lines
22 KiB
C
/** @file
|
|
This code implements the IP4Config and NicIp4Config protocols.
|
|
|
|
Copyright (c) 2006 - 2012, 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 "NicIp4Variable.h"
|
|
|
|
//
|
|
// Ip4 Config Protocol
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP4_CONFIG_PROTOCOL mIp4ConfigProtocolTemplate = {
|
|
EfiIp4ConfigStart,
|
|
EfiIp4ConfigStop,
|
|
EfiIp4ConfigGetData
|
|
};
|
|
|
|
/**
|
|
Get the NIC's configure information from the IP4 configure variable.
|
|
It will remove the invalid variable.
|
|
|
|
@param Instance The IP4 CONFIG instance.
|
|
|
|
@return NULL if no configure for the NIC in the variable, or it is invalid.
|
|
Otherwise the pointer to the NIC's IP configure parameter will be returned.
|
|
|
|
**/
|
|
NIC_IP4_CONFIG_INFO *
|
|
EfiNicIp4ConfigGetInfo (
|
|
IN IP4_CONFIG_INSTANCE *Instance
|
|
)
|
|
{
|
|
NIC_IP4_CONFIG_INFO *NicConfig;
|
|
|
|
//
|
|
// Read the configuration parameter for this NIC from
|
|
// the EFI variable
|
|
//
|
|
NicConfig = Ip4ConfigReadVariable (Instance);
|
|
if (NicConfig == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Validate the configuration, if the configuration is invalid,
|
|
// remove it from the variable.
|
|
//
|
|
if (!Ip4ConfigIsValid (NicConfig)) {
|
|
Ip4ConfigWriteVariable (Instance, NULL);
|
|
|
|
FreePool (NicConfig);
|
|
NicConfig = NULL;
|
|
}
|
|
|
|
return NicConfig;
|
|
}
|
|
|
|
/**
|
|
Set the IP configure parameters for this NIC.
|
|
|
|
If Reconfig is TRUE, the IP driver will be informed to discard current
|
|
auto configure parameter and restart the auto configuration process.
|
|
If current there is a pending auto configuration, EFI_ALREADY_STARTED is
|
|
returned. You can only change the configure setting when either
|
|
the configure has finished or not started yet. If NicConfig, the
|
|
NIC's configure parameter is removed from the variable.
|
|
|
|
@param Instance The IP4 CONFIG instance.
|
|
@param NicConfig The new NIC IP4 configure parameter.
|
|
@param Reconfig Inform the IP4 driver to restart the auto
|
|
configuration.
|
|
|
|
@retval EFI_SUCCESS The configure parameter for this NIC was
|
|
set successfully.
|
|
@retval EFI_INVALID_PARAMETER This is NULL or the configure parameter is
|
|
invalid.
|
|
@retval EFI_ALREADY_STARTED There is a pending auto configuration.
|
|
@retval EFI_NOT_FOUND No auto configure parameter is found.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EfiNicIp4ConfigSetInfo (
|
|
IN IP4_CONFIG_INSTANCE *Instance,
|
|
IN NIC_IP4_CONFIG_INFO *NicConfig OPTIONAL,
|
|
IN BOOLEAN Reconfig
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Validate the parameters
|
|
//
|
|
if (Instance == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if ((NicConfig != NULL) && (!Ip4ConfigIsValid (NicConfig) ||
|
|
!NIC_ADDR_EQUAL (&NicConfig->NicAddr, &Instance->NicAddr))) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Instance->State == IP4_CONFIG_STATE_STARTED) {
|
|
return EFI_ALREADY_STARTED;
|
|
}
|
|
|
|
//
|
|
// Update the parameter in the configure variable
|
|
//
|
|
Status = Ip4ConfigWriteVariable (Instance, NicConfig);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Signal the IP4 to run the auto configuration again
|
|
//
|
|
if (Reconfig && (Instance->ReconfigEvent != NULL)) {
|
|
//
|
|
// When NicConfig is NULL, NIC IP4 configuration parameter is removed,
|
|
// the auto configuration process should stop running the configuration
|
|
// policy for the EFI IPv4 Protocol driver.
|
|
//
|
|
if (NicConfig == NULL) {
|
|
Instance->DoNotStart = TRUE;
|
|
}
|
|
|
|
Status = gBS->SignalEvent (Instance->ReconfigEvent);
|
|
DispatchDpc ();
|
|
}
|
|
|
|
if (NicConfig == NULL) {
|
|
return Status;
|
|
}
|
|
//
|
|
// A dedicated timer is used to poll underlying media status.In case of
|
|
// cable swap, a new round auto configuration will be initiated. The timer
|
|
// starts in DHCP policy only. STATIC policy stops the timer.
|
|
//
|
|
if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {
|
|
gBS->SetTimer (Instance->Timer, TimerPeriodic, TICKS_PER_SECOND);
|
|
} else if (NicConfig->Source == IP4_CONFIG_SOURCE_STATIC) {
|
|
gBS->SetTimer (Instance->Timer, TimerCancel, 0);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Callback function when DHCP process finished. It will save the
|
|
retrieved IP configure parameter from DHCP to the NVRam.
|
|
|
|
@param Event The callback event
|
|
@param Context Opaque context to the callback
|
|
|
|
@return None
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
Ip4ConfigOnDhcp4Complete (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
IP4_CONFIG_INSTANCE *Instance;
|
|
EFI_DHCP4_MODE_DATA Dhcp4Mode;
|
|
EFI_IP4_IPCONFIG_DATA *Ip4Config;
|
|
EFI_STATUS Status;
|
|
BOOLEAN Permanent;
|
|
IP4_ADDR Subnet;
|
|
IP4_ADDR Ip1;
|
|
IP4_ADDR Ip2;
|
|
|
|
Instance = (IP4_CONFIG_INSTANCE *) Context;
|
|
ASSERT (Instance->Dhcp4 != NULL);
|
|
|
|
Instance->State = IP4_CONFIG_STATE_CONFIGURED;
|
|
Instance->Result = EFI_TIMEOUT;
|
|
|
|
//
|
|
// Get the DHCP retrieved parameters
|
|
//
|
|
Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_EXIT;
|
|
}
|
|
|
|
if (Dhcp4Mode.State == Dhcp4Bound) {
|
|
//
|
|
// Save the new configuration retrieved by DHCP both in
|
|
// the instance and to NVRam. So, both the IP4 driver and
|
|
// other user can get that address.
|
|
//
|
|
Permanent = FALSE;
|
|
|
|
if (Instance->NicConfig != NULL) {
|
|
ASSERT (Instance->NicConfig->Source == IP4_CONFIG_SOURCE_DHCP);
|
|
Permanent = Instance->NicConfig->Permanent;
|
|
FreePool (Instance->NicConfig);
|
|
}
|
|
|
|
Instance->NicConfig = AllocatePool (sizeof (NIC_IP4_CONFIG_INFO) + 2* sizeof (EFI_IP4_ROUTE_TABLE));
|
|
|
|
if (Instance->NicConfig == NULL) {
|
|
Instance->Result = EFI_OUT_OF_RESOURCES;
|
|
goto ON_EXIT;
|
|
}
|
|
|
|
Instance->NicConfig->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Instance->NicConfig + 1);
|
|
|
|
CopyMem (&Instance->NicConfig->NicAddr, &Instance->NicAddr, sizeof (Instance->NicConfig->NicAddr));
|
|
Instance->NicConfig->Source = IP4_CONFIG_SOURCE_DHCP;
|
|
Instance->NicConfig->Permanent = Permanent;
|
|
|
|
Ip4Config = &Instance->NicConfig->Ip4Info;
|
|
Ip4Config->StationAddress = Dhcp4Mode.ClientAddress;
|
|
Ip4Config->SubnetMask = Dhcp4Mode.SubnetMask;
|
|
|
|
//
|
|
// Create a route for the connected network
|
|
//
|
|
Ip4Config->RouteTableSize = 1;
|
|
|
|
CopyMem (&Ip1, &Dhcp4Mode.ClientAddress, sizeof (IP4_ADDR));
|
|
CopyMem (&Ip2, &Dhcp4Mode.SubnetMask, sizeof (IP4_ADDR));
|
|
|
|
Subnet = Ip1 & Ip2;
|
|
|
|
CopyMem (&Ip4Config->RouteTable[0].SubnetAddress, &Subnet, sizeof (EFI_IPv4_ADDRESS));
|
|
CopyMem (&Ip4Config->RouteTable[0].SubnetMask, &Dhcp4Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
|
|
ZeroMem (&Ip4Config->RouteTable[0].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
|
|
|
|
//
|
|
// Create a route if there is a default router.
|
|
//
|
|
if (!EFI_IP4_EQUAL (&Dhcp4Mode.RouterAddress, &mZeroIp4Addr)) {
|
|
Ip4Config->RouteTableSize = 2;
|
|
|
|
ZeroMem (&Ip4Config->RouteTable[1].SubnetAddress, sizeof (EFI_IPv4_ADDRESS));
|
|
ZeroMem (&Ip4Config->RouteTable[1].SubnetMask, sizeof (EFI_IPv4_ADDRESS));
|
|
CopyMem (&Ip4Config->RouteTable[1].GatewayAddress, &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
|
|
}
|
|
|
|
Instance->Result = EFI_SUCCESS;
|
|
|
|
//
|
|
// ignore the return status of EfiNicIp4ConfigSetInfo. Network
|
|
// stack can operate even that failed.
|
|
//
|
|
EfiNicIp4ConfigSetInfo (Instance, Instance->NicConfig, FALSE);
|
|
}
|
|
|
|
ON_EXIT:
|
|
gBS->SignalEvent (Instance->DoneEvent);
|
|
Ip4ConfigCleanDhcp4 (Instance);
|
|
|
|
DispatchDpc ();
|
|
|
|
return ;
|
|
}
|
|
|
|
/**
|
|
Starts running the configuration policy for the EFI IPv4 Protocol driver.
|
|
|
|
The Start() function is called to determine and to begin the platform
|
|
configuration policy by the EFI IPv4 Protocol driver. This determination may
|
|
be as simple as returning EFI_UNSUPPORTED if there is no EFI IPv4 Protocol
|
|
driver configuration policy. It may be as involved as loading some defaults
|
|
from nonvolatile storage, downloading dynamic data from a DHCP server, and
|
|
checking permissions with a site policy server.
|
|
Starting the configuration policy is just the beginning. It may finish almost
|
|
instantly or it may take several minutes before it fails to retrieve configuration
|
|
information from one or more servers. Once the policy is started, drivers
|
|
should use the DoneEvent parameter to determine when the configuration policy
|
|
has completed. EFI_IP4_CONFIG_PROTOCOL.GetData() must then be called to
|
|
determine if the configuration succeeded or failed.
|
|
Until the configuration completes successfully, EFI IPv4 Protocol driver instances
|
|
that are attempting to use default configurations must return EFI_NO_MAPPING.
|
|
Once the configuration is complete, the EFI IPv4 Configuration Protocol driver
|
|
signals DoneEvent. The configuration may need to be updated in the future,
|
|
however; in this case, the EFI IPv4 Configuration Protocol driver must signal
|
|
ReconfigEvent, and all EFI IPv4 Protocol driver instances that are using default
|
|
configurations must return EFI_NO_MAPPING until the configuration policy has
|
|
been rerun.
|
|
|
|
@param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
|
|
@param DoneEvent Event that will be signaled when the EFI IPv4
|
|
Protocol driver configuration policy completes
|
|
execution. This event must be of type EVT_NOTIFY_SIGNAL.
|
|
@param ReconfigEvent Event that will be signaled when the EFI IPv4
|
|
Protocol driver configuration needs to be updated.
|
|
This event must be of type EVT_NOTIFY_SIGNAL.
|
|
|
|
@retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol
|
|
driver is now running.
|
|
@retval EFI_INVALID_PARAMETER One or more of the following parameters is NULL:
|
|
This
|
|
DoneEvent
|
|
ReconfigEvent
|
|
@retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
|
|
@retval EFI_ALREADY_STARTED The configuration policy for the EFI IPv4 Protocol
|
|
driver was already started.
|
|
@retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
|
|
@retval EFI_UNSUPPORTED This interface does not support the EFI IPv4 Protocol
|
|
driver configuration.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EfiIp4ConfigStart (
|
|
IN EFI_IP4_CONFIG_PROTOCOL *This,
|
|
IN EFI_EVENT DoneEvent,
|
|
IN EFI_EVENT ReconfigEvent
|
|
)
|
|
{
|
|
IP4_CONFIG_INSTANCE *Instance;
|
|
EFI_DHCP4_PROTOCOL *Dhcp4;
|
|
EFI_DHCP4_MODE_DATA Dhcp4Mode;
|
|
EFI_DHCP4_PACKET_OPTION *OptionList[1];
|
|
IP4_CONFIG_DHCP4_OPTION ParaList;
|
|
EFI_STATUS Status;
|
|
UINT32 Source;
|
|
EFI_TPL OldTpl;
|
|
|
|
if ((This == NULL) || (DoneEvent == NULL) || (ReconfigEvent == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);
|
|
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
if (Instance->State != IP4_CONFIG_STATE_IDLE) {
|
|
Status = EFI_ALREADY_STARTED;
|
|
|
|
goto ON_EXIT;
|
|
}
|
|
|
|
Instance->DoneEvent = DoneEvent;
|
|
Instance->ReconfigEvent = ReconfigEvent;
|
|
|
|
Instance->NicConfig = EfiNicIp4ConfigGetInfo (Instance);
|
|
|
|
if (Instance->NicConfig == NULL) {
|
|
if (Instance->DoNotStart) {
|
|
Instance->DoNotStart = FALSE;
|
|
Status = EFI_SUCCESS;
|
|
goto ON_EXIT;
|
|
}
|
|
|
|
Source = IP4_CONFIG_SOURCE_DHCP;
|
|
} else {
|
|
Source = Instance->NicConfig->Source;
|
|
}
|
|
|
|
//
|
|
// If the source is static, the auto configuration is done.
|
|
// return now.
|
|
//
|
|
if (Source == IP4_CONFIG_SOURCE_STATIC) {
|
|
Instance->State = IP4_CONFIG_STATE_CONFIGURED;
|
|
Instance->Result = EFI_SUCCESS;
|
|
|
|
gBS->SignalEvent (Instance->DoneEvent);
|
|
Status = EFI_SUCCESS;
|
|
goto ON_EXIT;
|
|
}
|
|
|
|
//
|
|
// Start the dhcp process
|
|
//
|
|
ASSERT ((Source == IP4_CONFIG_SOURCE_DHCP) && (Instance->Dhcp4 == NULL));
|
|
|
|
Status = NetLibCreateServiceChild (
|
|
Instance->Controller,
|
|
Instance->Image,
|
|
&gEfiDhcp4ServiceBindingProtocolGuid,
|
|
&Instance->Dhcp4Handle
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Status = gBS->OpenProtocol (
|
|
Instance->Dhcp4Handle,
|
|
&gEfiDhcp4ProtocolGuid,
|
|
(VOID **) &Instance->Dhcp4,
|
|
Instance->Image,
|
|
Instance->Controller,
|
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Check the current DHCP status, if the DHCP process has
|
|
// already finished, return now.
|
|
//
|
|
Dhcp4 = Instance->Dhcp4;
|
|
Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
if (Dhcp4Mode.State == Dhcp4Bound) {
|
|
Ip4ConfigOnDhcp4Complete (NULL, Instance);
|
|
|
|
goto ON_EXIT;
|
|
}
|
|
|
|
//
|
|
// Try to start the DHCP process. Use most of the current
|
|
// DHCP configuration to avoid problems if some DHCP client
|
|
// yields the control of this DHCP service to us.
|
|
//
|
|
ParaList.Head.OpCode = DHCP_TAG_PARA_LIST;
|
|
ParaList.Head.Length = 2;
|
|
ParaList.Head.Data[0] = DHCP_TAG_NETMASK;
|
|
ParaList.Route = DHCP_TAG_ROUTER;
|
|
OptionList[0] = &ParaList.Head;
|
|
Dhcp4Mode.ConfigData.OptionCount = 1;
|
|
Dhcp4Mode.ConfigData.OptionList = OptionList;
|
|
|
|
Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
//
|
|
// Start the DHCP process
|
|
//
|
|
Status = gBS->CreateEvent (
|
|
EVT_NOTIFY_SIGNAL,
|
|
TPL_CALLBACK,
|
|
Ip4ConfigOnDhcp4Complete,
|
|
Instance,
|
|
&Instance->Dhcp4Event
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_ERROR;
|
|
}
|
|
|
|
Instance->State = IP4_CONFIG_STATE_STARTED;
|
|
Instance->Result = EFI_NOT_READY;
|
|
|
|
ON_ERROR:
|
|
if (EFI_ERROR (Status)) {
|
|
Ip4ConfigCleanConfig (Instance);
|
|
}
|
|
|
|
ON_EXIT:
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
DispatchDpc ();
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Stops running the configuration policy for the EFI IPv4 Protocol driver.
|
|
|
|
The Stop() function stops the configuration policy for the EFI IPv4 Protocol driver.
|
|
All configuration data will be lost after calling Stop().
|
|
|
|
@param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
|
|
|
|
@retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol
|
|
driver has been stopped.
|
|
@retval EFI_INVALID_PARAMETER This is NULL.
|
|
@retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol
|
|
driver was not started.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EfiIp4ConfigStop (
|
|
IN EFI_IP4_CONFIG_PROTOCOL *This
|
|
)
|
|
{
|
|
IP4_CONFIG_INSTANCE *Instance;
|
|
EFI_STATUS Status;
|
|
EFI_TPL OldTpl;
|
|
|
|
if (This == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);
|
|
|
|
Status = EFI_SUCCESS;
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
if (Instance->State == IP4_CONFIG_STATE_IDLE) {
|
|
Status = EFI_NOT_STARTED;
|
|
goto ON_EXIT;
|
|
}
|
|
|
|
//
|
|
// Release all the configure parameters. Don't signal the user
|
|
// event. The user wants to abort the configuration, this isn't
|
|
// the configuration done or reconfiguration.
|
|
//
|
|
Ip4ConfigCleanConfig (Instance);
|
|
|
|
ON_EXIT:
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
Returns the default configuration data (if any) for the EFI IPv4 Protocol driver.
|
|
|
|
The GetData() function returns the current configuration data for the EFI IPv4
|
|
Protocol driver after the configuration policy has completed.
|
|
|
|
@param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
|
|
@param ConfigDataSize On input, the size of the ConfigData buffer.
|
|
On output, the count of bytes that were written
|
|
into the ConfigData buffer.
|
|
@param ConfigData Pointer to the EFI IPv4 Configuration Protocol
|
|
driver configuration data structure.
|
|
Type EFI_IP4_IPCONFIG_DATA is defined in
|
|
"Related Definitions" below.
|
|
|
|
@retval EFI_SUCCESS The EFI IPv4 Protocol driver configuration has been returned.
|
|
@retval EFI_INVALID_PARAMETER This is NULL.
|
|
@retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol
|
|
driver is not running.
|
|
@retval EFI_NOT_READY EFI IPv4 Protocol driver configuration is still running.
|
|
@retval EFI_ABORTED EFI IPv4 Protocol driver configuration could not complete.
|
|
Currently not implemented.
|
|
@retval EFI_BUFFER_TOO_SMALL *ConfigDataSize is smaller than the configuration
|
|
data buffer or ConfigData is NULL.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EfiIp4ConfigGetData (
|
|
IN EFI_IP4_CONFIG_PROTOCOL *This,
|
|
IN OUT UINTN *ConfigDataSize,
|
|
OUT EFI_IP4_IPCONFIG_DATA *ConfigData OPTIONAL
|
|
)
|
|
{
|
|
IP4_CONFIG_INSTANCE *Instance;
|
|
NIC_IP4_CONFIG_INFO *NicConfig;
|
|
EFI_STATUS Status;
|
|
EFI_TPL OldTpl;
|
|
UINTN Len;
|
|
|
|
if ((This == NULL) || (ConfigDataSize == NULL)) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);
|
|
|
|
Status = EFI_SUCCESS;
|
|
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
|
|
|
if (Instance->State == IP4_CONFIG_STATE_IDLE) {
|
|
Status = EFI_NOT_STARTED;
|
|
} else if (Instance->State == IP4_CONFIG_STATE_STARTED) {
|
|
Status = EFI_NOT_READY;
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
goto ON_EXIT;
|
|
}
|
|
|
|
//
|
|
// Copy the configure data if auto configuration succeeds.
|
|
//
|
|
Status = Instance->Result;
|
|
|
|
if (Status == EFI_SUCCESS) {
|
|
ASSERT (Instance->NicConfig != NULL);
|
|
|
|
NicConfig = Instance->NicConfig;
|
|
Len = SIZEOF_IP4_CONFIG_INFO (&NicConfig->Ip4Info);
|
|
|
|
if ((*ConfigDataSize < Len) || (ConfigData == NULL)) {
|
|
Status = EFI_BUFFER_TOO_SMALL;
|
|
} else {
|
|
CopyMem (ConfigData, &NicConfig->Ip4Info, Len);
|
|
Ip4ConfigFixRouteTablePointer (ConfigData);
|
|
}
|
|
|
|
*ConfigDataSize = Len;
|
|
}
|
|
|
|
ON_EXIT:
|
|
gBS->RestoreTPL (OldTpl);
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Release all the DHCP related resources.
|
|
|
|
@param This The IP4 configure instance
|
|
|
|
@return None
|
|
|
|
**/
|
|
VOID
|
|
Ip4ConfigCleanDhcp4 (
|
|
IN IP4_CONFIG_INSTANCE *This
|
|
)
|
|
{
|
|
if (This->Dhcp4 != NULL) {
|
|
This->Dhcp4->Stop (This->Dhcp4);
|
|
|
|
gBS->CloseProtocol (
|
|
This->Dhcp4Handle,
|
|
&gEfiDhcp4ProtocolGuid,
|
|
This->Image,
|
|
This->Controller
|
|
);
|
|
|
|
This->Dhcp4 = NULL;
|
|
}
|
|
|
|
if (This->Dhcp4Handle != NULL) {
|
|
NetLibDestroyServiceChild (
|
|
This->Controller,
|
|
This->Image,
|
|
&gEfiDhcp4ServiceBindingProtocolGuid,
|
|
This->Dhcp4Handle
|
|
);
|
|
|
|
This->Dhcp4Handle = NULL;
|
|
}
|
|
|
|
if (This->Dhcp4Event == NULL) {
|
|
gBS->CloseEvent (This->Dhcp4Event);
|
|
This->Dhcp4Event = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Clean up all the configuration parameters.
|
|
|
|
@param Instance The IP4 configure instance
|
|
|
|
@return None
|
|
|
|
**/
|
|
VOID
|
|
Ip4ConfigCleanConfig (
|
|
IN IP4_CONFIG_INSTANCE *Instance
|
|
)
|
|
{
|
|
if (Instance->NicConfig != NULL) {
|
|
FreePool (Instance->NicConfig);
|
|
Instance->NicConfig = NULL;
|
|
}
|
|
|
|
Instance->State = IP4_CONFIG_STATE_IDLE;
|
|
Instance->DoneEvent = NULL;
|
|
Instance->ReconfigEvent = NULL;
|
|
|
|
Ip4ConfigCleanDhcp4 (Instance);
|
|
}
|
|
|
|
|
|
/**
|
|
A dedicated timer is used to poll underlying media status. In case of
|
|
cable swap, a new round auto configuration will be initiated. The timer
|
|
will signal the IP4 to run the auto configuration again. IP4 driver will free
|
|
old IP address related resource, such as route table and Interface, then
|
|
initiate a DHCP process by IP4Config->Start to acquire new IP, eventually
|
|
create route table for new IP address.
|
|
|
|
@param[in] Event The IP4 service instance's heart beat timer.
|
|
@param[in] Context The IP4 service instance.
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
MediaChangeDetect (
|
|
IN EFI_EVENT Event,
|
|
IN VOID *Context
|
|
)
|
|
{
|
|
BOOLEAN OldMediaPresent;
|
|
EFI_STATUS Status;
|
|
EFI_SIMPLE_NETWORK_MODE SnpModeData;
|
|
IP4_CONFIG_INSTANCE *Instance;
|
|
|
|
Instance = (IP4_CONFIG_INSTANCE *) Context;
|
|
|
|
OldMediaPresent = Instance->MediaPresent;
|
|
|
|
//
|
|
// Get fresh mode data from MNP, since underlying media status may change
|
|
//
|
|
Status = Instance->Mnp->GetModeData (Instance->Mnp, NULL, &SnpModeData);
|
|
if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
|
|
return;
|
|
}
|
|
|
|
Instance->MediaPresent = SnpModeData.MediaPresent;
|
|
//
|
|
// Media transimit Unpresent to Present means new link movement is detected.
|
|
//
|
|
if (!OldMediaPresent && Instance->MediaPresent) {
|
|
//
|
|
// Signal the IP4 to run the auto configuration again. IP4 driver will free
|
|
// old IP address related resource, such as route table and Interface, then
|
|
// initiate a DHCP round by IP4Config->Start to acquire new IP, eventually
|
|
// create route table for new IP address.
|
|
//
|
|
if (Instance->ReconfigEvent != NULL) {
|
|
Status = gBS->SignalEvent (Instance->ReconfigEvent);
|
|
DispatchDpc ();
|
|
}
|
|
}
|
|
}
|