]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
Fixing coding style issue.
[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 are licensed
6 and made available under the terms and conditions of the BSD License which
7 accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "MnpImpl.h"
17
18 EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol = {
19 MnpServiceBindingCreateChild,
20 MnpServiceBindingDestroyChild
21 };
22
23 EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate = {
24 MnpGetModeData,
25 MnpConfigure,
26 MnpMcastIpToMac,
27 MnpGroups,
28 MnpTransmit,
29 MnpReceive,
30 MnpCancel,
31 MnpPoll
32 };
33
34 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {
35 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
55 to 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) != 0) {
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, out] 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 OUT 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, out] 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 OUT 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[in, out] MnpServiceData Pointer to the mnp service context data.
337 @param[in, out] Nbuf Pointer to the NET_BUF to free.
338
339 **/
340 VOID
341 MnpFreeNbuf (
342 IN OUT MNP_SERVICE_DATA *MnpServiceData,
343 IN OUT 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, out] 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 EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.
376 @retval Others Other errors as indicated.
377
378 **/
379 EFI_STATUS
380 MnpInitializeServiceData (
381 IN OUT MNP_SERVICE_DATA *MnpServiceData,
382 IN EFI_HANDLE ImageHandle,
383 IN EFI_HANDLE ControllerHandle
384 )
385 {
386 EFI_STATUS Status;
387 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
388 EFI_SIMPLE_NETWORK_MODE *SnpMode;
389
390 MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;
391
392 MnpServiceData->ControllerHandle = ControllerHandle;
393
394 //
395 // Copy the ServiceBinding structure.
396 //
397 MnpServiceData->ServiceBinding = mMnpServiceBindingProtocol;
398
399 //
400 // Open the Simple Network protocol.
401 //
402 Status = gBS->OpenProtocol (
403 ControllerHandle,
404 &gEfiSimpleNetworkProtocolGuid,
405 (VOID **) &Snp,
406 ImageHandle,
407 ControllerHandle,
408 EFI_OPEN_PROTOCOL_BY_DRIVER
409 );
410 if (EFI_ERROR (Status)) {
411 return EFI_UNSUPPORTED;
412 }
413
414 //
415 // Get MTU from Snp.
416 //
417 SnpMode = Snp->Mode;
418 MnpServiceData->Snp = Snp;
419 MnpServiceData->Mtu = SnpMode->MaxPacketSize;
420
421 //
422 // Initialize the lists.
423 //
424 InitializeListHead (&MnpServiceData->GroupAddressList);
425 InitializeListHead (&MnpServiceData->ChildrenList);
426
427 //
428 // Get the buffer length used to allocate NET_BUF to hold data received
429 // from SNP. Do this before fill the FreeNetBufQue.
430 //
431 MnpServiceData->BufferLength = MnpServiceData->Mtu + SnpMode->MediaHeaderSize + NET_ETHER_FCS_SIZE;
432
433 //
434 // Make sure the protocol headers immediately following the media header
435 // 4-byte aligned
436 //
437 MnpServiceData->PaddingSize = (4 - SnpMode->MediaHeaderSize) & 0x3;
438
439 //
440 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
441 //
442 NetbufQueInit (&MnpServiceData->FreeNbufQue);
443 Status = MnpAddFreeNbuf (MnpServiceData, MNP_INIT_NET_BUFFER_NUM);
444 if (EFI_ERROR (Status)) {
445
446 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: MnpAddFreeNbuf failed, %r.\n", Status));
447 goto ERROR;
448 }
449 //
450 // Get one NET_BUF from the FreeNbufQue for rx cache.
451 //
452 MnpServiceData->RxNbufCache = MnpAllocNbuf (MnpServiceData);
453 NetbufAllocSpace (
454 MnpServiceData->RxNbufCache,
455 MnpServiceData->BufferLength,
456 NET_BUF_TAIL
457 );
458
459 //
460 // Allocate buffer pool for tx.
461 //
462 MnpServiceData->TxBuf = AllocatePool (MnpServiceData->Mtu + SnpMode->MediaHeaderSize);
463 if (MnpServiceData->TxBuf == NULL) {
464
465 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: AllocatePool failed.\n"));
466 Status = EFI_OUT_OF_RESOURCES;
467
468 goto ERROR;
469 }
470
471 //
472 // Create the system poll timer.
473 //
474 Status = gBS->CreateEvent (
475 EVT_NOTIFY_SIGNAL | EVT_TIMER,
476 TPL_CALLBACK,
477 MnpSystemPoll,
478 MnpServiceData,
479 &MnpServiceData->PollTimer
480 );
481 if (EFI_ERROR (Status)) {
482
483 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for poll timer failed.\n"));
484 goto ERROR;
485 }
486
487 //
488 // Create the timer for packet timeout check.
489 //
490 Status = gBS->CreateEvent (
491 EVT_NOTIFY_SIGNAL | EVT_TIMER,
492 TPL_CALLBACK,
493 MnpCheckPacketTimeout,
494 MnpServiceData,
495 &MnpServiceData->TimeoutCheckTimer
496 );
497 if (EFI_ERROR (Status)) {
498
499 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for packet timeout check failed.\n"));
500 goto ERROR;
501 }
502
503 //
504 // Create the timer for tx timeout check.
505 //
506 Status = gBS->CreateEvent (
507 EVT_TIMER,
508 TPL_CALLBACK,
509 NULL,
510 NULL,
511 &MnpServiceData->TxTimeoutEvent
512 );
513 if (EFI_ERROR (Status)) {
514
515 DEBUG ((EFI_D_ERROR, "MnpInitializeServiceData: CreateEvent for tx timeout event failed.\n"));
516 }
517
518 ERROR:
519
520 if (EFI_ERROR (Status)) {
521 //
522 // Free the dynamic allocated resources if necessary.
523 //
524 if (MnpServiceData->TimeoutCheckTimer != NULL) {
525
526 gBS->CloseEvent (MnpServiceData->TimeoutCheckTimer);
527 }
528
529 if (MnpServiceData->PollTimer != NULL) {
530
531 gBS->CloseEvent (MnpServiceData->PollTimer);
532 }
533
534 if (MnpServiceData->TxBuf != NULL) {
535
536 gBS->FreePool (MnpServiceData->TxBuf);
537 }
538
539 if (MnpServiceData->RxNbufCache != NULL) {
540
541 MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);
542 }
543
544 if (MnpServiceData->FreeNbufQue.BufNum != 0) {
545
546 NetbufQueFlush (&MnpServiceData->FreeNbufQue);
547 }
548 }
549
550 return Status;
551 }
552
553
554 /**
555 Flush the mnp service context data.
556
557 @param[in, out] MnpServiceData Pointer to the mnp service context data.
558 @param[in] ImageHandle The driver image handle.
559
560 **/
561 VOID
562 MnpFlushServiceData (
563 IN OUT MNP_SERVICE_DATA *MnpServiceData,
564 IN EFI_HANDLE ImageHandle
565 )
566 {
567 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
568
569 //
570 // The GroupAddressList must be empty.
571 //
572 ASSERT (IsListEmpty (&MnpServiceData->GroupAddressList));
573
574 //
575 // Close the event.
576 //
577 gBS->CloseEvent (&MnpServiceData->TxTimeoutEvent);
578 gBS->CloseEvent (&MnpServiceData->TimeoutCheckTimer);
579 gBS->CloseEvent (&MnpServiceData->PollTimer);
580
581 //
582 // Free the tx buffer.
583 //
584 gBS->FreePool (MnpServiceData->TxBuf);
585
586 //
587 // Free the RxNbufCache.
588 //
589 MnpFreeNbuf (MnpServiceData, MnpServiceData->RxNbufCache);
590
591 //
592 // Flush the FreeNbufQue.
593 //
594 MnpServiceData->NbufCnt -= MnpServiceData->FreeNbufQue.BufNum;
595 NetbufQueFlush (&MnpServiceData->FreeNbufQue);
596
597 DEBUG_CODE (
598
599 if (MnpServiceData->NbufCnt != 0) {
600
601 DEBUG ((EFI_D_WARN, "MnpFlushServiceData: Memory leak, MnpServiceData->NbufCnt != 0.\n"));
602 }
603 );
604
605 //
606 // Close the Simple Network Protocol.
607 //
608 gBS->CloseProtocol (
609 MnpServiceData->ControllerHandle,
610 &gEfiSimpleNetworkProtocolGuid,
611 ImageHandle,
612 MnpServiceData->ControllerHandle
613 );
614 }
615
616
617 /**
618 Initialize the mnp instance context data.
619
620 @param[in] MnpServiceData Pointer to the mnp service context data.
621 @param[in, out] Instance Pointer to the mnp instance context data
622 to initialize.
623
624 **/
625 VOID
626 MnpInitializeInstanceData (
627 IN MNP_SERVICE_DATA *MnpServiceData,
628 IN OUT MNP_INSTANCE_DATA *Instance
629 )
630 {
631 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
632 ASSERT (Instance != NULL);
633
634 //
635 // Set the signature.
636 //
637 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;
638
639 //
640 // Copy the MNP Protocol interfaces from the template.
641 //
642 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));
643
644 //
645 // Copy the default config data.
646 //
647 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));
648
649 //
650 // Initialize the lists.
651 //
652 InitializeListHead (&Instance->GroupCtrlBlkList);
653 InitializeListHead (&Instance->RcvdPacketQueue);
654 InitializeListHead (&Instance->RxDeliveredPacketQueue);
655
656 //
657 // Initialize the RxToken Map.
658 //
659 NetMapInit (&Instance->RxTokenMap);
660
661 //
662 // Save the MnpServiceData info.
663 //
664 Instance->MnpServiceData = MnpServiceData;
665 }
666
667
668 /**
669 Check whether the token specified by Arg matches the token in Item.
670
671 @param[in] Map Pointer to the NET_MAP.
672 @param[in] Item Pointer to the NET_MAP_ITEM.
673 @param[in] Arg Pointer to the Arg, it's a pointer to the token to
674 check.
675
676 @retval EFI_SUCCESS The token specified by Arg is different from the
677 token in Item.
678 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
679 Item.
680
681 **/
682 EFI_STATUS
683 MnpTokenExist (
684 IN NET_MAP *Map,
685 IN NET_MAP_ITEM *Item,
686 IN VOID *Arg
687 )
688 {
689 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;
690 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;
691
692 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;
693 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
694
695 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
696 //
697 // The token is the same either the two tokens equals or the Events in
698 // the two tokens are the same.
699 //
700 return EFI_ACCESS_DENIED;
701 }
702
703 return EFI_SUCCESS;
704 }
705
706 /**
707 Cancel the token specified by Arg if it matches the token in Item.
708
709 @param[in, out] Map Pointer to the NET_MAP.
710 @param[in, out] Item Pointer to the NET_MAP_ITEM.
711 @param[in] Arg Pointer to the Arg, it's a pointer to the
712 token to cancel.
713
714 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,
715 or the Arg isn't NULL, and the token in Item is
716 different from the Arg.
717 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
718 Arg, and the token is cancelled.
719
720 **/
721 EFI_STATUS
722 MnpCancelTokens (
723 IN OUT NET_MAP *Map,
724 IN OUT NET_MAP_ITEM *Item,
725 IN VOID *Arg
726 )
727 {
728 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;
729
730 if ((Arg != NULL) && (Item->Key != Arg)) {
731 //
732 // The token in Item is not the token specified by Arg.
733 //
734 return EFI_SUCCESS;
735 }
736
737 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
738
739 //
740 // Remove the item from the map.
741 //
742 NetMapRemoveItem (Map, Item, NULL);
743
744 //
745 // Cancel this token with status set to EFI_ABORTED.
746 //
747 TokenToCancel->Status = EFI_ABORTED;
748 gBS->SignalEvent (TokenToCancel->Event);
749
750 if (Arg != NULL) {
751 //
752 // Only abort the token specified by Arg if Arg isn't NULL.
753 //
754 return EFI_ABORTED;
755 }
756
757 return EFI_SUCCESS;
758 }
759
760
761 /**
762 Start and initialize the simple network.
763
764 @param[in] Snp Pointer to the simple network protocol.
765
766 @retval EFI_SUCCESS The simple network protocol is started.
767 @retval Others Other errors as indicated.
768
769 **/
770 EFI_STATUS
771 MnpStartSnp (
772 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
773 )
774 {
775 EFI_STATUS Status;
776
777 ASSERT (Snp != NULL);
778
779 //
780 // Start the simple network.
781 //
782 Status = Snp->Start (Snp);
783
784 if (!EFI_ERROR (Status)) {
785 //
786 // Initialize the simple network.
787 //
788 Status = Snp->Initialize (Snp, 0, 0);
789 }
790
791 return Status;
792 }
793
794
795 /**
796 Stop the simple network.
797
798 @param[in] Snp Pointer to the simple network protocol.
799
800 @retval EFI_SUCCESS The simple network is stopped.
801 @retval Others Other errors as indicated.
802
803 **/
804 EFI_STATUS
805 MnpStopSnp (
806 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
807 )
808 {
809 EFI_STATUS Status;
810
811 ASSERT (Snp != NULL);
812
813 //
814 // Shut down the simple network.
815 //
816 Status = Snp->Shutdown (Snp);
817
818 if (!EFI_ERROR (Status)) {
819 //
820 // Stop the simple network.
821 //
822 Status = Snp->Stop (Snp);
823 }
824
825 return Status;
826 }
827
828
829 /**
830 Start the managed network, this function is called when one instance is configured
831 or reconfigured.
832
833 @param[in, out] MnpServiceData Pointer to the mnp service context data.
834 @param[in] IsConfigUpdate The instance is reconfigured or it's the first
835 time the instanced is configured.
836 @param[in] EnableSystemPoll Enable the system polling or not.
837
838 @retval EFI_SUCCESS The managed network is started and some
839 configuration is updated.
840 @retval Others Other errors as indicated.
841
842 **/
843 EFI_STATUS
844 MnpStart (
845 IN OUT MNP_SERVICE_DATA *MnpServiceData,
846 IN BOOLEAN IsConfigUpdate,
847 IN BOOLEAN EnableSystemPoll
848 )
849 {
850 EFI_STATUS Status;
851 EFI_TIMER_DELAY TimerOpType;
852
853 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
854
855 Status = EFI_SUCCESS;
856
857 if (!IsConfigUpdate) {
858 //
859 // If it's not a configuration update, increase the configured children number.
860 //
861 MnpServiceData->ConfiguredChildrenNumber++;
862
863 if (MnpServiceData->ConfiguredChildrenNumber == 1) {
864 //
865 // It's the first configured child, start the simple network.
866 //
867 Status = MnpStartSnp (MnpServiceData->Snp);
868 if (EFI_ERROR (Status)) {
869
870 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));
871 goto ErrorExit;
872 }
873
874 //
875 // Start the timeout timer.
876 //
877 Status = gBS->SetTimer (
878 MnpServiceData->TimeoutCheckTimer,
879 TimerPeriodic,
880 MNP_TIMEOUT_CHECK_INTERVAL
881 );
882 if (EFI_ERROR (Status)) {
883
884 DEBUG (
885 (EFI_D_ERROR,
886 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
887 Status)
888 );
889 goto ErrorExit;
890 }
891 }
892 }
893
894 if (MnpServiceData->EnableSystemPoll ^ EnableSystemPoll) {
895 //
896 // The EnableSystemPoll differs with the current state, disable or enable
897 // the system poll.
898 //
899 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;
900
901 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);
902 if (EFI_ERROR (Status)) {
903
904 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));
905 goto ErrorExit;
906 }
907
908 MnpServiceData->EnableSystemPoll = EnableSystemPoll;
909 }
910
911 //
912 // Change the receive filters if need.
913 //
914 Status = MnpConfigReceiveFilters (MnpServiceData);
915
916 ErrorExit:
917
918 return Status;
919 }
920
921
922 /**
923 Stop the managed network.
924
925 @param[in, out] MnpServiceData Pointer to the mnp service context data.
926
927 @retval EFI_SUCCESS The managed network is stopped.
928 @retval Others Other errors as indicated.
929
930 **/
931 EFI_STATUS
932 MnpStop (
933 IN OUT MNP_SERVICE_DATA *MnpServiceData
934 )
935 {
936 EFI_STATUS Status;
937
938 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
939 ASSERT (MnpServiceData->ConfiguredChildrenNumber > 0);
940
941 //
942 // Configure the receive filters.
943 //
944 MnpConfigReceiveFilters (MnpServiceData);
945
946 //
947 // Decrease the children number.
948 //
949 MnpServiceData->ConfiguredChildrenNumber--;
950
951 if (MnpServiceData->ConfiguredChildrenNumber > 0) {
952 //
953 // If there are other configured chilren, return and keep the timers and
954 // simple network unchanged.
955 //
956 return EFI_SUCCESS;
957 }
958
959 //
960 // No configured children now.
961 //
962
963 if (MnpServiceData->EnableSystemPoll) {
964 //
965 // The system poll in on, cancel the poll timer.
966 //
967 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerCancel, 0);
968 MnpServiceData->EnableSystemPoll = FALSE;
969 }
970
971 //
972 // Cancel the timeout timer.
973 //
974 Status = gBS->SetTimer (MnpServiceData->TimeoutCheckTimer, TimerCancel, 0);
975
976 //
977 // Stop the simple network.
978 //
979 Status = MnpStopSnp (MnpServiceData->Snp);
980
981 return Status;
982 }
983
984
985 /**
986 Flush the instance's received data.
987
988 @param[in, out] Instance Pointer to the mnp instance context data.
989
990 **/
991 VOID
992 MnpFlushRcvdDataQueue (
993 IN OUT MNP_INSTANCE_DATA *Instance
994 )
995 {
996 EFI_TPL OldTpl;
997 MNP_RXDATA_WRAP *RxDataWrap;
998
999 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1000
1001 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1002
1003 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {
1004 //
1005 // Remove all the Wraps.
1006 //
1007 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
1008
1009 //
1010 // Recycle the RxDataWrap.
1011 //
1012 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);
1013 Instance->RcvdPacketQueueSize--;
1014 }
1015
1016 ASSERT (Instance->RcvdPacketQueueSize == 0);
1017
1018 gBS->RestoreTPL (OldTpl);
1019 }
1020
1021
1022 /**
1023 Configure the Instance using ConfigData.
1024
1025 @param[in, out] Instance Pointer to the mnp instance context data.
1026 @param[in] ConfigData Pointer to the configuration data used to configure
1027 the isntance.
1028
1029 @retval EFI_SUCCESS The Instance is configured.
1030 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1031 implementation doesn't support it.
1032 @retval Others Other errors as indicated.
1033
1034 **/
1035 EFI_STATUS
1036 MnpConfigureInstance (
1037 IN OUT MNP_INSTANCE_DATA *Instance,
1038 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL
1039 )
1040 {
1041 EFI_STATUS Status;
1042 MNP_SERVICE_DATA *MnpServiceData;
1043 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;
1044 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;
1045 BOOLEAN IsConfigUpdate;
1046
1047 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1048
1049 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {
1050 //
1051 // Don't support timestamp.
1052 //
1053 return EFI_UNSUPPORTED;
1054 }
1055
1056 Status = EFI_SUCCESS;
1057
1058 MnpServiceData = Instance->MnpServiceData;
1059 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1060
1061 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));
1062
1063 OldConfigData = &Instance->ConfigData;
1064 NewConfigData = ConfigData;
1065 if (NewConfigData == NULL) {
1066 //
1067 // Restore back the default config data if a reset of this instance
1068 // is required.
1069 //
1070 NewConfigData = &mMnpDefaultConfigData;
1071 }
1072
1073 //
1074 // Reset the instance's receive filter.
1075 //
1076 Instance->ReceiveFilter = 0;
1077
1078 //
1079 // Clear the receive counters according to the old ConfigData.
1080 //
1081 if (OldConfigData->EnableUnicastReceive) {
1082 MnpServiceData->UnicastCount--;
1083 }
1084
1085 if (OldConfigData->EnableMulticastReceive) {
1086 MnpServiceData->MulticastCount--;
1087 }
1088
1089 if (OldConfigData->EnableBroadcastReceive) {
1090 MnpServiceData->BroadcastCount--;
1091 }
1092
1093 if (OldConfigData->EnablePromiscuousReceive) {
1094 MnpServiceData->PromiscuousCount--;
1095 }
1096
1097 //
1098 // Set the receive filter counters and the receive filter of the
1099 // instance according to the new ConfigData.
1100 //
1101 if (NewConfigData->EnableUnicastReceive) {
1102 MnpServiceData->UnicastCount++;
1103 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;
1104 }
1105
1106 if (NewConfigData->EnableMulticastReceive) {
1107 MnpServiceData->MulticastCount++;
1108 }
1109
1110 if (NewConfigData->EnableBroadcastReceive) {
1111 MnpServiceData->BroadcastCount++;
1112 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;
1113 }
1114
1115 if (NewConfigData->EnablePromiscuousReceive) {
1116 MnpServiceData->PromiscuousCount++;
1117 }
1118
1119 if (OldConfigData->FlushQueuesOnReset) {
1120
1121 MnpFlushRcvdDataQueue (Instance);
1122 }
1123
1124 if (ConfigData == NULL) {
1125
1126 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);
1127 }
1128
1129 if (!NewConfigData->EnableMulticastReceive) {
1130
1131 MnpGroupOp (Instance, FALSE, NULL, NULL);
1132 }
1133
1134 //
1135 // Save the new configuration data.
1136 //
1137 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));
1138
1139 Instance->Configured = (BOOLEAN) (ConfigData != NULL);
1140
1141 if (Instance->Configured) {
1142 //
1143 // The instance is configured, start the Mnp.
1144 //
1145 Status = MnpStart (
1146 MnpServiceData,
1147 IsConfigUpdate,
1148 (BOOLEAN) !NewConfigData->DisableBackgroundPolling
1149 );
1150 } else {
1151 //
1152 // The instance is changed to the unconfigured state, stop the Mnp.
1153 //
1154 Status = MnpStop (MnpServiceData);
1155 }
1156
1157 return Status;
1158 }
1159
1160
1161
1162 /**
1163 Add a group address control block which controls the MacAddress for
1164 this instance.
1165
1166 @param[in, out] Instance Pointer to the mnp instance context data.
1167 @param[in, out] CtrlBlk Pointer to the group address control block.
1168 @param[in, out] GroupAddress Pointer to the group adress.
1169 @param[in] MacAddress Pointer to the mac address.
1170 @param[in] HwAddressSize The hardware address size.
1171
1172 @retval EFI_SUCCESS The group address control block is added.
1173 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1174
1175 **/
1176 EFI_STATUS
1177 MnpGroupOpAddCtrlBlk (
1178 IN OUT MNP_INSTANCE_DATA *Instance,
1179 IN OUT MNP_GROUP_CONTROL_BLOCK *CtrlBlk,
1180 IN OUT MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
1181 IN EFI_MAC_ADDRESS *MacAddress,
1182 IN UINT32 HwAddressSize
1183 )
1184 {
1185 MNP_SERVICE_DATA *MnpServiceData;
1186
1187 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1188
1189 MnpServiceData = Instance->MnpServiceData;
1190 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1191
1192 if (GroupAddress == NULL) {
1193
1194 ASSERT (MacAddress != NULL);
1195
1196 //
1197 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1198 //
1199 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));
1200 if (GroupAddress == NULL) {
1201
1202 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1203
1204 return EFI_OUT_OF_RESOURCES;
1205 }
1206
1207 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));
1208 GroupAddress->RefCnt = 0;
1209 InsertTailList (
1210 &MnpServiceData->GroupAddressList,
1211 &GroupAddress->AddrEntry
1212 );
1213 MnpServiceData->GroupAddressCount++;
1214 }
1215
1216 //
1217 // Increase the RefCnt.
1218 //
1219 GroupAddress->RefCnt++;
1220
1221 //
1222 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1223 //
1224 CtrlBlk->GroupAddress = GroupAddress;
1225 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);
1226
1227 return EFI_SUCCESS;
1228 }
1229
1230
1231 /**
1232 Delete a group control block from the instance. If the controlled group address's
1233 reference count reaches zero, the group address is removed too.
1234
1235 @param[in] Instance Pointer to the instance context data.
1236 @param[in] CtrlBlk Pointer to the group control block to delete.
1237
1238 @return The group address controlled by the control block is no longer used or not.
1239
1240 **/
1241 BOOLEAN
1242 MnpGroupOpDelCtrlBlk (
1243 IN MNP_INSTANCE_DATA *Instance,
1244 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk
1245 )
1246 {
1247 MNP_SERVICE_DATA *MnpServiceData;
1248 MNP_GROUP_ADDRESS *GroupAddress;
1249
1250 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1251
1252 MnpServiceData = Instance->MnpServiceData;
1253 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1254
1255 //
1256 // Remove and free the CtrlBlk.
1257 //
1258 GroupAddress = CtrlBlk->GroupAddress;
1259 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);
1260 gBS->FreePool (CtrlBlk);
1261
1262 ASSERT (GroupAddress->RefCnt > 0);
1263
1264 //
1265 // Count down the RefCnt.
1266 //
1267 GroupAddress->RefCnt--;
1268
1269 if (GroupAddress->RefCnt == 0) {
1270 //
1271 // Free this GroupAddress entry if no instance uses it.
1272 //
1273 MnpServiceData->GroupAddressCount--;
1274 RemoveEntryList (&GroupAddress->AddrEntry);
1275 gBS->FreePool (GroupAddress);
1276
1277 return TRUE;
1278 }
1279
1280 return FALSE;
1281 }
1282
1283
1284 /**
1285 Do the group operations for this instance.
1286
1287 @param[in, out] Instance Pointer to the instance context data.
1288 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to
1289 leave a group/groups.
1290 @param[in] MacAddress Pointer to the group address to join or leave.
1291 @param[in] CtrlBlk Pointer to the group control block if JoinFlag
1292 is FALSE.
1293
1294 @retval EFI_SUCCESS The group operation finished.
1295 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1296 @retval Others Other errors as indicated.
1297
1298 **/
1299 EFI_STATUS
1300 MnpGroupOp (
1301 IN OUT MNP_INSTANCE_DATA *Instance,
1302 IN BOOLEAN JoinFlag,
1303 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,
1304 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL
1305 )
1306 {
1307 MNP_SERVICE_DATA *MnpServiceData;
1308 LIST_ENTRY *Entry;
1309 LIST_ENTRY *NextEntry;
1310 MNP_GROUP_ADDRESS *GroupAddress;
1311 EFI_SIMPLE_NETWORK_MODE *SnpMode;
1312 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;
1313 EFI_STATUS Status;
1314 BOOLEAN AddressExist;
1315 BOOLEAN NeedUpdate;
1316
1317 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1318
1319 MnpServiceData = Instance->MnpServiceData;
1320 SnpMode = MnpServiceData->Snp->Mode;
1321
1322 if (JoinFlag) {
1323 //
1324 // A new gropu address is to be added.
1325 //
1326
1327 GroupAddress = NULL;
1328 AddressExist = FALSE;
1329
1330 //
1331 // Allocate memory for the control block.
1332 //
1333 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));
1334 if (NewCtrlBlk == NULL) {
1335
1336 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));
1337 return EFI_OUT_OF_RESOURCES;
1338 }
1339
1340 NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {
1341 //
1342 // Check whether the MacAddress is already joined by other instances.
1343 //
1344 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1345 if (0 == CompareMem (
1346 MacAddress,
1347 &GroupAddress->Address,
1348 SnpMode->HwAddressSize
1349 )) {
1350
1351 AddressExist = TRUE;
1352 break;
1353 }
1354 }
1355
1356 if (!AddressExist) {
1357 GroupAddress = NULL;
1358 }
1359
1360 //
1361 // Add the GroupAddress for this instance.
1362 //
1363 Status = MnpGroupOpAddCtrlBlk (
1364 Instance,
1365 NewCtrlBlk,
1366 GroupAddress,
1367 MacAddress,
1368 SnpMode->HwAddressSize
1369 );
1370 if (EFI_ERROR (Status)) {
1371
1372 return Status;
1373 }
1374
1375 NeedUpdate = TRUE;
1376 } else {
1377
1378 if (MacAddress != NULL) {
1379
1380 ASSERT (CtrlBlk != NULL);
1381
1382 //
1383 // Leave the specific multicast mac address.
1384 //
1385 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);
1386 } else {
1387 //
1388 // Leave all multicast mac addresses.
1389 //
1390 NeedUpdate = FALSE;
1391
1392 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {
1393
1394 NewCtrlBlk = NET_LIST_USER_STRUCT (
1395 Entry,
1396 MNP_GROUP_CONTROL_BLOCK,
1397 CtrlBlkEntry
1398 );
1399 //
1400 // Update is required if the group address left is no longer used
1401 // by other instances.
1402 //
1403 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);
1404 }
1405 }
1406 }
1407
1408 Status = EFI_SUCCESS;
1409
1410 if (NeedUpdate) {
1411 //
1412 // Reconfigure the receive filters if necessary.
1413 //
1414 Status = MnpConfigReceiveFilters (MnpServiceData);
1415 }
1416
1417 return Status;
1418 }