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 ((DEBUG_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
;
92 Allocate a free NET_BUF from MnpDeviceData->FreeNbufQue. If there is none
93 in the queue, first try to allocate some and add them into the queue, then
94 fetch the NET_BUF from the updated FreeNbufQue.
96 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
98 @return Pointer to the allocated free NET_BUF structure, if NULL the
104 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
108 NET_BUF_QUEUE
*FreeNbufQue
;
112 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
114 FreeNbufQue
= &MnpDeviceData
->FreeNbufQue
;
115 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
118 // Check whether there are available buffers, or else try to add some.
120 if (FreeNbufQue
->BufNum
== 0) {
121 if ((MnpDeviceData
->NbufCnt
+ MNP_NET_BUFFER_INCREASEMENT
) > MNP_MAX_NET_BUFFER_NUM
) {
124 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
132 Status
= MnpAddFreeNbuf (MnpDeviceData
, MNP_NET_BUFFER_INCREASEMENT
);
133 if (EFI_ERROR (Status
)) {
136 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
141 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
142 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
147 Nbuf
= NetbufQueRemove (FreeNbufQue
);
150 // Increase the RefCnt.
157 gBS
->RestoreTPL (OldTpl
);
163 Try to reclaim the Nbuf into the buffer pool.
165 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
166 @param[in, out] Nbuf Pointer to the NET_BUF to free.
171 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
177 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
178 ASSERT (Nbuf
->RefCnt
> 1);
180 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
184 if (Nbuf
->RefCnt
== 1) {
186 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
188 NetbufTrim (Nbuf
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
190 if (NetbufAllocSpace (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_HEAD
) != NULL
) {
192 // There is space reserved for vlan tag in the head, reclaim it
194 NetbufTrim (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_TAIL
);
197 NetbufQueAppend (&MnpDeviceData
->FreeNbufQue
, Nbuf
);
200 gBS
->RestoreTPL (OldTpl
);
204 Add Count of TX buffers to MnpDeviceData->AllTxBufList and MnpDeviceData->FreeTxBufList.
205 The length of the buffer is specified by MnpDeviceData->BufferLength.
207 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
208 @param[in] Count Number of TX buffers to add.
210 @retval EFI_SUCCESS The specified amount of TX buffers are allocated.
211 @retval EFI_OUT_OF_RESOURCES Failed to allocate a TX buffer.
216 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
222 MNP_TX_BUF_WRAP
*TxBufWrap
;
224 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
225 ASSERT ((Count
> 0) && (MnpDeviceData
->BufferLength
> 0));
227 Status
= EFI_SUCCESS
;
228 for (Index
= 0; Index
< Count
; Index
++) {
229 TxBufWrap
= (MNP_TX_BUF_WRAP
*)AllocatePool (OFFSET_OF (MNP_TX_BUF_WRAP
, TxBuf
) + MnpDeviceData
->BufferLength
);
230 if (TxBufWrap
== NULL
) {
231 DEBUG ((DEBUG_ERROR
, "MnpAddFreeTxBuf: TxBuf Alloc failed.\n"));
233 Status
= EFI_OUT_OF_RESOURCES
;
237 DEBUG ((DEBUG_INFO
, "MnpAddFreeTxBuf: Add TxBufWrap %p, TxBuf %p\n", TxBufWrap
, TxBufWrap
->TxBuf
));
238 TxBufWrap
->Signature
= MNP_TX_BUF_WRAP_SIGNATURE
;
239 TxBufWrap
->InUse
= FALSE
;
240 InsertTailList (&MnpDeviceData
->FreeTxBufList
, &TxBufWrap
->WrapEntry
);
241 InsertTailList (&MnpDeviceData
->AllTxBufList
, &TxBufWrap
->AllEntry
);
244 MnpDeviceData
->TxBufCount
+= Index
;
249 Allocate a free TX buffer from MnpDeviceData->FreeTxBufList. If there is none
250 in the queue, first try to recycle some from SNP, then try to allocate some and add
251 them into the queue, then fetch the NET_BUF from the updated FreeTxBufList.
253 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
255 @return Pointer to the allocated free NET_BUF structure, if NULL the
261 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
268 MNP_TX_BUF_WRAP
*TxBufWrap
;
270 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
272 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
274 if (IsListEmpty (&MnpDeviceData
->FreeTxBufList
)) {
276 // First try to recycle some TX buffer from SNP
278 Status
= MnpRecycleTxBuf (MnpDeviceData
);
279 if (EFI_ERROR (Status
)) {
285 // If still no free TX buffer, allocate more.
287 if (IsListEmpty (&MnpDeviceData
->FreeTxBufList
)) {
288 if ((MnpDeviceData
->TxBufCount
+ MNP_TX_BUFFER_INCREASEMENT
) > MNP_MAX_TX_BUFFER_NUM
) {
291 "MnpAllocTxBuf: The maximum TxBuf size is reached for MNP driver instance %p.\n",
299 Status
= MnpAddFreeTxBuf (MnpDeviceData
, MNP_TX_BUFFER_INCREASEMENT
);
300 if (IsListEmpty (&MnpDeviceData
->FreeTxBufList
)) {
303 "MnpAllocNbuf: Failed to add TxBuf into the FreeTxBufList, %r.\n",
313 ASSERT (!IsListEmpty (&MnpDeviceData
->FreeTxBufList
));
314 Entry
= MnpDeviceData
->FreeTxBufList
.ForwardLink
;
315 RemoveEntryList (MnpDeviceData
->FreeTxBufList
.ForwardLink
);
316 TxBufWrap
= NET_LIST_USER_STRUCT_S (Entry
, MNP_TX_BUF_WRAP
, WrapEntry
, MNP_TX_BUF_WRAP_SIGNATURE
);
317 TxBufWrap
->InUse
= TRUE
;
318 TxBuf
= TxBufWrap
->TxBuf
;
321 gBS
->RestoreTPL (OldTpl
);
327 Try to reclaim the TX buffer into the buffer pool.
329 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
330 @param[in, out] TxBuf Pointer to the TX buffer to free.
335 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
339 MNP_TX_BUF_WRAP
*TxBufWrap
;
342 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
348 TxBufWrap
= NET_LIST_USER_STRUCT (TxBuf
, MNP_TX_BUF_WRAP
, TxBuf
);
349 if (TxBufWrap
->Signature
!= MNP_TX_BUF_WRAP_SIGNATURE
) {
352 "MnpFreeTxBuf: Signature check failed in MnpFreeTxBuf.\n")
357 if (!TxBufWrap
->InUse
) {
360 "MnpFreeTxBuf: Duplicated recycle report from SNP.\n")
365 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
366 InsertTailList (&MnpDeviceData
->FreeTxBufList
, &TxBufWrap
->WrapEntry
);
367 TxBufWrap
->InUse
= FALSE
;
368 gBS
->RestoreTPL (OldTpl
);
372 Try to recycle all the transmitted buffer address from SNP.
374 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
376 @retval EFI_SUCCESS Successed to recyclethe transmitted buffer address.
377 @retval Others Failed to recyclethe transmitted buffer address.
382 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
386 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
389 Snp
= MnpDeviceData
->Snp
;
390 ASSERT (Snp
!= NULL
);
394 Status
= Snp
->GetStatus (Snp
, NULL
, (VOID
**)&TxBuf
);
395 if (EFI_ERROR (Status
)) {
400 MnpFreeTxBuf (MnpDeviceData
, TxBuf
);
402 } while (TxBuf
!= NULL
);
408 Initialize the mnp device context data.
410 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
411 @param[in] ImageHandle The driver image handle.
412 @param[in] ControllerHandle Handle of device to bind driver to.
414 @retval EFI_SUCCESS The mnp service context is initialized.
415 @retval EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.
416 @retval Others Other errors as indicated.
420 MnpInitializeDeviceData (
421 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
422 IN EFI_HANDLE ImageHandle
,
423 IN EFI_HANDLE ControllerHandle
427 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
428 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
430 MnpDeviceData
->Signature
= MNP_DEVICE_DATA_SIGNATURE
;
431 MnpDeviceData
->ImageHandle
= ImageHandle
;
432 MnpDeviceData
->ControllerHandle
= ControllerHandle
;
435 // Copy the MNP Protocol interfaces from the template.
437 CopyMem (&MnpDeviceData
->VlanConfig
, &mVlanConfigProtocolTemplate
, sizeof (EFI_VLAN_CONFIG_PROTOCOL
));
440 // Open the Simple Network protocol.
442 Status
= gBS
->OpenProtocol (
444 &gEfiSimpleNetworkProtocolGuid
,
448 EFI_OPEN_PROTOCOL_BY_DRIVER
450 if (EFI_ERROR (Status
)) {
451 return EFI_UNSUPPORTED
;
458 MnpDeviceData
->Snp
= Snp
;
461 // Initialize the lists.
463 InitializeListHead (&MnpDeviceData
->ServiceList
);
464 InitializeListHead (&MnpDeviceData
->GroupAddressList
);
467 // Get the buffer length used to allocate NET_BUF to hold data received
468 // from SNP. Do this before fill the FreeNetBufQue.
471 MnpDeviceData
->BufferLength
= SnpMode
->MediaHeaderSize
+ NET_VLAN_TAG_LEN
+ SnpMode
->MaxPacketSize
+ NET_ETHER_FCS_SIZE
;
474 // Make sure the protocol headers immediately following the media header
475 // 4-byte aligned, and also preserve additional space for VLAN tag
477 MnpDeviceData
->PaddingSize
= ((4 - SnpMode
->MediaHeaderSize
) & 0x3) + NET_VLAN_TAG_LEN
;
480 // Initialize MAC string which will be used as VLAN configuration variable name
482 Status
= NetLibGetMacString (ControllerHandle
, ImageHandle
, &MnpDeviceData
->MacString
);
483 if (EFI_ERROR (Status
)) {
488 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
490 NetbufQueInit (&MnpDeviceData
->FreeNbufQue
);
491 Status
= MnpAddFreeNbuf (MnpDeviceData
, MNP_INIT_NET_BUFFER_NUM
);
492 if (EFI_ERROR (Status
)) {
493 DEBUG ((DEBUG_ERROR
, "MnpInitializeDeviceData: MnpAddFreeNbuf failed, %r.\n", Status
));
499 // Get one NET_BUF from the FreeNbufQue for rx cache.
501 MnpDeviceData
->RxNbufCache
= MnpAllocNbuf (MnpDeviceData
);
503 MnpDeviceData
->RxNbufCache
,
504 MnpDeviceData
->BufferLength
,
509 // Allocate buffer pool for tx.
511 InitializeListHead (&MnpDeviceData
->FreeTxBufList
);
512 InitializeListHead (&MnpDeviceData
->AllTxBufList
);
513 MnpDeviceData
->TxBufCount
= 0;
516 // Create the system poll timer.
518 Status
= gBS
->CreateEvent (
519 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
523 &MnpDeviceData
->PollTimer
525 if (EFI_ERROR (Status
)) {
526 DEBUG ((DEBUG_ERROR
, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));
532 // Create the timer for packet timeout check.
534 Status
= gBS
->CreateEvent (
535 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
537 MnpCheckPacketTimeout
,
539 &MnpDeviceData
->TimeoutCheckTimer
541 if (EFI_ERROR (Status
)) {
542 DEBUG ((DEBUG_ERROR
, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));
548 // Create the timer for media detection.
550 Status
= gBS
->CreateEvent (
551 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
555 &MnpDeviceData
->MediaDetectTimer
557 if (EFI_ERROR (Status
)) {
558 DEBUG ((DEBUG_ERROR
, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n"));
564 if (EFI_ERROR (Status
)) {
566 // Free the dynamic allocated resources if necessary.
568 if (MnpDeviceData
->MacString
!= NULL
) {
569 FreePool (MnpDeviceData
->MacString
);
572 if (MnpDeviceData
->TimeoutCheckTimer
!= NULL
) {
573 gBS
->CloseEvent (MnpDeviceData
->TimeoutCheckTimer
);
576 if (MnpDeviceData
->MediaDetectTimer
!= NULL
) {
577 gBS
->CloseEvent (MnpDeviceData
->MediaDetectTimer
);
580 if (MnpDeviceData
->PollTimer
!= NULL
) {
581 gBS
->CloseEvent (MnpDeviceData
->PollTimer
);
584 if (MnpDeviceData
->RxNbufCache
!= NULL
) {
585 MnpFreeNbuf (MnpDeviceData
, MnpDeviceData
->RxNbufCache
);
588 if (MnpDeviceData
->FreeNbufQue
.BufNum
!= 0) {
589 NetbufQueFlush (&MnpDeviceData
->FreeNbufQue
);
593 // Close the Simple Network Protocol.
597 &gEfiSimpleNetworkProtocolGuid
,
607 Destroy the MNP device context data.
609 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
610 @param[in] ImageHandle The driver image handle.
614 MnpDestroyDeviceData (
615 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
616 IN EFI_HANDLE ImageHandle
620 LIST_ENTRY
*NextEntry
;
621 MNP_TX_BUF_WRAP
*TxBufWrap
;
623 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
626 // Free Vlan Config variable name string
628 if (MnpDeviceData
->MacString
!= NULL
) {
629 FreePool (MnpDeviceData
->MacString
);
633 // The GroupAddressList must be empty.
635 ASSERT (IsListEmpty (&MnpDeviceData
->GroupAddressList
));
640 gBS
->CloseEvent (MnpDeviceData
->TimeoutCheckTimer
);
641 gBS
->CloseEvent (MnpDeviceData
->MediaDetectTimer
);
642 gBS
->CloseEvent (MnpDeviceData
->PollTimer
);
645 // Free the Tx buffer pool.
647 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &MnpDeviceData
->AllTxBufList
) {
648 TxBufWrap
= NET_LIST_USER_STRUCT (Entry
, MNP_TX_BUF_WRAP
, AllEntry
);
649 RemoveEntryList (Entry
);
650 FreePool (TxBufWrap
);
651 MnpDeviceData
->TxBufCount
--;
653 ASSERT (IsListEmpty (&MnpDeviceData
->AllTxBufList
));
654 ASSERT (MnpDeviceData
->TxBufCount
== 0);
657 // Free the RxNbufCache.
659 MnpFreeNbuf (MnpDeviceData
, MnpDeviceData
->RxNbufCache
);
662 // Flush the FreeNbufQue.
664 MnpDeviceData
->NbufCnt
-= MnpDeviceData
->FreeNbufQue
.BufNum
;
665 NetbufQueFlush (&MnpDeviceData
->FreeNbufQue
);
668 // Close the Simple Network Protocol.
671 MnpDeviceData
->ControllerHandle
,
672 &gEfiSimpleNetworkProtocolGuid
,
674 MnpDeviceData
->ControllerHandle
679 Create mnp service context data.
681 @param[in] MnpDeviceData Pointer to the mnp device context data.
682 @param[in] VlanId The VLAN ID.
683 @param[in] Priority The VLAN priority. If VlanId is 0,
686 @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.
690 MnpCreateServiceData (
691 IN MNP_DEVICE_DATA
*MnpDeviceData
,
693 IN UINT8 Priority OPTIONAL
696 EFI_HANDLE MnpServiceHandle
;
697 MNP_SERVICE_DATA
*MnpServiceData
;
699 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
700 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
703 // Initialize the Mnp Service Data.
705 MnpServiceData
= AllocateZeroPool (sizeof (MNP_SERVICE_DATA
));
706 if (MnpServiceData
== NULL
) {
707 DEBUG ((DEBUG_ERROR
, "MnpCreateServiceData: Failed to allocate memory for the new Mnp Service Data.\n"));
713 // Add to MNP service list
715 InsertTailList (&MnpDeviceData
->ServiceList
, &MnpServiceData
->Link
);
717 MnpServiceData
->Signature
= MNP_SERVICE_DATA_SIGNATURE
;
718 MnpServiceData
->MnpDeviceData
= MnpDeviceData
;
721 // Copy the ServiceBinding structure.
723 CopyMem (&MnpServiceData
->ServiceBinding
, &mMnpServiceBindingProtocol
, sizeof (EFI_SERVICE_BINDING_PROTOCOL
));
726 // Initialize the lists.
728 InitializeListHead (&MnpServiceData
->ChildrenList
);
730 SnpMode
= MnpDeviceData
->Snp
->Mode
;
733 // Create VLAN child handle
735 MnpServiceHandle
= MnpCreateVlanChild (
736 MnpDeviceData
->ImageHandle
,
737 MnpDeviceData
->ControllerHandle
,
739 &MnpServiceData
->DevicePath
741 if (MnpServiceHandle
== NULL
) {
742 DEBUG ((DEBUG_ERROR
, "MnpCreateServiceData: Failed to create child handle.\n"));
748 // Open VLAN Config Protocol by child
750 Status
= gBS
->OpenProtocol (
751 MnpDeviceData
->ControllerHandle
,
752 &gEfiVlanConfigProtocolGuid
,
753 (VOID
**)&VlanConfig
,
754 MnpDeviceData
->ImageHandle
,
756 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
758 if (EFI_ERROR (Status
)) {
763 // Reduce MTU for VLAN device
765 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
- NET_VLAN_TAG_LEN
;
768 // VlanId set to 0 means rx/tx untagged frame
770 MnpServiceHandle
= MnpDeviceData
->ControllerHandle
;
771 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
;
774 MnpServiceData
->ServiceHandle
= MnpServiceHandle
;
775 MnpServiceData
->VlanId
= VlanId
;
776 MnpServiceData
->Priority
= Priority
;
779 // Install the MNP Service Binding Protocol
781 Status
= gBS
->InstallMultipleProtocolInterfaces (
783 &gEfiManagedNetworkServiceBindingProtocolGuid
,
784 &MnpServiceData
->ServiceBinding
,
789 if (EFI_ERROR (Status
)) {
790 MnpDestroyServiceData (MnpServiceData
);
791 MnpServiceData
= NULL
;
794 return MnpServiceData
;
798 Destroy the MNP service context data.
800 @param[in, out] MnpServiceData Pointer to the mnp service context data.
802 @retval EFI_SUCCESS The mnp service context is destroyed.
803 @retval Others Errors as indicated.
807 MnpDestroyServiceData (
808 IN OUT MNP_SERVICE_DATA
*MnpServiceData
814 // Uninstall the MNP Service Binding Protocol
816 Status
= gBS
->UninstallMultipleProtocolInterfaces (
817 MnpServiceData
->ServiceHandle
,
818 &gEfiManagedNetworkServiceBindingProtocolGuid
,
819 &MnpServiceData
->ServiceBinding
,
822 if (EFI_ERROR (Status
)) {
826 if (MnpServiceData
->VlanId
!= 0) {
828 // Close VlanConfig Protocol opened by VLAN child handle
830 Status
= gBS
->CloseProtocol (
831 MnpServiceData
->MnpDeviceData
->ControllerHandle
,
832 &gEfiVlanConfigProtocolGuid
,
833 MnpServiceData
->MnpDeviceData
->ImageHandle
,
834 MnpServiceData
->ServiceHandle
836 if (EFI_ERROR (Status
)) {
841 // Uninstall Device Path Protocol to destroy the VLAN child handle
843 Status
= gBS
->UninstallMultipleProtocolInterfaces (
844 MnpServiceData
->ServiceHandle
,
845 &gEfiDevicePathProtocolGuid
,
846 MnpServiceData
->DevicePath
,
849 if (EFI_ERROR (Status
)) {
853 if (MnpServiceData
->DevicePath
!= NULL
) {
854 FreePool (MnpServiceData
->DevicePath
);
859 // Remove from MnpDeviceData service list
861 RemoveEntryList (&MnpServiceData
->Link
);
863 FreePool (MnpServiceData
);
869 Callback function which provided by user to remove one node in NetDestroyLinkList process.
871 @param[in] Entry The entry to be removed.
872 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
874 @retval EFI_SUCCESS The entry has been removed successfully.
875 @retval Others Fail to remove the entry.
880 MnpDestoryChildEntry (
881 IN LIST_ENTRY
*Entry
,
885 MNP_INSTANCE_DATA
*Instance
;
886 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
888 ServiceBinding
= (EFI_SERVICE_BINDING_PROTOCOL
*)Context
;
889 Instance
= CR (Entry
, MNP_INSTANCE_DATA
, InstEntry
, MNP_INSTANCE_DATA_SIGNATURE
);
890 return ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
894 Destroy all child of the MNP service data.
896 @param[in, out] MnpServiceData Pointer to the mnp service context data.
898 @retval EFI_SUCCESS All child are destroyed.
899 @retval Others Failed to destroy all child.
903 MnpDestroyServiceChild (
904 IN OUT MNP_SERVICE_DATA
*MnpServiceData
911 List
= &MnpServiceData
->ChildrenList
;
913 Status
= NetDestroyLinkList (
915 MnpDestoryChildEntry
,
916 &MnpServiceData
->ServiceBinding
,
919 if (EFI_ERROR (Status
) || (ListLength
!= 0)) {
920 return EFI_DEVICE_ERROR
;
927 Find the MNP Service Data for given VLAN ID.
929 @param[in] MnpDeviceData Pointer to the mnp device context data.
930 @param[in] VlanId The VLAN ID.
932 @return A pointer to MNP_SERVICE_DATA or NULL if not found.
937 IN MNP_DEVICE_DATA
*MnpDeviceData
,
942 MNP_SERVICE_DATA
*MnpServiceData
;
944 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->ServiceList
) {
946 // Check VLAN ID of each Mnp Service Data
948 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
949 if (MnpServiceData
->VlanId
== VlanId
) {
950 return MnpServiceData
;
958 Initialize the mnp instance context data.
960 @param[in] MnpServiceData Pointer to the mnp service context data.
961 @param[in, out] Instance Pointer to the mnp instance context data
966 MnpInitializeInstanceData (
967 IN MNP_SERVICE_DATA
*MnpServiceData
,
968 IN OUT MNP_INSTANCE_DATA
*Instance
971 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
972 ASSERT (Instance
!= NULL
);
975 // Set the signature.
977 Instance
->Signature
= MNP_INSTANCE_DATA_SIGNATURE
;
980 // Copy the MNP Protocol interfaces from the template.
982 CopyMem (&Instance
->ManagedNetwork
, &mMnpProtocolTemplate
, sizeof (Instance
->ManagedNetwork
));
985 // Copy the default config data.
987 CopyMem (&Instance
->ConfigData
, &mMnpDefaultConfigData
, sizeof (Instance
->ConfigData
));
990 // Initialize the lists.
992 InitializeListHead (&Instance
->GroupCtrlBlkList
);
993 InitializeListHead (&Instance
->RcvdPacketQueue
);
994 InitializeListHead (&Instance
->RxDeliveredPacketQueue
);
997 // Initialize the RxToken Map.
999 NetMapInit (&Instance
->RxTokenMap
);
1002 // Save the MnpServiceData info.
1004 Instance
->MnpServiceData
= MnpServiceData
;
1008 Check whether the token specified by Arg matches the token in Item.
1010 @param[in] Map Pointer to the NET_MAP.
1011 @param[in] Item Pointer to the NET_MAP_ITEM.
1012 @param[in] Arg Pointer to the Arg, it's a pointer to the token to
1015 @retval EFI_SUCCESS The token specified by Arg is different from the
1017 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
1025 IN NET_MAP_ITEM
*Item
,
1029 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
;
1030 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenInItem
;
1032 Token
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*)Arg
;
1033 TokenInItem
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*)Item
->Key
;
1035 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
1037 // The token is the same either the two tokens equals or the Events in
1038 // the two tokens are the same.
1040 return EFI_ACCESS_DENIED
;
1047 Cancel the token specified by Arg if it matches the token in Item.
1049 @param[in, out] Map Pointer to the NET_MAP.
1050 @param[in, out] Item Pointer to the NET_MAP_ITEM.
1051 @param[in] Arg Pointer to the Arg, it's a pointer to the
1054 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,
1055 or the Arg isn't NULL, and the token in Item is
1056 different from the Arg.
1057 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
1058 Arg, and the token is cancelled.
1064 IN OUT NET_MAP
*Map
,
1065 IN OUT NET_MAP_ITEM
*Item
,
1069 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenToCancel
;
1071 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
1073 // The token in Item is not the token specified by Arg.
1078 TokenToCancel
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*)Item
->Key
;
1081 // Remove the item from the map.
1083 NetMapRemoveItem (Map
, Item
, NULL
);
1086 // Cancel this token with status set to EFI_ABORTED.
1088 TokenToCancel
->Status
= EFI_ABORTED
;
1089 gBS
->SignalEvent (TokenToCancel
->Event
);
1093 // Only abort the token specified by Arg if Arg isn't NULL.
1102 Start and initialize the simple network.
1104 @param[in] Snp Pointer to the simple network protocol.
1106 @retval EFI_SUCCESS The simple network protocol is started.
1107 @retval Others Other errors as indicated.
1112 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
1117 ASSERT (Snp
!= NULL
);
1120 // Start the simple network.
1122 Status
= Snp
->Start (Snp
);
1124 if (!EFI_ERROR (Status
)) {
1126 // Initialize the simple network.
1128 Status
= Snp
->Initialize (Snp
, 0, 0);
1135 Stop the simple network.
1137 @param[in] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
1139 @retval EFI_SUCCESS The simple network is stopped.
1140 @retval Others Other errors as indicated.
1145 IN MNP_DEVICE_DATA
*MnpDeviceData
1149 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1151 Snp
= MnpDeviceData
->Snp
;
1152 ASSERT (Snp
!= NULL
);
1155 // Recycle all the transmit buffer from SNP.
1157 Status
= MnpRecycleTxBuf (MnpDeviceData
);
1158 if (EFI_ERROR (Status
)) {
1163 // Shut down the simple network.
1165 Status
= Snp
->Shutdown (Snp
);
1166 if (!EFI_ERROR (Status
)) {
1168 // Stop the simple network.
1170 Status
= Snp
->Stop (Snp
);
1177 Start the managed network, this function is called when one instance is configured
1180 @param[in, out] MnpServiceData Pointer to the mnp service context data.
1181 @param[in] IsConfigUpdate The instance is reconfigured or it's the first
1182 time the instanced is configured.
1183 @param[in] EnableSystemPoll Enable the system polling or not.
1185 @retval EFI_SUCCESS The managed network is started and some
1186 configuration is updated.
1187 @retval Others Other errors as indicated.
1192 IN OUT MNP_SERVICE_DATA
*MnpServiceData
,
1193 IN BOOLEAN IsConfigUpdate
,
1194 IN BOOLEAN EnableSystemPoll
1198 EFI_TIMER_DELAY TimerOpType
;
1199 MNP_DEVICE_DATA
*MnpDeviceData
;
1201 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1203 Status
= EFI_SUCCESS
;
1204 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1206 if (!IsConfigUpdate
) {
1208 // If it's not a configuration update, increase the configured children number.
1210 MnpDeviceData
->ConfiguredChildrenNumber
++;
1212 if (MnpDeviceData
->ConfiguredChildrenNumber
== 1) {
1214 // It's the first configured child, start the simple network.
1216 Status
= MnpStartSnp (MnpDeviceData
->Snp
);
1217 if (EFI_ERROR (Status
)) {
1218 DEBUG ((DEBUG_ERROR
, "MnpStart: MnpStartSnp failed, %r.\n", Status
));
1224 // Start the timeout timer.
1226 Status
= gBS
->SetTimer (
1227 MnpDeviceData
->TimeoutCheckTimer
,
1229 MNP_TIMEOUT_CHECK_INTERVAL
1231 if (EFI_ERROR (Status
)) {
1234 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
1242 // Start the media detection timer.
1244 Status
= gBS
->SetTimer (
1245 MnpDeviceData
->MediaDetectTimer
,
1247 MNP_MEDIA_DETECT_INTERVAL
1249 if (EFI_ERROR (Status
)) {
1252 "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",
1261 if (MnpDeviceData
->EnableSystemPoll
^ EnableSystemPoll
) {
1263 // The EnableSystemPoll differs with the current state, disable or enable
1266 TimerOpType
= EnableSystemPoll
? TimerPeriodic
: TimerCancel
;
1268 Status
= gBS
->SetTimer (MnpDeviceData
->PollTimer
, TimerOpType
, MNP_SYS_POLL_INTERVAL
);
1269 if (EFI_ERROR (Status
)) {
1270 DEBUG ((DEBUG_ERROR
, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status
));
1275 MnpDeviceData
->EnableSystemPoll
= EnableSystemPoll
;
1279 // Change the receive filters if need.
1281 Status
= MnpConfigReceiveFilters (MnpDeviceData
);
1288 Stop the managed network.
1290 @param[in, out] MnpServiceData Pointer to the mnp service context data.
1292 @retval EFI_SUCCESS The managed network is stopped.
1293 @retval Others Other errors as indicated.
1298 IN OUT MNP_SERVICE_DATA
*MnpServiceData
1302 MNP_DEVICE_DATA
*MnpDeviceData
;
1304 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1305 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1306 ASSERT (MnpDeviceData
->ConfiguredChildrenNumber
> 0);
1309 // Configure the receive filters.
1311 MnpConfigReceiveFilters (MnpDeviceData
);
1314 // Decrease the children number.
1316 MnpDeviceData
->ConfiguredChildrenNumber
--;
1318 if (MnpDeviceData
->ConfiguredChildrenNumber
> 0) {
1320 // If there are other configured children, return and keep the timers and
1321 // simple network unchanged.
1327 // No configured children now.
1329 if (MnpDeviceData
->EnableSystemPoll
) {
1331 // The system poll in on, cancel the poll timer.
1333 Status
= gBS
->SetTimer (MnpDeviceData
->PollTimer
, TimerCancel
, 0);
1334 MnpDeviceData
->EnableSystemPoll
= FALSE
;
1338 // Cancel the timeout timer.
1340 Status
= gBS
->SetTimer (MnpDeviceData
->TimeoutCheckTimer
, TimerCancel
, 0);
1343 // Cancel the media detect timer.
1345 Status
= gBS
->SetTimer (MnpDeviceData
->MediaDetectTimer
, TimerCancel
, 0);
1348 // Stop the simple network.
1350 Status
= MnpStopSnp (MnpDeviceData
);
1355 Flush the instance's received data.
1357 @param[in, out] Instance Pointer to the mnp instance context data.
1361 MnpFlushRcvdDataQueue (
1362 IN OUT MNP_INSTANCE_DATA
*Instance
1366 MNP_RXDATA_WRAP
*RxDataWrap
;
1368 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1370 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1372 while (!IsListEmpty (&Instance
->RcvdPacketQueue
)) {
1374 // Remove all the Wraps.
1376 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
1379 // Recycle the RxDataWrap.
1381 MnpRecycleRxData (NULL
, (VOID
*)RxDataWrap
);
1382 Instance
->RcvdPacketQueueSize
--;
1385 ASSERT (Instance
->RcvdPacketQueueSize
== 0);
1387 gBS
->RestoreTPL (OldTpl
);
1391 Configure the Instance using ConfigData.
1393 @param[in, out] Instance Pointer to the mnp instance context data.
1394 @param[in] ConfigData Pointer to the configuration data used to configure
1397 @retval EFI_SUCCESS The Instance is configured.
1398 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1399 implementation doesn't support it.
1400 @retval Others Other errors as indicated.
1404 MnpConfigureInstance (
1405 IN OUT MNP_INSTANCE_DATA
*Instance
,
1406 IN EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData OPTIONAL
1410 MNP_SERVICE_DATA
*MnpServiceData
;
1411 MNP_DEVICE_DATA
*MnpDeviceData
;
1412 EFI_MANAGED_NETWORK_CONFIG_DATA
*OldConfigData
;
1413 EFI_MANAGED_NETWORK_CONFIG_DATA
*NewConfigData
;
1414 BOOLEAN IsConfigUpdate
;
1416 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1418 if ((ConfigData
!= NULL
) && ConfigData
->EnableReceiveTimestamps
) {
1420 // Don't support timestamp.
1422 return EFI_UNSUPPORTED
;
1425 Status
= EFI_SUCCESS
;
1427 MnpServiceData
= Instance
->MnpServiceData
;
1428 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1429 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1431 IsConfigUpdate
= (BOOLEAN
)((Instance
->Configured
) && (ConfigData
!= NULL
));
1433 OldConfigData
= &Instance
->ConfigData
;
1434 NewConfigData
= ConfigData
;
1435 if (NewConfigData
== NULL
) {
1437 // Restore back the default config data if a reset of this instance
1440 NewConfigData
= &mMnpDefaultConfigData
;
1444 // Reset the instance's receive filter.
1446 Instance
->ReceiveFilter
= 0;
1449 // Clear the receive counters according to the old ConfigData.
1451 if (OldConfigData
->EnableUnicastReceive
) {
1452 MnpDeviceData
->UnicastCount
--;
1455 if (OldConfigData
->EnableMulticastReceive
) {
1456 MnpDeviceData
->MulticastCount
--;
1459 if (OldConfigData
->EnableBroadcastReceive
) {
1460 MnpDeviceData
->BroadcastCount
--;
1463 if (OldConfigData
->EnablePromiscuousReceive
) {
1464 MnpDeviceData
->PromiscuousCount
--;
1468 // Set the receive filter counters and the receive filter of the
1469 // instance according to the new ConfigData.
1471 if (NewConfigData
->EnableUnicastReceive
) {
1472 MnpDeviceData
->UnicastCount
++;
1473 Instance
->ReceiveFilter
|= MNP_RECEIVE_UNICAST
;
1476 if (NewConfigData
->EnableMulticastReceive
) {
1477 MnpDeviceData
->MulticastCount
++;
1480 if (NewConfigData
->EnableBroadcastReceive
) {
1481 MnpDeviceData
->BroadcastCount
++;
1482 Instance
->ReceiveFilter
|= MNP_RECEIVE_BROADCAST
;
1485 if (NewConfigData
->EnablePromiscuousReceive
) {
1486 MnpDeviceData
->PromiscuousCount
++;
1489 if (OldConfigData
->FlushQueuesOnReset
) {
1490 MnpFlushRcvdDataQueue (Instance
);
1493 if (ConfigData
== NULL
) {
1494 Instance
->ManagedNetwork
.Cancel (&Instance
->ManagedNetwork
, NULL
);
1497 if (!NewConfigData
->EnableMulticastReceive
) {
1498 MnpGroupOp (Instance
, FALSE
, NULL
, NULL
);
1502 // Save the new configuration data.
1504 CopyMem (OldConfigData
, NewConfigData
, sizeof (*OldConfigData
));
1506 Instance
->Configured
= (BOOLEAN
)(ConfigData
!= NULL
);
1507 if (Instance
->Configured
) {
1509 // The instance is configured, start the Mnp.
1514 (BOOLEAN
) !NewConfigData
->DisableBackgroundPolling
1518 // The instance is changed to the unconfigured state, stop the Mnp.
1520 Status
= MnpStop (MnpServiceData
);
1527 Configure the Snp receive filters according to the instances' receive filter
1530 @param[in] MnpDeviceData Pointer to the mnp device context data.
1532 @retval EFI_SUCCESS The receive filters is configured.
1533 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due
1534 to lack of memory resource.
1538 MnpConfigReceiveFilters (
1539 IN MNP_DEVICE_DATA
*MnpDeviceData
1543 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1544 EFI_MAC_ADDRESS
*MCastFilter
;
1545 UINT32 MCastFilterCnt
;
1546 UINT32 EnableFilterBits
;
1547 UINT32 DisableFilterBits
;
1548 BOOLEAN ResetMCastFilters
;
1551 MNP_GROUP_ADDRESS
*GroupAddress
;
1553 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1555 Snp
= MnpDeviceData
->Snp
;
1558 // Initialize the enable filter and disable filter.
1560 EnableFilterBits
= 0;
1561 DisableFilterBits
= Snp
->Mode
->ReceiveFilterMask
;
1563 if (MnpDeviceData
->UnicastCount
!= 0) {
1565 // Enable unicast if any instance wants to receive unicast.
1567 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1570 if (MnpDeviceData
->BroadcastCount
!= 0) {
1572 // Enable broadcast if any instance wants to receive broadcast.
1574 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1579 ResetMCastFilters
= TRUE
;
1581 if ((MnpDeviceData
->MulticastCount
!= 0) && (MnpDeviceData
->GroupAddressCount
!= 0)) {
1583 // There are instances configured to receive multicast and already some group
1584 // addresses are joined.
1587 ResetMCastFilters
= FALSE
;
1589 if (MnpDeviceData
->GroupAddressCount
<= Snp
->Mode
->MaxMCastFilterCount
) {
1591 // The joind group address is less than simple network's maximum count.
1592 // Just configure the snp to do the multicast filtering.
1595 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1598 // Allocate pool for the multicast addresses.
1600 MCastFilterCnt
= MnpDeviceData
->GroupAddressCount
;
1601 MCastFilter
= AllocatePool (sizeof (EFI_MAC_ADDRESS
) * MCastFilterCnt
);
1602 if (MCastFilter
== NULL
) {
1603 DEBUG ((DEBUG_ERROR
, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1605 return EFI_OUT_OF_RESOURCES
;
1609 // Fill the multicast HW address buffer.
1612 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->GroupAddressList
) {
1613 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1614 CopyMem (MCastFilter
+ Index
, &GroupAddress
->Address
, sizeof (*(MCastFilter
+ Index
)));
1617 ASSERT (Index
<= MCastFilterCnt
);
1621 // The maximum multicast is reached, set the filter to be promiscuous
1625 if ((Snp
->Mode
->ReceiveFilterMask
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) != 0) {
1626 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1629 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1630 // set the NIC to be promiscuous although this will tremendously degrade
1633 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1638 if (MnpDeviceData
->PromiscuousCount
!= 0) {
1640 // Enable promiscuous if any instance wants to receive promiscuous.
1642 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1646 // Set the disable filter.
1648 DisableFilterBits
^= EnableFilterBits
;
1651 // Configure the receive filters of SNP.
1653 Status
= Snp
->ReceiveFilters (
1661 DEBUG_CODE_BEGIN ();
1662 if (EFI_ERROR (Status
)) {
1665 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1672 if (MCastFilter
!= NULL
) {
1674 // Free the buffer used to hold the group addresses.
1676 FreePool (MCastFilter
);
1683 Add a group address control block which controls the MacAddress for
1686 @param[in, out] Instance Pointer to the mnp instance context data.
1687 @param[in, out] CtrlBlk Pointer to the group address control block.
1688 @param[in, out] GroupAddress Pointer to the group address.
1689 @param[in] MacAddress Pointer to the mac address.
1690 @param[in] HwAddressSize The hardware address size.
1692 @retval EFI_SUCCESS The group address control block is added.
1693 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1697 MnpGroupOpAddCtrlBlk (
1698 IN OUT MNP_INSTANCE_DATA
*Instance
,
1699 IN OUT MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
1700 IN OUT MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
1701 IN EFI_MAC_ADDRESS
*MacAddress
,
1702 IN UINT32 HwAddressSize
1705 MNP_DEVICE_DATA
*MnpDeviceData
;
1707 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1709 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1710 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1712 if (GroupAddress
== NULL
) {
1713 ASSERT (MacAddress
!= NULL
);
1716 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1718 GroupAddress
= AllocatePool (sizeof (MNP_GROUP_ADDRESS
));
1719 if (GroupAddress
== NULL
) {
1720 DEBUG ((DEBUG_ERROR
, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1722 return EFI_OUT_OF_RESOURCES
;
1725 CopyMem (&GroupAddress
->Address
, MacAddress
, sizeof (GroupAddress
->Address
));
1726 GroupAddress
->RefCnt
= 0;
1728 &MnpDeviceData
->GroupAddressList
,
1729 &GroupAddress
->AddrEntry
1731 MnpDeviceData
->GroupAddressCount
++;
1735 // Increase the RefCnt.
1737 GroupAddress
->RefCnt
++;
1740 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1742 CtrlBlk
->GroupAddress
= GroupAddress
;
1743 InsertTailList (&Instance
->GroupCtrlBlkList
, &CtrlBlk
->CtrlBlkEntry
);
1749 Delete a group control block from the instance. If the controlled group address's
1750 reference count reaches zero, the group address is removed too.
1752 @param[in] Instance Pointer to the instance context data.
1753 @param[in] CtrlBlk Pointer to the group control block to delete.
1755 @return The group address controlled by the control block is no longer used or not.
1759 MnpGroupOpDelCtrlBlk (
1760 IN MNP_INSTANCE_DATA
*Instance
,
1761 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
1764 MNP_DEVICE_DATA
*MnpDeviceData
;
1765 MNP_GROUP_ADDRESS
*GroupAddress
;
1767 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1769 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1770 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1773 // Remove and free the CtrlBlk.
1775 GroupAddress
= CtrlBlk
->GroupAddress
;
1776 RemoveEntryList (&CtrlBlk
->CtrlBlkEntry
);
1779 ASSERT (GroupAddress
->RefCnt
> 0);
1782 // Count down the RefCnt.
1784 GroupAddress
->RefCnt
--;
1786 if (GroupAddress
->RefCnt
== 0) {
1788 // Free this GroupAddress entry if no instance uses it.
1790 MnpDeviceData
->GroupAddressCount
--;
1791 RemoveEntryList (&GroupAddress
->AddrEntry
);
1792 FreePool (GroupAddress
);
1801 Do the group operations for this instance.
1803 @param[in, out] Instance Pointer to the instance context data.
1804 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to
1805 leave a group/groups.
1806 @param[in] MacAddress Pointer to the group address to join or leave.
1807 @param[in] CtrlBlk Pointer to the group control block if JoinFlag
1810 @retval EFI_SUCCESS The group operation finished.
1811 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1812 @retval Others Other errors as indicated.
1817 IN OUT MNP_INSTANCE_DATA
*Instance
,
1818 IN BOOLEAN JoinFlag
,
1819 IN EFI_MAC_ADDRESS
*MacAddress OPTIONAL
,
1820 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk OPTIONAL
1823 MNP_DEVICE_DATA
*MnpDeviceData
;
1825 LIST_ENTRY
*NextEntry
;
1826 MNP_GROUP_ADDRESS
*GroupAddress
;
1827 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1828 MNP_GROUP_CONTROL_BLOCK
*NewCtrlBlk
;
1830 BOOLEAN AddressExist
;
1833 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1835 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1836 SnpMode
= MnpDeviceData
->Snp
->Mode
;
1840 // A new group address is to be added.
1842 GroupAddress
= NULL
;
1843 AddressExist
= FALSE
;
1846 // Allocate memory for the control block.
1848 NewCtrlBlk
= AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK
));
1849 if (NewCtrlBlk
== NULL
) {
1850 DEBUG ((DEBUG_ERROR
, "MnpGroupOp: Failed to allocate memory resource.\n"));
1852 return EFI_OUT_OF_RESOURCES
;
1855 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->GroupAddressList
) {
1857 // Check whether the MacAddress is already joined by other instances.
1859 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1860 if (CompareMem (MacAddress
, &GroupAddress
->Address
, SnpMode
->HwAddressSize
) == 0) {
1861 AddressExist
= TRUE
;
1866 if (!AddressExist
) {
1867 GroupAddress
= NULL
;
1871 // Add the GroupAddress for this instance.
1873 Status
= MnpGroupOpAddCtrlBlk (
1878 SnpMode
->HwAddressSize
1880 if (EFI_ERROR (Status
)) {
1886 if (MacAddress
!= NULL
) {
1887 ASSERT (CtrlBlk
!= NULL
);
1890 // Leave the specific multicast mac address.
1892 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, CtrlBlk
);
1895 // Leave all multicast mac addresses.
1899 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Instance
->GroupCtrlBlkList
) {
1900 NewCtrlBlk
= NET_LIST_USER_STRUCT (
1902 MNP_GROUP_CONTROL_BLOCK
,
1906 // Update is required if the group address left is no longer used
1907 // by other instances.
1909 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, NewCtrlBlk
);
1914 Status
= EFI_SUCCESS
;
1918 // Reconfigure the receive filters if necessary.
1920 Status
= MnpConfigReceiveFilters (MnpDeviceData
);