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