summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c')
-rw-r--r--MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c655
1 files changed, 655 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c b/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c
new file mode 100644
index 0000000000..02c0065c34
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/MnpDxe/MnpMain.c
@@ -0,0 +1,655 @@
+/** @file
+
+Copyright (c) 2005 - 2007, 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:
+
+ MnpMain.c
+
+Abstract:
+
+ Implementation of Managed Network Protocol public services.
+
+
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+
+#include "MnpImpl.h"
+
+
+/**
+ Get configuration data of this instance.
+
+ @param This Pointer to the Managed Network Protocol.
+ @param MnpConfigData Pointer to strorage for MNP operational
+ parameters.
+ @param SnpModeData Pointer to strorage for SNP operational
+ parameters.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_STARTED This MNP child driver instance has not been
+ configured The default values are returned in
+ MnpConfigData if it is not NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+MnpGetModeData (
+ IN EFI_MANAGED_NETWORK_PROTOCOL *This,
+ OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
+ OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
+ )
+{
+ MNP_INSTANCE_DATA *Instance;
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+
+ if (This == NULL) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
+
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
+
+ if (MnpConfigData != NULL) {
+ //
+ // Copy the instance configuration data.
+ //
+ *MnpConfigData = Instance->ConfigData;
+ }
+
+ if (SnpModeData != NULL) {
+ //
+ // Copy the underlayer Snp mode data.
+ //
+ Snp = Instance->MnpServiceData->Snp;
+ *SnpModeData = *(Snp->Mode);
+ }
+
+ if (!Instance->Configured) {
+ Status = EFI_NOT_STARTED;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+
+ NET_RESTORE_TPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Set or clear the operational parameters for the MNP child driver.
+
+ @param This Pointer to the Managed Network Protocol.
+ @param MnpConfigData Pointer to the configuration data that will be
+ assigned to the MNP child driver instance. If
+ NULL, the MNP child driver instance is reset to
+ startup defaults and all pending transmit and
+ receive requests are flushed.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Required system resources (usually memory) could
+ not be allocated.
+ @retval EFI_UNSUPPORTED EnableReceiveTimestamps is TRUE, this
+ implementation doesn't support it.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Other The MNP child driver instance has been reset to
+ startup defaults.
+
+**/
+EFI_STATUS
+EFIAPI
+MnpConfigure (
+ IN EFI_MANAGED_NETWORK_PROTOCOL *This,
+ IN EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL
+ )
+{
+ MNP_INSTANCE_DATA *Instance;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+
+ if ((This == NULL) ||
+ ((MnpConfigData != NULL) &&
+ (MnpConfigData->ProtocolTypeFilter > 0) &&
+ (MnpConfigData->ProtocolTypeFilter <= 1500))) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
+
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
+
+ if ((MnpConfigData == NULL) && (!Instance->Configured)) {
+ //
+ // If the instance is not configured and a reset is requested, just return.
+ //
+ Status = EFI_SUCCESS;
+ goto ON_EXIT;
+ }
+
+ //
+ // Configure the instance.
+ //
+ Status = MnpConfigureInstance (Instance, MnpConfigData);
+
+ON_EXIT:
+ NET_RESTORE_TPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Translate a multicast IP address to a multicast hardware (MAC) address.
+
+ @param This Pointer to the Managed Network Protocol.
+ @param Ipv6Flag Set to TRUE if IpAddress is an IPv6 multicast
+ address. Set to FALSE if IpAddress is an IPv4
+ multicast address.
+ @param IpAddress Pointer to the multicast IP address to convert.
+ @param MacAddress Pointer to the resulting multicast MAC address.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more parameter is invalid.
+ @retval EFI_NOT_STARTED This MNP child driver instance has not been
+ configured.
+ @retval EFI_UNSUPPORTED Ipv6Flag is TRUE, this implementation doesn't
+ supported it.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Other The address could not be converted.
+
+**/
+EFI_STATUS
+EFIAPI
+MnpMcastIpToMac (
+ IN EFI_MANAGED_NETWORK_PROTOCOL *This,
+ IN BOOLEAN Ipv6Flag,
+ IN EFI_IP_ADDRESS *IpAddress,
+ OUT EFI_MAC_ADDRESS *MacAddress
+ )
+{
+ EFI_STATUS Status;
+ MNP_INSTANCE_DATA *Instance;
+ EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (IpAddress == NULL) || (MacAddress == NULL)) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Ipv6Flag) {
+ //
+ // Currently IPv6 isn't supported.
+ //
+ return EFI_UNSUPPORTED;
+ }
+
+ if (!IP4_IS_MULTICAST (EFI_NTOHL (*IpAddress))) {
+ //
+ // The IPv4 address passed in is not a multicast address.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
+
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
+
+ if (!Instance->Configured) {
+
+ Status = EFI_NOT_STARTED;
+ goto ON_EXIT;
+ }
+
+ Snp = Instance->MnpServiceData->Snp;
+ ASSERT (Snp != NULL);
+
+ if (Snp->Mode->IfType == NET_IFTYPE_ETHERNET) {
+ //
+ // Translate the IPv4 address into a multicast MAC address if the NIC is an
+ // ethernet NIC.
+ //
+ MacAddress->Addr[0] = 0x01;
+ MacAddress->Addr[1] = 0x00;
+ MacAddress->Addr[2] = 0x5E;
+ MacAddress->Addr[3] = IpAddress->v4.Addr[1] & 0x7F;
+ MacAddress->Addr[4] = IpAddress->v4.Addr[2];
+ MacAddress->Addr[5] = IpAddress->v4.Addr[3];
+
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // Invoke Snp to translate the multicast IP address.
+ //
+ Status = Snp->MCastIpToMac (
+ Snp,
+ Ipv6Flag,
+ IpAddress,
+ MacAddress
+ );
+ }
+
+ON_EXIT:
+ NET_RESTORE_TPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Enable or disable receie filters for multicast address.
+
+ @param This Pointer to the Managed Network Protocol.
+ @param JoinFlag Set to TRUE to join this multicast group. Set to
+ FALSE to leave this multicast group.
+ @param MacAddress Pointer to the multicast MAC group (address) to
+ join or leave.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more parameter is invalid
+ @retval EFI_NOT_STARTED This MNP child driver instance has not been
+ configured.
+ @retval EFI_ALREADY_STARTED The supplied multicast group is already joined.
+ @retval EFI_NOT_FOUND The supplied multicast group is not joined.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Other The requested operation could not be completed.
+ The MNP multicast group settings are unchanged.
+
+**/
+EFI_STATUS
+EFIAPI
+MnpGroups (
+ IN EFI_MANAGED_NETWORK_PROTOCOL *This,
+ IN BOOLEAN JoinFlag,
+ IN EFI_MAC_ADDRESS *MacAddress OPTIONAL
+ )
+{
+ MNP_INSTANCE_DATA *Instance;
+ EFI_SIMPLE_NETWORK_MODE *SnpMode;
+ MNP_GROUP_CONTROL_BLOCK *GroupCtrlBlk;
+ MNP_GROUP_ADDRESS *GroupAddress;
+ NET_LIST_ENTRY *ListEntry;
+ BOOLEAN AddressExist;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+
+ if (This == NULL || (JoinFlag && (MacAddress == NULL))) {
+ //
+ // This is NULL, or it's a join operation but MacAddress is NULL.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
+ SnpMode = Instance->MnpServiceData->Snp->Mode;
+
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
+
+ if (!Instance->Configured) {
+
+ Status = EFI_NOT_STARTED;
+ goto ON_EXIT;
+ }
+
+ if ((!Instance->ConfigData.EnableMulticastReceive) ||
+ ((MacAddress != NULL) && !NET_MAC_IS_MULTICAST (MacAddress, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize))) {
+ //
+ // The instance isn't configured to do mulitcast receive. OR
+ // the passed in MacAddress is not a mutlticast mac address.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Status = EFI_SUCCESS;
+ AddressExist = FALSE;
+ GroupCtrlBlk = NULL;
+
+ if (MacAddress != NULL) {
+ //
+ // Search the instance's GroupCtrlBlkList to find the specific address.
+ //
+ NET_LIST_FOR_EACH (ListEntry, &Instance->GroupCtrlBlkList) {
+
+ GroupCtrlBlk = NET_LIST_USER_STRUCT (
+ ListEntry,
+ MNP_GROUP_CONTROL_BLOCK,
+ CtrlBlkEntry
+ );
+ GroupAddress = GroupCtrlBlk->GroupAddress;
+ if (0 == NetCompareMem (
+ MacAddress,
+ &GroupAddress->Address,
+ SnpMode->HwAddressSize
+ )) {
+ //
+ // There is already the same multicast mac address configured.
+ //
+ AddressExist = TRUE;
+ break;
+ }
+ }
+
+ if (JoinFlag && AddressExist) {
+ //
+ // The multicast mac address to join already exists.
+ //
+ Status = EFI_ALREADY_STARTED;
+ }
+
+ if (!JoinFlag && !AddressExist) {
+ //
+ // The multicast mac address to leave doesn't exist in this instance.
+ //
+ Status = EFI_NOT_FOUND;
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ } else if (NetListIsEmpty (&Instance->GroupCtrlBlkList)) {
+ //
+ // The MacAddress is NULL and there is no configured multicast mac address,
+ // just return.
+ //
+ goto ON_EXIT;
+ }
+
+ //
+ // OK, it is time to take action.
+ //
+ Status = MnpGroupOp (Instance, JoinFlag, MacAddress, GroupCtrlBlk);
+
+ON_EXIT:
+ NET_RESTORE_TPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Place an outgoing packet into the transmit queue.
+
+ @param This Pointer to the Managed Network Protocol.
+ @param Token Pointer to a token associated with the transmit
+ data descriptor.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_INVALID_PARAMETER One or more parameter is invalid
+ @retval EFI_NOT_STARTED This MNP child driver instance has not been
+ configured.
+ @retval EFI_ACCESS_DENIED The transmit completion token is already in the
+ transmit queue.
+ @retval EFI_OUT_OF_RESOURCES The transmit data could not be queued due to a
+ lack of system resources (usually memory).
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ The MNP child driver instance has been reset to
+ startup defaults.
+ @retval EFI_NOT_READY The transmit request could not be queued because
+ the transmit queue is full.
+
+**/
+EFI_STATUS
+EFIAPI
+MnpTransmit (
+ IN EFI_MANAGED_NETWORK_PROTOCOL *This,
+ IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
+ )
+{
+ EFI_STATUS Status;
+ MNP_INSTANCE_DATA *Instance;
+ MNP_SERVICE_DATA *MnpServiceData;
+ UINT8 *PktBuf;
+ UINT32 PktLen;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (Token == NULL)) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
+
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
+
+ if (!Instance->Configured) {
+
+ Status = EFI_NOT_STARTED;
+ goto ON_EXIT;
+ }
+
+ if (!MnpIsValidTxToken (Instance, Token)) {
+ //
+ // The Token is invalid.
+ //
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ MnpServiceData = Instance->MnpServiceData;
+ NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
+
+ //
+ // Build the tx packet
+ //
+ MnpBuildTxPacket (MnpServiceData, Token->Packet.TxData, &PktBuf, &PktLen);
+
+ //
+ // OK, send the packet synchronously.
+ //
+ Status = MnpSyncSendPacket (MnpServiceData, PktBuf, PktLen, Token);
+
+ON_EXIT:
+ NET_RESTORE_TPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Place an asynchronous receiving request into the receiving queue.
+
+ @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL
+ instance.
+ @param Token Pointer to a token associated with the receive
+ data descriptor.
+
+ @retval EFI_SUCCESS The receive completion token was cached.
+ @retval EFI_NOT_STARTED This MNP child driver instance has not been
+ configured.
+ @retval EFI_INVALID_PARAMETER One or more parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES The transmit data could not be queued due to a
+ lack of system resources (usually memory).
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ The MNP child driver instance has been reset to
+ startup defaults.
+ @retval EFI_ACCESS_DENIED The receive completion token was already in the
+ receive queue.
+ @retval EFI_NOT_READY The receive request could not be queued because
+ the receive queue is full.
+
+**/
+EFI_STATUS
+EFIAPI
+MnpReceive (
+ IN EFI_MANAGED_NETWORK_PROTOCOL *This,
+ IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
+ )
+{
+ EFI_STATUS Status;
+ MNP_INSTANCE_DATA *Instance;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (Token == NULL) || (Token->Event == NULL)) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
+
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
+
+ if (!Instance->Configured) {
+
+ Status = EFI_NOT_STARTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Check whether this token(event) is already in the rx token queue.
+ //
+ Status = NetMapIterate (&Instance->RxTokenMap, MnpTokenExist, (VOID *) Token);
+ if (EFI_ERROR (Status)) {
+
+ goto ON_EXIT;
+ }
+
+ //
+ // Insert the Token into the RxTokenMap.
+ //
+ Status = NetMapInsertTail (&Instance->RxTokenMap, (VOID *) Token, NULL);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Try to deliver any buffered packets.
+ //
+ Status = MnpInstanceDeliverPacket (Instance);
+ }
+
+ON_EXIT:
+ NET_RESTORE_TPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Abort a pending transmit or receive request.
+
+ @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL
+ instance.
+ @param Token Pointer to a token that has been issued by
+ EFI_MANAGED_NETWORK_PROTOCOL.Transmit() or
+ EFI_MANAGED_NETWORK_PROTOCOL.Receive(). If NULL,
+ all pending tokens are aborted.
+
+ @retval EFI_SUCCESS The asynchronous I/O request was aborted and
+ Token->Event was signaled.
+ @retval EFI_NOT_STARTED This MNP child driver instance has not been
+ configured.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_FOUND The asynchronous I/O request was not found in the
+ transmit or receive queue. It has either completed
+ or was not issued by Transmit() and Receive().
+
+**/
+EFI_STATUS
+EFIAPI
+MnpCancel (
+ IN EFI_MANAGED_NETWORK_PROTOCOL *This,
+ IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ MNP_INSTANCE_DATA *Instance;
+ EFI_TPL OldTpl;
+
+ if (This == NULL) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
+
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
+
+ if (!Instance->Configured) {
+
+ Status = EFI_NOT_STARTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Iterate the RxTokenMap to cancel the specified Token.
+ //
+ Status = NetMapIterate (&Instance->RxTokenMap, MnpCancelTokens, (VOID *) Token);
+
+ if (Token != NULL) {
+
+ Status = (Status == EFI_ABORTED) ? EFI_SUCCESS : EFI_NOT_FOUND;
+ }
+
+ON_EXIT:
+ NET_RESTORE_TPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Poll the network interface to do transmit/receive work.
+
+ @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL
+ instance.
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_NOT_STARTED This MNP child driver instance has not been
+ configured.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ The MNP child driver instance has been reset to
+ startup defaults.
+ @retval EFI_NOT_READY No incoming or outgoing data was processed.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or
+ receive queue.
+
+**/
+EFI_STATUS
+EFIAPI
+MnpPoll (
+ IN EFI_MANAGED_NETWORK_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ MNP_INSTANCE_DATA *Instance;
+ EFI_TPL OldTpl;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
+
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
+
+ if (!Instance->Configured) {
+ Status = EFI_NOT_STARTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Try to receive packets.
+ //
+ Status = MnpReceivePacket (Instance->MnpServiceData);
+
+ON_EXIT:
+ NET_RESTORE_TPL (OldTpl);
+
+ return Status;
+}