git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11297 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1792 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1792 lines
		
	
	
		
			56 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
 Copyright (c) 2010, Apple, Inc. All rights reserved.<BR>
 | 
						|
 | 
						|
    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:
 | 
						|
 | 
						|
  UnixSnp.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
-**/
 | 
						|
 | 
						|
#include <Library/PrintLib.h>
 | 
						|
 | 
						|
#include "UnixSnp.h"
 | 
						|
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL gUnixSnpDriverBinding =
 | 
						|
{
 | 
						|
  UnixSnpDriverBindingSupported,
 | 
						|
  UnixSnpDriverBindingStart,
 | 
						|
  UnixSnpDriverBindingStop,
 | 
						|
  0xA,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Changes the state of a network interface from "stopped" to "started".
 | 
						|
 | 
						|
  @param  This Protocol instance pointer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Always succeeds.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixSnpStart(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This
 | 
						|
  );
 | 
						|
  
 | 
						|
/**
 | 
						|
  Changes the state of a network interface from "started" to "stopped".
 | 
						|
 | 
						|
  @param  This Protocol instance pointer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Always succeeds.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixSnpStop(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This
 | 
						|
  );
 | 
						|
  
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpInitialize(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN UINTN              ExtraRxBufferSize OPTIONAL,
 | 
						|
  IN UINTN              ExtraTxBufferSize OPTIONAL
 | 
						|
  );
 | 
						|
  
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpReset(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              ExtendedVerification
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpShutdown(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpReceiveFilters(
 | 
						|
  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
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpStationAddress(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              Reset,
 | 
						|
  IN EFI_MAC_ADDRESS*          NewMacAddr OPTIONAL
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpStatistics(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              Reset,
 | 
						|
  IN OUT UINTN*            StatisticsSize OPTIONAL,
 | 
						|
  OUT EFI_NETWORK_STATISTICS*      StatisticsTable OPTIONAL
 | 
						|
  );
 | 
						|
  
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpMcastIptoMac(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              Ipv6,
 | 
						|
  IN EFI_IP_ADDRESS*          Ip,
 | 
						|
  OUT EFI_MAC_ADDRESS*        Mac
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpNvdata(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              ReadOrWrite,
 | 
						|
  IN UINTN              Offset,
 | 
						|
  IN UINTN              BufferSize,
 | 
						|
  IN OUT VOID*            Buffer
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpGetStatus(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  OUT UINT32*              InterruptStatus,
 | 
						|
  OUT VOID**              TxBuffer
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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_ACCESS_DENIED     Error acquire global lock for operation.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixSnpTransmit(
 | 
						|
  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
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  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_BUFFER_TOO_SMALL  The BufferSize parameter is too small.
 | 
						|
  @retval  EFI_DEVICE_ERROR      The command could not be sent to the network interface.
 | 
						|
  @retval  EFI_ACCESS_DENIED     Error acquire global lock for operation.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixSnpReceive(
 | 
						|
  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
 | 
						|
  );
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
UnixSnpWaitForPacketNotify(
 | 
						|
  IN EFI_EVENT            Event,
 | 
						|
  IN VOID*              Private
 | 
						|
  );
 | 
						|
 | 
						|
//
 | 
						|
// Strange, but there doesn't appear to be any structure for the Ethernet header in edk2...
 | 
						|
//
 | 
						|
 | 
						|
typedef struct
 | 
						|
{
 | 
						|
  UINT8                DstAddr[ NET_ETHER_ADDR_LEN ];
 | 
						|
  UINT8                SrcAddr[ NET_ETHER_ADDR_LEN ];
 | 
						|
  UINT16                Type;
 | 
						|
} EthernetHeader;
 | 
						|
 | 
						|
UNIX_SNP_PRIVATE_DATA gUnixSnpPrivateTemplate =
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA_SIGNATURE,      // Signature
 | 
						|
  NULL,                    // UnixThunk
 | 
						|
  NULL,                    // DeviceHandle
 | 
						|
  NULL,                    // DevicePath
 | 
						|
  { 0 },                    // MacAddress
 | 
						|
  NULL,                    // InterfaceName
 | 
						|
  0,                      // ReadBufferSize
 | 
						|
  NULL,                    // ReadBuffer
 | 
						|
  NULL,                    // CurrentReadPointer
 | 
						|
  NULL,                    // EndReadPointer
 | 
						|
  0,                      // BpfFd
 | 
						|
  {                    // Snp
 | 
						|
    EFI_SIMPLE_NETWORK_PROTOCOL_REVISION,  // Revision
 | 
						|
    UnixSnpStart,              // Start
 | 
						|
    UnixSnpStop,              // Stop
 | 
						|
    UnixSnpInitialize,            // Initialize
 | 
						|
    UnixSnpReset,              // Reset
 | 
						|
    UnixSnpShutdown,            // Shutdown
 | 
						|
    UnixSnpReceiveFilters,          // ReceiveFilters
 | 
						|
    UnixSnpStationAddress,          // StationAddress
 | 
						|
    UnixSnpStatistics,            // Statistics
 | 
						|
    UnixSnpMcastIptoMac,          // MCastIpToMac
 | 
						|
    UnixSnpNvdata,              // NvData
 | 
						|
    UnixSnpGetStatus,            // GetStatus
 | 
						|
    UnixSnpTransmit,            // Transmit
 | 
						|
    UnixSnpReceive,              // Receive
 | 
						|
    NULL,                  // WaitForPacket
 | 
						|
    NULL                  // Mode
 | 
						|
  },
 | 
						|
  {                    // Mode
 | 
						|
    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
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
STATIC EFI_STATUS
 | 
						|
GetInterfaceMacAddr(
 | 
						|
  IN UNIX_SNP_PRIVATE_DATA*      Private,
 | 
						|
  IN EFI_UNIX_IO_PROTOCOL*      UnixIo
 | 
						|
  )
 | 
						|
{
 | 
						|
  struct ifaddrs*            IfAddrs;
 | 
						|
  struct ifaddrs*            If;
 | 
						|
  struct sockaddr_dl*          IfSdl;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  INTN                Result;
 | 
						|
 | 
						|
  Result = UnixIo->UnixThunk->GetIfAddrs( &IfAddrs );
 | 
						|
  if ( Result != 0 )
 | 
						|
  {
 | 
						|
    return( EFI_UNSUPPORTED );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert the interface name to ASCII so we can find it.
 | 
						|
  //
 | 
						|
  Private->InterfaceName = AllocateZeroPool( StrLen( UnixIo->EnvString ) );
 | 
						|
 | 
						|
  if ( !Private->InterfaceName )
 | 
						|
  {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Exit;
 | 
						|
  }
 | 
						|
 | 
						|
  UnicodeStrToAsciiStr( UnixIo->EnvString, Private->InterfaceName );
 | 
						|
 | 
						|
  If = IfAddrs;
 | 
						|
 | 
						|
  while ( If != NULL )
 | 
						|
  {
 | 
						|
    IfSdl = ( struct sockaddr_dl * ) If->ifa_addr;
 | 
						|
 | 
						|
    if ( IfSdl->sdl_family == AF_LINK )
 | 
						|
    {
 | 
						|
      if ( !AsciiStrCmp( Private->InterfaceName, If->ifa_name ) )
 | 
						|
      {
 | 
						|
        CopyMem( &Private->MacAddress, LLADDR( IfSdl ), NET_ETHER_ADDR_LEN );
 | 
						|
 | 
						|
        Status = EFI_SUCCESS;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    If = If->ifa_next;
 | 
						|
  }
 | 
						|
 | 
						|
Exit:
 | 
						|
  ( VOID ) UnixIo->UnixThunk->FreeIfAddrs( IfAddrs );
 | 
						|
 | 
						|
  return( Status );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
STATIC EFI_STATUS
 | 
						|
OpenBpfFileDescriptor(
 | 
						|
  IN UNIX_SNP_PRIVATE_DATA*    Private,
 | 
						|
  OUT INTN*            Fd
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8              BfpDeviceName[ 256 ];
 | 
						|
  INTN              Index;
 | 
						|
  EFI_STATUS            Status = EFI_OUT_OF_RESOURCES;
 | 
						|
  INTN              Result;
 | 
						|
 | 
						|
  //
 | 
						|
  // Open a Berkeley Packet Filter device.  This must be done as root, so this is probably
 | 
						|
  // the place which is most likely to fail...
 | 
						|
  //
 | 
						|
  for ( Index = 0; TRUE; Index++ )
 | 
						|
  {
 | 
						|
    AsciiSPrint( BfpDeviceName, sizeof( BfpDeviceName ), "/dev/bpf%d", Index );
 | 
						|
 | 
						|
    *Fd = Private->UnixThunk->Open( BfpDeviceName, O_RDWR, 0 );
 | 
						|
 | 
						|
    if ( *Fd >= 0 )
 | 
						|
    {
 | 
						|
      Status = EFI_SUCCESS;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Result = Private->UnixThunk->GetErrno();
 | 
						|
    if ( Result == EACCES )
 | 
						|
    {
 | 
						|
      DEBUG( ( EFI_D_ERROR, "Permissions on '%a' are incorrect.  Fix with 'sudo chmod 666 %a'.\n",
 | 
						|
          BfpDeviceName, BfpDeviceName ) );
 | 
						|
    }
 | 
						|
    if ( Result != EBUSY )
 | 
						|
    {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  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
 | 
						|
UnixSnpDriverBindingSupported(
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL*    This,
 | 
						|
  IN EFI_HANDLE            ControllerHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  EFI_UNIX_IO_PROTOCOL*        UnixIo;
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the I/O abstraction needed to perform the supported test.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol(
 | 
						|
          ControllerHandle,
 | 
						|
          &gEfiUnixIoProtocolGuid,
 | 
						|
          ( VOID ** ) &UnixIo,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          ControllerHandle,
 | 
						|
          EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
          );
 | 
						|
 | 
						|
  if ( EFI_ERROR( Status ) )
 | 
						|
  {
 | 
						|
    return( Status );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Validate GUID
 | 
						|
  //
 | 
						|
  Status = EFI_UNSUPPORTED;
 | 
						|
  if ( CompareGuid( UnixIo->TypeGuid, &gEfiUnixNetworkGuid ) )
 | 
						|
  {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Close the I/O abstraction used to perform the supported test.
 | 
						|
  //
 | 
						|
  gBS->CloseProtocol(
 | 
						|
          ControllerHandle,
 | 
						|
          &gEfiUnixIoProtocolGuid,
 | 
						|
          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
 | 
						|
UnixSnpDriverBindingStart(
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL*    This,
 | 
						|
  IN EFI_HANDLE            ControllerHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL*    RemainingDevicePath OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  MAC_ADDR_DEVICE_PATH      Node;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL*    ParentDevicePath = NULL;
 | 
						|
  EFI_UNIX_IO_PROTOCOL*      UnixIo;
 | 
						|
  UNIX_SNP_PRIVATE_DATA*      Private = NULL;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  BOOLEAN              CreateDevice;
 | 
						|
 | 
						|
  //
 | 
						|
  // Grab the protocols we need.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol(
 | 
						|
          ControllerHandle,
 | 
						|
          &gEfiDevicePathProtocolGuid,
 | 
						|
          ( VOID ** ) &ParentDevicePath,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          ControllerHandle,
 | 
						|
          EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
          );
 | 
						|
  if ( EFI_ERROR( Status ) )
 | 
						|
  {
 | 
						|
    goto ErrorExit;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the I/O abstraction needed to perform the supported test.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol(
 | 
						|
          ControllerHandle,
 | 
						|
          &gEfiUnixIoProtocolGuid,
 | 
						|
          ( VOID ** ) &UnixIo,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          ControllerHandle,
 | 
						|
          EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
          );
 | 
						|
  if ( EFI_ERROR( Status ) )
 | 
						|
  {
 | 
						|
    goto ErrorExit;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Validate GUID
 | 
						|
  //
 | 
						|
  if ( !CompareGuid( UnixIo->TypeGuid, &gEfiUnixNetworkGuid ) )
 | 
						|
  {
 | 
						|
    Status = EFI_UNSUPPORTED;
 | 
						|
    goto ErrorExit;
 | 
						|
  }
 | 
						|
 | 
						|
  CreateDevice = TRUE;
 | 
						|
  if ( ( RemainingDevicePath != NULL ) && IsDevicePathEnd( RemainingDevicePath ) )
 | 
						|
  {
 | 
						|
    CreateDevice = FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( CreateDevice )
 | 
						|
  {
 | 
						|
    //
 | 
						|
    //  Allocate the private data.
 | 
						|
    //
 | 
						|
    Private = AllocateCopyPool( sizeof( UNIX_SNP_PRIVATE_DATA ), &gUnixSnpPrivateTemplate );
 | 
						|
    if ( Private == NULL )
 | 
						|
    {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto ErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = GetInterfaceMacAddr( Private, UnixIo );
 | 
						|
    if ( EFI_ERROR( Status ) )
 | 
						|
    {
 | 
						|
      goto ErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    Private->UnixThunk = UnixIo->UnixThunk;
 | 
						|
 | 
						|
    Private->Snp.Mode = &Private->Mode;
 | 
						|
 | 
						|
    //
 | 
						|
    // Set the broadcast address.
 | 
						|
    //
 | 
						|
    SetMem( &Private->Mode.BroadcastAddress, sizeof( EFI_MAC_ADDRESS ), 0xFF );
 | 
						|
 | 
						|
    CopyMem( &Private->Mode.CurrentAddress, &Private->MacAddress, sizeof( EFI_MAC_ADDRESS ) );
 | 
						|
    CopyMem( &Private->Mode.PermanentAddress, &Private->MacAddress, sizeof( EFI_MAC_ADDRESS ) );
 | 
						|
 | 
						|
    //
 | 
						|
    // Since the fake SNP is based on a real NIC, to avoid conflict with the host NIC
 | 
						|
    // network stack, we use a different MAC address.
 | 
						|
    // So just change the last byte of the MAC address for the real NIC.
 | 
						|
    //
 | 
						|
    Private->Mode.CurrentAddress.Addr[ NET_ETHER_ADDR_LEN - 1 ]++;
 | 
						|
 | 
						|
    //
 | 
						|
    // Build the device path by appending the MAC node to the ParentDevicePath
 | 
						|
    // from the UnixIo 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 UnixIo handle.
 | 
						|
    //
 | 
						|
    Private->DevicePath = AppendDevicePathNode( ParentDevicePath, ( EFI_DEVICE_PATH_PROTOCOL * ) &Node );
 | 
						|
    if ( Private->DevicePath == NULL )
 | 
						|
    {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto ErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces(
 | 
						|
            &Private->DeviceHandle,
 | 
						|
            &gEfiSimpleNetworkProtocolGuid,
 | 
						|
            &Private->Snp,
 | 
						|
            &gEfiDevicePathProtocolGuid,
 | 
						|
            Private->DevicePath,
 | 
						|
            NULL
 | 
						|
            );
 | 
						|
    if ( EFI_ERROR( Status ) )
 | 
						|
    {
 | 
						|
      goto ErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = gBS->OpenProtocol(
 | 
						|
            ControllerHandle,
 | 
						|
            &gEfiUnixIoProtocolGuid,
 | 
						|
            ( VOID ** ) &UnixIo,
 | 
						|
            This->DriverBindingHandle,
 | 
						|
            Private->DeviceHandle,
 | 
						|
            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
            );
 | 
						|
    if ( EFI_ERROR( Status ) )
 | 
						|
    {
 | 
						|
      goto ErrorExit;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return( Status );
 | 
						|
 | 
						|
ErrorExit:
 | 
						|
  if ( Private->InterfaceName != NULL )
 | 
						|
  {
 | 
						|
    FreePool( Private->InterfaceName );
 | 
						|
    Private->InterfaceName = NULL;
 | 
						|
  }
 | 
						|
  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
 | 
						|
UnixSnpDriverBindingStop(
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL*    This,
 | 
						|
  IN EFI_HANDLE            ControllerHandle,
 | 
						|
  IN UINTN              NumberOfChildren,
 | 
						|
  IN EFI_HANDLE*            ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private = NULL;
 | 
						|
  EFI_SIMPLE_NETWORK_PROTOCOL*    Snp;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Get our context back.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol(
 | 
						|
        ControllerHandle,
 | 
						|
        &gEfiSimpleNetworkProtocolGuid,
 | 
						|
        ( VOID ** ) &Snp,
 | 
						|
        This->DriverBindingHandle,
 | 
						|
        ControllerHandle,
 | 
						|
        EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
        );
 | 
						|
  if ( EFI_ERROR( Status ) )
 | 
						|
  {
 | 
						|
    return( EFI_UNSUPPORTED );
 | 
						|
  }
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( Snp );
 | 
						|
 | 
						|
  Status = gBS->CloseProtocol(
 | 
						|
        ControllerHandle,
 | 
						|
        &gEfiUnixIoProtocolGuid,
 | 
						|
        This->DriverBindingHandle,
 | 
						|
        Private->DeviceHandle
 | 
						|
        );
 | 
						|
 | 
						|
  Status = gBS->UninstallMultipleProtocolInterfaces(
 | 
						|
        Private->DeviceHandle,
 | 
						|
        &gEfiSimpleNetworkProtocolGuid,
 | 
						|
        &Private->Snp,
 | 
						|
        &gEfiDevicePathProtocolGuid,
 | 
						|
        Private->DevicePath,
 | 
						|
        NULL
 | 
						|
        );
 | 
						|
 | 
						|
  FreePool( Private->InterfaceName );
 | 
						|
  FreePool( Private->DevicePath );
 | 
						|
  FreePool( Private );
 | 
						|
 | 
						|
  return( EFI_SUCCESS );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Changes the state of a network interface from "stopped" to "started".
 | 
						|
 | 
						|
  @param  This Protocol instance pointer.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Always succeeds.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
UnixSnpStart(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This
 | 
						|
  )
 | 
						|
{
 | 
						|
  STATIC struct bpf_insn        FilterInstructionTemplate[] =
 | 
						|
  {
 | 
						|
    // Load 4 bytes from the destination MAC address.
 | 
						|
    BPF_STMT( BPF_LD + BPF_W + BPF_ABS, OFFSET_OF( EthernetHeader, DstAddr[ 0 ] ) ),
 | 
						|
 | 
						|
    // Compare to first 4 bytes of fake MAC address.
 | 
						|
    BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, 0x12345678, 0, 3 ),
 | 
						|
 | 
						|
    // Load remaining 2 bytes from the destination MAC address.
 | 
						|
    BPF_STMT( BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( EthernetHeader, DstAddr[ 4 ] ) ),
 | 
						|
 | 
						|
    // Compare to remaining 2 bytes of fake MAC address.
 | 
						|
    BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, 0x9ABC, 5, 0 ),
 | 
						|
 | 
						|
    // Load 4 bytes from the destination MAC address.
 | 
						|
    BPF_STMT( BPF_LD + BPF_W + BPF_ABS, OFFSET_OF( EthernetHeader, DstAddr[ 0 ] ) ),
 | 
						|
 | 
						|
    // Compare to first 4 bytes of broadcast MAC address.
 | 
						|
    BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, 0xFFFFFFFF, 0, 2 ),
 | 
						|
 | 
						|
    // Load remaining 2 bytes from the destination MAC address.
 | 
						|
    BPF_STMT( BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( EthernetHeader, DstAddr[ 4 ] ) ),
 | 
						|
 | 
						|
    // Compare to remaining 2 bytes of broadcast MAC address.
 | 
						|
    BPF_JUMP( BPF_JMP + BPF_JEQ + BPF_K, 0xFFFF, 1, 0 ),
 | 
						|
 | 
						|
    // Reject packet.
 | 
						|
    BPF_STMT( BPF_RET + BPF_K, 0 ),
 | 
						|
 | 
						|
    // Receive entire packet.
 | 
						|
    BPF_STMT( BPF_RET + BPF_K, -1 )
 | 
						|
  };
 | 
						|
  struct ifreq            BoundIf;
 | 
						|
  struct bpf_program          BpfProgram;
 | 
						|
  struct bpf_insn*          FilterProgram;
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
  UINT32                Temp32;
 | 
						|
  INTN                Fd;
 | 
						|
  INTN                Result;
 | 
						|
  INTN                Value;
 | 
						|
  UINT16                Temp16;
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( This );
 | 
						|
 | 
						|
  switch ( Private->Snp.Mode->State )
 | 
						|
  {
 | 
						|
    case EfiSimpleNetworkStopped:
 | 
						|
      break;
 | 
						|
 | 
						|
    case EfiSimpleNetworkStarted:
 | 
						|
    case EfiSimpleNetworkInitialized:
 | 
						|
      return( EFI_ALREADY_STARTED );
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      return( EFI_DEVICE_ERROR );
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( Private->BpfFd == 0 )
 | 
						|
  {
 | 
						|
    Status = OpenBpfFileDescriptor( Private, &Fd );
 | 
						|
 | 
						|
    if ( EFI_ERROR( Status ) )
 | 
						|
    {
 | 
						|
      goto ErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    Private->BpfFd = Fd;
 | 
						|
 | 
						|
    //
 | 
						|
    // Associate our interface with this BPF file descriptor.
 | 
						|
    //
 | 
						|
    AsciiStrCpy( BoundIf.ifr_name, Private->InterfaceName );
 | 
						|
    Result = Private->UnixThunk->IoCtl( Private->BpfFd, BIOCSETIF, &BoundIf );
 | 
						|
 | 
						|
    if ( Result < 0 )
 | 
						|
    {
 | 
						|
      goto DeviceErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Enable immediate mode and find out the buffer size.
 | 
						|
    //
 | 
						|
    Value = 1;
 | 
						|
    Result = Private->UnixThunk->IoCtl( Private->BpfFd, BIOCIMMEDIATE, &Value );
 | 
						|
 | 
						|
    if ( Result < 0 )
 | 
						|
    {
 | 
						|
      goto DeviceErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Enable non-blocking I/O.
 | 
						|
    //
 | 
						|
 | 
						|
    Value = Private->UnixThunk->Fcntl( Private->BpfFd, F_GETFL, 0 );
 | 
						|
 | 
						|
    if ( Value == -1 )
 | 
						|
    {
 | 
						|
      goto DeviceErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    Value |= O_NONBLOCK;
 | 
						|
 | 
						|
    Result = Private->UnixThunk->Fcntl( Private->BpfFd, F_SETFL, (void *) Value );
 | 
						|
 | 
						|
    if ( Result == -1 )
 | 
						|
    {
 | 
						|
      goto DeviceErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Disable "header complete" flag.  This means the supplied source MAC address is
 | 
						|
    // what goes on the wire.
 | 
						|
    //
 | 
						|
    Value = 1;
 | 
						|
    Result = Private->UnixThunk->IoCtl( Private->BpfFd, BIOCSHDRCMPLT, &Value );
 | 
						|
 | 
						|
    if ( Result < 0 )
 | 
						|
    {
 | 
						|
      goto DeviceErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    Result = Private->UnixThunk->IoCtl( Private->BpfFd, BIOCGBLEN, &Value );
 | 
						|
 | 
						|
    if ( Result < 0 )
 | 
						|
    {
 | 
						|
      goto DeviceErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Allocate read buffer.
 | 
						|
    //
 | 
						|
    Private->ReadBufferSize = Value;
 | 
						|
    Private->ReadBuffer = AllocateZeroPool( Private->ReadBufferSize );
 | 
						|
    if ( Private->ReadBuffer == NULL )
 | 
						|
    {
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto ErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer;
 | 
						|
 | 
						|
    //
 | 
						|
    // Install our packet filter: successful reads should only produce broadcast or unitcast
 | 
						|
    // packets directed to our fake MAC address.
 | 
						|
    //
 | 
						|
    FilterProgram = AllocateCopyPool( sizeof( FilterInstructionTemplate ), &FilterInstructionTemplate );
 | 
						|
    if ( FilterProgram == NULL )
 | 
						|
    {
 | 
						|
      goto ErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Insert out fake MAC address into the filter.  The data has to be host endian.
 | 
						|
    //
 | 
						|
    CopyMem( &Temp32, &Private->Mode.CurrentAddress.Addr[ 0 ], sizeof( UINT32 ) );
 | 
						|
    FilterProgram[ 1 ].k = NTOHL( Temp32 );
 | 
						|
    CopyMem( &Temp16, &Private->Mode.CurrentAddress.Addr[ 4 ], sizeof( UINT16 ) );
 | 
						|
    FilterProgram[ 3 ].k = NTOHS( Temp16 );
 | 
						|
 | 
						|
    BpfProgram.bf_len = sizeof( FilterInstructionTemplate ) / sizeof( struct bpf_insn );
 | 
						|
    BpfProgram.bf_insns = FilterProgram;
 | 
						|
 | 
						|
    Result = Private->UnixThunk->IoCtl( Private->BpfFd, BIOCSETF, &BpfProgram );
 | 
						|
 | 
						|
    if ( Result < 0 )
 | 
						|
    {
 | 
						|
      goto DeviceErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool( FilterProgram );
 | 
						|
 | 
						|
    //
 | 
						|
    // Enable promiscuous mode.
 | 
						|
    //
 | 
						|
 | 
						|
    Result = Private->UnixThunk->IoCtl( Private->BpfFd, BIOCPROMISC, 0 );
 | 
						|
 | 
						|
    if ( Result < 0 )
 | 
						|
    {
 | 
						|
      goto DeviceErrorExit;
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
    Private->Snp.Mode->State = EfiSimpleNetworkStarted;      
 | 
						|
  }
 | 
						|
 | 
						|
  return( Status );
 | 
						|
 | 
						|
DeviceErrorExit:
 | 
						|
  Status = EFI_DEVICE_ERROR;
 | 
						|
ErrorExit:
 | 
						|
  if ( Private->ReadBuffer != NULL )
 | 
						|
  {
 | 
						|
    FreePool( Private->ReadBuffer );
 | 
						|
    Private->ReadBuffer = NULL;
 | 
						|
  }
 | 
						|
  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
 | 
						|
UnixSnpStop(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private = EFI_SUCCESS;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( This );
 | 
						|
 | 
						|
  switch ( Private->Snp.Mode->State )
 | 
						|
  {
 | 
						|
    case EfiSimpleNetworkStarted:
 | 
						|
      break;
 | 
						|
 | 
						|
    case EfiSimpleNetworkStopped:
 | 
						|
      return( EFI_NOT_STARTED );
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      return( EFI_DEVICE_ERROR );
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( Private->BpfFd != 0 )
 | 
						|
  {
 | 
						|
    Private->UnixThunk->Close( Private->BpfFd );
 | 
						|
    Private->BpfFd = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( Private->ReadBuffer != NULL )
 | 
						|
  {
 | 
						|
    FreePool( Private->ReadBuffer );
 | 
						|
    Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Snp.Mode->State = EfiSimpleNetworkStopped;
 | 
						|
 | 
						|
  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
 | 
						|
UnixSnpInitialize(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN UINTN              ExtraRxBufferSize OPTIONAL,
 | 
						|
  IN UINTN              ExtraTxBufferSize OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private = EFI_SUCCESS;
 | 
						|
  EFI_STATUS              Status;
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( This );
 | 
						|
 | 
						|
  switch ( Private->Snp.Mode->State )
 | 
						|
  {
 | 
						|
    case EfiSimpleNetworkStarted:
 | 
						|
      break;
 | 
						|
 | 
						|
    case EfiSimpleNetworkStopped:
 | 
						|
      return( EFI_NOT_STARTED );
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      return( EFI_DEVICE_ERROR );
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
#if 0
 | 
						|
  Status = gBS->CreateEvent(
 | 
						|
          EVT_NOTIFY_WAIT,
 | 
						|
          TPL_NOTIFY,
 | 
						|
          UnixSnpWaitForPacketNotify,
 | 
						|
          Private,
 | 
						|
          &Private->Snp.WaitForPacket
 | 
						|
          );
 | 
						|
#endif
 | 
						|
 | 
						|
  if ( !EFI_ERROR( Status ) )
 | 
						|
  {
 | 
						|
    Private->Mode.MCastFilterCount = 0;
 | 
						|
    Private->Mode.ReceiveFilterSetting = 0;
 | 
						|
    ZeroMem( Private->Mode.MCastFilter, sizeof( Private->Mode.MCastFilter ) );
 | 
						|
 | 
						|
    Private->Snp.Mode->State = EfiSimpleNetworkInitialized;
 | 
						|
  }
 | 
						|
 | 
						|
  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
 | 
						|
UnixSnpReset(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private;
 | 
						|
  EFI_STATUS              Success = EFI_SUCCESS;
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( This );
 | 
						|
 | 
						|
  switch ( Private->Snp.Mode->State )
 | 
						|
  {
 | 
						|
    case EfiSimpleNetworkInitialized:
 | 
						|
      break;
 | 
						|
 | 
						|
    case EfiSimpleNetworkStopped:
 | 
						|
      return( EFI_NOT_STARTED );
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      return( EFI_DEVICE_ERROR );
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  return( Success );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpShutdown(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private;
 | 
						|
  EFI_STATUS              Success = EFI_SUCCESS;
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( This );
 | 
						|
 | 
						|
  switch ( Private->Snp.Mode->State )
 | 
						|
  {
 | 
						|
    case EfiSimpleNetworkInitialized:
 | 
						|
      break;
 | 
						|
 | 
						|
    case EfiSimpleNetworkStopped:
 | 
						|
      return( EFI_NOT_STARTED );
 | 
						|
      break;
 | 
						|
 | 
						|
    default:
 | 
						|
      return( EFI_DEVICE_ERROR );
 | 
						|
      break;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Snp.Mode->State = EfiSimpleNetworkStarted;
 | 
						|
 | 
						|
  Private->Mode.ReceiveFilterSetting = 0;
 | 
						|
  Private->Mode.MCastFilterCount = 0;
 | 
						|
  ZeroMem( Private->Mode.MCastFilter, sizeof( Private->Mode.MCastFilter ) );
 | 
						|
 | 
						|
  if ( Private->Snp.WaitForPacket != NULL )
 | 
						|
  {
 | 
						|
    gBS->CloseEvent( Private->Snp.WaitForPacket );
 | 
						|
    Private->Snp.WaitForPacket = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( Private->BpfFd != 0 )
 | 
						|
  {
 | 
						|
    Private->UnixThunk->Close( Private->BpfFd );
 | 
						|
    Private->BpfFd = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( Private->ReadBuffer != NULL )
 | 
						|
  {
 | 
						|
    FreePool( Private->ReadBuffer );
 | 
						|
    Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return( Success );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpReceiveFilters(
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private;
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( This );
 | 
						|
 | 
						|
//  ReturnValue = GlobalData->NtNetUtilityTable.SetReceiveFilter (
 | 
						|
//                                                Instance->InterfaceInfo.InterfaceIndex,
 | 
						|
//                                                EnableBits,
 | 
						|
//                                                McastFilterCount,
 | 
						|
//                                                McastFilter
 | 
						|
//                                                );
 | 
						|
 | 
						|
  // For now, just succeed...
 | 
						|
  return( EFI_SUCCESS );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpStationAddress(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              Reset,
 | 
						|
  IN EFI_MAC_ADDRESS*          NewMacAddr OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  return( EFI_UNSUPPORTED );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpStatistics(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              Reset,
 | 
						|
  IN OUT UINTN*            StatisticsSize OPTIONAL,
 | 
						|
  OUT EFI_NETWORK_STATISTICS*      StatisticsTable OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  return( EFI_UNSUPPORTED );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpMcastIptoMac(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              Ipv6,
 | 
						|
  IN EFI_IP_ADDRESS*          Ip,
 | 
						|
  OUT EFI_MAC_ADDRESS*        Mac
 | 
						|
  )
 | 
						|
{
 | 
						|
  return( EFI_UNSUPPORTED );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpNvdata(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  IN BOOLEAN              ReadOrWrite,
 | 
						|
  IN UINTN              Offset,
 | 
						|
  IN UINTN              BufferSize,
 | 
						|
  IN OUT VOID*            Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  return( EFI_UNSUPPORTED );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpGetStatus(
 | 
						|
  IN EFI_SIMPLE_NETWORK_PROTOCOL*    This,
 | 
						|
  OUT UINT32*              InterruptStatus,
 | 
						|
  OUT VOID**              TxBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  if ( TxBuffer != NULL )
 | 
						|
  {
 | 
						|
    *( ( UINT8 ** ) TxBuffer ) = ( UINT8 * ) 1;
 | 
						|
  }
 | 
						|
 | 
						|
  if ( InterruptStatus != NULL )
 | 
						|
  {
 | 
						|
    *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
 | 
						|
  }
 | 
						|
 | 
						|
  return( EFI_SUCCESS );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpTransmit(
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private;
 | 
						|
  EthernetHeader*            EnetHeader;
 | 
						|
  INTN                Result;
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( This );
 | 
						|
 | 
						|
  if ( This->Mode->State < EfiSimpleNetworkStarted )
 | 
						|
  {
 | 
						|
    return( EFI_NOT_STARTED );
 | 
						|
  }
 | 
						|
 | 
						|
  if ( HeaderSize != 0 )
 | 
						|
  {
 | 
						|
    if ( ( DestAddr == NULL ) || ( Protocol == NULL ) || ( HeaderSize != This->Mode->MediaHeaderSize ) )
 | 
						|
    {
 | 
						|
      return( EFI_INVALID_PARAMETER );
 | 
						|
    }
 | 
						|
 | 
						|
    if ( SrcAddr == NULL )
 | 
						|
    {
 | 
						|
      SrcAddr = &This->Mode->CurrentAddress;
 | 
						|
    }
 | 
						|
 | 
						|
    EnetHeader = ( EthernetHeader * ) Buffer;
 | 
						|
 | 
						|
    CopyMem( EnetHeader->DstAddr, DestAddr, NET_ETHER_ADDR_LEN );
 | 
						|
    CopyMem( EnetHeader->SrcAddr, SrcAddr, NET_ETHER_ADDR_LEN );
 | 
						|
 | 
						|
    EnetHeader->Type = HTONS( *Protocol );
 | 
						|
  }
 | 
						|
 | 
						|
  Result = Private->UnixThunk->Write( Private->BpfFd, Buffer, BufferSize );
 | 
						|
 | 
						|
  if ( Result < 0 )
 | 
						|
  {
 | 
						|
    return( EFI_DEVICE_ERROR );
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    return( EFI_SUCCESS );
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
UnixSnpReceive(
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private;
 | 
						|
  struct bpf_hdr*            BpfHeader;
 | 
						|
  EthernetHeader*            EnetHeader;
 | 
						|
  EFI_STATUS              Status = EFI_SUCCESS;
 | 
						|
  INTN                Result;
 | 
						|
 | 
						|
  if ( This->Mode->State < EfiSimpleNetworkStarted )
 | 
						|
  {
 | 
						|
    return( EFI_NOT_STARTED );
 | 
						|
  }
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( This );
 | 
						|
 | 
						|
  //
 | 
						|
  // Do we have any remaining packets from the previous read?
 | 
						|
  //
 | 
						|
  if ( Private->CurrentReadPointer >= Private->EndReadPointer )
 | 
						|
  {
 | 
						|
    Result = Private->UnixThunk->Read( Private->BpfFd, Private->ReadBuffer, Private->ReadBufferSize );
 | 
						|
 | 
						|
    if ( Result < 0 )
 | 
						|
    {
 | 
						|
      Result = Private->UnixThunk->GetErrno();
 | 
						|
 | 
						|
      //
 | 
						|
      // EAGAIN means that there's no I/O outstanding against this file descriptor.
 | 
						|
      //
 | 
						|
      if ( Result == EAGAIN )
 | 
						|
      {
 | 
						|
        return( EFI_NOT_READY );
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        return( EFI_DEVICE_ERROR );
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    if ( Result == 0 )
 | 
						|
    {
 | 
						|
      return( EFI_NOT_READY );
 | 
						|
    }
 | 
						|
 | 
						|
    Private->CurrentReadPointer = Private->ReadBuffer;
 | 
						|
    Private->EndReadPointer = Private->CurrentReadPointer + Result;
 | 
						|
  }
 | 
						|
 | 
						|
  BpfHeader = Private->CurrentReadPointer;
 | 
						|
  EnetHeader = Private->CurrentReadPointer + BpfHeader->bh_hdrlen;
 | 
						|
 | 
						|
  if ( BpfHeader->bh_caplen > *BuffSize )
 | 
						|
  {
 | 
						|
    *BuffSize = BpfHeader->bh_caplen;
 | 
						|
    return( EFI_BUFFER_TOO_SMALL );
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem( Buffer, EnetHeader, BpfHeader->bh_caplen );
 | 
						|
  *BuffSize = BpfHeader->bh_caplen;
 | 
						|
 | 
						|
  if ( HeaderSize != NULL )
 | 
						|
  {
 | 
						|
    *HeaderSize = sizeof( EthernetHeader );
 | 
						|
  }
 | 
						|
 | 
						|
  if ( DestinationAddr != NULL )
 | 
						|
  {
 | 
						|
    ZeroMem( DestinationAddr, sizeof( EFI_MAC_ADDRESS ) );
 | 
						|
    CopyMem( DestinationAddr, EnetHeader->DstAddr, NET_ETHER_ADDR_LEN );
 | 
						|
  }
 | 
						|
 | 
						|
  if ( SourceAddr != NULL )
 | 
						|
  {
 | 
						|
    ZeroMem( SourceAddr, sizeof( EFI_MAC_ADDRESS ) );
 | 
						|
    CopyMem( SourceAddr, EnetHeader->SrcAddr, NET_ETHER_ADDR_LEN );
 | 
						|
  }
 | 
						|
 | 
						|
  if ( Protocol != NULL )
 | 
						|
  {
 | 
						|
    *Protocol = NTOHS( EnetHeader->Type );
 | 
						|
  }
 | 
						|
 | 
						|
  Private->CurrentReadPointer += BPF_WORDALIGN( BpfHeader->bh_hdrlen + BpfHeader->bh_caplen );
 | 
						|
 | 
						|
  return( Status );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
UnixSnpWaitForPacketNotify(
 | 
						|
  IN EFI_EVENT            Event,
 | 
						|
  IN VOID*              Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  UNIX_SNP_PRIVATE_DATA*        Private;
 | 
						|
 | 
						|
  Private = UNIX_SNP_PRIVATE_DATA_FROM_SNP_THIS( Context );
 | 
						|
 | 
						|
  if ( Private->Snp.Mode->State < EfiSimpleNetworkStarted )
 | 
						|
  {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  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
 | 
						|
InitializeUnixSnpDriver(
 | 
						|
  IN EFI_HANDLE        ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE*    SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
 | 
						|
  //
 | 
						|
  // Install the Driver Protocols
 | 
						|
  //
 | 
						|
 | 
						|
  Status = EfiLibInstallDriverBindingComponentName2(
 | 
						|
          ImageHandle,
 | 
						|
          SystemTable,
 | 
						|
          &gUnixSnpDriverBinding,
 | 
						|
          ImageHandle,
 | 
						|
          &gUnixSnpDriverComponentName,
 | 
						|
          &gUnixSnpDriverComponentName2
 | 
						|
          );
 | 
						|
 | 
						|
  return( Status );
 | 
						|
}
 |