3 Copyright (c) 2005 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Implementation of Managed Network Protocol private services.
26 EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol
= {
27 MnpServiceBindingCreateChild
,
28 MnpServiceBindingDestroyChild
31 EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate
= {
42 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData
= {
58 IN MNP_SERVICE_DATA
*MnpServiceData
,
65 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
71 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
77 IN MNP_SERVICE_DATA
*MnpServiceData
,
78 IN BOOLEAN IsConfigUpdate
,
79 IN BOOLEAN EnableSystemPoll
85 IN MNP_SERVICE_DATA
*MnpServiceData
90 MnpConfigReceiveFilters (
91 IN MNP_SERVICE_DATA
*MnpServiceData
96 MnpGroupOpAddCtrlBlk (
97 IN MNP_INSTANCE_DATA
*Instance
,
98 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
99 IN MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
100 IN EFI_MAC_ADDRESS
*MacAddress
,
101 IN UINT32 HwAddressSize
106 MnpGroupOpDelCtrlBlk (
107 IN MNP_INSTANCE_DATA
*Instance
,
108 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
113 Add some NET_BUF into MnpServiceData->FreeNbufQue. The buffer length of
114 the NET_BUF is specified by MnpServiceData->BufferLength.
116 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
117 @param Count Number of NET_BUFFERs to add.
119 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated and
120 added into MnpServiceData->FreeNbufQue.
121 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.
127 IN MNP_SERVICE_DATA
*MnpServiceData
,
135 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
136 ASSERT ((Count
> 0) && (MnpServiceData
->BufferLength
> 0));
138 Status
= EFI_SUCCESS
;
140 for (Index
= 0; Index
< Count
; Index
++) {
142 Nbuf
= NetbufAlloc (MnpServiceData
->BufferLength
+ MnpServiceData
->PaddingSize
);
145 DEBUG ((EFI_D_ERROR
, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));
146 Status
= EFI_OUT_OF_RESOURCES
;
150 if (MnpServiceData
->PaddingSize
> 0) {
152 // Pad padding bytes before the media header
154 NetbufAllocSpace (Nbuf
, MnpServiceData
->PaddingSize
, NET_BUF_TAIL
);
155 NetbufTrim (Nbuf
, MnpServiceData
->PaddingSize
, NET_BUF_HEAD
);
158 NetbufQueAppend (&MnpServiceData
->FreeNbufQue
, Nbuf
);
161 MnpServiceData
->NbufCnt
+= Index
;
168 Allocate a free NET_BUF from MnpServiceData->FreeNbufQue. If there is none
169 in the queue, first try to allocate some and add them into the queue, then
170 fetch the NET_BUF from the updated FreeNbufQue.
172 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
174 @return Pointer to the allocated free NET_BUF structure, if NULL the operation is failed.
179 IN MNP_SERVICE_DATA
*MnpServiceData
183 NET_BUF_QUEUE
*FreeNbufQue
;
187 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
189 FreeNbufQue
= &MnpServiceData
->FreeNbufQue
;
191 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
194 // Check whether there are available buffers, or else try to add some.
196 if (FreeNbufQue
->BufNum
== 0) {
198 if ((MnpServiceData
->NbufCnt
+ MNP_NET_BUFFER_INCREASEMENT
) > MNP_MAX_NET_BUFFER_NUM
) {
202 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
210 Status
= MnpAddFreeNbuf (MnpServiceData
, MNP_NET_BUFFER_INCREASEMENT
);
211 if (EFI_ERROR (Status
)) {
215 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
219 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
220 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
225 Nbuf
= NetbufQueRemove (FreeNbufQue
);
228 // Increase the RefCnt.
235 gBS
->RestoreTPL (OldTpl
);
242 Try to reclaim the Nbuf into the buffer pool.
244 @param MnpServiceData Pointer to the mnp service context data.
245 @param Nbuf Pointer to the NET_BUF to free.
252 IN MNP_SERVICE_DATA
*MnpServiceData
,
258 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
259 ASSERT (Nbuf
->RefCnt
> 1);
261 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
265 if (Nbuf
->RefCnt
== 1) {
267 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
269 NetbufTrim (Nbuf
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
270 NetbufQueAppend (&MnpServiceData
->FreeNbufQue
, Nbuf
);
273 gBS
->RestoreTPL (OldTpl
);
278 Initialize the mnp service context data.
280 @param MnpServiceData Pointer to the mnp service context data.
281 @param Snp Pointer to the simple network protocol.
283 @retval EFI_SUCCESS The mnp service context is initialized.
284 @retval Other Some error occurs.
288 MnpInitializeServiceData (
289 IN MNP_SERVICE_DATA
*MnpServiceData
,
290 IN EFI_HANDLE ImageHandle
,
291 IN EFI_HANDLE ControllerHandle
295 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
296 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
298 MnpServiceData
->Signature
= MNP_SERVICE_DATA_SIGNATURE
;
300 MnpServiceData
->ControllerHandle
= ControllerHandle
;
303 // Copy the ServiceBinding structure.
305 MnpServiceData
->ServiceBinding
= mMnpServiceBindingProtocol
;
308 // Open the Simple Network protocol.
310 Status
= gBS
->OpenProtocol (
312 &gEfiSimpleNetworkProtocolGuid
,
316 EFI_OPEN_PROTOCOL_BY_DRIVER
318 if (EFI_ERROR (Status
)) {
319 return EFI_UNSUPPORTED
;
326 MnpServiceData
->Snp
= Snp
;
327 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
;
330 // Initialize the lists.
332 InitializeListHead (&MnpServiceData
->GroupAddressList
);
333 InitializeListHead (&MnpServiceData
->ChildrenList
);
336 // Get the buffer length used to allocate NET_BUF to hold data received
337 // from SNP. Do this before fill the FreeNetBufQue.
339 MnpServiceData
->BufferLength
= MnpServiceData
->Mtu
+ SnpMode
->MediaHeaderSize
+ NET_ETHER_FCS_SIZE
;
342 // Make sure the protocol headers immediately following the media header
345 MnpServiceData
->PaddingSize
= (4 - SnpMode
->MediaHeaderSize
) & 0x3;
348 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
350 NetbufQueInit (&MnpServiceData
->FreeNbufQue
);
351 Status
= MnpAddFreeNbuf (MnpServiceData
, MNP_INIT_NET_BUFFER_NUM
);
352 if (EFI_ERROR (Status
)) {
354 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status
));
358 // Get one NET_BUF from the FreeNbufQue for rx cache.
360 MnpServiceData
->RxNbufCache
= MnpAllocNbuf (MnpServiceData
);
362 MnpServiceData
->RxNbufCache
,
363 MnpServiceData
->BufferLength
,
368 // Allocate buffer pool for tx.
370 MnpServiceData
->TxBuf
= AllocatePool (MnpServiceData
->Mtu
+ SnpMode
->MediaHeaderSize
);
371 if (MnpServiceData
->TxBuf
== NULL
) {
373 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: AllocatePool failed.\n"));
374 Status
= EFI_OUT_OF_RESOURCES
;
380 // Create the system poll timer.
382 Status
= gBS
->CreateEvent (
383 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
387 &MnpServiceData
->PollTimer
389 if (EFI_ERROR (Status
)) {
391 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));
396 // Create the timer for packet timeout check.
398 Status
= gBS
->CreateEvent (
399 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
401 MnpCheckPacketTimeout
,
403 &MnpServiceData
->TimeoutCheckTimer
405 if (EFI_ERROR (Status
)) {
407 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));
412 // Create the timer for tx timeout check.
414 Status
= gBS
->CreateEvent (
419 &MnpServiceData
->TxTimeoutEvent
421 if (EFI_ERROR (Status
)) {
423 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));
428 if (EFI_ERROR (Status
)) {
430 // Free the dynamic allocated resources if necessary.
432 if (MnpServiceData
->TimeoutCheckTimer
!= NULL
) {
434 gBS
->CloseEvent (MnpServiceData
->TimeoutCheckTimer
);
437 if (MnpServiceData
->PollTimer
!= NULL
) {
439 gBS
->CloseEvent (MnpServiceData
->PollTimer
);
442 if (MnpServiceData
->TxBuf
!= NULL
) {
444 gBS
->FreePool (MnpServiceData
->TxBuf
);
447 if (MnpServiceData
->RxNbufCache
!= NULL
) {
449 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
452 if (MnpServiceData
->FreeNbufQue
.BufNum
!= 0) {
454 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
463 Flush the mnp service context data.
465 @param MnpServiceData Pointer to the mnp service context data.
471 MnpFlushServiceData (
472 IN MNP_SERVICE_DATA
*MnpServiceData
,
473 IN EFI_HANDLE ImageHandle
476 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
479 // The GroupAddressList must be empty.
481 ASSERT (IsListEmpty (&MnpServiceData
->GroupAddressList
));
486 gBS
->CloseEvent (&MnpServiceData
->TxTimeoutEvent
);
487 gBS
->CloseEvent (&MnpServiceData
->TimeoutCheckTimer
);
488 gBS
->CloseEvent (&MnpServiceData
->PollTimer
);
491 // Free the tx buffer.
493 gBS
->FreePool (MnpServiceData
->TxBuf
);
496 // Free the RxNbufCache.
498 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
501 // Flush the FreeNbufQue.
503 MnpServiceData
->NbufCnt
-= MnpServiceData
->FreeNbufQue
.BufNum
;
504 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
508 if (MnpServiceData
->NbufCnt
!= 0) {
510 DEBUG ((EFI_D_WARN
, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));
515 // Close the Simple Network Protocol.
518 MnpServiceData
->ControllerHandle
,
519 &gEfiSimpleNetworkProtocolGuid
,
521 MnpServiceData
->ControllerHandle
527 Initialize the mnp instance context data.
529 @param MnpServiceData Pointer to the mnp service context data.
530 @param Instance Pointer to the mnp instance context data to
537 MnpInitializeInstanceData (
538 IN MNP_SERVICE_DATA
*MnpServiceData
,
539 IN MNP_INSTANCE_DATA
*Instance
542 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
543 ASSERT (Instance
!= NULL
);
546 // Set the signature.
548 Instance
->Signature
= MNP_INSTANCE_DATA_SIGNATURE
;
551 // Copy the MNP Protocol interfaces from the template.
553 CopyMem (&Instance
->ManagedNetwork
, &mMnpProtocolTemplate
, sizeof (Instance
->ManagedNetwork
));
556 // Copy the default config data.
558 CopyMem (&Instance
->ConfigData
, &mMnpDefaultConfigData
, sizeof (Instance
->ConfigData
));
561 // Initialize the lists.
563 InitializeListHead (&Instance
->GroupCtrlBlkList
);
564 InitializeListHead (&Instance
->RcvdPacketQueue
);
565 InitializeListHead (&Instance
->RxDeliveredPacketQueue
);
568 // Initialize the RxToken Map.
570 NetMapInit (&Instance
->RxTokenMap
);
573 // Save the MnpServiceData info.
575 Instance
->MnpServiceData
= MnpServiceData
;
580 Check whether the token specified by Arg maches the token in Item.
582 @param Map Pointer to the NET_MAP.
583 @param Item Pointer to the NET_MAP_ITEM
584 @param Arg Pointer to the Arg, it's a pointer to the token to
587 @retval EFI_SUCCESS The token specified by Arg is different from the
589 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
596 IN NET_MAP_ITEM
*Item
,
600 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
;
601 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenInItem
;
603 Token
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Arg
;
604 TokenInItem
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
606 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
608 // The token is the same either the two tokens equals or the Events in
609 // the two tokens are the same.
611 return EFI_ACCESS_DENIED
;
619 Cancel the token specified by Arg if it matches the token in Item.
621 @param Map Pointer to the NET_MAP.
622 @param Item Pointer to the NET_MAP_ITEM
623 @param Arg Pointer to the Arg, it's a pointer to the token to
626 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is
627 cancelled, or the Arg isn't NULL, and the token in
628 Item is different from the Arg.
629 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
630 Arg, and the token is cancelled.
636 IN NET_MAP_ITEM
*Item
,
640 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenToCancel
;
642 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
644 // The token in Item is not the token specified by Arg.
649 TokenToCancel
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
652 // Remove the item from the map.
654 NetMapRemoveItem (Map
, Item
, NULL
);
657 // Cancel this token with status set to EFI_ABORTED.
659 TokenToCancel
->Status
= EFI_ABORTED
;
660 gBS
->SignalEvent (TokenToCancel
->Event
);
664 // Only abort the token specified by Arg if Arg isn't NULL.
674 Start and initialize the simple network.
676 @param Snp Pointer to the simple network protocol.
678 @retval EFI_SUCCESS The simple network protocol is started.
679 @retval Other Some error occurs.
685 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
690 ASSERT (Snp
!= NULL
);
693 // Start the simple network.
695 Status
= Snp
->Start (Snp
);
697 if (!EFI_ERROR (Status
)) {
699 // Initialize the simple network.
701 Status
= Snp
->Initialize (Snp
, 0, 0);
709 Stop the simple network.
711 @param Snp Pointer to the simple network protocol.
713 @retval EFI_SUCCESS The simple network is stopped.
714 @retval Other Some error occurs.
720 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
725 ASSERT (Snp
!= NULL
);
728 // Shut down the simple network.
730 Status
= Snp
->Shutdown (Snp
);
732 if (!EFI_ERROR (Status
)) {
734 // Stop the simple network.
736 Status
= Snp
->Stop (Snp
);
744 Start the managed network, this function is called when one instance is configured
747 @param MnpServiceData Pointer to the mnp service context data.
748 @param IsConfigUpdate The instance is reconfigured or it's the first time
749 the instanced is configured.
750 @param EnableSystemPoll Enable the system polling or not.
752 @retval EFI_SUCCESS The managed network is started and some
753 configuration is updated.
754 @retval Other Some error occurs.
760 IN MNP_SERVICE_DATA
*MnpServiceData
,
761 IN BOOLEAN IsConfigUpdate
,
762 IN BOOLEAN EnableSystemPoll
766 EFI_TIMER_DELAY TimerOpType
;
768 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
770 Status
= EFI_SUCCESS
;
772 if (!IsConfigUpdate
) {
774 // If it's not a configuration update, increase the configured children number.
776 MnpServiceData
->ConfiguredChildrenNumber
++;
778 if (MnpServiceData
->ConfiguredChildrenNumber
== 1) {
780 // It's the first configured child, start the simple network.
782 Status
= MnpStartSnp (MnpServiceData
->Snp
);
783 if (EFI_ERROR (Status
)) {
785 DEBUG ((EFI_D_ERROR
, "MnpStart: MnpStartSnp failed, %r.\n", Status
));
790 // Start the timeout timer.
792 Status
= gBS
->SetTimer (
793 MnpServiceData
->TimeoutCheckTimer
,
795 MNP_TIMEOUT_CHECK_INTERVAL
797 if (EFI_ERROR (Status
)) {
801 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
809 if (MnpServiceData
->EnableSystemPoll
^ EnableSystemPoll
) {
811 // The EnableSystemPoll differs with the current state, disable or enable
814 TimerOpType
= EnableSystemPoll
? TimerPeriodic
: TimerCancel
;
816 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerOpType
, MNP_SYS_POLL_INTERVAL
);
817 if (EFI_ERROR (Status
)) {
819 DEBUG ((EFI_D_ERROR
, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status
));
823 MnpServiceData
->EnableSystemPoll
= EnableSystemPoll
;
827 // Change the receive filters if need.
829 Status
= MnpConfigReceiveFilters (MnpServiceData
);
838 Stop the managed network.
840 @param MnpServiceData Pointer to the mnp service context data.
842 @retval EFI_SUCCESS The managed network is stopped.
843 @retval Other Some error occurs.
849 IN MNP_SERVICE_DATA
*MnpServiceData
854 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
855 ASSERT (MnpServiceData
->ConfiguredChildrenNumber
> 0);
858 // Configure the receive filters.
860 MnpConfigReceiveFilters (MnpServiceData
);
863 // Decrease the children number.
865 MnpServiceData
->ConfiguredChildrenNumber
--;
867 if (MnpServiceData
->ConfiguredChildrenNumber
> 0) {
869 // If there are other configured chilren, return and keep the timers and
870 // simple network unchanged.
876 // No configured children now.
879 if (MnpServiceData
->EnableSystemPoll
) {
881 // The system poll in on, cancel the poll timer.
883 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerCancel
, 0);
884 MnpServiceData
->EnableSystemPoll
= FALSE
;
888 // Cancel the timeout timer.
890 Status
= gBS
->SetTimer (MnpServiceData
->TimeoutCheckTimer
, TimerCancel
, 0);
893 // Stop the simple network.
895 Status
= MnpStopSnp (MnpServiceData
->Snp
);
902 Flush the instance's received data.
904 @param Instance Pointer to the mnp instance context data.
910 MnpFlushRcvdDataQueue (
911 IN MNP_INSTANCE_DATA
*Instance
915 MNP_RXDATA_WRAP
*RxDataWrap
;
917 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
919 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
921 while (!IsListEmpty (&Instance
->RcvdPacketQueue
)) {
923 // Remove all the Wraps.
925 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
928 // Recycle the RxDataWrap.
930 MnpRecycleRxData (NULL
, (VOID
*) RxDataWrap
);
931 Instance
->RcvdPacketQueueSize
--;
934 ASSERT (Instance
->RcvdPacketQueueSize
== 0);
936 gBS
->RestoreTPL (OldTpl
);
941 Configure the Instance using ConfigData.
943 @param Instance Pointer to the mnp instance context data.
944 @param ConfigData Pointer to the configuration data used to configure
947 @retval EFI_SUCCESS The Instance is configured.
948 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
949 implementation doesn't support it.
950 @retval Other Some error occurs.
954 MnpConfigureInstance (
955 IN MNP_INSTANCE_DATA
*Instance
,
956 IN EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData OPTIONAL
960 MNP_SERVICE_DATA
*MnpServiceData
;
961 EFI_MANAGED_NETWORK_CONFIG_DATA
*OldConfigData
;
962 EFI_MANAGED_NETWORK_CONFIG_DATA
*NewConfigData
;
963 BOOLEAN IsConfigUpdate
;
965 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
967 if ((ConfigData
!= NULL
) && ConfigData
->EnableReceiveTimestamps
) {
969 // Don't support timestamp.
971 return EFI_UNSUPPORTED
;
974 Status
= EFI_SUCCESS
;
976 MnpServiceData
= Instance
->MnpServiceData
;
977 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
979 IsConfigUpdate
= (BOOLEAN
) ((Instance
->Configured
) && (ConfigData
!= NULL
));
981 OldConfigData
= &Instance
->ConfigData
;
982 NewConfigData
= ConfigData
;
983 if (NewConfigData
== NULL
) {
985 // Restore back the default config data if a reset of this instance
988 NewConfigData
= &mMnpDefaultConfigData
;
992 // Reset the instance's receive filter.
994 Instance
->ReceiveFilter
= 0;
997 // Clear the receive counters according to the old ConfigData.
999 if (OldConfigData
->EnableUnicastReceive
) {
1000 MnpServiceData
->UnicastCount
--;
1003 if (OldConfigData
->EnableMulticastReceive
) {
1004 MnpServiceData
->MulticastCount
--;
1007 if (OldConfigData
->EnableBroadcastReceive
) {
1008 MnpServiceData
->BroadcastCount
--;
1011 if (OldConfigData
->EnablePromiscuousReceive
) {
1012 MnpServiceData
->PromiscuousCount
--;
1016 // Set the receive filter counters and the receive filter of the
1017 // instance according to the new ConfigData.
1019 if (NewConfigData
->EnableUnicastReceive
) {
1020 MnpServiceData
->UnicastCount
++;
1021 Instance
->ReceiveFilter
|= MNP_RECEIVE_UNICAST
;
1024 if (NewConfigData
->EnableMulticastReceive
) {
1025 MnpServiceData
->MulticastCount
++;
1028 if (NewConfigData
->EnableBroadcastReceive
) {
1029 MnpServiceData
->BroadcastCount
++;
1030 Instance
->ReceiveFilter
|= MNP_RECEIVE_BROADCAST
;
1033 if (NewConfigData
->EnablePromiscuousReceive
) {
1034 MnpServiceData
->PromiscuousCount
++;
1037 if (OldConfigData
->FlushQueuesOnReset
) {
1039 MnpFlushRcvdDataQueue (Instance
);
1042 if (ConfigData
== NULL
) {
1044 Instance
->ManagedNetwork
.Cancel (&Instance
->ManagedNetwork
, NULL
);
1047 if (!NewConfigData
->EnableMulticastReceive
) {
1049 MnpGroupOp (Instance
, FALSE
, NULL
, NULL
);
1053 // Save the new configuration data.
1055 CopyMem (OldConfigData
, NewConfigData
, sizeof (*OldConfigData
));
1057 Instance
->Configured
= (BOOLEAN
) (ConfigData
!= NULL
);
1059 if (Instance
->Configured
) {
1061 // The instance is configured, start the Mnp.
1066 (BOOLEAN
) !NewConfigData
->DisableBackgroundPolling
1070 // The instance is changed to the unconfigured state, stop the Mnp.
1072 Status
= MnpStop (MnpServiceData
);
1080 Configure the Snp receive filters according to the instances' receive filter
1083 @param MnpServiceData Pointer to the mnp service context data.
1085 @retval EFI_SUCCESS The receive filters is configured.
1086 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due to lack
1092 MnpConfigReceiveFilters (
1093 IN MNP_SERVICE_DATA
*MnpServiceData
1097 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1098 EFI_MAC_ADDRESS
*MCastFilter
;
1099 UINT32 MCastFilterCnt
;
1100 UINT32 EnableFilterBits
;
1101 UINT32 DisableFilterBits
;
1102 BOOLEAN ResetMCastFilters
;
1105 MNP_GROUP_ADDRESS
*GroupAddress
;
1107 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1109 Snp
= MnpServiceData
->Snp
;
1112 // Initialize the enable filter and disable filter.
1114 EnableFilterBits
= 0;
1115 DisableFilterBits
= Snp
->Mode
->ReceiveFilterMask
;
1117 if (MnpServiceData
->UnicastCount
!= 0) {
1119 // Enable unicast if any instance wants to receive unicast.
1121 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1124 if (MnpServiceData
->BroadcastCount
!= 0) {
1126 // Enable broadcast if any instance wants to receive broadcast.
1128 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1133 ResetMCastFilters
= TRUE
;
1135 if ((MnpServiceData
->MulticastCount
!= 0) && (MnpServiceData
->GroupAddressCount
!= 0)) {
1137 // There are instances configured to receive multicast and already some group
1138 // addresses are joined.
1141 ResetMCastFilters
= FALSE
;
1143 if (MnpServiceData
->GroupAddressCount
<= Snp
->Mode
->MaxMCastFilterCount
) {
1145 // The joind group address is less than simple network's maximum count.
1146 // Just configure the snp to do the multicast filtering.
1149 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1152 // Allocate pool for the mulicast addresses.
1154 MCastFilterCnt
= MnpServiceData
->GroupAddressCount
;
1155 MCastFilter
= AllocatePool (sizeof (EFI_MAC_ADDRESS
) * MCastFilterCnt
);
1156 if (MCastFilter
== NULL
) {
1158 DEBUG ((EFI_D_ERROR
, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1159 return EFI_OUT_OF_RESOURCES
;
1163 // Fill the multicast HW address buffer.
1166 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
1168 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1169 CopyMem (MCastFilter
+ Index
, &GroupAddress
->Address
, sizeof (*(MCastFilter
+ Index
)));
1172 ASSERT (Index
<= MCastFilterCnt
);
1176 // The maximum multicast is reached, set the filter to be promiscuous
1180 if (Snp
->Mode
->ReceiveFilterMask
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
1181 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1184 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1185 // set the NIC to be promiscuous although this will tremendously degrade
1188 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1193 if (MnpServiceData
->PromiscuousCount
!= 0) {
1195 // Enable promiscuous if any instance wants to receive promiscuous.
1197 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1201 // Set the disable filter.
1203 DisableFilterBits
^= EnableFilterBits
;
1206 // Configure the receive filters of SNP.
1208 Status
= Snp
->ReceiveFilters (
1217 if (EFI_ERROR (Status
)) {
1221 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1227 if (MCastFilter
!= NULL
) {
1229 // Free the buffer used to hold the group addresses.
1231 gBS
->FreePool (MCastFilter
);
1239 Add a group address control block which controls the MacAddress for
1242 @param Instance Pointer to the mnp instance context data.
1243 @param CtrlBlk Pointer to the group address control block.
1244 @param GroupAddress Pointer to the group adress.
1245 @param MacAddress Pointer to the mac address.
1246 @param HwAddressSize The hardware address size.
1248 @retval EFI_SUCCESS The group address control block is added.
1249 @retval EFI_OUT_OF_RESOURCE Failed due to lack of memory resources.
1254 MnpGroupOpAddCtrlBlk (
1255 IN MNP_INSTANCE_DATA
*Instance
,
1256 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
1257 IN MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
1258 IN EFI_MAC_ADDRESS
*MacAddress
,
1259 IN UINT32 HwAddressSize
1262 MNP_SERVICE_DATA
*MnpServiceData
;
1264 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1266 MnpServiceData
= Instance
->MnpServiceData
;
1267 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1269 if (GroupAddress
== NULL
) {
1271 ASSERT (MacAddress
!= NULL
);
1274 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1276 GroupAddress
= AllocatePool (sizeof (MNP_GROUP_ADDRESS
));
1277 if (GroupAddress
== NULL
) {
1279 DEBUG ((EFI_D_ERROR
, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1281 return EFI_OUT_OF_RESOURCES
;
1284 CopyMem (&GroupAddress
->Address
, MacAddress
, sizeof (GroupAddress
->Address
));
1285 GroupAddress
->RefCnt
= 0;
1287 &MnpServiceData
->GroupAddressList
,
1288 &GroupAddress
->AddrEntry
1290 MnpServiceData
->GroupAddressCount
++;
1294 // Increase the RefCnt.
1296 GroupAddress
->RefCnt
++;
1299 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1301 CtrlBlk
->GroupAddress
= GroupAddress
;
1302 InsertTailList (&Instance
->GroupCtrlBlkList
, &CtrlBlk
->CtrlBlkEntry
);
1309 Delete a group control block from the instance. If the controlled group address's
1310 reference count reaches zero, the group address is removed too.
1312 @param Instance Pointer to the instance context data.
1313 @param CtrlBlk Pointer to the group control block to delete.
1315 @return The group address controlled by the control block is no longer used or not.
1320 MnpGroupOpDelCtrlBlk (
1321 IN MNP_INSTANCE_DATA
*Instance
,
1322 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
1325 MNP_SERVICE_DATA
*MnpServiceData
;
1326 MNP_GROUP_ADDRESS
*GroupAddress
;
1328 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1330 MnpServiceData
= Instance
->MnpServiceData
;
1331 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1334 // Remove and free the CtrlBlk.
1336 GroupAddress
= CtrlBlk
->GroupAddress
;
1337 RemoveEntryList (&CtrlBlk
->CtrlBlkEntry
);
1338 gBS
->FreePool (CtrlBlk
);
1340 ASSERT (GroupAddress
->RefCnt
> 0);
1343 // Count down the RefCnt.
1345 GroupAddress
->RefCnt
--;
1347 if (GroupAddress
->RefCnt
== 0) {
1349 // Free this GroupAddress entry if no instance uses it.
1351 MnpServiceData
->GroupAddressCount
--;
1352 RemoveEntryList (&GroupAddress
->AddrEntry
);
1353 gBS
->FreePool (GroupAddress
);
1363 Do the group operations for this instance.
1365 @param Instance Pointer to the instance context data.
1366 @param JoinFlag Set to TRUE to join a group. Set to TRUE to leave a
1368 @param MacAddress Pointer to the group address to join or leave.
1369 @param CtrlBlk Pointer to the group control block if JoinFlag if
1372 @retval EFI_SUCCESS The group operation finished.
1373 @retval Other Some error occurs.
1378 IN MNP_INSTANCE_DATA
*Instance
,
1379 IN BOOLEAN JoinFlag
,
1380 IN EFI_MAC_ADDRESS
*MacAddress OPTIONAL
,
1381 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk OPTIONAL
1384 MNP_SERVICE_DATA
*MnpServiceData
;
1386 LIST_ENTRY
*NextEntry
;
1387 MNP_GROUP_ADDRESS
*GroupAddress
;
1388 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1389 MNP_GROUP_CONTROL_BLOCK
*NewCtrlBlk
;
1391 BOOLEAN AddressExist
;
1394 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1396 MnpServiceData
= Instance
->MnpServiceData
;
1397 SnpMode
= MnpServiceData
->Snp
->Mode
;
1401 // A new gropu address is to be added.
1404 GroupAddress
= NULL
;
1405 AddressExist
= FALSE
;
1408 // Allocate memory for the control block.
1410 NewCtrlBlk
= AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK
));
1411 if (NewCtrlBlk
== NULL
) {
1413 DEBUG ((EFI_D_ERROR
, "MnpGroupOp: Failed to allocate memory resource.\n"));
1414 return EFI_OUT_OF_RESOURCES
;
1417 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
1419 // Check whether the MacAddress is already joined by other instances.
1421 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1422 if (0 == CompareMem (
1424 &GroupAddress
->Address
,
1425 SnpMode
->HwAddressSize
1428 AddressExist
= TRUE
;
1433 if (!AddressExist
) {
1434 GroupAddress
= NULL
;
1438 // Add the GroupAddress for this instance.
1440 Status
= MnpGroupOpAddCtrlBlk (
1445 SnpMode
->HwAddressSize
1447 if (EFI_ERROR (Status
)) {
1455 if (MacAddress
!= NULL
) {
1457 ASSERT (CtrlBlk
!= NULL
);
1460 // Leave the specific multicast mac address.
1462 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, CtrlBlk
);
1465 // Leave all multicast mac addresses.
1469 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Instance
->GroupCtrlBlkList
) {
1471 NewCtrlBlk
= NET_LIST_USER_STRUCT (
1473 MNP_GROUP_CONTROL_BLOCK
,
1477 // Update is required if the group address left is no longer used
1478 // by other instances.
1480 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, NewCtrlBlk
);
1485 Status
= EFI_SUCCESS
;
1489 // Reconfigure the receive filters if necessary.
1491 Status
= MnpConfigReceiveFilters (MnpServiceData
);