mnpconfig.c

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

C
1,577
字号
  if (OldConfigData->EnableBroadcastReceive) {
    MnpServiceData->BroadcastCount--;
  }

  if (OldConfigData->EnablePromiscuousReceive) {
    MnpServiceData->PromiscuousCount--;
  }

  //
  // Set the receive filter counters and the receive filter of the
  // instance according to the new ConfigData.
  //
  if (NewConfigData->EnableUnicastReceive) {
    MnpServiceData->UnicastCount++;
    Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;
  }

  if (NewConfigData->EnableMulticastReceive) {
    MnpServiceData->MulticastCount++;
  }

  if (NewConfigData->EnableBroadcastReceive) {
    MnpServiceData->BroadcastCount++;
    Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;
  }

  if (NewConfigData->EnablePromiscuousReceive) {
    MnpServiceData->PromiscuousCount++;
  }

  if (EFI_ERROR (NET_TRYLOCK (&Instance->RxLock))) {

    return EFI_ACCESS_DENIED;
  }

  if (OldConfigData->FlushQueuesOnReset) {

    MnpFlushRcvdDataQueue (Instance);
  }

  if (ConfigData == NULL) {

    NetMapIterate (&Instance->RxTokenMap, MnpCancelTokens, NULL);
  }

  NET_UNLOCK (&Instance->RxLock);

  if (!NewConfigData->EnableMulticastReceive) {

    if (EFI_ERROR (NET_TRYLOCK (&MnpServiceData->GroupAddressLock))) {

      return EFI_ACCESS_DENIED;
    }

    MnpGroupOp (Instance, FALSE, NULL, NULL);

    NET_UNLOCK (&MnpServiceData->GroupAddressLock);
  }

  //
  // Save the new configuration data.
  //
  *OldConfigData        = *NewConfigData;

  Instance->Configured  = (BOOLEAN) (ConfigData != NULL);

  if (Instance->Configured) {
    //
    // The instance is configured, start the Mnp.
    //
    Status = MnpStart (
              MnpServiceData,
              IsConfigUpdate,
              !NewConfigData->DisableBackgroundPolling
              );
  } else {
    //
    // The instance is changed to the unconfigured state, stop the Mnp.
    //
    Status = MnpStop (MnpServiceData);
  }

  return Status;
}

STATIC
EFI_STATUS
MnpConfigReceiveFilters (
  IN MNP_SERVICE_DATA  *MnpServiceData
  )
