mnpconfig.c

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

C
1,577
字号
/*++

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:

  MnpConfig.c

Abstract:

  Implementation of Managed Network Protocol private services.

--*/

#include "MnpImpl.h"

EFI_SERVICE_BINDING_PROTOCOL    mMnpServiceBindingProtocol = {
  MnpServiceBindingCreateChild,
  MnpServiceBindingDestroyChild
};

EFI_MANAGED_NETWORK_PROTOCOL    mMnpProtocolTemplate = {
  MnpGetModeData,
  MnpConfigure,
  MnpMcastIpToMac,
  MnpGroups,
  MnpTransmit,
  MnpReceive,
  MnpCancel,
  MnpPoll
};

EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {
  10000,
  10000,
  0,
  FALSE,
  FALSE,
  FALSE,
  FALSE,
  FALSE,
  FALSE,
  FALSE
};

STATIC
EFI_STATUS
MnpAddFreeNbuf (
  IN MNP_SERVICE_DATA  *MnpServiceData,
  IN UINTN             Count
  );

STATIC
EFI_STATUS
MnpStartSnp (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *Snp
  );

STATIC
EFI_STATUS
MnpStopSnp (
  IN EFI_SIMPLE_NETWORK_PROTOCOL  *Snp
  );

STATIC
EFI_STATUS
MnpStart (
  IN MNP_SERVICE_DATA  *MnpServiceData,
  IN BOOLEAN           IsConfigUpdate,
  IN BOOLEAN           EnableSystemPoll
  );

STATIC
EFI_STATUS
MnpStop (
  IN MNP_SERVICE_DATA  *MnpServiceData
  );

STATIC
EFI_STATUS
MnpConfigReceiveFilters (
  IN MNP_SERVICE_DATA  *MnpServiceData
  );

STATIC
EFI_STATUS
MnpGroupOpAddCtrlBlk (
  IN MNP_INSTANCE_DATA        *Instance,
  IN MNP_GROUP_CONTROL_BLOCK  *CtrlBlk,
  IN MNP_GROUP_ADDRESS        *GroupAddress OPTIONAL,
  IN EFI_MAC_ADDRESS          *MacAddress,
  IN UINT32                   HwAddressSize
  );

STATIC
BOOLEAN
MnpGroupOpDelCtrlBlk (
  IN MNP_INSTANCE_DATA        *Instance,
  IN MNP_GROUP_CONTROL_BLOCK  *CtrlBlk
  );

STATIC
EFI_STATUS
MnpAddFreeNbuf (
  IN MNP_SERVICE_DATA  *MnpServiceData,
  IN UINTN             Count
  )
/*++

Routine Description:

  Add some NET_BUF into MnpServiceData->FreeNbufQue. The buffer length of
  the NET_BUF is specified by MnpServiceData->BufferLength.

Arguments:

  MnpServiceData - Pointer to the MNP_SERVICE_DATA.
  Count          - Number of NET_BUFFERs to add.

Returns:

  EFI_SUCCESS          - The specified amount of NET_BUFs are allocated and 
                         added into MnpServiceData->FreeNbufQue.
  EFI_OUT_OF_RESOURCES - Failed to allocate a NET_BUF structure.

--*/
{
  EFI_STATUS  Status;
  UINTN       Index;
  NET_BUF     *Nbuf;

  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
  ASSERT ((Count > 0) && (MnpServiceData->BufferLength > 0));

  Status = EFI_SUCCESS;

  for (Index = 0; Index < Count; Index++) {

    Nbuf = NetbufAlloc (MnpServiceData->BufferLength);
    if (Nbuf == NULL) {

      MNP_DEBUG_ERROR (("MnpAddFreeNbuf: NetBufAlloc failed.\n"));
      Status = EFI_OUT_OF_RESOURCES;
      break;
    }

    NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);
  }

  MnpServiceData->NbufCnt += Index;

  return Status;
}

NET_BUF *
MnpAllocNbuf (
  IN MNP_SERVICE_DATA  *MnpServiceData
  )
