Home | History | Annotate | Download | only in MnpDxe
      1 /** @file
      2   Implementation of Managed Network Protocol I/O functions.
      3 
      4 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions
      7 of the BSD License which accompanies this distribution.  The full
      8 text of the license may be found at<BR>
      9 http://opensource.org/licenses/bsd-license.php
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "MnpImpl.h"
     17 #include "MnpVlan.h"
     18 
     19 /**
     20   Validates the Mnp transmit token.
     21 
     22   @param[in]  Instance            Pointer to the Mnp instance context data.
     23   @param[in]  Token               Pointer to the transmit token to check.
     24 
     25   @return The Token is valid or not.
     26 
     27 **/
     28 BOOLEAN
     29 MnpIsValidTxToken (
     30   IN MNP_INSTANCE_DATA                       *Instance,
     31   IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN    *Token
     32   )
     33 {
     34   MNP_SERVICE_DATA                  *MnpServiceData;
     35   EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
     36   UINT32                            Index;
     37   UINT32                            TotalLength;
     38   EFI_MANAGED_NETWORK_FRAGMENT_DATA *FragmentTable;
     39 
     40   MnpServiceData = Instance->MnpServiceData;
     41   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
     42 
     43   TxData = Token->Packet.TxData;
     44 
     45   if ((Token->Event == NULL) || (TxData == NULL) || (TxData->FragmentCount == 0)) {
     46     //
     47     // The token is invalid if the Event is NULL, or the TxData is NULL, or
     48     // the fragment count is zero.
     49     //
     50     DEBUG ((EFI_D_WARN, "MnpIsValidTxToken: Invalid Token.\n"));
     51     return FALSE;
     52   }
     53 
     54   if ((TxData->DestinationAddress != NULL) && (TxData->HeaderLength != 0)) {
     55     //
     56     // The token is invalid if the HeaderLength isn't zero while the DestinationAddress
     57     // is NULL (The destination address is already put into the packet).
     58     //
     59     DEBUG ((EFI_D_WARN, "MnpIsValidTxToken: DestinationAddress isn't NULL, HeaderLength must be 0.\n"));
     60     return FALSE;
     61   }
     62 
     63   TotalLength   = 0;
     64   FragmentTable = TxData->FragmentTable;
     65   for (Index = 0; Index < TxData->FragmentCount; Index++) {
     66 
     67     if ((FragmentTable[Index].FragmentLength == 0) || (FragmentTable[Index].FragmentBuffer == NULL)) {
     68       //
     69       // The token is invalid if any FragmentLength is zero or any FragmentBuffer is NULL.
     70       //
     71       DEBUG ((EFI_D_WARN, "MnpIsValidTxToken: Invalid FragmentLength or FragmentBuffer.\n"));
     72       return FALSE;
     73     }
     74 
     75     TotalLength += FragmentTable[Index].FragmentLength;
     76   }
     77 
     78   if ((TxData->DestinationAddress == NULL) && (FragmentTable[0].FragmentLength < TxData->HeaderLength)) {
     79     //
     80     // Media header is split between fragments.
     81     //
     82     return FALSE;
     83   }
     84 
     85   if (TotalLength != (TxData->DataLength + TxData->HeaderLength)) {
     86     //
     87     // The length calculated from the fragment information doesn't equal to the
     88     // sum of the DataLength and the HeaderLength.
     89     //
     90     DEBUG ((EFI_D_WARN, "MnpIsValidTxData: Invalid Datalength compared with the sum of fragment length.\n"));
     91     return FALSE;
     92   }
     93 
     94   if (TxData->DataLength > MnpServiceData->Mtu) {
     95     //
     96     // The total length is larger than the MTU.
     97     //
     98     DEBUG ((EFI_D_WARN, "MnpIsValidTxData: TxData->DataLength exceeds Mtu.\n"));
     99     return FALSE;
    100   }
    101 
    102   return TRUE;
    103 }
    104 
    105 /**
    106   Build the packet to transmit from the TxData passed in.
    107 
    108   @param[in]   MnpServiceData      Pointer to the mnp service context data.
    109   @param[in]   TxData              Pointer to the transmit data containing the information
    110                                    to build the packet.
    111   @param[out]  PktBuf              Pointer to record the address of the packet.
    112   @param[out]  PktLen              Pointer to a UINT32 variable used to record the packet's
    113                                    length.
    114 
    115   @retval EFI_SUCCESS           TxPackage is built.
    116   @retval EFI_OUT_OF_RESOURCES  The deliver fails due to lack of memory resource.
    117 
    118 **/
    119 EFI_STATUS
    120 MnpBuildTxPacket (
    121   IN     MNP_SERVICE_DATA                    *MnpServiceData,
    122   IN     EFI_MANAGED_NETWORK_TRANSMIT_DATA   *TxData,
    123      OUT UINT8                               **PktBuf,
    124      OUT UINT32                              *PktLen
    125   )
    126 {
    127   EFI_SIMPLE_NETWORK_MODE *SnpMode;
    128   UINT8                   *DstPos;
    129   UINT16                  Index;
    130   MNP_DEVICE_DATA         *MnpDeviceData;
    131   UINT8                   *TxBuf;
    132 
    133   MnpDeviceData = MnpServiceData->MnpDeviceData;
    134 
    135   TxBuf = MnpAllocTxBuf (MnpDeviceData);
    136   if (TxBuf == NULL) {
    137     return EFI_OUT_OF_RESOURCES;
    138   }
    139 
    140   //
    141   // Reserve space for vlan tag if needed.
    142   //
    143   if (MnpServiceData->VlanId != 0) {
    144     *PktBuf = TxBuf + NET_VLAN_TAG_LEN;
    145   } else {
    146     *PktBuf = TxBuf;
    147   }
    148 
    149   if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {
    150     CopyMem (
    151         *PktBuf,
    152         TxData->FragmentTable[0].FragmentBuffer,
    153         TxData->FragmentTable[0].FragmentLength
    154         );
    155 
    156     *PktLen = TxData->FragmentTable[0].FragmentLength;
    157   } else {
    158     //
    159     // Either media header isn't in FragmentTable or there is more than
    160     // one fragment, copy the data into the packet buffer. Reserve the
    161     // media header space if necessary.
    162     //
    163     SnpMode = MnpDeviceData->Snp->Mode;
    164     DstPos  = *PktBuf;
    165     *PktLen = 0;
    166     if (TxData->DestinationAddress != NULL) {
    167       //
    168       // If dest address is not NULL, move DstPos to reserve space for the
    169       // media header. Add the media header length to buflen.
    170       //
    171       DstPos += SnpMode->MediaHeaderSize;
    172       *PktLen += SnpMode->MediaHeaderSize;
    173     }
    174 
    175     for (Index = 0; Index < TxData->FragmentCount; Index++) {
    176       //
    177       // Copy the data.
    178       //
    179       CopyMem (
    180         DstPos,
    181         TxData->FragmentTable[Index].FragmentBuffer,
    182         TxData->FragmentTable[Index].FragmentLength
    183         );
    184       DstPos += TxData->FragmentTable[Index].FragmentLength;
    185     }
    186 
    187     //
    188     // Set the buffer length.
    189     //
    190     *PktLen += TxData->DataLength + TxData->HeaderLength;
    191   }
    192 
    193   return EFI_SUCCESS;
    194 }
    195 
    196 
    197 /**
    198   Synchronously send out the packet.
    199 
    200   This functon places the packet buffer to SNP driver's tansmit queue. The packet
    201   can be considered successfully sent out once SNP acccetp the packet, while the
    202   packet buffer recycle is deferred for better performance.
    203 
    204   @param[in]       MnpServiceData      Pointer to the mnp service context data.
    205   @param[in]       Packet              Pointer to the pakcet buffer.
    206   @param[in]       Length              The length of the packet.
    207   @param[in, out]  Token               Pointer to the token the packet generated from.
    208 
    209   @retval EFI_SUCCESS                  The packet is sent out.
    210   @retval EFI_TIMEOUT                  Time out occurs, the packet isn't sent.
    211   @retval EFI_DEVICE_ERROR             An unexpected network error occurs.
    212 
    213 **/
    214 EFI_STATUS
    215 MnpSyncSendPacket (
    216   IN     MNP_SERVICE_DATA                        *MnpServiceData,
    217   IN     UINT8                                   *Packet,
    218   IN     UINT32                                  Length,
    219   IN OUT EFI_MANAGED_NETWORK_COMPLETION_TOKEN    *Token
    220   )
    221 {
    222   EFI_STATUS                        Status;
    223   EFI_SIMPLE_NETWORK_PROTOCOL       *Snp;
    224   EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
    225   UINT32                            HeaderSize;
    226   MNP_DEVICE_DATA                   *MnpDeviceData;
    227   UINT16                            ProtocolType;
    228 
    229   MnpDeviceData = MnpServiceData->MnpDeviceData;
    230   Snp           = MnpDeviceData->Snp;
    231   TxData        = Token->Packet.TxData;
    232   Token->Status = EFI_SUCCESS;
    233   HeaderSize    = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;
    234 
    235   //
    236   // Check media status before transmit packet.
    237   // Note: media status will be updated by periodic timer MediaDetectTimer.
    238   //
    239   if (Snp->Mode->MediaPresentSupported && !Snp->Mode->MediaPresent) {
    240     //
    241     // Media not present, skip packet transmit and report EFI_NO_MEDIA
    242     //
    243     DEBUG ((EFI_D_WARN, "MnpSyncSendPacket: No network cable detected.\n"));
    244     Token->Status = EFI_NO_MEDIA;
    245     goto SIGNAL_TOKEN;
    246   }
    247 
    248 
    249   if (MnpServiceData->VlanId != 0) {
    250     //
    251     // Insert VLAN tag
    252     //
    253     MnpInsertVlanTag (MnpServiceData, TxData, &ProtocolType, &Packet, &Length);
    254   } else {
    255     ProtocolType = TxData->ProtocolType;
    256   }
    257 
    258   //
    259   // Transmit the packet through SNP.
    260   //
    261   Status = Snp->Transmit (
    262                   Snp,
    263                   HeaderSize,
    264                   Length,
    265                   Packet,
    266                   TxData->SourceAddress,
    267                   TxData->DestinationAddress,
    268                   &ProtocolType
    269                   );
    270   if (Status == EFI_NOT_READY) {
    271     Status = MnpRecycleTxBuf (MnpDeviceData);
    272     if (EFI_ERROR (Status)) {
    273       Token->Status = EFI_DEVICE_ERROR;
    274       goto SIGNAL_TOKEN;
    275     }
    276 
    277     Status = Snp->Transmit (
    278                     Snp,
    279                     HeaderSize,
    280                     Length,
    281                     Packet,
    282                     TxData->SourceAddress,
    283                     TxData->DestinationAddress,
    284                     &ProtocolType
    285                     );
    286   }
    287 
    288   if (EFI_ERROR (Status)) {
    289     Token->Status = EFI_DEVICE_ERROR;
    290   }
    291 
    292 SIGNAL_TOKEN:
    293 
    294   gBS->SignalEvent (Token->Event);
    295 
    296   //
    297   // Dispatch the DPC queued by the NotifyFunction of Token->Event.
    298   //
    299   DispatchDpc ();
    300 
    301   return EFI_SUCCESS;
    302 }
    303 
    304 
    305 /**
    306   Try to deliver the received packet to the instance.
    307 
    308   @param[in, out]  Instance     Pointer to the mnp instance context data.
    309 
    310   @retval EFI_SUCCESS           The received packet is delivered, or there is no
    311                                 packet to deliver, or there is no available receive
    312                                 token.
    313   @retval EFI_OUT_OF_RESOURCES  The deliver fails due to lack of memory resource.
    314 
    315 **/
    316 EFI_STATUS
    317 MnpInstanceDeliverPacket (
    318   IN OUT MNP_INSTANCE_DATA   *Instance
    319   )
    320 {
    321   MNP_DEVICE_DATA                       *MnpDeviceData;
    322   MNP_RXDATA_WRAP                       *RxDataWrap;
    323   NET_BUF                               *DupNbuf;
    324   EFI_MANAGED_NETWORK_RECEIVE_DATA      *RxData;
    325   EFI_SIMPLE_NETWORK_MODE               *SnpMode;
    326   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *RxToken;
    327 
    328   MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
    329   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
    330 
    331   if (NetMapIsEmpty (&Instance->RxTokenMap) || IsListEmpty (&Instance->RcvdPacketQueue)) {
    332     //
    333     // No pending received data or no available receive token, return.
    334     //
    335     return EFI_SUCCESS;
    336   }
    337 
    338   ASSERT (Instance->RcvdPacketQueueSize != 0);
    339 
    340   RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
    341   if (RxDataWrap->Nbuf->RefCnt > 2) {
    342     //
    343     // There are other instances share this Nbuf, duplicate to get a
    344     // copy to allow the instance to do R/W operations.
    345     //
    346     DupNbuf = MnpAllocNbuf (MnpDeviceData);
    347     if (DupNbuf == NULL) {
    348       DEBUG ((EFI_D_WARN, "MnpDeliverPacket: Failed to allocate a free Nbuf.\n"));
    349 
    350       return EFI_OUT_OF_RESOURCES;
    351     }
    352 
    353     //
    354     // Duplicate the net buffer.
    355     //
    356     NetbufDuplicate (RxDataWrap->Nbuf, DupNbuf, 0);
    357     MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);
    358     RxDataWrap->Nbuf = DupNbuf;
    359   }
    360 
    361   //
    362   // All resources are OK, remove the packet from the queue.
    363   //
    364   NetListRemoveHead (&Instance->RcvdPacketQueue);
    365   Instance->RcvdPacketQueueSize--;
    366 
    367   RxData  = &RxDataWrap->RxData;
    368   SnpMode = MnpDeviceData->Snp->Mode;
    369 
    370   //
    371   // Set all the buffer pointers.
    372   //
    373   RxData->MediaHeader         = NetbufGetByte (RxDataWrap->Nbuf, 0, NULL);
    374   RxData->DestinationAddress  = RxData->MediaHeader;
    375   RxData->SourceAddress       = (UINT8 *) RxData->MediaHeader + SnpMode->HwAddressSize;
    376   RxData->PacketData          = (UINT8 *) RxData->MediaHeader + SnpMode->MediaHeaderSize;
    377 
    378   //
    379   // Insert this RxDataWrap into the delivered queue.
    380   //
    381   InsertTailList (&Instance->RxDeliveredPacketQueue, &RxDataWrap->WrapEntry);
    382 
    383   //
    384   // Get the receive token from the RxTokenMap.
    385   //
    386   RxToken = NetMapRemoveHead (&Instance->RxTokenMap, NULL);
    387 
    388   //
    389   // Signal this token's event.
    390   //
    391   RxToken->Packet.RxData  = &RxDataWrap->RxData;
    392   RxToken->Status         = EFI_SUCCESS;
    393   gBS->SignalEvent (RxToken->Event);
    394 
    395   return EFI_SUCCESS;
    396 }
    397 
    398 
    399 /**
    400   Deliver the received packet for the instances belonging to the MnpServiceData.
    401 
    402   @param[in]  MnpServiceData        Pointer to the mnp service context data.
    403 
    404 **/
    405 VOID
    406 MnpDeliverPacket (
    407   IN MNP_SERVICE_DATA    *MnpServiceData
    408   )
    409 {
    410   LIST_ENTRY        *Entry;
    411   MNP_INSTANCE_DATA *Instance;
    412 
    413   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
    414 
    415   NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
    416     Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
    417     NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
    418 
    419     //
    420     // Try to deliver packet for this instance.
    421     //
    422     MnpInstanceDeliverPacket (Instance);
    423   }
    424 }
    425 
    426 
    427 /**
    428   Recycle the RxData and other resources used to hold and deliver the received
    429   packet.
    430 
    431   @param[in]  Event               The event this notify function registered to.
    432   @param[in]  Context             Pointer to the context data registerd to the Event.
    433 
    434 **/
    435 VOID
    436 EFIAPI
    437 MnpRecycleRxData (
    438   IN EFI_EVENT     Event,
    439   IN VOID          *Context
    440   )
    441 {
    442   MNP_RXDATA_WRAP *RxDataWrap;
    443   MNP_DEVICE_DATA *MnpDeviceData;
    444 
    445   ASSERT (Context != NULL);
    446 
    447   RxDataWrap = (MNP_RXDATA_WRAP *) Context;
    448   NET_CHECK_SIGNATURE (RxDataWrap->Instance, MNP_INSTANCE_DATA_SIGNATURE);
    449 
    450   ASSERT (RxDataWrap->Nbuf != NULL);
    451 
    452   MnpDeviceData = RxDataWrap->Instance->MnpServiceData->MnpDeviceData;
    453   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
    454 
    455   //
    456   // Free this Nbuf.
    457   //
    458   MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);
    459   RxDataWrap->Nbuf = NULL;
    460 
    461   //
    462   // Close the recycle event.
    463   //
    464   gBS->CloseEvent (RxDataWrap->RxData.RecycleEvent);
    465 
    466   //
    467   // Remove this Wrap entry from the list.
    468   //
    469   RemoveEntryList (&RxDataWrap->WrapEntry);
    470 
    471   FreePool (RxDataWrap);
    472 }
    473 
    474 
    475 /**
    476   Queue the received packet into instance's receive queue.
    477 
    478   @param[in, out]  Instance        Pointer to the mnp instance context data.
    479   @param[in, out]  RxDataWrap      Pointer to the Wrap structure containing the
    480                                    received data and other information.
    481 **/
    482 VOID
    483 MnpQueueRcvdPacket (
    484   IN OUT MNP_INSTANCE_DATA   *Instance,
    485   IN OUT MNP_RXDATA_WRAP     *RxDataWrap
    486   )
    487 {
    488   MNP_RXDATA_WRAP *OldRxDataWrap;
    489 
    490   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
    491 
    492   //
    493   // Check the queue size. If it exceeds the limit, drop one packet
    494   // from the head.
    495   //
    496   if (Instance->RcvdPacketQueueSize == MNP_MAX_RCVD_PACKET_QUE_SIZE) {
    497 
    498     DEBUG ((EFI_D_WARN, "MnpQueueRcvdPacket: Drop one packet bcz queue size limit reached.\n"));
    499 
    500     //
    501     // Get the oldest packet.
    502     //
    503     OldRxDataWrap = NET_LIST_HEAD (
    504                       &Instance->RcvdPacketQueue,
    505                       MNP_RXDATA_WRAP,
    506                       WrapEntry
    507                       );
    508 
    509     //
    510     // Recycle this OldRxDataWrap, this entry will be removed by the callee.
    511     //
    512     MnpRecycleRxData (NULL, (VOID *) OldRxDataWrap);
    513     Instance->RcvdPacketQueueSize--;
    514   }
    515 
    516   //
    517   // Update the timeout tick using the configured parameter.
    518   //
    519   RxDataWrap->TimeoutTick = Instance->ConfigData.ReceivedQueueTimeoutValue;
    520 
    521   //
    522   // Insert this Wrap into the instance queue.
    523   //
    524   InsertTailList (&Instance->RcvdPacketQueue, &RxDataWrap->WrapEntry);
    525   Instance->RcvdPacketQueueSize++;
    526 }
    527 
    528 
    529 /**
    530   Match the received packet with the instance receive filters.
    531 
    532   @param[in]  Instance          Pointer to the mnp instance context data.
    533   @param[in]  RxData            Pointer to the EFI_MANAGED_NETWORK_RECEIVE_DATA.
    534   @param[in]  GroupAddress      Pointer to the GroupAddress, the GroupAddress is
    535                                 non-NULL and it contains the destination multicast
    536                                 mac address of the received packet if the packet
    537                                 destinated to a multicast mac address.
    538   @param[in]  PktAttr           The received packets attribute.
    539 
    540   @return The received packet matches the instance's receive filters or not.
    541 
    542 **/
    543 BOOLEAN
    544 MnpMatchPacket (
    545   IN MNP_INSTANCE_DATA                   *Instance,
    546   IN EFI_MANAGED_NETWORK_RECEIVE_DATA    *RxData,
    547   IN MNP_GROUP_ADDRESS                   *GroupAddress OPTIONAL,
    548   IN UINT8                               PktAttr
    549   )
    550 {
    551   EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData;
    552   LIST_ENTRY                      *Entry;
    553   MNP_GROUP_CONTROL_BLOCK         *GroupCtrlBlk;
    554 
    555   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
    556 
    557   ConfigData = &Instance->ConfigData;
    558 
    559   //
    560   // Check the protocol type.
    561   //
    562   if ((ConfigData->ProtocolTypeFilter != 0) && (ConfigData->ProtocolTypeFilter != RxData->ProtocolType)) {
    563     return FALSE;
    564   }
    565 
    566   if (ConfigData->EnablePromiscuousReceive) {
    567     //
    568     // Always match if this instance is configured to be promiscuous.
    569     //
    570     return TRUE;
    571   }
    572 
    573   //
    574   // The protocol type is matched, check receive filter, include unicast and broadcast.
    575   //
    576   if ((Instance->ReceiveFilter & PktAttr) != 0) {
    577     return TRUE;
    578   }
    579 
    580   //
    581   // Check multicast addresses.
    582   //
    583   if (ConfigData->EnableMulticastReceive && RxData->MulticastFlag) {
    584 
    585     ASSERT (GroupAddress != NULL);
    586 
    587     NET_LIST_FOR_EACH (Entry, &Instance->GroupCtrlBlkList) {
    588 
    589       GroupCtrlBlk = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_CONTROL_BLOCK, CtrlBlkEntry);
    590       if (GroupCtrlBlk->GroupAddress == GroupAddress) {
    591         //
    592         // The instance is configured to receiveing packets destinated to this
    593         // multicast address.
    594         //
    595         return TRUE;
    596       }
    597     }
    598   }
    599 
    600   //
    601   // No match.
    602   //
    603   return FALSE;
    604 }
    605 
    606 
    607 /**
    608   Analyse the received packets.
    609 
    610   @param[in]       MnpServiceData    Pointer to the mnp service context data.
    611   @param[in]       Nbuf              Pointer to the net buffer holding the received
    612                                      packet.
    613   @param[in, out]  RxData            Pointer to the buffer used to save the analysed
    614                                      result in EFI_MANAGED_NETWORK_RECEIVE_DATA.
    615   @param[out]      GroupAddress      Pointer to pointer to a MNP_GROUP_ADDRESS used to
    616                                      pass out the address of the multicast address the
    617                                      received packet destinated to.
    618   @param[out]      PktAttr           Pointer to the buffer used to save the analysed
    619                                      packet attribute.
    620 
    621 **/
    622 VOID
    623 MnpAnalysePacket (
    624   IN     MNP_SERVICE_DATA                    *MnpServiceData,
    625   IN     NET_BUF                             *Nbuf,
    626   IN OUT EFI_MANAGED_NETWORK_RECEIVE_DATA    *RxData,
    627      OUT MNP_GROUP_ADDRESS                   **GroupAddress,
    628      OUT UINT8                               *PktAttr
    629   )
    630 {
    631   EFI_SIMPLE_NETWORK_MODE *SnpMode;
    632   MNP_DEVICE_DATA         *MnpDeviceData;
    633   UINT8                   *BufPtr;
    634   LIST_ENTRY              *Entry;
    635 
    636   MnpDeviceData = MnpServiceData->MnpDeviceData;
    637   SnpMode       = MnpDeviceData->Snp->Mode;
    638 
    639   //
    640   // Get the packet buffer.
    641   //
    642   BufPtr = NetbufGetByte (Nbuf, 0, NULL);
    643   ASSERT (BufPtr != NULL);
    644 
    645   //
    646   // Set the initial values.
    647   //
    648   RxData->BroadcastFlag   = FALSE;
    649   RxData->MulticastFlag   = FALSE;
    650   RxData->PromiscuousFlag = FALSE;
    651   *PktAttr                = UNICAST_PACKET;
    652 
    653   if (!NET_MAC_EQUAL (&SnpMode->CurrentAddress, BufPtr, SnpMode->HwAddressSize)) {
    654     //
    655     // This packet isn't destinated to our current mac address, it't not unicast.
    656     //
    657     *PktAttr = 0;
    658 
    659     if (NET_MAC_EQUAL (&SnpMode->BroadcastAddress, BufPtr, SnpMode->HwAddressSize)) {
    660       //
    661       // It's broadcast.
    662       //
    663       RxData->BroadcastFlag = TRUE;
    664       *PktAttr              = BROADCAST_PACKET;
    665     } else if ((*BufPtr & 0x01) == 0x1) {
    666       //
    667       // It's multicast, try to match the multicast filters.
    668       //
    669       NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
    670 
    671         *GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
    672         if (NET_MAC_EQUAL (BufPtr, &((*GroupAddress)->Address), SnpMode->HwAddressSize)) {
    673           RxData->MulticastFlag = TRUE;
    674           break;
    675         }
    676       }
    677 
    678       if (!RxData->MulticastFlag) {
    679         //
    680         // No match, set GroupAddress to NULL. This multicast packet must
    681         // be the result of PROMISUCOUS or PROMISUCOUS_MULTICAST flag is on.
    682         //
    683         *GroupAddress           = NULL;
    684         RxData->PromiscuousFlag = TRUE;
    685 
    686         if (MnpDeviceData->PromiscuousCount == 0) {
    687           //
    688           // Skip the below code, there is no receiver of this packet.
    689           //
    690           return ;
    691         }
    692       }
    693     } else {
    694       RxData->PromiscuousFlag = TRUE;
    695     }
    696   }
    697 
    698   ZeroMem (&RxData->Timestamp, sizeof (EFI_TIME));
    699 
    700   //
    701   // Fill the common parts of RxData.
    702   //
    703   RxData->PacketLength  = Nbuf->TotalSize;
    704   RxData->HeaderLength  = SnpMode->MediaHeaderSize;
    705   RxData->AddressLength = SnpMode->HwAddressSize;
    706   RxData->DataLength    = RxData->PacketLength - RxData->HeaderLength;
    707   RxData->ProtocolType  = NTOHS (*(UINT16 *) (BufPtr + 2 * SnpMode->HwAddressSize));
    708 }
    709 
    710 
    711 /**
    712   Wrap the RxData.
    713 
    714   @param[in]  Instance           Pointer to the mnp instance context data.
    715   @param[in]  RxData             Pointer to the receive data to wrap.
    716 
    717   @return Pointer to a MNP_RXDATA_WRAP which wraps the RxData.
    718 
    719 **/
    720 MNP_RXDATA_WRAP *
    721 MnpWrapRxData (
    722   IN MNP_INSTANCE_DATA                   *Instance,
    723   IN EFI_MANAGED_NETWORK_RECEIVE_DATA    *RxData
    724   )
    725 {
    726   EFI_STATUS      Status;
    727   MNP_RXDATA_WRAP *RxDataWrap;
    728 
    729   //
    730   // Allocate memory.
    731   //
    732   RxDataWrap = AllocatePool (sizeof (MNP_RXDATA_WRAP));
    733   if (RxDataWrap == NULL) {
    734     DEBUG ((EFI_D_ERROR, "MnpDispatchPacket: Failed to allocate a MNP_RXDATA_WRAP.\n"));
    735     return NULL;
    736   }
    737 
    738   RxDataWrap->Instance = Instance;
    739 
    740   //
    741   // Fill the RxData in RxDataWrap,
    742   //
    743   CopyMem (&RxDataWrap->RxData, RxData, sizeof (RxDataWrap->RxData));
    744 
    745   //
    746   // Create the recycle event.
    747   //
    748   Status = gBS->CreateEvent (
    749                   EVT_NOTIFY_SIGNAL,
    750                   TPL_NOTIFY,
    751                   MnpRecycleRxData,
    752                   RxDataWrap,
    753                   &RxDataWrap->RxData.RecycleEvent
    754                   );
    755   if (EFI_ERROR (Status)) {
    756     DEBUG ((EFI_D_ERROR, "MnpDispatchPacket: gBS->CreateEvent failed, %r.\n", Status));
    757 
    758     FreePool (RxDataWrap);
    759     return NULL;
    760   }
    761 
    762   return RxDataWrap;
    763 }
    764 
    765 
    766 /**
    767   Enqueue the received the packets to the instances belonging to the
    768   MnpServiceData.
    769 
    770   @param[in]  MnpServiceData    Pointer to the mnp service context data.
    771   @param[in]  Nbuf              Pointer to the net buffer representing the received
    772                                 packet.
    773 
    774 **/
    775 VOID
    776 MnpEnqueuePacket (
    777   IN MNP_SERVICE_DATA    *MnpServiceData,
    778   IN NET_BUF             *Nbuf
    779   )
    780 {
    781   LIST_ENTRY                        *Entry;
    782   MNP_INSTANCE_DATA                 *Instance;
    783   EFI_MANAGED_NETWORK_RECEIVE_DATA  RxData;
    784   UINT8                             PktAttr;
    785   MNP_GROUP_ADDRESS                 *GroupAddress;
    786   MNP_RXDATA_WRAP                   *RxDataWrap;
    787 
    788 
    789   GroupAddress = NULL;
    790   //
    791   // First, analyse the packet header.
    792   //
    793   MnpAnalysePacket (MnpServiceData, Nbuf, &RxData, &GroupAddress, &PktAttr);
    794 
    795   if (RxData.PromiscuousFlag && (MnpServiceData->MnpDeviceData->PromiscuousCount == 0)) {
    796     //
    797     // No receivers, no more action need.
    798     //
    799     return ;
    800   }
    801 
    802   //
    803   // Iterate the children to find match.
    804   //
    805   NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
    806 
    807     Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
    808     NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
    809 
    810     if (!Instance->Configured) {
    811       continue;
    812     }
    813 
    814     //
    815     // Check the packet against the instance receive filters.
    816     //
    817     if (MnpMatchPacket (Instance, &RxData, GroupAddress, PktAttr)) {
    818       //
    819       // Wrap the RxData.
    820       //
    821       RxDataWrap = MnpWrapRxData (Instance, &RxData);
    822       if (RxDataWrap == NULL) {
    823         continue;
    824       }
    825 
    826       //
    827       // Associate RxDataWrap with Nbuf and increase the RefCnt.
    828       //
    829       RxDataWrap->Nbuf = Nbuf;
    830       NET_GET_REF (RxDataWrap->Nbuf);
    831 
    832       //
    833       // Queue the packet into the instance queue.
    834       //
    835       MnpQueueRcvdPacket (Instance, RxDataWrap);
    836     }
    837   }
    838 }
    839 
    840 
    841 /**
    842   Try to receive a packet and deliver it.
    843 
    844   @param[in, out]  MnpDeviceData        Pointer to the mnp device context data.
    845 
    846   @retval EFI_SUCCESS           add return value to function comment
    847   @retval EFI_NOT_STARTED       The simple network protocol is not started.
    848   @retval EFI_NOT_READY         No packet received.
    849   @retval EFI_DEVICE_ERROR      An unexpected error occurs.
    850 
    851 **/
    852 EFI_STATUS
    853 MnpReceivePacket (
    854   IN OUT MNP_DEVICE_DATA   *MnpDeviceData
    855   )
    856 {
    857   EFI_STATUS                  Status;
    858   EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
    859   NET_BUF                     *Nbuf;
    860   UINT8                       *BufPtr;
    861   UINTN                       BufLen;
    862   UINTN                       HeaderSize;
    863   UINT32                      Trimmed;
    864   MNP_SERVICE_DATA            *MnpServiceData;
    865   UINT16                      VlanId;
    866   BOOLEAN                     IsVlanPacket;
    867 
    868   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
    869 
    870   Snp = MnpDeviceData->Snp;
    871   if (Snp->Mode->State != EfiSimpleNetworkInitialized) {
    872     //
    873     // The simple network protocol is not started.
    874     //
    875     return EFI_NOT_STARTED;
    876   }
    877 
    878   if (MnpDeviceData->RxNbufCache == NULL) {
    879     //
    880     // Try to get a new buffer as there may be buffers recycled.
    881     //
    882     MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);
    883 
    884     if (MnpDeviceData->RxNbufCache == NULL) {
    885       //
    886       // No available buffer in the buffer pool.
    887       //
    888       return EFI_DEVICE_ERROR;
    889     }
    890 
    891     NetbufAllocSpace (
    892       MnpDeviceData->RxNbufCache,
    893       MnpDeviceData->BufferLength,
    894       NET_BUF_TAIL
    895       );
    896   }
    897 
    898   Nbuf    = MnpDeviceData->RxNbufCache;
    899   BufLen  = Nbuf->TotalSize;
    900   BufPtr  = NetbufGetByte (Nbuf, 0, NULL);
    901   ASSERT (BufPtr != NULL);
    902 
    903   //
    904   // Receive packet through Snp.
    905   //
    906   Status = Snp->Receive (Snp, &HeaderSize, &BufLen, BufPtr, NULL, NULL, NULL);
    907   if (EFI_ERROR (Status)) {
    908     DEBUG_CODE (
    909       if (Status != EFI_NOT_READY) {
    910         DEBUG ((EFI_D_WARN, "MnpReceivePacket: Snp->Receive() = %r.\n", Status));
    911       }
    912     );
    913 
    914     return Status;
    915   }
    916 
    917   //
    918   // Sanity check.
    919   //
    920   if ((HeaderSize != Snp->Mode->MediaHeaderSize) || (BufLen < HeaderSize)) {
    921     DEBUG (
    922       (EFI_D_WARN,
    923       "MnpReceivePacket: Size error, HL:TL = %d:%d.\n",
    924       HeaderSize,
    925       BufLen)
    926       );
    927     return EFI_DEVICE_ERROR;
    928   }
    929 
    930   Trimmed = 0;
    931   if (Nbuf->TotalSize != BufLen) {
    932     //
    933     // Trim the packet from tail.
    934     //
    935     Trimmed = NetbufTrim (Nbuf, Nbuf->TotalSize - (UINT32) BufLen, NET_BUF_TAIL);
    936     ASSERT (Nbuf->TotalSize == BufLen);
    937   }
    938 
    939   VlanId = 0;
    940   if (MnpDeviceData->NumberOfVlan != 0) {
    941     //
    942     // VLAN is configured, remove the VLAN tag if any
    943     //
    944     IsVlanPacket = MnpRemoveVlanTag (MnpDeviceData, Nbuf, &VlanId);
    945   } else {
    946     IsVlanPacket = FALSE;
    947   }
    948 
    949   MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);
    950   if (MnpServiceData == NULL) {
    951     //
    952     // VLAN is not set for this tagged frame, ignore this packet
    953     //
    954     if (Trimmed > 0) {
    955       NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);
    956     }
    957 
    958     if (IsVlanPacket) {
    959       NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);
    960     }
    961 
    962     goto EXIT;
    963   }
    964 
    965   //
    966   // Enqueue the packet to the matched instances.
    967   //
    968   MnpEnqueuePacket (MnpServiceData, Nbuf);
    969 
    970   if (Nbuf->RefCnt > 2) {
    971     //
    972     // RefCnt > 2 indicates there is at least one receiver of this packet.
    973     // Free the current RxNbufCache and allocate a new one.
    974     //
    975     MnpFreeNbuf (MnpDeviceData, Nbuf);
    976 
    977     Nbuf                       = MnpAllocNbuf (MnpDeviceData);
    978     MnpDeviceData->RxNbufCache = Nbuf;
    979     if (Nbuf == NULL) {
    980       DEBUG ((EFI_D_ERROR, "MnpReceivePacket: Alloc packet for receiving cache failed.\n"));
    981       return EFI_DEVICE_ERROR;
    982     }
    983 
    984     NetbufAllocSpace (Nbuf, MnpDeviceData->BufferLength, NET_BUF_TAIL);
    985   } else {
    986     //
    987     // No receiver for this packet.
    988     //
    989     if (Trimmed > 0) {
    990       NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);
    991     }
    992     if (IsVlanPacket) {
    993       NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);
    994     }
    995 
    996     goto EXIT;
    997   }
    998   //
    999   // Deliver the queued packets.
   1000   //
   1001   MnpDeliverPacket (MnpServiceData);
   1002 
   1003 EXIT:
   1004 
   1005   ASSERT (Nbuf->TotalSize == MnpDeviceData->BufferLength);
   1006 
   1007   return Status;
   1008 }
   1009 
   1010 
   1011 /**
   1012   Remove the received packets if timeout occurs.
   1013 
   1014   @param[in]  Event        The event this notify function registered to.
   1015   @param[in]  Context      Pointer to the context data registered to the event.
   1016 
   1017 **/
   1018 VOID
   1019 EFIAPI
   1020 MnpCheckPacketTimeout (
   1021   IN EFI_EVENT     Event,
   1022   IN VOID          *Context
   1023   )
   1024 {
   1025   MNP_DEVICE_DATA   *MnpDeviceData;
   1026   MNP_SERVICE_DATA  *MnpServiceData;
   1027   LIST_ENTRY        *Entry;
   1028   LIST_ENTRY        *ServiceEntry;
   1029   LIST_ENTRY        *RxEntry;
   1030   LIST_ENTRY        *NextEntry;
   1031   MNP_INSTANCE_DATA *Instance;
   1032   MNP_RXDATA_WRAP   *RxDataWrap;
   1033   EFI_TPL           OldTpl;
   1034 
   1035   MnpDeviceData = (MNP_DEVICE_DATA *) Context;
   1036   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
   1037 
   1038   NET_LIST_FOR_EACH (ServiceEntry, &MnpDeviceData->ServiceList) {
   1039     MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (ServiceEntry);
   1040 
   1041     NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
   1042 
   1043       Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
   1044       NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
   1045 
   1046       if (!Instance->Configured || (Instance->ConfigData.ReceivedQueueTimeoutValue == 0)) {
   1047         //
   1048         // This instance is not configured or there is no receive time out,
   1049         // just skip to the next instance.
   1050         //
   1051         continue;
   1052       }
   1053 
   1054       OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
   1055 
   1056       NET_LIST_FOR_EACH_SAFE (RxEntry, NextEntry, &Instance->RcvdPacketQueue) {
   1057 
   1058         RxDataWrap = NET_LIST_USER_STRUCT (RxEntry, MNP_RXDATA_WRAP, WrapEntry);
   1059 
   1060         //
   1061         // TimeoutTick unit is microsecond, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.
   1062         //
   1063         if (RxDataWrap->TimeoutTick >= (MNP_TIMEOUT_CHECK_INTERVAL / 10)) {
   1064           RxDataWrap->TimeoutTick -= (MNP_TIMEOUT_CHECK_INTERVAL / 10);
   1065         } else {
   1066           //
   1067           // Drop the timeout packet.
   1068           //
   1069           DEBUG ((EFI_D_WARN, "MnpCheckPacketTimeout: Received packet timeout.\n"));
   1070           MnpRecycleRxData (NULL, RxDataWrap);
   1071           Instance->RcvdPacketQueueSize--;
   1072         }
   1073       }
   1074 
   1075       gBS->RestoreTPL (OldTpl);
   1076     }
   1077   }
   1078 }
   1079 
   1080 /**
   1081   Poll to update MediaPresent field in SNP ModeData by Snp->GetStatus().
   1082 
   1083   @param[in]  Event        The event this notify function registered to.
   1084   @param[in]  Context      Pointer to the context data registered to the event.
   1085 
   1086 **/
   1087 VOID
   1088 EFIAPI
   1089 MnpCheckMediaStatus (
   1090   IN EFI_EVENT     Event,
   1091   IN VOID          *Context
   1092   )
   1093 {
   1094   MNP_DEVICE_DATA             *MnpDeviceData;
   1095   EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
   1096   UINT32                      InterruptStatus;
   1097 
   1098   MnpDeviceData = (MNP_DEVICE_DATA *) Context;
   1099   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
   1100 
   1101   Snp = MnpDeviceData->Snp;
   1102   if (Snp->Mode->MediaPresentSupported) {
   1103     //
   1104     // Upon successful return of GetStatus(), the MediaPresent field of
   1105     // EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change of media status
   1106     //
   1107     Snp->GetStatus (Snp, &InterruptStatus, NULL);
   1108   }
   1109 }
   1110 
   1111 /**
   1112   Poll to receive the packets from Snp. This function is either called by upperlayer
   1113   protocols/applications or the system poll timer notify mechanism.
   1114 
   1115   @param[in]  Event        The event this notify function registered to.
   1116   @param[in]  Context      Pointer to the context data registered to the event.
   1117 
   1118 **/
   1119 VOID
   1120 EFIAPI
   1121 MnpSystemPoll (
   1122   IN EFI_EVENT     Event,
   1123   IN VOID          *Context
   1124   )
   1125 {
   1126   MNP_DEVICE_DATA  *MnpDeviceData;
   1127 
   1128   MnpDeviceData = (MNP_DEVICE_DATA *) Context;
   1129   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
   1130 
   1131   //
   1132   // Try to receive packets from Snp.
   1133   //
   1134   MnpReceivePacket (MnpDeviceData);
   1135 
   1136   //
   1137   // Dispatch the DPC queued by the NotifyFunction of rx token's events.
   1138   //
   1139   DispatchDpc ();
   1140 }
   1141