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