ip4impl.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 2,133 行 · 第 1/4 页
C
2,133 行
/*++
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. 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.
Module Name:
Ip4Impl.c
Abstract:
--*/
#include "Ip4Impl.h"
STATIC
EFI_STATUS
EFIAPI
EfiIp4GetModeData (
IN EFI_IP4_PROTOCOL *This,
OUT EFI_IP4_MODE_DATA *Ip4ModeData, OPTIONAL
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData, OPTIONAL
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
)
/*++
Routine Description:
Get the IP child's current operational data. This can
all be used to get the underlying MNP and SNP data.
Arguments:
This - The IP4 protocol instance
Ip4ModeData - The IP4 operation data
MnpConfigData - The MNP configure data
SnpModeData - The SNP operation data
Returns:
EFI_INVALID_PARAMETER - The parameter is invalid because This == NULL
EFI_SUCCESS - The operational parameter is returned.
Others - Failed to retrieve the IP4 route table.
--*/
{
IP4_PROTOCOL *IpInstance;
IP4_SERVICE *IpSb;
EFI_IP4_CONFIG_DATA *Config;
EFI_STATUS Status;
EFI_TPL OldTpl;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
IpInstance = IP4_INSTANCE_FROM_PROTOCOL (This);
IpSb = IpInstance->Service;
if (Ip4ModeData != NULL) {
//
// IsStarted is "whether the EfiIp4Configure has been called".
// IsConfigured is "whether the station address has been configured"
//
Ip4ModeData->IsStarted = (BOOLEAN)(IpInstance->State == IP4_STATE_CONFIGED);
Ip4ModeData->ConfigData = IpInstance->ConfigData;
Ip4ModeData->IsConfigured = FALSE;
Ip4ModeData->GroupCount = IpInstance->GroupCount;
Ip4ModeData->GroupTable = (EFI_IPv4_ADDRESS *) IpInstance->Groups;
Ip4ModeData->IcmpTypeCount = 23;
Ip4ModeData->IcmpTypeList = mIp4SupportedIcmp;
Ip4ModeData->RouteTable = NULL;
Ip4ModeData->RouteCount = 0;
//
// return the current station address for this IP child. So,
// the user can get the default address through this. Some
// application wants to know it station address even it is
// using the default one, such as a ftp server.
//
if (Ip4ModeData->IsStarted) {
Config = &Ip4ModeData->ConfigData;
EFI_IP4 (Config->StationAddress) = HTONL (IpInstance->Interface->Ip);
EFI_IP4 (Config->SubnetMask) = HTONL (IpInstance->Interface->SubnetMask);
Ip4ModeData->IsConfigured = IpInstance->Interface->Configured;
//
// Build a EFI route table for user from the internal route table.
//
Status = Ip4BuildEfiRouteTable (IpInstance);
if (EFI_ERROR (Status)) {
NET_RESTORE_TPL (OldTpl);
return Status;
}
Ip4ModeData->RouteTable = IpInstance->EfiRouteTable;
Ip4ModeData->RouteCount = IpInstance->EfiRouteCount;
}
}
if (MnpConfigData != NULL) {
*MnpConfigData = IpSb->MnpConfigData;
}
if (SnpModeData != NULL) {
*SnpModeData = IpSb->SnpMode;
}
NET_RESTORE_TPL (OldTpl);
return EFI_SUCCESS;
}
EFI_STATUS
Ip4ServiceConfigMnp (
IN IP4_SERVICE *IpSb,
IN BOOLEAN Force
)
/*++
Routine Description:
Config the MNP parameter used by IP. The IP driver use one MNP
child to transmit/receive frames. By default, it configures MNP
to receive unicast/multicast/broadcast. And it will enable/disable
the promiscous receive according to whether there is IP child
enable that or not. If Force isn't false, it will iterate through
all the IP children to check whether the promiscuous receive
setting has been changed. If it hasn't been changed, it won't
reconfigure the MNP. If Force is true, the MNP is configured no
matter whether that is changed or not.
Arguments:
IpSb - The IP4 service instance that is to be changed.
Force - Force the configuration or not.
Returns:
EFI_SUCCESS - The MNP is successfully configured/reconfigured.
Others - Configuration failed.
--*/
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *ProtoEntry;
IP4_INTERFACE *IpIf;
IP4_PROTOCOL *IpInstance;
BOOLEAN Reconfig;
BOOLEAN PromiscReceive;
EFI_STATUS Status;
Reconfig = FALSE;
PromiscReceive = FALSE;
if (!Force) {
//
// Iterate through the IP children to check whether promiscuous
// receive setting has been changed. Update the interface's receive
// filter also.
//
NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {
IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);
IpIf->PromiscRecv = FALSE;
NET_LIST_FOR_EACH (ProtoEntry, &IpIf->IpInstances) {
IpInstance = NET_LIST_USER_STRUCT (ProtoEntry, IP4_PROTOCOL, AddrLink);
if (IpInstance->ConfigData.AcceptPromiscuous) {
IpIf->PromiscRecv = TRUE;
PromiscReceive = TRUE;
}
}
}
//
// If promiscuous receive isn't changed, it isn't necessary to reconfigure.
//
if (PromiscReceive == IpSb->MnpConfigData.EnablePromiscuousReceive) {
return EFI_SUCCESS;
}
Reconfig = TRUE;
IpSb->MnpConfigData.EnablePromiscuousReceive = PromiscReceive;
}
Status = IpSb->Mnp->Configure (IpSb->Mnp, &IpSb->MnpConfigData);
//
// recover the original configuration if failed to set the configure.
//
if (EFI_ERROR (Status) && Reconfig) {
IpSb->MnpConfigData.EnablePromiscuousReceive = !PromiscReceive;
}
return Status;
}
VOID
EFIAPI
Ip4AutoConfigCallBack (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
The event handle for IP4 auto configuration. If IP is asked
to reconfigure the default address. The original default
interface and route table are removed as the default. If there
is active IP children using the default address, the interface
will remain valid until all the children have freed their
references. If IP is signalled when auto configuration is done,
it will configure the default interface and default route table
with the configuration information retrieved by IP4_CONFIGURE.
Arguments:
Event - The event that is signalled.
Context - The IP4 service binding instance.
Returns:
None
--*/
{
EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
EFI_IP4_IPCONFIG_DATA *Data;
EFI_IP4_ROUTE_TABLE *RouteEntry;
IP4_SERVICE *IpSb;
IP4_ROUTE_TABLE *RouteTable;
IP4_INTERFACE *IpIf;
EFI_STATUS Status;
UINTN Len;
UINT32 Index;
IpSb = (IP4_SERVICE *) Context;
NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
Ip4Config = IpSb->Ip4Config;
//
// IP is asked to do the reconfiguration. If the default interface
// has been configured, release the default interface and route
// table, then create a new one. If there are some IP children
// using it, the interface won't be physically freed until all the
// children have released their reference to it. Also remember to
// restart the receive on the default address. IP4 driver only receive
// frames on the default address, and when the default interface is
// freed, Ip4AcceptFrame won't be informed.
//
if (Event == IpSb->ReconfigEvent) {
if (IpSb->DefaultInterface->Configured) {
IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);
if (IpIf == NULL) {
return;
}
RouteTable = Ip4CreateRouteTable ();
if (RouteTable == NULL) {
Ip4FreeInterface (IpIf, NULL);
return;
}
Ip4CancelReceive (IpSb->DefaultInterface);
Ip4FreeInterface (IpSb->DefaultInterface, NULL);
Ip4FreeRouteTable (IpSb->DefaultRouteTable);
IpSb->DefaultInterface = IpIf;
NetListInsertHead (&IpSb->Interfaces, &IpIf->Link);
IpSb->DefaultRouteTable = RouteTable;
Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);
}
Ip4Config->Stop (Ip4Config);
Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent);
return ;
}
//
// Get the configure data in two steps: get the length then the data.
//
Len = 0;
if (Ip4Config->GetData (Ip4Config, &Len, NULL) != EFI_BUFFER_TOO_SMALL) {
return ;
}
Data = NetAllocatePool (Len);
if (Data == NULL) {
return ;
}
Status = Ip4Config->GetData (Ip4Config, &Len, Data);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
IpIf = IpSb->DefaultInterface;
//
// If the default address has been configured don't change it.
// This is unlikely to happen if EFI_IP4_CONFIG protocol has
// informed us to reconfigure each time it wants to change the
// configuration parameters.
//
if (IpIf->Configured) {
goto ON_EXIT;
}
//
// Set the default interface's address, then add a directed
// route for it, that is, the route whose nexthop is zero.
//
Status = Ip4SetAddress (
IpIf,
EFI_NTOHL (Data->StationAddress),
EFI_NTOHL (Data->SubnetMask)
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
Ip4AddRoute (
IpSb->DefaultRouteTable,
EFI_NTOHL (Data->StationAddress),
EFI_NTOHL (Data->SubnetMask),
IP4_ALLZERO_ADDRESS
);
//
// Add routes returned by EFI_IP4_CONFIG protocol.
//
for (Index = 0; Index < Data->RouteTableSize; Index++) {
RouteEntry = &Data->RouteTable[Index];
Ip4AddRoute (
IpSb->DefaultRouteTable,
EFI_NTOHL (RouteEntry->SubnetAddress),
EFI_NTOHL (RouteEntry->SubnetMask),
EFI_NTOHL (RouteEntry->GatewayAddress)
);
}
IpSb->State = IP4_SERVICE_CONFIGED;
Ip4SetVariableData (IpSb);
ON_EXIT:
NetFreePool (Data);
}
EFI_STATUS
Ip4StartAutoConfig (
IN IP4_SERVICE *IpSb
)
/*++
Routine Description:
Start the auto configuration for this IP service instance.
It will locates the EFI_IP4_CONFIG_PROTOCOL, then start the
auto configuration.
Arguments:
IpSb - The IP4 service instance to configure
Returns:
EFI_SUCCESS - The auto configuration is successfull started
Others - Failed to start auto configuration.
--*/
{
EFI_IP4_CONFIG_PROTOCOL *Ip4Config;
EFI_STATUS Status;
if (IpSb->State > IP4_SERVICE_UNSTARTED) {
return EFI_SUCCESS;
}
//
// Create the DoneEvent and ReconfigEvent to call EFI_IP4_CONFIG
//
Status = gBS->CreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
NET_TPL_LOCK,
Ip4AutoConfigCallBack,
IpSb,
&IpSb->DoneEvent
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->CreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
EFI_TPL_CALLBACK,
Ip4AutoConfigCallBack,
IpSb,
&IpSb->ReconfigEvent
);
if (EFI_ERROR (Status)) {
goto CLOSE_DONE_EVENT;
}
//
// Open the EFI_IP4_CONFIG protocol then start auto configure
//
Status = gBS->OpenProtocol (
IpSb->Controller,
&gEfiIp4ConfigProtocolGuid,
&Ip4Config,
IpSb->Image,
IpSb->Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE
);
if (EFI_ERROR (Status)) {
Status = EFI_UNSUPPORTED;
goto CLOSE_RECONFIG_EVENT;
}
Status = Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
IpSb->Controller,
&gEfiIp4ConfigProtocolGuid,
IpSb->Image,
IpSb->Controller
);
goto CLOSE_RECONFIG_EVENT;
}
IpSb->Ip4Config = Ip4Config;
IpSb->State = IP4_SERVICE_STARTED;
return Status;
CLOSE_RECONFIG_EVENT:
gBS->CloseEvent (IpSb->ReconfigEvent);
IpSb->ReconfigEvent = NULL;
CLOSE_DONE_EVENT:
gBS->CloseEvent (IpSb->DoneEvent);
IpSb->DoneEvent = NULL;
return Status;
}
VOID
Ip4InitProtocol (
IN IP4_SERVICE *IpSb,
IN IP4_PROTOCOL *IpInstance
)
/*++
Routine Description:
Intiialize the IP4_PROTOCOL structure to the unconfigured states.
Arguments:
IpSb - The IP4 service instance.
IpInstance - The IP4 child instance.
Returns:
None
--*/
{
ASSERT ((IpSb != NULL) && (IpInstance != NULL));
NetZeroMem (IpInstance, sizeof (IP4_PROTOCOL));
IpInstance->Signature = IP4_PROTOCOL_SIGNATURE;
IpInstance->Ip4Proto = mEfiIp4ProtocolTemplete;
IpInstance->State = IP4_STATE_UNCONFIGED;
IpInstance->Service = IpSb;
NetListInit (&IpInstance->Link);
NetMapInit (&IpInstance->RxTokens);
NetMapInit (&IpInstance->TxTokens);
NetListInit (&IpInstance->Received);
NetListInit (&IpInstance->Delivered);
NetListInit (&IpInstance->AddrLink);
NET_GLOBAL_LOCK_INIT (&IpInstance->RecycleLock);
}
EFI_STATUS
Ip4ConfigProtocol (
IN IP4_PROTOCOL *IpInstance,
IN EFI_IP4_CONFIG_DATA *Config
)
/*++
Routine Description:
Configure the IP4 child. If the child is already configured,
change the configuration parameter. Otherwise configure it
for the first time. The caller should validate the configuration
before deliver them to it. It also don't do configure NULL.
Arguments:
IpInstance - The IP4 child to configure.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?