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