2 Implementation of Managed Network Protocol private services.
4 Copyright (c) 2005 - 2008, Intel Corporation. <BR>
5 All rights reserved. This program and the accompanying materials are licensed
6 and made available under the terms and conditions of the BSD License which
7 accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol
= {
19 MnpServiceBindingCreateChild
,
20 MnpServiceBindingDestroyChild
23 EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate
= {
34 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData
= {
48 Configure the Snp receive filters according to the instances' receive filter
51 @param MnpServiceData Pointer to the mnp service context data.
53 @retval EFI_SUCCESS The receive filters is configured.
54 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due to
55 lack of memory resource.
59 MnpConfigReceiveFilters (
60 IN MNP_SERVICE_DATA
*MnpServiceData
64 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
65 EFI_MAC_ADDRESS
*MCastFilter
;
66 UINT32 MCastFilterCnt
;
67 UINT32 EnableFilterBits
;
68 UINT32 DisableFilterBits
;
69 BOOLEAN ResetMCastFilters
;
72 MNP_GROUP_ADDRESS
*GroupAddress
;
74 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
76 Snp
= MnpServiceData
->Snp
;
79 // Initialize the enable filter and disable filter.
82 DisableFilterBits
= Snp
->Mode
->ReceiveFilterMask
;
84 if (MnpServiceData
->UnicastCount
!= 0) {
86 // Enable unicast if any instance wants to receive unicast.
88 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
91 if (MnpServiceData
->BroadcastCount
!= 0) {
93 // Enable broadcast if any instance wants to receive broadcast.
95 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
100 ResetMCastFilters
= TRUE
;
102 if ((MnpServiceData
->MulticastCount
!= 0) && (MnpServiceData
->GroupAddressCount
!= 0)) {
104 // There are instances configured to receive multicast and already some group
105 // addresses are joined.
108 ResetMCastFilters
= FALSE
;
110 if (MnpServiceData
->GroupAddressCount
<= Snp
->Mode
->MaxMCastFilterCount
) {
112 // The joind group address is less than simple network's maximum count.
113 // Just configure the snp to do the multicast filtering.
116 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
119 // Allocate pool for the mulicast addresses.
121 MCastFilterCnt
= MnpServiceData
->GroupAddressCount
;
122 MCastFilter
= AllocatePool (sizeof (EFI_MAC_ADDRESS
) * MCastFilterCnt
);
123 if (MCastFilter
== NULL
) {
125 DEBUG ((EFI_D_ERROR
, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
126 return EFI_OUT_OF_RESOURCES
;
130 // Fill the multicast HW address buffer.
133 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
135 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
136 CopyMem (MCastFilter
+ Index
, &GroupAddress
->Address
, sizeof (*(MCastFilter
+ Index
)));
139 ASSERT (Index
<= MCastFilterCnt
);
143 // The maximum multicast is reached, set the filter to be promiscuous
147 if (Snp
->Mode
->ReceiveFilterMask
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
148 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
151 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
152 // set the NIC to be promiscuous although this will tremendously degrade
155 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
160 if (MnpServiceData
->PromiscuousCount
!= 0) {
162 // Enable promiscuous if any instance wants to receive promiscuous.
164 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
168 // Set the disable filter.
170 DisableFilterBits
^= EnableFilterBits
;
173 // Configure the receive filters of SNP.
175 Status
= Snp
->ReceiveFilters (
184 if (EFI_ERROR (Status
)) {
188 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
194 if (MCastFilter
!= NULL
) {
196 // Free the buffer used to hold the group addresses.
198 gBS
->FreePool (MCastFilter
);
205 Add Count of net buffers to MnpServiceData->FreeNbufQue. The length of the net
206 buffer is specified by MnpServiceData->BufferLength.
208 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
209 @param Count Number of NET_BUFFERs to add.
211 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated
212 and added to MnpServiceData->FreeNbufQue.
213 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.
218 IN MNP_SERVICE_DATA
*MnpServiceData
,
226 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
227 ASSERT ((Count
> 0) && (MnpServiceData
->BufferLength
> 0));
229 Status
= EFI_SUCCESS
;
231 for (Index
= 0; Index
< Count
; Index
++) {
233 Nbuf
= NetbufAlloc (MnpServiceData
->BufferLength
+ MnpServiceData
->PaddingSize
);
236 DEBUG ((EFI_D_ERROR
, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));
237 Status
= EFI_OUT_OF_RESOURCES
;
241 if (MnpServiceData
->PaddingSize
> 0) {
243 // Pad padding bytes before the media header
245 NetbufAllocSpace (Nbuf
, MnpServiceData
->PaddingSize
, NET_BUF_TAIL
);
246 NetbufTrim (Nbuf
, MnpServiceData
->PaddingSize
, NET_BUF_HEAD
);
249 NetbufQueAppend (&MnpServiceData
->FreeNbufQue
, Nbuf
);
252 MnpServiceData
->NbufCnt
+= Index
;
259 Allocate a free NET_BUF from MnpServiceData->FreeNbufQue. If there is none
260 in the queue, first try to allocate some and add them into the queue, then
261 fetch the NET_BUF from the updated FreeNbufQue.
263 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
265 @return Pointer to the allocated free NET_BUF structure, if NULL the
271 IN MNP_SERVICE_DATA
*MnpServiceData
275 NET_BUF_QUEUE
*FreeNbufQue
;
279 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
281 FreeNbufQue
= &MnpServiceData
->FreeNbufQue
;
283 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
286 // Check whether there are available buffers, or else try to add some.
288 if (FreeNbufQue
->BufNum
== 0) {
290 if ((MnpServiceData
->NbufCnt
+ MNP_NET_BUFFER_INCREASEMENT
) > MNP_MAX_NET_BUFFER_NUM
) {
294 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
302 Status
= MnpAddFreeNbuf (MnpServiceData
, MNP_NET_BUFFER_INCREASEMENT
);
303 if (EFI_ERROR (Status
)) {
307 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
311 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
312 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
317 Nbuf
= NetbufQueRemove (FreeNbufQue
);
320 // Increase the RefCnt.
327 gBS
->RestoreTPL (OldTpl
);
334 Try to reclaim the Nbuf into the buffer pool.
336 @param MnpServiceData Pointer to the mnp service context data.
337 @param Nbuf Pointer to the NET_BUF to free.
342 IN MNP_SERVICE_DATA
*MnpServiceData
,
348 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
349 ASSERT (Nbuf
->RefCnt
> 1);
351 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
355 if (Nbuf
->RefCnt
== 1) {
357 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
359 NetbufTrim (Nbuf
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
360 NetbufQueAppend (&MnpServiceData
->FreeNbufQue
, Nbuf
);
363 gBS
->RestoreTPL (OldTpl
);
368 Initialize the mnp service context data.
370 @param MnpServiceData Pointer to the mnp service context data.
371 @param ImageHandle The driver image handle.
372 @param ControllerHandle Handle of device to bind driver to.
374 @retval EFI_SUCCESS The mnp service context is initialized.
375 @retval Other Some error occurs.
379 MnpInitializeServiceData (
380 IN MNP_SERVICE_DATA
*MnpServiceData
,
381 IN EFI_HANDLE ImageHandle
,
382 IN EFI_HANDLE ControllerHandle
386 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
387 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
389 MnpServiceData
->Signature
= MNP_SERVICE_DATA_SIGNATURE
;
391 MnpServiceData
->ControllerHandle
= ControllerHandle
;
394 // Copy the ServiceBinding structure.
396 MnpServiceData
->ServiceBinding
= mMnpServiceBindingProtocol
;
399 // Open the Simple Network protocol.
401 Status
= gBS
->OpenProtocol (
403 &gEfiSimpleNetworkProtocolGuid
,
407 EFI_OPEN_PROTOCOL_BY_DRIVER
409 if (EFI_ERROR (Status
)) {
410 return EFI_UNSUPPORTED
;
417 MnpServiceData
->Snp
= Snp
;
418 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
;
421 // Initialize the lists.
423 InitializeListHead (&MnpServiceData
->GroupAddressList
);
424 InitializeListHead (&MnpServiceData
->ChildrenList
);
427 // Get the buffer length used to allocate NET_BUF to hold data received
428 // from SNP. Do this before fill the FreeNetBufQue.
430 MnpServiceData
->BufferLength
= MnpServiceData
->Mtu
+ SnpMode
->MediaHeaderSize
+ NET_ETHER_FCS_SIZE
;
433 // Make sure the protocol headers immediately following the media header
436 MnpServiceData
->PaddingSize
= (4 - SnpMode
->MediaHeaderSize
) & 0x3;
439 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
441 NetbufQueInit (&MnpServiceData
->FreeNbufQue
);
442 Status
= MnpAddFreeNbuf (MnpServiceData
, MNP_INIT_NET_BUFFER_NUM
);
443 if (EFI_ERROR (Status
)) {
445 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status
));
449 // Get one NET_BUF from the FreeNbufQue for rx cache.
451 MnpServiceData
->RxNbufCache
= MnpAllocNbuf (MnpServiceData
);
453 MnpServiceData
->RxNbufCache
,
454 MnpServiceData
->BufferLength
,
459 // Allocate buffer pool for tx.
461 MnpServiceData
->TxBuf
= AllocatePool (MnpServiceData
->Mtu
+ SnpMode
->MediaHeaderSize
);
462 if (MnpServiceData
->TxBuf
== NULL
) {
464 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: AllocatePool failed.\n"));
465 Status
= EFI_OUT_OF_RESOURCES
;
471 // Create the system poll timer.
473 Status
= gBS
->CreateEvent (
474 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
478 &MnpServiceData
->PollTimer
480 if (EFI_ERROR (Status
)) {
482 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));
487 // Create the timer for packet timeout check.
489 Status
= gBS
->CreateEvent (
490 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
492 MnpCheckPacketTimeout
,
494 &MnpServiceData
->TimeoutCheckTimer
496 if (EFI_ERROR (Status
)) {
498 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));
503 // Create the timer for tx timeout check.
505 Status
= gBS
->CreateEvent (
510 &MnpServiceData
->TxTimeoutEvent
512 if (EFI_ERROR (Status
)) {
514 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));
519 if (EFI_ERROR (Status
)) {
521 // Free the dynamic allocated resources if necessary.
523 if (MnpServiceData
->TimeoutCheckTimer
!= NULL
) {
525 gBS
->CloseEvent (MnpServiceData
->TimeoutCheckTimer
);
528 if (MnpServiceData
->PollTimer
!= NULL
) {
530 gBS
->CloseEvent (MnpServiceData
->PollTimer
);
533 if (MnpServiceData
->TxBuf
!= NULL
) {
535 gBS
->FreePool (MnpServiceData
->TxBuf
);
538 if (MnpServiceData
->RxNbufCache
!= NULL
) {
540 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
543 if (MnpServiceData
->FreeNbufQue
.BufNum
!= 0) {
545 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
554 Flush the mnp service context data.
556 @param MnpServiceData Pointer to the mnp service context data.
557 @param ImageHandle The driver image handle.
561 MnpFlushServiceData (
562 IN MNP_SERVICE_DATA
*MnpServiceData
,
563 IN EFI_HANDLE ImageHandle
566 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
569 // The GroupAddressList must be empty.
571 ASSERT (IsListEmpty (&MnpServiceData
->GroupAddressList
));
576 gBS
->CloseEvent (&MnpServiceData
->TxTimeoutEvent
);
577 gBS
->CloseEvent (&MnpServiceData
->TimeoutCheckTimer
);
578 gBS
->CloseEvent (&MnpServiceData
->PollTimer
);
581 // Free the tx buffer.
583 gBS
->FreePool (MnpServiceData
->TxBuf
);
586 // Free the RxNbufCache.
588 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
591 // Flush the FreeNbufQue.
593 MnpServiceData
->NbufCnt
-= MnpServiceData
->FreeNbufQue
.BufNum
;
594 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
598 if (MnpServiceData
->NbufCnt
!= 0) {
600 DEBUG ((EFI_D_WARN
, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));
605 // Close the Simple Network Protocol.
608 MnpServiceData
->ControllerHandle
,
609 &gEfiSimpleNetworkProtocolGuid
,
611 MnpServiceData
->ControllerHandle
617 Initialize the mnp instance context data.
619 @param MnpServiceData Pointer to the mnp service context data.
620 @param Instance Pointer to the mnp instance context data to
625 MnpInitializeInstanceData (
626 IN MNP_SERVICE_DATA
*MnpServiceData
,
627 IN MNP_INSTANCE_DATA
*Instance
630 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
631 ASSERT (Instance
!= NULL
);
634 // Set the signature.
636 Instance
->Signature
= MNP_INSTANCE_DATA_SIGNATURE
;
639 // Copy the MNP Protocol interfaces from the template.
641 CopyMem (&Instance
->ManagedNetwork
, &mMnpProtocolTemplate
, sizeof (Instance
->ManagedNetwork
));
644 // Copy the default config data.
646 CopyMem (&Instance
->ConfigData
, &mMnpDefaultConfigData
, sizeof (Instance
->ConfigData
));
649 // Initialize the lists.
651 InitializeListHead (&Instance
->GroupCtrlBlkList
);
652 InitializeListHead (&Instance
->RcvdPacketQueue
);
653 InitializeListHead (&Instance
->RxDeliveredPacketQueue
);
656 // Initialize the RxToken Map.
658 NetMapInit (&Instance
->RxTokenMap
);
661 // Save the MnpServiceData info.
663 Instance
->MnpServiceData
= MnpServiceData
;
668 Check whether the token specified by Arg maches the token in Item.
670 @param Map Pointer to the NET_MAP.
671 @param Item Pointer to the NET_MAP_ITEM
672 @param Arg Pointer to the Arg, it's a pointer to the token to
675 @retval EFI_SUCCESS The token specified by Arg is different from the
677 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
684 IN NET_MAP_ITEM
*Item
,
688 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
;
689 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenInItem
;
691 Token
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Arg
;
692 TokenInItem
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
694 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
696 // The token is the same either the two tokens equals or the Events in
697 // the two tokens are the same.
699 return EFI_ACCESS_DENIED
;
706 Cancel the token specified by Arg if it matches the token in Item.
708 @param Map Pointer to the NET_MAP.
709 @param Item Pointer to the NET_MAP_ITEM
710 @param Arg Pointer to the Arg, it's a pointer to the token to
713 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,
714 or the Arg isn't NULL, and the token in Item is
715 different from the Arg.
716 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
717 Arg, and the token is cancelled.
723 IN NET_MAP_ITEM
*Item
,
727 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenToCancel
;
729 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
731 // The token in Item is not the token specified by Arg.
736 TokenToCancel
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
739 // Remove the item from the map.
741 NetMapRemoveItem (Map
, Item
, NULL
);
744 // Cancel this token with status set to EFI_ABORTED.
746 TokenToCancel
->Status
= EFI_ABORTED
;
747 gBS
->SignalEvent (TokenToCancel
->Event
);
751 // Only abort the token specified by Arg if Arg isn't NULL.
761 Start and initialize the simple network.
763 @param Snp Pointer to the simple network protocol.
765 @retval EFI_SUCCESS The simple network protocol is started.
766 @retval Other Some error occurs.
771 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
776 ASSERT (Snp
!= NULL
);
779 // Start the simple network.
781 Status
= Snp
->Start (Snp
);
783 if (!EFI_ERROR (Status
)) {
785 // Initialize the simple network.
787 Status
= Snp
->Initialize (Snp
, 0, 0);
795 Stop the simple network.
797 @param Snp Pointer to the simple network protocol.
799 @retval EFI_SUCCESS The simple network is stopped.
800 @retval Other Some error occurs.
805 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
810 ASSERT (Snp
!= NULL
);
813 // Shut down the simple network.
815 Status
= Snp
->Shutdown (Snp
);
817 if (!EFI_ERROR (Status
)) {
819 // Stop the simple network.
821 Status
= Snp
->Stop (Snp
);
829 Start the managed network, this function is called when one instance is configured
832 @param MnpServiceData Pointer to the mnp service context data.
833 @param IsConfigUpdate The instance is reconfigured or it's the first time
834 the instanced is configured.
835 @param EnableSystemPoll Enable the system polling or not.
837 @retval EFI_SUCCESS The managed network is started and some
838 configuration is updated.
839 @retval Other Some error occurs.
844 IN MNP_SERVICE_DATA
*MnpServiceData
,
845 IN BOOLEAN IsConfigUpdate
,
846 IN BOOLEAN EnableSystemPoll
850 EFI_TIMER_DELAY TimerOpType
;
852 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
854 Status
= EFI_SUCCESS
;
856 if (!IsConfigUpdate
) {
858 // If it's not a configuration update, increase the configured children number.
860 MnpServiceData
->ConfiguredChildrenNumber
++;
862 if (MnpServiceData
->ConfiguredChildrenNumber
== 1) {
864 // It's the first configured child, start the simple network.
866 Status
= MnpStartSnp (MnpServiceData
->Snp
);
867 if (EFI_ERROR (Status
)) {
869 DEBUG ((EFI_D_ERROR
, "MnpStart: MnpStartSnp failed, %r.\n", Status
));
874 // Start the timeout timer.
876 Status
= gBS
->SetTimer (
877 MnpServiceData
->TimeoutCheckTimer
,
879 MNP_TIMEOUT_CHECK_INTERVAL
881 if (EFI_ERROR (Status
)) {
885 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
893 if (MnpServiceData
->EnableSystemPoll
^ EnableSystemPoll
) {
895 // The EnableSystemPoll differs with the current state, disable or enable
898 TimerOpType
= EnableSystemPoll
? TimerPeriodic
: TimerCancel
;
900 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerOpType
, MNP_SYS_POLL_INTERVAL
);
901 if (EFI_ERROR (Status
)) {
903 DEBUG ((EFI_D_ERROR
, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status
));
907 MnpServiceData
->EnableSystemPoll
= EnableSystemPoll
;
911 // Change the receive filters if need.
913 Status
= MnpConfigReceiveFilters (MnpServiceData
);
922 Stop the managed network.
924 @param MnpServiceData Pointer to the mnp service context data.
926 @retval EFI_SUCCESS The managed network is stopped.
927 @retval Other Some error occurs.
932 IN MNP_SERVICE_DATA
*MnpServiceData
937 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
938 ASSERT (MnpServiceData
->ConfiguredChildrenNumber
> 0);
941 // Configure the receive filters.
943 MnpConfigReceiveFilters (MnpServiceData
);
946 // Decrease the children number.
948 MnpServiceData
->ConfiguredChildrenNumber
--;
950 if (MnpServiceData
->ConfiguredChildrenNumber
> 0) {
952 // If there are other configured chilren, return and keep the timers and
953 // simple network unchanged.
959 // No configured children now.
962 if (MnpServiceData
->EnableSystemPoll
) {
964 // The system poll in on, cancel the poll timer.
966 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerCancel
, 0);
967 MnpServiceData
->EnableSystemPoll
= FALSE
;
971 // Cancel the timeout timer.
973 Status
= gBS
->SetTimer (MnpServiceData
->TimeoutCheckTimer
, TimerCancel
, 0);
976 // Stop the simple network.
978 Status
= MnpStopSnp (MnpServiceData
->Snp
);
985 Flush the instance's received data.
987 @param Instance Pointer to the mnp instance context data.
991 MnpFlushRcvdDataQueue (
992 IN MNP_INSTANCE_DATA
*Instance
996 MNP_RXDATA_WRAP
*RxDataWrap
;
998 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1000 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1002 while (!IsListEmpty (&Instance
->RcvdPacketQueue
)) {
1004 // Remove all the Wraps.
1006 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
1009 // Recycle the RxDataWrap.
1011 MnpRecycleRxData (NULL
, (VOID
*) RxDataWrap
);
1012 Instance
->RcvdPacketQueueSize
--;
1015 ASSERT (Instance
->RcvdPacketQueueSize
== 0);
1017 gBS
->RestoreTPL (OldTpl
);
1022 Configure the Instance using ConfigData.
1024 @param Instance Pointer to the mnp instance context data.
1025 @param ConfigData Pointer to the configuration data used to configure
1028 @retval EFI_SUCCESS The Instance is configured.
1029 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1030 implementation doesn't support it.
1031 @retval Other Some error occurs.
1035 MnpConfigureInstance (
1036 IN MNP_INSTANCE_DATA
*Instance
,
1037 IN EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData OPTIONAL
1041 MNP_SERVICE_DATA
*MnpServiceData
;
1042 EFI_MANAGED_NETWORK_CONFIG_DATA
*OldConfigData
;
1043 EFI_MANAGED_NETWORK_CONFIG_DATA
*NewConfigData
;
1044 BOOLEAN IsConfigUpdate
;
1046 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1048 if ((ConfigData
!= NULL
) && ConfigData
->EnableReceiveTimestamps
) {
1050 // Don't support timestamp.
1052 return EFI_UNSUPPORTED
;
1055 Status
= EFI_SUCCESS
;
1057 MnpServiceData
= Instance
->MnpServiceData
;
1058 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1060 IsConfigUpdate
= (BOOLEAN
) ((Instance
->Configured
) && (ConfigData
!= NULL
));
1062 OldConfigData
= &Instance
->ConfigData
;
1063 NewConfigData
= ConfigData
;
1064 if (NewConfigData
== NULL
) {
1066 // Restore back the default config data if a reset of this instance
1069 NewConfigData
= &mMnpDefaultConfigData
;
1073 // Reset the instance's receive filter.
1075 Instance
->ReceiveFilter
= 0;
1078 // Clear the receive counters according to the old ConfigData.
1080 if (OldConfigData
->EnableUnicastReceive
) {
1081 MnpServiceData
->UnicastCount
--;
1084 if (OldConfigData
->EnableMulticastReceive
) {
1085 MnpServiceData
->MulticastCount
--;
1088 if (OldConfigData
->EnableBroadcastReceive
) {
1089 MnpServiceData
->BroadcastCount
--;
1092 if (OldConfigData
->EnablePromiscuousReceive
) {
1093 MnpServiceData
->PromiscuousCount
--;
1097 // Set the receive filter counters and the receive filter of the
1098 // instance according to the new ConfigData.
1100 if (NewConfigData
->EnableUnicastReceive
) {
1101 MnpServiceData
->UnicastCount
++;
1102 Instance
->ReceiveFilter
|= MNP_RECEIVE_UNICAST
;
1105 if (NewConfigData
->EnableMulticastReceive
) {
1106 MnpServiceData
->MulticastCount
++;
1109 if (NewConfigData
->EnableBroadcastReceive
) {
1110 MnpServiceData
->BroadcastCount
++;
1111 Instance
->ReceiveFilter
|= MNP_RECEIVE_BROADCAST
;
1114 if (NewConfigData
->EnablePromiscuousReceive
) {
1115 MnpServiceData
->PromiscuousCount
++;
1118 if (OldConfigData
->FlushQueuesOnReset
) {
1120 MnpFlushRcvdDataQueue (Instance
);
1123 if (ConfigData
== NULL
) {
1125 Instance
->ManagedNetwork
.Cancel (&Instance
->ManagedNetwork
, NULL
);
1128 if (!NewConfigData
->EnableMulticastReceive
) {
1130 MnpGroupOp (Instance
, FALSE
, NULL
, NULL
);
1134 // Save the new configuration data.
1136 CopyMem (OldConfigData
, NewConfigData
, sizeof (*OldConfigData
));
1138 Instance
->Configured
= (BOOLEAN
) (ConfigData
!= NULL
);
1140 if (Instance
->Configured
) {
1142 // The instance is configured, start the Mnp.
1147 (BOOLEAN
) !NewConfigData
->DisableBackgroundPolling
1151 // The instance is changed to the unconfigured state, stop the Mnp.
1153 Status
= MnpStop (MnpServiceData
);
1162 Add a group address control block which controls the MacAddress for
1165 @param Instance Pointer to the mnp instance context data.
1166 @param CtrlBlk Pointer to the group address control block.
1167 @param GroupAddress Pointer to the group adress.
1168 @param MacAddress Pointer to the mac address.
1169 @param HwAddressSize The hardware address size.
1171 @retval EFI_SUCCESS The group address control block is added.
1172 @retval EFI_OUT_OF_RESOURCE Failed due to lack of memory resources.
1176 MnpGroupOpAddCtrlBlk (
1177 IN MNP_INSTANCE_DATA
*Instance
,
1178 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
1179 IN MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
1180 IN EFI_MAC_ADDRESS
*MacAddress
,
1181 IN UINT32 HwAddressSize
1184 MNP_SERVICE_DATA
*MnpServiceData
;
1186 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1188 MnpServiceData
= Instance
->MnpServiceData
;
1189 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1191 if (GroupAddress
== NULL
) {
1193 ASSERT (MacAddress
!= NULL
);
1196 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1198 GroupAddress
= AllocatePool (sizeof (MNP_GROUP_ADDRESS
));
1199 if (GroupAddress
== NULL
) {
1201 DEBUG ((EFI_D_ERROR
, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1203 return EFI_OUT_OF_RESOURCES
;
1206 CopyMem (&GroupAddress
->Address
, MacAddress
, sizeof (GroupAddress
->Address
));
1207 GroupAddress
->RefCnt
= 0;
1209 &MnpServiceData
->GroupAddressList
,
1210 &GroupAddress
->AddrEntry
1212 MnpServiceData
->GroupAddressCount
++;
1216 // Increase the RefCnt.
1218 GroupAddress
->RefCnt
++;
1221 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1223 CtrlBlk
->GroupAddress
= GroupAddress
;
1224 InsertTailList (&Instance
->GroupCtrlBlkList
, &CtrlBlk
->CtrlBlkEntry
);
1231 Delete a group control block from the instance. If the controlled group address's
1232 reference count reaches zero, the group address is removed too.
1234 @param Instance Pointer to the instance context data.
1235 @param CtrlBlk Pointer to the group control block to delete.
1237 @return The group address controlled by the control block is no longer used or not.
1241 MnpGroupOpDelCtrlBlk (
1242 IN MNP_INSTANCE_DATA
*Instance
,
1243 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
1246 MNP_SERVICE_DATA
*MnpServiceData
;
1247 MNP_GROUP_ADDRESS
*GroupAddress
;
1249 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1251 MnpServiceData
= Instance
->MnpServiceData
;
1252 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1255 // Remove and free the CtrlBlk.
1257 GroupAddress
= CtrlBlk
->GroupAddress
;
1258 RemoveEntryList (&CtrlBlk
->CtrlBlkEntry
);
1259 gBS
->FreePool (CtrlBlk
);
1261 ASSERT (GroupAddress
->RefCnt
> 0);
1264 // Count down the RefCnt.
1266 GroupAddress
->RefCnt
--;
1268 if (GroupAddress
->RefCnt
== 0) {
1270 // Free this GroupAddress entry if no instance uses it.
1272 MnpServiceData
->GroupAddressCount
--;
1273 RemoveEntryList (&GroupAddress
->AddrEntry
);
1274 gBS
->FreePool (GroupAddress
);
1284 Do the group operations for this instance.
1286 @param Instance Pointer to the instance context data.
1287 @param JoinFlag Set to TRUE to join a group. Set to TRUE to leave a
1289 @param MacAddress Pointer to the group address to join or leave.
1290 @param CtrlBlk Pointer to the group control block if JoinFlag if
1293 @retval EFI_SUCCESS The group operation finished.
1294 @retval Other Some error occurs.
1299 IN MNP_INSTANCE_DATA
*Instance
,
1300 IN BOOLEAN JoinFlag
,
1301 IN EFI_MAC_ADDRESS
*MacAddress OPTIONAL
,
1302 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk OPTIONAL
1305 MNP_SERVICE_DATA
*MnpServiceData
;
1307 LIST_ENTRY
*NextEntry
;
1308 MNP_GROUP_ADDRESS
*GroupAddress
;
1309 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1310 MNP_GROUP_CONTROL_BLOCK
*NewCtrlBlk
;
1312 BOOLEAN AddressExist
;
1315 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1317 MnpServiceData
= Instance
->MnpServiceData
;
1318 SnpMode
= MnpServiceData
->Snp
->Mode
;
1322 // A new gropu address is to be added.
1325 GroupAddress
= NULL
;
1326 AddressExist
= FALSE
;
1329 // Allocate memory for the control block.
1331 NewCtrlBlk
= AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK
));
1332 if (NewCtrlBlk
== NULL
) {
1334 DEBUG ((EFI_D_ERROR
, "MnpGroupOp: Failed to allocate memory resource.\n"));
1335 return EFI_OUT_OF_RESOURCES
;
1338 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
1340 // Check whether the MacAddress is already joined by other instances.
1342 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1343 if (0 == CompareMem (
1345 &GroupAddress
->Address
,
1346 SnpMode
->HwAddressSize
1349 AddressExist
= TRUE
;
1354 if (!AddressExist
) {
1355 GroupAddress
= NULL
;
1359 // Add the GroupAddress for this instance.
1361 Status
= MnpGroupOpAddCtrlBlk (
1366 SnpMode
->HwAddressSize
1368 if (EFI_ERROR (Status
)) {
1376 if (MacAddress
!= NULL
) {
1378 ASSERT (CtrlBlk
!= NULL
);
1381 // Leave the specific multicast mac address.
1383 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, CtrlBlk
);
1386 // Leave all multicast mac addresses.
1390 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Instance
->GroupCtrlBlkList
) {
1392 NewCtrlBlk
= NET_LIST_USER_STRUCT (
1394 MNP_GROUP_CONTROL_BLOCK
,
1398 // Update is required if the group address left is no longer used
1399 // by other instances.
1401 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, NewCtrlBlk
);
1406 Status
= EFI_SUCCESS
;
1410 // Reconfigure the receive filters if necessary.
1412 Status
= MnpConfigReceiveFilters (MnpServiceData
);