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