1 /** @file
2   Implementation of Managed Network Protocol private services.
3 
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "MnpImpl.h"
10 #include "MnpVlan.h"
11 
12 EFI_SERVICE_BINDING_PROTOCOL    mMnpServiceBindingProtocol = {
13   MnpServiceBindingCreateChild,
14   MnpServiceBindingDestroyChild
15 };
16 
17 EFI_MANAGED_NETWORK_PROTOCOL    mMnpProtocolTemplate = {
18   MnpGetModeData,
19   MnpConfigure,
20   MnpMcastIpToMac,
21   MnpGroups,
22   MnpTransmit,
23   MnpReceive,
24   MnpCancel,
25   MnpPoll
26 };
27 
28 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {
29   10000000,
30   10000000,
31   0,
32   FALSE,
33   FALSE,
34   FALSE,
35   FALSE,
36   FALSE,
37   FALSE,
38   FALSE
39 };
40 
41 /**
42   Add Count of net buffers to MnpDeviceData->FreeNbufQue. The length of the net
43   buffer is specified by MnpDeviceData->BufferLength.
44 
45   @param[in, out]  MnpDeviceData         Pointer to the MNP_DEVICE_DATA.
46   @param[in]       Count                 Number of NET_BUFFERs to add.
47 
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.
51 
52 **/
53 EFI_STATUS
MnpAddFreeNbuf(IN OUT MNP_DEVICE_DATA * MnpDeviceData,IN UINTN Count)54 MnpAddFreeNbuf (
55   IN OUT MNP_DEVICE_DATA   *MnpDeviceData,
56   IN     UINTN             Count
57   )
58 {
59   EFI_STATUS  Status;
60   UINTN       Index;
61   NET_BUF     *Nbuf;
62 
63   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
64   ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));
65 
66   Status = EFI_SUCCESS;
67   for (Index = 0; Index < Count; Index++) {
68     Nbuf = NetbufAlloc (MnpDeviceData->BufferLength + MnpDeviceData->PaddingSize);
69     if (Nbuf == NULL) {
70       DEBUG ((EFI_D_ERROR, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));
71 
72       Status = EFI_OUT_OF_RESOURCES;
73       break;
74     }
75 
76     if (MnpDeviceData->PaddingSize > 0) {
77       //
78       // Pad padding bytes before the media header
79       //
80       NetbufAllocSpace (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_TAIL);
81       NetbufTrim (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_HEAD);
82     }
83 
84     NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);
85   }
86 
87   MnpDeviceData->NbufCnt += Index;
88   return Status;
89 }
90 
91 
92 /**
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.
96 
97   @param[in, out]  MnpDeviceData        Pointer to the MNP_DEVICE_DATA.
98 
99   @return     Pointer to the allocated free NET_BUF structure, if NULL the
100               operation is failed.
101 
102 **/
103 NET_BUF *
MnpAllocNbuf(IN OUT MNP_DEVICE_DATA * MnpDeviceData)104 MnpAllocNbuf (
105   IN OUT MNP_DEVICE_DATA   *MnpDeviceData
106   )
107 {
108   EFI_STATUS    Status;
109   NET_BUF_QUEUE *FreeNbufQue;
110   NET_BUF       *Nbuf;
111   EFI_TPL       OldTpl;
112 
113   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
114 
115   FreeNbufQue = &MnpDeviceData->FreeNbufQue;
116   OldTpl      = gBS->RaiseTPL (TPL_NOTIFY);
117 
118   //
119   // Check whether there are available buffers, or else try to add some.
120   //
121   if (FreeNbufQue->BufNum == 0) {
122     if ((MnpDeviceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {
123       DEBUG (
124         (EFI_D_ERROR,
125         "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
126         MnpDeviceData)
127         );
128 
129       Nbuf = NULL;
130       goto ON_EXIT;
131     }
132 
133     Status = MnpAddFreeNbuf (MnpDeviceData, MNP_NET_BUFFER_INCREASEMENT);
134     if (EFI_ERROR (Status)) {
135       DEBUG (
136         (EFI_D_ERROR,
137         "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
138         Status)
139         );
140 
141       //
142       // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
143       // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
144       //
145     }
146   }
147 
148   Nbuf = NetbufQueRemove (FreeNbufQue);
149 
150   //
151   // Increase the RefCnt.
152   //
153   if (Nbuf != NULL) {
154     NET_GET_REF (Nbuf);
155   }
156 
157 ON_EXIT:
158   gBS->RestoreTPL (OldTpl);
159 
160   return Nbuf;
161 }
162 
163 
164 /**
165   Try to reclaim the Nbuf into the buffer pool.
166 
167   @param[in, out]  MnpDeviceData         Pointer to the mnp device context data.
168   @param[in, out]  Nbuf                  Pointer to the NET_BUF to free.
169 
170 **/
171 VOID
MnpFreeNbuf(IN OUT MNP_DEVICE_DATA * MnpDeviceData,IN OUT NET_BUF * Nbuf)172 MnpFreeNbuf (
173   IN OUT MNP_DEVICE_DATA   *MnpDeviceData,
174   IN OUT NET_BUF           *Nbuf
175   )
176 {
177   EFI_TPL  OldTpl;
178 
179   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
180   ASSERT (Nbuf->RefCnt > 1);
181 
182   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
183 
184   NET_PUT_REF (Nbuf);
185 
186   if (Nbuf->RefCnt == 1) {
187     //
188     // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
189     //
190     NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_TAIL);
191 
192     if (NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD) != NULL) {
193       //
194       // There is space reserved for vlan tag in the head, reclaim it
195       //
196       NetbufTrim (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_TAIL);
197     }
198 
199     NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);
200   }
201 
202   gBS->RestoreTPL (OldTpl);
203 }
204 
205 /**
206   Add Count of TX buffers to MnpDeviceData->AllTxBufList and MnpDeviceData->FreeTxBufList.
207   The length of the buffer is specified by MnpDeviceData->BufferLength.
208 
209   @param[in, out]  MnpDeviceData         Pointer to the MNP_DEVICE_DATA.
210   @param[in]       Count                 Number of TX buffers to add.
211 
212   @retval EFI_SUCCESS           The specified amount of TX buffers are allocated.
213   @retval EFI_OUT_OF_RESOURCES  Failed to allocate a TX buffer.
214 
215 **/
216 EFI_STATUS
MnpAddFreeTxBuf(IN OUT MNP_DEVICE_DATA * MnpDeviceData,IN UINTN Count)217 MnpAddFreeTxBuf (
218   IN OUT MNP_DEVICE_DATA   *MnpDeviceData,
219   IN     UINTN             Count
220   )
221 {
222   EFI_STATUS        Status;
223   UINT32            Index;
224   MNP_TX_BUF_WRAP   *TxBufWrap;
225 
226   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
227   ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));
228 
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"));
234 
235       Status = EFI_OUT_OF_RESOURCES;
236       break;
237     }
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);
243   }
244 
245   MnpDeviceData->TxBufCount += Index;
246   return Status;
247 }
248 
249 /**
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.
253 
254   @param[in, out]  MnpDeviceData        Pointer to the MNP_DEVICE_DATA.
255 
256   @return     Pointer to the allocated free NET_BUF structure, if NULL the
257               operation is failed.
258 
259 **/
260 UINT8 *
MnpAllocTxBuf(IN OUT MNP_DEVICE_DATA * MnpDeviceData)261 MnpAllocTxBuf (
262   IN OUT MNP_DEVICE_DATA   *MnpDeviceData
263   )
264 {
265   EFI_TPL           OldTpl;
266   UINT8             *TxBuf;
267   EFI_STATUS        Status;
268   LIST_ENTRY        *Entry;
269   MNP_TX_BUF_WRAP   *TxBufWrap;
270 
271   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
272 
273   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
274 
275   if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
276     //
277     // First try to recycle some TX buffer from SNP
278     //
279     Status = MnpRecycleTxBuf (MnpDeviceData);
280     if (EFI_ERROR (Status)) {
281       TxBuf = NULL;
282       goto ON_EXIT;
283     }
284 
285     //
286     // If still no free TX buffer, allocate more.
287     //
288     if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
289       if ((MnpDeviceData->TxBufCount + MNP_TX_BUFFER_INCREASEMENT) > MNP_MAX_TX_BUFFER_NUM) {
290         DEBUG (
291           (EFI_D_ERROR,
292           "MnpAllocTxBuf: The maximum TxBuf size is reached for MNP driver instance %p.\n",
293           MnpDeviceData)
294           );
295 
296         TxBuf = NULL;
297         goto ON_EXIT;
298       }
299 
300       Status = MnpAddFreeTxBuf (MnpDeviceData, MNP_TX_BUFFER_INCREASEMENT);
301       if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
302         DEBUG (
303           (EFI_D_ERROR,
304           "MnpAllocNbuf: Failed to add TxBuf into the FreeTxBufList, %r.\n",
305           Status)
306           );
307 
308         TxBuf = NULL;
309         goto ON_EXIT;
310       }
311     }
312   }
313 
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;
320 
321 ON_EXIT:
322   gBS->RestoreTPL (OldTpl);
323 
324   return TxBuf;
325 }
326 
327 /**
328   Try to reclaim the TX buffer into the buffer pool.
329 
330   @param[in, out]  MnpDeviceData         Pointer to the mnp device context data.
331   @param[in, out]  TxBuf                 Pointer to the TX buffer to free.
332 
333 **/
334 VOID
MnpFreeTxBuf(IN OUT MNP_DEVICE_DATA * MnpDeviceData,IN OUT UINT8 * TxBuf)335 MnpFreeTxBuf (
336   IN OUT MNP_DEVICE_DATA   *MnpDeviceData,
337   IN OUT UINT8             *TxBuf
338   )
339 {
340   MNP_TX_BUF_WRAP   *TxBufWrap;
341   EFI_TPL           OldTpl;
342 
343   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
344 
345   if (TxBuf == NULL) {
346     return;
347   }
348 
349   TxBufWrap = NET_LIST_USER_STRUCT (TxBuf, MNP_TX_BUF_WRAP, TxBuf);
350   if (TxBufWrap->Signature != MNP_TX_BUF_WRAP_SIGNATURE) {
351     DEBUG (
352       (EFI_D_ERROR,
353       "MnpFreeTxBuf: Signature check failed in MnpFreeTxBuf.\n")
354       );
355     return;
356   }
357 
358   if (!TxBufWrap->InUse) {
359     DEBUG (
360       (EFI_D_WARN,
361       "MnpFreeTxBuf: Duplicated recycle report from SNP.\n")
362       );
363     return;
364   }
365 
366   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
367   InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);
368   TxBufWrap->InUse = FALSE;
369   gBS->RestoreTPL (OldTpl);
370 }
371 
372 /**
373   Try to recycle all the transmitted buffer address from SNP.
374 
375   @param[in, out]  MnpDeviceData     Pointer to the mnp device context data.
376 
377   @retval EFI_SUCCESS             Successed to recyclethe transmitted buffer address.
378   @retval Others                  Failed to recyclethe transmitted buffer address.
379 
380 **/
381 EFI_STATUS
MnpRecycleTxBuf(IN OUT MNP_DEVICE_DATA * MnpDeviceData)382 MnpRecycleTxBuf (
383   IN OUT MNP_DEVICE_DATA   *MnpDeviceData
384   )
385 {
386   UINT8                         *TxBuf;
387   EFI_SIMPLE_NETWORK_PROTOCOL   *Snp;
388   EFI_STATUS                    Status;
389 
390   Snp = MnpDeviceData->Snp;
391   ASSERT (Snp != NULL);
392 
393   do {
394     TxBuf = NULL;
395     Status = Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);
396     if (EFI_ERROR (Status)) {
397       return Status;
398     }
399 
400     if (TxBuf != NULL) {
401       MnpFreeTxBuf (MnpDeviceData, TxBuf);
402     }
403   } while (TxBuf != NULL);
404 
405   return EFI_SUCCESS;
406 }
407 
408 /**
409   Initialize the mnp device context data.
410 
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.
414 
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.
418 
419 **/
420 EFI_STATUS
MnpInitializeDeviceData(IN OUT MNP_DEVICE_DATA * MnpDeviceData,IN EFI_HANDLE ImageHandle,IN EFI_HANDLE ControllerHandle)421 MnpInitializeDeviceData (
422   IN OUT MNP_DEVICE_DATA   *MnpDeviceData,
423   IN     EFI_HANDLE        ImageHandle,
424   IN     EFI_HANDLE        ControllerHandle
425   )
426 {
427   EFI_STATUS                  Status;
428   EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
429   EFI_SIMPLE_NETWORK_MODE     *SnpMode;
430 
431   MnpDeviceData->Signature        = MNP_DEVICE_DATA_SIGNATURE;
432   MnpDeviceData->ImageHandle      = ImageHandle;
433   MnpDeviceData->ControllerHandle = ControllerHandle;
434 
435   //
436   // Copy the MNP Protocol interfaces from the template.
437   //
438   CopyMem (&MnpDeviceData->VlanConfig, &mVlanConfigProtocolTemplate, sizeof (EFI_VLAN_CONFIG_PROTOCOL));
439 
440   //
441   // Open the Simple Network protocol.
442   //
443   Status = gBS->OpenProtocol (
444                   ControllerHandle,
445                   &gEfiSimpleNetworkProtocolGuid,
446                   (VOID **) &Snp,
447                   ImageHandle,
448                   ControllerHandle,
449                   EFI_OPEN_PROTOCOL_BY_DRIVER
450                   );
451   if (EFI_ERROR (Status)) {
452     return EFI_UNSUPPORTED;
453   }
454 
455   //
456   // Get MTU from Snp.
457   //
458   SnpMode            = Snp->Mode;
459   MnpDeviceData->Snp = Snp;
460 
461   //
462   // Initialize the lists.
463   //
464   InitializeListHead (&MnpDeviceData->ServiceList);
465   InitializeListHead (&MnpDeviceData->GroupAddressList);
466 
467   //
468   // Get the buffer length used to allocate NET_BUF to hold data received
469   // from SNP. Do this before fill the FreeNetBufQue.
470   //
471   //
472   MnpDeviceData->BufferLength = SnpMode->MediaHeaderSize + NET_VLAN_TAG_LEN + SnpMode->MaxPacketSize + NET_ETHER_FCS_SIZE;
473 
474   //
475   // Make sure the protocol headers immediately following the media header
476   // 4-byte aligned, and also preserve additional space for VLAN tag
477   //
478   MnpDeviceData->PaddingSize = ((4 - SnpMode->MediaHeaderSize) & 0x3) + NET_VLAN_TAG_LEN;
479 
480   //
481   // Initialize MAC string which will be used as VLAN configuration variable name
482   //
483   Status = NetLibGetMacString (ControllerHandle, ImageHandle, &MnpDeviceData->MacString);
484   if (EFI_ERROR (Status)) {
485     goto ERROR;
486   }
487 
488   //
489   // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
490   //
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));
495 
496     goto ERROR;
497   }
498 
499   //
500   // Get one NET_BUF from the FreeNbufQue for rx cache.
501   //
502   MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);
503   NetbufAllocSpace (
504     MnpDeviceData->RxNbufCache,
505     MnpDeviceData->BufferLength,
506     NET_BUF_TAIL
507     );
508 
509   //
510   // Allocate buffer pool for tx.
511   //
512   InitializeListHead (&MnpDeviceData->FreeTxBufList);
513   InitializeListHead (&MnpDeviceData->AllTxBufList);
514   MnpDeviceData->TxBufCount = 0;
515 
516   //
517   // Create the system poll timer.
518   //
519   Status = gBS->CreateEvent (
520                   EVT_NOTIFY_SIGNAL | EVT_TIMER,
521                   TPL_CALLBACK,
522                   MnpSystemPoll,
523                   MnpDeviceData,
524                   &MnpDeviceData->PollTimer
525                   );
526   if (EFI_ERROR (Status)) {
527     DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));
528 
529     goto ERROR;
530   }
531 
532   //
533   // Create the timer for packet timeout check.
534   //
535   Status = gBS->CreateEvent (
536                   EVT_NOTIFY_SIGNAL | EVT_TIMER,
537                   TPL_CALLBACK,
538                   MnpCheckPacketTimeout,
539                   MnpDeviceData,
540                   &MnpDeviceData->TimeoutCheckTimer
541                   );
542   if (EFI_ERROR (Status)) {
543     DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));
544 
545     goto ERROR;
546   }
547 
548   //
549   // Create the timer for media detection.
550   //
551   Status = gBS->CreateEvent (
552                   EVT_NOTIFY_SIGNAL | EVT_TIMER,
553                   TPL_CALLBACK,
554                   MnpCheckMediaStatus,
555                   MnpDeviceData,
556                   &MnpDeviceData->MediaDetectTimer
557                   );
558   if (EFI_ERROR (Status)) {
559     DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n"));
560 
561     goto ERROR;
562   }
563 
564 ERROR:
565   if (EFI_ERROR (Status)) {
566     //
567     // Free the dynamic allocated resources if necessary.
568     //
569     if (MnpDeviceData->MacString != NULL) {
570       FreePool (MnpDeviceData->MacString);
571     }
572 
573     if (MnpDeviceData->TimeoutCheckTimer != NULL) {
574       gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);
575     }
576 
577     if (MnpDeviceData->MediaDetectTimer != NULL) {
578       gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);
579     }
580 
581     if (MnpDeviceData->PollTimer != NULL) {
582       gBS->CloseEvent (MnpDeviceData->PollTimer);
583     }
584 
585     if (MnpDeviceData->RxNbufCache != NULL) {
586       MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);
587     }
588 
589     if (MnpDeviceData->FreeNbufQue.BufNum != 0) {
590       NetbufQueFlush (&MnpDeviceData->FreeNbufQue);
591     }
592 
593     //
594     // Close the Simple Network Protocol.
595     //
596     gBS->CloseProtocol (
597           ControllerHandle,
598           &gEfiSimpleNetworkProtocolGuid,
599           ImageHandle,
600           ControllerHandle
601           );
602   }
603 
604   return Status;
605 }
606 
607 
608 /**
609   Destroy the MNP device context data.
610 
611   @param[in, out]  MnpDeviceData      Pointer to the mnp device context data.
612   @param[in]       ImageHandle        The driver image handle.
613 
614 **/
615 VOID
MnpDestroyDeviceData(IN OUT MNP_DEVICE_DATA * MnpDeviceData,IN EFI_HANDLE ImageHandle)616 MnpDestroyDeviceData (
617   IN OUT MNP_DEVICE_DATA   *MnpDeviceData,
618   IN     EFI_HANDLE        ImageHandle
619   )
620 {
621   LIST_ENTRY         *Entry;
622   LIST_ENTRY         *NextEntry;
623   MNP_TX_BUF_WRAP    *TxBufWrap;
624 
625   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
626 
627   //
628   // Free Vlan Config variable name string
629   //
630   if (MnpDeviceData->MacString != NULL) {
631     FreePool (MnpDeviceData->MacString);
632   }
633 
634   //
635   // The GroupAddressList must be empty.
636   //
637   ASSERT (IsListEmpty (&MnpDeviceData->GroupAddressList));
638 
639   //
640   // Close the event.
641   //
642   gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);
643   gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);
644   gBS->CloseEvent (MnpDeviceData->PollTimer);
645 
646   //
647   // Free the Tx buffer pool.
648   //
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--;
654   }
655   ASSERT (IsListEmpty (&MnpDeviceData->AllTxBufList));
656   ASSERT (MnpDeviceData->TxBufCount == 0);
657 
658   //
659   // Free the RxNbufCache.
660   //
661   MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);
662 
663   //
664   // Flush the FreeNbufQue.
665   //
666   MnpDeviceData->NbufCnt -= MnpDeviceData->FreeNbufQue.BufNum;
667   NetbufQueFlush (&MnpDeviceData->FreeNbufQue);
668 
669   //
670   // Close the Simple Network Protocol.
671   //
672   gBS->CloseProtocol (
673          MnpDeviceData->ControllerHandle,
674          &gEfiSimpleNetworkProtocolGuid,
675          ImageHandle,
676          MnpDeviceData->ControllerHandle
677          );
678 }
679 
680 
681 /**
682   Create mnp service context data.
683 
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,
687                                       Priority is ignored.
688 
689   @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.
690 
691 **/
692 MNP_SERVICE_DATA *
MnpCreateServiceData(IN MNP_DEVICE_DATA * MnpDeviceData,IN UINT16 VlanId,IN UINT8 Priority OPTIONAL)693 MnpCreateServiceData (
694   IN MNP_DEVICE_DATA     *MnpDeviceData,
695   IN UINT16              VlanId,
696   IN UINT8                Priority OPTIONAL
697   )
698 {
699   EFI_HANDLE                MnpServiceHandle;
700   MNP_SERVICE_DATA          *MnpServiceData;
701   EFI_STATUS                Status;
702   EFI_SIMPLE_NETWORK_MODE   *SnpMode;
703   EFI_VLAN_CONFIG_PROTOCOL  *VlanConfig;
704 
705   //
706   // Initialize the Mnp Service Data.
707   //
708   MnpServiceData = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));
709   if (MnpServiceData == NULL) {
710     DEBUG ((DEBUG_ERROR, "MnpCreateServiceData: Failed to allocate memory for the new Mnp Service Data.\n"));
711 
712     return NULL;
713   }
714 
715   //
716   // Add to MNP service list
717   //
718   InsertTailList (&MnpDeviceData->ServiceList, &MnpServiceData->Link);
719 
720   MnpServiceData->Signature     = MNP_SERVICE_DATA_SIGNATURE;
721   MnpServiceData->MnpDeviceData = MnpDeviceData;
722 
723   //
724   // Copy the ServiceBinding structure.
725   //
726   CopyMem (&MnpServiceData->ServiceBinding, &mMnpServiceBindingProtocol, sizeof (EFI_SERVICE_BINDING_PROTOCOL));
727 
728   //
729   // Initialize the lists.
730   //
731   InitializeListHead (&MnpServiceData->ChildrenList);
732 
733   SnpMode = MnpDeviceData->Snp->Mode;
734   if (VlanId != 0) {
735     //
736     // Create VLAN child handle
737     //
738     MnpServiceHandle = MnpCreateVlanChild (
739                          MnpDeviceData->ImageHandle,
740                          MnpDeviceData->ControllerHandle,
741                          VlanId,
742                          &MnpServiceData->DevicePath
743                          );
744     if (MnpServiceHandle == NULL) {
745       DEBUG ((DEBUG_ERROR, "MnpCreateServiceData: Failed to create child handle.\n"));
746 
747       return NULL;
748     }
749 
750     //
751     // Open VLAN Config Protocol by child
752     //
753     Status = gBS->OpenProtocol (
754                     MnpDeviceData->ControllerHandle,
755                     &gEfiVlanConfigProtocolGuid,
756                     (VOID **) &VlanConfig,
757                     MnpDeviceData->ImageHandle,
758                     MnpServiceHandle,
759                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
760                     );
761     if (EFI_ERROR (Status)) {
762       goto Exit;
763     }
764 
765     //
766     // Reduce MTU for VLAN device
767     //
768     MnpServiceData->Mtu = SnpMode->MaxPacketSize - NET_VLAN_TAG_LEN;
769   } else {
770     //
771     // VlanId set to 0 means rx/tx untagged frame
772     //
773     MnpServiceHandle    = MnpDeviceData->ControllerHandle;
774     MnpServiceData->Mtu = SnpMode->MaxPacketSize;
775   }
776 
777   MnpServiceData->ServiceHandle = MnpServiceHandle;
778   MnpServiceData->VlanId        = VlanId;
779   MnpServiceData->Priority      = Priority;
780 
781   //
782   // Install the MNP Service Binding Protocol
783   //
784   Status = gBS->InstallMultipleProtocolInterfaces (
785                   &MnpServiceHandle,
786                   &gEfiManagedNetworkServiceBindingProtocolGuid,
787                   &MnpServiceData->ServiceBinding,
788                   NULL
789                   );
790 
791 Exit:
792   if (EFI_ERROR (Status)) {
793     MnpDestroyServiceData (MnpServiceData);
794     MnpServiceData = NULL;
795   }
796 
797   return MnpServiceData;
798 }
799 
800 /**
801   Destroy the MNP service context data.
802 
803   @param[in, out]  MnpServiceData    Pointer to the mnp service context data.
804 
805   @retval EFI_SUCCESS           The mnp service context is destroyed.
806   @retval Others                Errors as indicated.
807 
808 **/
809 EFI_STATUS
MnpDestroyServiceData(IN OUT MNP_SERVICE_DATA * MnpServiceData)810 MnpDestroyServiceData (
811   IN OUT MNP_SERVICE_DATA    *MnpServiceData
812   )
813 {
814   EFI_STATUS  Status;
815 
816   //
817   // Uninstall the MNP Service Binding Protocol
818   //
819   Status = gBS->UninstallMultipleProtocolInterfaces (
820                   MnpServiceData->ServiceHandle,
821                   &gEfiManagedNetworkServiceBindingProtocolGuid,
822                   &MnpServiceData->ServiceBinding,
823                   NULL
824                   );
825   if (EFI_ERROR (Status)) {
826     return Status;
827   }
828 
829   if (MnpServiceData->VlanId != 0) {
830     //
831     // Close VlanConfig Protocol opened by VLAN child handle
832     //
833     Status = gBS->CloseProtocol (
834                     MnpServiceData->MnpDeviceData->ControllerHandle,
835                     &gEfiVlanConfigProtocolGuid,
836                     MnpServiceData->MnpDeviceData->ImageHandle,
837                     MnpServiceData->ServiceHandle
838                     );
839     if (EFI_ERROR (Status)) {
840       return Status;
841     }
842 
843     //
844     // Uninstall Device Path Protocol to destroy the VLAN child handle
845     //
846     Status = gBS->UninstallMultipleProtocolInterfaces (
847                     MnpServiceData->ServiceHandle,
848                     &gEfiDevicePathProtocolGuid,
849                     MnpServiceData->DevicePath,
850                     NULL
851                     );
852     if (EFI_ERROR (Status)) {
853       return Status;
854     }
855 
856     if (MnpServiceData->DevicePath != NULL) {
857       FreePool (MnpServiceData->DevicePath);
858     }
859   }
860 
861   //
862   // Remove from MnpDeviceData service list
863   //
864   RemoveEntryList (&MnpServiceData->Link);
865 
866   FreePool (MnpServiceData);
867 
868   return Status;
869 }
870 
871 /**
872   Callback function which provided by user to remove one node in NetDestroyLinkList process.
873 
874   @param[in]    Entry           The entry to be removed.
875   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
876 
877   @retval EFI_SUCCESS           The entry has been removed successfully.
878   @retval Others                Fail to remove the entry.
879 
880 **/
881 EFI_STATUS
882 EFIAPI
MnpDestoryChildEntry(IN LIST_ENTRY * Entry,IN VOID * Context)883 MnpDestoryChildEntry (
884   IN LIST_ENTRY         *Entry,
885   IN VOID               *Context
886   )
887 {
888   MNP_INSTANCE_DATA             *Instance;
889   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
890 
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);
894 }
895 
896 /**
897   Destroy all child of the MNP service data.
898 
899   @param[in, out]  MnpServiceData    Pointer to the mnp service context data.
900 
901   @retval EFI_SUCCESS           All child are destroyed.
902   @retval Others                Failed to destroy all child.
903 
904 **/
905 EFI_STATUS
MnpDestroyServiceChild(IN OUT MNP_SERVICE_DATA * MnpServiceData)906 MnpDestroyServiceChild (
907   IN OUT MNP_SERVICE_DATA    *MnpServiceData
908   )
909 {
910   LIST_ENTRY                         *List;
911   EFI_STATUS                         Status;
912   UINTN                              ListLength;
913 
914   List = &MnpServiceData->ChildrenList;
915 
916   Status = NetDestroyLinkList (
917              List,
918              MnpDestoryChildEntry,
919              &MnpServiceData->ServiceBinding,
920              &ListLength
921              );
922   if (EFI_ERROR (Status) || ListLength != 0) {
923     return EFI_DEVICE_ERROR;
924   }
925 
926   return EFI_SUCCESS;
927 }
928 
929 /**
930   Find the MNP Service Data for given VLAN ID.
931 
932   @param[in]  MnpDeviceData      Pointer to the mnp device context data.
933   @param[in]  VlanId             The VLAN ID.
934 
935   @return A pointer to MNP_SERVICE_DATA or NULL if not found.
936 
937 **/
938 MNP_SERVICE_DATA *
MnpFindServiceData(IN MNP_DEVICE_DATA * MnpDeviceData,IN UINT16 VlanId)939 MnpFindServiceData (
940   IN MNP_DEVICE_DATA     *MnpDeviceData,
941   IN UINT16              VlanId
942   )
943 {
944   LIST_ENTRY        *Entry;
945   MNP_SERVICE_DATA  *MnpServiceData;
946 
947   NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {
948     //
949     // Check VLAN ID of each Mnp Service Data
950     //
951     MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
952     if (MnpServiceData->VlanId == VlanId) {
953       return MnpServiceData;
954     }
955   }
956 
957   return NULL;
958 }
959 
960 /**
961   Initialize the mnp instance context data.
962 
963   @param[in]       MnpServiceData   Pointer to the mnp service context data.
964   @param[in, out]  Instance         Pointer to the mnp instance context data
965                                     to initialize.
966 
967 **/
968 VOID
MnpInitializeInstanceData(IN MNP_SERVICE_DATA * MnpServiceData,IN OUT MNP_INSTANCE_DATA * Instance)969 MnpInitializeInstanceData (
970   IN     MNP_SERVICE_DATA    *MnpServiceData,
971   IN OUT MNP_INSTANCE_DATA   *Instance
972   )
973 {
974   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
975   ASSERT (Instance != NULL);
976 
977   //
978   // Set the signature.
979   //
980   Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;
981 
982   //
983   // Copy the MNP Protocol interfaces from the template.
984   //
985   CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));
986 
987   //
988   // Copy the default config data.
989   //
990   CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));
991 
992   //
993   // Initialize the lists.
994   //
995   InitializeListHead (&Instance->GroupCtrlBlkList);
996   InitializeListHead (&Instance->RcvdPacketQueue);
997   InitializeListHead (&Instance->RxDeliveredPacketQueue);
998 
999   //
1000   // Initialize the RxToken Map.
1001   //
1002   NetMapInit (&Instance->RxTokenMap);
1003 
1004   //
1005   // Save the MnpServiceData info.
1006   //
1007   Instance->MnpServiceData = MnpServiceData;
1008 }
1009 
1010 
1011 /**
1012   Check whether the token specified by Arg matches the token in Item.
1013 
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
1017                                 check.
1018 
1019   @retval EFI_SUCCESS           The token specified by Arg is different from the
1020                                 token in Item.
1021   @retval EFI_ACCESS_DENIED     The token specified by Arg is the same as that in
1022                                 Item.
1023 
1024 **/
1025 EFI_STATUS
1026 EFIAPI
MnpTokenExist(IN NET_MAP * Map,IN NET_MAP_ITEM * Item,IN VOID * Arg)1027 MnpTokenExist (
1028   IN NET_MAP         *Map,
1029   IN NET_MAP_ITEM    *Item,
1030   IN VOID            *Arg
1031   )
1032 {
1033   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *Token;
1034   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *TokenInItem;
1035 
1036   Token       = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;
1037   TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
1038 
1039   if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
1040     //
1041     // The token is the same either the two tokens equals or the Events in
1042     // the two tokens are the same.
1043     //
1044     return EFI_ACCESS_DENIED;
1045   }
1046 
1047   return EFI_SUCCESS;
1048 }
1049 
1050 /**
1051   Cancel the token specified by Arg if it matches the token in Item.
1052 
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
1056                                      token to cancel.
1057 
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.
1063 
1064 **/
1065 EFI_STATUS
1066 EFIAPI
MnpCancelTokens(IN OUT NET_MAP * Map,IN OUT NET_MAP_ITEM * Item,IN VOID * Arg)1067 MnpCancelTokens (
1068   IN OUT NET_MAP         *Map,
1069   IN OUT NET_MAP_ITEM    *Item,
1070   IN     VOID            *Arg
1071   )
1072 {
1073   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *TokenToCancel;
1074 
1075   if ((Arg != NULL) && (Item->Key != Arg)) {
1076     //
1077     // The token in Item is not the token specified by Arg.
1078     //
1079     return EFI_SUCCESS;
1080   }
1081 
1082   TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
1083 
1084   //
1085   // Remove the item from the map.
1086   //
1087   NetMapRemoveItem (Map, Item, NULL);
1088 
1089   //
1090   // Cancel this token with status set to EFI_ABORTED.
1091   //
1092   TokenToCancel->Status = EFI_ABORTED;
1093   gBS->SignalEvent (TokenToCancel->Event);
1094 
1095   if (Arg != NULL) {
1096     //
1097     // Only abort the token specified by Arg if Arg isn't NULL.
1098     //
1099     return EFI_ABORTED;
1100   }
1101 
1102   return EFI_SUCCESS;
1103 }
1104 
1105 
1106 /**
1107   Start and initialize the simple network.
1108 
1109   @param[in]  Snp               Pointer to the simple network protocol.
1110 
1111   @retval EFI_SUCCESS           The simple network protocol is started.
1112   @retval Others                Other errors as indicated.
1113 
1114 **/
1115 EFI_STATUS
MnpStartSnp(IN EFI_SIMPLE_NETWORK_PROTOCOL * Snp)1116 MnpStartSnp (
1117   IN EFI_SIMPLE_NETWORK_PROTOCOL     *Snp
1118   )
1119 {
1120   EFI_STATUS  Status;
1121 
1122   ASSERT (Snp != NULL);
1123 
1124   //
1125   // Start the simple network.
1126   //
1127   Status = Snp->Start (Snp);
1128 
1129   if (!EFI_ERROR (Status)) {
1130     //
1131     // Initialize the simple network.
1132     //
1133     Status = Snp->Initialize (Snp, 0, 0);
1134   }
1135 
1136   return Status;
1137 }
1138 
1139 
1140 /**
1141   Stop the simple network.
1142 
1143   @param[in]  MnpDeviceData     Pointer to the MNP_DEVICE_DATA.
1144 
1145   @retval EFI_SUCCESS           The simple network is stopped.
1146   @retval Others                Other errors as indicated.
1147 
1148 **/
1149 EFI_STATUS
MnpStopSnp(IN MNP_DEVICE_DATA * MnpDeviceData)1150 MnpStopSnp (
1151   IN  MNP_DEVICE_DATA   *MnpDeviceData
1152   )
1153 {
1154   EFI_STATUS  Status;
1155   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
1156 
1157   Snp = MnpDeviceData->Snp;
1158   ASSERT (Snp != NULL);
1159 
1160   //
1161   // Recycle all the transmit buffer from SNP.
1162   //
1163   Status = MnpRecycleTxBuf (MnpDeviceData);
1164   if (EFI_ERROR (Status)) {
1165     return Status;
1166   }
1167 
1168   //
1169   // Shut down the simple network.
1170   //
1171   Status  = Snp->Shutdown (Snp);
1172   if (!EFI_ERROR (Status)) {
1173     //
1174     // Stop the simple network.
1175     //
1176     Status = Snp->Stop (Snp);
1177   }
1178 
1179   return Status;
1180 }
1181 
1182 
1183 /**
1184   Start the managed network, this function is called when one instance is configured
1185   or reconfigured.
1186 
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.
1191 
1192   @retval EFI_SUCCESS                   The managed network is started and some
1193                                         configuration is updated.
1194   @retval Others                        Other errors as indicated.
1195 
1196 **/
1197 EFI_STATUS
MnpStart(IN OUT MNP_SERVICE_DATA * MnpServiceData,IN BOOLEAN IsConfigUpdate,IN BOOLEAN EnableSystemPoll)1198 MnpStart (
1199   IN OUT MNP_SERVICE_DATA    *MnpServiceData,
1200   IN     BOOLEAN             IsConfigUpdate,
1201   IN     BOOLEAN             EnableSystemPoll
1202   )
1203 {
1204   EFI_STATUS      Status;
1205   EFI_TIMER_DELAY TimerOpType;
1206   MNP_DEVICE_DATA *MnpDeviceData;
1207 
1208   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1209 
1210   Status        = EFI_SUCCESS;
1211   MnpDeviceData = MnpServiceData->MnpDeviceData;
1212 
1213   if (!IsConfigUpdate) {
1214     //
1215     // If it's not a configuration update, increase the configured children number.
1216     //
1217     MnpDeviceData->ConfiguredChildrenNumber++;
1218 
1219     if (MnpDeviceData->ConfiguredChildrenNumber == 1) {
1220       //
1221       // It's the first configured child, start the simple network.
1222       //
1223       Status = MnpStartSnp (MnpDeviceData->Snp);
1224       if (EFI_ERROR (Status)) {
1225         DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));
1226 
1227         goto ErrorExit;
1228       }
1229 
1230       //
1231       // Start the timeout timer.
1232       //
1233       Status = gBS->SetTimer (
1234                       MnpDeviceData->TimeoutCheckTimer,
1235                       TimerPeriodic,
1236                       MNP_TIMEOUT_CHECK_INTERVAL
1237                       );
1238       if (EFI_ERROR (Status)) {
1239         DEBUG (
1240           (EFI_D_ERROR,
1241           "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
1242           Status)
1243           );
1244 
1245         goto ErrorExit;
1246       }
1247 
1248       //
1249       // Start the media detection timer.
1250       //
1251       Status = gBS->SetTimer (
1252                       MnpDeviceData->MediaDetectTimer,
1253                       TimerPeriodic,
1254                       MNP_MEDIA_DETECT_INTERVAL
1255                       );
1256       if (EFI_ERROR (Status)) {
1257         DEBUG (
1258           (EFI_D_ERROR,
1259           "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",
1260           Status)
1261           );
1262 
1263         goto ErrorExit;
1264       }
1265     }
1266   }
1267 
1268   if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {
1269     //
1270     // The EnableSystemPoll differs with the current state, disable or enable
1271     // the system poll.
1272     //
1273     TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;
1274 
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));
1278 
1279       goto ErrorExit;
1280     }
1281 
1282     MnpDeviceData->EnableSystemPoll = EnableSystemPoll;
1283   }
1284 
1285   //
1286   // Change the receive filters if need.
1287   //
1288   Status = MnpConfigReceiveFilters (MnpDeviceData);
1289 
1290 ErrorExit:
1291   return Status;
1292 }
1293 
1294 
1295 /**
1296   Stop the managed network.
1297 
1298   @param[in, out]  MnpServiceData    Pointer to the mnp service context data.
1299 
1300   @retval EFI_SUCCESS                The managed network is stopped.
1301   @retval Others                     Other errors as indicated.
1302 
1303 **/
1304 EFI_STATUS
MnpStop(IN OUT MNP_SERVICE_DATA * MnpServiceData)1305 MnpStop (
1306   IN OUT MNP_SERVICE_DATA    *MnpServiceData
1307   )
1308 {
1309   EFI_STATUS      Status;
1310   MNP_DEVICE_DATA *MnpDeviceData;
1311 
1312   NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1313   MnpDeviceData = MnpServiceData->MnpDeviceData;
1314   ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);
1315 
1316   //
1317   // Configure the receive filters.
1318   //
1319   MnpConfigReceiveFilters (MnpDeviceData);
1320 
1321   //
1322   // Decrease the children number.
1323   //
1324   MnpDeviceData->ConfiguredChildrenNumber--;
1325 
1326   if (MnpDeviceData->ConfiguredChildrenNumber > 0) {
1327     //
1328     // If there are other configured children, return and keep the timers and
1329     // simple network unchanged.
1330     //
1331     return EFI_SUCCESS;
1332   }
1333 
1334   //
1335   // No configured children now.
1336   //
1337   if (MnpDeviceData->EnableSystemPoll) {
1338     //
1339     //  The system poll in on, cancel the poll timer.
1340     //
1341     Status  = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);
1342     MnpDeviceData->EnableSystemPoll = FALSE;
1343   }
1344 
1345   //
1346   // Cancel the timeout timer.
1347   //
1348   Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);
1349 
1350   //
1351   // Cancel the media detect timer.
1352   //
1353   Status = gBS->SetTimer (MnpDeviceData->MediaDetectTimer, TimerCancel, 0);
1354 
1355   //
1356   // Stop the simple network.
1357   //
1358   Status = MnpStopSnp (MnpDeviceData);
1359   return Status;
1360 }
1361 
1362 
1363 /**
1364   Flush the instance's received data.
1365 
1366   @param[in, out]  Instance              Pointer to the mnp instance context data.
1367 
1368 **/
1369 VOID
MnpFlushRcvdDataQueue(IN OUT MNP_INSTANCE_DATA * Instance)1370 MnpFlushRcvdDataQueue (
1371   IN OUT MNP_INSTANCE_DATA   *Instance
1372   )
1373 {
1374   EFI_TPL         OldTpl;
1375   MNP_RXDATA_WRAP *RxDataWrap;
1376 
1377   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1378 
1379   OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1380 
1381   while (!IsListEmpty (&Instance->RcvdPacketQueue)) {
1382     //
1383     // Remove all the Wraps.
1384     //
1385     RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
1386 
1387     //
1388     // Recycle the RxDataWrap.
1389     //
1390     MnpRecycleRxData (NULL, (VOID *) RxDataWrap);
1391     Instance->RcvdPacketQueueSize--;
1392   }
1393 
1394   ASSERT (Instance->RcvdPacketQueueSize == 0);
1395 
1396   gBS->RestoreTPL (OldTpl);
1397 }
1398 
1399 
1400 /**
1401   Configure the Instance using ConfigData.
1402 
1403   @param[in, out]  Instance     Pointer to the mnp instance context data.
1404   @param[in]       ConfigData   Pointer to the configuration data used to configure
1405                                 the instance.
1406 
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.
1411 
1412 **/
1413 EFI_STATUS
MnpConfigureInstance(IN OUT MNP_INSTANCE_DATA * Instance,IN EFI_MANAGED_NETWORK_CONFIG_DATA * ConfigData OPTIONAL)1414 MnpConfigureInstance (
1415   IN OUT MNP_INSTANCE_DATA                 *Instance,
1416   IN     EFI_MANAGED_NETWORK_CONFIG_DATA   *ConfigData OPTIONAL
1417   )
1418 {
1419   EFI_STATUS                      Status;
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;
1425 
1426   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1427 
1428   if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {
1429     //
1430     // Don't support timestamp.
1431     //
1432     return EFI_UNSUPPORTED;
1433   }
1434 
1435   Status          = EFI_SUCCESS;
1436 
1437   MnpServiceData  = Instance->MnpServiceData;
1438   MnpDeviceData   = MnpServiceData->MnpDeviceData;
1439   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1440 
1441   IsConfigUpdate  = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));
1442 
1443   OldConfigData   = &Instance->ConfigData;
1444   NewConfigData   = ConfigData;
1445   if (NewConfigData == NULL) {
1446     //
1447     // Restore back the default config data if a reset of this instance
1448     // is required.
1449     //
1450     NewConfigData = &mMnpDefaultConfigData;
1451   }
1452 
1453   //
1454   // Reset the instance's receive filter.
1455   //
1456   Instance->ReceiveFilter = 0;
1457 
1458   //
1459   // Clear the receive counters according to the old ConfigData.
1460   //
1461   if (OldConfigData->EnableUnicastReceive) {
1462     MnpDeviceData->UnicastCount--;
1463   }
1464 
1465   if (OldConfigData->EnableMulticastReceive) {
1466     MnpDeviceData->MulticastCount--;
1467   }
1468 
1469   if (OldConfigData->EnableBroadcastReceive) {
1470     MnpDeviceData->BroadcastCount--;
1471   }
1472 
1473   if (OldConfigData->EnablePromiscuousReceive) {
1474     MnpDeviceData->PromiscuousCount--;
1475   }
1476 
1477   //
1478   // Set the receive filter counters and the receive filter of the
1479   // instance according to the new ConfigData.
1480   //
1481   if (NewConfigData->EnableUnicastReceive) {
1482     MnpDeviceData->UnicastCount++;
1483     Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;
1484   }
1485 
1486   if (NewConfigData->EnableMulticastReceive) {
1487     MnpDeviceData->MulticastCount++;
1488   }
1489 
1490   if (NewConfigData->EnableBroadcastReceive) {
1491     MnpDeviceData->BroadcastCount++;
1492     Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;
1493   }
1494 
1495   if (NewConfigData->EnablePromiscuousReceive) {
1496     MnpDeviceData->PromiscuousCount++;
1497   }
1498 
1499   if (OldConfigData->FlushQueuesOnReset) {
1500     MnpFlushRcvdDataQueue (Instance);
1501   }
1502 
1503   if (ConfigData == NULL) {
1504     Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);
1505   }
1506 
1507   if (!NewConfigData->EnableMulticastReceive) {
1508     MnpGroupOp (Instance, FALSE, NULL, NULL);
1509   }
1510 
1511   //
1512   // Save the new configuration data.
1513   //
1514   CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));
1515 
1516   Instance->Configured = (BOOLEAN) (ConfigData != NULL);
1517   if (Instance->Configured) {
1518     //
1519     // The instance is configured, start the Mnp.
1520     //
1521     Status = MnpStart (
1522               MnpServiceData,
1523               IsConfigUpdate,
1524               (BOOLEAN) !NewConfigData->DisableBackgroundPolling
1525               );
1526   } else {
1527     //
1528     // The instance is changed to the unconfigured state, stop the Mnp.
1529     //
1530     Status = MnpStop (MnpServiceData);
1531   }
1532 
1533   return Status;
1534 }
1535 
1536 /**
1537   Configure the Snp receive filters according to the instances' receive filter
1538   settings.
1539 
1540   @param[in]  MnpDeviceData         Pointer to the mnp device context data.
1541 
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.
1545 
1546 **/
1547 EFI_STATUS
MnpConfigReceiveFilters(IN MNP_DEVICE_DATA * MnpDeviceData)1548 MnpConfigReceiveFilters (
1549   IN MNP_DEVICE_DATA     *MnpDeviceData
1550   )
1551 {
1552   EFI_STATUS                  Status;
1553   EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
1554   EFI_MAC_ADDRESS             *MCastFilter;
1555   UINT32                      MCastFilterCnt;
1556   UINT32                      EnableFilterBits;
1557   UINT32                      DisableFilterBits;
1558   BOOLEAN                     ResetMCastFilters;
1559   LIST_ENTRY                  *Entry;
1560   UINT32                      Index;
1561   MNP_GROUP_ADDRESS           *GroupAddress;
1562 
1563   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1564 
1565   Snp = MnpDeviceData->Snp;
1566 
1567   //
1568   // Initialize the enable filter and disable filter.
1569   //
1570   EnableFilterBits  = 0;
1571   DisableFilterBits = Snp->Mode->ReceiveFilterMask;
1572 
1573   if (MnpDeviceData->UnicastCount != 0) {
1574     //
1575     // Enable unicast if any instance wants to receive unicast.
1576     //
1577     EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1578   }
1579 
1580   if (MnpDeviceData->BroadcastCount != 0) {
1581     //
1582     // Enable broadcast if any instance wants to receive broadcast.
1583     //
1584     EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
1585   }
1586 
1587   MCastFilter       = NULL;
1588   MCastFilterCnt    = 0;
1589   ResetMCastFilters = TRUE;
1590 
1591   if ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->GroupAddressCount != 0)) {
1592     //
1593     // There are instances configured to receive multicast and already some group
1594     // addresses are joined.
1595     //
1596 
1597     ResetMCastFilters = FALSE;
1598 
1599     if (MnpDeviceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {
1600       //
1601       // The joind group address is less than simple network's maximum count.
1602       // Just configure the snp to do the multicast filtering.
1603       //
1604 
1605       EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
1606 
1607       //
1608       // Allocate pool for the multicast addresses.
1609       //
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"));
1614 
1615         return EFI_OUT_OF_RESOURCES;
1616       }
1617 
1618       //
1619       // Fill the multicast HW address buffer.
1620       //
1621       Index = 0;
1622       NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
1623 
1624         GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1625         CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));
1626         Index++;
1627 
1628         ASSERT (Index <= MCastFilterCnt);
1629       }
1630     } else {
1631       //
1632       // The maximum multicast is reached, set the filter to be promiscuous
1633       // multicast.
1634       //
1635 
1636       if ((Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
1637         EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1638       } else {
1639         //
1640         // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1641         // set the NIC to be promiscuous although this will tremendously degrade
1642         // the performance.
1643         //
1644         EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1645       }
1646     }
1647   }
1648 
1649   if (MnpDeviceData->PromiscuousCount != 0) {
1650     //
1651     // Enable promiscuous if any instance wants to receive promiscuous.
1652     //
1653     EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1654   }
1655 
1656   //
1657   // Set the disable filter.
1658   //
1659   DisableFilterBits ^= EnableFilterBits;
1660 
1661   //
1662   // Configure the receive filters of SNP.
1663   //
1664   Status = Snp->ReceiveFilters (
1665                   Snp,
1666                   EnableFilterBits,
1667                   DisableFilterBits,
1668                   ResetMCastFilters,
1669                   MCastFilterCnt,
1670                   MCastFilter
1671                   );
1672   DEBUG_CODE (
1673     if (EFI_ERROR (Status)) {
1674       DEBUG (
1675         (EFI_D_ERROR,
1676         "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1677         Status)
1678         );
1679     }
1680   );
1681 
1682   if (MCastFilter != NULL) {
1683     //
1684     // Free the buffer used to hold the group addresses.
1685     //
1686     FreePool (MCastFilter);
1687   }
1688 
1689   return Status;
1690 }
1691 
1692 
1693 /**
1694   Add a group address control block which controls the MacAddress for
1695   this instance.
1696 
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 address.
1700   @param[in]       MacAddress      Pointer to the mac address.
1701   @param[in]       HwAddressSize   The hardware address size.
1702 
1703   @retval EFI_SUCCESS              The group address control block is added.
1704   @retval EFI_OUT_OF_RESOURCES     Failed due to lack of memory resources.
1705 
1706 **/
1707 EFI_STATUS
MnpGroupOpAddCtrlBlk(IN OUT MNP_INSTANCE_DATA * Instance,IN OUT MNP_GROUP_CONTROL_BLOCK * CtrlBlk,IN OUT MNP_GROUP_ADDRESS * GroupAddress OPTIONAL,IN EFI_MAC_ADDRESS * MacAddress,IN UINT32 HwAddressSize)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
1714   )
1715 {
1716   MNP_DEVICE_DATA  *MnpDeviceData;
1717 
1718   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1719 
1720   MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1721   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1722 
1723   if (GroupAddress == NULL) {
1724     ASSERT (MacAddress != NULL);
1725 
1726     //
1727     // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1728     //
1729     GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));
1730     if (GroupAddress == NULL) {
1731 
1732       DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1733 
1734       return EFI_OUT_OF_RESOURCES;
1735     }
1736 
1737     CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));
1738     GroupAddress->RefCnt = 0;
1739     InsertTailList (
1740       &MnpDeviceData->GroupAddressList,
1741       &GroupAddress->AddrEntry
1742       );
1743     MnpDeviceData->GroupAddressCount++;
1744   }
1745 
1746   //
1747   // Increase the RefCnt.
1748   //
1749   GroupAddress->RefCnt++;
1750 
1751   //
1752   // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1753   //
1754   CtrlBlk->GroupAddress = GroupAddress;
1755   InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);
1756 
1757   return EFI_SUCCESS;
1758 }
1759 
1760 
1761 /**
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.
1764 
1765   @param[in]  Instance              Pointer to the instance context data.
1766   @param[in]  CtrlBlk               Pointer to the group control block to delete.
1767 
1768   @return The group address controlled by the control block is no longer used or not.
1769 
1770 **/
1771 BOOLEAN
MnpGroupOpDelCtrlBlk(IN MNP_INSTANCE_DATA * Instance,IN MNP_GROUP_CONTROL_BLOCK * CtrlBlk)1772 MnpGroupOpDelCtrlBlk (
1773   IN MNP_INSTANCE_DATA           *Instance,
1774   IN MNP_GROUP_CONTROL_BLOCK     *CtrlBlk
1775   )
1776 {
1777   MNP_DEVICE_DATA   *MnpDeviceData;
1778   MNP_GROUP_ADDRESS *GroupAddress;
1779 
1780   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1781 
1782   MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1783   NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1784 
1785   //
1786   // Remove and free the CtrlBlk.
1787   //
1788   GroupAddress = CtrlBlk->GroupAddress;
1789   RemoveEntryList (&CtrlBlk->CtrlBlkEntry);
1790   FreePool (CtrlBlk);
1791 
1792   ASSERT (GroupAddress->RefCnt > 0);
1793 
1794   //
1795   // Count down the RefCnt.
1796   //
1797   GroupAddress->RefCnt--;
1798 
1799   if (GroupAddress->RefCnt == 0) {
1800     //
1801     // Free this GroupAddress entry if no instance uses it.
1802     //
1803     MnpDeviceData->GroupAddressCount--;
1804     RemoveEntryList (&GroupAddress->AddrEntry);
1805     FreePool (GroupAddress);
1806 
1807     return TRUE;
1808   }
1809 
1810   return FALSE;
1811 }
1812 
1813 
1814 /**
1815   Do the group operations for this instance.
1816 
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
1822                                    is FALSE.
1823 
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.
1827 
1828 **/
1829 EFI_STATUS
MnpGroupOp(IN OUT MNP_INSTANCE_DATA * Instance,IN BOOLEAN JoinFlag,IN EFI_MAC_ADDRESS * MacAddress OPTIONAL,IN MNP_GROUP_CONTROL_BLOCK * CtrlBlk OPTIONAL)1830 MnpGroupOp (
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
1835   )
1836 {
1837   MNP_DEVICE_DATA         *MnpDeviceData;
1838   LIST_ENTRY              *Entry;
1839   LIST_ENTRY              *NextEntry;
1840   MNP_GROUP_ADDRESS       *GroupAddress;
1841   EFI_SIMPLE_NETWORK_MODE *SnpMode;
1842   MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;
1843   EFI_STATUS              Status;
1844   BOOLEAN                 AddressExist;
1845   BOOLEAN                 NeedUpdate;
1846 
1847   NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1848 
1849   MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1850   SnpMode       = MnpDeviceData->Snp->Mode;
1851 
1852   if (JoinFlag) {
1853     //
1854     // A new group address is to be added.
1855     //
1856     GroupAddress  = NULL;
1857     AddressExist  = FALSE;
1858 
1859     //
1860     // Allocate memory for the control block.
1861     //
1862     NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));
1863     if (NewCtrlBlk == NULL) {
1864       DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));
1865 
1866       return EFI_OUT_OF_RESOURCES;
1867     }
1868 
1869     NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
1870       //
1871       // Check whether the MacAddress is already joined by other instances.
1872       //
1873       GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1874       if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {
1875         AddressExist = TRUE;
1876         break;
1877       }
1878     }
1879 
1880     if (!AddressExist) {
1881       GroupAddress = NULL;
1882     }
1883 
1884     //
1885     // Add the GroupAddress for this instance.
1886     //
1887     Status = MnpGroupOpAddCtrlBlk (
1888               Instance,
1889               NewCtrlBlk,
1890               GroupAddress,
1891               MacAddress,
1892               SnpMode->HwAddressSize
1893               );
1894     if (EFI_ERROR (Status)) {
1895       return Status;
1896     }
1897 
1898     NeedUpdate = TRUE;
1899   } else {
1900     if (MacAddress != NULL) {
1901       ASSERT (CtrlBlk != NULL);
1902 
1903       //
1904       // Leave the specific multicast mac address.
1905       //
1906       NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);
1907     } else {
1908       //
1909       // Leave all multicast mac addresses.
1910       //
1911       NeedUpdate = FALSE;
1912 
1913       NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {
1914 
1915         NewCtrlBlk = NET_LIST_USER_STRUCT (
1916                       Entry,
1917                       MNP_GROUP_CONTROL_BLOCK,
1918                       CtrlBlkEntry
1919                       );
1920         //
1921         // Update is required if the group address left is no longer used
1922         // by other instances.
1923         //
1924         NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);
1925       }
1926     }
1927   }
1928 
1929   Status = EFI_SUCCESS;
1930 
1931   if (NeedUpdate) {
1932     //
1933     // Reconfigure the receive filters if necessary.
1934     //
1935     Status = MnpConfigReceiveFilters (MnpDeviceData);
1936   }
1937 
1938   return Status;
1939 }
1940