/*++

Routine Description:

  Allocate a free NET_BUF from MnpServiceData->FreeNbufQue. If there is none
  in the queue, first try to allocate some and add them into the queue, then
  fetch the NET_BUF from the updated FreeNbufQue.

Arguments:

  MnpServiceData - Pointer to the MNP_SERVICE_DATA.

Returns:

  Pointer to the allocated free NET_BUF structure, if NULL the operation is failed.

--*/
{
  EFI_STATUS    Status;
  NET_BUF_QUEUE *FreeNbufQue;
  NET_BUF       *Nbuf;

  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);

  FreeNbufQue = &MnpServiceData->FreeNbufQue;

  //
  // Check whether there are available buffers, or else try to add some.
  //
  if (FreeNbufQue->BufNum == 0) {

    if ((MnpServiceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {

      MNP_DEBUG_ERROR (
        ("MnpAllocNbuf: The maximum NET_BUF size is reached ""for MNP driver instance %p.\n",
        MnpServiceData)
        );
      return NULL;
    }

    Status = MnpAddFreeNbuf (MnpServiceData, MNP_NET_BUFFER_INCREASEMENT);
    if (EFI_ERROR (Status)) {

      MNP_DEBUG_ERROR (
        ("MnpAllocNbuf: Failed to add NET_BUFs into the ""FreeNbufQue, %r.\n",
        Status)
        );
      //
      // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
      // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
      //
    }
  }

  Nbuf = NetbufQueRemove (FreeNbufQue);

  //
  // Increase the RefCnt.
  //
  if (Nbuf != NULL) {
    NET_GET_REF (Nbuf);
  }

  return Nbuf;
}

VOID
MnpFreeNbuf (
  IN MNP_SERVICE_DATA  *MnpServiceData,
  IN NET_BUF           *Nbuf
  )
/*++

Routine Description:

  Try to reclaim the Nbuf into the buffer pool.

Arguments:

  MnpServiceData - Pointer to the mnp service context data.
  Nbuf           - Pointer to the NET_BUF to free.

Returns:

  None.

--*/
{
  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
  ASSERT (Nbuf->RefCnt > 1);

  NET_PUT_REF (Nbuf);

  if (Nbuf->RefCnt == 1) {
    //
    // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
    //
    NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_TAIL);
    NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);
  }
}

EFI_STATUS
MnpInitializeServiceData (
  IN MNP_SERVICE_DATA  *MnpServiceData,
  IN EFI_HANDLE        ImageHandle,
  IN EFI_HANDLE        ControllerHandle
  )
