2 Implementation of Managed Network Protocol private services.
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol
= {
13 MnpServiceBindingCreateChild
,
14 MnpServiceBindingDestroyChild
17 EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate
= {
28 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData
= {
42 Add Count of net buffers to MnpDeviceData->FreeNbufQue. The length of the net
43 buffer is specified by MnpDeviceData->BufferLength.
45 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
46 @param[in] Count Number of NET_BUFFERs to add.
48 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated
49 and added to MnpDeviceData->FreeNbufQue.
50 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.
55 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
63 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
64 ASSERT ((Count
> 0) && (MnpDeviceData
->BufferLength
> 0));
67 for (Index
= 0; Index
< Count
; Index
++) {
68 Nbuf
= NetbufAlloc (MnpDeviceData
->BufferLength
+ MnpDeviceData
->PaddingSize
);
70 DEBUG ((EFI_D_ERROR
, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));
72 Status
= EFI_OUT_OF_RESOURCES
;
76 if (MnpDeviceData
->PaddingSize
> 0) {
78 // Pad padding bytes before the media header
80 NetbufAllocSpace (Nbuf
, MnpDeviceData
->PaddingSize
, NET_BUF_TAIL
);
81 NetbufTrim (Nbuf
, MnpDeviceData
->PaddingSize
, NET_BUF_HEAD
);
84 NetbufQueAppend (&MnpDeviceData
->FreeNbufQue
, Nbuf
);
87 MnpDeviceData
->NbufCnt
+= Index
;
93 Allocate a free NET_BUF from MnpDeviceData->FreeNbufQue. If there is none
94 in the queue, first try to allocate some and add them into the queue, then
95 fetch the NET_BUF from the updated FreeNbufQue.
97 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
99 @return Pointer to the allocated free NET_BUF structure, if NULL the
105 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
109 NET_BUF_QUEUE
*FreeNbufQue
;
113 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
115 FreeNbufQue
= &MnpDeviceData
->FreeNbufQue
;
116 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
119 // Check whether there are available buffers, or else try to add some.
121 if (FreeNbufQue
->BufNum
== 0) {
122 if ((MnpDeviceData
->NbufCnt
+ MNP_NET_BUFFER_INCREASEMENT
) > MNP_MAX_NET_BUFFER_NUM
) {
125 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
133 Status
= MnpAddFreeNbuf (MnpDeviceData
, MNP_NET_BUFFER_INCREASEMENT
);
134 if (EFI_ERROR (Status
)) {
137 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
142 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
143 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
148 Nbuf
= NetbufQueRemove (FreeNbufQue
);
151 // Increase the RefCnt.
158 gBS
->RestoreTPL (OldTpl
);
165 Try to reclaim the Nbuf into the buffer pool.
167 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
168 @param[in, out] Nbuf Pointer to the NET_BUF to free.
173 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
179 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
180 ASSERT (Nbuf
->RefCnt
> 1);
182 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
186 if (Nbuf
->RefCnt
== 1) {
188 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
190 NetbufTrim (Nbuf
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
192 if (NetbufAllocSpace (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_HEAD
) != NULL
) {
194 // There is space reserved for vlan tag in the head, reclaim it
196 NetbufTrim (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_TAIL
);
199 NetbufQueAppend (&MnpDeviceData
->FreeNbufQue
, Nbuf
);
202 gBS
->RestoreTPL (OldTpl
);
206 Add Count of TX buffers to MnpDeviceData->AllTxBufList and MnpDeviceData->FreeTxBufList.
207 The length of the buffer is specified by MnpDeviceData->BufferLength.
209 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
210 @param[in] Count Number of TX buffers to add.
212 @retval EFI_SUCCESS The specified amount of TX buffers are allocated.
213 @retval EFI_OUT_OF_RESOURCES Failed to allocate a TX buffer.
218 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
224 MNP_TX_BUF_WRAP
*TxBufWrap
;
226 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
227 ASSERT ((Count
> 0) && (MnpDeviceData
->BufferLength
> 0));
229 Status
= EFI_SUCCESS
;
230 for (Index
= 0; Index
< Count
; Index
++) {
231 TxBufWrap
= (MNP_TX_BUF_WRAP
*) AllocatePool (OFFSET_OF (MNP_TX_BUF_WRAP
, TxBuf
) + MnpDeviceData
->BufferLength
);
232 if (TxBufWrap
== NULL
) {
233 DEBUG ((EFI_D_ERROR
, "MnpAddFreeTxBuf: TxBuf Alloc failed.\n"));
235 Status
= EFI_OUT_OF_RESOURCES
;
238 DEBUG ((EFI_D_INFO
, "MnpAddFreeTxBuf: Add TxBufWrap %p, TxBuf %p\n", TxBufWrap
, TxBufWrap
->TxBuf
));
239 TxBufWrap
->Signature
= MNP_TX_BUF_WRAP_SIGNATURE
;
240 TxBufWrap
->InUse
= FALSE
;
241 InsertTailList (&MnpDeviceData
->FreeTxBufList
, &TxBufWrap
->WrapEntry
);
242 InsertTailList (&MnpDeviceData
->AllTxBufList
, &TxBufWrap
->AllEntry
);
245 MnpDeviceData
->TxBufCount
+= Index
;
250 Allocate a free TX buffer from MnpDeviceData->FreeTxBufList. If there is none
251 in the queue, first try to recycle some from SNP, then try to allocate some and add
252 them into the queue, then fetch the NET_BUF from the updated FreeTxBufList.
254 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
256 @return Pointer to the allocated free NET_BUF structure, if NULL the
262 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
269 MNP_TX_BUF_WRAP
*TxBufWrap
;
271 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
273 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
275 if (IsListEmpty (&MnpDeviceData
->FreeTxBufList
)) {
277 // First try to recycle some TX buffer from SNP
279 Status
= MnpRecycleTxBuf (MnpDeviceData
);
280 if (EFI_ERROR (Status
)) {
286 // If still no free TX buffer, allocate more.
288 if (IsListEmpty (&MnpDeviceData
->FreeTxBufList
)) {
289 if ((MnpDeviceData
->TxBufCount
+ MNP_TX_BUFFER_INCREASEMENT
) > MNP_MAX_TX_BUFFER_NUM
) {
292 "MnpAllocTxBuf: The maximum TxBuf size is reached for MNP driver instance %p.\n",
300 Status
= MnpAddFreeTxBuf (MnpDeviceData
, MNP_TX_BUFFER_INCREASEMENT
);
301 if (IsListEmpty (&MnpDeviceData
->FreeTxBufList
)) {
304 "MnpAllocNbuf: Failed to add TxBuf into the FreeTxBufList, %r.\n",
314 ASSERT (!IsListEmpty (&MnpDeviceData
->FreeTxBufList
));
315 Entry
= MnpDeviceData
->FreeTxBufList
.ForwardLink
;
316 RemoveEntryList (MnpDeviceData
->FreeTxBufList
.ForwardLink
);
317 TxBufWrap
= NET_LIST_USER_STRUCT_S (Entry
, MNP_TX_BUF_WRAP
, WrapEntry
, MNP_TX_BUF_WRAP_SIGNATURE
);
318 TxBufWrap
->InUse
= TRUE
;
319 TxBuf
= TxBufWrap
->TxBuf
;
322 gBS
->RestoreTPL (OldTpl
);
328 Try to reclaim the TX buffer into the buffer pool.
330 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
331 @param[in, out] TxBuf Pointer to the TX buffer to free.
336 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
340 MNP_TX_BUF_WRAP
*TxBufWrap
;
343 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
349 TxBufWrap
= NET_LIST_USER_STRUCT (TxBuf
, MNP_TX_BUF_WRAP
, TxBuf
);
350 if (TxBufWrap
->Signature
!= MNP_TX_BUF_WRAP_SIGNATURE
) {
353 "MnpFreeTxBuf: Signature check failed in MnpFreeTxBuf.\n")
358 if (!TxBufWrap
->InUse
) {
361 "MnpFreeTxBuf: Duplicated recycle report from SNP.\n")
366 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
367 InsertTailList (&MnpDeviceData
->FreeTxBufList
, &TxBufWrap
->WrapEntry
);
368 TxBufWrap
->InUse
= FALSE
;
369 gBS
->RestoreTPL (OldTpl
);
373 Try to recycle all the transmitted buffer address from SNP.
375 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
377 @retval EFI_SUCCESS Successed to recyclethe transmitted buffer address.
378 @retval Others Failed to recyclethe transmitted buffer address.
383 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
387 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
390 Snp
= MnpDeviceData
->Snp
;
391 ASSERT (Snp
!= NULL
);
395 Status
= Snp
->GetStatus (Snp
, NULL
, (VOID
**) &TxBuf
);
396 if (EFI_ERROR (Status
)) {
401 MnpFreeTxBuf (MnpDeviceData
, TxBuf
);
403 } while (TxBuf
!= NULL
);
409 Initialize the mnp device context data.
411 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
412 @param[in] ImageHandle The driver image handle.
413 @param[in] ControllerHandle Handle of device to bind driver to.
415 @retval EFI_SUCCESS The mnp service context is initialized.
416 @retval EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.
417 @retval Others Other errors as indicated.
421 MnpInitializeDeviceData (
422 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
423 IN EFI_HANDLE ImageHandle
,
424 IN EFI_HANDLE ControllerHandle
428 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
429 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
431 MnpDeviceData
->Signature
= MNP_DEVICE_DATA_SIGNATURE
;
432 MnpDeviceData
->ImageHandle
= ImageHandle
;
433 MnpDeviceData
->ControllerHandle
= ControllerHandle
;
436 // Copy the MNP Protocol interfaces from the template.
438 CopyMem (&MnpDeviceData
->VlanConfig
, &mVlanConfigProtocolTemplate
, sizeof (EFI_VLAN_CONFIG_PROTOCOL
));
441 // Open the Simple Network protocol.
443 Status
= gBS
->OpenProtocol (
445 &gEfiSimpleNetworkProtocolGuid
,
449 EFI_OPEN_PROTOCOL_BY_DRIVER
451 if (EFI_ERROR (Status
)) {
452 return EFI_UNSUPPORTED
;
459 MnpDeviceData
->Snp
= Snp
;
462 // Initialize the lists.
464 InitializeListHead (&MnpDeviceData
->ServiceList
);
465 InitializeListHead (&MnpDeviceData
->GroupAddressList
);
468 // Get the buffer length used to allocate NET_BUF to hold data received
469 // from SNP. Do this before fill the FreeNetBufQue.
472 MnpDeviceData
->BufferLength
= SnpMode
->MediaHeaderSize
+ NET_VLAN_TAG_LEN
+ SnpMode
->MaxPacketSize
+ NET_ETHER_FCS_SIZE
;
475 // Make sure the protocol headers immediately following the media header
476 // 4-byte aligned, and also preserve additional space for VLAN tag
478 MnpDeviceData
->PaddingSize
= ((4 - SnpMode
->MediaHeaderSize
) & 0x3) + NET_VLAN_TAG_LEN
;
481 // Initialize MAC string which will be used as VLAN configuration variable name
483 Status
= NetLibGetMacString (ControllerHandle
, ImageHandle
, &MnpDeviceData
->MacString
);
484 if (EFI_ERROR (Status
)) {
489 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
491 NetbufQueInit (&MnpDeviceData
->FreeNbufQue
);
492 Status
= MnpAddFreeNbuf (MnpDeviceData
, MNP_INIT_NET_BUFFER_NUM
);
493 if (EFI_ERROR (Status
)) {
494 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: MnpAddFreeNbuf failed, %r.\n", Status
));
500 // Get one NET_BUF from the FreeNbufQue for rx cache.
502 MnpDeviceData
->RxNbufCache
= MnpAllocNbuf (MnpDeviceData
);
504 MnpDeviceData
->RxNbufCache
,
505 MnpDeviceData
->BufferLength
,
510 // Allocate buffer pool for tx.
512 InitializeListHead (&MnpDeviceData
->FreeTxBufList
);
513 InitializeListHead (&MnpDeviceData
->AllTxBufList
);
514 MnpDeviceData
->TxBufCount
= 0;
517 // Create the system poll timer.
519 Status
= gBS
->CreateEvent (
520 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
524 &MnpDeviceData
->PollTimer
526 if (EFI_ERROR (Status
)) {
527 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));
533 // Create the timer for packet timeout check.
535 Status
= gBS
->CreateEvent (
536 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
538 MnpCheckPacketTimeout
,
540 &MnpDeviceData
->TimeoutCheckTimer
542 if (EFI_ERROR (Status
)) {
543 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));
549 // Create the timer for media detection.
551 Status
= gBS
->CreateEvent (
552 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
556 &MnpDeviceData
->MediaDetectTimer
558 if (EFI_ERROR (Status
)) {
559 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n"));
565 if (EFI_ERROR (Status
)) {
567 // Free the dynamic allocated resources if necessary.
569 if (MnpDeviceData
->MacString
!= NULL
) {
570 FreePool (MnpDeviceData
->MacString
);
573 if (MnpDeviceData
->TimeoutCheckTimer
!= NULL
) {
574 gBS
->CloseEvent (MnpDeviceData
->TimeoutCheckTimer
);
577 if (MnpDeviceData
->MediaDetectTimer
!= NULL
) {
578 gBS
->CloseEvent (MnpDeviceData
->MediaDetectTimer
);
581 if (MnpDeviceData
->PollTimer
!= NULL
) {
582 gBS
->CloseEvent (MnpDeviceData
->PollTimer
);
585 if (MnpDeviceData
->RxNbufCache
!= NULL
) {
586 MnpFreeNbuf (MnpDeviceData
, MnpDeviceData
->RxNbufCache
);
589 if (MnpDeviceData
->FreeNbufQue
.BufNum
!= 0) {
590 NetbufQueFlush (&MnpDeviceData
->FreeNbufQue
);
594 // Close the Simple Network Protocol.
598 &gEfiSimpleNetworkProtocolGuid
,
609 Destroy the MNP device context data.
611 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
612 @param[in] ImageHandle The driver image handle.
616 MnpDestroyDeviceData (
617 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
618 IN EFI_HANDLE ImageHandle
622 LIST_ENTRY
*NextEntry
;
623 MNP_TX_BUF_WRAP
*TxBufWrap
;
625 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
628 // Free Vlan Config variable name string
630 if (MnpDeviceData
->MacString
!= NULL
) {
631 FreePool (MnpDeviceData
->MacString
);
635 // The GroupAddressList must be empty.
637 ASSERT (IsListEmpty (&MnpDeviceData
->GroupAddressList
));
642 gBS
->CloseEvent (MnpDeviceData
->TimeoutCheckTimer
);
643 gBS
->CloseEvent (MnpDeviceData
->MediaDetectTimer
);
644 gBS
->CloseEvent (MnpDeviceData
->PollTimer
);
647 // Free the Tx buffer pool.
649 NET_LIST_FOR_EACH_SAFE(Entry
, NextEntry
, &MnpDeviceData
->AllTxBufList
) {
650 TxBufWrap
= NET_LIST_USER_STRUCT (Entry
, MNP_TX_BUF_WRAP
, AllEntry
);
651 RemoveEntryList (Entry
);
652 FreePool (TxBufWrap
);
653 MnpDeviceData
->TxBufCount
--;
655 ASSERT (IsListEmpty (&MnpDeviceData
->AllTxBufList
));
656 ASSERT (MnpDeviceData
->TxBufCount
== 0);
659 // Free the RxNbufCache.
661 MnpFreeNbuf (MnpDeviceData
, MnpDeviceData
->RxNbufCache
);
664 // Flush the FreeNbufQue.
666 MnpDeviceData
->NbufCnt
-= MnpDeviceData
->FreeNbufQue
.BufNum
;
667 NetbufQueFlush (&MnpDeviceData
->FreeNbufQue
);
670 // Close the Simple Network Protocol.
673 MnpDeviceData
->ControllerHandle
,
674 &gEfiSimpleNetworkProtocolGuid
,
676 MnpDeviceData
->ControllerHandle
682 Create mnp service context data.
684 @param[in] MnpDeviceData Pointer to the mnp device context data.
685 @param[in] VlanId The VLAN ID.
686 @param[in] Priority The VLAN priority. If VlanId is 0,
689 @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.
693 MnpCreateServiceData (
694 IN MNP_DEVICE_DATA
*MnpDeviceData
,
696 IN UINT8 Priority OPTIONAL
699 EFI_HANDLE MnpServiceHandle
;
700 MNP_SERVICE_DATA
*MnpServiceData
;
702 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
703 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
706 // Initialize the Mnp Service Data.
708 MnpServiceData
= AllocateZeroPool (sizeof (MNP_SERVICE_DATA
));
709 if (MnpServiceData
== NULL
) {
710 DEBUG ((EFI_D_ERROR
, "MnpCreateServiceData: Faild to allocate memory for the new Mnp Service Data.\n"));
716 // Add to MNP service list
718 InsertTailList (&MnpDeviceData
->ServiceList
, &MnpServiceData
->Link
);
720 MnpServiceData
->Signature
= MNP_SERVICE_DATA_SIGNATURE
;
721 MnpServiceData
->MnpDeviceData
= MnpDeviceData
;
724 // Copy the ServiceBinding structure.
726 CopyMem (&MnpServiceData
->ServiceBinding
, &mMnpServiceBindingProtocol
, sizeof (EFI_SERVICE_BINDING_PROTOCOL
));
729 // Initialize the lists.
731 InitializeListHead (&MnpServiceData
->ChildrenList
);
733 SnpMode
= MnpDeviceData
->Snp
->Mode
;
736 // Create VLAN child handle
738 MnpServiceHandle
= MnpCreateVlanChild (
739 MnpDeviceData
->ImageHandle
,
740 MnpDeviceData
->ControllerHandle
,
742 &MnpServiceData
->DevicePath
744 if (MnpServiceHandle
== NULL
) {
745 DEBUG ((EFI_D_ERROR
, "MnpCreateServiceData: Faild to create child handle.\n"));
751 // Open VLAN Config Protocol by child
753 Status
= gBS
->OpenProtocol (
754 MnpDeviceData
->ControllerHandle
,
755 &gEfiVlanConfigProtocolGuid
,
756 (VOID
**) &VlanConfig
,
757 MnpDeviceData
->ImageHandle
,
759 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
761 if (EFI_ERROR (Status
)) {
766 // Reduce MTU for VLAN device
768 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
- NET_VLAN_TAG_LEN
;
771 // VlanId set to 0 means rx/tx untagged frame
773 MnpServiceHandle
= MnpDeviceData
->ControllerHandle
;
774 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
;
777 MnpServiceData
->ServiceHandle
= MnpServiceHandle
;
778 MnpServiceData
->VlanId
= VlanId
;
779 MnpServiceData
->Priority
= Priority
;
782 // Install the MNP Service Binding Protocol
784 Status
= gBS
->InstallMultipleProtocolInterfaces (
786 &gEfiManagedNetworkServiceBindingProtocolGuid
,
787 &MnpServiceData
->ServiceBinding
,
792 if (EFI_ERROR (Status
)) {
793 MnpDestroyServiceData (MnpServiceData
);
794 MnpServiceData
= NULL
;
797 return MnpServiceData
;
801 Destroy the MNP service context data.
803 @param[in, out] MnpServiceData Pointer to the mnp service context data.
805 @retval EFI_SUCCESS The mnp service context is destroyed.
806 @retval Others Errors as indicated.
810 MnpDestroyServiceData (
811 IN OUT MNP_SERVICE_DATA
*MnpServiceData
817 // Uninstall the MNP Service Binding Protocol
819 Status
= gBS
->UninstallMultipleProtocolInterfaces (
820 MnpServiceData
->ServiceHandle
,
821 &gEfiManagedNetworkServiceBindingProtocolGuid
,
822 &MnpServiceData
->ServiceBinding
,
825 if (EFI_ERROR (Status
)) {
829 if (MnpServiceData
->VlanId
!= 0) {
831 // Close VlanConfig Protocol opened by VLAN child handle
833 Status
= gBS
->CloseProtocol (
834 MnpServiceData
->MnpDeviceData
->ControllerHandle
,
835 &gEfiVlanConfigProtocolGuid
,
836 MnpServiceData
->MnpDeviceData
->ImageHandle
,
837 MnpServiceData
->ServiceHandle
839 if (EFI_ERROR (Status
)) {
844 // Uninstall Device Path Protocol to destroy the VLAN child handle
846 Status
= gBS
->UninstallMultipleProtocolInterfaces (
847 MnpServiceData
->ServiceHandle
,
848 &gEfiDevicePathProtocolGuid
,
849 MnpServiceData
->DevicePath
,
852 if (EFI_ERROR (Status
)) {
856 if (MnpServiceData
->DevicePath
!= NULL
) {
857 FreePool (MnpServiceData
->DevicePath
);
862 // Remove from MnpDeviceData service list
864 RemoveEntryList (&MnpServiceData
->Link
);
866 FreePool (MnpServiceData
);
872 Callback function which provided by user to remove one node in NetDestroyLinkList process.
874 @param[in] Entry The entry to be removed.
875 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
877 @retval EFI_SUCCESS The entry has been removed successfully.
878 @retval Others Fail to remove the entry.
883 MnpDestoryChildEntry (
884 IN LIST_ENTRY
*Entry
,
888 MNP_INSTANCE_DATA
*Instance
;
889 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
891 ServiceBinding
= (EFI_SERVICE_BINDING_PROTOCOL
*) Context
;
892 Instance
= CR (Entry
, MNP_INSTANCE_DATA
, InstEntry
, MNP_INSTANCE_DATA_SIGNATURE
);
893 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
897 Destroy all child of the MNP service data.
899 @param[in, out] MnpServiceData Pointer to the mnp service context data.
901 @retval EFI_SUCCESS All child are destroyed.
902 @retval Others Failed to destroy all child.
906 MnpDestroyServiceChild (
907 IN OUT MNP_SERVICE_DATA
*MnpServiceData
914 List
= &MnpServiceData
->ChildrenList
;
916 Status
= NetDestroyLinkList (
918 MnpDestoryChildEntry
,
919 &MnpServiceData
->ServiceBinding
,
922 if (EFI_ERROR (Status
) || ListLength
!= 0) {
923 return EFI_DEVICE_ERROR
;
930 Find the MNP Service Data for given VLAN ID.
932 @param[in] MnpDeviceData Pointer to the mnp device context data.
933 @param[in] VlanId The VLAN ID.
935 @return A pointer to MNP_SERVICE_DATA or NULL if not found.
940 IN MNP_DEVICE_DATA
*MnpDeviceData
,
945 MNP_SERVICE_DATA
*MnpServiceData
;
947 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->ServiceList
) {
949 // Check VLAN ID of each Mnp Service Data
951 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
952 if (MnpServiceData
->VlanId
== VlanId
) {
953 return MnpServiceData
;
961 Initialize the mnp instance context data.
963 @param[in] MnpServiceData Pointer to the mnp service context data.
964 @param[in, out] Instance Pointer to the mnp instance context data
969 MnpInitializeInstanceData (
970 IN MNP_SERVICE_DATA
*MnpServiceData
,
971 IN OUT MNP_INSTANCE_DATA
*Instance
974 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
975 ASSERT (Instance
!= NULL
);
978 // Set the signature.
980 Instance
->Signature
= MNP_INSTANCE_DATA_SIGNATURE
;
983 // Copy the MNP Protocol interfaces from the template.
985 CopyMem (&Instance
->ManagedNetwork
, &mMnpProtocolTemplate
, sizeof (Instance
->ManagedNetwork
));
988 // Copy the default config data.
990 CopyMem (&Instance
->ConfigData
, &mMnpDefaultConfigData
, sizeof (Instance
->ConfigData
));
993 // Initialize the lists.
995 InitializeListHead (&Instance
->GroupCtrlBlkList
);
996 InitializeListHead (&Instance
->RcvdPacketQueue
);
997 InitializeListHead (&Instance
->RxDeliveredPacketQueue
);
1000 // Initialize the RxToken Map.
1002 NetMapInit (&Instance
->RxTokenMap
);
1005 // Save the MnpServiceData info.
1007 Instance
->MnpServiceData
= MnpServiceData
;
1012 Check whether the token specified by Arg matches the token in Item.
1014 @param[in] Map Pointer to the NET_MAP.
1015 @param[in] Item Pointer to the NET_MAP_ITEM.
1016 @param[in] Arg Pointer to the Arg, it's a pointer to the token to
1019 @retval EFI_SUCCESS The token specified by Arg is different from the
1021 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
1029 IN NET_MAP_ITEM
*Item
,
1033 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
;
1034 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenInItem
;
1036 Token
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Arg
;
1037 TokenInItem
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
1039 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
1041 // The token is the same either the two tokens equals or the Events in
1042 // the two tokens are the same.
1044 return EFI_ACCESS_DENIED
;
1051 Cancel the token specified by Arg if it matches the token in Item.
1053 @param[in, out] Map Pointer to the NET_MAP.
1054 @param[in, out] Item Pointer to the NET_MAP_ITEM.
1055 @param[in] Arg Pointer to the Arg, it's a pointer to the
1058 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,
1059 or the Arg isn't NULL, and the token in Item is
1060 different from the Arg.
1061 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
1062 Arg, and the token is cancelled.
1068 IN OUT NET_MAP
*Map
,
1069 IN OUT NET_MAP_ITEM
*Item
,
1073 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenToCancel
;
1075 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
1077 // The token in Item is not the token specified by Arg.
1082 TokenToCancel
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
1085 // Remove the item from the map.
1087 NetMapRemoveItem (Map
, Item
, NULL
);
1090 // Cancel this token with status set to EFI_ABORTED.
1092 TokenToCancel
->Status
= EFI_ABORTED
;
1093 gBS
->SignalEvent (TokenToCancel
->Event
);
1097 // Only abort the token specified by Arg if Arg isn't NULL.
1107 Start and initialize the simple network.
1109 @param[in] Snp Pointer to the simple network protocol.
1111 @retval EFI_SUCCESS The simple network protocol is started.
1112 @retval Others Other errors as indicated.
1117 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
1122 ASSERT (Snp
!= NULL
);
1125 // Start the simple network.
1127 Status
= Snp
->Start (Snp
);
1129 if (!EFI_ERROR (Status
)) {
1131 // Initialize the simple network.
1133 Status
= Snp
->Initialize (Snp
, 0, 0);
1141 Stop the simple network.
1143 @param[in] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
1145 @retval EFI_SUCCESS The simple network is stopped.
1146 @retval Others Other errors as indicated.
1151 IN MNP_DEVICE_DATA
*MnpDeviceData
1155 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1157 Snp
= MnpDeviceData
->Snp
;
1158 ASSERT (Snp
!= NULL
);
1161 // Recycle all the transmit buffer from SNP.
1163 Status
= MnpRecycleTxBuf (MnpDeviceData
);
1164 if (EFI_ERROR (Status
)) {
1169 // Shut down the simple network.
1171 Status
= Snp
->Shutdown (Snp
);
1172 if (!EFI_ERROR (Status
)) {
1174 // Stop the simple network.
1176 Status
= Snp
->Stop (Snp
);
1184 Start the managed network, this function is called when one instance is configured
1187 @param[in, out] MnpServiceData Pointer to the mnp service context data.
1188 @param[in] IsConfigUpdate The instance is reconfigured or it's the first
1189 time the instanced is configured.
1190 @param[in] EnableSystemPoll Enable the system polling or not.
1192 @retval EFI_SUCCESS The managed network is started and some
1193 configuration is updated.
1194 @retval Others Other errors as indicated.
1199 IN OUT MNP_SERVICE_DATA
*MnpServiceData
,
1200 IN BOOLEAN IsConfigUpdate
,
1201 IN BOOLEAN EnableSystemPoll
1205 EFI_TIMER_DELAY TimerOpType
;
1206 MNP_DEVICE_DATA
*MnpDeviceData
;
1208 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1210 Status
= EFI_SUCCESS
;
1211 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1213 if (!IsConfigUpdate
) {
1215 // If it's not a configuration update, increase the configured children number.
1217 MnpDeviceData
->ConfiguredChildrenNumber
++;
1219 if (MnpDeviceData
->ConfiguredChildrenNumber
== 1) {
1221 // It's the first configured child, start the simple network.
1223 Status
= MnpStartSnp (MnpDeviceData
->Snp
);
1224 if (EFI_ERROR (Status
)) {
1225 DEBUG ((EFI_D_ERROR
, "MnpStart: MnpStartSnp failed, %r.\n", Status
));
1231 // Start the timeout timer.
1233 Status
= gBS
->SetTimer (
1234 MnpDeviceData
->TimeoutCheckTimer
,
1236 MNP_TIMEOUT_CHECK_INTERVAL
1238 if (EFI_ERROR (Status
)) {
1241 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
1249 // Start the media detection timer.
1251 Status
= gBS
->SetTimer (
1252 MnpDeviceData
->MediaDetectTimer
,
1254 MNP_MEDIA_DETECT_INTERVAL
1256 if (EFI_ERROR (Status
)) {
1259 "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",
1268 if (MnpDeviceData
->EnableSystemPoll
^ EnableSystemPoll
) {
1270 // The EnableSystemPoll differs with the current state, disable or enable
1273 TimerOpType
= EnableSystemPoll
? TimerPeriodic
: TimerCancel
;
1275 Status
= gBS
->SetTimer (MnpDeviceData
->PollTimer
, TimerOpType
, MNP_SYS_POLL_INTERVAL
);
1276 if (EFI_ERROR (Status
)) {
1277 DEBUG ((EFI_D_ERROR
, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status
));
1282 MnpDeviceData
->EnableSystemPoll
= EnableSystemPoll
;
1286 // Change the receive filters if need.
1288 Status
= MnpConfigReceiveFilters (MnpDeviceData
);
1296 Stop the managed network.
1298 @param[in, out] MnpServiceData Pointer to the mnp service context data.
1300 @retval EFI_SUCCESS The managed network is stopped.
1301 @retval Others Other errors as indicated.
1306 IN OUT MNP_SERVICE_DATA
*MnpServiceData
1310 MNP_DEVICE_DATA
*MnpDeviceData
;
1312 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1313 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1314 ASSERT (MnpDeviceData
->ConfiguredChildrenNumber
> 0);
1317 // Configure the receive filters.
1319 MnpConfigReceiveFilters (MnpDeviceData
);
1322 // Decrease the children number.
1324 MnpDeviceData
->ConfiguredChildrenNumber
--;
1326 if (MnpDeviceData
->ConfiguredChildrenNumber
> 0) {
1328 // If there are other configured chilren, return and keep the timers and
1329 // simple network unchanged.
1335 // No configured children now.
1337 if (MnpDeviceData
->EnableSystemPoll
) {
1339 // The system poll in on, cancel the poll timer.
1341 Status
= gBS
->SetTimer (MnpDeviceData
->PollTimer
, TimerCancel
, 0);
1342 MnpDeviceData
->EnableSystemPoll
= FALSE
;
1346 // Cancel the timeout timer.
1348 Status
= gBS
->SetTimer (MnpDeviceData
->TimeoutCheckTimer
, TimerCancel
, 0);
1351 // Cancel the media detect timer.
1353 Status
= gBS
->SetTimer (MnpDeviceData
->MediaDetectTimer
, TimerCancel
, 0);
1356 // Stop the simple network.
1358 Status
= MnpStopSnp (MnpDeviceData
);
1364 Flush the instance's received data.
1366 @param[in, out] Instance Pointer to the mnp instance context data.
1370 MnpFlushRcvdDataQueue (
1371 IN OUT MNP_INSTANCE_DATA
*Instance
1375 MNP_RXDATA_WRAP
*RxDataWrap
;
1377 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1379 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1381 while (!IsListEmpty (&Instance
->RcvdPacketQueue
)) {
1383 // Remove all the Wraps.
1385 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
1388 // Recycle the RxDataWrap.
1390 MnpRecycleRxData (NULL
, (VOID
*) RxDataWrap
);
1391 Instance
->RcvdPacketQueueSize
--;
1394 ASSERT (Instance
->RcvdPacketQueueSize
== 0);
1396 gBS
->RestoreTPL (OldTpl
);
1401 Configure the Instance using ConfigData.
1403 @param[in, out] Instance Pointer to the mnp instance context data.
1404 @param[in] ConfigData Pointer to the configuration data used to configure
1407 @retval EFI_SUCCESS The Instance is configured.
1408 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1409 implementation doesn't support it.
1410 @retval Others Other errors as indicated.
1414 MnpConfigureInstance (
1415 IN OUT MNP_INSTANCE_DATA
*Instance
,
1416 IN EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData OPTIONAL
1420 MNP_SERVICE_DATA
*MnpServiceData
;
1421 MNP_DEVICE_DATA
*MnpDeviceData
;
1422 EFI_MANAGED_NETWORK_CONFIG_DATA
*OldConfigData
;
1423 EFI_MANAGED_NETWORK_CONFIG_DATA
*NewConfigData
;
1424 BOOLEAN IsConfigUpdate
;
1426 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1428 if ((ConfigData
!= NULL
) && ConfigData
->EnableReceiveTimestamps
) {
1430 // Don't support timestamp.
1432 return EFI_UNSUPPORTED
;
1435 Status
= EFI_SUCCESS
;
1437 MnpServiceData
= Instance
->MnpServiceData
;
1438 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1439 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1441 IsConfigUpdate
= (BOOLEAN
) ((Instance
->Configured
) && (ConfigData
!= NULL
));
1443 OldConfigData
= &Instance
->ConfigData
;
1444 NewConfigData
= ConfigData
;
1445 if (NewConfigData
== NULL
) {
1447 // Restore back the default config data if a reset of this instance
1450 NewConfigData
= &mMnpDefaultConfigData
;
1454 // Reset the instance's receive filter.
1456 Instance
->ReceiveFilter
= 0;
1459 // Clear the receive counters according to the old ConfigData.
1461 if (OldConfigData
->EnableUnicastReceive
) {
1462 MnpDeviceData
->UnicastCount
--;
1465 if (OldConfigData
->EnableMulticastReceive
) {
1466 MnpDeviceData
->MulticastCount
--;
1469 if (OldConfigData
->EnableBroadcastReceive
) {
1470 MnpDeviceData
->BroadcastCount
--;
1473 if (OldConfigData
->EnablePromiscuousReceive
) {
1474 MnpDeviceData
->PromiscuousCount
--;
1478 // Set the receive filter counters and the receive filter of the
1479 // instance according to the new ConfigData.
1481 if (NewConfigData
->EnableUnicastReceive
) {
1482 MnpDeviceData
->UnicastCount
++;
1483 Instance
->ReceiveFilter
|= MNP_RECEIVE_UNICAST
;
1486 if (NewConfigData
->EnableMulticastReceive
) {
1487 MnpDeviceData
->MulticastCount
++;
1490 if (NewConfigData
->EnableBroadcastReceive
) {
1491 MnpDeviceData
->BroadcastCount
++;
1492 Instance
->ReceiveFilter
|= MNP_RECEIVE_BROADCAST
;
1495 if (NewConfigData
->EnablePromiscuousReceive
) {
1496 MnpDeviceData
->PromiscuousCount
++;
1499 if (OldConfigData
->FlushQueuesOnReset
) {
1500 MnpFlushRcvdDataQueue (Instance
);
1503 if (ConfigData
== NULL
) {
1504 Instance
->ManagedNetwork
.Cancel (&Instance
->ManagedNetwork
, NULL
);
1507 if (!NewConfigData
->EnableMulticastReceive
) {
1508 MnpGroupOp (Instance
, FALSE
, NULL
, NULL
);
1512 // Save the new configuration data.
1514 CopyMem (OldConfigData
, NewConfigData
, sizeof (*OldConfigData
));
1516 Instance
->Configured
= (BOOLEAN
) (ConfigData
!= NULL
);
1517 if (Instance
->Configured
) {
1519 // The instance is configured, start the Mnp.
1524 (BOOLEAN
) !NewConfigData
->DisableBackgroundPolling
1528 // The instance is changed to the unconfigured state, stop the Mnp.
1530 Status
= MnpStop (MnpServiceData
);
1537 Configure the Snp receive filters according to the instances' receive filter
1540 @param[in] MnpDeviceData Pointer to the mnp device context data.
1542 @retval EFI_SUCCESS The receive filters is configured.
1543 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due
1544 to lack of memory resource.
1548 MnpConfigReceiveFilters (
1549 IN MNP_DEVICE_DATA
*MnpDeviceData
1553 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1554 EFI_MAC_ADDRESS
*MCastFilter
;
1555 UINT32 MCastFilterCnt
;
1556 UINT32 EnableFilterBits
;
1557 UINT32 DisableFilterBits
;
1558 BOOLEAN ResetMCastFilters
;
1561 MNP_GROUP_ADDRESS
*GroupAddress
;
1563 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1565 Snp
= MnpDeviceData
->Snp
;
1568 // Initialize the enable filter and disable filter.
1570 EnableFilterBits
= 0;
1571 DisableFilterBits
= Snp
->Mode
->ReceiveFilterMask
;
1573 if (MnpDeviceData
->UnicastCount
!= 0) {
1575 // Enable unicast if any instance wants to receive unicast.
1577 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1580 if (MnpDeviceData
->BroadcastCount
!= 0) {
1582 // Enable broadcast if any instance wants to receive broadcast.
1584 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1589 ResetMCastFilters
= TRUE
;
1591 if ((MnpDeviceData
->MulticastCount
!= 0) && (MnpDeviceData
->GroupAddressCount
!= 0)) {
1593 // There are instances configured to receive multicast and already some group
1594 // addresses are joined.
1597 ResetMCastFilters
= FALSE
;
1599 if (MnpDeviceData
->GroupAddressCount
<= Snp
->Mode
->MaxMCastFilterCount
) {
1601 // The joind group address is less than simple network's maximum count.
1602 // Just configure the snp to do the multicast filtering.
1605 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1608 // Allocate pool for the mulicast addresses.
1610 MCastFilterCnt
= MnpDeviceData
->GroupAddressCount
;
1611 MCastFilter
= AllocatePool (sizeof (EFI_MAC_ADDRESS
) * MCastFilterCnt
);
1612 if (MCastFilter
== NULL
) {
1613 DEBUG ((EFI_D_ERROR
, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1615 return EFI_OUT_OF_RESOURCES
;
1619 // Fill the multicast HW address buffer.
1622 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->GroupAddressList
) {
1624 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1625 CopyMem (MCastFilter
+ Index
, &GroupAddress
->Address
, sizeof (*(MCastFilter
+ Index
)));
1628 ASSERT (Index
<= MCastFilterCnt
);
1632 // The maximum multicast is reached, set the filter to be promiscuous
1636 if ((Snp
->Mode
->ReceiveFilterMask
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) != 0) {
1637 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1640 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1641 // set the NIC to be promiscuous although this will tremendously degrade
1644 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1649 if (MnpDeviceData
->PromiscuousCount
!= 0) {
1651 // Enable promiscuous if any instance wants to receive promiscuous.
1653 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1657 // Set the disable filter.
1659 DisableFilterBits
^= EnableFilterBits
;
1662 // Configure the receive filters of SNP.
1664 Status
= Snp
->ReceiveFilters (
1673 if (EFI_ERROR (Status
)) {
1676 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1682 if (MCastFilter
!= NULL
) {
1684 // Free the buffer used to hold the group addresses.
1686 FreePool (MCastFilter
);
1694 Add a group address control block which controls the MacAddress for
1697 @param[in, out] Instance Pointer to the mnp instance context data.
1698 @param[in, out] CtrlBlk Pointer to the group address control block.
1699 @param[in, out] GroupAddress Pointer to the group adress.
1700 @param[in] MacAddress Pointer to the mac address.
1701 @param[in] HwAddressSize The hardware address size.
1703 @retval EFI_SUCCESS The group address control block is added.
1704 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1708 MnpGroupOpAddCtrlBlk (
1709 IN OUT MNP_INSTANCE_DATA
*Instance
,
1710 IN OUT MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
1711 IN OUT MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
1712 IN EFI_MAC_ADDRESS
*MacAddress
,
1713 IN UINT32 HwAddressSize
1716 MNP_DEVICE_DATA
*MnpDeviceData
;
1718 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1720 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1721 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1723 if (GroupAddress
== NULL
) {
1724 ASSERT (MacAddress
!= NULL
);
1727 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1729 GroupAddress
= AllocatePool (sizeof (MNP_GROUP_ADDRESS
));
1730 if (GroupAddress
== NULL
) {
1732 DEBUG ((EFI_D_ERROR
, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1734 return EFI_OUT_OF_RESOURCES
;
1737 CopyMem (&GroupAddress
->Address
, MacAddress
, sizeof (GroupAddress
->Address
));
1738 GroupAddress
->RefCnt
= 0;
1740 &MnpDeviceData
->GroupAddressList
,
1741 &GroupAddress
->AddrEntry
1743 MnpDeviceData
->GroupAddressCount
++;
1747 // Increase the RefCnt.
1749 GroupAddress
->RefCnt
++;
1752 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1754 CtrlBlk
->GroupAddress
= GroupAddress
;
1755 InsertTailList (&Instance
->GroupCtrlBlkList
, &CtrlBlk
->CtrlBlkEntry
);
1762 Delete a group control block from the instance. If the controlled group address's
1763 reference count reaches zero, the group address is removed too.
1765 @param[in] Instance Pointer to the instance context data.
1766 @param[in] CtrlBlk Pointer to the group control block to delete.
1768 @return The group address controlled by the control block is no longer used or not.
1772 MnpGroupOpDelCtrlBlk (
1773 IN MNP_INSTANCE_DATA
*Instance
,
1774 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
1777 MNP_DEVICE_DATA
*MnpDeviceData
;
1778 MNP_GROUP_ADDRESS
*GroupAddress
;
1780 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1782 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1783 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1786 // Remove and free the CtrlBlk.
1788 GroupAddress
= CtrlBlk
->GroupAddress
;
1789 RemoveEntryList (&CtrlBlk
->CtrlBlkEntry
);
1792 ASSERT (GroupAddress
->RefCnt
> 0);
1795 // Count down the RefCnt.
1797 GroupAddress
->RefCnt
--;
1799 if (GroupAddress
->RefCnt
== 0) {
1801 // Free this GroupAddress entry if no instance uses it.
1803 MnpDeviceData
->GroupAddressCount
--;
1804 RemoveEntryList (&GroupAddress
->AddrEntry
);
1805 FreePool (GroupAddress
);
1815 Do the group operations for this instance.
1817 @param[in, out] Instance Pointer to the instance context data.
1818 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to
1819 leave a group/groups.
1820 @param[in] MacAddress Pointer to the group address to join or leave.
1821 @param[in] CtrlBlk Pointer to the group control block if JoinFlag
1824 @retval EFI_SUCCESS The group operation finished.
1825 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1826 @retval Others Other errors as indicated.
1831 IN OUT MNP_INSTANCE_DATA
*Instance
,
1832 IN BOOLEAN JoinFlag
,
1833 IN EFI_MAC_ADDRESS
*MacAddress OPTIONAL
,
1834 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk OPTIONAL
1837 MNP_DEVICE_DATA
*MnpDeviceData
;
1839 LIST_ENTRY
*NextEntry
;
1840 MNP_GROUP_ADDRESS
*GroupAddress
;
1841 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1842 MNP_GROUP_CONTROL_BLOCK
*NewCtrlBlk
;
1844 BOOLEAN AddressExist
;
1847 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1849 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1850 SnpMode
= MnpDeviceData
->Snp
->Mode
;
1854 // A new gropu address is to be added.
1856 GroupAddress
= NULL
;
1857 AddressExist
= FALSE
;
1860 // Allocate memory for the control block.
1862 NewCtrlBlk
= AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK
));
1863 if (NewCtrlBlk
== NULL
) {
1864 DEBUG ((EFI_D_ERROR
, "MnpGroupOp: Failed to allocate memory resource.\n"));
1866 return EFI_OUT_OF_RESOURCES
;
1869 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->GroupAddressList
) {
1871 // Check whether the MacAddress is already joined by other instances.
1873 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1874 if (CompareMem (MacAddress
, &GroupAddress
->Address
, SnpMode
->HwAddressSize
) == 0) {
1875 AddressExist
= TRUE
;
1880 if (!AddressExist
) {
1881 GroupAddress
= NULL
;
1885 // Add the GroupAddress for this instance.
1887 Status
= MnpGroupOpAddCtrlBlk (
1892 SnpMode
->HwAddressSize
1894 if (EFI_ERROR (Status
)) {
1900 if (MacAddress
!= NULL
) {
1901 ASSERT (CtrlBlk
!= NULL
);
1904 // Leave the specific multicast mac address.
1906 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, CtrlBlk
);
1909 // Leave all multicast mac addresses.
1913 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Instance
->GroupCtrlBlkList
) {
1915 NewCtrlBlk
= NET_LIST_USER_STRUCT (
1917 MNP_GROUP_CONTROL_BLOCK
,
1921 // Update is required if the group address left is no longer used
1922 // by other instances.
1924 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, NewCtrlBlk
);
1929 Status
= EFI_SUCCESS
;
1933 // Reconfigure the receive filters if necessary.
1935 Status
= MnpConfigReceiveFilters (MnpDeviceData
);