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