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
= {
56 Configure the Snp receive filters according to the instances' receive filter
59 @param MnpServiceData Pointer to the mnp service context data.
61 @retval EFI_SUCCESS The receive filters is configured.
62 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due to lack
67 MnpConfigReceiveFilters (
68 IN MNP_SERVICE_DATA
*MnpServiceData
72 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
73 EFI_MAC_ADDRESS
*MCastFilter
;
74 UINT32 MCastFilterCnt
;
75 UINT32 EnableFilterBits
;
76 UINT32 DisableFilterBits
;
77 BOOLEAN ResetMCastFilters
;
80 MNP_GROUP_ADDRESS
*GroupAddress
;
82 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
84 Snp
= MnpServiceData
->Snp
;
87 // Initialize the enable filter and disable filter.
90 DisableFilterBits
= Snp
->Mode
->ReceiveFilterMask
;
92 if (MnpServiceData
->UnicastCount
!= 0) {
94 // Enable unicast if any instance wants to receive unicast.
96 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
99 if (MnpServiceData
->BroadcastCount
!= 0) {
101 // Enable broadcast if any instance wants to receive broadcast.
103 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
108 ResetMCastFilters
= TRUE
;
110 if ((MnpServiceData
->MulticastCount
!= 0) && (MnpServiceData
->GroupAddressCount
!= 0)) {
112 // There are instances configured to receive multicast and already some group
113 // addresses are joined.
116 ResetMCastFilters
= FALSE
;
118 if (MnpServiceData
->GroupAddressCount
<= Snp
->Mode
->MaxMCastFilterCount
) {
120 // The joind group address is less than simple network's maximum count.
121 // Just configure the snp to do the multicast filtering.
124 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
127 // Allocate pool for the mulicast addresses.
129 MCastFilterCnt
= MnpServiceData
->GroupAddressCount
;
130 MCastFilter
= AllocatePool (sizeof (EFI_MAC_ADDRESS
) * MCastFilterCnt
);
131 if (MCastFilter
== NULL
) {
133 DEBUG ((EFI_D_ERROR
, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
134 return EFI_OUT_OF_RESOURCES
;
138 // Fill the multicast HW address buffer.
141 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
143 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
144 CopyMem (MCastFilter
+ Index
, &GroupAddress
->Address
, sizeof (*(MCastFilter
+ Index
)));
147 ASSERT (Index
<= MCastFilterCnt
);
151 // The maximum multicast is reached, set the filter to be promiscuous
155 if (Snp
->Mode
->ReceiveFilterMask
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) {
156 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
159 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
160 // set the NIC to be promiscuous although this will tremendously degrade
163 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
168 if (MnpServiceData
->PromiscuousCount
!= 0) {
170 // Enable promiscuous if any instance wants to receive promiscuous.
172 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
176 // Set the disable filter.
178 DisableFilterBits
^= EnableFilterBits
;
181 // Configure the receive filters of SNP.
183 Status
= Snp
->ReceiveFilters (
192 if (EFI_ERROR (Status
)) {
196 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
202 if (MCastFilter
!= NULL
) {
204 // Free the buffer used to hold the group addresses.
206 gBS
->FreePool (MCastFilter
);
213 Add some NET_BUF into MnpServiceData->FreeNbufQue. The buffer length of
214 the NET_BUF is specified by MnpServiceData->BufferLength.
216 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
217 @param Count Number of NET_BUFFERs to add.
219 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated and
220 added into MnpServiceData->FreeNbufQue.
221 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.
226 IN MNP_SERVICE_DATA
*MnpServiceData
,
234 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
235 ASSERT ((Count
> 0) && (MnpServiceData
->BufferLength
> 0));
237 Status
= EFI_SUCCESS
;
239 for (Index
= 0; Index
< Count
; Index
++) {
241 Nbuf
= NetbufAlloc (MnpServiceData
->BufferLength
+ MnpServiceData
->PaddingSize
);
244 DEBUG ((EFI_D_ERROR
, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));
245 Status
= EFI_OUT_OF_RESOURCES
;
249 if (MnpServiceData
->PaddingSize
> 0) {
251 // Pad padding bytes before the media header
253 NetbufAllocSpace (Nbuf
, MnpServiceData
->PaddingSize
, NET_BUF_TAIL
);
254 NetbufTrim (Nbuf
, MnpServiceData
->PaddingSize
, NET_BUF_HEAD
);
257 NetbufQueAppend (&MnpServiceData
->FreeNbufQue
, Nbuf
);
260 MnpServiceData
->NbufCnt
+= Index
;
267 Allocate a free NET_BUF from MnpServiceData->FreeNbufQue. If there is none
268 in the queue, first try to allocate some and add them into the queue, then
269 fetch the NET_BUF from the updated FreeNbufQue.
271 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
273 @return Pointer to the allocated free NET_BUF structure, if NULL the operation is failed.
278 IN MNP_SERVICE_DATA
*MnpServiceData
282 NET_BUF_QUEUE
*FreeNbufQue
;
286 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
288 FreeNbufQue
= &MnpServiceData
->FreeNbufQue
;
290 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
293 // Check whether there are available buffers, or else try to add some.
295 if (FreeNbufQue
->BufNum
== 0) {
297 if ((MnpServiceData
->NbufCnt
+ MNP_NET_BUFFER_INCREASEMENT
) > MNP_MAX_NET_BUFFER_NUM
) {
301 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
309 Status
= MnpAddFreeNbuf (MnpServiceData
, MNP_NET_BUFFER_INCREASEMENT
);
310 if (EFI_ERROR (Status
)) {
314 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
318 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
319 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
324 Nbuf
= NetbufQueRemove (FreeNbufQue
);
327 // Increase the RefCnt.
334 gBS
->RestoreTPL (OldTpl
);
341 Try to reclaim the Nbuf into the buffer pool.
343 @param MnpServiceData Pointer to the mnp service context data.
344 @param Nbuf Pointer to the NET_BUF to free.
349 IN MNP_SERVICE_DATA
*MnpServiceData
,
355 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
356 ASSERT (Nbuf
->RefCnt
> 1);
358 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
362 if (Nbuf
->RefCnt
== 1) {
364 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
366 NetbufTrim (Nbuf
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
367 NetbufQueAppend (&MnpServiceData
->FreeNbufQue
, Nbuf
);
370 gBS
->RestoreTPL (OldTpl
);
375 Initialize the mnp service context data.
377 @param MnpServiceData Pointer to the mnp service context data.
378 @param ImageHandle The driver image handle.
379 @param ControllerHandle Handle of device to bind driver to.
381 @retval EFI_SUCCESS The mnp service context is initialized.
382 @retval Other Some error occurs.
386 MnpInitializeServiceData (
387 IN MNP_SERVICE_DATA
*MnpServiceData
,
388 IN EFI_HANDLE ImageHandle
,
389 IN EFI_HANDLE ControllerHandle
393 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
394 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
396 MnpServiceData
->Signature
= MNP_SERVICE_DATA_SIGNATURE
;
398 MnpServiceData
->ControllerHandle
= ControllerHandle
;
401 // Copy the ServiceBinding structure.
403 MnpServiceData
->ServiceBinding
= mMnpServiceBindingProtocol
;
406 // Open the Simple Network protocol.
408 Status
= gBS
->OpenProtocol (
410 &gEfiSimpleNetworkProtocolGuid
,
414 EFI_OPEN_PROTOCOL_BY_DRIVER
416 if (EFI_ERROR (Status
)) {
417 return EFI_UNSUPPORTED
;
424 MnpServiceData
->Snp
= Snp
;
425 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
;
428 // Initialize the lists.
430 InitializeListHead (&MnpServiceData
->GroupAddressList
);
431 InitializeListHead (&MnpServiceData
->ChildrenList
);
434 // Get the buffer length used to allocate NET_BUF to hold data received
435 // from SNP. Do this before fill the FreeNetBufQue.
437 MnpServiceData
->BufferLength
= MnpServiceData
->Mtu
+ SnpMode
->MediaHeaderSize
+ NET_ETHER_FCS_SIZE
;
440 // Make sure the protocol headers immediately following the media header
443 MnpServiceData
->PaddingSize
= (4 - SnpMode
->MediaHeaderSize
) & 0x3;
446 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
448 NetbufQueInit (&MnpServiceData
->FreeNbufQue
);
449 Status
= MnpAddFreeNbuf (MnpServiceData
, MNP_INIT_NET_BUFFER_NUM
);
450 if (EFI_ERROR (Status
)) {
452 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status
));
456 // Get one NET_BUF from the FreeNbufQue for rx cache.
458 MnpServiceData
->RxNbufCache
= MnpAllocNbuf (MnpServiceData
);
460 MnpServiceData
->RxNbufCache
,
461 MnpServiceData
->BufferLength
,
466 // Allocate buffer pool for tx.
468 MnpServiceData
->TxBuf
= AllocatePool (MnpServiceData
->Mtu
+ SnpMode
->MediaHeaderSize
);
469 if (MnpServiceData
->TxBuf
== NULL
) {
471 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: AllocatePool failed.\n"));
472 Status
= EFI_OUT_OF_RESOURCES
;
478 // Create the system poll timer.
480 Status
= gBS
->CreateEvent (
481 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
485 &MnpServiceData
->PollTimer
487 if (EFI_ERROR (Status
)) {
489 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));
494 // Create the timer for packet timeout check.
496 Status
= gBS
->CreateEvent (
497 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
499 MnpCheckPacketTimeout
,
501 &MnpServiceData
->TimeoutCheckTimer
503 if (EFI_ERROR (Status
)) {
505 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));
510 // Create the timer for tx timeout check.
512 Status
= gBS
->CreateEvent (
517 &MnpServiceData
->TxTimeoutEvent
519 if (EFI_ERROR (Status
)) {
521 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));
526 if (EFI_ERROR (Status
)) {
528 // Free the dynamic allocated resources if necessary.
530 if (MnpServiceData
->TimeoutCheckTimer
!= NULL
) {
532 gBS
->CloseEvent (MnpServiceData
->TimeoutCheckTimer
);
535 if (MnpServiceData
->PollTimer
!= NULL
) {
537 gBS
->CloseEvent (MnpServiceData
->PollTimer
);
540 if (MnpServiceData
->TxBuf
!= NULL
) {
542 gBS
->FreePool (MnpServiceData
->TxBuf
);
545 if (MnpServiceData
->RxNbufCache
!= NULL
) {
547 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
550 if (MnpServiceData
->FreeNbufQue
.BufNum
!= 0) {
552 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
561 Flush the mnp service context data.
563 @param MnpServiceData Pointer to the mnp service context data.
564 @param ImageHandle The driver image handle.
568 MnpFlushServiceData (
569 IN MNP_SERVICE_DATA
*MnpServiceData
,
570 IN EFI_HANDLE ImageHandle
573 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
576 // The GroupAddressList must be empty.
578 ASSERT (IsListEmpty (&MnpServiceData
->GroupAddressList
));
583 gBS
->CloseEvent (&MnpServiceData
->TxTimeoutEvent
);
584 gBS
->CloseEvent (&MnpServiceData
->TimeoutCheckTimer
);
585 gBS
->CloseEvent (&MnpServiceData
->PollTimer
);
588 // Free the tx buffer.
590 gBS
->FreePool (MnpServiceData
->TxBuf
);
593 // Free the RxNbufCache.
595 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
598 // Flush the FreeNbufQue.
600 MnpServiceData
->NbufCnt
-= MnpServiceData
->FreeNbufQue
.BufNum
;
601 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
605 if (MnpServiceData
->NbufCnt
!= 0) {
607 DEBUG ((EFI_D_WARN
, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));
612 // Close the Simple Network Protocol.
615 MnpServiceData
->ControllerHandle
,
616 &gEfiSimpleNetworkProtocolGuid
,
618 MnpServiceData
->ControllerHandle
624 Initialize the mnp instance context data.
626 @param MnpServiceData Pointer to the mnp service context data.
627 @param Instance Pointer to the mnp instance context data to
632 MnpInitializeInstanceData (
633 IN MNP_SERVICE_DATA
*MnpServiceData
,
634 IN MNP_INSTANCE_DATA
*Instance
637 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
638 ASSERT (Instance
!= NULL
);
641 // Set the signature.
643 Instance
->Signature
= MNP_INSTANCE_DATA_SIGNATURE
;
646 // Copy the MNP Protocol interfaces from the template.
648 CopyMem (&Instance
->ManagedNetwork
, &mMnpProtocolTemplate
, sizeof (Instance
->ManagedNetwork
));
651 // Copy the default config data.
653 CopyMem (&Instance
->ConfigData
, &mMnpDefaultConfigData
, sizeof (Instance
->ConfigData
));
656 // Initialize the lists.
658 InitializeListHead (&Instance
->GroupCtrlBlkList
);
659 InitializeListHead (&Instance
->RcvdPacketQueue
);
660 InitializeListHead (&Instance
->RxDeliveredPacketQueue
);
663 // Initialize the RxToken Map.
665 NetMapInit (&Instance
->RxTokenMap
);
668 // Save the MnpServiceData info.
670 Instance
->MnpServiceData
= MnpServiceData
;
675 Check whether the token specified by Arg maches the token in Item.
677 @param Map Pointer to the NET_MAP.
678 @param Item Pointer to the NET_MAP_ITEM
679 @param Arg Pointer to the Arg, it's a pointer to the token to
682 @retval EFI_SUCCESS The token specified by Arg is different from the
684 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
691 IN NET_MAP_ITEM
*Item
,
695 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
;
696 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenInItem
;
698 Token
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Arg
;
699 TokenInItem
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
701 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
703 // The token is the same either the two tokens equals or the Events in
704 // the two tokens are the same.
706 return EFI_ACCESS_DENIED
;
713 Cancel the token specified by Arg if it matches the token in Item.
715 @param Map Pointer to the NET_MAP.
716 @param Item Pointer to the NET_MAP_ITEM
717 @param Arg Pointer to the Arg, it's a pointer to the token to
720 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is
721 cancelled, or the Arg isn't NULL, and the token in
722 Item is different from the Arg.
723 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
724 Arg, and the token is cancelled.
730 IN NET_MAP_ITEM
*Item
,
734 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenToCancel
;
736 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
738 // The token in Item is not the token specified by Arg.
743 TokenToCancel
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
746 // Remove the item from the map.
748 NetMapRemoveItem (Map
, Item
, NULL
);
751 // Cancel this token with status set to EFI_ABORTED.
753 TokenToCancel
->Status
= EFI_ABORTED
;
754 gBS
->SignalEvent (TokenToCancel
->Event
);
758 // Only abort the token specified by Arg if Arg isn't NULL.
768 Start and initialize the simple network.
770 @param Snp Pointer to the simple network protocol.
772 @retval EFI_SUCCESS The simple network protocol is started.
773 @retval Other Some error occurs.
778 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
783 ASSERT (Snp
!= NULL
);
786 // Start the simple network.
788 Status
= Snp
->Start (Snp
);
790 if (!EFI_ERROR (Status
)) {
792 // Initialize the simple network.
794 Status
= Snp
->Initialize (Snp
, 0, 0);
802 Stop the simple network.
804 @param Snp Pointer to the simple network protocol.
806 @retval EFI_SUCCESS The simple network is stopped.
807 @retval Other Some error occurs.
812 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
817 ASSERT (Snp
!= NULL
);
820 // Shut down the simple network.
822 Status
= Snp
->Shutdown (Snp
);
824 if (!EFI_ERROR (Status
)) {
826 // Stop the simple network.
828 Status
= Snp
->Stop (Snp
);
836 Start the managed network, this function is called when one instance is configured
839 @param MnpServiceData Pointer to the mnp service context data.
840 @param IsConfigUpdate The instance is reconfigured or it's the first time
841 the instanced is configured.
842 @param EnableSystemPoll Enable the system polling or not.
844 @retval EFI_SUCCESS The managed network is started and some
845 configuration is updated.
846 @retval Other Some error occurs.
851 IN MNP_SERVICE_DATA
*MnpServiceData
,
852 IN BOOLEAN IsConfigUpdate
,
853 IN BOOLEAN EnableSystemPoll
857 EFI_TIMER_DELAY TimerOpType
;
859 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
861 Status
= EFI_SUCCESS
;
863 if (!IsConfigUpdate
) {
865 // If it's not a configuration update, increase the configured children number.
867 MnpServiceData
->ConfiguredChildrenNumber
++;
869 if (MnpServiceData
->ConfiguredChildrenNumber
== 1) {
871 // It's the first configured child, start the simple network.
873 Status
= MnpStartSnp (MnpServiceData
->Snp
);
874 if (EFI_ERROR (Status
)) {
876 DEBUG ((EFI_D_ERROR
, "MnpStart: MnpStartSnp failed, %r.\n", Status
));
881 // Start the timeout timer.
883 Status
= gBS
->SetTimer (
884 MnpServiceData
->TimeoutCheckTimer
,
886 MNP_TIMEOUT_CHECK_INTERVAL
888 if (EFI_ERROR (Status
)) {
892 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
900 if (MnpServiceData
->EnableSystemPoll
^ EnableSystemPoll
) {
902 // The EnableSystemPoll differs with the current state, disable or enable
905 TimerOpType
= EnableSystemPoll
? TimerPeriodic
: TimerCancel
;
907 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerOpType
, MNP_SYS_POLL_INTERVAL
);
908 if (EFI_ERROR (Status
)) {
910 DEBUG ((EFI_D_ERROR
, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status
));
914 MnpServiceData
->EnableSystemPoll
= EnableSystemPoll
;
918 // Change the receive filters if need.
920 Status
= MnpConfigReceiveFilters (MnpServiceData
);
929 Stop the managed network.
931 @param MnpServiceData Pointer to the mnp service context data.
933 @retval EFI_SUCCESS The managed network is stopped.
934 @retval Other Some error occurs.
939 IN MNP_SERVICE_DATA
*MnpServiceData
944 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
945 ASSERT (MnpServiceData
->ConfiguredChildrenNumber
> 0);
948 // Configure the receive filters.
950 MnpConfigReceiveFilters (MnpServiceData
);
953 // Decrease the children number.
955 MnpServiceData
->ConfiguredChildrenNumber
--;
957 if (MnpServiceData
->ConfiguredChildrenNumber
> 0) {
959 // If there are other configured chilren, return and keep the timers and
960 // simple network unchanged.
966 // No configured children now.
969 if (MnpServiceData
->EnableSystemPoll
) {
971 // The system poll in on, cancel the poll timer.
973 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerCancel
, 0);
974 MnpServiceData
->EnableSystemPoll
= FALSE
;
978 // Cancel the timeout timer.
980 Status
= gBS
->SetTimer (MnpServiceData
->TimeoutCheckTimer
, TimerCancel
, 0);
983 // Stop the simple network.
985 Status
= MnpStopSnp (MnpServiceData
->Snp
);
992 Flush the instance's received data.
994 @param Instance Pointer to the mnp instance context data.
998 MnpFlushRcvdDataQueue (
999 IN MNP_INSTANCE_DATA
*Instance
1003 MNP_RXDATA_WRAP
*RxDataWrap
;
1005 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1007 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1009 while (!IsListEmpty (&Instance
->RcvdPacketQueue
)) {
1011 // Remove all the Wraps.
1013 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
1016 // Recycle the RxDataWrap.
1018 MnpRecycleRxData (NULL
, (VOID
*) RxDataWrap
);
1019 Instance
->RcvdPacketQueueSize
--;
1022 ASSERT (Instance
->RcvdPacketQueueSize
== 0);
1024 gBS
->RestoreTPL (OldTpl
);
1029 Configure the Instance using ConfigData.
1031 @param Instance Pointer to the mnp instance context data.
1032 @param ConfigData Pointer to the configuration data used to configure
1035 @retval EFI_SUCCESS The Instance is configured.
1036 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1037 implementation doesn't support it.
1038 @retval Other Some error occurs.
1042 MnpConfigureInstance (
1043 IN MNP_INSTANCE_DATA
*Instance
,
1044 IN EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData OPTIONAL
1048 MNP_SERVICE_DATA
*MnpServiceData
;
1049 EFI_MANAGED_NETWORK_CONFIG_DATA
*OldConfigData
;
1050 EFI_MANAGED_NETWORK_CONFIG_DATA
*NewConfigData
;
1051 BOOLEAN IsConfigUpdate
;
1053 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1055 if ((ConfigData
!= NULL
) && ConfigData
->EnableReceiveTimestamps
) {
1057 // Don't support timestamp.
1059 return EFI_UNSUPPORTED
;
1062 Status
= EFI_SUCCESS
;
1064 MnpServiceData
= Instance
->MnpServiceData
;
1065 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1067 IsConfigUpdate
= (BOOLEAN
) ((Instance
->Configured
) && (ConfigData
!= NULL
));
1069 OldConfigData
= &Instance
->ConfigData
;
1070 NewConfigData
= ConfigData
;
1071 if (NewConfigData
== NULL
) {
1073 // Restore back the default config data if a reset of this instance
1076 NewConfigData
= &mMnpDefaultConfigData
;
1080 // Reset the instance's receive filter.
1082 Instance
->ReceiveFilter
= 0;
1085 // Clear the receive counters according to the old ConfigData.
1087 if (OldConfigData
->EnableUnicastReceive
) {
1088 MnpServiceData
->UnicastCount
--;
1091 if (OldConfigData
->EnableMulticastReceive
) {
1092 MnpServiceData
->MulticastCount
--;
1095 if (OldConfigData
->EnableBroadcastReceive
) {
1096 MnpServiceData
->BroadcastCount
--;
1099 if (OldConfigData
->EnablePromiscuousReceive
) {
1100 MnpServiceData
->PromiscuousCount
--;
1104 // Set the receive filter counters and the receive filter of the
1105 // instance according to the new ConfigData.
1107 if (NewConfigData
->EnableUnicastReceive
) {
1108 MnpServiceData
->UnicastCount
++;
1109 Instance
->ReceiveFilter
|= MNP_RECEIVE_UNICAST
;
1112 if (NewConfigData
->EnableMulticastReceive
) {
1113 MnpServiceData
->MulticastCount
++;
1116 if (NewConfigData
->EnableBroadcastReceive
) {
1117 MnpServiceData
->BroadcastCount
++;
1118 Instance
->ReceiveFilter
|= MNP_RECEIVE_BROADCAST
;
1121 if (NewConfigData
->EnablePromiscuousReceive
) {
1122 MnpServiceData
->PromiscuousCount
++;
1125 if (OldConfigData
->FlushQueuesOnReset
) {
1127 MnpFlushRcvdDataQueue (Instance
);
1130 if (ConfigData
== NULL
) {
1132 Instance
->ManagedNetwork
.Cancel (&Instance
->ManagedNetwork
, NULL
);
1135 if (!NewConfigData
->EnableMulticastReceive
) {
1137 MnpGroupOp (Instance
, FALSE
, NULL
, NULL
);
1141 // Save the new configuration data.
1143 CopyMem (OldConfigData
, NewConfigData
, sizeof (*OldConfigData
));
1145 Instance
->Configured
= (BOOLEAN
) (ConfigData
!= NULL
);
1147 if (Instance
->Configured
) {
1149 // The instance is configured, start the Mnp.
1154 (BOOLEAN
) !NewConfigData
->DisableBackgroundPolling
1158 // The instance is changed to the unconfigured state, stop the Mnp.
1160 Status
= MnpStop (MnpServiceData
);
1169 Add a group address control block which controls the MacAddress for
1172 @param Instance Pointer to the mnp instance context data.
1173 @param CtrlBlk Pointer to the group address control block.
1174 @param GroupAddress Pointer to the group adress.
1175 @param MacAddress Pointer to the mac address.
1176 @param HwAddressSize The hardware address size.
1178 @retval EFI_SUCCESS The group address control block is added.
1179 @retval EFI_OUT_OF_RESOURCE Failed due to lack of memory resources.
1183 MnpGroupOpAddCtrlBlk (
1184 IN MNP_INSTANCE_DATA
*Instance
,
1185 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
1186 IN MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
1187 IN EFI_MAC_ADDRESS
*MacAddress
,
1188 IN UINT32 HwAddressSize
1191 MNP_SERVICE_DATA
*MnpServiceData
;
1193 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1195 MnpServiceData
= Instance
->MnpServiceData
;
1196 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1198 if (GroupAddress
== NULL
) {
1200 ASSERT (MacAddress
!= NULL
);
1203 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1205 GroupAddress
= AllocatePool (sizeof (MNP_GROUP_ADDRESS
));
1206 if (GroupAddress
== NULL
) {
1208 DEBUG ((EFI_D_ERROR
, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1210 return EFI_OUT_OF_RESOURCES
;
1213 CopyMem (&GroupAddress
->Address
, MacAddress
, sizeof (GroupAddress
->Address
));
1214 GroupAddress
->RefCnt
= 0;
1216 &MnpServiceData
->GroupAddressList
,
1217 &GroupAddress
->AddrEntry
1219 MnpServiceData
->GroupAddressCount
++;
1223 // Increase the RefCnt.
1225 GroupAddress
->RefCnt
++;
1228 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1230 CtrlBlk
->GroupAddress
= GroupAddress
;
1231 InsertTailList (&Instance
->GroupCtrlBlkList
, &CtrlBlk
->CtrlBlkEntry
);
1238 Delete a group control block from the instance. If the controlled group address's
1239 reference count reaches zero, the group address is removed too.
1241 @param Instance Pointer to the instance context data.
1242 @param CtrlBlk Pointer to the group control block to delete.
1244 @return The group address controlled by the control block is no longer used or not.
1248 MnpGroupOpDelCtrlBlk (
1249 IN MNP_INSTANCE_DATA
*Instance
,
1250 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
1253 MNP_SERVICE_DATA
*MnpServiceData
;
1254 MNP_GROUP_ADDRESS
*GroupAddress
;
1256 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1258 MnpServiceData
= Instance
->MnpServiceData
;
1259 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1262 // Remove and free the CtrlBlk.
1264 GroupAddress
= CtrlBlk
->GroupAddress
;
1265 RemoveEntryList (&CtrlBlk
->CtrlBlkEntry
);
1266 gBS
->FreePool (CtrlBlk
);
1268 ASSERT (GroupAddress
->RefCnt
> 0);
1271 // Count down the RefCnt.
1273 GroupAddress
->RefCnt
--;
1275 if (GroupAddress
->RefCnt
== 0) {
1277 // Free this GroupAddress entry if no instance uses it.
1279 MnpServiceData
->GroupAddressCount
--;
1280 RemoveEntryList (&GroupAddress
->AddrEntry
);
1281 gBS
->FreePool (GroupAddress
);
1291 Do the group operations for this instance.
1293 @param Instance Pointer to the instance context data.
1294 @param JoinFlag Set to TRUE to join a group. Set to TRUE to leave a
1296 @param MacAddress Pointer to the group address to join or leave.
1297 @param CtrlBlk Pointer to the group control block if JoinFlag if
1300 @retval EFI_SUCCESS The group operation finished.
1301 @retval Other Some error occurs.
1306 IN MNP_INSTANCE_DATA
*Instance
,
1307 IN BOOLEAN JoinFlag
,
1308 IN EFI_MAC_ADDRESS
*MacAddress OPTIONAL
,
1309 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk OPTIONAL
1312 MNP_SERVICE_DATA
*MnpServiceData
;
1314 LIST_ENTRY
*NextEntry
;
1315 MNP_GROUP_ADDRESS
*GroupAddress
;
1316 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1317 MNP_GROUP_CONTROL_BLOCK
*NewCtrlBlk
;
1319 BOOLEAN AddressExist
;
1322 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1324 MnpServiceData
= Instance
->MnpServiceData
;
1325 SnpMode
= MnpServiceData
->Snp
->Mode
;
1329 // A new gropu address is to be added.
1332 GroupAddress
= NULL
;
1333 AddressExist
= FALSE
;
1336 // Allocate memory for the control block.
1338 NewCtrlBlk
= AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK
));
1339 if (NewCtrlBlk
== NULL
) {
1341 DEBUG ((EFI_D_ERROR
, "MnpGroupOp: Failed to allocate memory resource.\n"));
1342 return EFI_OUT_OF_RESOURCES
;
1345 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
1347 // Check whether the MacAddress is already joined by other instances.
1349 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1350 if (0 == CompareMem (
1352 &GroupAddress
->Address
,
1353 SnpMode
->HwAddressSize
1356 AddressExist
= TRUE
;
1361 if (!AddressExist
) {
1362 GroupAddress
= NULL
;
1366 // Add the GroupAddress for this instance.
1368 Status
= MnpGroupOpAddCtrlBlk (
1373 SnpMode
->HwAddressSize
1375 if (EFI_ERROR (Status
)) {
1383 if (MacAddress
!= NULL
) {
1385 ASSERT (CtrlBlk
!= NULL
);
1388 // Leave the specific multicast mac address.
1390 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, CtrlBlk
);
1393 // Leave all multicast mac addresses.
1397 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Instance
->GroupCtrlBlkList
) {
1399 NewCtrlBlk
= NET_LIST_USER_STRUCT (
1401 MNP_GROUP_CONTROL_BLOCK
,
1405 // Update is required if the group address left is no longer used
1406 // by other instances.
1408 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, NewCtrlBlk
);
1413 Status
= EFI_SUCCESS
;
1417 // Reconfigure the receive filters if necessary.
1419 Status
= MnpConfigReceiveFilters (MnpServiceData
);