]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
Add VLAN support.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
1 /** @file
2 Implementation of Managed Network Protocol private services.
3
4 Copyright (c) 2005 - 2009, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The full
8 text of the license may be found at<BR>
9 http://opensource.org/licenses/bsd-license.php
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 tx timeout check.
360 //
361 Status = gBS->CreateEvent (
362 EVT_TIMER,
363 TPL_CALLBACK,
364 NULL,
365 NULL,
366 &MnpDeviceData->TxTimeoutEvent
367 );
368 if (EFI_ERROR (Status)) {
369 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for tx timeout event failed.\n"));
370 }
371
372 ERROR:
373 if (EFI_ERROR (Status)) {
374 //
375 // Free the dynamic allocated resources if necessary.
376 //
377 if (MnpDeviceData->MacString != NULL) {
378 FreePool (MnpDeviceData->MacString);
379 }
380
381 if (MnpDeviceData->TimeoutCheckTimer != NULL) {
382 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);
383 }
384
385 if (MnpDeviceData->PollTimer != NULL) {
386 gBS->CloseEvent (MnpDeviceData->PollTimer);
387 }
388
389 if (MnpDeviceData->TxBuf != NULL) {
390 FreePool (MnpDeviceData->TxBuf);
391 }
392
393 if (MnpDeviceData->RxNbufCache != NULL) {
394 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);
395 }
396
397 if (MnpDeviceData->FreeNbufQue.BufNum != 0) {
398 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);
399 }
400
401 //
402 // Close the Simple Network Protocol.
403 //
404 gBS->CloseProtocol (
405 ControllerHandle,
406 &gEfiSimpleNetworkProtocolGuid,
407 ImageHandle,
408 ControllerHandle
409 );
410 }
411
412 return Status;
413 }
414
415
416 /**
417 Destroy the MNP device context data.
418
419 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
420 @param[in] ImageHandle The driver image handle.
421
422 **/
423 VOID
424 MnpDestroyDeviceData (
425 IN OUT MNP_DEVICE_DATA *MnpDeviceData,
426 IN EFI_HANDLE ImageHandle
427 )
428 {
429 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
430
431 //
432 // Free Vlan Config variable name string
433 //
434 if (MnpDeviceData->MacString != NULL) {
435 FreePool (MnpDeviceData->MacString);
436 }
437
438 //
439 // The GroupAddressList must be empty.
440 //
441 ASSERT (IsListEmpty (&MnpDeviceData->GroupAddressList));
442
443 //
444 // Close the event.
445 //
446 gBS->CloseEvent (&MnpDeviceData->TxTimeoutEvent);
447 gBS->CloseEvent (&MnpDeviceData->TimeoutCheckTimer);
448 gBS->CloseEvent (&MnpDeviceData->PollTimer);
449
450 //
451 // Free the tx buffer.
452 //
453 FreePool (MnpDeviceData->TxBuf);
454
455 //
456 // Free the RxNbufCache.
457 //
458 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);
459
460 //
461 // Flush the FreeNbufQue.
462 //
463 MnpDeviceData->NbufCnt -= MnpDeviceData->FreeNbufQue.BufNum;
464 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);
465
466 //
467 // Close the Simple Network Protocol.
468 //
469 gBS->CloseProtocol (
470 MnpDeviceData->ControllerHandle,
471 &gEfiSimpleNetworkProtocolGuid,
472 ImageHandle,
473 MnpDeviceData->ControllerHandle
474 );
475 }
476
477
478 /**
479 Create mnp service context data.
480
481 @param[in] MnpDeviceData Pointer to the mnp device context data.
482 @param[in] VlanId The VLAN ID.
483 @param[in] Priority The VLAN priority. If VlanId is 0,
484 Priority is ignored.
485
486 @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.
487
488 **/
489 MNP_SERVICE_DATA *
490 MnpCreateServiceData (
491 IN MNP_DEVICE_DATA *MnpDeviceData,
492 IN UINT16 VlanId,
493 IN UINT8 Priority OPTIONAL
494 )
495 {
496 EFI_HANDLE MnpServiceHandle;
497 MNP_SERVICE_DATA *MnpServiceData;
498 EFI_STATUS Status;
499 EFI_SIMPLE_NETWORK_MODE *SnpMode;
500 EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
501
502 //
503 // Initialize the Mnp Service Data.
504 //
505 MnpServiceData = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));
506 if (MnpServiceData == NULL) {
507 DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to allocate memory for the new Mnp Service Data.\n"));
508
509 return NULL;
510 }
511
512 //
513 // Add to MNP service list
514 //
515 InsertTailList (&MnpDeviceData->ServiceList, &MnpServiceData->Link);
516
517 MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;
518 MnpServiceData->MnpDeviceData = MnpDeviceData;
519
520 //
521 // Copy the ServiceBinding structure.
522 //
523 CopyMem (&MnpServiceData->ServiceBinding, &mMnpServiceBindingProtocol, sizeof (EFI_SERVICE_BINDING_PROTOCOL));
524
525 //
526 // Initialize the lists.
527 //
528 InitializeListHead (&MnpServiceData->ChildrenList);
529
530 SnpMode = MnpDeviceData->Snp->Mode;
531 if (VlanId != 0) {
532 //
533 // Create VLAN child handle
534 //
535 MnpServiceHandle = MnpCreateVlanChild (
536 MnpDeviceData->ImageHandle,
537 MnpDeviceData->ControllerHandle,
538 VlanId,
539 &MnpServiceData->DevicePath
540 );
541 if (MnpServiceHandle == NULL) {
542 DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to create child handle.\n"));
543
544 return NULL;
545 }
546
547 //
548 // Open VLAN Config Protocol by child
549 //
550 Status = gBS->OpenProtocol (
551 MnpDeviceData->ControllerHandle,
552 &gEfiVlanConfigProtocolGuid,
553 (VOID **) &VlanConfig,
554 MnpDeviceData->ImageHandle,
555 MnpServiceHandle,
556 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
557 );
558 if (EFI_ERROR (Status)) {
559 goto Exit;
560 }
561
562 //
563 // Reduce MTU for VLAN device
564 //
565 MnpServiceData->Mtu = SnpMode->MaxPacketSize - NET_VLAN_TAG_LEN;
566 } else {
567 //
568 // VlanId set to 0 means rx/tx untagged frame
569 //
570 MnpServiceHandle = MnpDeviceData->ControllerHandle;
571 MnpServiceData->Mtu = SnpMode->MaxPacketSize;
572 }
573
574 MnpServiceData->ServiceHandle = MnpServiceHandle;
575 MnpServiceData->VlanId = VlanId;
576 MnpServiceData->Priority = Priority;
577
578 //
579 // Install the MNP Service Binding Protocol
580 //
581 Status = gBS->InstallMultipleProtocolInterfaces (
582 &MnpServiceHandle,
583 &gEfiManagedNetworkServiceBindingProtocolGuid,
584 &MnpServiceData->ServiceBinding,
585 NULL
586 );
587
588 Exit:
589 if (EFI_ERROR (Status)) {
590 MnpDestroyServiceData (MnpServiceData);
591 MnpServiceData = NULL;
592 }
593
594 return MnpServiceData;
595 }
596
597 /**
598 Destroy the MNP service context data.
599
600 @param[in, out] MnpServiceData Pointer to the mnp service context data.
601
602 @retval EFI_SUCCESS The mnp service context is destroyed.
603 @retval Others Errors as indicated.
604
605 **/
606 EFI_STATUS
607 MnpDestroyServiceData (
608 IN OUT MNP_SERVICE_DATA *MnpServiceData
609 )
610 {
611 EFI_STATUS Status;
612
613 //
614 // Uninstall the MNP Service Binding Protocol
615 //
616 Status = gBS->UninstallMultipleProtocolInterfaces (
617 MnpServiceData->ServiceHandle,
618 &gEfiManagedNetworkServiceBindingProtocolGuid,
619 &MnpServiceData->ServiceBinding,
620 NULL
621 );
622 if (EFI_ERROR (Status)) {
623 return Status;
624 }
625
626 if (MnpServiceData->VlanId != 0) {
627 //
628 // Close VlanConfig Protocol opened by VLAN child handle
629 //
630 Status = gBS->CloseProtocol (
631 MnpServiceData->MnpDeviceData->ControllerHandle,
632 &gEfiVlanConfigProtocolGuid,
633 MnpServiceData->MnpDeviceData->ImageHandle,
634 MnpServiceData->ServiceHandle
635 );
636 if (EFI_ERROR (Status)) {
637 return Status;
638 }
639
640 //
641 // Uninstall Device Path Protocol to destroy the VLAN child handle
642 //
643 Status = gBS->UninstallMultipleProtocolInterfaces (
644 MnpServiceData->ServiceHandle,
645 &gEfiDevicePathProtocolGuid,
646 MnpServiceData->DevicePath,
647 NULL
648 );
649 if (EFI_ERROR (Status)) {
650 return Status;
651 }
652
653 if (MnpServiceData->DevicePath != NULL) {
654 FreePool (MnpServiceData->DevicePath);
655 }
656 }
657
658 //
659 // Remove from MnpDeviceData service list
660 //
661 RemoveEntryList (&MnpServiceData->Link);
662
663 FreePool (MnpServiceData);
664
665 return Status;
666 }
667
668 /**
669 Destroy all child of the MNP service data.
670
671 @param[in, out] MnpServiceData Pointer to the mnp service context data.
672
673 @retval EFI_SUCCESS All child are destroyed.
674 @retval Others Failed to destroy all child.
675
676 **/
677 EFI_STATUS
678 MnpDestroyServiceChild (
679 IN OUT MNP_SERVICE_DATA *MnpServiceData
680 )
681 {
682 EFI_STATUS Status;
683 MNP_INSTANCE_DATA *Instance;
684 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
685
686 ServiceBinding = &MnpServiceData->ServiceBinding;
687 while (!IsListEmpty (&MnpServiceData->ChildrenList)) {
688 //
689 // Don't use NetListRemoveHead here, the remove opreration will be done
690 // in ServiceBindingDestroyChild.
691 //
692 Instance = NET_LIST_HEAD (
693 &MnpServiceData->ChildrenList,
694 MNP_INSTANCE_DATA,
695 InstEntry
696 );
697
698 Status = ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
699 if (EFI_ERROR (Status)) {
700 return Status;
701 }
702 }
703
704 return EFI_SUCCESS;
705 }
706
707 /**
708 Find the MNP Service Data for given VLAN ID.
709
710 @param[in] MnpDeviceData Pointer to the mnp device context data.
711 @param[in] VlanId The VLAN ID.
712
713 @return A pointer to MNP_SERVICE_DATA or NULL if not found.
714
715 **/
716 MNP_SERVICE_DATA *
717 MnpFindServiceData (
718 IN MNP_DEVICE_DATA *MnpDeviceData,
719 IN UINT16 VlanId
720 )
721 {
722 LIST_ENTRY *Entry;
723 MNP_SERVICE_DATA *MnpServiceData;
724
725 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {
726 //
727 // Check VLAN ID of each Mnp Service Data
728 //
729 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
730 if (MnpServiceData->VlanId == VlanId) {
731 return MnpServiceData;
732 }
733 }
734
735 return NULL;
736 }
737
738 /**
739 Initialize the mnp instance context data.
740
741 @param[in] MnpServiceData Pointer to the mnp service context data.
742 @param[in, out] Instance Pointer to the mnp instance context data
743 to initialize.
744
745 **/
746 VOID
747 MnpInitializeInstanceData (
748 IN MNP_SERVICE_DATA *MnpServiceData,
749 IN OUT MNP_INSTANCE_DATA *Instance
750 )
751 {
752 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
753 ASSERT (Instance != NULL);
754
755 //
756 // Set the signature.
757 //
758 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;
759
760 //
761 // Copy the MNP Protocol interfaces from the template.
762 //
763 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));
764
765 //
766 // Copy the default config data.
767 //
768 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));
769
770 //
771 // Initialize the lists.
772 //
773 InitializeListHead (&Instance->GroupCtrlBlkList);
774 InitializeListHead (&Instance->RcvdPacketQueue);
775 InitializeListHead (&Instance->RxDeliveredPacketQueue);
776
777 //
778 // Initialize the RxToken Map.
779 //
780 NetMapInit (&Instance->RxTokenMap);
781
782 //
783 // Save the MnpServiceData info.
784 //
785 Instance->MnpServiceData = MnpServiceData;
786 }
787
788
789 /**
790 Check whether the token specified by Arg matches the token in Item.
791
792 @param[in] Map Pointer to the NET_MAP.
793 @param[in] Item Pointer to the NET_MAP_ITEM.
794 @param[in] Arg Pointer to the Arg, it's a pointer to the token to
795 check.
796
797 @retval EFI_SUCCESS The token specified by Arg is different from the
798 token in Item.
799 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
800 Item.
801
802 **/
803 EFI_STATUS
804 MnpTokenExist (
805 IN NET_MAP *Map,
806 IN NET_MAP_ITEM *Item,
807 IN VOID *Arg
808 )
809 {
810 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;
811 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;
812
813 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;
814 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
815
816 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
817 //
818 // The token is the same either the two tokens equals or the Events in
819 // the two tokens are the same.
820 //
821 return EFI_ACCESS_DENIED;
822 }
823
824 return EFI_SUCCESS;
825 }
826
827 /**
828 Cancel the token specified by Arg if it matches the token in Item.
829
830 @param[in, out] Map Pointer to the NET_MAP.
831 @param[in, out] Item Pointer to the NET_MAP_ITEM.
832 @param[in] Arg Pointer to the Arg, it's a pointer to the
833 token to cancel.
834
835 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,
836 or the Arg isn't NULL, and the token in Item is
837 different from the Arg.
838 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
839 Arg, and the token is cancelled.
840
841 **/
842 EFI_STATUS
843 MnpCancelTokens (
844 IN OUT NET_MAP *Map,
845 IN OUT NET_MAP_ITEM *Item,
846 IN VOID *Arg
847 )
848 {
849 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;
850
851 if ((Arg != NULL) && (Item->Key != Arg)) {
852 //
853 // The token in Item is not the token specified by Arg.
854 //
855 return EFI_SUCCESS;
856 }
857
858 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
859
860 //
861 // Remove the item from the map.
862 //
863 NetMapRemoveItem (Map, Item, NULL);
864
865 //
866 // Cancel this token with status set to EFI_ABORTED.
867 //
868 TokenToCancel->Status = EFI_ABORTED;
869 gBS->SignalEvent (TokenToCancel->Event);
870
871 if (Arg != NULL) {
872 //
873 // Only abort the token specified by Arg if Arg isn't NULL.
874 //
875 return EFI_ABORTED;
876 }
877
878 return EFI_SUCCESS;
879 }
880
881
882 /**
883 Start and initialize the simple network.
884
885 @param[in] Snp Pointer to the simple network protocol.
886
887 @retval EFI_SUCCESS The simple network protocol is started.
888 @retval Others Other errors as indicated.
889
890 **/
891 EFI_STATUS
892 MnpStartSnp (
893 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
894 )
895 {
896 EFI_STATUS Status;
897
898 ASSERT (Snp != NULL);
899
900 //
901 // Start the simple network.
902 //
903 Status = Snp->Start (Snp);
904
905 if (!EFI_ERROR (Status)) {
906 //
907 // Initialize the simple network.
908 //
909 Status = Snp->Initialize (Snp, 0, 0);
910 }
911
912 return Status;
913 }
914
915
916 /**
917 Stop the simple network.
918
919 @param[in] Snp Pointer to the simple network protocol.
920
921 @retval EFI_SUCCESS The simple network is stopped.
922 @retval Others Other errors as indicated.
923
924 **/
925 EFI_STATUS
926 MnpStopSnp (
927 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
928 )
929 {
930 EFI_STATUS Status;
931
932 ASSERT (Snp != NULL);
933
934 //
935 // Shut down the simple network.
936 //
937 Status = Snp->Shutdown (Snp);
938 if (!EFI_ERROR (Status)) {
939 //
940 // Stop the simple network.
941 //
942 Status = Snp->Stop (Snp);
943 }
944
945 return Status;
946 }
947
948
949 /**
950 Start the managed network, this function is called when one instance is configured
951 or reconfigured.
952
953 @param[in, out] MnpServiceData Pointer to the mnp service context data.
954 @param[in] IsConfigUpdate The instance is reconfigured or it's the first
955 time the instanced is configured.
956 @param[in] EnableSystemPoll Enable the system polling or not.
957
958 @retval EFI_SUCCESS The managed network is started and some
959 configuration is updated.
960 @retval Others Other errors as indicated.
961
962 **/
963 EFI_STATUS
964 MnpStart (
965 IN OUT MNP_SERVICE_DATA *MnpServiceData,
966 IN BOOLEAN IsConfigUpdate,
967 IN BOOLEAN EnableSystemPoll
968 )
969 {
970 EFI_STATUS Status;
971 EFI_TIMER_DELAY TimerOpType;
972 MNP_DEVICE_DATA *MnpDeviceData;
973
974 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
975
976 Status = EFI_SUCCESS;
977 MnpDeviceData = MnpServiceData->MnpDeviceData;
978
979 if (!IsConfigUpdate) {
980 //
981 // If it's not a configuration update, increase the configured children number.
982 //
983 MnpDeviceData->ConfiguredChildrenNumber++;
984
985 if (MnpDeviceData->ConfiguredChildrenNumber == 1) {
986 //
987 // It's the first configured child, start the simple network.
988 //
989 Status = MnpStartSnp (MnpDeviceData->Snp);
990 if (EFI_ERROR (Status)) {
991 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));
992
993 goto ErrorExit;
994 }
995
996 //
997 // Start the timeout timer.
998 //
999 Status = gBS->SetTimer (
1000 MnpDeviceData->TimeoutCheckTimer,
1001 TimerPeriodic,
1002 MNP_TIMEOUT_CHECK_INTERVAL
1003 );
1004 if (EFI_ERROR (Status)) {
1005 DEBUG (
1006 (EFI_D_ERROR,
1007 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
1008 Status)
1009 );
1010
1011 goto ErrorExit;
1012 }
1013 }
1014 }
1015
1016 if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {
1017 //
1018 // The EnableSystemPoll differs with the current state, disable or enable
1019 // the system poll.
1020 //
1021 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;
1022
1023 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);
1024 if (EFI_ERROR (Status)) {
1025 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));
1026
1027 goto ErrorExit;
1028 }
1029
1030 MnpDeviceData->EnableSystemPoll = EnableSystemPoll;
1031 }
1032
1033 //
1034 // Change the receive filters if need.
1035 //
1036 Status = MnpConfigReceiveFilters (MnpDeviceData);
1037
1038 ErrorExit:
1039 return Status;
1040 }
1041
1042
1043 /**
1044 Stop the managed network.
1045
1046 @param[in, out] MnpServiceData Pointer to the mnp service context data.
1047
1048 @retval EFI_SUCCESS The managed network is stopped.
1049 @retval Others Other errors as indicated.
1050
1051 **/
1052 EFI_STATUS
1053 MnpStop (
1054 IN OUT MNP_SERVICE_DATA *MnpServiceData
1055 )
1056 {
1057 EFI_STATUS Status;
1058 MNP_DEVICE_DATA *MnpDeviceData;
1059
1060 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1061 MnpDeviceData = MnpServiceData->MnpDeviceData;
1062 ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);
1063
1064 //
1065 // Configure the receive filters.
1066 //
1067 MnpConfigReceiveFilters (MnpDeviceData);
1068
1069 //
1070 // Decrease the children number.
1071 //
1072 MnpDeviceData->ConfiguredChildrenNumber--;
1073
1074 if (MnpDeviceData->ConfiguredChildrenNumber > 0) {
1075 //
1076 // If there are other configured chilren, return and keep the timers and
1077 // simple network unchanged.
1078 //
1079 return EFI_SUCCESS;
1080 }
1081
1082 //
1083 // No configured children now.
1084 //
1085 if (MnpDeviceData->EnableSystemPoll) {
1086 //
1087 // The system poll in on, cancel the poll timer.
1088 //
1089 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);
1090 MnpDeviceData->EnableSystemPoll = FALSE;
1091 }
1092
1093 //
1094 // Cancel the timeout timer.
1095 //
1096 Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);
1097
1098 //
1099 // Stop the simple network.
1100 //
1101 Status = MnpStopSnp (MnpDeviceData->Snp);
1102 return Status;
1103 }
1104
1105
1106 /**
1107 Flush the instance's received data.
1108
1109 @param[in, out] Instance Pointer to the mnp instance context data.
1110
1111 **/
1112 VOID
1113 MnpFlushRcvdDataQueue (
1114 IN OUT MNP_INSTANCE_DATA *Instance
1115 )
1116 {
1117 EFI_TPL OldTpl;
1118 MNP_RXDATA_WRAP *RxDataWrap;
1119
1120 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1121
1122 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1123
1124 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {
1125 //
1126 // Remove all the Wraps.
1127 //
1128 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
1129
1130 //
1131 // Recycle the RxDataWrap.
1132 //
1133 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);
1134 Instance->RcvdPacketQueueSize--;
1135 }
1136
1137 ASSERT (Instance->RcvdPacketQueueSize == 0);
1138
1139 gBS->RestoreTPL (OldTpl);
1140 }
1141
1142
1143 /**
1144 Configure the Instance using ConfigData.
1145
1146 @param[in, out] Instance Pointer to the mnp instance context data.
1147 @param[in] ConfigData Pointer to the configuration data used to configure
1148 the isntance.
1149
1150 @retval EFI_SUCCESS The Instance is configured.
1151 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1152 implementation doesn't support it.
1153 @retval Others Other errors as indicated.
1154
1155 **/
1156 EFI_STATUS
1157 MnpConfigureInstance (
1158 IN OUT MNP_INSTANCE_DATA *Instance,
1159 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL
1160 )
1161 {
1162 EFI_STATUS Status;
1163 MNP_SERVICE_DATA *MnpServiceData;
1164 MNP_DEVICE_DATA *MnpDeviceData;
1165 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;
1166 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;
1167 BOOLEAN IsConfigUpdate;
1168
1169 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1170
1171 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {
1172 //
1173 // Don't support timestamp.
1174 //
1175 return EFI_UNSUPPORTED;
1176 }
1177
1178 Status = EFI_SUCCESS;
1179
1180 MnpServiceData = Instance->MnpServiceData;
1181 MnpDeviceData = MnpServiceData->MnpDeviceData;
1182 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1183
1184 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));
1185
1186 OldConfigData = &Instance->ConfigData;
1187 NewConfigData = ConfigData;
1188 if (NewConfigData == NULL) {
1189 //
1190 // Restore back the default config data if a reset of this instance
1191 // is required.
1192 //
1193 NewConfigData = &mMnpDefaultConfigData;
1194 }
1195
1196 //
1197 // Reset the instance's receive filter.
1198 //
1199 Instance->ReceiveFilter = 0;
1200
1201 //
1202 // Clear the receive counters according to the old ConfigData.
1203 //
1204 if (OldConfigData->EnableUnicastReceive) {
1205 MnpDeviceData->UnicastCount--;
1206 }
1207
1208 if (OldConfigData->EnableMulticastReceive) {
1209 MnpDeviceData->MulticastCount--;
1210 }
1211
1212 if (OldConfigData->EnableBroadcastReceive) {
1213 MnpDeviceData->BroadcastCount--;
1214 }
1215
1216 if (OldConfigData->EnablePromiscuousReceive) {
1217 MnpDeviceData->PromiscuousCount--;
1218 }
1219
1220 //
1221 // Set the receive filter counters and the receive filter of the
1222 // instance according to the new ConfigData.
1223 //
1224 if (NewConfigData->EnableUnicastReceive) {
1225 MnpDeviceData->UnicastCount++;
1226 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;
1227 }
1228
1229 if (NewConfigData->EnableMulticastReceive) {
1230 MnpDeviceData->MulticastCount++;
1231 }
1232
1233 if (NewConfigData->EnableBroadcastReceive) {
1234 MnpDeviceData->BroadcastCount++;
1235 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;
1236 }
1237
1238 if (NewConfigData->EnablePromiscuousReceive) {
1239 MnpDeviceData->PromiscuousCount++;
1240 }
1241
1242 if (OldConfigData->FlushQueuesOnReset) {
1243 MnpFlushRcvdDataQueue (Instance);
1244 }
1245
1246 if (ConfigData == NULL) {
1247 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);
1248 }
1249
1250 if (!NewConfigData->EnableMulticastReceive) {
1251 MnpGroupOp (Instance, FALSE, NULL, NULL);
1252 }
1253
1254 //
1255 // Save the new configuration data.
1256 //
1257 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));
1258
1259 Instance->Configured = (BOOLEAN) (ConfigData != NULL);
1260 if (Instance->Configured) {
1261 //
1262 // The instance is configured, start the Mnp.
1263 //
1264 Status = MnpStart (
1265 MnpServiceData,
1266 IsConfigUpdate,
1267 (BOOLEAN) !NewConfigData->DisableBackgroundPolling
1268 );
1269 } else {
1270 //
1271 // The instance is changed to the unconfigured state, stop the Mnp.
1272 //
1273 Status = MnpStop (MnpServiceData);
1274 }
1275
1276 return Status;
1277 }
1278
1279 /**
1280 Configure the Snp receive filters according to the instances' receive filter
1281 settings.
1282
1283 @param[in] MnpDeviceData Pointer to the mnp device context data.
1284
1285 @retval EFI_SUCCESS The receive filters is configured.
1286 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due
1287 to lack of memory resource.
1288
1289 **/
1290 EFI_STATUS
1291 MnpConfigReceiveFilters (
1292 IN MNP_DEVICE_DATA *MnpDeviceData
1293 )
1294 {
1295 EFI_STATUS Status;
1296 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
1297 EFI_MAC_ADDRESS *MCastFilter;
1298 UINT32 MCastFilterCnt;
1299 UINT32 EnableFilterBits;
1300 UINT32 DisableFilterBits;
1301 BOOLEAN ResetMCastFilters;
1302 LIST_ENTRY *Entry;
1303 UINT32 Index;
1304 MNP_GROUP_ADDRESS *GroupAddress;
1305
1306 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1307
1308 Snp = MnpDeviceData->Snp;
1309
1310 //
1311 // Initialize the enable filter and disable filter.
1312 //
1313 EnableFilterBits = 0;
1314 DisableFilterBits = Snp->Mode->ReceiveFilterMask;
1315
1316 if (MnpDeviceData->UnicastCount != 0) {
1317 //
1318 // Enable unicast if any instance wants to receive unicast.
1319 //
1320 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1321 }
1322
1323 if (MnpDeviceData->BroadcastCount != 0) {
1324 //
1325 // Enable broadcast if any instance wants to receive broadcast.
1326 //
1327 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
1328 }
1329
1330 MCastFilter = NULL;
1331 MCastFilterCnt = 0;
1332 ResetMCastFilters = TRUE;
1333
1334 if ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->GroupAddressCount != 0)) {
1335 //
1336 // There are instances configured to receive multicast and already some group
1337 // addresses are joined.
1338 //
1339
1340 ResetMCastFilters = FALSE;
1341
1342 if (MnpDeviceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {
1343 //
1344 // The joind group address is less than simple network's maximum count.
1345 // Just configure the snp to do the multicast filtering.
1346 //
1347
1348 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
1349
1350 //
1351 // Allocate pool for the mulicast addresses.
1352 //
1353 MCastFilterCnt = MnpDeviceData->GroupAddressCount;
1354 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);
1355 if (MCastFilter == NULL) {
1356 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1357
1358 return EFI_OUT_OF_RESOURCES;
1359 }
1360
1361 //
1362 // Fill the multicast HW address buffer.
1363 //
1364 Index = 0;
1365 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
1366
1367 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1368 CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));
1369 Index++;
1370
1371 ASSERT (Index <= MCastFilterCnt);
1372 }
1373 } else {
1374 //
1375 // The maximum multicast is reached, set the filter to be promiscuous
1376 // multicast.
1377 //
1378
1379 if ((Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
1380 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1381 } else {
1382 //
1383 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1384 // set the NIC to be promiscuous although this will tremendously degrade
1385 // the performance.
1386 //
1387 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1388 }
1389 }
1390 }
1391
1392 if (MnpDeviceData->PromiscuousCount != 0) {
1393 //
1394 // Enable promiscuous if any instance wants to receive promiscuous.
1395 //
1396 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1397 }
1398
1399 //
1400 // Set the disable filter.
1401 //
1402 DisableFilterBits ^= EnableFilterBits;
1403
1404 //
1405 // Configure the receive filters of SNP.
1406 //
1407 Status = Snp->ReceiveFilters (
1408 Snp,
1409 EnableFilterBits,
1410 DisableFilterBits,
1411 ResetMCastFilters,
1412 MCastFilterCnt,
1413 MCastFilter
1414 );
1415 DEBUG_CODE (
1416 if (EFI_ERROR (Status)) {
1417 DEBUG (
1418 (EFI_D_ERROR,
1419 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1420 Status)
1421 );
1422 }
1423 );
1424
1425 if (MCastFilter != NULL) {
1426 //
1427 // Free the buffer used to hold the group addresses.
1428 //
1429 FreePool (MCastFilter);
1430 }
1431
1432 return Status;
1433 }
1434
1435
1436 /**
1437 Add a group address control block which controls the MacAddress for
1438 this instance.
1439
1440 @param[in, out] Instance Pointer to the mnp instance context data.
1441 @param[in, out] CtrlBlk Pointer to the group address control block.
1442 @param[in, out] GroupAddress Pointer to the group adress.
1443 @param[in] MacAddress Pointer to the mac address.
1444 @param[in] HwAddressSize The hardware address size.
1445
1446 @retval EFI_SUCCESS The group address control block is added.
1447 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1448
1449 **/
1450 EFI_STATUS
1451 MnpGroupOpAddCtrlBlk (
1452 IN OUT MNP_INSTANCE_DATA *Instance,
1453 IN OUT MNP_GROUP_CONTROL_BLOCK *CtrlBlk,
1454 IN OUT MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
1455 IN EFI_MAC_ADDRESS *MacAddress,
1456 IN UINT32 HwAddressSize
1457 )
1458 {
1459 MNP_DEVICE_DATA *MnpDeviceData;
1460
1461 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1462
1463 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1464 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1465
1466 if (GroupAddress == NULL) {
1467 ASSERT (MacAddress != NULL);
1468
1469 //
1470 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1471 //
1472 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));
1473 if (GroupAddress == NULL) {
1474
1475 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1476
1477 return EFI_OUT_OF_RESOURCES;
1478 }
1479
1480 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));
1481 GroupAddress->RefCnt = 0;
1482 InsertTailList (
1483 &MnpDeviceData->GroupAddressList,
1484 &GroupAddress->AddrEntry
1485 );
1486 MnpDeviceData->GroupAddressCount++;
1487 }
1488
1489 //
1490 // Increase the RefCnt.
1491 //
1492 GroupAddress->RefCnt++;
1493
1494 //
1495 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1496 //
1497 CtrlBlk->GroupAddress = GroupAddress;
1498 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);
1499
1500 return EFI_SUCCESS;
1501 }
1502
1503
1504 /**
1505 Delete a group control block from the instance. If the controlled group address's
1506 reference count reaches zero, the group address is removed too.
1507
1508 @param[in] Instance Pointer to the instance context data.
1509 @param[in] CtrlBlk Pointer to the group control block to delete.
1510
1511 @return The group address controlled by the control block is no longer used or not.
1512
1513 **/
1514 BOOLEAN
1515 MnpGroupOpDelCtrlBlk (
1516 IN MNP_INSTANCE_DATA *Instance,
1517 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk
1518 )
1519 {
1520 MNP_DEVICE_DATA *MnpDeviceData;
1521 MNP_GROUP_ADDRESS *GroupAddress;
1522
1523 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1524
1525 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1526 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1527
1528 //
1529 // Remove and free the CtrlBlk.
1530 //
1531 GroupAddress = CtrlBlk->GroupAddress;
1532 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);
1533 FreePool (CtrlBlk);
1534
1535 ASSERT (GroupAddress->RefCnt > 0);
1536
1537 //
1538 // Count down the RefCnt.
1539 //
1540 GroupAddress->RefCnt--;
1541
1542 if (GroupAddress->RefCnt == 0) {
1543 //
1544 // Free this GroupAddress entry if no instance uses it.
1545 //
1546 MnpDeviceData->GroupAddressCount--;
1547 RemoveEntryList (&GroupAddress->AddrEntry);
1548 FreePool (GroupAddress);
1549
1550 return TRUE;
1551 }
1552
1553 return FALSE;
1554 }
1555
1556
1557 /**
1558 Do the group operations for this instance.
1559
1560 @param[in, out] Instance Pointer to the instance context data.
1561 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to
1562 leave a group/groups.
1563 @param[in] MacAddress Pointer to the group address to join or leave.
1564 @param[in] CtrlBlk Pointer to the group control block if JoinFlag
1565 is FALSE.
1566
1567 @retval EFI_SUCCESS The group operation finished.
1568 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1569 @retval Others Other errors as indicated.
1570
1571 **/
1572 EFI_STATUS
1573 MnpGroupOp (
1574 IN OUT MNP_INSTANCE_DATA *Instance,
1575 IN BOOLEAN JoinFlag,
1576 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,
1577 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL
1578 )
1579 {
1580 MNP_DEVICE_DATA *MnpDeviceData;
1581 LIST_ENTRY *Entry;
1582 LIST_ENTRY *NextEntry;
1583 MNP_GROUP_ADDRESS *GroupAddress;
1584 EFI_SIMPLE_NETWORK_MODE *SnpMode;
1585 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;
1586 EFI_STATUS Status;
1587 BOOLEAN AddressExist;
1588 BOOLEAN NeedUpdate;
1589
1590 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1591
1592 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1593 SnpMode = MnpDeviceData->Snp->Mode;
1594
1595 if (JoinFlag) {
1596 //
1597 // A new gropu address is to be added.
1598 //
1599 GroupAddress = NULL;
1600 AddressExist = FALSE;
1601
1602 //
1603 // Allocate memory for the control block.
1604 //
1605 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));
1606 if (NewCtrlBlk == NULL) {
1607 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));
1608
1609 return EFI_OUT_OF_RESOURCES;
1610 }
1611
1612 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
1613 //
1614 // Check whether the MacAddress is already joined by other instances.
1615 //
1616 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1617 if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {
1618 AddressExist = TRUE;
1619 break;
1620 }
1621 }
1622
1623 if (!AddressExist) {
1624 GroupAddress = NULL;
1625 }
1626
1627 //
1628 // Add the GroupAddress for this instance.
1629 //
1630 Status = MnpGroupOpAddCtrlBlk (
1631 Instance,
1632 NewCtrlBlk,
1633 GroupAddress,
1634 MacAddress,
1635 SnpMode->HwAddressSize
1636 );
1637 if (EFI_ERROR (Status)) {
1638 return Status;
1639 }
1640
1641 NeedUpdate = TRUE;
1642 } else {
1643 if (MacAddress != NULL) {
1644 ASSERT (CtrlBlk != NULL);
1645
1646 //
1647 // Leave the specific multicast mac address.
1648 //
1649 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);
1650 } else {
1651 //
1652 // Leave all multicast mac addresses.
1653 //
1654 NeedUpdate = FALSE;
1655
1656 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {
1657
1658 NewCtrlBlk = NET_LIST_USER_STRUCT (
1659 Entry,
1660 MNP_GROUP_CONTROL_BLOCK,
1661 CtrlBlkEntry
1662 );
1663 //
1664 // Update is required if the group address left is no longer used
1665 // by other instances.
1666 //
1667 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);
1668 }
1669 }
1670 }
1671
1672 Status = EFI_SUCCESS;
1673
1674 if (NeedUpdate) {
1675 //
1676 // Reconfigure the receive filters if necessary.
1677 //
1678 Status = MnpConfigReceiveFilters (MnpDeviceData);
1679 }
1680
1681 return Status;
1682 }