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