/*++

Routine Description:

  Configure the Snp receive filters according to the instances' receive filter
  settings.

Arguments:

  MnpServiceData - Pointer to the mnp service context data.

Returns:

  EFI_SUCCESS          - The receive filters is configured.
  EFI_OUT_OF_RESOURCES - The receive filters can't be configured due to lack of
                         memory resource.

--*/
{
  EFI_STATUS                  Status;
  EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
  EFI_MAC_ADDRESS             *MCastFilter;
  UINT32                      MCastFilterCnt;
  UINT32                      EnableFilterBits;
  UINT32                      DisableFilterBits;
  BOOLEAN                     ResetMCastFilters;
  NET_LIST_ENTRY              *Entry;
  UINT32                      Index;
  MNP_GROUP_ADDRESS           *GroupAddress;

  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);

  Snp = MnpServiceData->Snp;

  //
  // Initialize the enable filter and disable filter.
  //
  EnableFilterBits  = 0;
  DisableFilterBits = Snp->Mode->ReceiveFilterMask;

  if (MnpServiceData->UnicastCount != 0) {
    //
    // Enable unicast if any instance wants to receive unicast.
    //
    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
  }

  if (MnpServiceData->BroadcastCount != 0) {
    //
    // Enable broadcast if any instance wants to receive broadcast.
    //
    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
  }

  MCastFilter       = NULL;
  MCastFilterCnt    = 0;
  ResetMCastFilters = TRUE;

  if ((MnpServiceData->MulticastCount != 0) && (MnpServiceData->GroupAddressCount != 0)) {
    //
    // There are instances configured to receive multicast and already some group
    // addresses are joined.
    //

    ResetMCastFilters = FALSE;

    if (MnpServiceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {
      //
      // The joind group address is less than simple network's maximum count.
      // Just configure the snp to do the multicast filtering.
      //

      EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;

      //
      // Allocate pool for the mulicast addresses.
      //
      MCastFilterCnt  = MnpServiceData->GroupAddressCount;
      MCastFilter     = NetAllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);
      if (MCastFilter == NULL) {

        MNP_DEBUG_ERROR (("MnpConfigReceiveFilters: Failed to allocate memory"" resource for MCastFilter.\n"));
        return EFI_OUT_OF_RESOURCES;
      }

      //
      // Fill the multicast HW address buffer.
      //
      Index = 0;
      NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {

        GroupAddress            = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
        *(MCastFilter + Index)  = GroupAddress->Address;
        Index++;

        ASSERT (Index <= MCastFilterCnt);
      }
    } else {
      //
      // The maximum multicast is reached, set the filter to be promiscuous
      // multicast.
      //

      if (Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {
        EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
      } else {
        //
        // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
        // set the NIC to be promiscuous although this will tremendously degrade
        // the performance.
        //
        EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
      }
    }
  }

  if (MnpServiceData->PromiscuousCount != 0) {
    //
    // Enable promiscuous if any instance wants to receive promiscuous.
    //
    EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
  }

  //
  // Set the disable filter.
  //
  DisableFilterBits ^= EnableFilterBits;

  //
  // Configure the receive filters of SNP.
  //
  Status = Snp->ReceiveFilters (
                  Snp,
                  EnableFilterBits,
                  DisableFilterBits,
                  ResetMCastFilters,
                  MCastFilterCnt,
                  MCastFilter
                  );
  DEBUG_CODE (
    if (EFI_ERROR (Status)) {

    MNP_DEBUG_ERROR (
      ("MnpConfigReceiveFilters: Snp->ReceiveFilters ""failed, %r.\n",
      Status)
      );
  }
  );

  if (MCastFilter != NULL) {
    //
    // Free the buffer used to hold the group addresses.
    //
    NetFreePool (MCastFilter);
  }

  return Status;
}

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
  )
/*++

Routine Description:

  Add a group address control block which controls the MacAddress for
  this instance.

Arguments:

  Instance      - Pointer to the mnp instance context data.
  CtrlBlk       - Pointer to the group address control block.
  GroupAddress  - Pointer to the group adress.
  MacAddress    - Pointer to the mac address.
  HwAddressSize - The hardware address size.

Returns:

  EFI_SUCCESS         - The group address control block is added.
  EFI_OUT_OF_RESOURCE - Failed due to lack of memory resources.

--*/
{
  MNP_SERVICE_DATA  *MnpServiceData;

  NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);

  MnpServiceData = Instance->MnpServiceData;
  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);

  if (GroupAddress == NULL) {

    ASSERT (MacAddress != NULL);

    //
    // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
    //
    GroupAddress = NetAllocatePool (sizeof (MNP_GROUP_ADDRESS));
    if (GroupAddress == NULL) {

      MNP_DEBUG_ERROR (("MnpGroupOpFormCtrlBlk: Failed to allocate memory ""resource.\n"));

      return EFI_OUT_OF_RESOURCES;
    }

    GroupAddress->Address = *MacAddress;
    GroupAddress->RefCnt  = 0;
    NetListInsertTail (
      &MnpServiceData->GroupAddressList,
      &GroupAddress->AddrEntry
      );
    MnpServiceData->GroupAddressCount++;
  }

  //
  // Increase the RefCnt.
  //
  GroupAddress->RefCnt++;

  //
  // Add the CtrlBlk into the instance's GroupCtrlBlkList.
  //
  CtrlBlk->GroupAddress = GroupAddress;
  NetListInsertTail (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);

  return EFI_SUCCESS;
}

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

Routine Description:

  Delete a group control block from the instance. If the controlled group address's
  reference count reaches zero, the group address is removed too.

Arguments:

  Instance - Pointer to the instance context data.
  CtrlBlk  - Pointer to the group control block to delete.

Returns:

  The group address controlled by the control block is no longer used or not.

