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