2 Implementation of Managed Network Protocol private services.
4 Copyright (c) 2005 - 2010, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The full
8 text of the license may be found at<BR>
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol
= {
20 MnpServiceBindingCreateChild
,
21 MnpServiceBindingDestroyChild
24 EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate
= {
35 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData
= {
50 Add Count of net buffers to MnpDeviceData->FreeNbufQue. The length of the net
51 buffer is specified by MnpDeviceData->BufferLength.
53 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
54 @param[in] Count Number of NET_BUFFERs to add.
56 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated
57 and added to MnpDeviceData->FreeNbufQue.
58 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.
63 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
71 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
72 ASSERT ((Count
> 0) && (MnpDeviceData
->BufferLength
> 0));
75 for (Index
= 0; Index
< Count
; Index
++) {
76 Nbuf
= NetbufAlloc (MnpDeviceData
->BufferLength
+ MnpDeviceData
->PaddingSize
);
78 DEBUG ((EFI_D_ERROR
, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));
80 Status
= EFI_OUT_OF_RESOURCES
;
84 if (MnpDeviceData
->PaddingSize
> 0) {
86 // Pad padding bytes before the media header
88 NetbufAllocSpace (Nbuf
, MnpDeviceData
->PaddingSize
, NET_BUF_TAIL
);
89 NetbufTrim (Nbuf
, MnpDeviceData
->PaddingSize
, NET_BUF_HEAD
);
92 NetbufQueAppend (&MnpDeviceData
->FreeNbufQue
, Nbuf
);
95 MnpDeviceData
->NbufCnt
+= Index
;
101 Allocate a free NET_BUF from MnpDeviceData->FreeNbufQue. If there is none
102 in the queue, first try to allocate some and add them into the queue, then
103 fetch the NET_BUF from the updated FreeNbufQue.
105 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
107 @return Pointer to the allocated free NET_BUF structure, if NULL the
113 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
117 NET_BUF_QUEUE
*FreeNbufQue
;
121 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
123 FreeNbufQue
= &MnpDeviceData
->FreeNbufQue
;
124 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
127 // Check whether there are available buffers, or else try to add some.
129 if (FreeNbufQue
->BufNum
== 0) {
130 if ((MnpDeviceData
->NbufCnt
+ MNP_NET_BUFFER_INCREASEMENT
) > MNP_MAX_NET_BUFFER_NUM
) {
133 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
141 Status
= MnpAddFreeNbuf (MnpDeviceData
, MNP_NET_BUFFER_INCREASEMENT
);
142 if (EFI_ERROR (Status
)) {
145 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
150 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
151 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
156 Nbuf
= NetbufQueRemove (FreeNbufQue
);
159 // Increase the RefCnt.
166 gBS
->RestoreTPL (OldTpl
);
173 Try to reclaim the Nbuf into the buffer pool.
175 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
176 @param[in, out] Nbuf Pointer to the NET_BUF to free.
181 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
187 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
188 ASSERT (Nbuf
->RefCnt
> 1);
190 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
194 if (Nbuf
->RefCnt
== 1) {
196 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
198 NetbufTrim (Nbuf
, Nbuf
->TotalSize
, NET_BUF_TAIL
);
200 if (NetbufAllocSpace (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_HEAD
) != NULL
) {
202 // There is space reserved for vlan tag in the head, reclaim it
204 NetbufTrim (Nbuf
, NET_VLAN_TAG_LEN
, NET_BUF_TAIL
);
207 NetbufQueAppend (&MnpDeviceData
->FreeNbufQue
, Nbuf
);
210 gBS
->RestoreTPL (OldTpl
);
215 Initialize the mnp device context data.
217 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
218 @param[in] ImageHandle The driver image handle.
219 @param[in] ControllerHandle Handle of device to bind driver to.
221 @retval EFI_SUCCESS The mnp service context is initialized.
222 @retval EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.
223 @retval Others Other errors as indicated.
227 MnpInitializeDeviceData (
228 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
229 IN EFI_HANDLE ImageHandle
,
230 IN EFI_HANDLE ControllerHandle
234 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
235 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
237 MnpDeviceData
->Signature
= MNP_DEVICE_DATA_SIGNATURE
;
238 MnpDeviceData
->ImageHandle
= ImageHandle
;
239 MnpDeviceData
->ControllerHandle
= ControllerHandle
;
242 // Copy the MNP Protocol interfaces from the template.
244 CopyMem (&MnpDeviceData
->VlanConfig
, &mVlanConfigProtocolTemplate
, sizeof (EFI_VLAN_CONFIG_PROTOCOL
));
247 // Open the Simple Network protocol.
249 Status
= gBS
->OpenProtocol (
251 &gEfiSimpleNetworkProtocolGuid
,
255 EFI_OPEN_PROTOCOL_BY_DRIVER
257 if (EFI_ERROR (Status
)) {
258 return EFI_UNSUPPORTED
;
265 MnpDeviceData
->Snp
= Snp
;
268 // Initialize the lists.
270 InitializeListHead (&MnpDeviceData
->ServiceList
);
271 InitializeListHead (&MnpDeviceData
->GroupAddressList
);
274 // Get the buffer length used to allocate NET_BUF to hold data received
275 // from SNP. Do this before fill the FreeNetBufQue.
278 MnpDeviceData
->BufferLength
= SnpMode
->MediaHeaderSize
+ NET_VLAN_TAG_LEN
+ SnpMode
->MaxPacketSize
+ NET_ETHER_FCS_SIZE
;
281 // Make sure the protocol headers immediately following the media header
282 // 4-byte aligned, and also preserve additional space for VLAN tag
284 MnpDeviceData
->PaddingSize
= ((4 - SnpMode
->MediaHeaderSize
) & 0x3) + NET_VLAN_TAG_LEN
;
287 // Initialize MAC string which will be used as VLAN configuration variable name
289 Status
= NetLibGetMacString (ControllerHandle
, ImageHandle
, &MnpDeviceData
->MacString
);
290 if (EFI_ERROR (Status
)) {
295 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
297 NetbufQueInit (&MnpDeviceData
->FreeNbufQue
);
298 Status
= MnpAddFreeNbuf (MnpDeviceData
, MNP_INIT_NET_BUFFER_NUM
);
299 if (EFI_ERROR (Status
)) {
300 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: MnpAddFreeNbuf failed, %r.\n", Status
));
306 // Get one NET_BUF from the FreeNbufQue for rx cache.
308 MnpDeviceData
->RxNbufCache
= MnpAllocNbuf (MnpDeviceData
);
310 MnpDeviceData
->RxNbufCache
,
311 MnpDeviceData
->BufferLength
,
316 // Allocate buffer pool for tx.
318 MnpDeviceData
->TxBuf
= AllocatePool (MnpDeviceData
->BufferLength
);
319 if (MnpDeviceData
->TxBuf
== NULL
) {
320 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: AllocatePool failed.\n"));
322 Status
= EFI_OUT_OF_RESOURCES
;
327 // Create the system poll timer.
329 Status
= gBS
->CreateEvent (
330 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
334 &MnpDeviceData
->PollTimer
336 if (EFI_ERROR (Status
)) {
337 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));
343 // Create the timer for packet timeout check.
345 Status
= gBS
->CreateEvent (
346 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
348 MnpCheckPacketTimeout
,
350 &MnpDeviceData
->TimeoutCheckTimer
352 if (EFI_ERROR (Status
)) {
353 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));
359 // Create the timer for media detection.
361 Status
= gBS
->CreateEvent (
362 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
366 &MnpDeviceData
->MediaDetectTimer
368 if (EFI_ERROR (Status
)) {
369 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n"));
375 // Create the timer for tx timeout check.
377 Status
= gBS
->CreateEvent (
382 &MnpDeviceData
->TxTimeoutEvent
384 if (EFI_ERROR (Status
)) {
385 DEBUG ((EFI_D_ERROR
, "MnpInitializeDeviceData: CreateEvent for tx timeout event failed.\n"));
389 if (EFI_ERROR (Status
)) {
391 // Free the dynamic allocated resources if necessary.
393 if (MnpDeviceData
->MacString
!= NULL
) {
394 FreePool (MnpDeviceData
->MacString
);
397 if (MnpDeviceData
->TimeoutCheckTimer
!= NULL
) {
398 gBS
->CloseEvent (MnpDeviceData
->TimeoutCheckTimer
);
401 if (MnpDeviceData
->MediaDetectTimer
!= NULL
) {
402 gBS
->CloseEvent (MnpDeviceData
->MediaDetectTimer
);
405 if (MnpDeviceData
->PollTimer
!= NULL
) {
406 gBS
->CloseEvent (MnpDeviceData
->PollTimer
);
409 if (MnpDeviceData
->TxBuf
!= NULL
) {
410 FreePool (MnpDeviceData
->TxBuf
);
413 if (MnpDeviceData
->RxNbufCache
!= NULL
) {
414 MnpFreeNbuf (MnpDeviceData
, MnpDeviceData
->RxNbufCache
);
417 if (MnpDeviceData
->FreeNbufQue
.BufNum
!= 0) {
418 NetbufQueFlush (&MnpDeviceData
->FreeNbufQue
);
422 // Close the Simple Network Protocol.
426 &gEfiSimpleNetworkProtocolGuid
,
437 Destroy the MNP device context data.
439 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
440 @param[in] ImageHandle The driver image handle.
444 MnpDestroyDeviceData (
445 IN OUT MNP_DEVICE_DATA
*MnpDeviceData
,
446 IN EFI_HANDLE ImageHandle
449 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
452 // Free Vlan Config variable name string
454 if (MnpDeviceData
->MacString
!= NULL
) {
455 FreePool (MnpDeviceData
->MacString
);
459 // The GroupAddressList must be empty.
461 ASSERT (IsListEmpty (&MnpDeviceData
->GroupAddressList
));
466 gBS
->CloseEvent (MnpDeviceData
->TxTimeoutEvent
);
467 gBS
->CloseEvent (MnpDeviceData
->TimeoutCheckTimer
);
468 gBS
->CloseEvent (MnpDeviceData
->MediaDetectTimer
);
469 gBS
->CloseEvent (MnpDeviceData
->PollTimer
);
472 // Free the tx buffer.
474 FreePool (MnpDeviceData
->TxBuf
);
477 // Free the RxNbufCache.
479 MnpFreeNbuf (MnpDeviceData
, MnpDeviceData
->RxNbufCache
);
482 // Flush the FreeNbufQue.
484 MnpDeviceData
->NbufCnt
-= MnpDeviceData
->FreeNbufQue
.BufNum
;
485 NetbufQueFlush (&MnpDeviceData
->FreeNbufQue
);
488 // Close the Simple Network Protocol.
491 MnpDeviceData
->ControllerHandle
,
492 &gEfiSimpleNetworkProtocolGuid
,
494 MnpDeviceData
->ControllerHandle
500 Create mnp service context data.
502 @param[in] MnpDeviceData Pointer to the mnp device context data.
503 @param[in] VlanId The VLAN ID.
504 @param[in] Priority The VLAN priority. If VlanId is 0,
507 @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.
511 MnpCreateServiceData (
512 IN MNP_DEVICE_DATA
*MnpDeviceData
,
514 IN UINT8 Priority OPTIONAL
517 EFI_HANDLE MnpServiceHandle
;
518 MNP_SERVICE_DATA
*MnpServiceData
;
520 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
521 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
524 // Initialize the Mnp Service Data.
526 MnpServiceData
= AllocateZeroPool (sizeof (MNP_SERVICE_DATA
));
527 if (MnpServiceData
== NULL
) {
528 DEBUG ((EFI_D_ERROR
, "MnpCreateServiceData: Faild to allocate memory for the new Mnp Service Data.\n"));
534 // Add to MNP service list
536 InsertTailList (&MnpDeviceData
->ServiceList
, &MnpServiceData
->Link
);
538 MnpServiceData
->Signature
= MNP_SERVICE_DATA_SIGNATURE
;
539 MnpServiceData
->MnpDeviceData
= MnpDeviceData
;
542 // Copy the ServiceBinding structure.
544 CopyMem (&MnpServiceData
->ServiceBinding
, &mMnpServiceBindingProtocol
, sizeof (EFI_SERVICE_BINDING_PROTOCOL
));
547 // Initialize the lists.
549 InitializeListHead (&MnpServiceData
->ChildrenList
);
551 SnpMode
= MnpDeviceData
->Snp
->Mode
;
554 // Create VLAN child handle
556 MnpServiceHandle
= MnpCreateVlanChild (
557 MnpDeviceData
->ImageHandle
,
558 MnpDeviceData
->ControllerHandle
,
560 &MnpServiceData
->DevicePath
562 if (MnpServiceHandle
== NULL
) {
563 DEBUG ((EFI_D_ERROR
, "MnpCreateServiceData: Faild to create child handle.\n"));
569 // Open VLAN Config Protocol by child
571 Status
= gBS
->OpenProtocol (
572 MnpDeviceData
->ControllerHandle
,
573 &gEfiVlanConfigProtocolGuid
,
574 (VOID
**) &VlanConfig
,
575 MnpDeviceData
->ImageHandle
,
577 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
579 if (EFI_ERROR (Status
)) {
584 // Reduce MTU for VLAN device
586 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
- NET_VLAN_TAG_LEN
;
589 // VlanId set to 0 means rx/tx untagged frame
591 MnpServiceHandle
= MnpDeviceData
->ControllerHandle
;
592 MnpServiceData
->Mtu
= SnpMode
->MaxPacketSize
;
595 MnpServiceData
->ServiceHandle
= MnpServiceHandle
;
596 MnpServiceData
->VlanId
= VlanId
;
597 MnpServiceData
->Priority
= Priority
;
600 // Install the MNP Service Binding Protocol
602 Status
= gBS
->InstallMultipleProtocolInterfaces (
604 &gEfiManagedNetworkServiceBindingProtocolGuid
,
605 &MnpServiceData
->ServiceBinding
,
610 if (EFI_ERROR (Status
)) {
611 MnpDestroyServiceData (MnpServiceData
);
612 MnpServiceData
= NULL
;
615 return MnpServiceData
;
619 Destroy the MNP service context data.
621 @param[in, out] MnpServiceData Pointer to the mnp service context data.
623 @retval EFI_SUCCESS The mnp service context is destroyed.
624 @retval Others Errors as indicated.
628 MnpDestroyServiceData (
629 IN OUT MNP_SERVICE_DATA
*MnpServiceData
635 // Uninstall the MNP Service Binding Protocol
637 Status
= gBS
->UninstallMultipleProtocolInterfaces (
638 MnpServiceData
->ServiceHandle
,
639 &gEfiManagedNetworkServiceBindingProtocolGuid
,
640 &MnpServiceData
->ServiceBinding
,
643 if (EFI_ERROR (Status
)) {
647 if (MnpServiceData
->VlanId
!= 0) {
649 // Close VlanConfig Protocol opened by VLAN child handle
651 Status
= gBS
->CloseProtocol (
652 MnpServiceData
->MnpDeviceData
->ControllerHandle
,
653 &gEfiVlanConfigProtocolGuid
,
654 MnpServiceData
->MnpDeviceData
->ImageHandle
,
655 MnpServiceData
->ServiceHandle
657 if (EFI_ERROR (Status
)) {
662 // Uninstall Device Path Protocol to destroy the VLAN child handle
664 Status
= gBS
->UninstallMultipleProtocolInterfaces (
665 MnpServiceData
->ServiceHandle
,
666 &gEfiDevicePathProtocolGuid
,
667 MnpServiceData
->DevicePath
,
670 if (EFI_ERROR (Status
)) {
674 if (MnpServiceData
->DevicePath
!= NULL
) {
675 FreePool (MnpServiceData
->DevicePath
);
680 // Remove from MnpDeviceData service list
682 RemoveEntryList (&MnpServiceData
->Link
);
684 FreePool (MnpServiceData
);
690 Destroy all child of the MNP service data.
692 @param[in, out] MnpServiceData Pointer to the mnp service context data.
694 @retval EFI_SUCCESS All child are destroyed.
695 @retval Others Failed to destroy all child.
699 MnpDestroyServiceChild (
700 IN OUT MNP_SERVICE_DATA
*MnpServiceData
704 MNP_INSTANCE_DATA
*Instance
;
705 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
707 ServiceBinding
= &MnpServiceData
->ServiceBinding
;
708 while (!IsListEmpty (&MnpServiceData
->ChildrenList
)) {
710 // Don't use NetListRemoveHead here, the remove opreration will be done
711 // in ServiceBindingDestroyChild.
713 Instance
= NET_LIST_HEAD (
714 &MnpServiceData
->ChildrenList
,
719 Status
= ServiceBinding
->DestroyChild (ServiceBinding
, Instance
->Handle
);
720 if (EFI_ERROR (Status
)) {
729 Find the MNP Service Data for given VLAN ID.
731 @param[in] MnpDeviceData Pointer to the mnp device context data.
732 @param[in] VlanId The VLAN ID.
734 @return A pointer to MNP_SERVICE_DATA or NULL if not found.
739 IN MNP_DEVICE_DATA
*MnpDeviceData
,
744 MNP_SERVICE_DATA
*MnpServiceData
;
746 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->ServiceList
) {
748 // Check VLAN ID of each Mnp Service Data
750 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
751 if (MnpServiceData
->VlanId
== VlanId
) {
752 return MnpServiceData
;
760 Initialize the mnp instance context data.
762 @param[in] MnpServiceData Pointer to the mnp service context data.
763 @param[in, out] Instance Pointer to the mnp instance context data
768 MnpInitializeInstanceData (
769 IN MNP_SERVICE_DATA
*MnpServiceData
,
770 IN OUT MNP_INSTANCE_DATA
*Instance
773 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
774 ASSERT (Instance
!= NULL
);
777 // Set the signature.
779 Instance
->Signature
= MNP_INSTANCE_DATA_SIGNATURE
;
782 // Copy the MNP Protocol interfaces from the template.
784 CopyMem (&Instance
->ManagedNetwork
, &mMnpProtocolTemplate
, sizeof (Instance
->ManagedNetwork
));
787 // Copy the default config data.
789 CopyMem (&Instance
->ConfigData
, &mMnpDefaultConfigData
, sizeof (Instance
->ConfigData
));
792 // Initialize the lists.
794 InitializeListHead (&Instance
->GroupCtrlBlkList
);
795 InitializeListHead (&Instance
->RcvdPacketQueue
);
796 InitializeListHead (&Instance
->RxDeliveredPacketQueue
);
799 // Initialize the RxToken Map.
801 NetMapInit (&Instance
->RxTokenMap
);
804 // Save the MnpServiceData info.
806 Instance
->MnpServiceData
= MnpServiceData
;
811 Check whether the token specified by Arg matches the token in Item.
813 @param[in] Map Pointer to the NET_MAP.
814 @param[in] Item Pointer to the NET_MAP_ITEM.
815 @param[in] Arg Pointer to the Arg, it's a pointer to the token to
818 @retval EFI_SUCCESS The token specified by Arg is different from the
820 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
828 IN NET_MAP_ITEM
*Item
,
832 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*Token
;
833 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenInItem
;
835 Token
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Arg
;
836 TokenInItem
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
838 if ((Token
== TokenInItem
) || (Token
->Event
== TokenInItem
->Event
)) {
840 // The token is the same either the two tokens equals or the Events in
841 // the two tokens are the same.
843 return EFI_ACCESS_DENIED
;
850 Cancel the token specified by Arg if it matches the token in Item.
852 @param[in, out] Map Pointer to the NET_MAP.
853 @param[in, out] Item Pointer to the NET_MAP_ITEM.
854 @param[in] Arg Pointer to the Arg, it's a pointer to the
857 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,
858 or the Arg isn't NULL, and the token in Item is
859 different from the Arg.
860 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
861 Arg, and the token is cancelled.
868 IN OUT NET_MAP_ITEM
*Item
,
872 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*TokenToCancel
;
874 if ((Arg
!= NULL
) && (Item
->Key
!= Arg
)) {
876 // The token in Item is not the token specified by Arg.
881 TokenToCancel
= (EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*) Item
->Key
;
884 // Remove the item from the map.
886 NetMapRemoveItem (Map
, Item
, NULL
);
889 // Cancel this token with status set to EFI_ABORTED.
891 TokenToCancel
->Status
= EFI_ABORTED
;
892 gBS
->SignalEvent (TokenToCancel
->Event
);
896 // Only abort the token specified by Arg if Arg isn't NULL.
906 Start and initialize the simple network.
908 @param[in] Snp Pointer to the simple network protocol.
910 @retval EFI_SUCCESS The simple network protocol is started.
911 @retval Others Other errors as indicated.
916 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
921 ASSERT (Snp
!= NULL
);
924 // Start the simple network.
926 Status
= Snp
->Start (Snp
);
928 if (!EFI_ERROR (Status
)) {
930 // Initialize the simple network.
932 Status
= Snp
->Initialize (Snp
, 0, 0);
940 Stop the simple network.
942 @param[in] Snp Pointer to the simple network protocol.
944 @retval EFI_SUCCESS The simple network is stopped.
945 @retval Others Other errors as indicated.
950 IN EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
955 ASSERT (Snp
!= NULL
);
958 // Shut down the simple network.
960 Status
= Snp
->Shutdown (Snp
);
961 if (!EFI_ERROR (Status
)) {
963 // Stop the simple network.
965 Status
= Snp
->Stop (Snp
);
973 Start the managed network, this function is called when one instance is configured
976 @param[in, out] MnpServiceData Pointer to the mnp service context data.
977 @param[in] IsConfigUpdate The instance is reconfigured or it's the first
978 time the instanced is configured.
979 @param[in] EnableSystemPoll Enable the system polling or not.
981 @retval EFI_SUCCESS The managed network is started and some
982 configuration is updated.
983 @retval Others Other errors as indicated.
988 IN OUT MNP_SERVICE_DATA
*MnpServiceData
,
989 IN BOOLEAN IsConfigUpdate
,
990 IN BOOLEAN EnableSystemPoll
994 EFI_TIMER_DELAY TimerOpType
;
995 MNP_DEVICE_DATA
*MnpDeviceData
;
997 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
999 Status
= EFI_SUCCESS
;
1000 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1002 if (!IsConfigUpdate
) {
1004 // If it's not a configuration update, increase the configured children number.
1006 MnpDeviceData
->ConfiguredChildrenNumber
++;
1008 if (MnpDeviceData
->ConfiguredChildrenNumber
== 1) {
1010 // It's the first configured child, start the simple network.
1012 Status
= MnpStartSnp (MnpDeviceData
->Snp
);
1013 if (EFI_ERROR (Status
)) {
1014 DEBUG ((EFI_D_ERROR
, "MnpStart: MnpStartSnp failed, %r.\n", Status
));
1020 // Start the timeout timer.
1022 Status
= gBS
->SetTimer (
1023 MnpDeviceData
->TimeoutCheckTimer
,
1025 MNP_TIMEOUT_CHECK_INTERVAL
1027 if (EFI_ERROR (Status
)) {
1030 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
1038 // Start the media detection timer.
1040 Status
= gBS
->SetTimer (
1041 MnpDeviceData
->MediaDetectTimer
,
1043 MNP_MEDIA_DETECT_INTERVAL
1045 if (EFI_ERROR (Status
)) {
1048 "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",
1057 if (MnpDeviceData
->EnableSystemPoll
^ EnableSystemPoll
) {
1059 // The EnableSystemPoll differs with the current state, disable or enable
1062 TimerOpType
= EnableSystemPoll
? TimerPeriodic
: TimerCancel
;
1064 Status
= gBS
->SetTimer (MnpDeviceData
->PollTimer
, TimerOpType
, MNP_SYS_POLL_INTERVAL
);
1065 if (EFI_ERROR (Status
)) {
1066 DEBUG ((EFI_D_ERROR
, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status
));
1071 MnpDeviceData
->EnableSystemPoll
= EnableSystemPoll
;
1075 // Change the receive filters if need.
1077 Status
= MnpConfigReceiveFilters (MnpDeviceData
);
1085 Stop the managed network.
1087 @param[in, out] MnpServiceData Pointer to the mnp service context data.
1089 @retval EFI_SUCCESS The managed network is stopped.
1090 @retval Others Other errors as indicated.
1095 IN OUT MNP_SERVICE_DATA
*MnpServiceData
1099 MNP_DEVICE_DATA
*MnpDeviceData
;
1101 NET_CHECK_SIGNATURE (MnpServiceData
, MNP_SERVICE_DATA_SIGNATURE
);
1102 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1103 ASSERT (MnpDeviceData
->ConfiguredChildrenNumber
> 0);
1106 // Configure the receive filters.
1108 MnpConfigReceiveFilters (MnpDeviceData
);
1111 // Decrease the children number.
1113 MnpDeviceData
->ConfiguredChildrenNumber
--;
1115 if (MnpDeviceData
->ConfiguredChildrenNumber
> 0) {
1117 // If there are other configured chilren, return and keep the timers and
1118 // simple network unchanged.
1124 // No configured children now.
1126 if (MnpDeviceData
->EnableSystemPoll
) {
1128 // The system poll in on, cancel the poll timer.
1130 Status
= gBS
->SetTimer (MnpDeviceData
->PollTimer
, TimerCancel
, 0);
1131 MnpDeviceData
->EnableSystemPoll
= FALSE
;
1135 // Cancel the timeout timer.
1137 Status
= gBS
->SetTimer (MnpDeviceData
->TimeoutCheckTimer
, TimerCancel
, 0);
1140 // Cancel the media detect timer.
1142 Status
= gBS
->SetTimer (MnpDeviceData
->MediaDetectTimer
, TimerCancel
, 0);
1145 // Stop the simple network.
1147 Status
= MnpStopSnp (MnpDeviceData
->Snp
);
1153 Flush the instance's received data.
1155 @param[in, out] Instance Pointer to the mnp instance context data.
1159 MnpFlushRcvdDataQueue (
1160 IN OUT MNP_INSTANCE_DATA
*Instance
1164 MNP_RXDATA_WRAP
*RxDataWrap
;
1166 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1168 OldTpl
= gBS
->RaiseTPL (TPL_NOTIFY
);
1170 while (!IsListEmpty (&Instance
->RcvdPacketQueue
)) {
1172 // Remove all the Wraps.
1174 RxDataWrap
= NET_LIST_HEAD (&Instance
->RcvdPacketQueue
, MNP_RXDATA_WRAP
, WrapEntry
);
1177 // Recycle the RxDataWrap.
1179 MnpRecycleRxData (NULL
, (VOID
*) RxDataWrap
);
1180 Instance
->RcvdPacketQueueSize
--;
1183 ASSERT (Instance
->RcvdPacketQueueSize
== 0);
1185 gBS
->RestoreTPL (OldTpl
);
1190 Configure the Instance using ConfigData.
1192 @param[in, out] Instance Pointer to the mnp instance context data.
1193 @param[in] ConfigData Pointer to the configuration data used to configure
1196 @retval EFI_SUCCESS The Instance is configured.
1197 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1198 implementation doesn't support it.
1199 @retval Others Other errors as indicated.
1203 MnpConfigureInstance (
1204 IN OUT MNP_INSTANCE_DATA
*Instance
,
1205 IN EFI_MANAGED_NETWORK_CONFIG_DATA
*ConfigData OPTIONAL
1209 MNP_SERVICE_DATA
*MnpServiceData
;
1210 MNP_DEVICE_DATA
*MnpDeviceData
;
1211 EFI_MANAGED_NETWORK_CONFIG_DATA
*OldConfigData
;
1212 EFI_MANAGED_NETWORK_CONFIG_DATA
*NewConfigData
;
1213 BOOLEAN IsConfigUpdate
;
1215 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1217 if ((ConfigData
!= NULL
) && ConfigData
->EnableReceiveTimestamps
) {
1219 // Don't support timestamp.
1221 return EFI_UNSUPPORTED
;
1224 Status
= EFI_SUCCESS
;
1226 MnpServiceData
= Instance
->MnpServiceData
;
1227 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
1228 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1230 IsConfigUpdate
= (BOOLEAN
) ((Instance
->Configured
) && (ConfigData
!= NULL
));
1232 OldConfigData
= &Instance
->ConfigData
;
1233 NewConfigData
= ConfigData
;
1234 if (NewConfigData
== NULL
) {
1236 // Restore back the default config data if a reset of this instance
1239 NewConfigData
= &mMnpDefaultConfigData
;
1243 // Reset the instance's receive filter.
1245 Instance
->ReceiveFilter
= 0;
1248 // Clear the receive counters according to the old ConfigData.
1250 if (OldConfigData
->EnableUnicastReceive
) {
1251 MnpDeviceData
->UnicastCount
--;
1254 if (OldConfigData
->EnableMulticastReceive
) {
1255 MnpDeviceData
->MulticastCount
--;
1258 if (OldConfigData
->EnableBroadcastReceive
) {
1259 MnpDeviceData
->BroadcastCount
--;
1262 if (OldConfigData
->EnablePromiscuousReceive
) {
1263 MnpDeviceData
->PromiscuousCount
--;
1267 // Set the receive filter counters and the receive filter of the
1268 // instance according to the new ConfigData.
1270 if (NewConfigData
->EnableUnicastReceive
) {
1271 MnpDeviceData
->UnicastCount
++;
1272 Instance
->ReceiveFilter
|= MNP_RECEIVE_UNICAST
;
1275 if (NewConfigData
->EnableMulticastReceive
) {
1276 MnpDeviceData
->MulticastCount
++;
1279 if (NewConfigData
->EnableBroadcastReceive
) {
1280 MnpDeviceData
->BroadcastCount
++;
1281 Instance
->ReceiveFilter
|= MNP_RECEIVE_BROADCAST
;
1284 if (NewConfigData
->EnablePromiscuousReceive
) {
1285 MnpDeviceData
->PromiscuousCount
++;
1288 if (OldConfigData
->FlushQueuesOnReset
) {
1289 MnpFlushRcvdDataQueue (Instance
);
1292 if (ConfigData
== NULL
) {
1293 Instance
->ManagedNetwork
.Cancel (&Instance
->ManagedNetwork
, NULL
);
1296 if (!NewConfigData
->EnableMulticastReceive
) {
1297 MnpGroupOp (Instance
, FALSE
, NULL
, NULL
);
1301 // Save the new configuration data.
1303 CopyMem (OldConfigData
, NewConfigData
, sizeof (*OldConfigData
));
1305 Instance
->Configured
= (BOOLEAN
) (ConfigData
!= NULL
);
1306 if (Instance
->Configured
) {
1308 // The instance is configured, start the Mnp.
1313 (BOOLEAN
) !NewConfigData
->DisableBackgroundPolling
1317 // The instance is changed to the unconfigured state, stop the Mnp.
1319 Status
= MnpStop (MnpServiceData
);
1326 Configure the Snp receive filters according to the instances' receive filter
1329 @param[in] MnpDeviceData Pointer to the mnp device context data.
1331 @retval EFI_SUCCESS The receive filters is configured.
1332 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due
1333 to lack of memory resource.
1337 MnpConfigReceiveFilters (
1338 IN MNP_DEVICE_DATA
*MnpDeviceData
1342 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
1343 EFI_MAC_ADDRESS
*MCastFilter
;
1344 UINT32 MCastFilterCnt
;
1345 UINT32 EnableFilterBits
;
1346 UINT32 DisableFilterBits
;
1347 BOOLEAN ResetMCastFilters
;
1350 MNP_GROUP_ADDRESS
*GroupAddress
;
1352 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1354 Snp
= MnpDeviceData
->Snp
;
1357 // Initialize the enable filter and disable filter.
1359 EnableFilterBits
= 0;
1360 DisableFilterBits
= Snp
->Mode
->ReceiveFilterMask
;
1362 if (MnpDeviceData
->UnicastCount
!= 0) {
1364 // Enable unicast if any instance wants to receive unicast.
1366 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
1369 if (MnpDeviceData
->BroadcastCount
!= 0) {
1371 // Enable broadcast if any instance wants to receive broadcast.
1373 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
1378 ResetMCastFilters
= TRUE
;
1380 if ((MnpDeviceData
->MulticastCount
!= 0) && (MnpDeviceData
->GroupAddressCount
!= 0)) {
1382 // There are instances configured to receive multicast and already some group
1383 // addresses are joined.
1386 ResetMCastFilters
= FALSE
;
1388 if (MnpDeviceData
->GroupAddressCount
<= Snp
->Mode
->MaxMCastFilterCount
) {
1390 // The joind group address is less than simple network's maximum count.
1391 // Just configure the snp to do the multicast filtering.
1394 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
1397 // Allocate pool for the mulicast addresses.
1399 MCastFilterCnt
= MnpDeviceData
->GroupAddressCount
;
1400 MCastFilter
= AllocatePool (sizeof (EFI_MAC_ADDRESS
) * MCastFilterCnt
);
1401 if (MCastFilter
== NULL
) {
1402 DEBUG ((EFI_D_ERROR
, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1404 return EFI_OUT_OF_RESOURCES
;
1408 // Fill the multicast HW address buffer.
1411 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->GroupAddressList
) {
1413 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1414 CopyMem (MCastFilter
+ Index
, &GroupAddress
->Address
, sizeof (*(MCastFilter
+ Index
)));
1417 ASSERT (Index
<= MCastFilterCnt
);
1421 // The maximum multicast is reached, set the filter to be promiscuous
1425 if ((Snp
->Mode
->ReceiveFilterMask
& EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
) != 0) {
1426 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
1429 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1430 // set the NIC to be promiscuous although this will tremendously degrade
1433 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1438 if (MnpDeviceData
->PromiscuousCount
!= 0) {
1440 // Enable promiscuous if any instance wants to receive promiscuous.
1442 EnableFilterBits
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
1446 // Set the disable filter.
1448 DisableFilterBits
^= EnableFilterBits
;
1451 // Configure the receive filters of SNP.
1453 Status
= Snp
->ReceiveFilters (
1462 if (EFI_ERROR (Status
)) {
1465 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1471 if (MCastFilter
!= NULL
) {
1473 // Free the buffer used to hold the group addresses.
1475 FreePool (MCastFilter
);
1483 Add a group address control block which controls the MacAddress for
1486 @param[in, out] Instance Pointer to the mnp instance context data.
1487 @param[in, out] CtrlBlk Pointer to the group address control block.
1488 @param[in, out] GroupAddress Pointer to the group adress.
1489 @param[in] MacAddress Pointer to the mac address.
1490 @param[in] HwAddressSize The hardware address size.
1492 @retval EFI_SUCCESS The group address control block is added.
1493 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1497 MnpGroupOpAddCtrlBlk (
1498 IN OUT MNP_INSTANCE_DATA
*Instance
,
1499 IN OUT MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
,
1500 IN OUT MNP_GROUP_ADDRESS
*GroupAddress OPTIONAL
,
1501 IN EFI_MAC_ADDRESS
*MacAddress
,
1502 IN UINT32 HwAddressSize
1505 MNP_DEVICE_DATA
*MnpDeviceData
;
1507 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1509 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1510 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1512 if (GroupAddress
== NULL
) {
1513 ASSERT (MacAddress
!= NULL
);
1516 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1518 GroupAddress
= AllocatePool (sizeof (MNP_GROUP_ADDRESS
));
1519 if (GroupAddress
== NULL
) {
1521 DEBUG ((EFI_D_ERROR
, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1523 return EFI_OUT_OF_RESOURCES
;
1526 CopyMem (&GroupAddress
->Address
, MacAddress
, sizeof (GroupAddress
->Address
));
1527 GroupAddress
->RefCnt
= 0;
1529 &MnpDeviceData
->GroupAddressList
,
1530 &GroupAddress
->AddrEntry
1532 MnpDeviceData
->GroupAddressCount
++;
1536 // Increase the RefCnt.
1538 GroupAddress
->RefCnt
++;
1541 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1543 CtrlBlk
->GroupAddress
= GroupAddress
;
1544 InsertTailList (&Instance
->GroupCtrlBlkList
, &CtrlBlk
->CtrlBlkEntry
);
1551 Delete a group control block from the instance. If the controlled group address's
1552 reference count reaches zero, the group address is removed too.
1554 @param[in] Instance Pointer to the instance context data.
1555 @param[in] CtrlBlk Pointer to the group control block to delete.
1557 @return The group address controlled by the control block is no longer used or not.
1561 MnpGroupOpDelCtrlBlk (
1562 IN MNP_INSTANCE_DATA
*Instance
,
1563 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk
1566 MNP_DEVICE_DATA
*MnpDeviceData
;
1567 MNP_GROUP_ADDRESS
*GroupAddress
;
1569 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1571 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1572 NET_CHECK_SIGNATURE (MnpDeviceData
, MNP_DEVICE_DATA_SIGNATURE
);
1575 // Remove and free the CtrlBlk.
1577 GroupAddress
= CtrlBlk
->GroupAddress
;
1578 RemoveEntryList (&CtrlBlk
->CtrlBlkEntry
);
1581 ASSERT (GroupAddress
->RefCnt
> 0);
1584 // Count down the RefCnt.
1586 GroupAddress
->RefCnt
--;
1588 if (GroupAddress
->RefCnt
== 0) {
1590 // Free this GroupAddress entry if no instance uses it.
1592 MnpDeviceData
->GroupAddressCount
--;
1593 RemoveEntryList (&GroupAddress
->AddrEntry
);
1594 FreePool (GroupAddress
);
1604 Do the group operations for this instance.
1606 @param[in, out] Instance Pointer to the instance context data.
1607 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to
1608 leave a group/groups.
1609 @param[in] MacAddress Pointer to the group address to join or leave.
1610 @param[in] CtrlBlk Pointer to the group control block if JoinFlag
1613 @retval EFI_SUCCESS The group operation finished.
1614 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1615 @retval Others Other errors as indicated.
1620 IN OUT MNP_INSTANCE_DATA
*Instance
,
1621 IN BOOLEAN JoinFlag
,
1622 IN EFI_MAC_ADDRESS
*MacAddress OPTIONAL
,
1623 IN MNP_GROUP_CONTROL_BLOCK
*CtrlBlk OPTIONAL
1626 MNP_DEVICE_DATA
*MnpDeviceData
;
1628 LIST_ENTRY
*NextEntry
;
1629 MNP_GROUP_ADDRESS
*GroupAddress
;
1630 EFI_SIMPLE_NETWORK_MODE
*SnpMode
;
1631 MNP_GROUP_CONTROL_BLOCK
*NewCtrlBlk
;
1633 BOOLEAN AddressExist
;
1636 NET_CHECK_SIGNATURE (Instance
, MNP_INSTANCE_DATA_SIGNATURE
);
1638 MnpDeviceData
= Instance
->MnpServiceData
->MnpDeviceData
;
1639 SnpMode
= MnpDeviceData
->Snp
->Mode
;
1643 // A new gropu address is to be added.
1645 GroupAddress
= NULL
;
1646 AddressExist
= FALSE
;
1649 // Allocate memory for the control block.
1651 NewCtrlBlk
= AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK
));
1652 if (NewCtrlBlk
== NULL
) {
1653 DEBUG ((EFI_D_ERROR
, "MnpGroupOp: Failed to allocate memory resource.\n"));
1655 return EFI_OUT_OF_RESOURCES
;
1658 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->GroupAddressList
) {
1660 // Check whether the MacAddress is already joined by other instances.
1662 GroupAddress
= NET_LIST_USER_STRUCT (Entry
, MNP_GROUP_ADDRESS
, AddrEntry
);
1663 if (CompareMem (MacAddress
, &GroupAddress
->Address
, SnpMode
->HwAddressSize
) == 0) {
1664 AddressExist
= TRUE
;
1669 if (!AddressExist
) {
1670 GroupAddress
= NULL
;
1674 // Add the GroupAddress for this instance.
1676 Status
= MnpGroupOpAddCtrlBlk (
1681 SnpMode
->HwAddressSize
1683 if (EFI_ERROR (Status
)) {
1689 if (MacAddress
!= NULL
) {
1690 ASSERT (CtrlBlk
!= NULL
);
1693 // Leave the specific multicast mac address.
1695 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, CtrlBlk
);
1698 // Leave all multicast mac addresses.
1702 NET_LIST_FOR_EACH_SAFE (Entry
, NextEntry
, &Instance
->GroupCtrlBlkList
) {
1704 NewCtrlBlk
= NET_LIST_USER_STRUCT (
1706 MNP_GROUP_CONTROL_BLOCK
,
1710 // Update is required if the group address left is no longer used
1711 // by other instances.
1713 NeedUpdate
= MnpGroupOpDelCtrlBlk (Instance
, NewCtrlBlk
);
1718 Status
= EFI_SUCCESS
;
1722 // Reconfigure the receive filters if necessary.
1724 Status
= MnpConfigReceiveFilters (MnpDeviceData
);