ip4driver.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 957 行 · 第 1/2 页

C
957
字号
/*++

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:

  Ip4Driver.c

Abstract:

  The driver binding and service binding protocol for IP4 driver.

--*/

#include "Ip4Impl.h"

EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {
  Ip4DriverBindingSupported,
  Ip4DriverBindingStart,
  Ip4DriverBindingStop,
  0x10,
  NULL,
  NULL
};

EFI_DRIVER_ENTRY_POINT (Ip4DriverEntryPoint)

EFI_STATUS
EFIAPI
Ip4DriverEntryPoint (
  IN EFI_HANDLE             ImageHandle,
  IN EFI_SYSTEM_TABLE       *SystemTable
  )
/*++

Routine Description:

  The entry point for IP4 driver which install the driver 
  binding and component name protocol on its image.

Arguments:

  ImageHandle - The image handle of the driver
  SystemTable - The system table

Returns:

  EFI_SUCCESS if the driver binding and component name protocols
  are successfully installed, otherwise if failed.

--*/
{
  return NetLibInstallAllDriverProtocols (
           ImageHandle,
           SystemTable,
           &gIp4DriverBinding,
           ImageHandle,
           &gIp4ComponentName,
           NULL,
           NULL
           );
}

EFI_STATUS
EFIAPI
Ip4DriverBindingSupported (
  IN EFI_DRIVER_BINDING_PROTOCOL  * This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL
  )
/*++

  Routine Description:
    Test to see if this driver supports ControllerHandle. 

  Arguments:
    This                - Protocol instance pointer.
    ControllerHandle    - Handle of device to test
    RemainingDevicePath - Optional parameter use to pick a specific child 
                          device to start.

  Returns:
    EFI_SUCCES          - This driver supports this device
    EFI_ALREADY_STARTED - This driver is already running on this device
    other               - This driver does not support this device

--*/
{
  EFI_STATUS                Status;

  //
  // Test for the MNP service binding Protocol
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiManagedNetworkServiceBindingProtocolGuid,
                  NULL,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );

  if (EFI_ERROR (Status)) {
    return Status;
  }
  
  //
  // Test for the Arp service binding Protocol
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiArpServiceBindingProtocolGuid,
                  NULL,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );

  return Status;
}

STATIC
EFI_STATUS
Ip4CleanService (
  IN IP4_SERVICE            *IpSb
  );

STATIC
EFI_STATUS
Ip4CreateService (
  IN  EFI_HANDLE            Controller,
  IN  EFI_HANDLE            ImageHandle,
  OUT IP4_SERVICE           **Service
  )
/*++

Routine Description:

  Create a new IP4 driver service binding protocol

Arguments:

  Controller  - The controller that has MNP service binding installed
  ImageHandle - The IP4 driver's image handle
  Service     - The variable to receive the newly created IP4 service.

Returns:

  EFI_OUT_OF_RESOURCES - Failed to allocate some resource
  EFI_SUCCESS          - A new IP4 service binding private is created.

--*/
{
  IP4_SERVICE               *IpSb;
  EFI_STATUS                Status;

  ASSERT (Service != NULL);

  *Service = NULL;

  //
  // allocate a service private data then initialize all the filed to 
  // empty resources, so if any thing goes wrong when allocating 
  // resources, Ip4CleanService can be called to clean it up.
  //
  IpSb = NetAllocatePool (sizeof (IP4_SERVICE));
  
  if (IpSb == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  IpSb->Signature                   = IP4_SERVICE_SIGNATURE;
  IpSb->ServiceBinding.CreateChild  = Ip4ServiceBindingCreateChild;
  IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;
  IpSb->State                       = IP4_SERVICE_UNSTARTED;
  IpSb->InDestory                   = FALSE;

  IpSb->NumChildren                 = 0;
  NetListInit (&IpSb->Children);

  NetListInit (&IpSb->Interfaces);
  IpSb->DefaultInterface            = NULL;
  IpSb->DefaultRouteTable           = NULL;

  Ip4InitAssembleTable (&IpSb->Assemble);

  IpSb->IgmpCtrl.Igmpv1QuerySeen    = 0;
  NetListInit (&IpSb->IgmpCtrl.Groups);

  IpSb->Image                       = ImageHandle;
  IpSb->Controller                  = Controller;

  IpSb->MnpChildHandle              = NULL;
  IpSb->Mnp                         = NULL;

  IpSb->MnpConfigData.ReceivedQueueTimeoutValue = 0;
  IpSb->MnpConfigData.TransmitQueueTimeoutValue = 0;
  IpSb->MnpConfigData.ProtocolTypeFilter        = IP4_ETHER_PROTO;
  IpSb->MnpConfigData.EnableUnicastReceive      = TRUE;
  IpSb->MnpConfigData.EnableMulticastReceive    = TRUE;
  IpSb->MnpConfigData.EnableBroadcastReceive    = TRUE;
  IpSb->MnpConfigData.EnablePromiscuousReceive  = FALSE;
  IpSb->MnpConfigData.FlushQueuesOnReset        = TRUE;
  IpSb->MnpConfigData.EnableReceiveTimestamps   = FALSE;
  IpSb->MnpConfigData.DisableBackgroundPolling  = FALSE;

  NetZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));

  IpSb->Timer                       = NULL;
  IpSb->Ip4Config                   = NULL;
  IpSb->DoneEvent                   = NULL;
  IpSb->ReconfigEvent               = NULL;

  //
  // Create various resources. First create the route table, timer
  // event and MNP child. IGMP, interface's initialization depend
  // on the MNP child.
  //
  IpSb->DefaultRouteTable = Ip4CreateRouteTable ();

  if (IpSb->DefaultRouteTable == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_ERROR;
  }

  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL | EFI_EVENT_TIMER,
                  EFI_TPL_CALLBACK,
                  Ip4TimerTicking,
                  IpSb,
                  &IpSb->Timer
                  );

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = NetLibCreateServiceChild (
             Controller,
             ImageHandle,
             &gEfiManagedNetworkServiceBindingProtocolGuid,
             &IpSb->MnpChildHandle
             );

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = gBS->OpenProtocol (
                  IpSb->MnpChildHandle,
                  &gEfiManagedNetworkProtocolGuid,
                  &IpSb->Mnp,
                  ImageHandle,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = Ip4ServiceConfigMnp (IpSb, TRUE);
  
  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  
  Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  Status = Ip4InitIgmp (IpSb);

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }

  IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);

  if (IpSb->DefaultInterface == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_ERROR;
  }

  NetListInsertHead (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);

  IpSb->MacString = NULL;
  
  *Service = IpSb;
  return EFI_SUCCESS;

