]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
Import SnpDxe, Tcp4Dxe, Udp4Dxe and MnpDxe.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
1 /** @file
2
3 Copyright (c) 2005 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 MnpConfig.c
15
16 Abstract:
17
18 Implementation of Managed Network Protocol private services.
19
20
21 **/
22
23
24 #include "MnpImpl.h"
25
26 EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol = {
27 MnpServiceBindingCreateChild,
28 MnpServiceBindingDestroyChild
29 };
30
31 EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate = {
32 MnpGetModeData,
33 MnpConfigure,
34 MnpMcastIpToMac,
35 MnpGroups,
36 MnpTransmit,
37 MnpReceive,
38 MnpCancel,
39 MnpPoll
40 };
41
42 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {
43 10000,
44 10000,
45 0,
46 FALSE,
47 FALSE,
48 FALSE,
49 FALSE,
50 FALSE,
51 FALSE,
52 FALSE
53 };
54
55 STATIC
56 EFI_STATUS
57 MnpAddFreeNbuf (
58 IN MNP_SERVICE_DATA *MnpServiceData,
59 IN UINTN Count
60 );
61
62 STATIC
63 EFI_STATUS
64 MnpStartSnp (
65 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
66 );
67
68 STATIC
69 EFI_STATUS
70 MnpStopSnp (
71 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
72 );
73
74 STATIC
75 EFI_STATUS
76 MnpStart (
77 IN MNP_SERVICE_DATA *MnpServiceData,
78 IN BOOLEAN IsConfigUpdate,
79 IN BOOLEAN EnableSystemPoll
80 );
81
82 STATIC
83 EFI_STATUS
84 MnpStop (
85 IN MNP_SERVICE_DATA *MnpServiceData
86 );
87
88 STATIC
89 EFI_STATUS
90 MnpConfigReceiveFilters (
91 IN MNP_SERVICE_DATA *MnpServiceData
92 );
93
94 STATIC
95 EFI_STATUS
96 MnpGroupOpAddCtrlBlk (
97 IN MNP_INSTANCE_DATA *Instance,
98 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk,
99 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
100 IN EFI_MAC_ADDRESS *MacAddress,
101 IN UINT32 HwAddressSize
102 );
103
104 STATIC
105 BOOLEAN
106 MnpGroupOpDelCtrlBlk (
107 IN MNP_INSTANCE_DATA *Instance,
108 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk
109 );
110
111
112 /**
113 Add some NET_BUF into MnpServiceData->FreeNbufQue. The buffer length of
114 the NET_BUF is specified by MnpServiceData->BufferLength.
115
116 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
117 @param Count Number of NET_BUFFERs to add.
118
119 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated and
120 added into MnpServiceData->FreeNbufQue.
121 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.
122
123 **/
124 STATIC
125 EFI_STATUS
126 MnpAddFreeNbuf (
127 IN MNP_SERVICE_DATA *MnpServiceData,
128 IN UINTN Count
129 )
130 {
131 EFI_STATUS Status;
132 UINTN Index;
133 NET_BUF *Nbuf;
134
135 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
136 ASSERT ((Count > 0) && (MnpServiceData->BufferLength > 0));
137
138 Status = EFI_SUCCESS;
139
140 for (Index = 0; Index < Count; Index++) {
141
142 Nbuf = NetbufAlloc (MnpServiceData->BufferLength);
143 if (Nbuf == NULL) {
144
145 MNP_DEBUG_ERROR (("MnpAddFreeNbuf: NetBufAlloc failed.\n"));
146 Status = EFI_OUT_OF_RESOURCES;
147 break;
148 }
149
150 NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);
151 }
152
153 MnpServiceData->NbufCnt += Index;
154
155 return Status;
156 }
157
158
159 /**
160 Allocate a free NET_BUF from MnpServiceData->FreeNbufQue. If there is none
161 in the queue, first try to allocate some and add them into the queue, then
162 fetch the NET_BUF from the updated FreeNbufQue.
163
164 @param MnpServiceData Pointer to the MNP_SERVICE_DATA.
165
166 @return Pointer to the allocated free NET_BUF structure, if NULL the operation is failed.
167
168 **/
169 NET_BUF *
170 MnpAllocNbuf (
171 IN MNP_SERVICE_DATA *MnpServiceData
172 )
173 {
174 EFI_STATUS Status;
175 NET_BUF_QUEUE *FreeNbufQue;
176 NET_BUF *Nbuf;
177 EFI_TPL OldTpl;
178
179 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
180
181 FreeNbufQue = &MnpServiceData->FreeNbufQue;
182
183 OldTpl = NET_RAISE_TPL (NET_TPL_RECYCLE);
184
185 //
186 // Check whether there are available buffers, or else try to add some.
187 //
188 if (FreeNbufQue->BufNum == 0) {
189
190 if ((MnpServiceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {
191
192 MNP_DEBUG_ERROR (
193 ("MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
194 MnpServiceData)
195 );
196
197 Nbuf = NULL;
198 goto ON_EXIT;
199 }
200
201 Status = MnpAddFreeNbuf (MnpServiceData, MNP_NET_BUFFER_INCREASEMENT);
202 if (EFI_ERROR (Status)) {
203
204 MNP_DEBUG_ERROR (
205 ("MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
206 Status)
207 );
208 //
209 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
210 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
211 //
212 }
213 }
214
215 Nbuf = NetbufQueRemove (FreeNbufQue);
216
217 //
218 // Increase the RefCnt.
219 //
220 if (Nbuf != NULL) {
221 NET_GET_REF (Nbuf);
222 }
223
224 ON_EXIT:
225 NET_RESTORE_TPL (OldTpl);
226
227 return Nbuf;
228 }
229
230
231 /**
232 Try to reclaim the Nbuf into the buffer pool.
233
234 @param MnpServiceData Pointer to the mnp service context data.
235 @param Nbuf Pointer to the NET_BUF to free.
236
237 @return None.
238
239 **/
240 VOID
241 MnpFreeNbuf (
242 IN MNP_SERVICE_DATA *MnpServiceData,
243 IN NET_BUF *Nbuf
244 )
245 {
246 EFI_TPL OldTpl;
247
248 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
249 ASSERT (Nbuf->RefCnt > 1);
250
251 OldTpl = NET_RAISE_TPL (NET_TPL_RECYCLE);
252
253 NET_PUT_REF (Nbuf);
254
255 if (Nbuf->RefCnt == 1) {
256 //
257 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
258 //
259 NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_TAIL);
260 NetbufQueAppend (&MnpServiceData->FreeNbufQue, Nbuf);
261 }
262
263 NET_RESTORE_TPL (OldTpl);
264 }
265
266
267 /**
268 Initialize the mnp service context data.
269
270 @param MnpServiceData Pointer to the mnp service context data.
271 @param Snp Pointer to the simple network protocol.
272
273 @retval EFI_SUCCESS The mnp service context is initialized.
274 @retval Other Some error occurs.
275
276 **/
277 EFI_STATUS
278 MnpInitializeServiceData (
279 IN MNP_SERVICE_DATA *MnpServiceData,
280 IN EFI_HANDLE ImageHandle,
281 IN EFI_HANDLE ControllerHandle
282 )
283 {
284 EFI_STATUS Status;
285 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
286 EFI_SIMPLE_NETWORK_MODE *SnpMode;
287
288 MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;
289
290 MnpServiceData->ControllerHandle = ControllerHandle;
291
292 //
293 // Copy the ServiceBinding structure.
294 //
295 MnpServiceData->ServiceBinding = mMnpServiceBindingProtocol;
296
297 //
298 // Open the Simple Network protocol.
299 //
300 Status = gBS->OpenProtocol (
301 ControllerHandle,
302 &gEfiSimpleNetworkProtocolGuid,
303 (VOID **) &Snp,
304 ImageHandle,
305 ControllerHandle,
306 EFI_OPEN_PROTOCOL_BY_DRIVER
307 );
308 if (EFI_ERROR (Status)) {
309 return EFI_UNSUPPORTED;
310 }
311
312 //
313 // Get MTU from Snp.
314 //
315 SnpMode = Snp->Mode;
316 MnpServiceData->Snp = Snp;
317 MnpServiceData->Mtu = SnpMode->MaxPacketSize;
318
319 //
320 // Initialize the lists.
321 //
322 NetListInit (&MnpServiceData->GroupAddressList);
323 NetListInit (&MnpServiceData->ChildrenList);
324
325 //
326 // Get the buffer length used to allocate NET_BUF to hold data received
327 // from SNP. Do this before fill the FreeNetBufQue.
328 //
329 MnpServiceData->BufferLength = MnpServiceData->Mtu + SnpMode->MediaHeaderSize + NET_ETHER_FCS_SIZE;
330
331 //
332 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
333 //
334 NetbufQueInit (&MnpServiceData->FreeNbufQue);
335 Status = MnpAddFreeNbuf (MnpServiceData, MNP_INIT_NET_BUFFER_NUM);
336 if (EFI_ERROR (Status)) {
337
338 MNP_DEBUG_ERROR (("MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status));
339 goto ERROR;
340 }
341 //
342 // Get one NET_BUF from the FreeNbufQue for rx cache.
343 //
344 MnpServiceData->RxNbufCache = MnpAllocNbuf (MnpServiceData);
345 NetbufAllocSpace (
346 MnpServiceData->RxNbufCache,
347 MnpServiceData->BufferLength,
348 NET_BUF_TAIL
349 );
350
351 //
352 // Allocate buffer pool for tx.
353 //
354 MnpServiceData->TxBuf = NetAllocatePool (MnpServiceData->Mtu + SnpMode->MediaHeaderSize);
355 if (MnpServiceData->TxBuf == NULL) {
356
357 MNP_DEBUG_ERROR (("MnpInitializeServiceData: NetAllocatePool failed.\n"));
358 Status = EFI_OUT_OF_RESOURCES;
359
360 goto ERROR;
361 }
362
363 //
364 // Create the system poll timer.
365 //
366 Status = gBS->CreateEvent (
367 EVT_NOTIFY_SIGNAL | EVT_TIMER,
368 NET_TPL_LOCK,
369 MnpSystemPoll,
370 MnpServiceData,
371 &MnpServiceData->PollTimer
372 );
373 if (EFI_ERROR (Status)) {
374
375 MNP_DEBUG_ERROR (("MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));
376 goto ERROR;
377 }
378
379 //
380 // Create the timer for packet timeout check.
381 //
382 Status = gBS->CreateEvent (
383 EVT_NOTIFY_SIGNAL | EVT_TIMER,
384 NET_TPL_EVENT,
385 MnpCheckPacketTimeout,
386 MnpServiceData,
387 &MnpServiceData->TimeoutCheckTimer
388 );
389 if (EFI_ERROR (Status)) {
390
391 MNP_DEBUG_ERROR (("MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));
392 goto ERROR;
393 }
394
395 //
396 // Create the timer for tx timeout check.
397 //
398 Status = gBS->CreateEvent (
399 EVT_TIMER,
400 NET_TPL_SLOW_TIMER,
401 NULL,
402 NULL,
403 &MnpServiceData->TxTimeoutEvent
404 );
405 if (EFI_ERROR (Status)) {
406
407 MNP_DEBUG_ERROR (("MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));
408 }
409
410 ERROR:
411
412 if (EFI_ERROR (Status)) {
413 //
414 // Free the dynamic allocated resources if necessary.
415 //
416 if (MnpServiceData->TimeoutCheckTimer != NULL) {
417
418 gBS->CloseEvent (MnpServiceData->TimeoutCheckTimer);
419 }
420
421 if (MnpServiceData->PollTimer != NULL) {
422
423 gBS->CloseEvent (MnpServiceData->PollTimer);
424 }
425
426 if (MnpServiceData->TxBuf != NULL) {
427
428 NetFreePool (MnpServiceData->TxBuf);
429 }
430
431 if (MnpServiceData->RxNbufCache != NULL) {
432
433 MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);
434 }
435
436 if (MnpServiceData->FreeNbufQue.BufNum != 0) {
437
438 NetbufQueFlush (&MnpServiceData->FreeNbufQue);
439 }
440 }
441
442 return Status;
443 }
444
445
446 /**
447 Flush the mnp service context data.
448
449 @param MnpServiceData Pointer to the mnp service context data.
450
451 @return None.
452
453 **/
454 VOID
455 MnpFlushServiceData (
456 MNP_SERVICE_DATA *MnpServiceData
457 )
458 {
459 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
460
461 //
462 // The GroupAddressList must be empty.
463 //
464 ASSERT (NetListIsEmpty (&MnpServiceData->GroupAddressList));
465
466 //
467 // Close the event.
468 //
469 gBS->CloseEvent (&MnpServiceData->TxTimeoutEvent);
470 gBS->CloseEvent (&MnpServiceData->TimeoutCheckTimer);
471 gBS->CloseEvent (&MnpServiceData->PollTimer);
472
473 //
474 // Free the tx buffer.
475 //
476 NetFreePool (MnpServiceData->TxBuf);
477
478 //
479 // Free the RxNbufCache.
480 //
481 MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);
482
483 //
484 // Flush the FreeNbufQue.
485 //
486 MnpServiceData->NbufCnt -= MnpServiceData->FreeNbufQue.BufNum;
487 NetbufQueFlush (&MnpServiceData->FreeNbufQue);
488
489 DEBUG_CODE (
490
491 if (MnpServiceData->NbufCnt != 0) {
492
493 MNP_DEBUG_WARN (("MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));
494 }
495 );
496 }
497
498
499 /**
500 Initialize the mnp instance context data.
501
502 @param MnpServiceData Pointer to the mnp service context data.
503 @param Instance Pointer to the mnp instance context data to
504 initialize.
505
506 @return None.
507
508 **/
509 VOID
510 MnpInitializeInstanceData (
511 IN MNP_SERVICE_DATA *MnpServiceData,
512 IN MNP_INSTANCE_DATA *Instance
513 )
514 {
515 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
516 ASSERT (Instance != NULL);
517
518 //
519 // Set the signature.
520 //
521 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;
522
523 //
524 // Copy the MNP Protocol interfaces from the template.
525 //
526 Instance->ManagedNetwork = mMnpProtocolTemplate;
527
528 //
529 // Copy the default config data.
530 //
531 Instance->ConfigData = mMnpDefaultConfigData;
532
533 //
534 // Initialize the lists.
535 //
536 NetListInit (&Instance->GroupCtrlBlkList);
537 NetListInit (&Instance->RcvdPacketQueue);
538 NetListInit (&Instance->RxDeliveredPacketQueue);
539
540 //
541 // Initialize the RxToken Map.
542 //
543 NetMapInit (&Instance->RxTokenMap);
544
545 //
546 // Save the MnpServiceData info.
547 //
548 Instance->MnpServiceData = MnpServiceData;
549 }
550
551
552 /**
553 Check whether the token specified by Arg maches the token in Item.
554
555 @param Map Pointer to the NET_MAP.
556 @param Item Pointer to the NET_MAP_ITEM
557 @param Arg Pointer to the Arg, it's a pointer to the token to
558 check.
559
560 @retval EFI_SUCCESS The token specified by Arg is different from the
561 token in Item.
562 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
563 Item.
564
565 **/
566 EFI_STATUS
567 MnpTokenExist (
568 IN NET_MAP *Map,
569 IN NET_MAP_ITEM *Item,
570 IN VOID *Arg
571 )
572 {
573 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;
574 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;
575
576 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;
577 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
578
579 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
580 //
581 // The token is the same either the two tokens equals or the Events in
582 // the two tokens are the same.
583 //
584 return EFI_ACCESS_DENIED;
585 }
586
587 return EFI_SUCCESS;
588 }
589
590
591 /**
592 Cancel the token specified by Arg if it matches the token in Item.
593
594 @param Map Pointer to the NET_MAP.
595 @param Item Pointer to the NET_MAP_ITEM
596 @param Arg Pointer to the Arg, it's a pointer to the token to
597 cancel.
598
599 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is
600 cancelled, or the Arg isn't NULL, and the token in
601 Item is different from the Arg.
602 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
603 Arg, and the token is cancelled.
604
605 **/
606 EFI_STATUS
607 MnpCancelTokens (
608 IN NET_MAP *Map,
609 IN NET_MAP_ITEM *Item,
610 IN VOID *Arg
611 )
612 {
613 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;
614
615 if ((Arg != NULL) && (Item->Key != Arg)) {
616 //
617 // The token in Item is not the token specified by Arg.
618 //
619 return EFI_SUCCESS;
620 }
621
622 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
623
624 //
625 // Cancel this token with status set to EFI_ABORTED.
626 //
627 TokenToCancel->Status = EFI_ABORTED;
628 gBS->SignalEvent (TokenToCancel->Event);
629
630 //
631 // Remove the item from the map.
632 //
633 NetMapRemoveItem (Map, Item, NULL);
634
635 if (Arg != NULL) {
636 //
637 // Only abort the token specified by Arg if Arg isn't NULL.
638 //
639 return EFI_ABORTED;
640 }
641
642 return EFI_SUCCESS;
643 }
644
645
646 /**
647 Start and initialize the simple network.
648
649 @param Snp Pointer to the simple network protocol.
650
651 @retval EFI_SUCCESS The simple network protocol is started.
652 @retval Other Some error occurs.
653
654 **/
655 STATIC
656 EFI_STATUS
657 MnpStartSnp (
658 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
659 )
660 {
661 EFI_STATUS Status;
662
663 ASSERT (Snp != NULL);
664
665 //
666 // Start the simple network.
667 //
668 Status = Snp->Start (Snp);
669
670 if (!EFI_ERROR (Status)) {
671 //
672 // Initialize the simple network.
673 //
674 Status = Snp->Initialize (Snp, 0, 0);
675 }
676
677 return Status;
678 }
679
680
681 /**
682 Stop the simple network.
683
684 @param Snp Pointer to the simple network protocol.
685
686 @retval EFI_SUCCESS The simple network is stopped.
687 @retval Other Some error occurs.
688
689 **/
690 STATIC
691 EFI_STATUS
692 MnpStopSnp (
693 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
694 )
695 {
696 EFI_STATUS Status;
697
698 ASSERT (Snp != NULL);
699
700 //
701 // Shut down the simple network.
702 //
703 Status = Snp->Shutdown (Snp);
704
705 if (!EFI_ERROR (Status)) {
706 //
707 // Stop the simple network.
708 //
709 Status = Snp->Stop (Snp);
710 }
711
712 return Status;
713 }
714
715
716 /**
717 Start the managed network, this function is called when one instance is configured
718 or reconfigured.
719
720 @param MnpServiceData Pointer to the mnp service context data.
721 @param IsConfigUpdate The instance is reconfigured or it's the first time
722 the instanced is configured.
723 @param EnableSystemPoll Enable the system polling or not.
724
725 @retval EFI_SUCCESS The managed network is started and some
726 configuration is updated.
727 @retval Other Some error occurs.
728
729 **/
730 STATIC
731 EFI_STATUS
732 MnpStart (
733 IN MNP_SERVICE_DATA *MnpServiceData,
734 IN BOOLEAN IsConfigUpdate,
735 IN BOOLEAN EnableSystemPoll
736 )
737 {
738 EFI_STATUS Status;
739 EFI_TIMER_DELAY TimerOpType;
740
741 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
742
743 Status = EFI_SUCCESS;
744
745 if (!IsConfigUpdate) {
746 //
747 // If it's not a configuration update, increase the configured children number.
748 //
749 MnpServiceData->ConfiguredChildrenNumber++;
750
751 if (MnpServiceData->ConfiguredChildrenNumber == 1) {
752 //
753 // It's the first configured child, start the simple network.
754 //
755 Status = MnpStartSnp (MnpServiceData->Snp);
756 if (EFI_ERROR (Status)) {
757
758 MNP_DEBUG_ERROR (("MnpStart: MnpStartSnp failed, %r.\n", Status));
759 goto ErrorExit;
760 }
761
762 //
763 // Start the timeout timer.
764 //
765 Status = gBS->SetTimer (
766 MnpServiceData->TimeoutCheckTimer,
767 TimerPeriodic,
768 MNP_TIMEOUT_CHECK_INTERVAL
769 );
770 if (EFI_ERROR (Status)) {
771
772 MNP_DEBUG_ERROR (
773 ("MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
774 Status)
775 );
776 goto ErrorExit;
777 }
778 }
779 }
780
781 if (MnpServiceData->EnableSystemPoll ^ EnableSystemPoll) {
782 //
783 // The EnableSystemPoll differs with the current state, disable or enable
784 // the system poll.
785 //
786 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;
787
788 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);
789 if (EFI_ERROR (Status)) {
790
791 MNP_DEBUG_ERROR (("MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));
792 goto ErrorExit;
793 }
794
795 MnpServiceData->EnableSystemPoll = EnableSystemPoll;
796 }
797
798 //
799 // Change the receive filters if need.
800 //
801 Status = MnpConfigReceiveFilters (MnpServiceData);
802
803 ErrorExit:
804
805 return Status;
806 }
807
808
809 /**
810 Stop the managed network.
811
812 @param MnpServiceData Pointer to the mnp service context data.
813
814 @retval EFI_SUCCESS The managed network is stopped.
815 @retval Other Some error occurs.
816
817 **/
818 STATIC
819 EFI_STATUS
820 MnpStop (
821 IN MNP_SERVICE_DATA *MnpServiceData
822 )
823 {
824 EFI_STATUS Status;
825
826 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
827 ASSERT (MnpServiceData->ConfiguredChildrenNumber > 0);
828
829 //
830 // Configure the receive filters.
831 //
832 MnpConfigReceiveFilters (MnpServiceData);
833
834 //
835 // Decrease the children number.
836 //
837 MnpServiceData->ConfiguredChildrenNumber--;
838
839 if (MnpServiceData->ConfiguredChildrenNumber > 0) {
840 //
841 // If there are other configured chilren, return and keep the timers and
842 // simple network unchanged.
843 //
844 return EFI_SUCCESS;
845 }
846
847 //
848 // No configured children now.
849 //
850
851 if (MnpServiceData->EnableSystemPoll) {
852 //
853 // The system poll in on, cancel the poll timer.
854 //
855 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerCancel, 0);
856 MnpServiceData->EnableSystemPoll = FALSE;
857 }
858
859 //
860 // Cancel the timeout timer.
861 //
862 Status = gBS->SetTimer (MnpServiceData->TimeoutCheckTimer, TimerCancel, 0);
863
864 //
865 // Stop the simple network.
866 //
867 Status = MnpStopSnp (MnpServiceData->Snp);
868
869 return Status;
870 }
871
872
873 /**
874 Flush the instance's received data.
875
876 @param Instance Pointer to the mnp instance context data.
877
878 @return None.
879
880 **/
881 VOID
882 MnpFlushRcvdDataQueue (
883 IN MNP_INSTANCE_DATA *Instance
884 )
885 {
886 EFI_TPL OldTpl;
887 MNP_RXDATA_WRAP *RxDataWrap;
888
889 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
890
891 OldTpl = NET_RAISE_TPL (NET_TPL_RECYCLE);
892
893 while (!NetListIsEmpty (&Instance->RcvdPacketQueue)) {
894 //
895 // Remove all the Wraps.
896 //
897 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
898
899 //
900 // Recycle the RxDataWrap.
901 //
902 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);
903 Instance->RcvdPacketQueueSize--;
904 }
905
906 ASSERT (Instance->RcvdPacketQueueSize == 0);
907
908 NET_RESTORE_TPL (OldTpl);
909 }
910
911
912 /**
913 Configure the Instance using ConfigData.
914
915 @param Instance Pointer to the mnp instance context data.
916 @param ConfigData Pointer to the configuration data used to configure
917 the isntance.
918
919 @retval EFI_SUCCESS The Instance is configured.
920 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
921 implementation doesn't support it.
922 @retval Other Some error occurs.
923
924 **/
925 EFI_STATUS
926 MnpConfigureInstance (
927 IN MNP_INSTANCE_DATA *Instance,
928 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL
929 )
930 {
931 EFI_STATUS Status;
932 MNP_SERVICE_DATA *MnpServiceData;
933 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;
934 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;
935 BOOLEAN IsConfigUpdate;
936
937 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
938
939 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {
940 //
941 // Don't support timestamp.
942 //
943 return EFI_UNSUPPORTED;
944 }
945
946 Status = EFI_SUCCESS;
947
948 MnpServiceData = Instance->MnpServiceData;
949 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
950
951 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));
952
953 OldConfigData = &Instance->ConfigData;
954 NewConfigData = ConfigData;
955 if (NewConfigData == NULL) {
956 //
957 // Restore back the default config data if a reset of this instance
958 // is required.
959 //
960 NewConfigData = &mMnpDefaultConfigData;
961 }
962
963 //
964 // Reset the instance's receive filter.
965 //
966 Instance->ReceiveFilter = 0;
967
968 //
969 // Clear the receive counters according to the old ConfigData.
970 //
971 if (OldConfigData->EnableUnicastReceive) {
972 MnpServiceData->UnicastCount--;
973 }
974
975 if (OldConfigData->EnableMulticastReceive) {
976 MnpServiceData->MulticastCount--;
977 }
978
979 if (OldConfigData->EnableBroadcastReceive) {
980 MnpServiceData->BroadcastCount--;
981 }
982
983 if (OldConfigData->EnablePromiscuousReceive) {
984 MnpServiceData->PromiscuousCount--;
985 }
986
987 //
988 // Set the receive filter counters and the receive filter of the
989 // instance according to the new ConfigData.
990 //
991 if (NewConfigData->EnableUnicastReceive) {
992 MnpServiceData->UnicastCount++;
993 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;
994 }
995
996 if (NewConfigData->EnableMulticastReceive) {
997 MnpServiceData->MulticastCount++;
998 }
999
1000 if (NewConfigData->EnableBroadcastReceive) {
1001 MnpServiceData->BroadcastCount++;
1002 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;
1003 }
1004
1005 if (NewConfigData->EnablePromiscuousReceive) {
1006 MnpServiceData->PromiscuousCount++;
1007 }
1008
1009 if (OldConfigData->FlushQueuesOnReset) {
1010
1011 MnpFlushRcvdDataQueue (Instance);
1012 }
1013
1014 if (ConfigData == NULL) {
1015
1016 NetMapIterate (&Instance->RxTokenMap, MnpCancelTokens, NULL);
1017 }
1018
1019 if (!NewConfigData->EnableMulticastReceive) {
1020
1021 MnpGroupOp (Instance, FALSE, NULL, NULL);
1022 }
1023
1024 //
1025 // Save the new configuration data.
1026 //
1027 *OldConfigData = *NewConfigData;
1028
1029 Instance->Configured = (BOOLEAN) (ConfigData != NULL);
1030
1031 if (Instance->Configured) {
1032 //
1033 // The instance is configured, start the Mnp.
1034 //
1035 Status = MnpStart (
1036 MnpServiceData,
1037 IsConfigUpdate,
1038 !NewConfigData->DisableBackgroundPolling
1039 );
1040 } else {
1041 //
1042 // The instance is changed to the unconfigured state, stop the Mnp.
1043 //
1044 Status = MnpStop (MnpServiceData);
1045 }
1046
1047 return Status;
1048 }
1049
1050
1051 /**
1052 Configure the Snp receive filters according to the instances' receive filter
1053 settings.
1054
1055 @param MnpServiceData Pointer to the mnp service context data.
1056
1057 @retval EFI_SUCCESS The receive filters is configured.
1058 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due to lack
1059 of memory resource.
1060
1061 **/
1062 STATIC
1063 EFI_STATUS
1064 MnpConfigReceiveFilters (
1065 IN MNP_SERVICE_DATA *MnpServiceData
1066 )
1067 {
1068 EFI_STATUS Status;
1069 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
1070 EFI_MAC_ADDRESS *MCastFilter;
1071 UINT32 MCastFilterCnt;
1072 UINT32 EnableFilterBits;
1073 UINT32 DisableFilterBits;
1074 BOOLEAN ResetMCastFilters;
1075 NET_LIST_ENTRY *Entry;
1076 UINT32 Index;
1077 MNP_GROUP_ADDRESS *GroupAddress;
1078
1079 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1080
1081 Snp = MnpServiceData->Snp;
1082
1083 //
1084 // Initialize the enable filter and disable filter.
1085 //
1086 EnableFilterBits = 0;
1087 DisableFilterBits = Snp->Mode->ReceiveFilterMask;
1088
1089 if (MnpServiceData->UnicastCount != 0) {
1090 //
1091 // Enable unicast if any instance wants to receive unicast.
1092 //
1093 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1094 }
1095
1096 if (MnpServiceData->BroadcastCount != 0) {
1097 //
1098 // Enable broadcast if any instance wants to receive broadcast.
1099 //
1100 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
1101 }
1102
1103 MCastFilter = NULL;
1104 MCastFilterCnt = 0;
1105 ResetMCastFilters = TRUE;
1106
1107 if ((MnpServiceData->MulticastCount != 0) && (MnpServiceData->GroupAddressCount != 0)) {
1108 //
1109 // There are instances configured to receive multicast and already some group
1110 // addresses are joined.
1111 //
1112
1113 ResetMCastFilters = FALSE;
1114
1115 if (MnpServiceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {
1116 //
1117 // The joind group address is less than simple network's maximum count.
1118 // Just configure the snp to do the multicast filtering.
1119 //
1120
1121 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
1122
1123 //
1124 // Allocate pool for the mulicast addresses.
1125 //
1126 MCastFilterCnt = MnpServiceData->GroupAddressCount;
1127 MCastFilter = NetAllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);
1128 if (MCastFilter == NULL) {
1129
1130 MNP_DEBUG_ERROR (("MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1131 return EFI_OUT_OF_RESOURCES;
1132 }
1133
1134 //
1135 // Fill the multicast HW address buffer.
1136 //
1137 Index = 0;
1138 NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {
1139
1140 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1141 *(MCastFilter + Index) = GroupAddress->Address;
1142 Index++;
1143
1144 ASSERT (Index <= MCastFilterCnt);
1145 }
1146 } else {
1147 //
1148 // The maximum multicast is reached, set the filter to be promiscuous
1149 // multicast.
1150 //
1151
1152 if (Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {
1153 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1154 } else {
1155 //
1156 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1157 // set the NIC to be promiscuous although this will tremendously degrade
1158 // the performance.
1159 //
1160 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1161 }
1162 }
1163 }
1164
1165 if (MnpServiceData->PromiscuousCount != 0) {
1166 //
1167 // Enable promiscuous if any instance wants to receive promiscuous.
1168 //
1169 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1170 }
1171
1172 //
1173 // Set the disable filter.
1174 //
1175 DisableFilterBits ^= EnableFilterBits;
1176
1177 //
1178 // Configure the receive filters of SNP.
1179 //
1180 Status = Snp->ReceiveFilters (
1181 Snp,
1182 EnableFilterBits,
1183 DisableFilterBits,
1184 ResetMCastFilters,
1185 MCastFilterCnt,
1186 MCastFilter
1187 );
1188 DEBUG_CODE (
1189 if (EFI_ERROR (Status)) {
1190
1191 MNP_DEBUG_ERROR (
1192 ("MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1193 Status)
1194 );
1195 }
1196 );
1197
1198 if (MCastFilter != NULL) {
1199 //
1200 // Free the buffer used to hold the group addresses.
1201 //
1202 NetFreePool (MCastFilter);
1203 }
1204
1205 return Status;
1206 }
1207
1208
1209 /**
1210 Add a group address control block which controls the MacAddress for
1211 this instance.
1212
1213 @param Instance Pointer to the mnp instance context data.
1214 @param CtrlBlk Pointer to the group address control block.
1215 @param GroupAddress Pointer to the group adress.
1216 @param MacAddress Pointer to the mac address.
1217 @param HwAddressSize The hardware address size.
1218
1219 @retval EFI_SUCCESS The group address control block is added.
1220 @retval EFI_OUT_OF_RESOURCE Failed due to lack of memory resources.
1221
1222 **/
1223 STATIC
1224 EFI_STATUS
1225 MnpGroupOpAddCtrlBlk (
1226 IN MNP_INSTANCE_DATA *Instance,
1227 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk,
1228 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
1229 IN EFI_MAC_ADDRESS *MacAddress,
1230 IN UINT32 HwAddressSize
1231 )
1232 {
1233 MNP_SERVICE_DATA *MnpServiceData;
1234
1235 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1236
1237 MnpServiceData = Instance->MnpServiceData;
1238 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1239
1240 if (GroupAddress == NULL) {
1241
1242 ASSERT (MacAddress != NULL);
1243
1244 //
1245 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1246 //
1247 GroupAddress = NetAllocatePool (sizeof (MNP_GROUP_ADDRESS));
1248 if (GroupAddress == NULL) {
1249
1250 MNP_DEBUG_ERROR (("MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1251
1252 return EFI_OUT_OF_RESOURCES;
1253 }
1254
1255 GroupAddress->Address = *MacAddress;
1256 GroupAddress->RefCnt = 0;
1257 NetListInsertTail (
1258 &MnpServiceData->GroupAddressList,
1259 &GroupAddress->AddrEntry
1260 );
1261 MnpServiceData->GroupAddressCount++;
1262 }
1263
1264 //
1265 // Increase the RefCnt.
1266 //
1267 GroupAddress->RefCnt++;
1268
1269 //
1270 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1271 //
1272 CtrlBlk->GroupAddress = GroupAddress;
1273 NetListInsertTail (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);
1274
1275 return EFI_SUCCESS;
1276 }
1277
1278
1279 /**
1280 Delete a group control block from the instance. If the controlled group address's
1281 reference count reaches zero, the group address is removed too.
1282
1283 @param Instance Pointer to the instance context data.
1284 @param CtrlBlk Pointer to the group control block to delete.
1285
1286 @return The group address controlled by the control block is no longer used or not.
1287
1288 **/
1289 STATIC
1290 BOOLEAN
1291 MnpGroupOpDelCtrlBlk (
1292 IN MNP_INSTANCE_DATA *Instance,
1293 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk
1294 )
1295 {
1296 MNP_SERVICE_DATA *MnpServiceData;
1297 MNP_GROUP_ADDRESS *GroupAddress;
1298
1299 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1300
1301 MnpServiceData = Instance->MnpServiceData;
1302 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1303
1304 //
1305 // Remove and free the CtrlBlk.
1306 //
1307 GroupAddress = CtrlBlk->GroupAddress;
1308 NetListRemoveEntry (&CtrlBlk->CtrlBlkEntry);
1309 NetFreePool (CtrlBlk);
1310
1311 ASSERT (GroupAddress->RefCnt > 0);
1312
1313 //
1314 // Count down the RefCnt.
1315 //
1316 GroupAddress->RefCnt--;
1317
1318 if (GroupAddress->RefCnt == 0) {
1319 //
1320 // Free this GroupAddress entry if no instance uses it.
1321 //
1322 MnpServiceData->GroupAddressCount--;
1323 NetListRemoveEntry (&GroupAddress->AddrEntry);
1324 NetFreePool (GroupAddress);
1325
1326 return TRUE;
1327 }
1328
1329 return FALSE;
1330 }
1331
1332
1333 /**
1334 Do the group operations for this instance.
1335
1336 @param Instance Pointer to the instance context data.
1337 @param JoinFlag Set to TRUE to join a group. Set to TRUE to leave a
1338 group/groups.
1339 @param MacAddress Pointer to the group address to join or leave.
1340 @param CtrlBlk Pointer to the group control block if JoinFlag if
1341 FALSE.
1342
1343 @retval EFI_SUCCESS The group operation finished.
1344 @retval Other Some error occurs.
1345
1346 **/
1347 EFI_STATUS
1348 MnpGroupOp (
1349 IN MNP_INSTANCE_DATA *Instance,
1350 IN BOOLEAN JoinFlag,
1351 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,
1352 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL
1353 )
1354 {
1355 MNP_SERVICE_DATA *MnpServiceData;
1356 NET_LIST_ENTRY *Entry;
1357 NET_LIST_ENTRY *NextEntry;
1358 MNP_GROUP_ADDRESS *GroupAddress;
1359 EFI_SIMPLE_NETWORK_MODE *SnpMode;
1360 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;
1361 EFI_STATUS Status;
1362 BOOLEAN AddressExist;
1363 BOOLEAN NeedUpdate;
1364
1365 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1366
1367 MnpServiceData = Instance->MnpServiceData;
1368 SnpMode = MnpServiceData->Snp->Mode;
1369
1370 if (JoinFlag) {
1371 //
1372 // A new gropu address is to be added.
1373 //
1374
1375 GroupAddress = NULL;
1376 AddressExist = FALSE;
1377
1378 //
1379 // Allocate memory for the control block.
1380 //
1381 NewCtrlBlk = NetAllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));
1382 if (NewCtrlBlk == NULL) {
1383
1384 MNP_DEBUG_ERROR (("MnpGroupOp: Failed to allocate memory resource.\n"));
1385 return EFI_OUT_OF_RESOURCES;
1386 }
1387
1388 NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {
1389 //
1390 // Check whether the MacAddress is already joined by other instances.
1391 //
1392 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1393 if (0 == NetCompareMem (
1394 MacAddress,
1395 &GroupAddress->Address,
1396 SnpMode->HwAddressSize
1397 )) {
1398
1399 AddressExist = TRUE;
1400 break;
1401 }
1402 }
1403
1404 if (!AddressExist) {
1405 GroupAddress = NULL;
1406 }
1407
1408 //
1409 // Add the GroupAddress for this instance.
1410 //
1411 Status = MnpGroupOpAddCtrlBlk (
1412 Instance,
1413 NewCtrlBlk,
1414 GroupAddress,
1415 MacAddress,
1416 SnpMode->HwAddressSize
1417 );
1418 if (EFI_ERROR (Status)) {
1419
1420 return Status;
1421 }
1422
1423 NeedUpdate = TRUE;
1424 } else {
1425
1426 if (MacAddress != NULL) {
1427
1428 ASSERT (CtrlBlk != NULL);
1429
1430 //
1431 // Leave the specific multicast mac address.
1432 //
1433 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);
1434 } else {
1435 //
1436 // Leave all multicast mac addresses.
1437 //
1438 NeedUpdate = FALSE;
1439
1440 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {
1441
1442 NewCtrlBlk = NET_LIST_USER_STRUCT (
1443 Entry,
1444 MNP_GROUP_CONTROL_BLOCK,
1445 CtrlBlkEntry
1446 );
1447 //
1448 // Update is required if the group address left is no longer used
1449 // by other instances.
1450 //
1451 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);
1452 }
1453 }
1454 }
1455
1456 Status = EFI_SUCCESS;
1457
1458 if (NeedUpdate) {
1459 //
1460 // Reconfigure the receive filters if necessary.
1461 //
1462 Status = MnpConfigReceiveFilters (MnpServiceData);
1463 }
1464
1465 return Status;
1466 }