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