EDK2 doxygen online documents - Firmware Encoding Index 1
EDK2 doxygen online documents - Firmware Encoding Index

EmulatorPkg/Unix/Host/BerkeleyPacketFilter.c

Go to the documentation of this file.
00001 
00021 #include "Host.h"
00022 
00023 #ifdef __APPLE__
00024 
00025 
00026 #include <Library/NetLib.h>
00027 
00028 
00029 #define EMU_SNP_PRIVATE_SIGNATURE SIGNATURE_32('E', 'M', 's', 'n')
00030 typedef struct {
00031   UINTN                       Signature;
00032 
00033   EMU_IO_THUNK_PROTOCOL       *Thunk;
00034   EMU_SNP_PROTOCOL            EmuSnp;
00035   EFI_SIMPLE_NETWORK_MODE     *Mode;
00036 
00037   int                         BpfFd;
00038   char                        *InterfaceName;
00039   EFI_MAC_ADDRESS             MacAddress;
00040   u_int                       ReadBufferSize;
00041   VOID                        *ReadBuffer;
00042 
00043   //
00044   // Two walking pointers to manage the multiple packets that can be returned
00045   // in a single read.
00046   //
00047   VOID                        *CurrentReadPointer;
00048   VOID                        *EndReadPointer;
00049 
00050         UINT32                                                                      ReceivedPackets;
00051         UINT32                                                                      DroppedPackets;
00052 
00053 } EMU_SNP_PRIVATE;
00054 
00055 #define EMU_SNP_PRIVATE_DATA_FROM_THIS(a) \
00056          CR(a, EMU_SNP_PRIVATE, EmuSnp, EMU_SNP_PRIVATE_SIGNATURE)
00057 
00058 
00059 //
00060 // Strange, but there doesn't appear to be any structure for the Ethernet header in edk2...
00061 //
00062 
00063 typedef struct {
00064   UINT8   DstAddr[NET_ETHER_ADDR_LEN];
00065   UINT8   SrcAddr[NET_ETHER_ADDR_LEN];
00066   UINT16  Type;
00067 } ETHERNET_HEADER;
00068 
00079 EFI_STATUS
00080 EmuSnpCreateMapping (
00081   IN     EMU_SNP_PROTOCOL         *This,
00082   IN     EFI_SIMPLE_NETWORK_MODE  *Mode
00083   )
00084 {
00085   EMU_SNP_PRIVATE    *Private;
00086 
00087   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00088 
00089   Private->Mode = Mode;
00090 
00091   //
00092   // Set the broadcast address.
00093   //
00094   SetMem (&Mode->BroadcastAddress, sizeof (EFI_MAC_ADDRESS), 0xFF);
00095 
00096   CopyMem (&Mode->CurrentAddress, &Private->MacAddress, sizeof (EFI_MAC_ADDRESS));
00097   CopyMem (&Mode->PermanentAddress, &Private->MacAddress, sizeof (EFI_MAC_ADDRESS));
00098 
00099   //
00100   // Since the fake SNP is based on a real NIC, to avoid conflict with the host NIC
00101   // network stack, we use a different MAC address.
00102   // So just change the last byte of the MAC address for the real NIC.
00103   //
00104   Mode->CurrentAddress.Addr[NET_ETHER_ADDR_LEN - 1]++;
00105 
00106   return EFI_SUCCESS;
00107 }
00108 
00109 
00110 static struct bpf_insn mFilterInstructionTemplate[] = {
00111   // Load 4 bytes from the destination MAC address.
00112   BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])),
00113 
00114   // Compare to first 4 bytes of fake MAC address.
00115   BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x12345678, 0, 3 ),
00116 
00117   // Load remaining 2 bytes from the destination MAC address.
00118   BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( ETHERNET_HEADER, DstAddr[4])),
00119 
00120   // Compare to remaining 2 bytes of fake MAC address.
00121   BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0x9ABC, 5, 0 ),
00122 
00123   // Load 4 bytes from the destination MAC address.
00124   BPF_STMT (BPF_LD + BPF_W + BPF_ABS, OFFSET_OF (ETHERNET_HEADER, DstAddr[0])),
00125 
00126   // Compare to first 4 bytes of broadcast MAC address.
00127   BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0xFFFFFFFF, 0, 2),
00128 
00129   // Load remaining 2 bytes from the destination MAC address.
00130   BPF_STMT (BPF_LD + BPF_H + BPF_ABS, OFFSET_OF( ETHERNET_HEADER, DstAddr[4])),
00131 
00132   // Compare to remaining 2 bytes of broadcast MAC address.
00133   BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, 0xFFFF, 1, 0),
00134 
00135   // Reject packet.
00136   BPF_STMT (BPF_RET + BPF_K, 0),
00137 
00138   // Receive entire packet.
00139   BPF_STMT (BPF_RET + BPF_K, -1)
00140 };
00141 
00142 
00143 EFI_STATUS
00144 OpenBpfFileDescriptor (
00145   IN EMU_SNP_PRIVATE  *Private,
00146   OUT int             *Fd
00147   )
00148 {
00149   char  BfpDeviceName[256];
00150   int   Index;
00151 
00152   //
00153   // Open a Berkeley Packet Filter device.  This must be done as root, so this is probably
00154   // the place which is most likely to fail...
00155   //
00156   for (Index = 0; TRUE; Index++ ) {
00157     snprintf (BfpDeviceName, sizeof (BfpDeviceName), "/dev/bpf%d", Index);
00158 
00159     *Fd = open (BfpDeviceName, O_RDWR, 0);
00160     if ( *Fd >= 0 ) {
00161       return EFI_SUCCESS;
00162     }
00163 
00164     if (errno == EACCES) {
00165       printf (
00166         "SNP: Permissions on '%s' are incorrect.  Fix with 'sudo chmod 666 %s'.\n",
00167         BfpDeviceName,
00168         BfpDeviceName
00169         );
00170     }
00171 
00172     if (errno != EBUSY) {
00173       break;
00174     }
00175   }
00176 
00177   return EFI_OUT_OF_RESOURCES;
00178 }
00179 
00180 
00193 EFI_STATUS
00194 EmuSnpStart (
00195   IN EMU_SNP_PROTOCOL  *This
00196   )
00197 {
00198   EFI_STATUS         Status;
00199   EMU_SNP_PRIVATE    *Private;
00200   struct ifreq       BoundIf;
00201   struct bpf_program BpfProgram;
00202   struct bpf_insn    *FilterProgram;
00203         u_int                                                    Value;
00204         u_int                                            ReadBufferSize;
00205   UINT16             Temp16;
00206   UINT32             Temp32;
00207 
00208   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00209 
00210   switch (Private->Mode->State) {
00211     case EfiSimpleNetworkStopped:
00212       break;
00213 
00214     case EfiSimpleNetworkStarted:
00215     case EfiSimpleNetworkInitialized:
00216       return EFI_ALREADY_STARTED;
00217       break;
00218 
00219     default:
00220       return EFI_DEVICE_ERROR;
00221       break;
00222   }
00223 
00224   Status = EFI_SUCCESS;
00225   if (Private->BpfFd == 0) {
00226     Status = OpenBpfFileDescriptor (Private, &Private->BpfFd);
00227     if (EFI_ERROR (Status)) {
00228       goto DeviceErrorExit;
00229     }
00230 
00231     //
00232                 // Get the read buffer size.
00233                 //
00234                 if (ioctl (Private->BpfFd, BIOCGBLEN, &ReadBufferSize) < 0) {
00235                         goto DeviceErrorExit;
00236                 }
00237 
00238                 //
00239                 // Default value from BIOCGBLEN is usually too small, so use a much larger size, if necessary.
00240                 //
00241                 if (ReadBufferSize < FixedPcdGet32 (PcdNetworkPacketFilterSize)) {
00242                         ReadBufferSize = FixedPcdGet32 (PcdNetworkPacketFilterSize);
00243                         if (ioctl (Private->BpfFd, BIOCSBLEN, &ReadBufferSize) < 0) {
00244                                 goto DeviceErrorExit;
00245                         }
00246                 }
00247 
00248                 //
00249     // Associate our interface with this BPF file descriptor.
00250     //
00251     AsciiStrCpy (BoundIf.ifr_name, Private->InterfaceName);
00252     if (ioctl (Private->BpfFd, BIOCSETIF, &BoundIf) < 0) {
00253       goto DeviceErrorExit;
00254     }
00255 
00256     //
00257                 // Enable immediate mode.
00258     //
00259     Value = 1;
00260     if (ioctl (Private->BpfFd, BIOCIMMEDIATE, &Value) < 0) {
00261       goto DeviceErrorExit;
00262     }
00263 
00264     //
00265     // Enable non-blocking I/O.
00266     //
00267     if (fcntl (Private->BpfFd, F_GETFL, 0) == -1) {
00268       goto DeviceErrorExit;
00269     }
00270 
00271     Value |= O_NONBLOCK;
00272 
00273     if (fcntl (Private->BpfFd, F_SETFL, Value) == -1) {
00274       goto DeviceErrorExit;
00275     }
00276 
00277     //
00278     // Disable "header complete" flag.  This means the supplied source MAC address is
00279     // what goes on the wire.
00280     //
00281     Value = 1;
00282     if (ioctl (Private->BpfFd, BIOCSHDRCMPLT, &Value) < 0) {
00283       goto DeviceErrorExit;
00284     }
00285 
00286     //
00287     // Allocate read buffer.
00288     //
00289                 Private->ReadBufferSize = ReadBufferSize;
00290                 Private->ReadBuffer = malloc (Private->ReadBufferSize);
00291     if (Private->ReadBuffer == NULL) {
00292       goto ErrorExit;
00293     }
00294 
00295     Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer;
00296 
00297     //
00298                 // Install our packet filter: successful reads should only produce broadcast or unicast
00299     // packets directed to our fake MAC address.
00300     //
00301     FilterProgram = malloc (sizeof (mFilterInstructionTemplate)) ;
00302     if ( FilterProgram == NULL ) {
00303       goto ErrorExit;
00304     }
00305 
00306     CopyMem (FilterProgram, &mFilterInstructionTemplate, sizeof (mFilterInstructionTemplate));
00307 
00308     //
00309     // Insert out fake MAC address into the filter.  The data has to be host endian.
00310     //
00311     CopyMem (&Temp32, &Private->Mode->CurrentAddress.Addr[0], sizeof (UINT32));
00312     FilterProgram[1].k = NTOHL (Temp32);
00313     CopyMem (&Temp16, &Private->Mode->CurrentAddress.Addr[4], sizeof (UINT16));
00314     FilterProgram[3].k = NTOHS (Temp16);
00315 
00316     BpfProgram.bf_len = sizeof (mFilterInstructionTemplate) / sizeof (struct bpf_insn);
00317     BpfProgram.bf_insns = FilterProgram;
00318 
00319     if (ioctl (Private->BpfFd, BIOCSETF, &BpfProgram) < 0) {
00320       goto DeviceErrorExit;
00321     }
00322 
00323     free (FilterProgram);
00324 
00325     //
00326     // Enable promiscuous mode.
00327     //
00328     if (ioctl (Private->BpfFd, BIOCPROMISC, 0) < 0) {
00329       goto DeviceErrorExit;
00330     }
00331 
00332 
00333     Private->Mode->State = EfiSimpleNetworkStarted;
00334   }
00335 
00336   return Status;
00337 
00338 DeviceErrorExit:
00339   Status = EFI_DEVICE_ERROR;
00340 ErrorExit:
00341   if (Private->ReadBuffer != NULL) {
00342     free (Private->ReadBuffer);
00343     Private->ReadBuffer = NULL;
00344   }
00345   return Status;
00346 }
00347 
00348 
00361 EFI_STATUS
00362 EmuSnpStop (
00363   IN EMU_SNP_PROTOCOL  *This
00364   )
00365 {
00366   EMU_SNP_PRIVATE    *Private;
00367 
00368   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00369 
00370   switch ( Private->Mode->State ) {
00371     case EfiSimpleNetworkStarted:
00372       break;
00373 
00374     case EfiSimpleNetworkStopped:
00375       return EFI_NOT_STARTED;
00376       break;
00377 
00378     default:
00379       return EFI_DEVICE_ERROR;
00380       break;
00381   }
00382 
00383   if (Private->BpfFd != 0) {
00384     close (Private->BpfFd);
00385     Private->BpfFd = 0;
00386   }
00387 
00388   if (Private->ReadBuffer != NULL) {
00389     free (Private->ReadBuffer );
00390     Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer = NULL;
00391   }
00392 
00393   Private->Mode->State = EfiSimpleNetworkStopped;
00394 
00395   return EFI_SUCCESS;
00396 }
00397 
00398 
00425 EFI_STATUS
00426 EmuSnpInitialize (
00427   IN EMU_SNP_PROTOCOL                    *This,
00428   IN UINTN                               ExtraRxBufferSize  OPTIONAL,
00429   IN UINTN                               ExtraTxBufferSize  OPTIONAL
00430   )
00431 {
00432   EMU_SNP_PRIVATE    *Private;
00433 
00434   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00435 
00436   switch ( Private->Mode->State ) {
00437     case EfiSimpleNetworkStarted:
00438       break;
00439 
00440     case EfiSimpleNetworkStopped:
00441       return EFI_NOT_STARTED;
00442       break;
00443 
00444     default:
00445       return EFI_DEVICE_ERROR;
00446       break;
00447   }
00448 
00449   Private->Mode->MCastFilterCount = 0;
00450   Private->Mode->ReceiveFilterSetting = 0;
00451   ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter));
00452 
00453   Private->Mode->State = EfiSimpleNetworkInitialized;
00454 
00455   return EFI_SUCCESS;
00456 }
00457 
00458 
00475 EFI_STATUS
00476 EmuSnpReset (
00477   IN EMU_SNP_PROTOCOL   *This,
00478   IN BOOLEAN            ExtendedVerification
00479   )
00480 {
00481   EMU_SNP_PRIVATE    *Private;
00482 
00483   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00484 
00485   switch ( Private->Mode->State ) {
00486     case EfiSimpleNetworkInitialized:
00487       break;
00488 
00489     case EfiSimpleNetworkStopped:
00490       return EFI_NOT_STARTED;
00491       break;
00492 
00493     default:
00494       return EFI_DEVICE_ERROR;
00495       break;
00496   }
00497 
00498   return EFI_SUCCESS;
00499 }
00500 
00501 
00515 EFI_STATUS
00516 EmuSnpShutdown (
00517   IN EMU_SNP_PROTOCOL  *This
00518   )
00519 {
00520   EMU_SNP_PRIVATE    *Private;
00521 
00522   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00523 
00524   switch ( Private->Mode->State ) {
00525     case EfiSimpleNetworkInitialized:
00526       break;
00527 
00528     case EfiSimpleNetworkStopped:
00529       return EFI_NOT_STARTED;
00530       break;
00531 
00532     default:
00533       return EFI_DEVICE_ERROR;
00534       break;
00535   }
00536 
00537   Private->Mode->State = EfiSimpleNetworkStarted;
00538 
00539   Private->Mode->ReceiveFilterSetting = 0;
00540   Private->Mode->MCastFilterCount = 0;
00541   ZeroMem (Private->Mode->MCastFilter, sizeof (Private->Mode->MCastFilter));
00542 
00543   if (Private->BpfFd != 0) {
00544     close (Private->BpfFd);
00545     Private->BpfFd = 0;
00546   }
00547 
00548   if (Private->ReadBuffer != NULL) {
00549     free (Private->ReadBuffer);
00550     Private->CurrentReadPointer = Private->EndReadPointer = Private->ReadBuffer = NULL;
00551   }
00552 
00553   return EFI_SUCCESS;
00554 }
00555 
00580 EFI_STATUS
00581 EmuSnpReceiveFilters (
00582   IN EMU_SNP_PROTOCOL                             *This,
00583   IN UINT32                                       Enable,
00584   IN UINT32                                       Disable,
00585   IN BOOLEAN                                      ResetMCastFilter,
00586   IN UINTN                                        MCastFilterCnt     OPTIONAL,
00587   IN EFI_MAC_ADDRESS                              *MCastFilter OPTIONAL
00588   )
00589 {
00590   EMU_SNP_PRIVATE    *Private;
00591 
00592   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00593 
00594   // For now, just succeed...
00595   return EFI_SUCCESS;
00596 }
00597 
00598 
00614 EFI_STATUS
00615 EmuSnpStationAddress (
00616   IN EMU_SNP_PROTOCOL            *This,
00617   IN BOOLEAN                     Reset,
00618   IN EFI_MAC_ADDRESS             *New OPTIONAL
00619   )
00620 {
00621   EMU_SNP_PRIVATE    *Private;
00622 
00623   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00624 
00625   return EFI_UNSUPPORTED;
00626 }
00627 
00628 
00650 EFI_STATUS
00651 EmuSnpStatistics (
00652   IN EMU_SNP_PROTOCOL                     *This,
00653   IN BOOLEAN                              Reset,
00654   IN OUT UINTN                            *StatisticsSize   OPTIONAL,
00655   OUT EFI_NETWORK_STATISTICS              *StatisticsTable  OPTIONAL
00656   )
00657 {
00658   EMU_SNP_PRIVATE    *Private;
00659 
00660   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00661 
00662   return EFI_UNSUPPORTED;
00663 }
00664 
00665 
00687 EFI_STATUS
00688 EmuSnpMCastIpToMac (
00689   IN EMU_SNP_PROTOCOL                     *This,
00690   IN BOOLEAN                              IPv6,
00691   IN EFI_IP_ADDRESS                       *IP,
00692   OUT EFI_MAC_ADDRESS                     *MAC
00693   )
00694 {
00695   EMU_SNP_PRIVATE    *Private;
00696 
00697   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00698 
00699   return EFI_UNSUPPORTED;
00700 }
00701 
00702 
00723 EFI_STATUS
00724 EmuSnpNvData (
00725   IN EMU_SNP_PROTOCOL                     *This,
00726   IN BOOLEAN                              ReadWrite,
00727   IN UINTN                                Offset,
00728   IN UINTN                                BufferSize,
00729   IN OUT VOID                             *Buffer
00730   )
00731 {
00732   EMU_SNP_PRIVATE    *Private;
00733 
00734   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00735 
00736   return EFI_UNSUPPORTED;
00737 }
00738 
00764 EFI_STATUS
00765 EmuSnpGetStatus (
00766   IN EMU_SNP_PROTOCOL                     *This,
00767   OUT UINT32                              *InterruptStatus OPTIONAL,
00768   OUT VOID                                **TxBuf OPTIONAL
00769   )
00770 {
00771   EMU_SNP_PRIVATE    *Private;
00772 
00773   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00774 
00775   if (TxBuf != NULL) {
00776     *((UINT8 **)TxBuf) =  (UINT8 *)1;
00777   }
00778 
00779   if ( InterruptStatus != NULL ) {
00780     *InterruptStatus = EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
00781   }
00782 
00783   return EFI_SUCCESS;
00784 }
00785 
00786 
00820 EFI_STATUS
00821 EmuSnpTransmit (
00822   IN EMU_SNP_PROTOCOL                     *This,
00823   IN UINTN                                HeaderSize,
00824   IN UINTN                                BufferSize,
00825   IN VOID                                 *Buffer,
00826   IN EFI_MAC_ADDRESS                      *SrcAddr  OPTIONAL,
00827   IN EFI_MAC_ADDRESS                      *DestAddr OPTIONAL,
00828   IN UINT16                               *Protocol OPTIONAL
00829   )
00830 {
00831   EMU_SNP_PRIVATE    *Private;
00832   ETHERNET_HEADER    *EnetHeader;
00833 
00834   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00835 
00836   if (Private->Mode->State < EfiSimpleNetworkStarted) {
00837     return EFI_NOT_STARTED;
00838   }
00839 
00840   if ( HeaderSize != 0 ) {
00841     if ((DestAddr == NULL) || (Protocol == NULL) || (HeaderSize != Private->Mode->MediaHeaderSize)) {
00842       return EFI_INVALID_PARAMETER;
00843     }
00844 
00845     if (SrcAddr == NULL) {
00846       SrcAddr = &Private->Mode->CurrentAddress;
00847     }
00848 
00849     EnetHeader = (ETHERNET_HEADER *) Buffer;
00850 
00851     CopyMem (EnetHeader->DstAddr, DestAddr, NET_ETHER_ADDR_LEN);
00852     CopyMem (EnetHeader->SrcAddr, SrcAddr, NET_ETHER_ADDR_LEN);
00853 
00854     EnetHeader->Type = HTONS(*Protocol);
00855   }
00856 
00857   if (write  (Private->BpfFd, Buffer, BufferSize) < 0) {
00858     return EFI_DEVICE_ERROR;
00859   }
00860 
00861   return EFI_SUCCESS;
00862 }
00863 
00896 EFI_STATUS
00897 EmuSnpReceive (
00898   IN EMU_SNP_PROTOCOL                     *This,
00899   OUT UINTN                               *HeaderSize OPTIONAL,
00900   IN OUT UINTN                            *BufferSize,
00901   OUT VOID                                *Buffer,
00902   OUT EFI_MAC_ADDRESS                     *SrcAddr    OPTIONAL,
00903   OUT EFI_MAC_ADDRESS                     *DestAddr   OPTIONAL,
00904   OUT UINT16                              *Protocol   OPTIONAL
00905   )
00906 {
00907   EMU_SNP_PRIVATE    *Private;
00908   struct bpf_hdr     *BpfHeader;
00909         struct bpf_stat    BpfStats;
00910   ETHERNET_HEADER    *EnetHeader;
00911   ssize_t            Result;
00912 
00913   Private = EMU_SNP_PRIVATE_DATA_FROM_THIS (This);
00914 
00915   if (Private->Mode->State < EfiSimpleNetworkStarted) {
00916     return EFI_NOT_STARTED;
00917   }
00918 
00919         ZeroMem (&BpfStats, sizeof( BpfStats));
00920 
00921         if (ioctl (Private->BpfFd, BIOCGSTATS, &BpfStats) == 0) {
00922                 Private->ReceivedPackets += BpfStats.bs_recv;
00923                 if (BpfStats.bs_drop > Private->DroppedPackets) {
00924                         printf (
00925                           "SNP: STATS: RCVD = %d DROPPED = %d.  Probably need to increase BPF PcdNetworkPacketFilterSize?\n",
00926                                 BpfStats.bs_recv,
00927                                 BpfStats.bs_drop - Private->DroppedPackets
00928                                 );
00929                         Private->DroppedPackets = BpfStats.bs_drop;
00930                 }
00931         }
00932 
00933   //
00934   // Do we have any remaining packets from the previous read?
00935   //
00936   if (Private->CurrentReadPointer >= Private->EndReadPointer) {
00937     Result = read (Private->BpfFd, Private->ReadBuffer, Private->ReadBufferSize);
00938     if (Result < 0) {
00939       // EAGAIN means that there's no I/O outstanding against this file descriptor.
00940       return (errno == EAGAIN) ? EFI_NOT_READY : EFI_DEVICE_ERROR;
00941     }
00942 
00943     if (Result == 0) {
00944       return EFI_NOT_READY;
00945     }
00946 
00947     Private->CurrentReadPointer = Private->ReadBuffer;
00948     Private->EndReadPointer = Private->CurrentReadPointer + Result;
00949   }
00950 
00951   BpfHeader = Private->CurrentReadPointer;
00952   EnetHeader = Private->CurrentReadPointer + BpfHeader->bh_hdrlen;
00953 
00954   if (BpfHeader->bh_caplen > *BufferSize) {
00955     *BufferSize = BpfHeader->bh_caplen;
00956     return EFI_BUFFER_TOO_SMALL;
00957   }
00958 
00959   CopyMem (Buffer, EnetHeader, BpfHeader->bh_caplen);
00960   *BufferSize = BpfHeader->bh_caplen;
00961 
00962   if (HeaderSize != NULL) {
00963     *HeaderSize = sizeof (ETHERNET_HEADER);
00964   }
00965 
00966   if (DestAddr != NULL) {
00967     ZeroMem (DestAddr, sizeof (EFI_MAC_ADDRESS));
00968     CopyMem (DestAddr, EnetHeader->DstAddr, NET_ETHER_ADDR_LEN);
00969   }
00970 
00971   if (SrcAddr != NULL) {
00972     ZeroMem (SrcAddr, sizeof (EFI_MAC_ADDRESS));
00973     CopyMem (SrcAddr, EnetHeader->SrcAddr, NET_ETHER_ADDR_LEN);
00974   }
00975 
00976   if (Protocol != NULL) {
00977     *Protocol = NTOHS (EnetHeader->Type);
00978   }
00979 
00980   Private->CurrentReadPointer += BPF_WORDALIGN (BpfHeader->bh_hdrlen + BpfHeader->bh_caplen);
00981   return EFI_SUCCESS;
00982 }
00983 
00984 
00985 EMU_SNP_PROTOCOL gEmuSnpProtocol = {
00986   GasketSnpCreateMapping,
00987   GasketSnpStart,
00988   GasketSnpStop,
00989   GasketSnpInitialize,
00990   GasketSnpReset,
00991   GasketSnpShutdown,
00992   GasketSnpReceiveFilters,
00993   GasketSnpStationAddress,
00994   GasketSnpStatistics,
00995   GasketSnpMCastIpToMac,
00996   GasketSnpNvData,
00997   GasketSnpGetStatus,
00998   GasketSnpTransmit,
00999   GasketSnpReceive
01000 };
01001 
01002 EFI_STATUS
01003 GetInterfaceMacAddr (
01004   EMU_SNP_PRIVATE    *Private
01005   )
01006 {
01007         EFI_STATUS                                Status;
01008   struct ifaddrs      *IfAddrs;
01009   struct ifaddrs      *If;
01010   struct sockaddr_dl  *IfSdl;
01011 
01012   if (getifaddrs (&IfAddrs) != 0) {
01013     return EFI_UNSUPPORTED;
01014   }
01015 
01016   //
01017   // Convert the interface name to ASCII so we can find it.
01018   //
01019   Private->InterfaceName = malloc (StrSize (Private->Thunk->ConfigString));
01020   if (Private->InterfaceName == NULL) {
01021     Status = EFI_OUT_OF_RESOURCES;
01022     goto Exit;
01023   }
01024 
01025   UnicodeStrToAsciiStr (Private->Thunk->ConfigString, Private->InterfaceName);
01026 
01027   Status = EFI_NOT_FOUND;
01028   If = IfAddrs;
01029   while (If != NULL) {
01030     IfSdl = (struct sockaddr_dl *)If->ifa_addr;
01031 
01032     if (IfSdl->sdl_family == AF_LINK) {
01033       if (!AsciiStrCmp( Private->InterfaceName, If->ifa_name)) {
01034         CopyMem (&Private->MacAddress, LLADDR (IfSdl), NET_ETHER_ADDR_LEN);
01035 
01036         Status = EFI_SUCCESS;
01037         break;
01038       }
01039     }
01040 
01041     If = If->ifa_next;
01042   }
01043 
01044 Exit:
01045   freeifaddrs (IfAddrs);
01046   return Status;
01047 }
01048 
01049 
01050 EFI_STATUS
01051 EmuSnpThunkOpen (
01052   IN  EMU_IO_THUNK_PROTOCOL   *This
01053   )
01054 {
01055   EMU_SNP_PRIVATE  *Private;
01056 
01057   if (This->Private != NULL) {
01058     return EFI_ALREADY_STARTED;
01059   }
01060 
01061   if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) {
01062     return EFI_UNSUPPORTED;
01063   }
01064 
01065   Private = malloc (sizeof (EMU_SNP_PRIVATE));
01066   if (Private == NULL) {
01067     return EFI_OUT_OF_RESOURCES;
01068   }
01069 
01070 
01071   Private->Signature = EMU_SNP_PRIVATE_SIGNATURE;
01072   Private->Thunk     = This;
01073   CopyMem (&Private->EmuSnp, &gEmuSnpProtocol, sizeof (gEmuSnpProtocol));
01074   GetInterfaceMacAddr (Private);
01075 
01076   This->Interface = &Private->EmuSnp;
01077   This->Private   = Private;
01078   return EFI_SUCCESS;
01079 }
01080 
01081 
01082 EFI_STATUS
01083 EmuSnpThunkClose (
01084   IN  EMU_IO_THUNK_PROTOCOL   *This
01085   )
01086 {
01087   EMU_SNP_PRIVATE  *Private;
01088 
01089   if (!CompareGuid (This->Protocol, &gEmuSnpProtocolGuid)) {
01090     return EFI_UNSUPPORTED;
01091   }
01092 
01093   Private = This->Private;
01094   free (Private);
01095 
01096   return EFI_SUCCESS;
01097 }
01098 
01099 
01100 
01101 EMU_IO_THUNK_PROTOCOL gSnpThunkIo = {
01102   &gEmuSnpProtocolGuid,
01103   NULL,
01104   NULL,
01105   0,
01106   GasketSnpThunkOpen,
01107   GasketSnpThunkClose,
01108   NULL
01109 };
01110 
01111 #endif
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Defines