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[in] 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
55 to 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
) != 0) {
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[in, out] MnpServiceData Pointer to the MNP_SERVICE_DATA.
209 @param[in] 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 OUT 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[in, out] MnpServiceData Pointer to the MNP_SERVICE_DATA.
265 @return Pointer to the allocated free NET_BUF structure, if NULL the
271 IN OUT 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[in,out] MnpServiceData Pointer to the mnp service context data.
337 @param[in,out] Nbuf Pointer to the NET_BUF to free.
342 IN OUT 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[in, out] MnpServiceData Pointer to the mnp service context data.
371 @param[in] ImageHandle The driver image handle.
372 @param[in] ControllerHandle Handle of device to bind driver to.
374 @retval EFI_SUCCESS The mnp service context is initialized.
375 @retval EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.
376 @retval Others Other errors as indicated.
380 MnpInitializeServiceData (
381 IN OUT MNP_SERVICE_DATA
*MnpServiceData
,
382 IN EFI_HANDLE ImageHandle
,
383 IN EFI_HANDLE ControllerHandle
387 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
388 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
390 MnpServiceData
->Signature
= MNP_SERVICE_DATA_SIGNATURE
;
392 MnpServiceData
->ControllerHandle
= ControllerHandle
;
395 // Copy the ServiceBinding structure.
397 MnpServiceData
->ServiceBinding
= mMnpServiceBindingProtocol
;
400 // Open the Simple Network protocol.
402 Status
= gBS
->OpenProtocol (
404 &gEfiSimpleNetworkProtocolGuid
,
408 EFI_OPEN_PROTOCOL_BY_DRIVER
410 if (EFI_ERROR (Status
)) {
411 return EFI_UNSUPPORTED
;
418 MnpServiceData
->Snp
= Snp
;
419 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
;
422 // Initialize the lists.
424 InitializeListHead (&MnpServiceData
->GroupAddressList
);
425 InitializeListHead (&MnpServiceData
->ChildrenList
);
428 // Get the buffer length used to allocate NET_BUF to hold data received
429 // from SNP. Do this before fill the FreeNetBufQue.
431 MnpServiceData
->BufferLength
= MnpServiceData
->Mtu
+ SnpMode
->MediaHeaderSize
+ NET_ETHER_FCS_SIZE
;
434 // Make sure the protocol headers immediately following the media header
437 MnpServiceData
->PaddingSize
= (4 - SnpMode
->MediaHeaderSize
) & 0x3;
440 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
442 NetbufQueInit (&MnpServiceData
->FreeNbufQue
);
443 Status
= MnpAddFreeNbuf (MnpServiceData
, MNP_INIT_NET_BUFFER_NUM
);
444 if (EFI_ERROR (Status
)) {
446 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status
));
450 // Get one NET_BUF from the FreeNbufQue for rx cache.
452 MnpServiceData
->RxNbufCache
= MnpAllocNbuf (MnpServiceData
);
454 MnpServiceData
->RxNbufCache
,
455 MnpServiceData
->BufferLength
,
460 // Allocate buffer pool for tx.
462 MnpServiceData
->TxBuf
= AllocatePool (MnpServiceData
->Mtu
+ SnpMode
->MediaHeaderSize
);
463 if (MnpServiceData
->TxBuf
== NULL
) {
465 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: AllocatePool failed.\n"));
466 Status
= EFI_OUT_OF_RESOURCES
;
472 // Create the system poll timer.
474 Status
= gBS
->CreateEvent (
475 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
479 &MnpServiceData
->PollTimer
481 if (EFI_ERROR (Status
)) {
483 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));
488 // Create the timer for packet timeout check.
490 Status
= gBS
->CreateEvent (
491 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
493 MnpCheckPacketTimeout
,
495 &MnpServiceData
->TimeoutCheckTimer
497 if (EFI_ERROR (Status
)) {
499 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));
504 // Create the timer for tx timeout check.
506 Status
= gBS
->CreateEvent (
511 &MnpServiceData
->TxTimeoutEvent
513 if (EFI_ERROR (Status
)) {
515 DEBUG ((EFI_D_ERROR
, "MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));
520 if (EFI_ERROR (Status
)) {
522 // Free the dynamic allocated resources if necessary.
524 if (MnpServiceData
->TimeoutCheckTimer
!= NULL
) {
526 gBS
->CloseEvent (MnpServiceData
->TimeoutCheckTimer
);
529 if (MnpServiceData
->PollTimer
!= NULL
) {
531 gBS
->CloseEvent (MnpServiceData
->PollTimer
);
534 if (MnpServiceData
->TxBuf
!= NULL
) {
536 gBS
->FreePool (MnpServiceData
->TxBuf
);
539 if (MnpServiceData
->RxNbufCache
!= NULL
) {
541 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
544 if (MnpServiceData
->FreeNbufQue
.BufNum
!= 0) {
546 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
555 Flush the mnp service context data.
557 @param[in, out] MnpServiceData Pointer to the mnp service context data.
558 @param[in] ImageHandle The driver image handle.
562 MnpFlushServiceData (
563 IN OUT MNP_SERVICE_DATA
*MnpServiceData
,
564 IN EFI_HANDLE ImageHandle
567 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
570 // The GroupAddressList must be empty.
572 ASSERT (IsListEmpty (&MnpServiceData
->GroupAddressList
));
577 gBS
->CloseEvent (&MnpServiceData
->TxTimeoutEvent
);
578 gBS
->CloseEvent (&MnpServiceData
->TimeoutCheckTimer
);
579 gBS
->CloseEvent (&MnpServiceData
->PollTimer
);
582 // Free the tx buffer.
584 gBS
->FreePool (MnpServiceData
->TxBuf
);
587 // Free the RxNbufCache.
589 MnpFreeNbuf (MnpServiceData
, MnpServiceData
->RxNbufCache
);
592 // Flush the FreeNbufQue.
594 MnpServiceData
->NbufCnt
-= MnpServiceData
->FreeNbufQue
.BufNum
;
595 NetbufQueFlush (&MnpServiceData
->FreeNbufQue
);
599 if (MnpServiceData
->NbufCnt
!= 0) {
601 DEBUG ((EFI_D_WARN
, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));
606 // Close the Simple Network Protocol.
609 MnpServiceData
->ControllerHandle
,
610 &gEfiSimpleNetworkProtocolGuid
,
612 MnpServiceData
->ControllerHandle
618 Initialize the mnp instance context data.
620 @param[in] MnpServiceData Pointer to the mnp service context data.
621 @param[in, out] Instance Pointer to the mnp instance context data
626 MnpInitializeInstanceData (
627 IN MNP_SERVICE_DATA
*MnpServiceData
,
628 IN OUT MNP_INSTANCE_DATA
*Instance
631 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
632 ASSERT (Instance
!= NULL
);
635 // Set the signature.
637 Instance
->Signature
= MNP_INSTANCE_DATA_SIGNATURE
;
640 // Copy the MNP Protocol interfaces from the template.
642 CopyMem (&Instance
->ManagedNetwork
, &mMnpProtocolTemplate
, sizeof (Instance
->ManagedNetwork
));
645 // Copy the default config data.
647 CopyMem (&Instance
->ConfigData
, &mMnpDefaultConfigData
, sizeof (Instance
->ConfigData
));
650 // Initialize the lists.
652 InitializeListHead (&Instance
->GroupCtrlBlkList
);
653 InitializeListHead (&Instance
->RcvdPacketQueue
);
654 InitializeListHead (&Instance
->RxDeliveredPacketQueue
);
657 // Initialize the RxToken Map.
659 NetMapInit (&Instance
->RxTokenMap
);
662 // Save the MnpServiceData info.
664 Instance
->MnpServiceData
= MnpServiceData
;
669 Check whether the token specified by Arg matches the token in Item.
671 @param[in] Map Pointer to the NET_MAP.
672 @param[in] Item Pointer to the NET_MAP_ITEM.
673 @param[in] Arg Pointer to the Arg, it's a pointer to the token to
676 @retval EFI_SUCCESS The token specified by Arg is different from the
678 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
685 IN NET_MAP_ITEM
*Item
,
689 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
;
690 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenInItem
;
692 Token
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Arg
;
693 TokenInItem
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
695 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
697 // The token is the same either the two tokens equals or the Events in
698 // the two tokens are the same.
700 return EFI_ACCESS_DENIED
;
707 Cancel the token specified by Arg if it matches the token in Item.
709 @param[in, out] Map Pointer to the NET_MAP.
710 @param[in, out] Item Pointer to the NET_MAP_ITEM.
711 @param[in] Arg Pointer to the Arg, it's a pointer to the
714 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,
715 or the Arg isn't NULL, and the token in Item is
716 different from the Arg.
717 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
718 Arg, and the token is cancelled.
724 IN OUT NET_MAP_ITEM
*Item
,
728 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenToCancel
;
730 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
732 // The token in Item is not the token specified by Arg.
737 TokenToCancel
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
740 // Remove the item from the map.
742 NetMapRemoveItem (Map
, Item
, NULL
);
745 // Cancel this token with status set to EFI_ABORTED.
747 TokenToCancel
->Status
= EFI_ABORTED
;
748 gBS
->SignalEvent (TokenToCancel
->Event
);
752 // Only abort the token specified by Arg if Arg isn't NULL.
762 Start and initialize the simple network.
764 @param[in] Snp Pointer to the simple network protocol.
766 @retval EFI_SUCCESS The simple network protocol is started.
767 @retval Others Other errors as indicated.
772 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
777 ASSERT (Snp
!= NULL
);
780 // Start the simple network.
782 Status
= Snp
->Start (Snp
);
784 if (!EFI_ERROR (Status
)) {
786 // Initialize the simple network.
788 Status
= Snp
->Initialize (Snp
, 0, 0);
796 Stop the simple network.
798 @param[in] Snp Pointer to the simple network protocol.
800 @retval EFI_SUCCESS The simple network is stopped.
801 @retval Others Other errors as indicated.
806 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
811 ASSERT (Snp
!= NULL
);
814 // Shut down the simple network.
816 Status
= Snp
->Shutdown (Snp
);
818 if (!EFI_ERROR (Status
)) {
820 // Stop the simple network.
822 Status
= Snp
->Stop (Snp
);
830 Start the managed network, this function is called when one instance is configured
833 @param[in, out] MnpServiceData Pointer to the mnp service context data.
834 @param[in] IsConfigUpdate The instance is reconfigured or it's the first
835 time the instanced is configured.
836 @param[in] EnableSystemPoll Enable the system polling or not.
838 @retval EFI_SUCCESS The managed network is started and some
839 configuration is updated.
840 @retval Others Other errors as indicated.
845 IN OUT MNP_SERVICE_DATA
*MnpServiceData
,
846 IN BOOLEAN IsConfigUpdate
,
847 IN BOOLEAN EnableSystemPoll
851 EFI_TIMER_DELAY TimerOpType
;
853 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
855 Status
= EFI_SUCCESS
;
857 if (!IsConfigUpdate
) {
859 // If it's not a configuration update, increase the configured children number.
861 MnpServiceData
->ConfiguredChildrenNumber
++;
863 if (MnpServiceData
->ConfiguredChildrenNumber
== 1) {
865 // It's the first configured child, start the simple network.
867 Status
= MnpStartSnp (MnpServiceData
->Snp
);
868 if (EFI_ERROR (Status
)) {
870 DEBUG ((EFI_D_ERROR
, "MnpStart: MnpStartSnp failed, %r.\n", Status
));
875 // Start the timeout timer.
877 Status
= gBS
->SetTimer (
878 MnpServiceData
->TimeoutCheckTimer
,
880 MNP_TIMEOUT_CHECK_INTERVAL
882 if (EFI_ERROR (Status
)) {
886 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
894 if (MnpServiceData
->EnableSystemPoll
^ EnableSystemPoll
) {
896 // The EnableSystemPoll differs with the current state, disable or enable
899 TimerOpType
= EnableSystemPoll
? TimerPeriodic
: TimerCancel
;
901 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerOpType
, MNP_SYS_POLL_INTERVAL
);
902 if (EFI_ERROR (Status
)) {
904 DEBUG ((EFI_D_ERROR
, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status
));
908 MnpServiceData
->EnableSystemPoll
= EnableSystemPoll
;
912 // Change the receive filters if need.
914 Status
= MnpConfigReceiveFilters (MnpServiceData
);
923 Stop the managed network.
925 @param[in, out] MnpServiceData Pointer to the mnp service context data.
927 @retval EFI_SUCCESS The managed network is stopped.
928 @retval Others Other errors as indicated.
933 IN OUT MNP_SERVICE_DATA
*MnpServiceData
938 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
939 ASSERT (MnpServiceData
->ConfiguredChildrenNumber
> 0);
942 // Configure the receive filters.
944 MnpConfigReceiveFilters (MnpServiceData
);
947 // Decrease the children number.
949 MnpServiceData
->ConfiguredChildrenNumber
--;
951 if (MnpServiceData
->ConfiguredChildrenNumber
> 0) {
953 // If there are other configured chilren, return and keep the timers and
954 // simple network unchanged.
960 // No configured children now.
963 if (MnpServiceData
->EnableSystemPoll
) {
965 // The system poll in on, cancel the poll timer.
967 Status
= gBS
->SetTimer (MnpServiceData
->PollTimer
, TimerCancel
, 0);
968 MnpServiceData
->EnableSystemPoll
= FALSE
;
972 // Cancel the timeout timer.
974 Status
= gBS
->SetTimer (MnpServiceData
->TimeoutCheckTimer
, TimerCancel
, 0);
977 // Stop the simple network.
979 Status
= MnpStopSnp (MnpServiceData
->Snp
);
986 Flush the instance's received data.
988 @param[in, out] Instance Pointer to the mnp instance context data.
992 MnpFlushRcvdDataQueue (
993 IN OUT MNP_INSTANCE_DATA
*Instance
997 MNP_RXDATA_WRAP
*RxDataWrap
;
999 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1001 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1003 while (!IsListEmpty (&Instance
->RcvdPacketQueue
)) {
1005 // Remove all the Wraps.
1007 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
1010 // Recycle the RxDataWrap.
1012 MnpRecycleRxData (NULL
, (VOID
*) RxDataWrap
);
1013 Instance
->RcvdPacketQueueSize
--;
1016 ASSERT (Instance
->RcvdPacketQueueSize
== 0);
1018 gBS
->RestoreTPL (OldTpl
);
1023 Configure the Instance using ConfigData.
1025 @param[in, out] Instance Pointer to the mnp instance context data.
1026 @param[in] ConfigData Pointer to the configuration data used to configure
1029 @retval EFI_SUCCESS The Instance is configured.
1030 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1031 implementation doesn't support it.
1032 @retval Others Other errors as indicated.
1036 MnpConfigureInstance (
1037 IN OUT MNP_INSTANCE_DATA
*Instance
,
1038 IN EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData OPTIONAL
1042 MNP_SERVICE_DATA
*MnpServiceData
;
1043 EFI_MANAGED_NETWORK_CONFIG_DATA
*OldConfigData
;
1044 EFI_MANAGED_NETWORK_CONFIG_DATA
*NewConfigData
;
1045 BOOLEAN IsConfigUpdate
;
1047 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1049 if ((ConfigData
!= NULL
) && ConfigData
->EnableReceiveTimestamps
) {
1051 // Don't support timestamp.
1053 return EFI_UNSUPPORTED
;
1056 Status
= EFI_SUCCESS
;
1058 MnpServiceData
= Instance
->MnpServiceData
;
1059 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1061 IsConfigUpdate
= (BOOLEAN
) ((Instance
->Configured
) && (ConfigData
!= NULL
));
1063 OldConfigData
= &Instance
->ConfigData
;
1064 NewConfigData
= ConfigData
;
1065 if (NewConfigData
== NULL
) {
1067 // Restore back the default config data if a reset of this instance
1070 NewConfigData
= &mMnpDefaultConfigData
;
1074 // Reset the instance's receive filter.
1076 Instance
->ReceiveFilter
= 0;
1079 // Clear the receive counters according to the old ConfigData.
1081 if (OldConfigData
->EnableUnicastReceive
) {
1082 MnpServiceData
->UnicastCount
--;
1085 if (OldConfigData
->EnableMulticastReceive
) {
1086 MnpServiceData
->MulticastCount
--;
1089 if (OldConfigData
->EnableBroadcastReceive
) {
1090 MnpServiceData
->BroadcastCount
--;
1093 if (OldConfigData
->EnablePromiscuousReceive
) {
1094 MnpServiceData
->PromiscuousCount
--;
1098 // Set the receive filter counters and the receive filter of the
1099 // instance according to the new ConfigData.
1101 if (NewConfigData
->EnableUnicastReceive
) {
1102 MnpServiceData
->UnicastCount
++;
1103 Instance
->ReceiveFilter
|= MNP_RECEIVE_UNICAST
;
1106 if (NewConfigData
->EnableMulticastReceive
) {
1107 MnpServiceData
->MulticastCount
++;
1110 if (NewConfigData
->EnableBroadcastReceive
) {
1111 MnpServiceData
->BroadcastCount
++;
1112 Instance
->ReceiveFilter
|= MNP_RECEIVE_BROADCAST
;
1115 if (NewConfigData
->EnablePromiscuousReceive
) {
1116 MnpServiceData
->PromiscuousCount
++;
1119 if (OldConfigData
->FlushQueuesOnReset
) {
1121 MnpFlushRcvdDataQueue (Instance
);
1124 if (ConfigData
== NULL
) {
1126 Instance
->ManagedNetwork
.Cancel (&Instance
->ManagedNetwork
, NULL
);
1129 if (!NewConfigData
->EnableMulticastReceive
) {
1131 MnpGroupOp (Instance
, FALSE
, NULL
, NULL
);
1135 // Save the new configuration data.
1137 CopyMem (OldConfigData
, NewConfigData
, sizeof (*OldConfigData
));
1139 Instance
->Configured
= (BOOLEAN
) (ConfigData
!= NULL
);
1141 if (Instance
->Configured
) {
1143 // The instance is configured, start the Mnp.
1148 (BOOLEAN
) !NewConfigData
->DisableBackgroundPolling
1152 // The instance is changed to the unconfigured state, stop the Mnp.
1154 Status
= MnpStop (MnpServiceData
);
1163 Add a group address control block which controls the MacAddress for
1166 @param[in, out] Instance Pointer to the mnp instance context data.
1167 @param[in, out] CtrlBlk Pointer to the group address control block.
1168 @param[in, out] GroupAddress Pointer to the group adress.
1169 @param[in] MacAddress Pointer to the mac address.
1170 @param[in] HwAddressSize The hardware address size.
1172 @retval EFI_SUCCESS The group address control block is added.
1173 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1177 MnpGroupOpAddCtrlBlk (
1178 IN OUT MNP_INSTANCE_DATA
*Instance
,
1179 IN OUT MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
1180 IN OUT MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
1181 IN EFI_MAC_ADDRESS
*MacAddress
,
1182 IN UINT32 HwAddressSize
1185 MNP_SERVICE_DATA
*MnpServiceData
;
1187 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1189 MnpServiceData
= Instance
->MnpServiceData
;
1190 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1192 if (GroupAddress
== NULL
) {
1194 ASSERT (MacAddress
!= NULL
);
1197 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1199 GroupAddress
= AllocatePool (sizeof (MNP_GROUP_ADDRESS
));
1200 if (GroupAddress
== NULL
) {
1202 DEBUG ((EFI_D_ERROR
, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1204 return EFI_OUT_OF_RESOURCES
;
1207 CopyMem (&GroupAddress
->Address
, MacAddress
, sizeof (GroupAddress
->Address
));
1208 GroupAddress
->RefCnt
= 0;
1210 &MnpServiceData
->GroupAddressList
,
1211 &GroupAddress
->AddrEntry
1213 MnpServiceData
->GroupAddressCount
++;
1217 // Increase the RefCnt.
1219 GroupAddress
->RefCnt
++;
1222 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1224 CtrlBlk
->GroupAddress
= GroupAddress
;
1225 InsertTailList (&Instance
->GroupCtrlBlkList
, &CtrlBlk
->CtrlBlkEntry
);
1232 Delete a group control block from the instance. If the controlled group address's
1233 reference count reaches zero, the group address is removed too.
1235 @param[in] Instance Pointer to the instance context data.
1236 @param[in] CtrlBlk Pointer to the group control block to delete.
1238 @return The group address controlled by the control block is no longer used or not.
1242 MnpGroupOpDelCtrlBlk (
1243 IN MNP_INSTANCE_DATA
*Instance
,
1244 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
1247 MNP_SERVICE_DATA
*MnpServiceData
;
1248 MNP_GROUP_ADDRESS
*GroupAddress
;
1250 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1252 MnpServiceData
= Instance
->MnpServiceData
;
1253 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1256 // Remove and free the CtrlBlk.
1258 GroupAddress
= CtrlBlk
->GroupAddress
;
1259 RemoveEntryList (&CtrlBlk
->CtrlBlkEntry
);
1260 gBS
->FreePool (CtrlBlk
);
1262 ASSERT (GroupAddress
->RefCnt
> 0);
1265 // Count down the RefCnt.
1267 GroupAddress
->RefCnt
--;
1269 if (GroupAddress
->RefCnt
== 0) {
1271 // Free this GroupAddress entry if no instance uses it.
1273 MnpServiceData
->GroupAddressCount
--;
1274 RemoveEntryList (&GroupAddress
->AddrEntry
);
1275 gBS
->FreePool (GroupAddress
);
1285 Do the group operations for this instance.
1287 @param[in, out] Instance Pointer to the instance context data.
1288 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to
1289 leave a group/groups.
1290 @param[in] MacAddress Pointer to the group address to join or leave.
1291 @param[in] CtrlBlk Pointer to the group control block if JoinFlag
1294 @retval EFI_SUCCESS The group operation finished.
1295 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1296 @retval Others Other errors as indicated.
1301 IN OUT MNP_INSTANCE_DATA
*Instance
,
1302 IN BOOLEAN JoinFlag
,
1303 IN EFI_MAC_ADDRESS
*MacAddress OPTIONAL
,
1304 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk OPTIONAL
1307 MNP_SERVICE_DATA
*MnpServiceData
;
1309 LIST_ENTRY
*NextEntry
;
1310 MNP_GROUP_ADDRESS
*GroupAddress
;
1311 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1312 MNP_GROUP_CONTROL_BLOCK
*NewCtrlBlk
;
1314 BOOLEAN AddressExist
;
1317 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1319 MnpServiceData
= Instance
->MnpServiceData
;
1320 SnpMode
= MnpServiceData
->Snp
->Mode
;
1324 // A new gropu address is to be added.
1327 GroupAddress
= NULL
;
1328 AddressExist
= FALSE
;
1331 // Allocate memory for the control block.
1333 NewCtrlBlk
= AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK
));
1334 if (NewCtrlBlk
== NULL
) {
1336 DEBUG ((EFI_D_ERROR
, "MnpGroupOp: Failed to allocate memory resource.\n"));
1337 return EFI_OUT_OF_RESOURCES
;
1340 NET_LIST_FOR_EACH (Entry
, &MnpServiceData
->GroupAddressList
) {
1342 // Check whether the MacAddress is already joined by other instances.
1344 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1345 if (0 == CompareMem (
1347 &GroupAddress
->Address
,
1348 SnpMode
->HwAddressSize
1351 AddressExist
= TRUE
;
1356 if (!AddressExist
) {
1357 GroupAddress
= NULL
;
1361 // Add the GroupAddress for this instance.
1363 Status
= MnpGroupOpAddCtrlBlk (
1368 SnpMode
->HwAddressSize
1370 if (EFI_ERROR (Status
)) {
1378 if (MacAddress
!= NULL
) {
1380 ASSERT (CtrlBlk
!= NULL
);
1383 // Leave the specific multicast mac address.
1385 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, CtrlBlk
);
1388 // Leave all multicast mac addresses.
1392 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Instance
->GroupCtrlBlkList
) {
1394 NewCtrlBlk
= NET_LIST_USER_STRUCT (
1396 MNP_GROUP_CONTROL_BLOCK
,
1400 // Update is required if the group address left is no longer used
1401 // by other instances.
1403 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, NewCtrlBlk
);
1408 Status
= EFI_SUCCESS
;
1412 // Reconfigure the receive filters if necessary.
1414 Status
= MnpConfigReceiveFilters (MnpServiceData
);