ON_ERROR:
  Ip4CleanService (IpSb);
  NetFreePool (IpSb);
  
  return Status;
}

EFI_STATUS
Ip4CleanService (
  IN IP4_SERVICE            *IpSb
  )
/*++

Routine Description:

  Clean up a IP4 service binding instance. It will release all
  the resource allocated by the instance. The instance may be 
  partly initialized, or partly destoried. If a resource is 
  destoried, it is marked as that in case the destory failed and 
  being called again later.

Arguments:

  IpSb  - The IP4 serviceing binding instance to clean up

Returns:

  EFI_SUCCESS - The resource used by the instance are cleaned up
  Others      - Failed to clean up some of the resources.

--*/
{
  EFI_STATUS                Status;

  if (IpSb->DefaultInterface != NULL) {
    Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);

    if (EFI_ERROR (Status)) {
      return Status;
    }

    IpSb->DefaultInterface = NULL;
  }

  if (IpSb->DefaultRouteTable != NULL) {
    Ip4FreeRouteTable (IpSb->DefaultRouteTable);
    IpSb->DefaultRouteTable = NULL;
  }

  Ip4CleanAssembleTable (&IpSb->Assemble);

  if (IpSb->MnpChildHandle != NULL) {
    if (IpSb->Mnp) {
      gBS->CloseProtocol (
            IpSb->MnpChildHandle,
            &gEfiManagedNetworkProtocolGuid,
            IpSb->Image,
            IpSb->Controller
            );

      IpSb->Mnp = NULL;
    }

    NetLibDestroyServiceChild (
      IpSb->Controller,
      IpSb->Image,
      &gEfiManagedNetworkServiceBindingProtocolGuid,
      IpSb->MnpChildHandle
      );

    IpSb->MnpChildHandle = NULL;
  }

  if (IpSb->Timer != NULL) {
    gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
    gBS->CloseEvent (IpSb->Timer);

    IpSb->Timer = NULL;
  }

  if (IpSb->Ip4Config != NULL) {
    IpSb->Ip4Config->Stop (IpSb->Ip4Config);

    gBS->CloseProtocol (
          IpSb->Controller,
          &gEfiIp4ConfigProtocolGuid,
          IpSb->Image,
          IpSb->Controller
          );

    gBS->CloseEvent (IpSb->DoneEvent);
    gBS->CloseEvent (IpSb->ReconfigEvent);
    IpSb->Ip4Config = NULL;
  }

  return EFI_SUCCESS;
}

EFI_STATUS
EFIAPI
Ip4DriverBindingStart (
  IN EFI_DRIVER_BINDING_PROTOCOL  * This,
  IN EFI_HANDLE                   ControllerHandle,
  IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL
  )
/*++

  Routine Description:
    Start this driver on ControllerHandle.

  Arguments:
    This                - Protocol instance pointer.
    ControllerHandle    - Handle of device to bind driver to
    RemainingDevicePath - Optional parameter use to pick a specific child 
                          device to start.

  Returns:
    EFI_SUCCES          - This driver is added to ControllerHandle
    EFI_ALREADY_STARTED - This driver is already running on ControllerHandle
    other               - This driver does not support this device
    
--*/
{
  IP4_SERVICE               *IpSb;
  EFI_STATUS                Status;

  //
  // Test for the Ip4 service binding protocol
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiIp4ServiceBindingProtocolGuid,
                  NULL,
                  This->DriverBindingHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
                  );

  if (Status == EFI_SUCCESS) {
    return EFI_ALREADY_STARTED;
  }

  Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);

  if (EFI_ERROR (Status)) {
    return Status;
  }
  
  //
  // Install the Ip4ServiceBinding Protocol onto ControlerHandle
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &ControllerHandle,
                  &gEfiIp4ServiceBindingProtocolGuid,
                  &IpSb->ServiceBinding,
                  NULL
                  );

  if (EFI_ERROR (Status)) {
    goto FREE_SERVICE;
  }
  
  //
  // ready to go: start the receiving and timer
  //
  Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);

  if (EFI_ERROR (Status)) {
    goto UNINSTALL_PROTOCOL;
  }

  Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);

  if (EFI_ERROR (Status)) {
    goto UNINSTALL_PROTOCOL;
  }

  //
  // Initialize the IP4 ID

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?