--- /dev/null
+/**@file\r
+ Windows Packet Filter implementation of the EMU_SNP_PROTOCOL that allows the\r
+ emulator to get on real networks.\r
+\r
+Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>\r
+Portions copyright (c) 2011, Apple Inc. All rights reserved.\r
+(C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>\r
+\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#include "WinHost.h"\r
+\r
+#define NETWORK_LIBRARY_NAME_U L"SnpNt32Io.dll"\r
+#define NETWORK_LIBRARY_INITIALIZE "SnpInitialize"\r
+#define NETWORK_LIBRARY_FINALIZE "SnpFinalize"\r
+#define NETWORK_LIBRARY_SET_RCV_FILTER "SnpSetReceiveFilter"\r
+#define NETWORK_LIBRARY_RECEIVE "SnpReceive"\r
+#define NETWORK_LIBRARY_TRANSMIT "SnpTransmit"\r
+\r
+#pragma pack(1)\r
+typedef struct _NT_NET_INTERFACE_INFO {\r
+ UINT32 InterfaceIndex;\r
+ EFI_MAC_ADDRESS MacAddr;\r
+} NT_NET_INTERFACE_INFO;\r
+#pragma pack()\r
+\r
+#define NET_ETHER_HEADER_SIZE 14\r
+#define MAX_INTERFACE_INFO_NUMBER 16\r
+#define SNP_MAX_TX_BUFFER_NUM 65536\r
+#define SNP_TX_BUFFER_INCREASEMENT 32\r
+#define DEFAULT_SELECTED_NIC_INDEX 0\r
+\r
+//\r
+// Functions in Net Library\r
+//\r
+typedef\r
+INT32\r
+(*NT_NET_INITIALIZE) (\r
+ IN OUT UINT32 *InterfaceCount,\r
+ IN OUT NT_NET_INTERFACE_INFO * InterfaceInfoBuffer\r
+ );\r
+\r
+typedef\r
+INT32\r
+(*NT_NET_FINALIZE) (\r
+ VOID\r
+ );\r
+\r
+typedef\r
+INT32\r
+(*NT_NET_SET_RECEIVE_FILTER) (\r
+ IN UINT32 Index,\r
+ IN UINT32 EnableFilter,\r
+ IN UINT32 MCastFilterCnt,\r
+ IN EFI_MAC_ADDRESS * MCastFilter\r
+ );\r
+\r
+typedef\r
+INT32\r
+(*NT_NET_RECEIVE) (\r
+ IN UINT32 Index,\r
+ IN OUT UINT32 *BufferSize,\r
+ OUT VOID *Buffer\r
+ );\r
+\r
+typedef\r
+INT32\r
+(*NT_NET_TRANSMIT) (\r
+ IN UINT32 Index,\r
+ IN UINT32 HeaderSize,\r
+ IN UINT32 BufferSize,\r
+ IN VOID *Buffer,\r
+ IN EFI_MAC_ADDRESS * SrcAddr,\r
+ IN EFI_MAC_ADDRESS * DestAddr,\r
+ IN UINT16 *Protocol\r
+ );\r
+\r
+typedef struct _NT_NET_UTILITY_TABLE {\r
+ NT_NET_INITIALIZE Initialize;\r
+ NT_NET_FINALIZE Finalize;\r
+ NT_NET_SET_RECEIVE_FILTER SetReceiveFilter;\r
+ NT_NET_RECEIVE Receive;\r
+ NT_NET_TRANSMIT Transmit;\r
+} NT_NET_UTILITY_TABLE;\r
+\r
+//\r
+// Instance data for each fake SNP instance\r
+//\r
+#define WIN_NT_INSTANCE_SIGNATURE SIGNATURE_32 ('N', 'T', 'I', 'S')\r
+\r
+typedef struct {\r
+ UINT32 Signature;\r
+\r
+ //\r
+ // Array of the recycled transmit buffer address.\r
+ //\r
+ UINT64 *RecycledTxBuf;\r
+\r
+ //\r
+ // Current number of recycled buffer pointers in RecycledTxBuf.\r
+ //\r
+ UINT32 RecycledTxBufCount;\r
+\r
+ //\r
+ // The maximum number of recycled buffer pointers in RecycledTxBuf.\r
+ //\r
+ UINT32 MaxRecycledTxBuf;\r
+ EFI_SIMPLE_NETWORK_MODE Mode;\r
+ NT_NET_INTERFACE_INFO InterfaceInfo;\r
+} WIN_NT_INSTANCE_DATA;\r
+\r
+//\r
+// Instance data for each SNP private instance\r
+//\r
+#define WIN_NT_SIMPLE_NETWORK_PRIVATE_SIGNATURE SIGNATURE_32 ('N', 'T', 's', 'n')\r
+\r
+typedef struct {\r
+ UINTN Signature;\r
+ EMU_IO_THUNK_PROTOCOL *Thunk;\r
+ EMU_SNP_PROTOCOL EmuSnp;\r
+ EFI_SIMPLE_NETWORK_MODE *Mode;\r
+ HMODULE NetworkLibraryHandle;\r
+ NT_NET_UTILITY_TABLE NtNetUtilityTable;\r
+ WIN_NT_INSTANCE_DATA Instance;\r
+} WIN_NT_SNP_PRIVATE;\r
+\r
+#define WIN_NT_SNP_PRIVATE_DATA_FROM_THIS(a) \\r
+ CR(a, WIN_NT_SNP_PRIVATE, EmuSnp, WIN_NT_SIMPLE_NETWORK_PRIVATE_SIGNATURE)\r
+\r
+\r
+/**\r
+ Register storage for SNP Mode.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Mode SimpleNetworkProtocol Mode structure passed into driver.\r
+\r
+ @retval EFI_SUCCESS The network interface was started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpCreateMapping (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN EFI_SIMPLE_NETWORK_MODE *Mode\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ Private->Mode = Mode;\r
+\r
+ //\r
+ // Set the broadcast address.\r
+ //\r
+ CopyMem (&Mode->BroadcastAddress, &Private->Instance.Mode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS));\r
+ //\r
+ // Set the MAC address.\r
+ //\r
+ CopyMem (&Mode->CurrentAddress, &Private->Instance.Mode.CurrentAddress, sizeof (EFI_MAC_ADDRESS));\r
+ CopyMem (&Mode->PermanentAddress, &Private->Instance.Mode.PermanentAddress, sizeof (EFI_MAC_ADDRESS));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Changes the state of a network interface from "stopped" to "started".\r
+\r
+ @param This Protocol instance pointer.\r
+\r
+ @retval EFI_SUCCESS The network interface was started.\r
+ @retval EFI_ALREADY_STARTED The network interface is already in the started state.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpStart (\r
+ IN EMU_SNP_PROTOCOL *This\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ switch (Private->Mode->State) {\r
+ case EfiSimpleNetworkStopped:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStarted:\r
+ case EfiSimpleNetworkInitialized:\r
+ return EFI_ALREADY_STARTED;\r
+ break;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ Private->Mode->State = EfiSimpleNetworkStarted;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Changes the state of a network interface from "started" to "stopped".\r
+\r
+ @param This Protocol instance pointer.\r
+\r
+ @retval EFI_SUCCESS The network interface was stopped.\r
+ @retval EFI_ALREADY_STARTED The network interface is already in the stopped state.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpStop (\r
+ IN EMU_SNP_PROTOCOL *This\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ switch ( Private->Mode->State ) {\r
+ case EfiSimpleNetworkStarted:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+ break;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ Private->Mode->State = EfiSimpleNetworkStopped;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Resets a network adapter and allocates the transmit and receive buffers\r
+ required by the network interface; optionally, also requests allocation\r
+ of additional transmit and receive buffers.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space\r
+ that the driver should allocate for the network interface.\r
+ Some network interfaces will not be able to use the extra\r
+ buffer, and the caller will not know if it is actually\r
+ being used.\r
+ @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space\r
+ that the driver should allocate for the network interface.\r
+ Some network interfaces will not be able to use the extra\r
+ buffer, and the caller will not know if it is actually\r
+ being used.\r
+\r
+ @retval EFI_SUCCESS The network interface was initialized.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and\r
+ receive buffers.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpInitialize (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN UINTN ExtraRxBufferSize OPTIONAL,\r
+ IN UINTN ExtraTxBufferSize OPTIONAL\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ switch ( Private->Mode->State ) {\r
+ case EfiSimpleNetworkStarted:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+ break;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ Private->Mode->MCastFilterCount = 0;\r
+ Private->Mode->ReceiveFilterSetting = 0;\r
+ ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter));\r
+\r
+ Private->Mode->State = EfiSimpleNetworkInitialized;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Resets a network adapter and re-initializes it with the parameters that were\r
+ provided in the previous call to Initialize().\r
+\r
+ @param This The protocol instance pointer.\r
+ @param ExtendedVerification Indicates that the driver may perform a more\r
+ exhaustive verification operation of the device\r
+ during reset.\r
+\r
+ @retval EFI_SUCCESS The network interface was reset.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpReset (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN BOOLEAN ExtendedVerification\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ switch ( Private->Mode->State ) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+ break;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Resets a network adapter and leaves it in a state that is safe for\r
+ another driver to initialize.\r
+\r
+ @param This Protocol instance pointer.\r
+\r
+ @retval EFI_SUCCESS The network interface was shutdown.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpShutdown (\r
+ IN EMU_SNP_PROTOCOL *This\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ switch ( Private->Mode->State ) {\r
+ case EfiSimpleNetworkInitialized:\r
+ break;\r
+\r
+ case EfiSimpleNetworkStopped:\r
+ return EFI_NOT_STARTED;\r
+ break;\r
+\r
+ default:\r
+ return EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ Private->Mode->State = EfiSimpleNetworkStarted;\r
+\r
+ Private->Mode->ReceiveFilterSetting = 0;\r
+ Private->Mode->MCastFilterCount = 0;\r
+ ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter));\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Manages the multicast receive filters of a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param Enable A bit mask of receive filters to enable on the network interface.\r
+ @param Disable A bit mask of receive filters to disable on the network interface.\r
+ @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive\r
+ filters on the network interface to their default values.\r
+ @param McastFilterCnt Number of multicast HW MAC addresses in the new\r
+ MCastFilter list. This value must be less than or equal to\r
+ the MCastFilterCnt field of EMU_SNP_MODE. This\r
+ field is optional if ResetMCastFilter is TRUE.\r
+ @param MCastFilter A pointer to a list of new multicast receive filter HW MAC\r
+ addresses. This list will replace any existing multicast\r
+ HW MAC address list. This field is optional if\r
+ ResetMCastFilter is TRUE.\r
+\r
+ @retval EFI_SUCCESS The multicast receive filter list was updated.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpReceiveFilters (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN UINT32 Enable,\r
+ IN UINT32 Disable,\r
+ IN BOOLEAN ResetMCastFilter,\r
+ IN UINTN MCastFilterCnt OPTIONAL,\r
+ IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+ INT32 ReturnValue;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ ReturnValue = Private->NtNetUtilityTable.SetReceiveFilter (\r
+ Private->Instance.InterfaceInfo.InterfaceIndex,\r
+ Enable,\r
+ (UINT32)MCastFilterCnt,\r
+ MCastFilter\r
+ );\r
+\r
+ if (ReturnValue <= 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Modifies or resets the current station address, if supported.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param Reset Flag used to reset the station address to the network interfaces\r
+ permanent address.\r
+ @param New The new station address to be used for the network interface.\r
+\r
+ @retval EFI_SUCCESS The network interfaces station address was updated.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpStationAddress (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN BOOLEAN Reset,\r
+ IN EFI_MAC_ADDRESS *New OPTIONAL\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Resets or collects the statistics on a network interface.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param Reset Set to TRUE to reset the statistics for the network interface.\r
+ @param StatisticsSize On input the size, in bytes, of StatisticsTable. On\r
+ output the size, in bytes, of the resulting table of\r
+ statistics.\r
+ @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that\r
+ contains the statistics.\r
+\r
+ @retval EFI_SUCCESS The statistics were collected from the network interface.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer\r
+ size needed to hold the statistics is returned in\r
+ StatisticsSize.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpStatistics (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN BOOLEAN Reset,\r
+ IN OUT UINTN *StatisticsSize OPTIONAL,\r
+ OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Converts a multicast IP address to a multicast HW MAC address.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set\r
+ to FALSE if the multicast IP address is IPv4 [RFC 791].\r
+ @param IP The multicast IP address that is to be converted to a multicast\r
+ HW MAC address.\r
+ @param MAC The multicast HW MAC address that is to be generated from IP.\r
+\r
+ @retval EFI_SUCCESS The multicast IP address was mapped to the multicast\r
+ HW MAC address.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer\r
+ size needed to hold the statistics is returned in\r
+ StatisticsSize.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpMCastIpToMac (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN BOOLEAN IPv6,\r
+ IN EFI_IP_ADDRESS *IP,\r
+ OUT EFI_MAC_ADDRESS *MAC\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Performs read and write operations on the NVRAM device attached to a\r
+ network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param ReadWrite TRUE for read operations, FALSE for write operations.\r
+ @param Offset Byte offset in the NVRAM device at which to start the read or\r
+ write operation. This must be a multiple of NvRamAccessSize and\r
+ less than NvRamSize.\r
+ @param BufferSize The number of bytes to read or write from the NVRAM device.\r
+ This must also be a multiple of NvramAccessSize.\r
+ @param Buffer A pointer to the data buffer.\r
+\r
+ @retval EFI_SUCCESS The NVRAM access was performed.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpNvData (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN BOOLEAN ReadWrite,\r
+ IN UINTN Offset,\r
+ IN UINTN BufferSize,\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+ Reads the current interrupt status and recycled transmit buffer status from\r
+ a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param InterruptStatus A pointer to the bit mask of the currently active interrupts\r
+ If this is NULL, the interrupt status will not be read from\r
+ the device. If this is not NULL, the interrupt status will\r
+ be read from the device. When the interrupt status is read,\r
+ it will also be cleared. Clearing the transmit interrupt\r
+ does not empty the recycled transmit buffer array.\r
+ @param TxBuf Recycled transmit buffer address. The network interface will\r
+ not transmit if its internal recycled transmit buffer array\r
+ is full. Reading the transmit buffer does not clear the\r
+ transmit interrupt. If this is NULL, then the transmit buffer\r
+ status will not be read. If there are no transmit buffers to\r
+ recycle and TxBuf is not NULL, * TxBuf will be set to NULL.\r
+\r
+ @retval EFI_SUCCESS The status of the network interface was retrieved.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpGetStatus (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ OUT UINT32 *InterruptStatus OPTIONAL,\r
+ OUT VOID **TxBuf OPTIONAL\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if (TxBuf != NULL) {\r
+ if (Private->Instance.RecycledTxBufCount != 0) {\r
+ Private->Instance.RecycledTxBufCount --;\r
+ *((UINT8 **) TxBuf) = (UINT8 *) (UINTN)Private->Instance.RecycledTxBuf[Private->Instance.RecycledTxBufCount];\r
+ } else {\r
+ *((UINT8 **) TxBuf) = NULL;\r
+ }\r
+ }\r
+\r
+ if (InterruptStatus != NULL) {\r
+ *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Places a packet in the transmit queue of a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param HeaderSize The size, in bytes, of the media header to be filled in by\r
+ the Transmit() function. If HeaderSize is non-zero, then it\r
+ must be equal to This->Mode->MediaHeaderSize and the DestAddr\r
+ and Protocol parameters must not be NULL.\r
+ @param BufferSize The size, in bytes, of the entire packet (media header and\r
+ data) to be transmitted through the network interface.\r
+ @param Buffer A pointer to the packet (media header followed by data) to be\r
+ transmitted. This parameter cannot be NULL. If HeaderSize is zero,\r
+ then the media header in Buffer must already be filled in by the\r
+ caller. If HeaderSize is non-zero, then the media header will be\r
+ filled in by the Transmit() function.\r
+ @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter\r
+ is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then\r
+ This->Mode->CurrentAddress is used for the source HW MAC address.\r
+ @param DestAddr The destination HW MAC address. If HeaderSize is zero, then this\r
+ parameter is ignored.\r
+ @param Protocol The type of header to build. If HeaderSize is zero, then this\r
+ parameter is ignored. See RFC 1700, section "Ether Types", for\r
+ examples.\r
+\r
+ @retval EFI_SUCCESS The packet was placed on the transmit queue.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit request.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpTransmit (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ IN UINTN HeaderSize,\r
+ IN UINTN BufferSize,\r
+ IN VOID *Buffer,\r
+ IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
+ IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
+ IN UINT16 *Protocol OPTIONAL\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+ INT32 ReturnValue;\r
+ UINT64 *Tmp;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ if ((HeaderSize != 0) && (SrcAddr == NULL)) {\r
+ SrcAddr = &Private->Instance.Mode.CurrentAddress;\r
+ }\r
+\r
+ ReturnValue = Private->NtNetUtilityTable.Transmit (\r
+ Private->Instance.InterfaceInfo.InterfaceIndex,\r
+ (UINT32)HeaderSize,\r
+ (UINT32)BufferSize,\r
+ Buffer,\r
+ SrcAddr,\r
+ DestAddr,\r
+ Protocol\r
+ );\r
+\r
+ if (ReturnValue < 0) {\r
+ return EFI_DEVICE_ERROR;\r
+ } else {\r
+ if ((Private->Instance.MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= SNP_MAX_TX_BUFFER_NUM) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ if (Private->Instance.RecycledTxBufCount < Private->Instance.MaxRecycledTxBuf) {\r
+ Private->Instance.RecycledTxBuf[Private->Instance.RecycledTxBufCount] = (UINT64) Buffer;\r
+ Private->Instance.RecycledTxBufCount ++;\r
+ } else {\r
+ Tmp = malloc (sizeof (UINT64) * (Private->Instance.MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT));\r
+ if (Tmp == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ CopyMem (Tmp, Private->Instance.RecycledTxBuf, sizeof (UINT64) * Private->Instance.RecycledTxBufCount);\r
+ free (Private->Instance.RecycledTxBuf);\r
+ Private->Instance.RecycledTxBuf = Tmp;\r
+ Private->Instance.MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Receives a packet from a network interface.\r
+\r
+ @param This The protocol instance pointer.\r
+ @param HeaderSize The size, in bytes, of the media header received on the network\r
+ interface. If this parameter is NULL, then the media header size\r
+ will not be returned.\r
+ @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in\r
+ bytes, of the packet that was received on the network interface.\r
+ @param Buffer A pointer to the data buffer to receive both the media header and\r
+ the data.\r
+ @param SrcAddr The source HW MAC address. If this parameter is NULL, the\r
+ HW MAC source address will not be extracted from the media\r
+ header.\r
+ @param DestAddr The destination HW MAC address. If this parameter is NULL,\r
+ the HW MAC destination address will not be extracted from the\r
+ media header.\r
+ @param Protocol The media header type. If this parameter is NULL, then the\r
+ protocol will not be extracted from the media header. See\r
+ RFC 1700 section "Ether Types" for examples.\r
+\r
+ @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has\r
+ been updated to the number of bytes received.\r
+ @retval EFI_NOT_STARTED The network interface has not been started.\r
+ @retval EFI_NOT_READY The network interface is too busy to accept this transmit\r
+ request.\r
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.\r
+ @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.\r
+ @retval EFI_DEVICE_ERROR The command could not be sent to the network interface.\r
+ @retval EFI_UNSUPPORTED This function is not supported by the network interface.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpReceive (\r
+ IN EMU_SNP_PROTOCOL *This,\r
+ OUT UINTN *HeaderSize OPTIONAL,\r
+ IN OUT UINTN *BufferSize,\r
+ OUT VOID *Buffer,\r
+ OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,\r
+ OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,\r
+ OUT UINT16 *Protocol OPTIONAL\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+ INT32 ReturnValue;\r
+ UINTN BufSize;\r
+\r
+ Private = WIN_NT_SNP_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+ BufSize = *BufferSize;\r
+\r
+ ASSERT (Private->NtNetUtilityTable.Receive != NULL);\r
+\r
+ ReturnValue = Private->NtNetUtilityTable.Receive (\r
+ Private->Instance.InterfaceInfo.InterfaceIndex,\r
+ BufferSize,\r
+ Buffer\r
+ );\r
+\r
+ if (ReturnValue < 0) {\r
+ if (ReturnValue == -100) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ return EFI_DEVICE_ERROR;\r
+ } else if (ReturnValue == 0) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ if (HeaderSize != NULL) {\r
+ *HeaderSize = 14;\r
+ }\r
+\r
+ if (SrcAddr != NULL) {\r
+ ZeroMem (SrcAddr, sizeof (EFI_MAC_ADDRESS));\r
+ CopyMem (SrcAddr, ((UINT8 *) Buffer) + 6, 6);\r
+ }\r
+\r
+ if (DestAddr != NULL) {\r
+ ZeroMem (DestAddr, sizeof (EFI_MAC_ADDRESS));\r
+ CopyMem (DestAddr, ((UINT8 *) Buffer), 6);\r
+ }\r
+\r
+ if (Protocol != NULL) {\r
+ *Protocol = NTOHS (*((UINT16 *) (((UINT8 *) Buffer) + 12)));\r
+ }\r
+\r
+ return (*BufferSize <= BufSize) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;\r
+}\r
+\r
+/**\r
+ Initialize the snpnt32 driver instance.\r
+\r
+ @param Instance Pointer to the instance context data.\r
+ @param NetInfo Pointer to the interface info.\r
+\r
+ @retval EFI_SUCCESS The driver instance is initialized.\r
+ @retval other Initialization errors.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtInitializeInstanceData (\r
+ IN OUT WIN_NT_INSTANCE_DATA *Instance,\r
+ IN NT_NET_INTERFACE_INFO *NetInfo\r
+ )\r
+{\r
+ if (Instance == NULL || NetInfo == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ZeroMem (Instance, sizeof (WIN_NT_INSTANCE_DATA));\r
+\r
+ Instance->Signature = WIN_NT_INSTANCE_SIGNATURE;\r
+ Instance->RecycledTxBufCount = 0;\r
+ Instance->MaxRecycledTxBuf = 32;\r
+ Instance->Mode.State = EfiSimpleNetworkInitialized;\r
+ Instance->Mode.HwAddressSize = NET_ETHER_ADDR_LEN;\r
+ Instance->Mode.MediaHeaderSize = NET_ETHER_HEADER_SIZE;\r
+ Instance->Mode.MaxPacketSize = 1500;\r
+ Instance->Mode.MaxMCastFilterCount = MAX_MCAST_FILTER_CNT;\r
+ Instance->Mode.IfType = NET_IFTYPE_ETHERNET;\r
+ Instance->Mode.MediaPresentSupported = TRUE;\r
+ Instance->Mode.MediaPresent = TRUE;\r
+\r
+ //\r
+ // Allocate the RecycledTxBuf.\r
+ //\r
+ Instance->RecycledTxBuf = malloc (sizeof (UINT64) * Instance->MaxRecycledTxBuf);\r
+ if (Instance->RecycledTxBuf == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Set the interface information.\r
+ //\r
+ CopyMem (&Instance->InterfaceInfo, NetInfo, sizeof (Instance->InterfaceInfo));\r
+\r
+\r
+ //\r
+ // Set broadcast address\r
+ //\r
+ SetMem (&Instance->Mode.BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);\r
+\r
+ //\r
+ // Copy Current/PermanentAddress MAC address\r
+ //\r
+ CopyMem (&Instance->Mode.CurrentAddress, &Instance->InterfaceInfo.MacAddr, sizeof(Instance->Mode.CurrentAddress));\r
+ CopyMem (&Instance->Mode.PermanentAddress, &Instance->InterfaceInfo.MacAddr, sizeof(Instance->Mode.PermanentAddress));\r
+\r
+ //\r
+ // Since the fake SNP is based on a real NIC, to avoid conflict with the host\r
+ // NIC network stack, we use a different MAC address.\r
+ // So just change the last byte of the MAC address for the real NIC.\r
+ //\r
+ Instance->Mode.CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Initialize the net utility data.\r
+\r
+ @param This Pointer to the private data.\r
+ @param ActiveInstance The active network interface.\r
+\r
+ @retval EFI_SUCCESS The global data is initialized.\r
+ @retval EFI_NOT_FOUND The required DLL is not found.\r
+ @retval EFI_DEVICE_ERROR Error initialize network utility library.\r
+ @retval other Other errors.\r
+\r
+**/\r
+EFI_STATUS\r
+WintNtInitializeNetUtilityData (\r
+ IN OUT WIN_NT_SNP_PRIVATE *Private,\r
+ IN UINT8 ActiveInstance\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *DllFileNameU;\r
+ INT32 ReturnValue;\r
+ BOOLEAN NetUtilityLibInitDone;\r
+ NT_NET_INTERFACE_INFO NetInterfaceInfoBuffer[MAX_INTERFACE_INFO_NUMBER];\r
+ UINT32 InterfaceCount;\r
+ UINT8 ActiveInterfaceIndex;\r
+\r
+ if (Private == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ NetUtilityLibInitDone = FALSE;\r
+ InterfaceCount = MAX_INTERFACE_INFO_NUMBER;\r
+ DllFileNameU = NETWORK_LIBRARY_NAME_U;\r
+\r
+ //\r
+ // Load network utility library\r
+ //\r
+ Private->NetworkLibraryHandle = LoadLibraryEx (DllFileNameU, NULL, 0);\r
+ if (NULL == Private->NetworkLibraryHandle) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ Private->NtNetUtilityTable.Initialize = (NT_NET_INITIALIZE) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_INITIALIZE);\r
+ if (NULL == Private->NtNetUtilityTable.Initialize) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto ErrorReturn;\r
+ }\r
+\r
+ Private->NtNetUtilityTable.Finalize = (NT_NET_FINALIZE) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_FINALIZE);\r
+ if (NULL == Private->NtNetUtilityTable.Finalize) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto ErrorReturn;\r
+ }\r
+\r
+ Private->NtNetUtilityTable.SetReceiveFilter = (NT_NET_SET_RECEIVE_FILTER) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_SET_RCV_FILTER);\r
+ if (NULL == Private->NtNetUtilityTable.SetReceiveFilter) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto ErrorReturn;\r
+ }\r
+\r
+ Private->NtNetUtilityTable.Receive = (NT_NET_RECEIVE) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_RECEIVE);\r
+ if (NULL == Private->NtNetUtilityTable.Receive) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto ErrorReturn;\r
+ }\r
+\r
+ Private->NtNetUtilityTable.Transmit = (NT_NET_TRANSMIT) GetProcAddress (Private->NetworkLibraryHandle, NETWORK_LIBRARY_TRANSMIT);\r
+ if (NULL == Private->NtNetUtilityTable.Transmit) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto ErrorReturn;\r
+ }\r
+\r
+ //\r
+ // Initialize the network utility library\r
+ // And enumerate the interfaces in emulator host\r
+ //\r
+ ReturnValue = Private->NtNetUtilityTable.Initialize (&InterfaceCount, &NetInterfaceInfoBuffer[0]);\r
+ if (ReturnValue <= 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ErrorReturn;\r
+ }\r
+\r
+ NetUtilityLibInitDone = TRUE;\r
+\r
+ if (InterfaceCount == 0) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto ErrorReturn;\r
+ }\r
+\r
+ DEBUG ((DEBUG_INFO, "%a, total %d interface(s) found\n", __FUNCTION__, InterfaceCount));\r
+ //\r
+ // Active interface index is set to first interface if given instance does\r
+ // not exist.\r
+ //\r
+ ActiveInterfaceIndex = (ActiveInstance >= InterfaceCount ? DEFAULT_SELECTED_NIC_INDEX : ActiveInstance);\r
+\r
+ //\r
+ // Initialize instance\r
+ //\r
+ Status = WinNtInitializeInstanceData (&Private->Instance, &NetInterfaceInfoBuffer[ActiveInterfaceIndex]);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ErrorReturn;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ErrorReturn:\r
+\r
+ if (Private->Instance.RecycledTxBuf != NULL) {\r
+ free (Private->Instance.RecycledTxBuf);\r
+ }\r
+\r
+ if (NetUtilityLibInitDone) {\r
+ if (Private->NtNetUtilityTable.Finalize != NULL) {\r
+ Private->NtNetUtilityTable.Finalize ();\r
+ Private->NtNetUtilityTable.Finalize = NULL;\r
+ }\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Release the net utility data.\r
+\r
+ @param This Pointer to the private data.\r
+\r
+ @retval EFI_SUCCESS The global data is released.\r
+ @retval other Other errors.\r
+\r
+**/\r
+EFI_STATUS\r
+WintNtReleaseNetUtilityData (\r
+ IN OUT WIN_NT_SNP_PRIVATE *Private\r
+ )\r
+{\r
+ if (Private == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Private->Instance.RecycledTxBuf != NULL) {\r
+ free (Private->Instance.RecycledTxBuf);\r
+ }\r
+\r
+ if (Private->NtNetUtilityTable.Finalize != NULL) {\r
+ Private->NtNetUtilityTable.Finalize ();\r
+ }\r
+\r
+ FreeLibrary (Private->NetworkLibraryHandle);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EMU_SNP_PROTOCOL mWinNtSnpProtocol = {\r
+ WinNtSnpCreateMapping,\r
+ WinNtSnpStart,\r
+ WinNtSnpStop,\r
+ WinNtSnpInitialize,\r
+ WinNtSnpReset,\r
+ WinNtSnpShutdown,\r
+ WinNtSnpReceiveFilters,\r
+ WinNtSnpStationAddress,\r
+ WinNtSnpStatistics,\r
+ WinNtSnpMCastIpToMac,\r
+ WinNtSnpNvData,\r
+ WinNtSnpGetStatus,\r
+ WinNtSnpTransmit,\r
+ WinNtSnpReceive\r
+};\r
+\r
+/**\r
+ Open SNP thunk protocol.\r
+\r
+ @param This Pointer to the thunk protocol instance.\r
+\r
+ @retval EFI_SUCCESS SNP thunk protocol is opened successfully.\r
+ @retval EFI_UNSUPPORTED This is not SNP thunk protocol.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
+ @retval other Other errors.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpThunkOpen (\r
+ IN EMU_IO_THUNK_PROTOCOL *This\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+ UINT8 HostInterfaceIndex;\r
+\r
+ HostInterfaceIndex = 0;\r
+\r
+ if (This->Private != NULL) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Private = malloc (sizeof (WIN_NT_SNP_PRIVATE));\r
+ if (Private == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ Private->Signature = WIN_NT_SIMPLE_NETWORK_PRIVATE_SIGNATURE;\r
+ Private->Thunk = This;\r
+ CopyMem (&Private->EmuSnp, &mWinNtSnpProtocol, sizeof (mWinNtSnpProtocol));\r
+\r
+ This->Interface = &Private->EmuSnp;\r
+ This->Private = Private;\r
+\r
+ if (This->ConfigString != NULL && This->ConfigString[0] != '\0') {\r
+ HostInterfaceIndex = (UINT8)StrDecimalToUintn (This->ConfigString);\r
+ }\r
+\r
+ return WintNtInitializeNetUtilityData (Private, HostInterfaceIndex);\r
+}\r
+\r
+/**\r
+ Close SNP thunk protocol.\r
+\r
+ @param This Pointer to the thunk protocol instance.\r
+\r
+ @retval EFI_SUCCESS SNP thunk protocol is closed successfully.\r
+ @retval EFI_UNSUPPORTED This is not SNP thunk protocol.\r
+ @retval other Other errors.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtSnpThunkClose (\r
+ IN EMU_IO_THUNK_PROTOCOL *This\r
+ )\r
+{\r
+ WIN_NT_SNP_PRIVATE *Private;\r
+\r
+ if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Private = This->Private;\r
+ WintNtReleaseNetUtilityData (Private);\r
+ free (Private);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EMU_IO_THUNK_PROTOCOL mWinNtSnpThunkIo = {\r
+ &gEmuSnpProtocolGuid,\r
+ NULL,\r
+ NULL,\r
+ 0,\r
+ WinNtSnpThunkOpen,\r
+ WinNtSnpThunkClose,\r
+ NULL\r
+};\r