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