]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
move protocol close process from MnpDriverBindingStart() to MnpFlushServiceData().
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
CommitLineData
8a67d61d 1/** @file\r
2\r
e21ef3a2 3Copyright (c) 2005 - 2008, Intel Corporation\r
8a67d61d 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
e21ef3a2 512\r
513 //\r
514 // Close the Simple Network Protocol.\r
515 //\r
516 gBS->CloseProtocol (\r
517 MnpServiceData->ControllerHandle,\r
518 &gEfiSimpleNetworkProtocolGuid,\r
519 This->DriverBindingHandle,\r
520 MnpServiceData->ControllerHandle\r
521 );\r
8a67d61d 522}\r
523\r
524\r
525/**\r
526 Initialize the mnp instance context data.\r
527\r
528 @param MnpServiceData Pointer to the mnp service context data.\r
529 @param Instance Pointer to the mnp instance context data to\r
530 initialize.\r
531\r
532 @return None.\r
533\r
534**/\r
535VOID\r
536MnpInitializeInstanceData (\r
537 IN MNP_SERVICE_DATA *MnpServiceData,\r
538 IN MNP_INSTANCE_DATA *Instance\r
539 )\r
540{\r
541 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
542 ASSERT (Instance != NULL);\r
543\r
544 //\r
545 // Set the signature.\r
546 //\r
547 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;\r
548\r
549 //\r
550 // Copy the MNP Protocol interfaces from the template.\r
551 //\r
687a2e5f 552 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));\r
8a67d61d 553\r
554 //\r
555 // Copy the default config data.\r
556 //\r
687a2e5f 557 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));\r
8a67d61d 558\r
559 //\r
560 // Initialize the lists.\r
561 //\r
e48e37fc 562 InitializeListHead (&Instance->GroupCtrlBlkList);\r
563 InitializeListHead (&Instance->RcvdPacketQueue);\r
564 InitializeListHead (&Instance->RxDeliveredPacketQueue);\r
8a67d61d 565\r
566 //\r
567 // Initialize the RxToken Map.\r
568 //\r
569 NetMapInit (&Instance->RxTokenMap);\r
570\r
571 //\r
572 // Save the MnpServiceData info.\r
573 //\r
574 Instance->MnpServiceData = MnpServiceData;\r
575}\r
576\r
577\r
578/**\r
579 Check whether the token specified by Arg maches the token in Item.\r
580\r
581 @param Map Pointer to the NET_MAP.\r
582 @param Item Pointer to the NET_MAP_ITEM\r
583 @param Arg Pointer to the Arg, it's a pointer to the token to\r
584 check.\r
585\r
586 @retval EFI_SUCCESS The token specified by Arg is different from the\r
587 token in Item.\r
588 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in\r
589 Item.\r
590\r
591**/\r
592EFI_STATUS\r
593MnpTokenExist (\r
594 IN NET_MAP *Map,\r
595 IN NET_MAP_ITEM *Item,\r
596 IN VOID *Arg\r
597 )\r
598{\r
599 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;\r
600 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;\r
601\r
602 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;\r
603 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
604\r
605 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {\r
606 //\r
607 // The token is the same either the two tokens equals or the Events in\r
608 // the two tokens are the same.\r
609 //\r
610 return EFI_ACCESS_DENIED;\r
611 }\r
612\r
613 return EFI_SUCCESS;\r
614}\r
615\r
616\r
617/**\r
618 Cancel the token specified by Arg if it matches the token in Item.\r
619\r
620 @param Map Pointer to the NET_MAP.\r
621 @param Item Pointer to the NET_MAP_ITEM\r
622 @param Arg Pointer to the Arg, it's a pointer to the token to\r
623 cancel.\r
624\r
625 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is\r
626 cancelled, or the Arg isn't NULL, and the token in\r
627 Item is different from the Arg.\r
628 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the\r
629 Arg, and the token is cancelled.\r
630\r
631**/\r
632EFI_STATUS\r
633MnpCancelTokens (\r
634 IN NET_MAP *Map,\r
635 IN NET_MAP_ITEM *Item,\r
636 IN VOID *Arg\r
637 )\r
638{\r
639 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;\r
640\r
641 if ((Arg != NULL) && (Item->Key != Arg)) {\r
642 //\r
643 // The token in Item is not the token specified by Arg.\r
644 //\r
645 return EFI_SUCCESS;\r
646 }\r
647\r
648 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;\r
649\r
650 //\r
36ee91ca 651 // Remove the item from the map.\r
8a67d61d 652 //\r
36ee91ca 653 NetMapRemoveItem (Map, Item, NULL);\r
8a67d61d 654\r
655 //\r
36ee91ca 656 // Cancel this token with status set to EFI_ABORTED.\r
8a67d61d 657 //\r
36ee91ca 658 TokenToCancel->Status = EFI_ABORTED;\r
659 gBS->SignalEvent (TokenToCancel->Event);\r
8a67d61d 660\r
661 if (Arg != NULL) {\r
662 //\r
663 // Only abort the token specified by Arg if Arg isn't NULL.\r
664 //\r
665 return EFI_ABORTED;\r
666 }\r
667\r
668 return EFI_SUCCESS;\r
669}\r
670\r
671\r
672/**\r
673 Start and initialize the simple network.\r
674\r
675 @param Snp Pointer to the simple network protocol.\r
676\r
677 @retval EFI_SUCCESS The simple network protocol is started.\r
678 @retval Other Some error occurs.\r
679\r
680**/\r
681STATIC\r
682EFI_STATUS\r
683MnpStartSnp (\r
684 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
685 )\r
686{\r
687 EFI_STATUS Status;\r
688\r
689 ASSERT (Snp != NULL);\r
690\r
691 //\r
692 // Start the simple network.\r
693 //\r
694 Status = Snp->Start (Snp);\r
695\r
696 if (!EFI_ERROR (Status)) {\r
697 //\r
698 // Initialize the simple network.\r
699 //\r
700 Status = Snp->Initialize (Snp, 0, 0);\r
701 }\r
702\r
703 return Status;\r
704}\r
705\r
706\r
707/**\r
708 Stop the simple network.\r
709\r
710 @param Snp Pointer to the simple network protocol.\r
711\r
712 @retval EFI_SUCCESS The simple network is stopped.\r
713 @retval Other Some error occurs.\r
714\r
715**/\r
716STATIC\r
717EFI_STATUS\r
718MnpStopSnp (\r
719 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp\r
720 )\r
721{\r
722 EFI_STATUS Status;\r
723\r
724 ASSERT (Snp != NULL);\r
725\r
726 //\r
727 // Shut down the simple network.\r
728 //\r
729 Status = Snp->Shutdown (Snp);\r
730\r
731 if (!EFI_ERROR (Status)) {\r
732 //\r
733 // Stop the simple network.\r
734 //\r
735 Status = Snp->Stop (Snp);\r
736 }\r
737\r
738 return Status;\r
739}\r
740\r
741\r
742/**\r
743 Start the managed network, this function is called when one instance is configured\r
744 or reconfigured.\r
745\r
746 @param MnpServiceData Pointer to the mnp service context data.\r
747 @param IsConfigUpdate The instance is reconfigured or it's the first time\r
748 the instanced is configured.\r
749 @param EnableSystemPoll Enable the system polling or not.\r
750\r
751 @retval EFI_SUCCESS The managed network is started and some\r
752 configuration is updated.\r
753 @retval Other Some error occurs.\r
754\r
755**/\r
756STATIC\r
757EFI_STATUS\r
758MnpStart (\r
759 IN MNP_SERVICE_DATA *MnpServiceData,\r
760 IN BOOLEAN IsConfigUpdate,\r
761 IN BOOLEAN EnableSystemPoll\r
762 )\r
763{\r
764 EFI_STATUS Status;\r
765 EFI_TIMER_DELAY TimerOpType;\r
766\r
767 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
768\r
769 Status = EFI_SUCCESS;\r
770\r
771 if (!IsConfigUpdate) {\r
772 //\r
773 // If it's not a configuration update, increase the configured children number.\r
774 //\r
775 MnpServiceData->ConfiguredChildrenNumber++;\r
776\r
777 if (MnpServiceData->ConfiguredChildrenNumber == 1) {\r
778 //\r
779 // It's the first configured child, start the simple network.\r
780 //\r
781 Status = MnpStartSnp (MnpServiceData->Snp);\r
782 if (EFI_ERROR (Status)) {\r
783\r
e48e37fc 784 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));\r
8a67d61d 785 goto ErrorExit;\r
786 }\r
787\r
788 //\r
789 // Start the timeout timer.\r
790 //\r
791 Status = gBS->SetTimer (\r
792 MnpServiceData->TimeoutCheckTimer,\r
793 TimerPeriodic,\r
794 MNP_TIMEOUT_CHECK_INTERVAL\r
795 );\r
796 if (EFI_ERROR (Status)) {\r
797\r
e48e37fc 798 DEBUG (\r
799 (EFI_D_ERROR,\r
800 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",\r
8a67d61d 801 Status)\r
802 );\r
803 goto ErrorExit;\r
804 }\r
805 }\r
806 }\r
807\r
808 if (MnpServiceData->EnableSystemPoll ^ EnableSystemPoll) {\r
809 //\r
810 // The EnableSystemPoll differs with the current state, disable or enable\r
811 // the system poll.\r
812 //\r
813 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;\r
814\r
815 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);\r
816 if (EFI_ERROR (Status)) {\r
817\r
e48e37fc 818 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));\r
8a67d61d 819 goto ErrorExit;\r
820 }\r
821\r
822 MnpServiceData->EnableSystemPoll = EnableSystemPoll;\r
823 }\r
824\r
825 //\r
826 // Change the receive filters if need.\r
827 //\r
828 Status = MnpConfigReceiveFilters (MnpServiceData);\r
829\r
830ErrorExit:\r
831\r
832 return Status;\r
833}\r
834\r
835\r
836/**\r
837 Stop the managed network.\r
838\r
839 @param MnpServiceData Pointer to the mnp service context data.\r
840\r
841 @retval EFI_SUCCESS The managed network is stopped.\r
842 @retval Other Some error occurs.\r
843\r
844**/\r
845STATIC\r
846EFI_STATUS\r
847MnpStop (\r
848 IN MNP_SERVICE_DATA *MnpServiceData\r
849 )\r
850{\r
851 EFI_STATUS Status;\r
852\r
853 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
854 ASSERT (MnpServiceData->ConfiguredChildrenNumber > 0);\r
855\r
856 //\r
857 // Configure the receive filters.\r
858 //\r
859 MnpConfigReceiveFilters (MnpServiceData);\r
860\r
861 //\r
862 // Decrease the children number.\r
863 //\r
864 MnpServiceData->ConfiguredChildrenNumber--;\r
865\r
866 if (MnpServiceData->ConfiguredChildrenNumber > 0) {\r
867 //\r
868 // If there are other configured chilren, return and keep the timers and\r
869 // simple network unchanged.\r
870 //\r
871 return EFI_SUCCESS;\r
872 }\r
873\r
874 //\r
875 // No configured children now.\r
876 //\r
877\r
878 if (MnpServiceData->EnableSystemPoll) {\r
879 //\r
880 // The system poll in on, cancel the poll timer.\r
881 //\r
882 Status = gBS->SetTimer (MnpServiceData->PollTimer, TimerCancel, 0);\r
883 MnpServiceData->EnableSystemPoll = FALSE;\r
884 }\r
885\r
886 //\r
887 // Cancel the timeout timer.\r
888 //\r
889 Status = gBS->SetTimer (MnpServiceData->TimeoutCheckTimer, TimerCancel, 0);\r
890\r
891 //\r
892 // Stop the simple network.\r
893 //\r
894 Status = MnpStopSnp (MnpServiceData->Snp);\r
895\r
896 return Status;\r
897}\r
898\r
899\r
900/**\r
901 Flush the instance's received data.\r
902\r
903 @param Instance Pointer to the mnp instance context data.\r
904\r
905 @return None.\r
906\r
907**/\r
908VOID\r
909MnpFlushRcvdDataQueue (\r
910 IN MNP_INSTANCE_DATA *Instance\r
911 )\r
912{\r
913 EFI_TPL OldTpl;\r
914 MNP_RXDATA_WRAP *RxDataWrap;\r
915\r
916 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
917\r
e48e37fc 918 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
8a67d61d 919\r
e48e37fc 920 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {\r
8a67d61d 921 //\r
922 // Remove all the Wraps.\r
923 //\r
924 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);\r
925\r
926 //\r
927 // Recycle the RxDataWrap.\r
928 //\r
929 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);\r
930 Instance->RcvdPacketQueueSize--;\r
931 }\r
932\r
933 ASSERT (Instance->RcvdPacketQueueSize == 0);\r
934\r
e48e37fc 935 gBS->RestoreTPL (OldTpl);\r
8a67d61d 936}\r
937\r
938\r
939/**\r
940 Configure the Instance using ConfigData.\r
941\r
942 @param Instance Pointer to the mnp instance context data.\r
943 @param ConfigData Pointer to the configuration data used to configure\r
944 the isntance.\r
945\r
946 @retval EFI_SUCCESS The Instance is configured.\r
947 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the\r
948 implementation doesn't support it.\r
949 @retval Other Some error occurs.\r
950\r
951**/\r
952EFI_STATUS\r
953MnpConfigureInstance (\r
954 IN MNP_INSTANCE_DATA *Instance,\r
955 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL\r
956 )\r
957{\r
958 EFI_STATUS Status;\r
959 MNP_SERVICE_DATA *MnpServiceData;\r
960 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;\r
961 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;\r
962 BOOLEAN IsConfigUpdate;\r
963\r
964 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
965\r
966 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {\r
967 //\r
968 // Don't support timestamp.\r
969 //\r
970 return EFI_UNSUPPORTED;\r
971 }\r
972\r
973 Status = EFI_SUCCESS;\r
974\r
975 MnpServiceData = Instance->MnpServiceData;\r
976 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
977\r
978 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));\r
979\r
980 OldConfigData = &Instance->ConfigData;\r
981 NewConfigData = ConfigData;\r
982 if (NewConfigData == NULL) {\r
983 //\r
984 // Restore back the default config data if a reset of this instance\r
985 // is required.\r
986 //\r
987 NewConfigData = &mMnpDefaultConfigData;\r
988 }\r
989\r
990 //\r
991 // Reset the instance's receive filter.\r
992 //\r
993 Instance->ReceiveFilter = 0;\r
994\r
995 //\r
996 // Clear the receive counters according to the old ConfigData.\r
997 //\r
998 if (OldConfigData->EnableUnicastReceive) {\r
999 MnpServiceData->UnicastCount--;\r
1000 }\r
1001\r
1002 if (OldConfigData->EnableMulticastReceive) {\r
1003 MnpServiceData->MulticastCount--;\r
1004 }\r
1005\r
1006 if (OldConfigData->EnableBroadcastReceive) {\r
1007 MnpServiceData->BroadcastCount--;\r
1008 }\r
1009\r
1010 if (OldConfigData->EnablePromiscuousReceive) {\r
1011 MnpServiceData->PromiscuousCount--;\r
1012 }\r
1013\r
1014 //\r
1015 // Set the receive filter counters and the receive filter of the\r
1016 // instance according to the new ConfigData.\r
1017 //\r
1018 if (NewConfigData->EnableUnicastReceive) {\r
1019 MnpServiceData->UnicastCount++;\r
1020 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;\r
1021 }\r
1022\r
1023 if (NewConfigData->EnableMulticastReceive) {\r
1024 MnpServiceData->MulticastCount++;\r
1025 }\r
1026\r
1027 if (NewConfigData->EnableBroadcastReceive) {\r
1028 MnpServiceData->BroadcastCount++;\r
1029 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;\r
1030 }\r
1031\r
1032 if (NewConfigData->EnablePromiscuousReceive) {\r
1033 MnpServiceData->PromiscuousCount++;\r
1034 }\r
1035\r
1036 if (OldConfigData->FlushQueuesOnReset) {\r
1037\r
1038 MnpFlushRcvdDataQueue (Instance);\r
1039 }\r
1040\r
1041 if (ConfigData == NULL) {\r
1042\r
36ee91ca 1043 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);\r
8a67d61d 1044 }\r
1045\r
1046 if (!NewConfigData->EnableMulticastReceive) {\r
1047\r
1048 MnpGroupOp (Instance, FALSE, NULL, NULL);\r
1049 }\r
1050\r
1051 //\r
1052 // Save the new configuration data.\r
1053 //\r
687a2e5f 1054 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));\r
8a67d61d 1055\r
1056 Instance->Configured = (BOOLEAN) (ConfigData != NULL);\r
1057\r
1058 if (Instance->Configured) {\r
1059 //\r
1060 // The instance is configured, start the Mnp.\r
1061 //\r
1062 Status = MnpStart (\r
1063 MnpServiceData,\r
1064 IsConfigUpdate,\r
4eb65aff 1065 (BOOLEAN) !NewConfigData->DisableBackgroundPolling\r
8a67d61d 1066 );\r
1067 } else {\r
1068 //\r
1069 // The instance is changed to the unconfigured state, stop the Mnp.\r
1070 //\r
1071 Status = MnpStop (MnpServiceData);\r
1072 }\r
1073\r
1074 return Status;\r
1075}\r
1076\r
1077\r
1078/**\r
1079 Configure the Snp receive filters according to the instances' receive filter\r
1080 settings.\r
1081\r
1082 @param MnpServiceData Pointer to the mnp service context data.\r
1083\r
1084 @retval EFI_SUCCESS The receive filters is configured.\r
1085 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due to lack\r
1086 of memory resource.\r
1087\r
1088**/\r
1089STATIC\r
1090EFI_STATUS\r
1091MnpConfigReceiveFilters (\r
1092 IN MNP_SERVICE_DATA *MnpServiceData\r
1093 )\r
1094{\r
1095 EFI_STATUS Status;\r
1096 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;\r
1097 EFI_MAC_ADDRESS *MCastFilter;\r
1098 UINT32 MCastFilterCnt;\r
1099 UINT32 EnableFilterBits;\r
1100 UINT32 DisableFilterBits;\r
1101 BOOLEAN ResetMCastFilters;\r
e48e37fc 1102 LIST_ENTRY *Entry;\r
8a67d61d 1103 UINT32 Index;\r
1104 MNP_GROUP_ADDRESS *GroupAddress;\r
1105\r
1106 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1107\r
1108 Snp = MnpServiceData->Snp;\r
1109\r
1110 //\r
1111 // Initialize the enable filter and disable filter.\r
1112 //\r
1113 EnableFilterBits = 0;\r
1114 DisableFilterBits = Snp->Mode->ReceiveFilterMask;\r
1115\r
1116 if (MnpServiceData->UnicastCount != 0) {\r
1117 //\r
1118 // Enable unicast if any instance wants to receive unicast.\r
1119 //\r
1120 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
1121 }\r
1122\r
1123 if (MnpServiceData->BroadcastCount != 0) {\r
1124 //\r
1125 // Enable broadcast if any instance wants to receive broadcast.\r
1126 //\r
1127 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
1128 }\r
1129\r
1130 MCastFilter = NULL;\r
1131 MCastFilterCnt = 0;\r
1132 ResetMCastFilters = TRUE;\r
1133\r
1134 if ((MnpServiceData->MulticastCount != 0) && (MnpServiceData->GroupAddressCount != 0)) {\r
1135 //\r
1136 // There are instances configured to receive multicast and already some group\r
1137 // addresses are joined.\r
1138 //\r
1139\r
1140 ResetMCastFilters = FALSE;\r
1141\r
1142 if (MnpServiceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {\r
1143 //\r
1144 // The joind group address is less than simple network's maximum count.\r
1145 // Just configure the snp to do the multicast filtering.\r
1146 //\r
1147\r
1148 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
1149\r
1150 //\r
1151 // Allocate pool for the mulicast addresses.\r
1152 //\r
1153 MCastFilterCnt = MnpServiceData->GroupAddressCount;\r
e48e37fc 1154 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);\r
8a67d61d 1155 if (MCastFilter == NULL) {\r
1156\r
e48e37fc 1157 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));\r
8a67d61d 1158 return EFI_OUT_OF_RESOURCES;\r
1159 }\r
1160\r
1161 //\r
1162 // Fill the multicast HW address buffer.\r
1163 //\r
1164 Index = 0;\r
1165 NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {\r
1166\r
1167 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
687a2e5f 1168 CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));\r
8a67d61d 1169 Index++;\r
1170\r
1171 ASSERT (Index <= MCastFilterCnt);\r
1172 }\r
1173 } else {\r
1174 //\r
1175 // The maximum multicast is reached, set the filter to be promiscuous\r
1176 // multicast.\r
1177 //\r
1178\r
1179 if (Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) {\r
1180 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
1181 } else {\r
1182 //\r
1183 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,\r
1184 // set the NIC to be promiscuous although this will tremendously degrade\r
1185 // the performance.\r
1186 //\r
1187 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1188 }\r
1189 }\r
1190 }\r
1191\r
1192 if (MnpServiceData->PromiscuousCount != 0) {\r
1193 //\r
1194 // Enable promiscuous if any instance wants to receive promiscuous.\r
1195 //\r
1196 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
1197 }\r
1198\r
1199 //\r
1200 // Set the disable filter.\r
1201 //\r
1202 DisableFilterBits ^= EnableFilterBits;\r
1203\r
1204 //\r
1205 // Configure the receive filters of SNP.\r
1206 //\r
1207 Status = Snp->ReceiveFilters (\r
1208 Snp,\r
1209 EnableFilterBits,\r
1210 DisableFilterBits,\r
1211 ResetMCastFilters,\r
1212 MCastFilterCnt,\r
1213 MCastFilter\r
1214 );\r
1215 DEBUG_CODE (\r
1216 if (EFI_ERROR (Status)) {\r
1217\r
e48e37fc 1218 DEBUG (\r
1219 (EFI_D_ERROR,\r
1220 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",\r
8a67d61d 1221 Status)\r
1222 );\r
1223 }\r
1224 );\r
1225\r
1226 if (MCastFilter != NULL) {\r
1227 //\r
1228 // Free the buffer used to hold the group addresses.\r
1229 //\r
e48e37fc 1230 gBS->FreePool (MCastFilter);\r
8a67d61d 1231 }\r
1232\r
1233 return Status;\r
1234}\r
1235\r
1236\r
1237/**\r
1238 Add a group address control block which controls the MacAddress for\r
1239 this instance.\r
1240\r
1241 @param Instance Pointer to the mnp instance context data.\r
1242 @param CtrlBlk Pointer to the group address control block.\r
1243 @param GroupAddress Pointer to the group adress.\r
1244 @param MacAddress Pointer to the mac address.\r
1245 @param HwAddressSize The hardware address size.\r
1246\r
1247 @retval EFI_SUCCESS The group address control block is added.\r
1248 @retval EFI_OUT_OF_RESOURCE Failed due to lack of memory resources.\r
1249\r
1250**/\r
1251STATIC\r
1252EFI_STATUS\r
1253MnpGroupOpAddCtrlBlk (\r
1254 IN MNP_INSTANCE_DATA *Instance,\r
1255 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk,\r
1256 IN MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,\r
1257 IN EFI_MAC_ADDRESS *MacAddress,\r
1258 IN UINT32 HwAddressSize\r
1259 )\r
1260{\r
1261 MNP_SERVICE_DATA *MnpServiceData;\r
1262\r
1263 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1264\r
1265 MnpServiceData = Instance->MnpServiceData;\r
1266 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1267\r
1268 if (GroupAddress == NULL) {\r
1269\r
1270 ASSERT (MacAddress != NULL);\r
1271\r
1272 //\r
1273 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.\r
1274 //\r
e48e37fc 1275 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));\r
8a67d61d 1276 if (GroupAddress == NULL) {\r
1277\r
e48e37fc 1278 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));\r
8a67d61d 1279\r
1280 return EFI_OUT_OF_RESOURCES;\r
1281 }\r
1282\r
687a2e5f 1283 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));\r
8a67d61d 1284 GroupAddress->RefCnt = 0;\r
e48e37fc 1285 InsertTailList (\r
8a67d61d 1286 &MnpServiceData->GroupAddressList,\r
1287 &GroupAddress->AddrEntry\r
1288 );\r
1289 MnpServiceData->GroupAddressCount++;\r
1290 }\r
1291\r
1292 //\r
1293 // Increase the RefCnt.\r
1294 //\r
1295 GroupAddress->RefCnt++;\r
1296\r
1297 //\r
1298 // Add the CtrlBlk into the instance's GroupCtrlBlkList.\r
1299 //\r
1300 CtrlBlk->GroupAddress = GroupAddress;\r
e48e37fc 1301 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);\r
8a67d61d 1302\r
1303 return EFI_SUCCESS;\r
1304}\r
1305\r
1306\r
1307/**\r
1308 Delete a group control block from the instance. If the controlled group address's\r
1309 reference count reaches zero, the group address is removed too.\r
1310\r
1311 @param Instance Pointer to the instance context data.\r
1312 @param CtrlBlk Pointer to the group control block to delete.\r
1313\r
1314 @return The group address controlled by the control block is no longer used or not.\r
1315\r
1316**/\r
1317STATIC\r
1318BOOLEAN\r
1319MnpGroupOpDelCtrlBlk (\r
1320 IN MNP_INSTANCE_DATA *Instance,\r
1321 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk\r
1322 )\r
1323{\r
1324 MNP_SERVICE_DATA *MnpServiceData;\r
1325 MNP_GROUP_ADDRESS *GroupAddress;\r
1326\r
1327 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1328\r
1329 MnpServiceData = Instance->MnpServiceData;\r
1330 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);\r
1331\r
1332 //\r
1333 // Remove and free the CtrlBlk.\r
1334 //\r
1335 GroupAddress = CtrlBlk->GroupAddress;\r
e48e37fc 1336 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);\r
1337 gBS->FreePool (CtrlBlk);\r
8a67d61d 1338\r
1339 ASSERT (GroupAddress->RefCnt > 0);\r
1340\r
1341 //\r
1342 // Count down the RefCnt.\r
1343 //\r
1344 GroupAddress->RefCnt--;\r
1345\r
1346 if (GroupAddress->RefCnt == 0) {\r
1347 //\r
1348 // Free this GroupAddress entry if no instance uses it.\r
1349 //\r
1350 MnpServiceData->GroupAddressCount--;\r
e48e37fc 1351 RemoveEntryList (&GroupAddress->AddrEntry);\r
1352 gBS->FreePool (GroupAddress);\r
8a67d61d 1353\r
1354 return TRUE;\r
1355 }\r
1356\r
1357 return FALSE;\r
1358}\r
1359\r
1360\r
1361/**\r
1362 Do the group operations for this instance.\r
1363\r
1364 @param Instance Pointer to the instance context data.\r
1365 @param JoinFlag Set to TRUE to join a group. Set to TRUE to leave a\r
1366 group/groups.\r
1367 @param MacAddress Pointer to the group address to join or leave.\r
1368 @param CtrlBlk Pointer to the group control block if JoinFlag if\r
1369 FALSE.\r
1370\r
1371 @retval EFI_SUCCESS The group operation finished.\r
1372 @retval Other Some error occurs.\r
1373\r
1374**/\r
1375EFI_STATUS\r
1376MnpGroupOp (\r
1377 IN MNP_INSTANCE_DATA *Instance,\r
1378 IN BOOLEAN JoinFlag,\r
1379 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,\r
1380 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL\r
1381 )\r
1382{\r
1383 MNP_SERVICE_DATA *MnpServiceData;\r
e48e37fc 1384 LIST_ENTRY *Entry;\r
1385 LIST_ENTRY *NextEntry;\r
8a67d61d 1386 MNP_GROUP_ADDRESS *GroupAddress;\r
1387 EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
1388 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;\r
1389 EFI_STATUS Status;\r
1390 BOOLEAN AddressExist;\r
1391 BOOLEAN NeedUpdate;\r
1392\r
1393 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);\r
1394\r
1395 MnpServiceData = Instance->MnpServiceData;\r
1396 SnpMode = MnpServiceData->Snp->Mode;\r
1397\r
1398 if (JoinFlag) {\r
1399 //\r
1400 // A new gropu address is to be added.\r
1401 //\r
1402\r
1403 GroupAddress = NULL;\r
1404 AddressExist = FALSE;\r
1405\r
1406 //\r
1407 // Allocate memory for the control block.\r
1408 //\r
e48e37fc 1409 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));\r
8a67d61d 1410 if (NewCtrlBlk == NULL) {\r
1411\r
e48e37fc 1412 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));\r
8a67d61d 1413 return EFI_OUT_OF_RESOURCES;\r
1414 }\r
1415\r
1416 NET_LIST_FOR_EACH (Entry, &MnpServiceData->GroupAddressList) {\r
1417 //\r
1418 // Check whether the MacAddress is already joined by other instances.\r
1419 //\r
1420 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);\r
e48e37fc 1421 if (0 == CompareMem (\r
8a67d61d 1422 MacAddress,\r
1423 &GroupAddress->Address,\r
1424 SnpMode->HwAddressSize\r
1425 )) {\r
1426\r
1427 AddressExist = TRUE;\r
1428 break;\r
1429 }\r
1430 }\r
1431\r
1432 if (!AddressExist) {\r
1433 GroupAddress = NULL;\r
1434 }\r
1435\r
1436 //\r
1437 // Add the GroupAddress for this instance.\r
1438 //\r
1439 Status = MnpGroupOpAddCtrlBlk (\r
1440 Instance,\r
1441 NewCtrlBlk,\r
1442 GroupAddress,\r
1443 MacAddress,\r
1444 SnpMode->HwAddressSize\r
1445 );\r
1446 if (EFI_ERROR (Status)) {\r
1447\r
1448 return Status;\r
1449 }\r
1450\r
1451 NeedUpdate = TRUE;\r
1452 } else {\r
1453\r
1454 if (MacAddress != NULL) {\r
1455\r
1456 ASSERT (CtrlBlk != NULL);\r
1457\r
1458 //\r
1459 // Leave the specific multicast mac address.\r
1460 //\r
1461 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);\r
1462 } else {\r
1463 //\r
1464 // Leave all multicast mac addresses.\r
1465 //\r
1466 NeedUpdate = FALSE;\r
1467\r
1468 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {\r
1469\r
1470 NewCtrlBlk = NET_LIST_USER_STRUCT (\r
1471 Entry,\r
1472 MNP_GROUP_CONTROL_BLOCK,\r
1473 CtrlBlkEntry\r
1474 );\r
1475 //\r
1476 // Update is required if the group address left is no longer used\r
1477 // by other instances.\r
1478 //\r
1479 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);\r
1480 }\r
1481 }\r
1482 }\r
1483\r
1484 Status = EFI_SUCCESS;\r
1485\r
1486 if (NeedUpdate) {\r
1487 //\r
1488 // Reconfigure the receive filters if necessary.\r
1489 //\r
1490 Status = MnpConfigReceiveFilters (MnpServiceData);\r
1491 }\r
1492\r
1493 return Status;\r
1494}\r