TianoCore EDK2 master
Loading...
Searching...
No Matches
MnpIo.c
Go to the documentation of this file.
1
9#include "MnpImpl.h"
10#include "MnpVlan.h"
11
21BOOLEAN
23 IN MNP_INSTANCE_DATA *Instance,
25 )
26{
27 MNP_SERVICE_DATA *MnpServiceData;
29 UINT32 Index;
30 UINT32 TotalLength;
32
33 MnpServiceData = Instance->MnpServiceData;
34 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
35
36 TxData = Token->Packet.TxData;
37
38 if ((Token->Event == NULL) || (TxData == NULL) || (TxData->FragmentCount == 0)) {
39 //
40 // The token is invalid if the Event is NULL, or the TxData is NULL, or
41 // the fragment count is zero.
42 //
43 DEBUG ((DEBUG_WARN, "MnpIsValidTxToken: Invalid Token.\n"));
44 return FALSE;
45 }
46
47 if ((TxData->DestinationAddress != NULL) && (TxData->HeaderLength != 0)) {
48 //
49 // The token is invalid if the HeaderLength isn't zero while the DestinationAddress
50 // is NULL (The destination address is already put into the packet).
51 //
52 DEBUG ((DEBUG_WARN, "MnpIsValidTxToken: DestinationAddress isn't NULL, HeaderLength must be 0.\n"));
53 return FALSE;
54 }
55
56 TotalLength = 0;
57 FragmentTable = TxData->FragmentTable;
58 for (Index = 0; Index < TxData->FragmentCount; Index++) {
59 if ((FragmentTable[Index].FragmentLength == 0) || (FragmentTable[Index].FragmentBuffer == NULL)) {
60 //
61 // The token is invalid if any FragmentLength is zero or any FragmentBuffer is NULL.
62 //
63 DEBUG ((DEBUG_WARN, "MnpIsValidTxToken: Invalid FragmentLength or FragmentBuffer.\n"));
64 return FALSE;
65 }
66
67 TotalLength += FragmentTable[Index].FragmentLength;
68 }
69
70 if ((TxData->DestinationAddress == NULL) && (FragmentTable[0].FragmentLength < TxData->HeaderLength)) {
71 //
72 // Media header is split between fragments.
73 //
74 return FALSE;
75 }
76
77 if (TotalLength != (TxData->DataLength + TxData->HeaderLength)) {
78 //
79 // The length calculated from the fragment information doesn't equal to the
80 // sum of the DataLength and the HeaderLength.
81 //
82 DEBUG ((DEBUG_WARN, "MnpIsValidTxData: Invalid Datalength compared with the sum of fragment length.\n"));
83 return FALSE;
84 }
85
86 if (TxData->DataLength > MnpServiceData->Mtu) {
87 //
88 // The total length is larger than the MTU.
89 //
90 DEBUG ((DEBUG_WARN, "MnpIsValidTxData: TxData->DataLength exceeds Mtu.\n"));
91 return FALSE;
92 }
93
94 return TRUE;
95}
96
113 IN MNP_SERVICE_DATA *MnpServiceData,
115 OUT UINT8 **PktBuf,
116 OUT UINT32 *PktLen
117 )
118{
120 UINT8 *DstPos;
121 UINT16 Index;
122 MNP_DEVICE_DATA *MnpDeviceData;
123 UINT8 *TxBuf;
124
125 MnpDeviceData = MnpServiceData->MnpDeviceData;
126
127 TxBuf = MnpAllocTxBuf (MnpDeviceData);
128 if (TxBuf == NULL) {
129 return EFI_OUT_OF_RESOURCES;
130 }
131
132 //
133 // Reserve space for vlan tag if needed.
134 //
135 if (MnpServiceData->VlanId != 0) {
136 *PktBuf = TxBuf + NET_VLAN_TAG_LEN;
137 } else {
138 *PktBuf = TxBuf;
139 }
140
141 if ((TxData->DestinationAddress == NULL) && (TxData->FragmentCount == 1)) {
142 CopyMem (
143 *PktBuf,
144 TxData->FragmentTable[0].FragmentBuffer,
145 TxData->FragmentTable[0].FragmentLength
146 );
147
148 *PktLen = TxData->FragmentTable[0].FragmentLength;
149 } else {
150 //
151 // Either media header isn't in FragmentTable or there is more than
152 // one fragment, copy the data into the packet buffer. Reserve the
153 // media header space if necessary.
154 //
155 SnpMode = MnpDeviceData->Snp->Mode;
156 DstPos = *PktBuf;
157 *PktLen = 0;
158 if (TxData->DestinationAddress != NULL) {
159 //
160 // If dest address is not NULL, move DstPos to reserve space for the
161 // media header. Add the media header length to buflen.
162 //
163 DstPos += SnpMode->MediaHeaderSize;
164 *PktLen += SnpMode->MediaHeaderSize;
165 }
166
167 for (Index = 0; Index < TxData->FragmentCount; Index++) {
168 //
169 // Copy the data.
170 //
171 CopyMem (
172 DstPos,
173 TxData->FragmentTable[Index].FragmentBuffer,
174 TxData->FragmentTable[Index].FragmentLength
175 );
176 DstPos += TxData->FragmentTable[Index].FragmentLength;
177 }
178
179 //
180 // Set the buffer length.
181 //
182 *PktLen += TxData->DataLength + TxData->HeaderLength;
183 }
184
185 return EFI_SUCCESS;
186}
187
207 IN MNP_SERVICE_DATA *MnpServiceData,
208 IN UINT8 *Packet,
209 IN UINT32 Length,
211 )
212{
213 EFI_STATUS Status;
216 UINT32 HeaderSize;
217 MNP_DEVICE_DATA *MnpDeviceData;
218 UINT16 ProtocolType;
219
220 MnpDeviceData = MnpServiceData->MnpDeviceData;
221 Snp = MnpDeviceData->Snp;
222 TxData = Token->Packet.TxData;
223 Token->Status = EFI_SUCCESS;
224 HeaderSize = Snp->Mode->MediaHeaderSize - TxData->HeaderLength;
225
226 //
227 // Check media status before transmit packet.
228 // Note: media status will be updated by periodic timer MediaDetectTimer.
229 //
230 if (Snp->Mode->MediaPresentSupported && !Snp->Mode->MediaPresent) {
231 //
232 // Media not present, skip packet transmit and report EFI_NO_MEDIA
233 //
234 DEBUG ((DEBUG_WARN, "MnpSyncSendPacket: No network cable detected.\n"));
235 Token->Status = EFI_NO_MEDIA;
236 goto SIGNAL_TOKEN;
237 }
238
239 if (MnpServiceData->VlanId != 0) {
240 //
241 // Insert VLAN tag
242 //
243 MnpInsertVlanTag (MnpServiceData, TxData, &ProtocolType, &Packet, &Length);
244 } else {
245 ProtocolType = TxData->ProtocolType;
246 }
247
248 //
249 // Transmit the packet through SNP.
250 //
251 Status = Snp->Transmit (
252 Snp,
253 HeaderSize,
254 Length,
255 Packet,
256 TxData->SourceAddress,
257 TxData->DestinationAddress,
258 &ProtocolType
259 );
260 if (Status == EFI_NOT_READY) {
261 Status = MnpRecycleTxBuf (MnpDeviceData);
262 if (EFI_ERROR (Status)) {
263 Token->Status = EFI_DEVICE_ERROR;
264 goto SIGNAL_TOKEN;
265 }
266
267 Status = Snp->Transmit (
268 Snp,
269 HeaderSize,
270 Length,
271 Packet,
272 TxData->SourceAddress,
273 TxData->DestinationAddress,
274 &ProtocolType
275 );
276 }
277
278 if (EFI_ERROR (Status)) {
279 Token->Status = EFI_DEVICE_ERROR;
280 }
281
283
284 gBS->SignalEvent (Token->Event);
285
286 //
287 // Dispatch the DPC queued by the NotifyFunction of Token->Event.
288 //
289 DispatchDpc ();
290
291 return EFI_SUCCESS;
292}
293
307 IN OUT MNP_INSTANCE_DATA *Instance
308 )
309{
310 MNP_DEVICE_DATA *MnpDeviceData;
311 MNP_RXDATA_WRAP *RxDataWrap;
312 NET_BUF *DupNbuf;
316
317 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
318 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
319
320 if (NetMapIsEmpty (&Instance->RxTokenMap) || IsListEmpty (&Instance->RcvdPacketQueue)) {
321 //
322 // No pending received data or no available receive token, return.
323 //
324 return EFI_SUCCESS;
325 }
326
327 ASSERT (Instance->RcvdPacketQueueSize != 0);
328
329 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
330 if (RxDataWrap->Nbuf->RefCnt > 2) {
331 //
332 // There are other instances share this Nbuf, duplicate to get a
333 // copy to allow the instance to do R/W operations.
334 //
335 DupNbuf = MnpAllocNbuf (MnpDeviceData);
336 if (DupNbuf == NULL) {
337 DEBUG ((DEBUG_WARN, "MnpDeliverPacket: Failed to allocate a free Nbuf.\n"));
338
339 return EFI_OUT_OF_RESOURCES;
340 }
341
342 //
343 // Duplicate the net buffer.
344 //
345 NetbufDuplicate (RxDataWrap->Nbuf, DupNbuf, 0);
346 MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);
347 RxDataWrap->Nbuf = DupNbuf;
348 }
349
350 //
351 // All resources are OK, remove the packet from the queue.
352 //
353 NetListRemoveHead (&Instance->RcvdPacketQueue);
354 Instance->RcvdPacketQueueSize--;
355
356 RxData = &RxDataWrap->RxData;
357 SnpMode = MnpDeviceData->Snp->Mode;
358
359 //
360 // Set all the buffer pointers.
361 //
362 RxData->MediaHeader = NetbufGetByte (RxDataWrap->Nbuf, 0, NULL);
363 RxData->DestinationAddress = RxData->MediaHeader;
364 RxData->SourceAddress = (UINT8 *)RxData->MediaHeader + SnpMode->HwAddressSize;
365 RxData->PacketData = (UINT8 *)RxData->MediaHeader + SnpMode->MediaHeaderSize;
366
367 //
368 // Insert this RxDataWrap into the delivered queue.
369 //
370 InsertTailList (&Instance->RxDeliveredPacketQueue, &RxDataWrap->WrapEntry);
371
372 //
373 // Get the receive token from the RxTokenMap.
374 //
375 RxToken = NetMapRemoveHead (&Instance->RxTokenMap, NULL);
376
377 //
378 // Signal this token's event.
379 //
380 RxToken->Packet.RxData = &RxDataWrap->RxData;
381 RxToken->Status = EFI_SUCCESS;
382 gBS->SignalEvent (RxToken->Event);
383
384 return EFI_SUCCESS;
385}
386
393VOID
395 IN MNP_SERVICE_DATA *MnpServiceData
396 )
397{
398 LIST_ENTRY *Entry;
399 MNP_INSTANCE_DATA *Instance;
400
401 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
402
403 NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
404 Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
405 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
406
407 //
408 // Try to deliver packet for this instance.
409 //
410 MnpInstanceDeliverPacket (Instance);
411 }
412}
413
422VOID
423EFIAPI
425 IN EFI_EVENT Event,
426 IN VOID *Context
427 )
428{
429 MNP_RXDATA_WRAP *RxDataWrap;
430 MNP_DEVICE_DATA *MnpDeviceData;
431
432 ASSERT (Context != NULL);
433
434 RxDataWrap = (MNP_RXDATA_WRAP *)Context;
435 NET_CHECK_SIGNATURE (RxDataWrap->Instance, MNP_INSTANCE_DATA_SIGNATURE);
436
437 ASSERT (RxDataWrap->Nbuf != NULL);
438
439 MnpDeviceData = RxDataWrap->Instance->MnpServiceData->MnpDeviceData;
440 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
441
442 //
443 // Free this Nbuf.
444 //
445 MnpFreeNbuf (MnpDeviceData, RxDataWrap->Nbuf);
446 RxDataWrap->Nbuf = NULL;
447
448 //
449 // Close the recycle event.
450 //
451 gBS->CloseEvent (RxDataWrap->RxData.RecycleEvent);
452
453 //
454 // Remove this Wrap entry from the list.
455 //
456 RemoveEntryList (&RxDataWrap->WrapEntry);
457
458 FreePool (RxDataWrap);
459}
460
468VOID
470 IN OUT MNP_INSTANCE_DATA *Instance,
471 IN OUT MNP_RXDATA_WRAP *RxDataWrap
472 )
473{
474 MNP_RXDATA_WRAP *OldRxDataWrap;
475
476 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
477
478 //
479 // Check the queue size. If it exceeds the limit, drop one packet
480 // from the head.
481 //
482 if (Instance->RcvdPacketQueueSize == MNP_MAX_RCVD_PACKET_QUE_SIZE) {
483 DEBUG ((DEBUG_WARN, "MnpQueueRcvdPacket: Drop one packet bcz queue size limit reached.\n"));
484
485 //
486 // Get the oldest packet.
487 //
488 OldRxDataWrap = NET_LIST_HEAD (
489 &Instance->RcvdPacketQueue,
491 WrapEntry
492 );
493
494 //
495 // Recycle this OldRxDataWrap, this entry will be removed by the callee.
496 //
497 MnpRecycleRxData (NULL, (VOID *)OldRxDataWrap);
498 Instance->RcvdPacketQueueSize--;
499 }
500
501 //
502 // Update the timeout tick using the configured parameter.
503 //
504 RxDataWrap->TimeoutTick = Instance->ConfigData.ReceivedQueueTimeoutValue;
505
506 //
507 // Insert this Wrap into the instance queue.
508 //
509 InsertTailList (&Instance->RcvdPacketQueue, &RxDataWrap->WrapEntry);
510 Instance->RcvdPacketQueueSize++;
511}
512
527BOOLEAN
529 IN MNP_INSTANCE_DATA *Instance,
531 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
532 IN UINT8 PktAttr
533 )
534{
536 LIST_ENTRY *Entry;
537 MNP_GROUP_CONTROL_BLOCK *GroupCtrlBlk;
538
539 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
540
541 ConfigData = &Instance->ConfigData;
542
543 //
544 // Check the protocol type.
545 //
546 if ((ConfigData->ProtocolTypeFilter != 0) && (ConfigData->ProtocolTypeFilter != RxData->ProtocolType)) {
547 return FALSE;
548 }
549
550 if (ConfigData->EnablePromiscuousReceive) {
551 //
552 // Always match if this instance is configured to be promiscuous.
553 //
554 return TRUE;
555 }
556
557 //
558 // The protocol type is matched, check receive filter, include unicast and broadcast.
559 //
560 if ((Instance->ReceiveFilter & PktAttr) != 0) {
561 return TRUE;
562 }
563
564 //
565 // Check multicast addresses.
566 //
567 if (ConfigData->EnableMulticastReceive && RxData->MulticastFlag) {
568 ASSERT (GroupAddress != NULL);
569
570 NET_LIST_FOR_EACH (Entry, &Instance->GroupCtrlBlkList) {
571 GroupCtrlBlk = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_CONTROL_BLOCK, CtrlBlkEntry);
572 if (GroupCtrlBlk->GroupAddress == GroupAddress) {
573 //
574 // The instance is configured to receiveing packets destinated to this
575 // multicast address.
576 //
577 return TRUE;
578 }
579 }
580 }
581
582 //
583 // No match.
584 //
585 return FALSE;
586}
587
603VOID
605 IN MNP_SERVICE_DATA *MnpServiceData,
606 IN NET_BUF *Nbuf,
608 OUT MNP_GROUP_ADDRESS **GroupAddress,
609 OUT UINT8 *PktAttr
610 )
611{
613 MNP_DEVICE_DATA *MnpDeviceData;
614 UINT8 *BufPtr;
615 LIST_ENTRY *Entry;
616
617 MnpDeviceData = MnpServiceData->MnpDeviceData;
618 SnpMode = MnpDeviceData->Snp->Mode;
619
620 //
621 // Get the packet buffer.
622 //
623 BufPtr = NetbufGetByte (Nbuf, 0, NULL);
624 ASSERT (BufPtr != NULL);
625
626 //
627 // Set the initial values.
628 //
629 RxData->BroadcastFlag = FALSE;
630 RxData->MulticastFlag = FALSE;
631 RxData->PromiscuousFlag = FALSE;
632 *PktAttr = UNICAST_PACKET;
633
634 if (!NET_MAC_EQUAL (&SnpMode->CurrentAddress, BufPtr, SnpMode->HwAddressSize)) {
635 //
636 // This packet isn't destinated to our current mac address, it't not unicast.
637 //
638 *PktAttr = 0;
639
640 if (NET_MAC_EQUAL (&SnpMode->BroadcastAddress, BufPtr, SnpMode->HwAddressSize)) {
641 //
642 // It's broadcast.
643 //
644 RxData->BroadcastFlag = TRUE;
645 *PktAttr = BROADCAST_PACKET;
646 } else if ((*BufPtr & 0x01) == 0x1) {
647 //
648 // It's multicast, try to match the multicast filters.
649 //
650 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
651 *GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
652 if (NET_MAC_EQUAL (BufPtr, &((*GroupAddress)->Address), SnpMode->HwAddressSize)) {
653 RxData->MulticastFlag = TRUE;
654 break;
655 }
656 }
657
658 if (!RxData->MulticastFlag) {
659 //
660 // No match, set GroupAddress to NULL. This multicast packet must
661 // be the result of PROMISUCOUS or PROMISUCOUS_MULTICAST flag is on.
662 //
663 *GroupAddress = NULL;
664 RxData->PromiscuousFlag = TRUE;
665
666 if (MnpDeviceData->PromiscuousCount == 0) {
667 //
668 // Skip the below code, there is no receiver of this packet.
669 //
670 return;
671 }
672 }
673 } else {
674 RxData->PromiscuousFlag = TRUE;
675 }
676 }
677
678 ZeroMem (&RxData->Timestamp, sizeof (EFI_TIME));
679
680 //
681 // Fill the common parts of RxData.
682 //
683 RxData->PacketLength = Nbuf->TotalSize;
684 RxData->HeaderLength = SnpMode->MediaHeaderSize;
685 RxData->AddressLength = SnpMode->HwAddressSize;
686 RxData->DataLength = RxData->PacketLength - RxData->HeaderLength;
687 RxData->ProtocolType = NTOHS (*(UINT16 *)(BufPtr + 2 * SnpMode->HwAddressSize));
688}
689
701 IN MNP_INSTANCE_DATA *Instance,
703 )
704{
705 EFI_STATUS Status;
706 MNP_RXDATA_WRAP *RxDataWrap;
707
708 //
709 // Allocate memory.
710 //
711 RxDataWrap = AllocatePool (sizeof (MNP_RXDATA_WRAP));
712 if (RxDataWrap == NULL) {
713 DEBUG ((DEBUG_ERROR, "MnpDispatchPacket: Failed to allocate a MNP_RXDATA_WRAP.\n"));
714 return NULL;
715 }
716
717 RxDataWrap->Instance = Instance;
718
719 //
720 // Fill the RxData in RxDataWrap,
721 //
722 CopyMem (&RxDataWrap->RxData, RxData, sizeof (RxDataWrap->RxData));
723
724 //
725 // Create the recycle event.
726 //
727 Status = gBS->CreateEvent (
728 EVT_NOTIFY_SIGNAL,
729 TPL_NOTIFY,
731 RxDataWrap,
732 &RxDataWrap->RxData.RecycleEvent
733 );
734 if (EFI_ERROR (Status)) {
735 DEBUG ((DEBUG_ERROR, "MnpDispatchPacket: gBS->CreateEvent failed, %r.\n", Status));
736
737 FreePool (RxDataWrap);
738 return NULL;
739 }
740
741 return RxDataWrap;
742}
743
753VOID
755 IN MNP_SERVICE_DATA *MnpServiceData,
756 IN NET_BUF *Nbuf
757 )
758{
759 LIST_ENTRY *Entry;
760 MNP_INSTANCE_DATA *Instance;
762 UINT8 PktAttr;
763 MNP_GROUP_ADDRESS *GroupAddress;
764 MNP_RXDATA_WRAP *RxDataWrap;
765
766 GroupAddress = NULL;
767 //
768 // First, analyse the packet header.
769 //
770 MnpAnalysePacket (MnpServiceData, Nbuf, &RxData, &GroupAddress, &PktAttr);
771
772 if (RxData.PromiscuousFlag && (MnpServiceData->MnpDeviceData->PromiscuousCount == 0)) {
773 //
774 // No receivers, no more action need.
775 //
776 return;
777 }
778
779 //
780 // Iterate the children to find match.
781 //
782 NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
783 Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
784 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
785
786 if (!Instance->Configured) {
787 continue;
788 }
789
790 //
791 // Check the packet against the instance receive filters.
792 //
793 if (MnpMatchPacket (Instance, &RxData, GroupAddress, PktAttr)) {
794 //
795 // Wrap the RxData.
796 //
797 RxDataWrap = MnpWrapRxData (Instance, &RxData);
798 if (RxDataWrap == NULL) {
799 continue;
800 }
801
802 //
803 // Associate RxDataWrap with Nbuf and increase the RefCnt.
804 //
805 RxDataWrap->Nbuf = Nbuf;
806 NET_GET_REF (RxDataWrap->Nbuf);
807
808 //
809 // Queue the packet into the instance queue.
810 //
811 MnpQueueRcvdPacket (Instance, RxDataWrap);
812 }
813 }
814}
815
829 IN OUT MNP_DEVICE_DATA *MnpDeviceData
830 )
831{
832 EFI_STATUS Status;
834 NET_BUF *Nbuf;
835 UINT8 *BufPtr;
836 UINTN BufLen;
837 UINTN HeaderSize;
838 UINT32 Trimmed;
839 MNP_SERVICE_DATA *MnpServiceData;
840 UINT16 VlanId;
841 BOOLEAN IsVlanPacket;
842
843 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
844
845 Snp = MnpDeviceData->Snp;
846 if (Snp->Mode->State != EfiSimpleNetworkInitialized) {
847 //
848 // The simple network protocol is not started.
849 //
850 return EFI_NOT_STARTED;
851 }
852
853 if (MnpDeviceData->RxNbufCache == NULL) {
854 //
855 // Try to get a new buffer as there may be buffers recycled.
856 //
857 MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);
858
859 if (MnpDeviceData->RxNbufCache == NULL) {
860 //
861 // No available buffer in the buffer pool.
862 //
863 return EFI_DEVICE_ERROR;
864 }
865
867 MnpDeviceData->RxNbufCache,
868 MnpDeviceData->BufferLength,
869 NET_BUF_TAIL
870 );
871 }
872
873 Nbuf = MnpDeviceData->RxNbufCache;
874 BufLen = Nbuf->TotalSize;
875 BufPtr = NetbufGetByte (Nbuf, 0, NULL);
876 ASSERT (BufPtr != NULL);
877
878 //
879 // Receive packet through Snp.
880 //
881 Status = Snp->Receive (Snp, &HeaderSize, &BufLen, BufPtr, NULL, NULL, NULL);
882 if (EFI_ERROR (Status)) {
884 if (Status != EFI_NOT_READY) {
885 DEBUG ((DEBUG_WARN, "MnpReceivePacket: Snp->Receive() = %r.\n", Status));
886 }
887
889
890 return Status;
891 }
892
893 //
894 // Sanity check.
895 //
896 if ((HeaderSize != Snp->Mode->MediaHeaderSize) || (BufLen < HeaderSize)) {
897 DEBUG (
898 (DEBUG_WARN,
899 "MnpReceivePacket: Size error, HL:TL = %d:%d.\n",
900 HeaderSize,
901 BufLen)
902 );
903 return EFI_DEVICE_ERROR;
904 }
905
906 Trimmed = 0;
907 if (Nbuf->TotalSize != BufLen) {
908 //
909 // Trim the packet from tail.
910 //
911 Trimmed = NetbufTrim (Nbuf, Nbuf->TotalSize - (UINT32)BufLen, NET_BUF_TAIL);
912 ASSERT (Nbuf->TotalSize == BufLen);
913 }
914
915 VlanId = 0;
916 if (MnpDeviceData->NumberOfVlan != 0) {
917 //
918 // VLAN is configured, remove the VLAN tag if any
919 //
920 IsVlanPacket = MnpRemoveVlanTag (MnpDeviceData, Nbuf, &VlanId);
921 } else {
922 IsVlanPacket = FALSE;
923 }
924
925 MnpServiceData = MnpFindServiceData (MnpDeviceData, VlanId);
926 if (MnpServiceData == NULL) {
927 //
928 // VLAN is not set for this tagged frame, ignore this packet
929 //
930 if (Trimmed > 0) {
931 NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);
932 }
933
934 if (IsVlanPacket) {
935 NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);
936 }
937
938 goto EXIT;
939 }
940
941 //
942 // Enqueue the packet to the matched instances.
943 //
944 MnpEnqueuePacket (MnpServiceData, Nbuf);
945
946 if (Nbuf->RefCnt > 2) {
947 //
948 // RefCnt > 2 indicates there is at least one receiver of this packet.
949 // Free the current RxNbufCache and allocate a new one.
950 //
951 MnpFreeNbuf (MnpDeviceData, Nbuf);
952
953 Nbuf = MnpAllocNbuf (MnpDeviceData);
954 MnpDeviceData->RxNbufCache = Nbuf;
955 if (Nbuf == NULL) {
956 DEBUG ((DEBUG_ERROR, "MnpReceivePacket: Alloc packet for receiving cache failed.\n"));
957 return EFI_DEVICE_ERROR;
958 }
959
960 NetbufAllocSpace (Nbuf, MnpDeviceData->BufferLength, NET_BUF_TAIL);
961 } else {
962 //
963 // No receiver for this packet.
964 //
965 if (Trimmed > 0) {
966 NetbufAllocSpace (Nbuf, Trimmed, NET_BUF_TAIL);
967 }
968
969 if (IsVlanPacket) {
970 NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD);
971 }
972
973 goto EXIT;
974 }
975
976 //
977 // Deliver the queued packets.
978 //
979 MnpDeliverPacket (MnpServiceData);
980
981EXIT:
982
983 ASSERT (Nbuf->TotalSize == MnpDeviceData->BufferLength);
984
985 return Status;
986}
987
995VOID
996EFIAPI
998 IN EFI_EVENT Event,
999 IN VOID *Context
1000 )
1001{
1002 MNP_DEVICE_DATA *MnpDeviceData;
1003 MNP_SERVICE_DATA *MnpServiceData;
1004 LIST_ENTRY *Entry;
1005 LIST_ENTRY *ServiceEntry;
1006 LIST_ENTRY *RxEntry;
1007 LIST_ENTRY *NextEntry;
1008 MNP_INSTANCE_DATA *Instance;
1009 MNP_RXDATA_WRAP *RxDataWrap;
1010 EFI_TPL OldTpl;
1011
1012 MnpDeviceData = (MNP_DEVICE_DATA *)Context;
1013 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1014
1015 NET_LIST_FOR_EACH (ServiceEntry, &MnpDeviceData->ServiceList) {
1016 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (ServiceEntry);
1017
1018 NET_LIST_FOR_EACH (Entry, &MnpServiceData->ChildrenList) {
1019 Instance = NET_LIST_USER_STRUCT (Entry, MNP_INSTANCE_DATA, InstEntry);
1020 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1021
1022 if (!Instance->Configured || (Instance->ConfigData.ReceivedQueueTimeoutValue == 0)) {
1023 //
1024 // This instance is not configured or there is no receive time out,
1025 // just skip to the next instance.
1026 //
1027 continue;
1028 }
1029
1030 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1031
1032 NET_LIST_FOR_EACH_SAFE (RxEntry, NextEntry, &Instance->RcvdPacketQueue) {
1033 RxDataWrap = NET_LIST_USER_STRUCT (RxEntry, MNP_RXDATA_WRAP, WrapEntry);
1034
1035 //
1036 // TimeoutTick unit is microsecond, MNP_TIMEOUT_CHECK_INTERVAL unit is 100ns.
1037 //
1038 if (RxDataWrap->TimeoutTick >= (MNP_TIMEOUT_CHECK_INTERVAL / 10)) {
1039 RxDataWrap->TimeoutTick -= (MNP_TIMEOUT_CHECK_INTERVAL / 10);
1040 } else {
1041 //
1042 // Drop the timeout packet.
1043 //
1044 DEBUG ((DEBUG_WARN, "MnpCheckPacketTimeout: Received packet timeout.\n"));
1045 MnpRecycleRxData (NULL, RxDataWrap);
1046 Instance->RcvdPacketQueueSize--;
1047 }
1048 }
1049
1050 gBS->RestoreTPL (OldTpl);
1051 }
1052 }
1053}
1054
1062VOID
1063EFIAPI
1065 IN EFI_EVENT Event,
1066 IN VOID *Context
1067 )
1068{
1069 MNP_DEVICE_DATA *MnpDeviceData;
1071 UINT32 InterruptStatus;
1072
1073 MnpDeviceData = (MNP_DEVICE_DATA *)Context;
1074 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1075
1076 Snp = MnpDeviceData->Snp;
1077 if (Snp->Mode->MediaPresentSupported) {
1078 //
1079 // Upon successful return of GetStatus(), the MediaPresent field of
1080 // EFI_SIMPLE_NETWORK_MODE will be updated to reflect any change of media status
1081 //
1082 Snp->GetStatus (Snp, &InterruptStatus, NULL);
1083 }
1084}
1085
1094VOID
1095EFIAPI
1097 IN EFI_EVENT Event,
1098 IN VOID *Context
1099 )
1100{
1101 MNP_DEVICE_DATA *MnpDeviceData;
1102
1103 MnpDeviceData = (MNP_DEVICE_DATA *)Context;
1104 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1105
1106 //
1107 // Try to receive packets from Snp.
1108 //
1109 MnpReceivePacket (MnpDeviceData);
1110
1111 //
1112 // Dispatch the DPC queued by the NotifyFunction of rx token's events.
1113 //
1114 DispatchDpc ();
1115}
UINT64 UINTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_STATUS EFIAPI DispatchDpc(VOID)
Definition: DpcLib.c:86
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
MNP_SERVICE_DATA * MnpFindServiceData(IN MNP_DEVICE_DATA *MnpDeviceData, IN UINT16 VlanId)
Definition: MnpConfig.c:936
UINT8 * MnpAllocTxBuf(IN OUT MNP_DEVICE_DATA *MnpDeviceData)
Definition: MnpConfig.c:260
VOID MnpFreeNbuf(IN OUT MNP_DEVICE_DATA *MnpDeviceData, IN OUT NET_BUF *Nbuf)
Definition: MnpConfig.c:170
EFI_STATUS MnpRecycleTxBuf(IN OUT MNP_DEVICE_DATA *MnpDeviceData)
Definition: MnpConfig.c:381
NET_BUF * MnpAllocNbuf(IN OUT MNP_DEVICE_DATA *MnpDeviceData)
Definition: MnpConfig.c:103
MNP_RXDATA_WRAP * MnpWrapRxData(IN MNP_INSTANCE_DATA *Instance, IN EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData)
Definition: MnpIo.c:700
VOID EFIAPI MnpCheckMediaStatus(IN EFI_EVENT Event, IN VOID *Context)
Definition: MnpIo.c:1064
EFI_STATUS MnpSyncSendPacket(IN MNP_SERVICE_DATA *MnpServiceData, IN UINT8 *Packet, IN UINT32 Length, IN OUT EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token)
Definition: MnpIo.c:206
EFI_STATUS MnpReceivePacket(IN OUT MNP_DEVICE_DATA *MnpDeviceData)
Definition: MnpIo.c:828
EFI_STATUS MnpInstanceDeliverPacket(IN OUT MNP_INSTANCE_DATA *Instance)
Definition: MnpIo.c:306
BOOLEAN MnpMatchPacket(IN MNP_INSTANCE_DATA *Instance, IN EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData, IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL, IN UINT8 PktAttr)
Definition: MnpIo.c:528
VOID EFIAPI MnpRecycleRxData(IN EFI_EVENT Event, IN VOID *Context)
Definition: MnpIo.c:424
BOOLEAN MnpIsValidTxToken(IN MNP_INSTANCE_DATA *Instance, IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token)
Definition: MnpIo.c:22
VOID EFIAPI MnpSystemPoll(IN EFI_EVENT Event, IN VOID *Context)
Definition: MnpIo.c:1096
EFI_STATUS MnpBuildTxPacket(IN MNP_SERVICE_DATA *MnpServiceData, IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData, OUT UINT8 **PktBuf, OUT UINT32 *PktLen)
Definition: MnpIo.c:112
VOID MnpDeliverPacket(IN MNP_SERVICE_DATA *MnpServiceData)
Definition: MnpIo.c:394
VOID EFIAPI MnpCheckPacketTimeout(IN EFI_EVENT Event, IN VOID *Context)
Definition: MnpIo.c:997
VOID MnpEnqueuePacket(IN MNP_SERVICE_DATA *MnpServiceData, IN NET_BUF *Nbuf)
Definition: MnpIo.c:754
VOID MnpQueueRcvdPacket(IN OUT MNP_INSTANCE_DATA *Instance, IN OUT MNP_RXDATA_WRAP *RxDataWrap)
Definition: MnpIo.c:469
VOID MnpAnalysePacket(IN MNP_SERVICE_DATA *MnpServiceData, IN NET_BUF *Nbuf, IN OUT EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData, OUT MNP_GROUP_ADDRESS **GroupAddress, OUT UINT8 *PktAttr)
Definition: MnpIo.c:604
BOOLEAN MnpRemoveVlanTag(IN OUT MNP_DEVICE_DATA *MnpDeviceData, IN OUT NET_BUF *Nbuf, OUT UINT16 *VlanId)
Definition: MnpVlan.c:117
VOID MnpInsertVlanTag(IN MNP_SERVICE_DATA *MnpServiceData, IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData, OUT UINT16 *ProtocolType, IN OUT UINT8 **Packet, IN OUT UINT32 *Length)
Definition: MnpVlan.c:177
LIST_ENTRY *EFIAPI NetListRemoveHead(IN OUT LIST_ENTRY *Head)
Definition: DxeNetLib.c:1090
UINT32 EFIAPI NetbufTrim(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1134
UINT8 *EFIAPI NetbufAllocSpace(IN OUT NET_BUF *Nbuf, IN UINT32 Len, IN BOOLEAN FromHead)
Definition: NetBuffer.c:1015
NET_BUF *EFIAPI NetbufDuplicate(IN NET_BUF *Nbuf, IN OUT NET_BUF *Duplicate OPTIONAL, IN UINT32 HeadSpace)
Definition: NetBuffer.c:280
BOOLEAN EFIAPI NetMapIsEmpty(IN NET_MAP *Map)
Definition: DxeNetLib.c:1413
UINT8 *EFIAPI NetbufGetByte(IN NET_BUF *Nbuf, IN UINT32 Offset, OUT UINT32 *Index OPTIONAL)
Definition: NetBuffer.c:359
VOID *EFIAPI NetMapRemoveHead(IN OUT NET_MAP *Map, OUT VOID **Value OPTIONAL)
Definition: DxeNetLib.c:1710
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
#define SIGNAL_TOKEN(Token, TokenStatus)
Definition: SockImpl.h:23
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_SIMPLE_NETWORK_MODE * Mode
EFI_MANAGED_NETWORK_RECEIVE_DATA * RxData
EFI_MAC_ADDRESS CurrentAddress
EFI_MAC_ADDRESS BroadcastAddress