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