--*/
{
  MNP_SERVICE_DATA  *MnpServiceData;
  MNP_GROUP_ADDRESS *GroupAddress;

  NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);

  MnpServiceData = Instance->MnpServiceData;
  NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);

  //
  // Remove and free the CtrlBlk.
  //
  GroupAddress = CtrlBlk->GroupAddress;
  NetListRemoveEntry (&CtrlBlk->CtrlBlkEntry);
  NetFreePool (CtrlBlk);

  ASSERT (GroupAddress->RefCnt > 0);

  //
  // Count down the RefCnt.
  //
  GroupAddress->RefCnt--;

  if (GroupAddress->RefCnt == 0) {
    //
    // Free this GroupAddress entry if no instance uses it.
    //
    MnpServiceData->GroupAddressCount--;
    NetListRemoveEntry (&GroupAddress->AddrEntry);
    NetFreePool (GroupAddress);

    return TRUE;
  }

  return FALSE;
}

EFI_STATUS
MnpGroupOp (
  IN MNP_INSTANCE_DATA        *Instance,
  IN BOOLEAN                  JoinFlag,
  IN EFI_MAC_ADDRESS          *MacAddress OPTIONAL,
  IN MNP_GROUP_CONTROL_BLOCK  *CtrlBlk OPTIONAL
  )
/*++

Routine Description:

  Do the group operations for this instance.

Arguments:

  Instance   - Pointer to the instance context data.
  JoinFlag   - Set to TRUE to join a group. Set to TRUE to leave a group/groups.
  MacAddress - Pointer to the group address to join or leave.
  CtrlBlk    - Pointer to the group control block if JoinFlag if FALSE.

Returns:

  EFI_SUCCESS - The group operation finished.
  Other       - Some error occurs.

--*/
{
  MNP_SERVICE_DATA        *MnpServiceData;
  NET_LIST_ENTRY          *Entry;
  NET_LIST_ENTRY          *NextEntry;
  MNP_GROUP_ADDRESS       *GroupAddress;
  EFI_SIMPLE_NETWORK_MODE *SnpMode;
  MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;
  EFI_STATUS              Status;
  BOOLEAN                 AddressExist;
  BOOLEAN                 NeedUpdate;

  NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);

  MnpServiceData  = Instance->MnpServiceData;
  SnpMode         = MnpServiceData->Snp->Mode;

  if (JoinFlag) {
    //
    // A new gropu address is to be added.
    //

    GroupAddress  = NULL;
    AddressExist  = FALSE;

    //
    // Allocate memory for the control block.
    //
    NewCtrlBlk    = NetAllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));
    if (NewCtrlBlk == NULL) {

      MNP_DEBUG_ERROR (("MnpGroupOp: Failed to allocate memory resource.\n"));
      return EFI_OUT_OF_RESOURCES;
    }

    NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {
      //
      // Check whether the MacAddress is already joined by other instances.
      //
      GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
      if (0 == NetCompareMem (
                MacAddress,
                &GroupAddress->Address,
                SnpMode->HwAddressSize
                )) {

        AddressExist = TRUE;
        break;
      }
    }

    if (!AddressExist) {
      GroupAddress = NULL;
    }

    //
    // Add the GroupAddress for this instance.
    //
    Status = MnpGroupOpAddCtrlBlk (
              Instance,
              NewCtrlBlk,
              GroupAddress,
              MacAddress,
              SnpMode->HwAddressSize
              );
    if (EFI_ERROR (Status)) {

      return Status;
    }

    NeedUpdate = TRUE;
  } else {

    if (MacAddress != NULL) {

      ASSERT (CtrlBlk != NULL);

      //
      // Leave the specific multicast mac address.
      //
      NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);
    } else {
      //
      // Leave all multicast mac addresses.
      //
      NeedUpdate = FALSE;

      NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {

        NewCtrlBlk = NET_LIST_USER_STRUCT (
                      Entry,
                      MNP_GROUP_CONTROL_BLOCK,
                      CtrlBlkEntry
                      );
        //
        // Update is required if the group address left is no longer used
        // by other instances.
        //
        NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);
      }
    }
  }

  Status = EFI_SUCCESS;

  if (NeedUpdate) {
    //
    // Reconfigure the receive filters if necessary.
    //
    Status = MnpConfigReceiveFilters (MnpServiceData);
  }

  return Status;
}

⌨️ 快捷键说明

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