997 lines
32 KiB
C
997 lines
32 KiB
C
|
/** @file
|
||
|
|
||
|
Copyright (c) 2010, Apple, Inc. All rights reserved.<BR>
|
||
|
Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
|
||
|
|
||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
EmuSnp.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
-**/
|
||
|
|
||
|
#include "EmuSnpDxe.h"
|
||
|
|
||
|
|
||
|
|
||
|
EFI_SIMPLE_NETWORK_PROTOCOL gEmuSnpTemplate = {
|
||
|
EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,
|
||
|
EmuSnpStart,
|
||
|
EmuSnpStop,
|
||
|
EmuSnpInitialize,
|
||
|
EmuSnpReset,
|
||
|
EmuSnpShutdown,
|
||
|
EmuSnpReceiveFilters,
|
||
|
EmuSnpStationAddress,
|
||
|
EmuSnpStatistics,
|
||
|
EmuSnpMcastIptoMac,
|
||
|
EmuSnpNvdata,
|
||
|
EmuSnpGetStatus,
|
||
|
EmuSnpTransmit,
|
||
|
EmuSnpReceive,
|
||
|
NULL, // WaitForPacket
|
||
|
NULL // Mode
|
||
|
};
|
||
|
|
||
|
EFI_SIMPLE_NETWORK_MODE gEmuSnpModeTemplate = {
|
||
|
EfiSimpleNetworkStopped, // State
|
||
|
NET_ETHER_ADDR_LEN, // HwAddressSize
|
||
|
NET_ETHER_HEADER_SIZE, // MediaHeaderSize
|
||
|
1500, // MaxPacketSize
|
||
|
0, // NvRamSize
|
||
|
0, // NvRamAccessSize
|
||
|
0, // ReceiveFilterMask
|
||
|
0, // ReceiveFilterSetting
|
||
|
MAX_MCAST_FILTER_CNT, // MaxMCastFilterCount
|
||
|
0, // MCastFilterCount
|
||
|
{
|
||
|
{ { 0 } }
|
||
|
}, // MCastFilter
|
||
|
{
|
||
|
{ 0 }
|
||
|
}, // CurrentAddress
|
||
|
{
|
||
|
{ 0 }
|
||
|
}, // BroadcastAddress
|
||
|
{
|
||
|
{ 0 }
|
||
|
}, // PermanentAddress
|
||
|
NET_IFTYPE_ETHERNET, // IfType
|
||
|
FALSE, // MacAddressChangeable
|
||
|
FALSE, // MultipleTxSupported
|
||
|
FALSE, // MediaPresentSupported
|
||
|
TRUE // MediaPresent
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
Changes the state of a network interface from "stopped" to "started".
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
|
||
|
@retval EFI_SUCCESS Always succeeds.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpStart(
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->Start (Private->Io);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
Changes the state of a network interface from "started" to "stopped".
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
|
||
|
@retval EFI_SUCCESS Always succeeds.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpStop (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->Stop (Private->Io);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
Resets a network adapter and allocates the transmit and receive buffers
|
||
|
required by the network interface; optionally, also requests allocation
|
||
|
of additional transmit and receive buffers.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
|
||
|
that the driver should allocate for the network interface.
|
||
|
Some network interfaces will not be able to use the extra
|
||
|
buffer, and the caller will not know if it is actually
|
||
|
being used.
|
||
|
@param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
|
||
|
that the driver should allocate for the network interface.
|
||
|
Some network interfaces will not be able to use the extra
|
||
|
buffer, and the caller will not know if it is actually
|
||
|
being used.
|
||
|
|
||
|
@retval EFI_SUCCESS Always succeeds.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpInitialize (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
IN UINTN ExtraRxBufferSize OPTIONAL,
|
||
|
IN UINTN ExtraTxBufferSize OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->Initialize (Private->Io, ExtraRxBufferSize, ExtraTxBufferSize);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Resets a network adapter and re-initializes it with the parameters that were
|
||
|
provided in the previous call to Initialize().
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param ExtendedVerification Indicates that the driver may perform a more
|
||
|
exhaustive verification operation of the device
|
||
|
during reset.
|
||
|
|
||
|
@retval EFI_SUCCESS Always succeeds.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpReset (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
IN BOOLEAN ExtendedVerification
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->Reset (Private->Io, ExtendedVerification);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Resets a network adapter and leaves it in a state that is safe for
|
||
|
another driver to initialize.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
|
||
|
@retval EFI_SUCCESS Always succeeds.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpShutdown (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->Shutdown (Private->Io);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Manages the multicast receive filters of a network interface.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param EnableBits A bit mask of receive filters to enable on the network interface.
|
||
|
@param DisableBits A bit mask of receive filters to disable on the network interface.
|
||
|
@param ResetMcastFilter Set to TRUE to reset the contents of the multicast receive
|
||
|
filters on the network interface to their default values.
|
||
|
@param McastFilterCount Number of multicast HW MAC addresses in the new
|
||
|
MCastFilter list. This value must be less than or equal to
|
||
|
the MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE. This
|
||
|
field is optional if ResetMCastFilter is TRUE.
|
||
|
@param McastFilter A pointer to a list of new multicast receive filter HW MAC
|
||
|
addresses. This list will replace any existing multicast
|
||
|
HW MAC address list. This field is optional if
|
||
|
ResetMCastFilter is TRUE.
|
||
|
|
||
|
@retval EFI_SUCCESS The multicast receive filter list was updated.
|
||
|
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpReceiveFilters (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
IN UINT32 EnableBits,
|
||
|
IN UINT32 DisableBits,
|
||
|
IN BOOLEAN ResetMcastFilter,
|
||
|
IN UINTN McastFilterCount OPTIONAL,
|
||
|
IN EFI_MAC_ADDRESS *McastFilter OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->ReceiveFilters (
|
||
|
Private->Io,
|
||
|
EnableBits,
|
||
|
DisableBits,
|
||
|
ResetMcastFilter,
|
||
|
McastFilterCount,
|
||
|
McastFilter
|
||
|
);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Modifies or resets the current station address, if supported.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param Reset Flag used to reset the station address to the network interfaces
|
||
|
permanent address.
|
||
|
@param NewMacAddr New station address to be used for the network interface.
|
||
|
|
||
|
@retval EFI_UNSUPPORTED Not supported yet.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpStationAddress (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
IN BOOLEAN Reset,
|
||
|
IN EFI_MAC_ADDRESS *NewMacAddr OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->StationAddress (Private->Io, Reset, NewMacAddr);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Resets or collects the statistics on a network interface.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param Reset Set to TRUE to reset the statistics for the network interface.
|
||
|
@param StatisticsSize On input the size, in bytes, of StatisticsTable. On
|
||
|
output the size, in bytes, of the resulting table of
|
||
|
statistics.
|
||
|
@param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
|
||
|
contains the statistics.
|
||
|
|
||
|
@retval EFI_SUCCESS The statistics were collected from the network interface.
|
||
|
@retval EFI_NOT_STARTED The network interface has not been started.
|
||
|
@retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
|
||
|
size needed to hold the statistics is returned in
|
||
|
StatisticsSize.
|
||
|
@retval EFI_UNSUPPORTED Not supported yet.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpStatistics (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
IN BOOLEAN Reset,
|
||
|
IN OUT UINTN *StatisticsSize OPTIONAL,
|
||
|
OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->Statistics (Private->Io, Reset, StatisticsSize, StatisticsTable);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Converts a multicast IP address to a multicast HW MAC address.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param Ipv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set
|
||
|
to FALSE if the multicast IP address is IPv4 [RFC 791].
|
||
|
@param Ip The multicast IP address that is to be converted to a multicast
|
||
|
HW MAC address.
|
||
|
@param Mac The multicast HW MAC address that is to be generated from IP.
|
||
|
|
||
|
@retval EFI_SUCCESS The multicast IP address was mapped to the multicast
|
||
|
HW MAC address.
|
||
|
@retval EFI_NOT_STARTED The network interface has not been started.
|
||
|
@retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer
|
||
|
size needed to hold the statistics is returned in
|
||
|
StatisticsSize.
|
||
|
@retval EFI_UNSUPPORTED Not supported yet.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpMcastIptoMac (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
IN BOOLEAN Ipv6,
|
||
|
IN EFI_IP_ADDRESS *Ip,
|
||
|
OUT EFI_MAC_ADDRESS *Mac
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->MCastIpToMac (Private->Io, Ipv6, Ip, Mac);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
Performs read and write operations on the NVRAM device attached to a
|
||
|
network interface.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param ReadOrWrite TRUE for read operations, FALSE for write operations.
|
||
|
@param Offset Byte offset in the NVRAM device at which to start the read or
|
||
|
write operation. This must be a multiple of NvRamAccessSize and
|
||
|
less than NvRamSize.
|
||
|
@param BufferSize The number of bytes to read or write from the NVRAM device.
|
||
|
This must also be a multiple of NvramAccessSize.
|
||
|
@param Buffer A pointer to the data buffer.
|
||
|
|
||
|
@retval EFI_UNSUPPORTED Not supported yet.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpNvdata (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
IN BOOLEAN ReadOrWrite,
|
||
|
IN UINTN Offset,
|
||
|
IN UINTN BufferSize,
|
||
|
IN OUT VOID *Buffer
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->NvData (Private->Io, ReadOrWrite, Offset, BufferSize, Buffer);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
Reads the current interrupt status and recycled transmit buffer status from
|
||
|
a network interface.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param InterruptStatus A pointer to the bit mask of the currently active interrupts
|
||
|
If this is NULL, the interrupt status will not be read from
|
||
|
the device. If this is not NULL, the interrupt status will
|
||
|
be read from the device. When the interrupt status is read,
|
||
|
it will also be cleared. Clearing the transmit interrupt
|
||
|
does not empty the recycled transmit buffer array.
|
||
|
@param TxBuffer Recycled transmit buffer address. The network interface will
|
||
|
not transmit if its internal recycled transmit buffer array
|
||
|
is full. Reading the transmit buffer does not clear the
|
||
|
transmit interrupt. If this is NULL, then the transmit buffer
|
||
|
status will not be read. If there are no transmit buffers to
|
||
|
recycle and TxBuf is not NULL, * TxBuf will be set to NULL.
|
||
|
|
||
|
@retval EFI_SUCCESS Always succeeds.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpGetStatus (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
OUT UINT32 *InterruptStatus,
|
||
|
OUT VOID **TxBuffer
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->GetStatus (Private->Io, InterruptStatus, TxBuffer);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
Places a packet in the transmit queue of a network interface.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param HeaderSize The size, in bytes, of the media header to be filled in by
|
||
|
the Transmit() function. If HeaderSize is non-zero, then it
|
||
|
must be equal to This->Mode->MediaHeaderSize and the DestAddr
|
||
|
and Protocol parameters must not be NULL.
|
||
|
@param BufferSize The size, in bytes, of the entire packet (media header and
|
||
|
data) to be transmitted through the network interface.
|
||
|
@param Buffer A pointer to the packet (media header followed by data) to be
|
||
|
transmitted. This parameter cannot be NULL. If HeaderSize is zero,
|
||
|
then the media header in Buffer must already be filled in by the
|
||
|
caller. If HeaderSize is non-zero, then the media header will be
|
||
|
filled in by the Transmit() function.
|
||
|
@param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter
|
||
|
is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then
|
||
|
This->Mode->CurrentAddress is used for the source HW MAC address.
|
||
|
@param DestAddr The destination HW MAC address. If HeaderSize is zero, then this
|
||
|
parameter is ignored.
|
||
|
@param Protocol The type of header to build. If HeaderSize is zero, then this
|
||
|
parameter is ignored. See RFC 1700, section "Ether Types", for
|
||
|
examples.
|
||
|
|
||
|
@retval EFI_SUCCESS The packet was placed on the transmit queue.
|
||
|
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||
|
@retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
|
||
|
@retval EFI_NOT_STARTED The network interface has not been started.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpTransmit (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
IN UINTN HeaderSize,
|
||
|
IN UINTN BufferSize,
|
||
|
IN VOID* Buffer,
|
||
|
IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
|
||
|
IN EFI_MAC_ADDRESS *DestAddr OPTIONAL,
|
||
|
IN UINT16 *Protocol OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->Transmit (
|
||
|
Private->Io,
|
||
|
HeaderSize,
|
||
|
BufferSize,
|
||
|
Buffer,
|
||
|
SrcAddr,
|
||
|
DestAddr,
|
||
|
Protocol
|
||
|
);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Receives a packet from a network interface.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param HeaderSize The size, in bytes, of the media header received on the network
|
||
|
interface. If this parameter is NULL, then the media header size
|
||
|
will not be returned.
|
||
|
@param BuffSize On entry, the size, in bytes, of Buffer. On exit, the size, in
|
||
|
bytes, of the packet that was received on the network interface.
|
||
|
@param Buffer A pointer to the data buffer to receive both the media header and
|
||
|
the data.
|
||
|
@param SourceAddr The source HW MAC address. If this parameter is NULL, the
|
||
|
HW MAC source address will not be extracted from the media
|
||
|
header.
|
||
|
@param DestinationAddr The destination HW MAC address. If this parameter is NULL,
|
||
|
the HW MAC destination address will not be extracted from the
|
||
|
media header.
|
||
|
@param Protocol The media header type. If this parameter is NULL, then the
|
||
|
protocol will not be extracted from the media header. See
|
||
|
RFC 1700 section "Ether Types" for examples.
|
||
|
|
||
|
@retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has
|
||
|
been updated to the number of bytes received.
|
||
|
@retval EFI_NOT_READY The network interface is too busy to accept this transmit
|
||
|
request.
|
||
|
@retval EFI_NOT_STARTED The network interface has not been started.
|
||
|
@retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
|
||
|
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpReceive (
|
||
|
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||
|
OUT UINTN *HeaderSize OPTIONAL,
|
||
|
IN OUT UINTN *BuffSize,
|
||
|
OUT VOID *Buffer,
|
||
|
OUT EFI_MAC_ADDRESS *SourceAddr OPTIONAL,
|
||
|
OUT EFI_MAC_ADDRESS *DestinationAddr OPTIONAL,
|
||
|
OUT UINT16 *Protocol OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (This);
|
||
|
|
||
|
Status = Private->Io->Receive (
|
||
|
Private->Io,
|
||
|
HeaderSize,
|
||
|
BuffSize,
|
||
|
Buffer,
|
||
|
SourceAddr,
|
||
|
DestinationAddr,
|
||
|
Protocol
|
||
|
);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
Test to see if this driver supports ControllerHandle. This service
|
||
|
is called by the EFI boot service ConnectController(). In
|
||
|
order to make drivers as small as possible, there are a few calling
|
||
|
restrictions for this service. ConnectController() must
|
||
|
follow these calling restrictions. If any other agent wishes to call
|
||
|
Supported() it must also follow these calling restrictions.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param ControllerHandle Handle of device to test
|
||
|
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||
|
device to start.
|
||
|
|
||
|
@retval EFI_SUCCESS This driver supports this device
|
||
|
@retval EFI_UNSUPPORTED This driver does not support this device
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpDriverBindingSupported (
|
||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||
|
IN EFI_HANDLE ControllerHandle,
|
||
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
|
||
|
MAC_ADDR_DEVICE_PATH *Node;
|
||
|
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||
|
|
||
|
if (RemainingDevicePath != NULL) {
|
||
|
if (!IsDevicePathEnd (RemainingDevicePath)) {
|
||
|
Node = (MAC_ADDR_DEVICE_PATH *)RemainingDevicePath;
|
||
|
if (Node->Header.Type != MESSAGING_DEVICE_PATH ||
|
||
|
Node->Header.SubType != MSG_MAC_ADDR_DP) {
|
||
|
// If the remaining device path does not match we don't support the request
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// Open the IO Abstraction(s) needed to perform the supported test
|
||
|
//
|
||
|
Status = gBS->OpenProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEmuIoThunkProtocolGuid,
|
||
|
(VOID **)&EmuIoThunk,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle,
|
||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Close the I/O Abstraction(s) used to perform the supported test
|
||
|
//
|
||
|
gBS->CloseProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEmuIoThunkProtocolGuid,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle
|
||
|
);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Open the EFI Device Path protocol needed to perform the supported test
|
||
|
//
|
||
|
Status = gBS->OpenProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEfiDevicePathProtocolGuid,
|
||
|
(VOID **) &ParentDevicePath,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle,
|
||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||
|
);
|
||
|
if (Status == EFI_ALREADY_STARTED) {
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Make sure GUID is for a SNP handle.
|
||
|
//
|
||
|
Status = EFI_UNSUPPORTED;
|
||
|
if (CompareGuid (EmuIoThunk->Protocol, &gEmuSnpProtocolGuid)) {
|
||
|
Status = EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Close protocol, don't use device path protocol in the Support() function
|
||
|
//
|
||
|
gBS->CloseProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEfiDevicePathProtocolGuid,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle
|
||
|
);
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
Start this driver on ControllerHandle. This service is called by the
|
||
|
EFI boot service ConnectController(). In order to make
|
||
|
drivers as small as possible, there are a few calling restrictions for
|
||
|
this service. ConnectController() must follow these
|
||
|
calling restrictions. If any other agent wishes to call Start() it
|
||
|
must also follow these calling restrictions.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param ControllerHandle Handle of device to bind driver to
|
||
|
@param RemainingDevicePath Optional parameter use to pick a specific child
|
||
|
device to start.
|
||
|
|
||
|
@retval EFI_SUCCESS Always succeeds.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpDriverBindingStart (
|
||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||
|
IN EFI_HANDLE ControllerHandle,
|
||
|
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_IO_THUNK_PROTOCOL *EmuIoThunk;
|
||
|
EMU_SNP_PRIVATE_DATA *Private;
|
||
|
MAC_ADDR_DEVICE_PATH Node;
|
||
|
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||
|
|
||
|
Private = NULL;
|
||
|
|
||
|
//
|
||
|
// Grab the protocols we need
|
||
|
//
|
||
|
Status = gBS->OpenProtocol(
|
||
|
ControllerHandle,
|
||
|
&gEfiDevicePathProtocolGuid,
|
||
|
( VOID ** ) &ParentDevicePath,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle,
|
||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||
|
);
|
||
|
if (EFI_ERROR (Status) && Status) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
Status = gBS->OpenProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEmuIoThunkProtocolGuid,
|
||
|
(VOID **)&EmuIoThunk,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle,
|
||
|
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
if (!CompareGuid (EmuIoThunk->Protocol, &gEmuSnpProtocolGuid)) {
|
||
|
return EFI_UNSUPPORTED;
|
||
|
}
|
||
|
|
||
|
Status = EmuIoThunk->Open (EmuIoThunk);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Allocate the private data.
|
||
|
//
|
||
|
Private = AllocateZeroPool (sizeof (EMU_SNP_PRIVATE_DATA));
|
||
|
if (Private == NULL) {
|
||
|
Status = EFI_OUT_OF_RESOURCES;
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
CopyMem (&Private->Snp, &gEmuSnpTemplate, sizeof (EFI_SIMPLE_NETWORK_PROTOCOL));
|
||
|
CopyMem (&Private->Mode, &gEmuSnpModeTemplate, sizeof (EFI_SIMPLE_NETWORK_MODE));
|
||
|
|
||
|
Private->Signature = EMU_SNP_PRIVATE_DATA_SIGNATURE;
|
||
|
Private->IoThunk = EmuIoThunk;
|
||
|
Private->Io = EmuIoThunk->Interface;
|
||
|
Private->EfiHandle = ControllerHandle;
|
||
|
Private->DeviceHandle = NULL;
|
||
|
Private->Snp.Mode = &Private->Mode;
|
||
|
Private->ControllerNameTable = NULL;
|
||
|
|
||
|
|
||
|
Status = Private->Io->CreateMapping (Private->Io, &Private->Mode);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Build the device path by appending the MAC node to the ParentDevicePath
|
||
|
// from the EmuIo handle.
|
||
|
//
|
||
|
ZeroMem (&Node, sizeof (MAC_ADDR_DEVICE_PATH));
|
||
|
|
||
|
Node.Header.Type = MESSAGING_DEVICE_PATH;
|
||
|
Node.Header.SubType = MSG_MAC_ADDR_DP;
|
||
|
Node.IfType = Private->Mode.IfType;
|
||
|
|
||
|
SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL * )&Node, sizeof (MAC_ADDR_DEVICE_PATH));
|
||
|
|
||
|
CopyMem (&Node.MacAddress, &Private->Mode.CurrentAddress, sizeof (EFI_MAC_ADDRESS));
|
||
|
|
||
|
//
|
||
|
// Build the device path by appending the MAC node to the ParentDevicePath from the EmuIo handle.
|
||
|
//
|
||
|
Private->DevicePath = AppendDevicePathNode (ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&Node);
|
||
|
if ( Private->DevicePath == NULL ) {
|
||
|
Status = EFI_OUT_OF_RESOURCES;
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
AddUnicodeString2 (
|
||
|
"eng",
|
||
|
gEmuSnpDriverComponentName.SupportedLanguages,
|
||
|
&Private->ControllerNameTable,
|
||
|
EmuIoThunk->ConfigString,
|
||
|
TRUE
|
||
|
);
|
||
|
|
||
|
AddUnicodeString2 (
|
||
|
"en",
|
||
|
gEmuSnpDriverComponentName2.SupportedLanguages,
|
||
|
&Private->ControllerNameTable,
|
||
|
EmuIoThunk->ConfigString,
|
||
|
FALSE
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// Create Child Handle
|
||
|
//
|
||
|
Status = gBS->InstallMultipleProtocolInterfaces(
|
||
|
&Private->DeviceHandle,
|
||
|
&gEfiSimpleNetworkProtocolGuid, &Private->Snp,
|
||
|
&gEfiDevicePathProtocolGuid, Private->DevicePath,
|
||
|
NULL
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Open For Child Device
|
||
|
//
|
||
|
Status = gBS->OpenProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEmuIoThunkProtocolGuid,
|
||
|
(VOID **)&EmuIoThunk,
|
||
|
This->DriverBindingHandle,
|
||
|
Private->DeviceHandle,
|
||
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||
|
);
|
||
|
|
||
|
Done:
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
if (Private != NULL) {
|
||
|
FreePool (Private);
|
||
|
}
|
||
|
if (ParentDevicePath != NULL) {
|
||
|
gBS->CloseProtocol(
|
||
|
ControllerHandle,
|
||
|
&gEfiDevicePathProtocolGuid,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
Stop this driver on ControllerHandle. This service is called by the
|
||
|
EFI boot service DisconnectController(). In order to
|
||
|
make drivers as small as possible, there are a few calling
|
||
|
restrictions for this service. DisconnectController()
|
||
|
must follow these calling restrictions. If any other agent wishes
|
||
|
to call Stop() it must also follow these calling restrictions.
|
||
|
|
||
|
@param This Protocol instance pointer.
|
||
|
@param ControllerHandle Handle of device to stop driver on
|
||
|
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
||
|
children is zero stop the entire bus driver.
|
||
|
@param ChildHandleBuffer List of Child Handles to Stop.
|
||
|
|
||
|
@retval EFI_SUCCESS Always succeeds.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
EmuSnpDriverBindingStop (
|
||
|
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||
|
IN EFI_HANDLE ControllerHandle,
|
||
|
IN UINTN NumberOfChildren,
|
||
|
IN EFI_HANDLE *ChildHandleBuffer
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
EMU_SNP_PRIVATE_DATA *Private = NULL;
|
||
|
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
|
||
|
VOID *EmuIoThunk;
|
||
|
|
||
|
//
|
||
|
// Complete all outstanding transactions to Controller.
|
||
|
// Don't allow any new transaction to Controller to be started.
|
||
|
//
|
||
|
if (NumberOfChildren == 0) {
|
||
|
//
|
||
|
// Close the bus driver
|
||
|
//
|
||
|
Status = gBS->CloseProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEmuIoThunkProtocolGuid,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle
|
||
|
);
|
||
|
|
||
|
Status = gBS->CloseProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEfiDevicePathProtocolGuid,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle
|
||
|
);
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
ASSERT (NumberOfChildren == 1);
|
||
|
|
||
|
|
||
|
//
|
||
|
// Get our context back.
|
||
|
//
|
||
|
Status = gBS->OpenProtocol(
|
||
|
ChildHandleBuffer[0],
|
||
|
&gEfiSimpleNetworkProtocolGuid,
|
||
|
( VOID ** ) &Snp,
|
||
|
This->DriverBindingHandle,
|
||
|
ControllerHandle,
|
||
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
|
||
|
Private = EMU_SNP_PRIVATE_DATA_FROM_SNP_THIS (Snp);
|
||
|
ASSERT (Private->DeviceHandle == ChildHandleBuffer[0]);
|
||
|
ASSERT (Private->EfiHandle == ControllerHandle);
|
||
|
|
||
|
Status = gBS->CloseProtocol(
|
||
|
ControllerHandle,
|
||
|
&gEmuIoThunkProtocolGuid,
|
||
|
This->DriverBindingHandle,
|
||
|
Private->DeviceHandle
|
||
|
);
|
||
|
ASSERT_EFI_ERROR (Status);
|
||
|
|
||
|
Status = gBS->UninstallMultipleProtocolInterfaces(
|
||
|
Private->DeviceHandle,
|
||
|
&gEfiSimpleNetworkProtocolGuid, &Private->Snp,
|
||
|
&gEfiDevicePathProtocolGuid, Private->DevicePath,
|
||
|
NULL
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
gBS->OpenProtocol (
|
||
|
ControllerHandle,
|
||
|
&gEmuIoThunkProtocolGuid,
|
||
|
&EmuIoThunk,
|
||
|
This->DriverBindingHandle,
|
||
|
Private->DeviceHandle,
|
||
|
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||
|
);
|
||
|
} else {
|
||
|
Status = Private->IoThunk->Close (Private->IoThunk);
|
||
|
ASSERT_EFI_ERROR (Status);
|
||
|
|
||
|
FreePool (Private->DevicePath);
|
||
|
FreeUnicodeStringTable (Private->ControllerNameTable);
|
||
|
FreePool (Private);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
|
||
|
EFI_DRIVER_BINDING_PROTOCOL gEmuSnpDriverBinding = {
|
||
|
EmuSnpDriverBindingSupported,
|
||
|
EmuSnpDriverBindingStart,
|
||
|
EmuSnpDriverBindingStop,
|
||
|
0xA,
|
||
|
NULL,
|
||
|
NULL
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
/**
|
||
|
This is the declaration of an EFI image entry point. This entry point is
|
||
|
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
|
||
|
both device drivers and bus drivers.
|
||
|
|
||
|
@param ImageHandle The firmware allocated handle for the UEFI image.
|
||
|
@param SystemTable A pointer to the EFI System Table.
|
||
|
|
||
|
@retval EFI_SUCCESS The operation completed successfully.
|
||
|
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||
|
|
||
|
**/
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
InitializeEmuSnpDriver (
|
||
|
IN EFI_HANDLE ImageHandle,
|
||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
|
||
|
//
|
||
|
// Install the Driver Protocols
|
||
|
//
|
||
|
Status = EfiLibInstallDriverBindingComponentName2(
|
||
|
ImageHandle,
|
||
|
SystemTable,
|
||
|
&gEmuSnpDriverBinding,
|
||
|
ImageHandle,
|
||
|
&gEmuSnpDriverComponentName,
|
||
|
&gEmuSnpDriverComponentName2
|
||
|
);
|
||
|
|
||
|
return Status;
|
||
|
}
|