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 MNP_SERVICE_DATA
*MnpServiceData
475 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
478 // The GroupAddressList must be empty.
480 ASSERT (IsListEmpty (&MnpServiceData
->GroupAddressList
));
485 gBS
->CloseEvent (&MnpServiceData
->TxTimeoutEvent
);
486 gBS
->CloseEvent (&MnpServiceData
->TimeoutCheckTimer
);
487 gBS
->CloseEvent (&MnpServiceData
->PollTimer
);
490 // Free the tx buffer.
492 gBS
->FreePool (MnpServiceData
->TxBuf
);
495 // Free the RxNbufCache.
497 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
500 // Flush the FreeNbufQue.
502 MnpServiceData
->NbufCnt
-= MnpServiceData
->FreeNbufQue
.BufNum
;
503 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
507 if (MnpServiceData
->NbufCnt
!= 0) {
509 DEBUG ((EFI_D_WARN
, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));
514 // Close the Simple Network Protocol.
517 MnpServiceData
->ControllerHandle
,
518 &gEfiSimpleNetworkProtocolGuid
,
519 This
->DriverBindingHandle
,
520 MnpServiceData
->ControllerHandle
526 Initialize the mnp instance context data.
528 @param MnpServiceData Pointer to the mnp service context data.
529 @param Instance Pointer to the mnp instance context data to
536 MnpInitializeInstanceData (
537 IN MNP_SERVICE_DATA
*MnpServiceData
,
538 IN MNP_INSTANCE_DATA
*Instance
541 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
542 ASSERT (Instance
!= NULL
);
545 // Set the signature.
547 Instance
->Signature
= MNP_INSTANCE_DATA_SIGNATURE
;
550 // Copy the MNP Protocol interfaces from the template.
552 CopyMem (&Instance
->ManagedNetwork
, &mMnpProtocolTemplate
, sizeof (Instance
->ManagedNetwork
));
555 // Copy the default config data.
557 CopyMem (&Instance
->ConfigData
, &mMnpDefaultConfigData
, sizeof (Instance
->ConfigData
));
560 // Initialize the lists.
562 InitializeListHead (&Instance
->GroupCtrlBlkList
);
563 InitializeListHead (&Instance
->RcvdPacketQueue
);
564 InitializeListHead (&Instance
->RxDeliveredPacketQueue
);
567 // Initialize the RxToken Map.
569 NetMapInit (&Instance
->RxTokenMap
);
572 // Save the MnpServiceData info.
574 Instance
->MnpServiceData
= MnpServiceData
;
579 Check whether the token specified by Arg maches the token in Item.
581 @param Map Pointer to the NET_MAP.
582 @param Item Pointer to the NET_MAP_ITEM
583 @param Arg Pointer to the Arg, it's a pointer to the token to
586 @retval EFI_SUCCESS The token specified by Arg is different from the
588 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
595 IN NET_MAP_ITEM
*Item
,
599 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
;
600 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenInItem
;
602 Token
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Arg
;
603 TokenInItem
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
605 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
607 // The token is the same either the two tokens equals or the Events in
608 // the two tokens are the same.
610 return EFI_ACCESS_DENIED
;
618 Cancel the token specified by Arg if it matches the token in Item.
620 @param Map Pointer to the NET_MAP.
621 @param Item Pointer to the NET_MAP_ITEM
622 @param Arg Pointer to the Arg, it's a pointer to the token to
625 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is
626 cancelled, or the Arg isn't NULL, and the token in
627 Item is different from the Arg.
628 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
629 Arg, and the token is cancelled.
635 IN NET_MAP_ITEM
*Item
,
639 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenToCancel
;
641 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
643 // The token in Item is not the token specified by Arg.
648 TokenToCancel
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
651 // Remove the item from the map.
653 NetMapRemoveItem (Map
, Item
, NULL
);
656 // Cancel this token with status set to EFI_ABORTED.
658 TokenToCancel
->Status
= EFI_ABORTED
;
659 gBS
->SignalEvent (TokenToCancel
->Event
);
663 // Only abort the token specified by Arg if Arg isn't NULL.
673 Start and initialize the simple network.
675 @param Snp Pointer to the simple network protocol.
677 @retval EFI_SUCCESS The simple network protocol is started.
678 @retval Other Some error occurs.
684 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
689 ASSERT (Snp
!= NULL
);
692 // Start the simple network.
694 Status
= Snp
->Start (Snp
);
696 if (!EFI_ERROR (Status
)) {
698 // Initialize the simple network.
700 Status
= Snp
->Initialize (Snp
, 0, 0);
708 Stop the simple network.
710 @param Snp Pointer to the simple network protocol.
712 @retval EFI_SUCCESS The simple network is stopped.
713 @retval Other Some error occurs.
719 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
724 ASSERT (Snp
!= NULL
);
727 // Shut down the simple network.
729 Status
= Snp
->Shutdown (Snp
);
731 if (!EFI_ERROR (Status
)) {
733 // Stop the simple network.
735 Status
= Snp
->Stop (Snp
);
743 Start the managed network, this function is called when one instance is configured
746 @param MnpServiceData Pointer to the mnp service context data.
747 @param IsConfigUpdate The instance is reconfigured or it's the first time
748 the instanced is configured.
749 @param EnableSystemPoll Enable the system polling or not.
751 @retval EFI_SUCCESS The managed network is started and some
752 configuration is updated.
753 @retval Other Some error occurs.
759 IN MNP_SERVICE_DATA
*MnpServiceData
,
760 IN BOOLEAN IsConfigUpdate
,
761 IN BOOLEAN EnableSystemPoll
765 EFI_TIMER_DELAY TimerOpType
;
767 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
769 Status
= EFI_SUCCESS
;
771 if (!IsConfigUpdate
) {
773 // If it's not a configuration update, increase the configured children number.
775 MnpServiceData
->ConfiguredChildrenNumber
++;
777 if (MnpServiceData
->ConfiguredChildrenNumber
== 1) {
779 // It's the first configured child, start the simple network.
781 Status
= MnpStartSnp (MnpServiceData
->Snp
);
782 if (EFI_ERROR (Status
)) {
784 DEBUG ((EFI_D_ERROR
, "MnpStart: MnpStartSnp failed, %r.\n", Status
));
789 // Start the timeout timer.
791 Status
= gBS
->SetTimer (
792 MnpServiceData
->TimeoutCheckTimer
,
794 MNP_TIMEOUT_CHECK_INTERVAL
796 if (EFI_ERROR (Status
)) {
800 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
808 if (MnpServiceData
->EnableSystemPoll
^ EnableSystemPoll
) {
810 // The EnableSystemPoll differs with the current state, disable or enable
813 TimerOpType
= EnableSystemPoll
? TimerPeriodic
: TimerCancel
;
815 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerOpType
, MNP_SYS_POLL_INTERVAL
);
816 if (EFI_ERROR (Status
)) {
818 DEBUG ((EFI_D_ERROR
, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status
));
822 MnpServiceData
->EnableSystemPoll
= EnableSystemPoll
;
826 // Change the receive filters if need.
828 Status
= MnpConfigReceiveFilters (MnpServiceData
);
837 Stop the managed network.
839 @param MnpServiceData Pointer to the mnp service context data.
841 @retval EFI_SUCCESS The managed network is stopped.
842 @retval Other Some error occurs.
848 IN MNP_SERVICE_DATA
*MnpServiceData
853 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
854 ASSERT (MnpServiceData
->ConfiguredChildrenNumber
> 0);
857 // Configure the receive filters.
859 MnpConfigReceiveFilters (MnpServiceData
);
862 // Decrease the children number.
864 MnpServiceData
->ConfiguredChildrenNumber
--;
866 if (MnpServiceData
->ConfiguredChildrenNumber
> 0) {
868 // If there are other configured chilren, return and keep the timers and
869 // simple network unchanged.
875 // No configured children now.
878 if (MnpServiceData
->EnableSystemPoll
) {
880 // The system poll in on, cancel the poll timer.
882 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerCancel
, 0);
883 MnpServiceData
->EnableSystemPoll
= FALSE
;
887 // Cancel the timeout timer.
889 Status
= gBS
->SetTimer (MnpServiceData
->TimeoutCheckTimer
, TimerCancel
, 0);
892 // Stop the simple network.
894 Status
= MnpStopSnp (MnpServiceData
->Snp
);
901 Flush the instance's received data.
903 @param Instance Pointer to the mnp instance context data.
909 MnpFlushRcvdDataQueue (
910 IN MNP_INSTANCE_DATA
*Instance
914 MNP_RXDATA_WRAP
*RxDataWrap
;
916 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
918 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
920 while (!IsListEmpty (&Instance
->RcvdPacketQueue
)) {
922 // Remove all the Wraps.
924 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
927 // Recycle the RxDataWrap.
929 MnpRecycleRxData (NULL
, (VOID
*) RxDataWrap
);
930 Instance
->RcvdPacketQueueSize
--;
933 ASSERT (Instance
->RcvdPacketQueueSize
== 0);
935 gBS
->RestoreTPL (OldTpl
);
940 Configure the Instance using ConfigData.
942 @param Instance Pointer to the mnp instance context data.
943 @param ConfigData Pointer to the configuration data used to configure
946 @retval EFI_SUCCESS The Instance is configured.
947 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
948 implementation doesn't support it.
949 @retval Other Some error occurs.
953 MnpConfigureInstance (
954 IN MNP_INSTANCE_DATA
*Instance
,
955 IN EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData OPTIONAL
959 MNP_SERVICE_DATA
*MnpServiceData
;
960 EFI_MANAGED_NETWORK_CONFIG_DATA
*OldConfigData
;
961 EFI_MANAGED_NETWORK_CONFIG_DATA
*NewConfigData
;
962 BOOLEAN IsConfigUpdate
;
964 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
966 if ((ConfigData
!= NULL
) && ConfigData
->EnableReceiveTimestamps
) {
968 // Don't support timestamp.
970 return EFI_UNSUPPORTED
;
973 Status
= EFI_SUCCESS
;
975 MnpServiceData
= Instance
->MnpServiceData
;
976 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
978 IsConfigUpdate
= (BOOLEAN
) ((Instance
->Configured
) && (ConfigData
!= NULL
));
980 OldConfigData
= &Instance
->ConfigData
;
981 NewConfigData
= ConfigData
;
982 if (NewConfigData
== NULL
) {
984 // Restore back the default config data if a reset of this instance
987 NewConfigData
= &mMnpDefaultConfigData
;
991 // Reset the instance's receive filter.
993 Instance
->ReceiveFilter
= 0;
996 // Clear the receive counters according to the old ConfigData.
998 if (OldConfigData
->EnableUnicastReceive
) {
999 MnpServiceData
->UnicastCount
--;
1002 if (OldConfigData
->EnableMulticastReceive
) {
1003 MnpServiceData
->MulticastCount
--;
1006 if (OldConfigData
->EnableBroadcastReceive
) {
1007 MnpServiceData
->BroadcastCount
--;
1010 if (OldConfigData
->EnablePromiscuousReceive
) {
1011 MnpServiceData
->PromiscuousCount
--;
1015 // Set the receive filter counters and the receive filter of the
1016 // instance according to the new ConfigData.
1018 if (NewConfigData
->EnableUnicastReceive
) {
1019 MnpServiceData
->UnicastCount
++;
1020 Instance
->ReceiveFilter
|= MNP_RECEIVE_UNICAST
;
1023 if (NewConfigData
->EnableMulticastReceive
) {
1024 MnpServiceData
->MulticastCount
++;
1027 if (NewConfigData
->EnableBroadcastReceive
) {
1028 MnpServiceData
->BroadcastCount
++;
1029 Instance
->ReceiveFilter
|= MNP_RECEIVE_BROADCAST
;
1032 if (NewConfigData
->EnablePromiscuousReceive
) {
1033 MnpServiceData
->PromiscuousCount
++;
1036 if (OldConfigData
->FlushQueuesOnReset
) {
1038 MnpFlushRcvdDataQueue (Instance
);
1041 if (ConfigData
== NULL
) {
1043 Instance
->ManagedNetwork
.Cancel (&Instance
->ManagedNetwork
, NULL
);
1046 if (!NewConfigData
->EnableMulticastReceive
) {
1048 MnpGroupOp (Instance
, FALSE
, NULL
, NULL
);
1052 // Save the new configuration data.
1054 CopyMem (OldConfigData
, NewConfigData
, sizeof (*OldConfigData
));
1056 Instance
->Configured
= (BOOLEAN
) (ConfigData
!= NULL
);
1058 if (Instance
->Configured
) {
1060 // The instance is configured, start the Mnp.
1065 (BOOLEAN
) !NewConfigData
->DisableBackgroundPolling
1069 // The instance is changed to the unconfigured state, stop the Mnp.
1071 Status
= MnpStop (MnpServiceData
);
1079 Configure the Snp receive filters according to the instances' receive filter
1082 @param MnpServiceData Pointer to the mnp service context data.
1084 @retval EFI_SUCCESS The receive filters is configured.
1085 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due to lack
1091 MnpConfigReceiveFilters (
1092 IN MNP_SERVICE_DATA
*MnpServiceData
1096 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1097 EFI_MAC_ADDRESS
*MCastFilter
;
1098 UINT32 MCastFilterCnt
;
1099 UINT32 EnableFilterBits
;
1100 UINT32 DisableFilterBits
;
1101 BOOLEAN ResetMCastFilters
;
1104 MNP_GROUP_ADDRESS
*GroupAddress
;
1106 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1108 Snp
= MnpServiceData
->Snp
;
1111 // Initialize the enable filter and disable filter.
1113 EnableFilterBits
= 0;
1114 DisableFilterBits
= Snp
->Mode
->ReceiveFilterMask
;
1116 if (MnpServiceData
->UnicastCount
!= 0) {
1118 // Enable unicast if any instance wants to receive unicast.
1120 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1123 if (MnpServiceData
->BroadcastCount
!= 0) {
1125 // Enable broadcast if any instance wants to receive broadcast.
1127 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1132 ResetMCastFilters
= TRUE
;
1134 if ((MnpServiceData
->MulticastCount
!= 0) && (MnpServiceData
->GroupAddressCount
!= 0)) {
1136 // There are instances configured to receive multicast and already some group
1137 // addresses are joined.
1140 ResetMCastFilters
= FALSE
;
1142 if (MnpServiceData
->GroupAddressCount
<= Snp
->Mode
->MaxMCastFilterCount
) {
1144 // The joind group address is less than simple network's maximum count.
1145 // Just configure the snp to do the multicast filtering.
1148 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1151 // Allocate pool for the mulicast addresses.
1153 MCastFilterCnt
= MnpServiceData
->GroupAddressCount
;
1154 MCastFilter
= AllocatePool (sizeof (EFI_MAC_ADDRESS
) * MCastFilterCnt
);
1155 if (MCastFilter
== NULL
) {
1157 DEBUG ((EFI_D_ERROR
, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1158 return EFI_OUT_OF_RESOURCES
;
1162 // Fill the multicast HW address buffer.
1165 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
1167 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1168 CopyMem (MCastFilter
+ Index
, &GroupAddress
->Address
, sizeof (*(MCastFilter
+ Index
)));
1171 ASSERT (Index
<= MCastFilterCnt
);
1175 // The maximum multicast is reached, set the filter to be promiscuous
1179 if (Snp
->Mode
->ReceiveFilterMask
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
1180 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1183 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1184 // set the NIC to be promiscuous although this will tremendously degrade
1187 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1192 if (MnpServiceData
->PromiscuousCount
!= 0) {
1194 // Enable promiscuous if any instance wants to receive promiscuous.
1196 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1200 // Set the disable filter.
1202 DisableFilterBits
^= EnableFilterBits
;
1205 // Configure the receive filters of SNP.
1207 Status
= Snp
->ReceiveFilters (
1216 if (EFI_ERROR (Status
)) {
1220 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1226 if (MCastFilter
!= NULL
) {
1228 // Free the buffer used to hold the group addresses.
1230 gBS
->FreePool (MCastFilter
);
1238 Add a group address control block which controls the MacAddress for
1241 @param Instance Pointer to the mnp instance context data.
1242 @param CtrlBlk Pointer to the group address control block.
1243 @param GroupAddress Pointer to the group adress.
1244 @param MacAddress Pointer to the mac address.
1245 @param HwAddressSize The hardware address size.
1247 @retval EFI_SUCCESS The group address control block is added.
1248 @retval EFI_OUT_OF_RESOURCE Failed due to lack of memory resources.
1253 MnpGroupOpAddCtrlBlk (
1254 IN MNP_INSTANCE_DATA
*Instance
,
1255 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
1256 IN MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
1257 IN EFI_MAC_ADDRESS
*MacAddress
,
1258 IN UINT32 HwAddressSize
1261 MNP_SERVICE_DATA
*MnpServiceData
;
1263 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1265 MnpServiceData
= Instance
->MnpServiceData
;
1266 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1268 if (GroupAddress
== NULL
) {
1270 ASSERT (MacAddress
!= NULL
);
1273 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1275 GroupAddress
= AllocatePool (sizeof (MNP_GROUP_ADDRESS
));
1276 if (GroupAddress
== NULL
) {
1278 DEBUG ((EFI_D_ERROR
, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1280 return EFI_OUT_OF_RESOURCES
;
1283 CopyMem (&GroupAddress
->Address
, MacAddress
, sizeof (GroupAddress
->Address
));
1284 GroupAddress
->RefCnt
= 0;
1286 &MnpServiceData
->GroupAddressList
,
1287 &GroupAddress
->AddrEntry
1289 MnpServiceData
->GroupAddressCount
++;
1293 // Increase the RefCnt.
1295 GroupAddress
->RefCnt
++;
1298 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1300 CtrlBlk
->GroupAddress
= GroupAddress
;
1301 InsertTailList (&Instance
->GroupCtrlBlkList
, &CtrlBlk
->CtrlBlkEntry
);
1308 Delete a group control block from the instance. If the controlled group address's
1309 reference count reaches zero, the group address is removed too.
1311 @param Instance Pointer to the instance context data.
1312 @param CtrlBlk Pointer to the group control block to delete.
1314 @return The group address controlled by the control block is no longer used or not.
1319 MnpGroupOpDelCtrlBlk (
1320 IN MNP_INSTANCE_DATA
*Instance
,
1321 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
1324 MNP_SERVICE_DATA
*MnpServiceData
;
1325 MNP_GROUP_ADDRESS
*GroupAddress
;
1327 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1329 MnpServiceData
= Instance
->MnpServiceData
;
1330 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1333 // Remove and free the CtrlBlk.
1335 GroupAddress
= CtrlBlk
->GroupAddress
;
1336 RemoveEntryList (&CtrlBlk
->CtrlBlkEntry
);
1337 gBS
->FreePool (CtrlBlk
);
1339 ASSERT (GroupAddress
->RefCnt
> 0);
1342 // Count down the RefCnt.
1344 GroupAddress
->RefCnt
--;
1346 if (GroupAddress
->RefCnt
== 0) {
1348 // Free this GroupAddress entry if no instance uses it.
1350 MnpServiceData
->GroupAddressCount
--;
1351 RemoveEntryList (&GroupAddress
->AddrEntry
);
1352 gBS
->FreePool (GroupAddress
);
1362 Do the group operations for this instance.
1364 @param Instance Pointer to the instance context data.
1365 @param JoinFlag Set to TRUE to join a group. Set to TRUE to leave a
1367 @param MacAddress Pointer to the group address to join or leave.
1368 @param CtrlBlk Pointer to the group control block if JoinFlag if
1371 @retval EFI_SUCCESS The group operation finished.
1372 @retval Other Some error occurs.
1377 IN MNP_INSTANCE_DATA
*Instance
,
1378 IN BOOLEAN JoinFlag
,
1379 IN EFI_MAC_ADDRESS
*MacAddress OPTIONAL
,
1380 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk OPTIONAL
1383 MNP_SERVICE_DATA
*MnpServiceData
;
1385 LIST_ENTRY
*NextEntry
;
1386 MNP_GROUP_ADDRESS
*GroupAddress
;
1387 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1388 MNP_GROUP_CONTROL_BLOCK
*NewCtrlBlk
;
1390 BOOLEAN AddressExist
;
1393 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1395 MnpServiceData
= Instance
->MnpServiceData
;
1396 SnpMode
= MnpServiceData
->Snp
->Mode
;
1400 // A new gropu address is to be added.
1403 GroupAddress
= NULL
;
1404 AddressExist
= FALSE
;
1407 // Allocate memory for the control block.
1409 NewCtrlBlk
= AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK
));
1410 if (NewCtrlBlk
== NULL
) {
1412 DEBUG ((EFI_D_ERROR
, "MnpGroupOp: Failed to allocate memory resource.\n"));
1413 return EFI_OUT_OF_RESOURCES
;
1416 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
1418 // Check whether the MacAddress is already joined by other instances.
1420 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1421 if (0 == CompareMem (
1423 &GroupAddress
->Address
,
1424 SnpMode
->HwAddressSize
1427 AddressExist
= TRUE
;
1432 if (!AddressExist
) {
1433 GroupAddress
= NULL
;
1437 // Add the GroupAddress for this instance.
1439 Status
= MnpGroupOpAddCtrlBlk (
1444 SnpMode
->HwAddressSize
1446 if (EFI_ERROR (Status
)) {
1454 if (MacAddress
!= NULL
) {
1456 ASSERT (CtrlBlk
!= NULL
);
1459 // Leave the specific multicast mac address.
1461 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, CtrlBlk
);
1464 // Leave all multicast mac addresses.
1468 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Instance
->GroupCtrlBlkList
) {
1470 NewCtrlBlk
= NET_LIST_USER_STRUCT (
1472 MNP_GROUP_CONTROL_BLOCK
,
1476 // Update is required if the group address left is no longer used
1477 // by other instances.
1479 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, NewCtrlBlk
);
1484 Status
= EFI_SUCCESS
;
1488 // Reconfigure the receive filters if necessary.
1490 Status
= MnpConfigReceiveFilters (MnpServiceData
);