2 Implementation of Managed Network Protocol I/O functions.
4 Copyright (c) 2005 - 2018, 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
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.
20 Validates the Mnp transmit token.
22 @param[in] Instance Pointer to the Mnp instance context data.
23 @param[in] Token Pointer to the transmit token to check.
25 @return The Token is valid or not.
30 IN MNP_INSTANCE_DATA
*Instance
,
31 IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
34 MNP_SERVICE_DATA
*MnpServiceData
;
35 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
38 EFI_MANAGED_NETWORK_FRAGMENT_DATA
*FragmentTable
;
40 MnpServiceData
= Instance
->MnpServiceData
;
41 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
43 TxData
= Token
->Packet
.TxData
;
45 if ((Token
->Event
== NULL
) || (TxData
== NULL
) || (TxData
->FragmentCount
== 0)) {
47 // The token is invalid if the Event is NULL, or the TxData is NULL, or
48 // the fragment count is zero.
50 DEBUG ((EFI_D_WARN
, "MnpIsValidTxToken: Invalid Token.\n"));
54 if ((TxData
->DestinationAddress
!= NULL
) && (TxData
->HeaderLength
!= 0)) {
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).
59 DEBUG ((EFI_D_WARN
, "MnpIsValidTxToken: DestinationAddress isn't NULL, HeaderLength must be 0.\n"));
64 FragmentTable
= TxData
->FragmentTable
;
65 for (Index
= 0; Index
< TxData
->FragmentCount
; Index
++) {
67 if ((FragmentTable
[Index
].FragmentLength
== 0) || (FragmentTable
[Index
].FragmentBuffer
== NULL
)) {
69 // The token is invalid if any FragmentLength is zero or any FragmentBuffer is NULL.
71 DEBUG ((EFI_D_WARN
, "MnpIsValidTxToken: Invalid FragmentLength or FragmentBuffer.\n"));
75 TotalLength
+= FragmentTable
[Index
].FragmentLength
;
78 if ((TxData
->DestinationAddress
== NULL
) && (FragmentTable
[0].FragmentLength
< TxData
->HeaderLength
)) {
80 // Media header is split between fragments.
85 if (TotalLength
!= (TxData
->DataLength
+ TxData
->HeaderLength
)) {
87 // The length calculated from the fragment information doesn't equal to the
88 // sum of the DataLength and the HeaderLength.
90 DEBUG ((EFI_D_WARN
, "MnpIsValidTxData: Invalid Datalength compared with the sum of fragment length.\n"));
94 if (TxData
->DataLength
> MnpServiceData
->Mtu
) {
96 // The total length is larger than the MTU.
98 DEBUG ((EFI_D_WARN
, "MnpIsValidTxData: TxData->DataLength exceeds Mtu.\n"));
106 Build the packet to transmit from the TxData passed in.
108 @param[in] MnpServiceData Pointer to the mnp service context data.
109 @param[in] TxData Pointer to the transmit data containing the information
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
115 @retval EFI_SUCCESS TxPackage is built.
116 @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.
121 IN MNP_SERVICE_DATA
*MnpServiceData
,
122 IN EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
,
127 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
130 MNP_DEVICE_DATA
*MnpDeviceData
;
133 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
135 TxBuf
= MnpAllocTxBuf (MnpDeviceData
);
137 return EFI_OUT_OF_RESOURCES
;
141 // Reserve space for vlan tag if needed.
143 if (MnpServiceData
->VlanId
!= 0) {
144 *PktBuf
= TxBuf
+ NET_VLAN_TAG_LEN
;
149 if ((TxData
->DestinationAddress
== NULL
) && (TxData
->FragmentCount
== 1)) {
152 TxData
->FragmentTable
[0].FragmentBuffer
,
153 TxData
->FragmentTable
[0].FragmentLength
156 *PktLen
= TxData
->FragmentTable
[0].FragmentLength
;
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.
163 SnpMode
= MnpDeviceData
->Snp
->Mode
;
166 if (TxData
->DestinationAddress
!= NULL
) {
168 // If dest address is not NULL, move DstPos to reserve space for the
169 // media header. Add the media header length to buflen.
171 DstPos
+= SnpMode
->MediaHeaderSize
;
172 *PktLen
+= SnpMode
->MediaHeaderSize
;
175 for (Index
= 0; Index
< TxData
->FragmentCount
; Index
++) {
181 TxData
->FragmentTable
[Index
].FragmentBuffer
,
182 TxData
->FragmentTable
[Index
].FragmentLength
184 DstPos
+= TxData
->FragmentTable
[Index
].FragmentLength
;
188 // Set the buffer length.
190 *PktLen
+= TxData
->DataLength
+ TxData
->HeaderLength
;
198 Synchronously send out the packet.
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.
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.
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.
216 IN MNP_SERVICE_DATA
*MnpServiceData
,
219 IN OUT EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
223 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
224 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*TxData
;
226 MNP_DEVICE_DATA
*MnpDeviceData
;
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
;
236 // Check media status before transmit packet.
237 // Note: media status will be updated by periodic timer MediaDetectTimer.
239 if (Snp
->Mode
->MediaPresentSupported
&& !Snp
->Mode
->MediaPresent
) {
241 // Media not present, skip packet transmit and report EFI_NO_MEDIA
243 DEBUG ((EFI_D_WARN
, "MnpSyncSendPacket: No network cable detected.\n"));
244 Token
->Status
= EFI_NO_MEDIA
;
249 if (MnpServiceData
->VlanId
!= 0) {
253 MnpInsertVlanTag (MnpServiceData
, TxData
, &ProtocolType
, &Packet
, &Length
);
255 ProtocolType
= TxData
->ProtocolType
;
259 // Transmit the packet through SNP.
261 Status
= Snp
->Transmit (
266 TxData
->SourceAddress
,
267 TxData
->DestinationAddress
,
270 if (Status
== EFI_NOT_READY
) {
271 Status
= MnpRecycleTxBuf (MnpDeviceData
);
272 if (EFI_ERROR (Status
)) {
273 Token
->Status
= EFI_DEVICE_ERROR
;
277 Status
= Snp
->Transmit (
282 TxData
->SourceAddress
,
283 TxData
->DestinationAddress
,
288 if (EFI_ERROR (Status
)) {
289 Token
->Status
= EFI_DEVICE_ERROR
;
294 gBS
->SignalEvent (Token
->Event
);
297 // Dispatch the DPC queued by the NotifyFunction of Token->Event.
306 Try to deliver the received packet to the instance.
308 @param[in, out] Instance Pointer to the mnp instance context data.
310 @retval EFI_SUCCESS The received packet is delivered, or there is no
311 packet to deliver, or there is no available receive
313 @retval EFI_OUT_OF_RESOURCES The deliver fails due to lack of memory resource.
317 MnpInstanceDeliverPacket (
318 IN OUT MNP_INSTANCE_DATA
*Instance
321 MNP_DEVICE_DATA
*MnpDeviceData
;
322 MNP_RXDATA_WRAP
*RxDataWrap
;
324 EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
;
325 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
326 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*RxToken
;
328 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
329 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
331 if (NetMapIsEmpty (&Instance
->RxTokenMap
) || IsListEmpty (&Instance
->RcvdPacketQueue
)) {
333 // No pending received data or no available receive token, return.
338 ASSERT (Instance
->RcvdPacketQueueSize
!= 0);
340 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
341 if (RxDataWrap
->Nbuf
->RefCnt
> 2) {
343 // There are other instances share this Nbuf, duplicate to get a
344 // copy to allow the instance to do R/W operations.
346 DupNbuf
= MnpAllocNbuf (MnpDeviceData
);
347 if (DupNbuf
== NULL
) {
348 DEBUG ((EFI_D_WARN
, "MnpDeliverPacket: Failed to allocate a free Nbuf.\n"));
350 return EFI_OUT_OF_RESOURCES
;
354 // Duplicate the net buffer.
356 NetbufDuplicate (RxDataWrap
->Nbuf
, DupNbuf
, 0);
357 MnpFreeNbuf (MnpDeviceData
, RxDataWrap
->Nbuf
);
358 RxDataWrap
->Nbuf
= DupNbuf
;
362 // All resources are OK, remove the packet from the queue.
364 NetListRemoveHead (&Instance
->RcvdPacketQueue
);
365 Instance
->RcvdPacketQueueSize
--;
367 RxData
= &RxDataWrap
->RxData
;
368 SnpMode
= MnpDeviceData
->Snp
->Mode
;
371 // Set all the buffer pointers.
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
;
379 // Insert this RxDataWrap into the delivered queue.
381 InsertTailList (&Instance
->RxDeliveredPacketQueue
, &RxDataWrap
->WrapEntry
);
384 // Get the receive token from the RxTokenMap.
386 RxToken
= NetMapRemoveHead (&Instance
->RxTokenMap
, NULL
);
389 // Signal this token's event.
391 RxToken
->Packet
.RxData
= &RxDataWrap
->RxData
;
392 RxToken
->Status
= EFI_SUCCESS
;
393 gBS
->SignalEvent (RxToken
->Event
);
400 Deliver the received packet for the instances belonging to the MnpServiceData.
402 @param[in] MnpServiceData Pointer to the mnp service context data.
407 IN MNP_SERVICE_DATA
*MnpServiceData
411 MNP_INSTANCE_DATA
*Instance
;
413 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
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
);
420 // Try to deliver packet for this instance.
422 MnpInstanceDeliverPacket (Instance
);
428 Recycle the RxData and other resources used to hold and deliver the received
431 @param[in] Event The event this notify function registered to.
432 @param[in] Context Pointer to the context data registerd to the Event.
442 MNP_RXDATA_WRAP
*RxDataWrap
;
443 MNP_DEVICE_DATA
*MnpDeviceData
;
445 ASSERT (Context
!= NULL
);
447 RxDataWrap
= (MNP_RXDATA_WRAP
*) Context
;
448 NET_CHECK_SIGNATURE (RxDataWrap
->Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
450 ASSERT (RxDataWrap
->Nbuf
!= NULL
);
452 MnpDeviceData
= RxDataWrap
->Instance
->MnpServiceData
->MnpDeviceData
;
453 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
458 MnpFreeNbuf (MnpDeviceData
, RxDataWrap
->Nbuf
);
459 RxDataWrap
->Nbuf
= NULL
;
462 // Close the recycle event.
464 gBS
->CloseEvent (RxDataWrap
->RxData
.RecycleEvent
);
467 // Remove this Wrap entry from the list.
469 RemoveEntryList (&RxDataWrap
->WrapEntry
);
471 FreePool (RxDataWrap
);
476 Queue the received packet into instance's receive queue.
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.
484 IN OUT MNP_INSTANCE_DATA
*Instance
,
485 IN OUT MNP_RXDATA_WRAP
*RxDataWrap
488 MNP_RXDATA_WRAP
*OldRxDataWrap
;
490 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
493 // Check the queue size. If it exceeds the limit, drop one packet
496 if (Instance
->RcvdPacketQueueSize
== MNP_MAX_RCVD_PACKET_QUE_SIZE
) {
498 DEBUG ((EFI_D_WARN
, "MnpQueueRcvdPacket: Drop one packet bcz queue size limit reached.\n"));
501 // Get the oldest packet.
503 OldRxDataWrap
= NET_LIST_HEAD (
504 &Instance
->RcvdPacketQueue
,
510 // Recycle this OldRxDataWrap, this entry will be removed by the callee.
512 MnpRecycleRxData (NULL
, (VOID
*) OldRxDataWrap
);
513 Instance
->RcvdPacketQueueSize
--;
517 // Update the timeout tick using the configured parameter.
519 RxDataWrap
->TimeoutTick
= Instance
->ConfigData
.ReceivedQueueTimeoutValue
;
522 // Insert this Wrap into the instance queue.
524 InsertTailList (&Instance
->RcvdPacketQueue
, &RxDataWrap
->WrapEntry
);
525 Instance
->RcvdPacketQueueSize
++;
530 Match the received packet with the instance receive filters.
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.
540 @return The received packet matches the instance's receive filters or not.
545 IN MNP_INSTANCE_DATA
*Instance
,
546 IN EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
,
547 IN MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
551 EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData
;
553 MNP_GROUP_CONTROL_BLOCK
*GroupCtrlBlk
;
555 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
557 ConfigData
= &Instance
->ConfigData
;
560 // Check the protocol type.
562 if ((ConfigData
->ProtocolTypeFilter
!= 0) && (ConfigData
->ProtocolTypeFilter
!= RxData
->ProtocolType
)) {
566 if (ConfigData
->EnablePromiscuousReceive
) {
568 // Always match if this instance is configured to be promiscuous.
574 // The protocol type is matched, check receive filter, include unicast and broadcast.
576 if ((Instance
->ReceiveFilter
& PktAttr
) != 0) {
581 // Check multicast addresses.
583 if (ConfigData
->EnableMulticastReceive
&& RxData
->MulticastFlag
) {
585 ASSERT (GroupAddress
!= NULL
);
587 NET_LIST_FOR_EACH (Entry
, &Instance
->GroupCtrlBlkList
) {
589 GroupCtrlBlk
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_CONTROL_BLOCK
, CtrlBlkEntry
);
590 if (GroupCtrlBlk
->GroupAddress
== GroupAddress
) {
592 // The instance is configured to receiveing packets destinated to this
593 // multicast address.
608 Analyse the received packets.
610 @param[in] MnpServiceData Pointer to the mnp service context data.
611 @param[in] Nbuf Pointer to the net buffer holding the received
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
624 IN MNP_SERVICE_DATA
*MnpServiceData
,
626 IN OUT EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
,
627 OUT MNP_GROUP_ADDRESS
**GroupAddress
,
631 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
632 MNP_DEVICE_DATA
*MnpDeviceData
;
636 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
637 SnpMode
= MnpDeviceData
->Snp
->Mode
;
640 // Get the packet buffer.
642 BufPtr
= NetbufGetByte (Nbuf
, 0, NULL
);
643 ASSERT (BufPtr
!= NULL
);
646 // Set the initial values.
648 RxData
->BroadcastFlag
= FALSE
;
649 RxData
->MulticastFlag
= FALSE
;
650 RxData
->PromiscuousFlag
= FALSE
;
651 *PktAttr
= UNICAST_PACKET
;
653 if (!NET_MAC_EQUAL (&SnpMode
->CurrentAddress
, BufPtr
, SnpMode
->HwAddressSize
)) {
655 // This packet isn't destinated to our current mac address, it't not unicast.
659 if (NET_MAC_EQUAL (&SnpMode
->BroadcastAddress
, BufPtr
, SnpMode
->HwAddressSize
)) {
663 RxData
->BroadcastFlag
= TRUE
;
664 *PktAttr
= BROADCAST_PACKET
;
665 } else if ((*BufPtr
& 0x01) == 0x1) {
667 // It's multicast, try to match the multicast filters.
669 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->GroupAddressList
) {
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
;
678 if (!RxData
->MulticastFlag
) {
680 // No match, set GroupAddress to NULL. This multicast packet must
681 // be the result of PROMISUCOUS or PROMISUCOUS_MULTICAST flag is on.
683 *GroupAddress
= NULL
;
684 RxData
->PromiscuousFlag
= TRUE
;
686 if (MnpDeviceData
->PromiscuousCount
== 0) {
688 // Skip the below code, there is no receiver of this packet.
694 RxData
->PromiscuousFlag
= TRUE
;
698 ZeroMem (&RxData
->Timestamp
, sizeof (EFI_TIME
));
701 // Fill the common parts of RxData.
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
));
714 @param[in] Instance Pointer to the mnp instance context data.
715 @param[in] RxData Pointer to the receive data to wrap.
717 @return Pointer to a MNP_RXDATA_WRAP which wraps the RxData.
722 IN MNP_INSTANCE_DATA
*Instance
,
723 IN EFI_MANAGED_NETWORK_RECEIVE_DATA
*RxData
727 MNP_RXDATA_WRAP
*RxDataWrap
;
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"));
738 RxDataWrap
->Instance
= Instance
;
741 // Fill the RxData in RxDataWrap,
743 CopyMem (&RxDataWrap
->RxData
, RxData
, sizeof (RxDataWrap
->RxData
));
746 // Create the recycle event.
748 Status
= gBS
->CreateEvent (
753 &RxDataWrap
->RxData
.RecycleEvent
755 if (EFI_ERROR (Status
)) {
756 DEBUG ((EFI_D_ERROR
, "MnpDispatchPacket: gBS->CreateEvent failed, %r.\n", Status
));
758 FreePool (RxDataWrap
);
767 Enqueue the received the packets to the instances belonging to the
770 @param[in] MnpServiceData Pointer to the mnp service context data.
771 @param[in] Nbuf Pointer to the net buffer representing the received
777 IN MNP_SERVICE_DATA
*MnpServiceData
,
782 MNP_INSTANCE_DATA
*Instance
;
783 EFI_MANAGED_NETWORK_RECEIVE_DATA RxData
;
785 MNP_GROUP_ADDRESS
*GroupAddress
;
786 MNP_RXDATA_WRAP
*RxDataWrap
;
791 // First, analyse the packet header.
793 MnpAnalysePacket (MnpServiceData
, Nbuf
, &RxData
, &GroupAddress
, &PktAttr
);
795 if (RxData
.PromiscuousFlag
&& (MnpServiceData
->MnpDeviceData
->PromiscuousCount
== 0)) {
797 // No receivers, no more action need.
803 // Iterate the children to find match.
805 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->ChildrenList
) {
807 Instance
= NET_LIST_USER_STRUCT (Entry
, MNP_INSTANCE_DATA
, InstEntry
);
808 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
810 if (!Instance
->Configured
) {
815 // Check the packet against the instance receive filters.
817 if (MnpMatchPacket (Instance
, &RxData
, GroupAddress
, PktAttr
)) {
821 RxDataWrap
= MnpWrapRxData (Instance
, &RxData
);
822 if (RxDataWrap
== NULL
) {
827 // Associate RxDataWrap with Nbuf and increase the RefCnt.
829 RxDataWrap
->Nbuf
= Nbuf
;
830 NET_GET_REF (RxDataWrap
->Nbuf
);
833 // Queue the packet into the instance queue.
835 MnpQueueRcvdPacket (Instance
, RxDataWrap
);
842 Try to receive a packet and deliver it.
844 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
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.
854 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
858 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
864 MNP_SERVICE_DATA
*MnpServiceData
;
866 BOOLEAN IsVlanPacket
;
868 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
870 Snp
= MnpDeviceData
->Snp
;
871 if (Snp
->Mode
->State
!= EfiSimpleNetworkInitialized
) {
873 // The simple network protocol is not started.
875 return EFI_NOT_STARTED
;
878 if (MnpDeviceData
->RxNbufCache
== NULL
) {
880 // Try to get a new buffer as there may be buffers recycled.
882 MnpDeviceData
->RxNbufCache
= MnpAllocNbuf (MnpDeviceData
);
884 if (MnpDeviceData
->RxNbufCache
== NULL
) {
886 // No available buffer in the buffer pool.
888 return EFI_DEVICE_ERROR
;
892 MnpDeviceData
->RxNbufCache
,
893 MnpDeviceData
->BufferLength
,
898 Nbuf
= MnpDeviceData
->RxNbufCache
;
899 BufLen
= Nbuf
->TotalSize
;
900 BufPtr
= NetbufGetByte (Nbuf
, 0, NULL
);
901 ASSERT (BufPtr
!= NULL
);
904 // Receive packet through Snp.
906 Status
= Snp
->Receive (Snp
, &HeaderSize
, &BufLen
, BufPtr
, NULL
, NULL
, NULL
);
907 if (EFI_ERROR (Status
)) {
909 if (Status
!= EFI_NOT_READY
) {
910 DEBUG ((EFI_D_WARN
, "MnpReceivePacket: Snp->Receive() = %r.\n", Status
));
920 if ((HeaderSize
!= Snp
->Mode
->MediaHeaderSize
) || (BufLen
< HeaderSize
)) {
923 "MnpReceivePacket: Size error, HL:TL = %d:%d.\n",
927 return EFI_DEVICE_ERROR
;
931 if (Nbuf
->TotalSize
!= BufLen
) {
933 // Trim the packet from tail.
935 Trimmed
= NetbufTrim (Nbuf
, Nbuf
->TotalSize
- (UINT32
) BufLen
, NET_BUF_TAIL
);
936 ASSERT (Nbuf
->TotalSize
== BufLen
);
940 if (MnpDeviceData
->NumberOfVlan
!= 0) {
942 // VLAN is configured, remove the VLAN tag if any
944 IsVlanPacket
= MnpRemoveVlanTag (MnpDeviceData
, Nbuf
, &VlanId
);
946 IsVlanPacket
= FALSE
;
949 MnpServiceData
= MnpFindServiceData (MnpDeviceData
, VlanId
);
950 if (MnpServiceData
== NULL
) {
952 // VLAN is not set for this tagged frame, ignore this packet
955 NetbufAllocSpace (Nbuf
, Trimmed
, NET_BUF_TAIL
);
959 NetbufAllocSpace (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_HEAD
);
966 // Enqueue the packet to the matched instances.
968 MnpEnqueuePacket (MnpServiceData
, Nbuf
);
970 if (Nbuf
->RefCnt
> 2) {
972 // RefCnt > 2 indicates there is at least one receiver of this packet.
973 // Free the current RxNbufCache and allocate a new one.
975 MnpFreeNbuf (MnpDeviceData
, Nbuf
);
977 Nbuf
= MnpAllocNbuf (MnpDeviceData
);
978 MnpDeviceData
->RxNbufCache
= Nbuf
;
980 DEBUG ((EFI_D_ERROR
, "MnpReceivePacket: Alloc packet for receiving cache failed.\n"));
981 return EFI_DEVICE_ERROR
;
984 NetbufAllocSpace (Nbuf
, MnpDeviceData
->BufferLength
, NET_BUF_TAIL
);
987 // No receiver for this packet.
990 NetbufAllocSpace (Nbuf
, Trimmed
, NET_BUF_TAIL
);
993 NetbufAllocSpace (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_HEAD
);
999 // Deliver the queued packets.
1001 MnpDeliverPacket (MnpServiceData
);
1005 ASSERT (Nbuf
->TotalSize
== MnpDeviceData
->BufferLength
);
1012 Remove the received packets if timeout occurs.
1014 @param[in] Event The event this notify function registered to.
1015 @param[in] Context Pointer to the context data registered to the event.
1020 MnpCheckPacketTimeout (
1025 MNP_DEVICE_DATA
*MnpDeviceData
;
1026 MNP_SERVICE_DATA
*MnpServiceData
;
1028 LIST_ENTRY
*ServiceEntry
;
1029 LIST_ENTRY
*RxEntry
;
1030 LIST_ENTRY
*NextEntry
;
1031 MNP_INSTANCE_DATA
*Instance
;
1032 MNP_RXDATA_WRAP
*RxDataWrap
;
1035 MnpDeviceData
= (MNP_DEVICE_DATA
*) Context
;
1036 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1038 NET_LIST_FOR_EACH (ServiceEntry
, &MnpDeviceData
->ServiceList
) {
1039 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (ServiceEntry
);
1041 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->ChildrenList
) {
1043 Instance
= NET_LIST_USER_STRUCT (Entry
, MNP_INSTANCE_DATA
, InstEntry
);
1044 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1046 if (!Instance
->Configured
|| (Instance
->ConfigData
.ReceivedQueueTimeoutValue
== 0)) {
1048 // This instance is not configured or there is no receive time out,
1049 // just skip to the next instance.
1054 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1056 NET_LIST_FOR_EACH_SAFE (RxEntry
, NextEntry
, &Instance
->RcvdPacketQueue
) {
1058 RxDataWrap
= NET_LIST_USER_STRUCT (RxEntry
, MNP_RXDATA_WRAP
, WrapEntry
);
1061 // TimeoutTick unit is microsecond, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.
1063 if (RxDataWrap
->TimeoutTick
>= (MNP_TIMEOUT_CHECK_INTERVAL
/ 10)) {
1064 RxDataWrap
->TimeoutTick
-= (MNP_TIMEOUT_CHECK_INTERVAL
/ 10);
1067 // Drop the timeout packet.
1069 DEBUG ((EFI_D_WARN
, "MnpCheckPacketTimeout: Received packet timeout.\n"));
1070 MnpRecycleRxData (NULL
, RxDataWrap
);
1071 Instance
->RcvdPacketQueueSize
--;
1075 gBS
->RestoreTPL (OldTpl
);
1081 Poll to update MediaPresent field in SNP ModeData by Snp->GetStatus().
1083 @param[in] Event The event this notify function registered to.
1084 @param[in] Context Pointer to the context data registered to the event.
1089 MnpCheckMediaStatus (
1094 MNP_DEVICE_DATA
*MnpDeviceData
;
1095 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1096 UINT32 InterruptStatus
;
1098 MnpDeviceData
= (MNP_DEVICE_DATA
*) Context
;
1099 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1101 Snp
= MnpDeviceData
->Snp
;
1102 if (Snp
->Mode
->MediaPresentSupported
) {
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
1107 Snp
->GetStatus (Snp
, &InterruptStatus
, NULL
);
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.
1115 @param[in] Event The event this notify function registered to.
1116 @param[in] Context Pointer to the context data registered to the event.
1126 MNP_DEVICE_DATA
*MnpDeviceData
;
1128 MnpDeviceData
= (MNP_DEVICE_DATA
*) Context
;
1129 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1132 // Try to receive packets from Snp.
1134 MnpReceivePacket (MnpDeviceData
);
1137 // Dispatch the DPC queued by the NotifyFunction of rx token's events.