/*++

Routine Description:

  Initialize the mnp service context data.

Arguments:

  MnpServiceData - Pointer to the mnp service context data.
  Snp            - Pointer to the simple network protocol.

Returns:

  EFI_SUCCESS - The mnp service context is initialized.
  Other       - Some error occurs.

--*/
{
  EFI_STATUS                   Status;
  EFI_SIMPLE_NETWORK_PROTOCOL  *Snp;
  EFI_SIMPLE_NETWORK_MODE      *SnpMode;

  MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;

  MnpServiceData->ControllerHandle = ControllerHandle;

  //
  // Copy the ServiceBinding structure.
  //
  MnpServiceData->ServiceBinding = mMnpServiceBindingProtocol;

  //
  // Open the Simple Network protocol.
  //
  Status = gBS->OpenProtocol (
                  ControllerHandle,
                  &gEfiSimpleNetworkProtocolGuid,
                  (VOID **) &Snp,
                  ImageHandle,
                  ControllerHandle,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );
  if (EFI_ERROR (Status)) {
    return EFI_UNSUPPORTED;
  }

  //
  // Get MTU from Snp.
  //
  SnpMode             = Snp->Mode;
  MnpServiceData->Snp = Snp;
  MnpServiceData->Mtu = SnpMode->MaxPacketSize;

  //
  // Initialize the lists.
  //
  NetListInit (&MnpServiceData->GroupAddressList);
  NetListInit (&MnpServiceData->ChildrenList);

  //
  // Initialize the locks.
  //
  NET_GLOBAL_LOCK_INIT (&MnpServiceData->ChildrenListLock);
  NET_GLOBAL_LOCK_INIT (&MnpServiceData->GroupAddressLock);
  NET_GLOBAL_LOCK_INIT (&MnpServiceData->TxLock);

  //
  // Get the buffer length used to allocate NET_BUF to hold data received
  // from SNP. Do this before fill the FreeNetBufQue.
  //
  MnpServiceData->BufferLength = MnpServiceData->Mtu + SnpMode->MediaHeaderSize + NET_ETHER_FCS_SIZE;

  //
  // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
  //
  NetbufQueInit (&MnpServiceData->FreeNbufQue);
  Status = MnpAddFreeNbuf (MnpServiceData, MNP_INIT_NET_BUFFER_NUM);
  if (EFI_ERROR (Status)) {

    MNP_DEBUG_ERROR (("MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status));
    goto ERROR;
  }
  //
  // Get one NET_BUF from the FreeNbufQue for rx cache.
  //
  MnpServiceData->RxNbufCache = MnpAllocNbuf (MnpServiceData);
  NetbufAllocSpace (
    MnpServiceData->RxNbufCache,
    MnpServiceData->BufferLength,
    NET_BUF_TAIL
    );

  //
  // Allocate buffer pool for tx.
  //
  MnpServiceData->TxBuf = NetAllocatePool (MnpServiceData->Mtu + SnpMode->MediaHeaderSize);
  if (MnpServiceData->TxBuf == NULL) {

    MNP_DEBUG_ERROR (("MnpInitializeServiceData: NetAllocatePool failed.\n"));
    Status = EFI_OUT_OF_RESOURCES;

    goto ERROR;
  }

  //
  // Create the system poll timer.
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL | EFI_EVENT_TIMER,
                  NET_TPL_SYSTEM_POLL,
                  MnpSystemPoll,
                  MnpServiceData,
                  &MnpServiceData->PollTimer
                  );
  if (EFI_ERROR (Status)) {

    MNP_DEBUG_ERROR (("MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));
    goto ERROR;
  }

  //
  // Create the timer for packet timeout check.
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL | EFI_EVENT_TIMER,
                  NET_TPL_EVENT,
                  MnpCheckPacketTimeout,
                  MnpServiceData,
                  &MnpServiceData->TimeoutCheckTimer
                  );
  if (EFI_ERROR (Status)) {

    MNP_DEBUG_ERROR (("MnpInitializeServiceData: CreateEvent for packet ""timeout check failed.\n"));
    goto ERROR;
  }

  //
  // Create the timer for tx timeout check.
  //
  Status = gBS->CreateEvent (
                  EFI_EVENT_TIMER,
                  NET_TPL_SLOW_TIMER,
                  NULL,
                  NULL,
                  &MnpServiceData->TxTimeoutEvent
                  );
  if (EFI_ERROR (Status)) {

    MNP_DEBUG_ERROR (("MnpInitializeServiceData: CreateEvent for tx ""timeout event failed.\n"));
  }

ERROR:

  if (EFI_ERROR (Status)) {
    //
    // Free the dynamic allocated resources if necessary.
    //
    if (MnpServiceData->TimeoutCheckTimer != NULL) {

      gBS->CloseEvent (MnpServiceData->TimeoutCheckTimer);
    }

    if (MnpServiceData->PollTimer != NULL) {

      gBS->CloseEvent (MnpServiceData->PollTimer);
    }

    if (MnpServiceData->TxBuf != NULL) {

      NetFreePool (MnpServiceData->TxBuf);
    }

    if (MnpServiceData->RxNbufCache != NULL) {

      MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);
    }

    if (MnpServiceData->FreeNbufQue.BufNum != 0) {

      NetbufQueFlush (&MnpServiceData->FreeNbufQue);
    }
  }

  return Status;
}

VOID
MnpFlushServiceData (
  MNP_SERVICE_DATA  *MnpServiceData
  )
/*++

Routine Description:

  Flush the mnp service context data.

Arguments:

  MnpServiceData - Pointer to the mnp service context data.

Returns:

  None.

--*/
{
  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);

  //
  // The GroupAddressList must be empty.
  //
  ASSERT (NetListIsEmpty (&MnpServiceData->GroupAddressList));

  //
  // Close the event.
  //
  gBS->CloseEvent (&MnpServiceData->TxTimeoutEvent);
  gBS->CloseEvent (&MnpServiceData->TimeoutCheckTimer);
  gBS->CloseEvent (&MnpServiceData->PollTimer);

  //
  // Free the tx buffer.
  //
  NetFreePool (MnpServiceData->TxBuf);

  //
  // Free the RxNbufCache.
  //
  MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);

  //
  // Flush the FreeNbufQue.
  //
  MnpServiceData->NbufCnt -= MnpServiceData->FreeNbufQue.BufNum;
  NetbufQueFlush (&MnpServiceData->FreeNbufQue);

  DEBUG_CODE (

    if (MnpServiceData->NbufCnt != 0) {

    MNP_DEBUG_WARN (("MnpFlushServiceData: Memory leak, ""MnpServiceData->NbufCnt != 0.\n"));
  }
  );
}

VOID
MnpInitializeInstanceData (
  IN MNP_SERVICE_DATA   *MnpServiceData,
  IN MNP_INSTANCE_DATA  *Instance
  )
/*++

Routine Description:

⌨️ 快捷键说明

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