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