]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpConfig.c
BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpConfig.c
1 /** @file
2 Implementation of Managed Network Protocol private services.
3
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include "MnpImpl.h"
10 #include "MnpVlan.h"
11
12 EFI_SERVICE_BINDING_PROTOCOL mMnpServiceBindingProtocol = {
13 MnpServiceBindingCreateChild,
14 MnpServiceBindingDestroyChild
15 };
16
17 EFI_MANAGED_NETWORK_PROTOCOL mMnpProtocolTemplate = {
18 MnpGetModeData,
19 MnpConfigure,
20 MnpMcastIpToMac,
21 MnpGroups,
22 MnpTransmit,
23 MnpReceive,
24 MnpCancel,
25 MnpPoll
26 };
27
28 EFI_MANAGED_NETWORK_CONFIG_DATA mMnpDefaultConfigData = {
29 10000000,
30 10000000,
31 0,
32 FALSE,
33 FALSE,
34 FALSE,
35 FALSE,
36 FALSE,
37 FALSE,
38 FALSE
39 };
40
41 /**
42 Add Count of net buffers to MnpDeviceData->FreeNbufQue. The length of the net
43 buffer is specified by MnpDeviceData->BufferLength.
44
45 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
46 @param[in] Count Number of NET_BUFFERs to add.
47
48 @retval EFI_SUCCESS The specified amount of NET_BUFs are allocated
49 and added to MnpDeviceData->FreeNbufQue.
50 @retval EFI_OUT_OF_RESOURCES Failed to allocate a NET_BUF structure.
51
52 **/
53 EFI_STATUS
54 MnpAddFreeNbuf (
55 IN OUT MNP_DEVICE_DATA *MnpDeviceData,
56 IN UINTN Count
57 )
58 {
59 EFI_STATUS Status;
60 UINTN Index;
61 NET_BUF *Nbuf;
62
63 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
64 ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));
65
66 Status = EFI_SUCCESS;
67 for (Index = 0; Index < Count; Index++) {
68 Nbuf = NetbufAlloc (MnpDeviceData->BufferLength + MnpDeviceData->PaddingSize);
69 if (Nbuf == NULL) {
70 DEBUG ((EFI_D_ERROR, "MnpAddFreeNbuf: NetBufAlloc failed.\n"));
71
72 Status = EFI_OUT_OF_RESOURCES;
73 break;
74 }
75
76 if (MnpDeviceData->PaddingSize > 0) {
77 //
78 // Pad padding bytes before the media header
79 //
80 NetbufAllocSpace (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_TAIL);
81 NetbufTrim (Nbuf, MnpDeviceData->PaddingSize, NET_BUF_HEAD);
82 }
83
84 NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);
85 }
86
87 MnpDeviceData->NbufCnt += Index;
88 return Status;
89 }
90
91
92 /**
93 Allocate a free NET_BUF from MnpDeviceData->FreeNbufQue. If there is none
94 in the queue, first try to allocate some and add them into the queue, then
95 fetch the NET_BUF from the updated FreeNbufQue.
96
97 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
98
99 @return Pointer to the allocated free NET_BUF structure, if NULL the
100 operation is failed.
101
102 **/
103 NET_BUF *
104 MnpAllocNbuf (
105 IN OUT MNP_DEVICE_DATA *MnpDeviceData
106 )
107 {
108 EFI_STATUS Status;
109 NET_BUF_QUEUE *FreeNbufQue;
110 NET_BUF *Nbuf;
111 EFI_TPL OldTpl;
112
113 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
114
115 FreeNbufQue = &MnpDeviceData->FreeNbufQue;
116 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
117
118 //
119 // Check whether there are available buffers, or else try to add some.
120 //
121 if (FreeNbufQue->BufNum == 0) {
122 if ((MnpDeviceData->NbufCnt + MNP_NET_BUFFER_INCREASEMENT) > MNP_MAX_NET_BUFFER_NUM) {
123 DEBUG (
124 (EFI_D_ERROR,
125 "MnpAllocNbuf: The maximum NET_BUF size is reached for MNP driver instance %p.\n",
126 MnpDeviceData)
127 );
128
129 Nbuf = NULL;
130 goto ON_EXIT;
131 }
132
133 Status = MnpAddFreeNbuf (MnpDeviceData, MNP_NET_BUFFER_INCREASEMENT);
134 if (EFI_ERROR (Status)) {
135 DEBUG (
136 (EFI_D_ERROR,
137 "MnpAllocNbuf: Failed to add NET_BUFs into the FreeNbufQue, %r.\n",
138 Status)
139 );
140
141 //
142 // Don't return NULL, perhaps MnpAddFreeNbuf does add some NET_BUFs but
143 // the amount is less than MNP_NET_BUFFER_INCREASEMENT.
144 //
145 }
146 }
147
148 Nbuf = NetbufQueRemove (FreeNbufQue);
149
150 //
151 // Increase the RefCnt.
152 //
153 if (Nbuf != NULL) {
154 NET_GET_REF (Nbuf);
155 }
156
157 ON_EXIT:
158 gBS->RestoreTPL (OldTpl);
159
160 return Nbuf;
161 }
162
163
164 /**
165 Try to reclaim the Nbuf into the buffer pool.
166
167 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
168 @param[in, out] Nbuf Pointer to the NET_BUF to free.
169
170 **/
171 VOID
172 MnpFreeNbuf (
173 IN OUT MNP_DEVICE_DATA *MnpDeviceData,
174 IN OUT NET_BUF *Nbuf
175 )
176 {
177 EFI_TPL OldTpl;
178
179 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
180 ASSERT (Nbuf->RefCnt > 1);
181
182 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
183
184 NET_PUT_REF (Nbuf);
185
186 if (Nbuf->RefCnt == 1) {
187 //
188 // Trim all buffer contained in the Nbuf, then append it to the NbufQue.
189 //
190 NetbufTrim (Nbuf, Nbuf->TotalSize, NET_BUF_TAIL);
191
192 if (NetbufAllocSpace (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_HEAD) != NULL) {
193 //
194 // There is space reserved for vlan tag in the head, reclaim it
195 //
196 NetbufTrim (Nbuf, NET_VLAN_TAG_LEN, NET_BUF_TAIL);
197 }
198
199 NetbufQueAppend (&MnpDeviceData->FreeNbufQue, Nbuf);
200 }
201
202 gBS->RestoreTPL (OldTpl);
203 }
204
205 /**
206 Add Count of TX buffers to MnpDeviceData->AllTxBufList and MnpDeviceData->FreeTxBufList.
207 The length of the buffer is specified by MnpDeviceData->BufferLength.
208
209 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
210 @param[in] Count Number of TX buffers to add.
211
212 @retval EFI_SUCCESS The specified amount of TX buffers are allocated.
213 @retval EFI_OUT_OF_RESOURCES Failed to allocate a TX buffer.
214
215 **/
216 EFI_STATUS
217 MnpAddFreeTxBuf (
218 IN OUT MNP_DEVICE_DATA *MnpDeviceData,
219 IN UINTN Count
220 )
221 {
222 EFI_STATUS Status;
223 UINT32 Index;
224 MNP_TX_BUF_WRAP *TxBufWrap;
225
226 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
227 ASSERT ((Count > 0) && (MnpDeviceData->BufferLength > 0));
228
229 Status = EFI_SUCCESS;
230 for (Index = 0; Index < Count; Index++) {
231 TxBufWrap = (MNP_TX_BUF_WRAP*) AllocatePool (OFFSET_OF (MNP_TX_BUF_WRAP, TxBuf) + MnpDeviceData->BufferLength );
232 if (TxBufWrap == NULL) {
233 DEBUG ((EFI_D_ERROR, "MnpAddFreeTxBuf: TxBuf Alloc failed.\n"));
234
235 Status = EFI_OUT_OF_RESOURCES;
236 break;
237 }
238 DEBUG ((EFI_D_INFO, "MnpAddFreeTxBuf: Add TxBufWrap %p, TxBuf %p\n", TxBufWrap, TxBufWrap->TxBuf));
239 TxBufWrap->Signature = MNP_TX_BUF_WRAP_SIGNATURE;
240 TxBufWrap->InUse = FALSE;
241 InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);
242 InsertTailList (&MnpDeviceData->AllTxBufList, &TxBufWrap->AllEntry);
243 }
244
245 MnpDeviceData->TxBufCount += Index;
246 return Status;
247 }
248
249 /**
250 Allocate a free TX buffer from MnpDeviceData->FreeTxBufList. If there is none
251 in the queue, first try to recycle some from SNP, then try to allocate some and add
252 them into the queue, then fetch the NET_BUF from the updated FreeTxBufList.
253
254 @param[in, out] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
255
256 @return Pointer to the allocated free NET_BUF structure, if NULL the
257 operation is failed.
258
259 **/
260 UINT8 *
261 MnpAllocTxBuf (
262 IN OUT MNP_DEVICE_DATA *MnpDeviceData
263 )
264 {
265 EFI_TPL OldTpl;
266 UINT8 *TxBuf;
267 EFI_STATUS Status;
268 LIST_ENTRY *Entry;
269 MNP_TX_BUF_WRAP *TxBufWrap;
270
271 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
272
273 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
274
275 if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
276 //
277 // First try to recycle some TX buffer from SNP
278 //
279 Status = MnpRecycleTxBuf (MnpDeviceData);
280 if (EFI_ERROR (Status)) {
281 TxBuf = NULL;
282 goto ON_EXIT;
283 }
284
285 //
286 // If still no free TX buffer, allocate more.
287 //
288 if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
289 if ((MnpDeviceData->TxBufCount + MNP_TX_BUFFER_INCREASEMENT) > MNP_MAX_TX_BUFFER_NUM) {
290 DEBUG (
291 (EFI_D_ERROR,
292 "MnpAllocTxBuf: The maximum TxBuf size is reached for MNP driver instance %p.\n",
293 MnpDeviceData)
294 );
295
296 TxBuf = NULL;
297 goto ON_EXIT;
298 }
299
300 Status = MnpAddFreeTxBuf (MnpDeviceData, MNP_TX_BUFFER_INCREASEMENT);
301 if (IsListEmpty (&MnpDeviceData->FreeTxBufList)) {
302 DEBUG (
303 (EFI_D_ERROR,
304 "MnpAllocNbuf: Failed to add TxBuf into the FreeTxBufList, %r.\n",
305 Status)
306 );
307
308 TxBuf = NULL;
309 goto ON_EXIT;
310 }
311 }
312 }
313
314 ASSERT (!IsListEmpty (&MnpDeviceData->FreeTxBufList));
315 Entry = MnpDeviceData->FreeTxBufList.ForwardLink;
316 RemoveEntryList (MnpDeviceData->FreeTxBufList.ForwardLink);
317 TxBufWrap = NET_LIST_USER_STRUCT_S (Entry, MNP_TX_BUF_WRAP, WrapEntry, MNP_TX_BUF_WRAP_SIGNATURE);
318 TxBufWrap->InUse = TRUE;
319 TxBuf = TxBufWrap->TxBuf;
320
321 ON_EXIT:
322 gBS->RestoreTPL (OldTpl);
323
324 return TxBuf;
325 }
326
327 /**
328 Try to reclaim the TX buffer into the buffer pool.
329
330 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
331 @param[in, out] TxBuf Pointer to the TX buffer to free.
332
333 **/
334 VOID
335 MnpFreeTxBuf (
336 IN OUT MNP_DEVICE_DATA *MnpDeviceData,
337 IN OUT UINT8 *TxBuf
338 )
339 {
340 MNP_TX_BUF_WRAP *TxBufWrap;
341 EFI_TPL OldTpl;
342
343 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
344
345 if (TxBuf == NULL) {
346 return;
347 }
348
349 TxBufWrap = NET_LIST_USER_STRUCT (TxBuf, MNP_TX_BUF_WRAP, TxBuf);
350 if (TxBufWrap->Signature != MNP_TX_BUF_WRAP_SIGNATURE) {
351 DEBUG (
352 (EFI_D_ERROR,
353 "MnpFreeTxBuf: Signature check failed in MnpFreeTxBuf.\n")
354 );
355 return;
356 }
357
358 if (!TxBufWrap->InUse) {
359 DEBUG (
360 (EFI_D_WARN,
361 "MnpFreeTxBuf: Duplicated recycle report from SNP.\n")
362 );
363 return;
364 }
365
366 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
367 InsertTailList (&MnpDeviceData->FreeTxBufList, &TxBufWrap->WrapEntry);
368 TxBufWrap->InUse = FALSE;
369 gBS->RestoreTPL (OldTpl);
370 }
371
372 /**
373 Try to recycle all the transmitted buffer address from SNP.
374
375 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
376
377 @retval EFI_SUCCESS Successed to recyclethe transmitted buffer address.
378 @retval Others Failed to recyclethe transmitted buffer address.
379
380 **/
381 EFI_STATUS
382 MnpRecycleTxBuf (
383 IN OUT MNP_DEVICE_DATA *MnpDeviceData
384 )
385 {
386 UINT8 *TxBuf;
387 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
388 EFI_STATUS Status;
389
390 Snp = MnpDeviceData->Snp;
391 ASSERT (Snp != NULL);
392
393 do {
394 TxBuf = NULL;
395 Status = Snp->GetStatus (Snp, NULL, (VOID **) &TxBuf);
396 if (EFI_ERROR (Status)) {
397 return Status;
398 }
399
400 if (TxBuf != NULL) {
401 MnpFreeTxBuf (MnpDeviceData, TxBuf);
402 }
403 } while (TxBuf != NULL);
404
405 return EFI_SUCCESS;
406 }
407
408 /**
409 Initialize the mnp device context data.
410
411 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
412 @param[in] ImageHandle The driver image handle.
413 @param[in] ControllerHandle Handle of device to bind driver to.
414
415 @retval EFI_SUCCESS The mnp service context is initialized.
416 @retval EFI_UNSUPPORTED ControllerHandle does not support Simple Network Protocol.
417 @retval Others Other errors as indicated.
418
419 **/
420 EFI_STATUS
421 MnpInitializeDeviceData (
422 IN OUT MNP_DEVICE_DATA *MnpDeviceData,
423 IN EFI_HANDLE ImageHandle,
424 IN EFI_HANDLE ControllerHandle
425 )
426 {
427 EFI_STATUS Status;
428 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
429 EFI_SIMPLE_NETWORK_MODE *SnpMode;
430
431 MnpDeviceData->Signature = MNP_DEVICE_DATA_SIGNATURE;
432 MnpDeviceData->ImageHandle = ImageHandle;
433 MnpDeviceData->ControllerHandle = ControllerHandle;
434
435 //
436 // Copy the MNP Protocol interfaces from the template.
437 //
438 CopyMem (&MnpDeviceData->VlanConfig, &mVlanConfigProtocolTemplate, sizeof (EFI_VLAN_CONFIG_PROTOCOL));
439
440 //
441 // Open the Simple Network protocol.
442 //
443 Status = gBS->OpenProtocol (
444 ControllerHandle,
445 &gEfiSimpleNetworkProtocolGuid,
446 (VOID **) &Snp,
447 ImageHandle,
448 ControllerHandle,
449 EFI_OPEN_PROTOCOL_BY_DRIVER
450 );
451 if (EFI_ERROR (Status)) {
452 return EFI_UNSUPPORTED;
453 }
454
455 //
456 // Get MTU from Snp.
457 //
458 SnpMode = Snp->Mode;
459 MnpDeviceData->Snp = Snp;
460
461 //
462 // Initialize the lists.
463 //
464 InitializeListHead (&MnpDeviceData->ServiceList);
465 InitializeListHead (&MnpDeviceData->GroupAddressList);
466
467 //
468 // Get the buffer length used to allocate NET_BUF to hold data received
469 // from SNP. Do this before fill the FreeNetBufQue.
470 //
471 //
472 MnpDeviceData->BufferLength = SnpMode->MediaHeaderSize + NET_VLAN_TAG_LEN + SnpMode->MaxPacketSize + NET_ETHER_FCS_SIZE;
473
474 //
475 // Make sure the protocol headers immediately following the media header
476 // 4-byte aligned, and also preserve additional space for VLAN tag
477 //
478 MnpDeviceData->PaddingSize = ((4 - SnpMode->MediaHeaderSize) & 0x3) + NET_VLAN_TAG_LEN;
479
480 //
481 // Initialize MAC string which will be used as VLAN configuration variable name
482 //
483 Status = NetLibGetMacString (ControllerHandle, ImageHandle, &MnpDeviceData->MacString);
484 if (EFI_ERROR (Status)) {
485 goto ERROR;
486 }
487
488 //
489 // Initialize the FreeNetBufQue and pre-allocate some NET_BUFs.
490 //
491 NetbufQueInit (&MnpDeviceData->FreeNbufQue);
492 Status = MnpAddFreeNbuf (MnpDeviceData, MNP_INIT_NET_BUFFER_NUM);
493 if (EFI_ERROR (Status)) {
494 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: MnpAddFreeNbuf failed, %r.\n", Status));
495
496 goto ERROR;
497 }
498
499 //
500 // Get one NET_BUF from the FreeNbufQue for rx cache.
501 //
502 MnpDeviceData->RxNbufCache = MnpAllocNbuf (MnpDeviceData);
503 NetbufAllocSpace (
504 MnpDeviceData->RxNbufCache,
505 MnpDeviceData->BufferLength,
506 NET_BUF_TAIL
507 );
508
509 //
510 // Allocate buffer pool for tx.
511 //
512 InitializeListHead (&MnpDeviceData->FreeTxBufList);
513 InitializeListHead (&MnpDeviceData->AllTxBufList);
514 MnpDeviceData->TxBufCount = 0;
515
516 //
517 // Create the system poll timer.
518 //
519 Status = gBS->CreateEvent (
520 EVT_NOTIFY_SIGNAL | EVT_TIMER,
521 TPL_CALLBACK,
522 MnpSystemPoll,
523 MnpDeviceData,
524 &MnpDeviceData->PollTimer
525 );
526 if (EFI_ERROR (Status)) {
527 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for poll timer failed.\n"));
528
529 goto ERROR;
530 }
531
532 //
533 // Create the timer for packet timeout check.
534 //
535 Status = gBS->CreateEvent (
536 EVT_NOTIFY_SIGNAL | EVT_TIMER,
537 TPL_CALLBACK,
538 MnpCheckPacketTimeout,
539 MnpDeviceData,
540 &MnpDeviceData->TimeoutCheckTimer
541 );
542 if (EFI_ERROR (Status)) {
543 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for packet timeout check failed.\n"));
544
545 goto ERROR;
546 }
547
548 //
549 // Create the timer for media detection.
550 //
551 Status = gBS->CreateEvent (
552 EVT_NOTIFY_SIGNAL | EVT_TIMER,
553 TPL_CALLBACK,
554 MnpCheckMediaStatus,
555 MnpDeviceData,
556 &MnpDeviceData->MediaDetectTimer
557 );
558 if (EFI_ERROR (Status)) {
559 DEBUG ((EFI_D_ERROR, "MnpInitializeDeviceData: CreateEvent for media detection failed.\n"));
560
561 goto ERROR;
562 }
563
564 ERROR:
565 if (EFI_ERROR (Status)) {
566 //
567 // Free the dynamic allocated resources if necessary.
568 //
569 if (MnpDeviceData->MacString != NULL) {
570 FreePool (MnpDeviceData->MacString);
571 }
572
573 if (MnpDeviceData->TimeoutCheckTimer != NULL) {
574 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);
575 }
576
577 if (MnpDeviceData->MediaDetectTimer != NULL) {
578 gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);
579 }
580
581 if (MnpDeviceData->PollTimer != NULL) {
582 gBS->CloseEvent (MnpDeviceData->PollTimer);
583 }
584
585 if (MnpDeviceData->RxNbufCache != NULL) {
586 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);
587 }
588
589 if (MnpDeviceData->FreeNbufQue.BufNum != 0) {
590 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);
591 }
592
593 //
594 // Close the Simple Network Protocol.
595 //
596 gBS->CloseProtocol (
597 ControllerHandle,
598 &gEfiSimpleNetworkProtocolGuid,
599 ImageHandle,
600 ControllerHandle
601 );
602 }
603
604 return Status;
605 }
606
607
608 /**
609 Destroy the MNP device context data.
610
611 @param[in, out] MnpDeviceData Pointer to the mnp device context data.
612 @param[in] ImageHandle The driver image handle.
613
614 **/
615 VOID
616 MnpDestroyDeviceData (
617 IN OUT MNP_DEVICE_DATA *MnpDeviceData,
618 IN EFI_HANDLE ImageHandle
619 )
620 {
621 LIST_ENTRY *Entry;
622 LIST_ENTRY *NextEntry;
623 MNP_TX_BUF_WRAP *TxBufWrap;
624
625 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
626
627 //
628 // Free Vlan Config variable name string
629 //
630 if (MnpDeviceData->MacString != NULL) {
631 FreePool (MnpDeviceData->MacString);
632 }
633
634 //
635 // The GroupAddressList must be empty.
636 //
637 ASSERT (IsListEmpty (&MnpDeviceData->GroupAddressList));
638
639 //
640 // Close the event.
641 //
642 gBS->CloseEvent (MnpDeviceData->TimeoutCheckTimer);
643 gBS->CloseEvent (MnpDeviceData->MediaDetectTimer);
644 gBS->CloseEvent (MnpDeviceData->PollTimer);
645
646 //
647 // Free the Tx buffer pool.
648 //
649 NET_LIST_FOR_EACH_SAFE(Entry, NextEntry, &MnpDeviceData->AllTxBufList) {
650 TxBufWrap = NET_LIST_USER_STRUCT (Entry, MNP_TX_BUF_WRAP, AllEntry);
651 RemoveEntryList (Entry);
652 FreePool (TxBufWrap);
653 MnpDeviceData->TxBufCount--;
654 }
655 ASSERT (IsListEmpty (&MnpDeviceData->AllTxBufList));
656 ASSERT (MnpDeviceData->TxBufCount == 0);
657
658 //
659 // Free the RxNbufCache.
660 //
661 MnpFreeNbuf (MnpDeviceData, MnpDeviceData->RxNbufCache);
662
663 //
664 // Flush the FreeNbufQue.
665 //
666 MnpDeviceData->NbufCnt -= MnpDeviceData->FreeNbufQue.BufNum;
667 NetbufQueFlush (&MnpDeviceData->FreeNbufQue);
668
669 //
670 // Close the Simple Network Protocol.
671 //
672 gBS->CloseProtocol (
673 MnpDeviceData->ControllerHandle,
674 &gEfiSimpleNetworkProtocolGuid,
675 ImageHandle,
676 MnpDeviceData->ControllerHandle
677 );
678 }
679
680
681 /**
682 Create mnp service context data.
683
684 @param[in] MnpDeviceData Pointer to the mnp device context data.
685 @param[in] VlanId The VLAN ID.
686 @param[in] Priority The VLAN priority. If VlanId is 0,
687 Priority is ignored.
688
689 @return A pointer to MNP_SERVICE_DATA or NULL if failed to create MNP service context.
690
691 **/
692 MNP_SERVICE_DATA *
693 MnpCreateServiceData (
694 IN MNP_DEVICE_DATA *MnpDeviceData,
695 IN UINT16 VlanId,
696 IN UINT8 Priority OPTIONAL
697 )
698 {
699 EFI_HANDLE MnpServiceHandle;
700 MNP_SERVICE_DATA *MnpServiceData;
701 EFI_STATUS Status;
702 EFI_SIMPLE_NETWORK_MODE *SnpMode;
703 EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
704
705 //
706 // Initialize the Mnp Service Data.
707 //
708 MnpServiceData = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));
709 if (MnpServiceData == NULL) {
710 DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to allocate memory for the new Mnp Service Data.\n"));
711
712 return NULL;
713 }
714
715 //
716 // Add to MNP service list
717 //
718 InsertTailList (&MnpDeviceData->ServiceList, &MnpServiceData->Link);
719
720 MnpServiceData->Signature = MNP_SERVICE_DATA_SIGNATURE;
721 MnpServiceData->MnpDeviceData = MnpDeviceData;
722
723 //
724 // Copy the ServiceBinding structure.
725 //
726 CopyMem (&MnpServiceData->ServiceBinding, &mMnpServiceBindingProtocol, sizeof (EFI_SERVICE_BINDING_PROTOCOL));
727
728 //
729 // Initialize the lists.
730 //
731 InitializeListHead (&MnpServiceData->ChildrenList);
732
733 SnpMode = MnpDeviceData->Snp->Mode;
734 if (VlanId != 0) {
735 //
736 // Create VLAN child handle
737 //
738 MnpServiceHandle = MnpCreateVlanChild (
739 MnpDeviceData->ImageHandle,
740 MnpDeviceData->ControllerHandle,
741 VlanId,
742 &MnpServiceData->DevicePath
743 );
744 if (MnpServiceHandle == NULL) {
745 DEBUG ((EFI_D_ERROR, "MnpCreateServiceData: Faild to create child handle.\n"));
746
747 return NULL;
748 }
749
750 //
751 // Open VLAN Config Protocol by child
752 //
753 Status = gBS->OpenProtocol (
754 MnpDeviceData->ControllerHandle,
755 &gEfiVlanConfigProtocolGuid,
756 (VOID **) &VlanConfig,
757 MnpDeviceData->ImageHandle,
758 MnpServiceHandle,
759 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
760 );
761 if (EFI_ERROR (Status)) {
762 goto Exit;
763 }
764
765 //
766 // Reduce MTU for VLAN device
767 //
768 MnpServiceData->Mtu = SnpMode->MaxPacketSize - NET_VLAN_TAG_LEN;
769 } else {
770 //
771 // VlanId set to 0 means rx/tx untagged frame
772 //
773 MnpServiceHandle = MnpDeviceData->ControllerHandle;
774 MnpServiceData->Mtu = SnpMode->MaxPacketSize;
775 }
776
777 MnpServiceData->ServiceHandle = MnpServiceHandle;
778 MnpServiceData->VlanId = VlanId;
779 MnpServiceData->Priority = Priority;
780
781 //
782 // Install the MNP Service Binding Protocol
783 //
784 Status = gBS->InstallMultipleProtocolInterfaces (
785 &MnpServiceHandle,
786 &gEfiManagedNetworkServiceBindingProtocolGuid,
787 &MnpServiceData->ServiceBinding,
788 NULL
789 );
790
791 Exit:
792 if (EFI_ERROR (Status)) {
793 MnpDestroyServiceData (MnpServiceData);
794 MnpServiceData = NULL;
795 }
796
797 return MnpServiceData;
798 }
799
800 /**
801 Destroy the MNP service context data.
802
803 @param[in, out] MnpServiceData Pointer to the mnp service context data.
804
805 @retval EFI_SUCCESS The mnp service context is destroyed.
806 @retval Others Errors as indicated.
807
808 **/
809 EFI_STATUS
810 MnpDestroyServiceData (
811 IN OUT MNP_SERVICE_DATA *MnpServiceData
812 )
813 {
814 EFI_STATUS Status;
815
816 //
817 // Uninstall the MNP Service Binding Protocol
818 //
819 Status = gBS->UninstallMultipleProtocolInterfaces (
820 MnpServiceData->ServiceHandle,
821 &gEfiManagedNetworkServiceBindingProtocolGuid,
822 &MnpServiceData->ServiceBinding,
823 NULL
824 );
825 if (EFI_ERROR (Status)) {
826 return Status;
827 }
828
829 if (MnpServiceData->VlanId != 0) {
830 //
831 // Close VlanConfig Protocol opened by VLAN child handle
832 //
833 Status = gBS->CloseProtocol (
834 MnpServiceData->MnpDeviceData->ControllerHandle,
835 &gEfiVlanConfigProtocolGuid,
836 MnpServiceData->MnpDeviceData->ImageHandle,
837 MnpServiceData->ServiceHandle
838 );
839 if (EFI_ERROR (Status)) {
840 return Status;
841 }
842
843 //
844 // Uninstall Device Path Protocol to destroy the VLAN child handle
845 //
846 Status = gBS->UninstallMultipleProtocolInterfaces (
847 MnpServiceData->ServiceHandle,
848 &gEfiDevicePathProtocolGuid,
849 MnpServiceData->DevicePath,
850 NULL
851 );
852 if (EFI_ERROR (Status)) {
853 return Status;
854 }
855
856 if (MnpServiceData->DevicePath != NULL) {
857 FreePool (MnpServiceData->DevicePath);
858 }
859 }
860
861 //
862 // Remove from MnpDeviceData service list
863 //
864 RemoveEntryList (&MnpServiceData->Link);
865
866 FreePool (MnpServiceData);
867
868 return Status;
869 }
870
871 /**
872 Callback function which provided by user to remove one node in NetDestroyLinkList process.
873
874 @param[in] Entry The entry to be removed.
875 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
876
877 @retval EFI_SUCCESS The entry has been removed successfully.
878 @retval Others Fail to remove the entry.
879
880 **/
881 EFI_STATUS
882 EFIAPI
883 MnpDestoryChildEntry (
884 IN LIST_ENTRY *Entry,
885 IN VOID *Context
886 )
887 {
888 MNP_INSTANCE_DATA *Instance;
889 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
890
891 ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *) Context;
892 Instance = CR (Entry, MNP_INSTANCE_DATA, InstEntry, MNP_INSTANCE_DATA_SIGNATURE);
893 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
894 }
895
896 /**
897 Destroy all child of the MNP service data.
898
899 @param[in, out] MnpServiceData Pointer to the mnp service context data.
900
901 @retval EFI_SUCCESS All child are destroyed.
902 @retval Others Failed to destroy all child.
903
904 **/
905 EFI_STATUS
906 MnpDestroyServiceChild (
907 IN OUT MNP_SERVICE_DATA *MnpServiceData
908 )
909 {
910 LIST_ENTRY *List;
911 EFI_STATUS Status;
912 UINTN ListLength;
913
914 List = &MnpServiceData->ChildrenList;
915
916 Status = NetDestroyLinkList (
917 List,
918 MnpDestoryChildEntry,
919 &MnpServiceData->ServiceBinding,
920 &ListLength
921 );
922 if (EFI_ERROR (Status) || ListLength != 0) {
923 return EFI_DEVICE_ERROR;
924 }
925
926 return EFI_SUCCESS;
927 }
928
929 /**
930 Find the MNP Service Data for given VLAN ID.
931
932 @param[in] MnpDeviceData Pointer to the mnp device context data.
933 @param[in] VlanId The VLAN ID.
934
935 @return A pointer to MNP_SERVICE_DATA or NULL if not found.
936
937 **/
938 MNP_SERVICE_DATA *
939 MnpFindServiceData (
940 IN MNP_DEVICE_DATA *MnpDeviceData,
941 IN UINT16 VlanId
942 )
943 {
944 LIST_ENTRY *Entry;
945 MNP_SERVICE_DATA *MnpServiceData;
946
947 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {
948 //
949 // Check VLAN ID of each Mnp Service Data
950 //
951 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
952 if (MnpServiceData->VlanId == VlanId) {
953 return MnpServiceData;
954 }
955 }
956
957 return NULL;
958 }
959
960 /**
961 Initialize the mnp instance context data.
962
963 @param[in] MnpServiceData Pointer to the mnp service context data.
964 @param[in, out] Instance Pointer to the mnp instance context data
965 to initialize.
966
967 **/
968 VOID
969 MnpInitializeInstanceData (
970 IN MNP_SERVICE_DATA *MnpServiceData,
971 IN OUT MNP_INSTANCE_DATA *Instance
972 )
973 {
974 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
975 ASSERT (Instance != NULL);
976
977 //
978 // Set the signature.
979 //
980 Instance->Signature = MNP_INSTANCE_DATA_SIGNATURE;
981
982 //
983 // Copy the MNP Protocol interfaces from the template.
984 //
985 CopyMem (&Instance->ManagedNetwork, &mMnpProtocolTemplate, sizeof (Instance->ManagedNetwork));
986
987 //
988 // Copy the default config data.
989 //
990 CopyMem (&Instance->ConfigData, &mMnpDefaultConfigData, sizeof (Instance->ConfigData));
991
992 //
993 // Initialize the lists.
994 //
995 InitializeListHead (&Instance->GroupCtrlBlkList);
996 InitializeListHead (&Instance->RcvdPacketQueue);
997 InitializeListHead (&Instance->RxDeliveredPacketQueue);
998
999 //
1000 // Initialize the RxToken Map.
1001 //
1002 NetMapInit (&Instance->RxTokenMap);
1003
1004 //
1005 // Save the MnpServiceData info.
1006 //
1007 Instance->MnpServiceData = MnpServiceData;
1008 }
1009
1010
1011 /**
1012 Check whether the token specified by Arg matches the token in Item.
1013
1014 @param[in] Map Pointer to the NET_MAP.
1015 @param[in] Item Pointer to the NET_MAP_ITEM.
1016 @param[in] Arg Pointer to the Arg, it's a pointer to the token to
1017 check.
1018
1019 @retval EFI_SUCCESS The token specified by Arg is different from the
1020 token in Item.
1021 @retval EFI_ACCESS_DENIED The token specified by Arg is the same as that in
1022 Item.
1023
1024 **/
1025 EFI_STATUS
1026 EFIAPI
1027 MnpTokenExist (
1028 IN NET_MAP *Map,
1029 IN NET_MAP_ITEM *Item,
1030 IN VOID *Arg
1031 )
1032 {
1033 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token;
1034 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenInItem;
1035
1036 Token = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Arg;
1037 TokenInItem = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
1038
1039 if ((Token == TokenInItem) || (Token->Event == TokenInItem->Event)) {
1040 //
1041 // The token is the same either the two tokens equals or the Events in
1042 // the two tokens are the same.
1043 //
1044 return EFI_ACCESS_DENIED;
1045 }
1046
1047 return EFI_SUCCESS;
1048 }
1049
1050 /**
1051 Cancel the token specified by Arg if it matches the token in Item.
1052
1053 @param[in, out] Map Pointer to the NET_MAP.
1054 @param[in, out] Item Pointer to the NET_MAP_ITEM.
1055 @param[in] Arg Pointer to the Arg, it's a pointer to the
1056 token to cancel.
1057
1058 @retval EFI_SUCCESS The Arg is NULL, and the token in Item is cancelled,
1059 or the Arg isn't NULL, and the token in Item is
1060 different from the Arg.
1061 @retval EFI_ABORTED The Arg isn't NULL, the token in Item mathces the
1062 Arg, and the token is cancelled.
1063
1064 **/
1065 EFI_STATUS
1066 EFIAPI
1067 MnpCancelTokens (
1068 IN OUT NET_MAP *Map,
1069 IN OUT NET_MAP_ITEM *Item,
1070 IN VOID *Arg
1071 )
1072 {
1073 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TokenToCancel;
1074
1075 if ((Arg != NULL) && (Item->Key != Arg)) {
1076 //
1077 // The token in Item is not the token specified by Arg.
1078 //
1079 return EFI_SUCCESS;
1080 }
1081
1082 TokenToCancel = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *) Item->Key;
1083
1084 //
1085 // Remove the item from the map.
1086 //
1087 NetMapRemoveItem (Map, Item, NULL);
1088
1089 //
1090 // Cancel this token with status set to EFI_ABORTED.
1091 //
1092 TokenToCancel->Status = EFI_ABORTED;
1093 gBS->SignalEvent (TokenToCancel->Event);
1094
1095 if (Arg != NULL) {
1096 //
1097 // Only abort the token specified by Arg if Arg isn't NULL.
1098 //
1099 return EFI_ABORTED;
1100 }
1101
1102 return EFI_SUCCESS;
1103 }
1104
1105
1106 /**
1107 Start and initialize the simple network.
1108
1109 @param[in] Snp Pointer to the simple network protocol.
1110
1111 @retval EFI_SUCCESS The simple network protocol is started.
1112 @retval Others Other errors as indicated.
1113
1114 **/
1115 EFI_STATUS
1116 MnpStartSnp (
1117 IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
1118 )
1119 {
1120 EFI_STATUS Status;
1121
1122 ASSERT (Snp != NULL);
1123
1124 //
1125 // Start the simple network.
1126 //
1127 Status = Snp->Start (Snp);
1128
1129 if (!EFI_ERROR (Status)) {
1130 //
1131 // Initialize the simple network.
1132 //
1133 Status = Snp->Initialize (Snp, 0, 0);
1134 }
1135
1136 return Status;
1137 }
1138
1139
1140 /**
1141 Stop the simple network.
1142
1143 @param[in] MnpDeviceData Pointer to the MNP_DEVICE_DATA.
1144
1145 @retval EFI_SUCCESS The simple network is stopped.
1146 @retval Others Other errors as indicated.
1147
1148 **/
1149 EFI_STATUS
1150 MnpStopSnp (
1151 IN MNP_DEVICE_DATA *MnpDeviceData
1152 )
1153 {
1154 EFI_STATUS Status;
1155 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
1156
1157 Snp = MnpDeviceData->Snp;
1158 ASSERT (Snp != NULL);
1159
1160 //
1161 // Recycle all the transmit buffer from SNP.
1162 //
1163 Status = MnpRecycleTxBuf (MnpDeviceData);
1164 if (EFI_ERROR (Status)) {
1165 return Status;
1166 }
1167
1168 //
1169 // Shut down the simple network.
1170 //
1171 Status = Snp->Shutdown (Snp);
1172 if (!EFI_ERROR (Status)) {
1173 //
1174 // Stop the simple network.
1175 //
1176 Status = Snp->Stop (Snp);
1177 }
1178
1179 return Status;
1180 }
1181
1182
1183 /**
1184 Start the managed network, this function is called when one instance is configured
1185 or reconfigured.
1186
1187 @param[in, out] MnpServiceData Pointer to the mnp service context data.
1188 @param[in] IsConfigUpdate The instance is reconfigured or it's the first
1189 time the instanced is configured.
1190 @param[in] EnableSystemPoll Enable the system polling or not.
1191
1192 @retval EFI_SUCCESS The managed network is started and some
1193 configuration is updated.
1194 @retval Others Other errors as indicated.
1195
1196 **/
1197 EFI_STATUS
1198 MnpStart (
1199 IN OUT MNP_SERVICE_DATA *MnpServiceData,
1200 IN BOOLEAN IsConfigUpdate,
1201 IN BOOLEAN EnableSystemPoll
1202 )
1203 {
1204 EFI_STATUS Status;
1205 EFI_TIMER_DELAY TimerOpType;
1206 MNP_DEVICE_DATA *MnpDeviceData;
1207
1208 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1209
1210 Status = EFI_SUCCESS;
1211 MnpDeviceData = MnpServiceData->MnpDeviceData;
1212
1213 if (!IsConfigUpdate) {
1214 //
1215 // If it's not a configuration update, increase the configured children number.
1216 //
1217 MnpDeviceData->ConfiguredChildrenNumber++;
1218
1219 if (MnpDeviceData->ConfiguredChildrenNumber == 1) {
1220 //
1221 // It's the first configured child, start the simple network.
1222 //
1223 Status = MnpStartSnp (MnpDeviceData->Snp);
1224 if (EFI_ERROR (Status)) {
1225 DEBUG ((EFI_D_ERROR, "MnpStart: MnpStartSnp failed, %r.\n", Status));
1226
1227 goto ErrorExit;
1228 }
1229
1230 //
1231 // Start the timeout timer.
1232 //
1233 Status = gBS->SetTimer (
1234 MnpDeviceData->TimeoutCheckTimer,
1235 TimerPeriodic,
1236 MNP_TIMEOUT_CHECK_INTERVAL
1237 );
1238 if (EFI_ERROR (Status)) {
1239 DEBUG (
1240 (EFI_D_ERROR,
1241 "MnpStart, gBS->SetTimer for TimeoutCheckTimer %r.\n",
1242 Status)
1243 );
1244
1245 goto ErrorExit;
1246 }
1247
1248 //
1249 // Start the media detection timer.
1250 //
1251 Status = gBS->SetTimer (
1252 MnpDeviceData->MediaDetectTimer,
1253 TimerPeriodic,
1254 MNP_MEDIA_DETECT_INTERVAL
1255 );
1256 if (EFI_ERROR (Status)) {
1257 DEBUG (
1258 (EFI_D_ERROR,
1259 "MnpStart, gBS->SetTimer for MediaDetectTimer %r.\n",
1260 Status)
1261 );
1262
1263 goto ErrorExit;
1264 }
1265 }
1266 }
1267
1268 if (MnpDeviceData->EnableSystemPoll ^ EnableSystemPoll) {
1269 //
1270 // The EnableSystemPoll differs with the current state, disable or enable
1271 // the system poll.
1272 //
1273 TimerOpType = EnableSystemPoll ? TimerPeriodic : TimerCancel;
1274
1275 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerOpType, MNP_SYS_POLL_INTERVAL);
1276 if (EFI_ERROR (Status)) {
1277 DEBUG ((EFI_D_ERROR, "MnpStart: gBS->SetTimer for PollTimer failed, %r.\n", Status));
1278
1279 goto ErrorExit;
1280 }
1281
1282 MnpDeviceData->EnableSystemPoll = EnableSystemPoll;
1283 }
1284
1285 //
1286 // Change the receive filters if need.
1287 //
1288 Status = MnpConfigReceiveFilters (MnpDeviceData);
1289
1290 ErrorExit:
1291 return Status;
1292 }
1293
1294
1295 /**
1296 Stop the managed network.
1297
1298 @param[in, out] MnpServiceData Pointer to the mnp service context data.
1299
1300 @retval EFI_SUCCESS The managed network is stopped.
1301 @retval Others Other errors as indicated.
1302
1303 **/
1304 EFI_STATUS
1305 MnpStop (
1306 IN OUT MNP_SERVICE_DATA *MnpServiceData
1307 )
1308 {
1309 EFI_STATUS Status;
1310 MNP_DEVICE_DATA *MnpDeviceData;
1311
1312 NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
1313 MnpDeviceData = MnpServiceData->MnpDeviceData;
1314 ASSERT (MnpDeviceData->ConfiguredChildrenNumber > 0);
1315
1316 //
1317 // Configure the receive filters.
1318 //
1319 MnpConfigReceiveFilters (MnpDeviceData);
1320
1321 //
1322 // Decrease the children number.
1323 //
1324 MnpDeviceData->ConfiguredChildrenNumber--;
1325
1326 if (MnpDeviceData->ConfiguredChildrenNumber > 0) {
1327 //
1328 // If there are other configured chilren, return and keep the timers and
1329 // simple network unchanged.
1330 //
1331 return EFI_SUCCESS;
1332 }
1333
1334 //
1335 // No configured children now.
1336 //
1337 if (MnpDeviceData->EnableSystemPoll) {
1338 //
1339 // The system poll in on, cancel the poll timer.
1340 //
1341 Status = gBS->SetTimer (MnpDeviceData->PollTimer, TimerCancel, 0);
1342 MnpDeviceData->EnableSystemPoll = FALSE;
1343 }
1344
1345 //
1346 // Cancel the timeout timer.
1347 //
1348 Status = gBS->SetTimer (MnpDeviceData->TimeoutCheckTimer, TimerCancel, 0);
1349
1350 //
1351 // Cancel the media detect timer.
1352 //
1353 Status = gBS->SetTimer (MnpDeviceData->MediaDetectTimer, TimerCancel, 0);
1354
1355 //
1356 // Stop the simple network.
1357 //
1358 Status = MnpStopSnp (MnpDeviceData);
1359 return Status;
1360 }
1361
1362
1363 /**
1364 Flush the instance's received data.
1365
1366 @param[in, out] Instance Pointer to the mnp instance context data.
1367
1368 **/
1369 VOID
1370 MnpFlushRcvdDataQueue (
1371 IN OUT MNP_INSTANCE_DATA *Instance
1372 )
1373 {
1374 EFI_TPL OldTpl;
1375 MNP_RXDATA_WRAP *RxDataWrap;
1376
1377 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1378
1379 OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
1380
1381 while (!IsListEmpty (&Instance->RcvdPacketQueue)) {
1382 //
1383 // Remove all the Wraps.
1384 //
1385 RxDataWrap = NET_LIST_HEAD (&Instance->RcvdPacketQueue, MNP_RXDATA_WRAP, WrapEntry);
1386
1387 //
1388 // Recycle the RxDataWrap.
1389 //
1390 MnpRecycleRxData (NULL, (VOID *) RxDataWrap);
1391 Instance->RcvdPacketQueueSize--;
1392 }
1393
1394 ASSERT (Instance->RcvdPacketQueueSize == 0);
1395
1396 gBS->RestoreTPL (OldTpl);
1397 }
1398
1399
1400 /**
1401 Configure the Instance using ConfigData.
1402
1403 @param[in, out] Instance Pointer to the mnp instance context data.
1404 @param[in] ConfigData Pointer to the configuration data used to configure
1405 the isntance.
1406
1407 @retval EFI_SUCCESS The Instance is configured.
1408 @retval EFI_UNSUPPORTED EnableReceiveTimestamps is on and the
1409 implementation doesn't support it.
1410 @retval Others Other errors as indicated.
1411
1412 **/
1413 EFI_STATUS
1414 MnpConfigureInstance (
1415 IN OUT MNP_INSTANCE_DATA *Instance,
1416 IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL
1417 )
1418 {
1419 EFI_STATUS Status;
1420 MNP_SERVICE_DATA *MnpServiceData;
1421 MNP_DEVICE_DATA *MnpDeviceData;
1422 EFI_MANAGED_NETWORK_CONFIG_DATA *OldConfigData;
1423 EFI_MANAGED_NETWORK_CONFIG_DATA *NewConfigData;
1424 BOOLEAN IsConfigUpdate;
1425
1426 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1427
1428 if ((ConfigData != NULL) && ConfigData->EnableReceiveTimestamps) {
1429 //
1430 // Don't support timestamp.
1431 //
1432 return EFI_UNSUPPORTED;
1433 }
1434
1435 Status = EFI_SUCCESS;
1436
1437 MnpServiceData = Instance->MnpServiceData;
1438 MnpDeviceData = MnpServiceData->MnpDeviceData;
1439 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1440
1441 IsConfigUpdate = (BOOLEAN) ((Instance->Configured) && (ConfigData != NULL));
1442
1443 OldConfigData = &Instance->ConfigData;
1444 NewConfigData = ConfigData;
1445 if (NewConfigData == NULL) {
1446 //
1447 // Restore back the default config data if a reset of this instance
1448 // is required.
1449 //
1450 NewConfigData = &mMnpDefaultConfigData;
1451 }
1452
1453 //
1454 // Reset the instance's receive filter.
1455 //
1456 Instance->ReceiveFilter = 0;
1457
1458 //
1459 // Clear the receive counters according to the old ConfigData.
1460 //
1461 if (OldConfigData->EnableUnicastReceive) {
1462 MnpDeviceData->UnicastCount--;
1463 }
1464
1465 if (OldConfigData->EnableMulticastReceive) {
1466 MnpDeviceData->MulticastCount--;
1467 }
1468
1469 if (OldConfigData->EnableBroadcastReceive) {
1470 MnpDeviceData->BroadcastCount--;
1471 }
1472
1473 if (OldConfigData->EnablePromiscuousReceive) {
1474 MnpDeviceData->PromiscuousCount--;
1475 }
1476
1477 //
1478 // Set the receive filter counters and the receive filter of the
1479 // instance according to the new ConfigData.
1480 //
1481 if (NewConfigData->EnableUnicastReceive) {
1482 MnpDeviceData->UnicastCount++;
1483 Instance->ReceiveFilter |= MNP_RECEIVE_UNICAST;
1484 }
1485
1486 if (NewConfigData->EnableMulticastReceive) {
1487 MnpDeviceData->MulticastCount++;
1488 }
1489
1490 if (NewConfigData->EnableBroadcastReceive) {
1491 MnpDeviceData->BroadcastCount++;
1492 Instance->ReceiveFilter |= MNP_RECEIVE_BROADCAST;
1493 }
1494
1495 if (NewConfigData->EnablePromiscuousReceive) {
1496 MnpDeviceData->PromiscuousCount++;
1497 }
1498
1499 if (OldConfigData->FlushQueuesOnReset) {
1500 MnpFlushRcvdDataQueue (Instance);
1501 }
1502
1503 if (ConfigData == NULL) {
1504 Instance->ManagedNetwork.Cancel (&Instance->ManagedNetwork, NULL);
1505 }
1506
1507 if (!NewConfigData->EnableMulticastReceive) {
1508 MnpGroupOp (Instance, FALSE, NULL, NULL);
1509 }
1510
1511 //
1512 // Save the new configuration data.
1513 //
1514 CopyMem (OldConfigData, NewConfigData, sizeof (*OldConfigData));
1515
1516 Instance->Configured = (BOOLEAN) (ConfigData != NULL);
1517 if (Instance->Configured) {
1518 //
1519 // The instance is configured, start the Mnp.
1520 //
1521 Status = MnpStart (
1522 MnpServiceData,
1523 IsConfigUpdate,
1524 (BOOLEAN) !NewConfigData->DisableBackgroundPolling
1525 );
1526 } else {
1527 //
1528 // The instance is changed to the unconfigured state, stop the Mnp.
1529 //
1530 Status = MnpStop (MnpServiceData);
1531 }
1532
1533 return Status;
1534 }
1535
1536 /**
1537 Configure the Snp receive filters according to the instances' receive filter
1538 settings.
1539
1540 @param[in] MnpDeviceData Pointer to the mnp device context data.
1541
1542 @retval EFI_SUCCESS The receive filters is configured.
1543 @retval EFI_OUT_OF_RESOURCES The receive filters can't be configured due
1544 to lack of memory resource.
1545
1546 **/
1547 EFI_STATUS
1548 MnpConfigReceiveFilters (
1549 IN MNP_DEVICE_DATA *MnpDeviceData
1550 )
1551 {
1552 EFI_STATUS Status;
1553 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
1554 EFI_MAC_ADDRESS *MCastFilter;
1555 UINT32 MCastFilterCnt;
1556 UINT32 EnableFilterBits;
1557 UINT32 DisableFilterBits;
1558 BOOLEAN ResetMCastFilters;
1559 LIST_ENTRY *Entry;
1560 UINT32 Index;
1561 MNP_GROUP_ADDRESS *GroupAddress;
1562
1563 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1564
1565 Snp = MnpDeviceData->Snp;
1566
1567 //
1568 // Initialize the enable filter and disable filter.
1569 //
1570 EnableFilterBits = 0;
1571 DisableFilterBits = Snp->Mode->ReceiveFilterMask;
1572
1573 if (MnpDeviceData->UnicastCount != 0) {
1574 //
1575 // Enable unicast if any instance wants to receive unicast.
1576 //
1577 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
1578 }
1579
1580 if (MnpDeviceData->BroadcastCount != 0) {
1581 //
1582 // Enable broadcast if any instance wants to receive broadcast.
1583 //
1584 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
1585 }
1586
1587 MCastFilter = NULL;
1588 MCastFilterCnt = 0;
1589 ResetMCastFilters = TRUE;
1590
1591 if ((MnpDeviceData->MulticastCount != 0) && (MnpDeviceData->GroupAddressCount != 0)) {
1592 //
1593 // There are instances configured to receive multicast and already some group
1594 // addresses are joined.
1595 //
1596
1597 ResetMCastFilters = FALSE;
1598
1599 if (MnpDeviceData->GroupAddressCount <= Snp->Mode->MaxMCastFilterCount) {
1600 //
1601 // The joind group address is less than simple network's maximum count.
1602 // Just configure the snp to do the multicast filtering.
1603 //
1604
1605 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
1606
1607 //
1608 // Allocate pool for the mulicast addresses.
1609 //
1610 MCastFilterCnt = MnpDeviceData->GroupAddressCount;
1611 MCastFilter = AllocatePool (sizeof (EFI_MAC_ADDRESS) * MCastFilterCnt);
1612 if (MCastFilter == NULL) {
1613 DEBUG ((EFI_D_ERROR, "MnpConfigReceiveFilters: Failed to allocate memory resource for MCastFilter.\n"));
1614
1615 return EFI_OUT_OF_RESOURCES;
1616 }
1617
1618 //
1619 // Fill the multicast HW address buffer.
1620 //
1621 Index = 0;
1622 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
1623
1624 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1625 CopyMem (MCastFilter + Index, &GroupAddress->Address, sizeof (*(MCastFilter + Index)));
1626 Index++;
1627
1628 ASSERT (Index <= MCastFilterCnt);
1629 }
1630 } else {
1631 //
1632 // The maximum multicast is reached, set the filter to be promiscuous
1633 // multicast.
1634 //
1635
1636 if ((Snp->Mode->ReceiveFilterMask & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
1637 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
1638 } else {
1639 //
1640 // Either MULTICAST or PROMISCUOUS_MULTICAST is not supported by Snp,
1641 // set the NIC to be promiscuous although this will tremendously degrade
1642 // the performance.
1643 //
1644 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1645 }
1646 }
1647 }
1648
1649 if (MnpDeviceData->PromiscuousCount != 0) {
1650 //
1651 // Enable promiscuous if any instance wants to receive promiscuous.
1652 //
1653 EnableFilterBits |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
1654 }
1655
1656 //
1657 // Set the disable filter.
1658 //
1659 DisableFilterBits ^= EnableFilterBits;
1660
1661 //
1662 // Configure the receive filters of SNP.
1663 //
1664 Status = Snp->ReceiveFilters (
1665 Snp,
1666 EnableFilterBits,
1667 DisableFilterBits,
1668 ResetMCastFilters,
1669 MCastFilterCnt,
1670 MCastFilter
1671 );
1672 DEBUG_CODE (
1673 if (EFI_ERROR (Status)) {
1674 DEBUG (
1675 (EFI_D_ERROR,
1676 "MnpConfigReceiveFilters: Snp->ReceiveFilters failed, %r.\n",
1677 Status)
1678 );
1679 }
1680 );
1681
1682 if (MCastFilter != NULL) {
1683 //
1684 // Free the buffer used to hold the group addresses.
1685 //
1686 FreePool (MCastFilter);
1687 }
1688
1689 return Status;
1690 }
1691
1692
1693 /**
1694 Add a group address control block which controls the MacAddress for
1695 this instance.
1696
1697 @param[in, out] Instance Pointer to the mnp instance context data.
1698 @param[in, out] CtrlBlk Pointer to the group address control block.
1699 @param[in, out] GroupAddress Pointer to the group adress.
1700 @param[in] MacAddress Pointer to the mac address.
1701 @param[in] HwAddressSize The hardware address size.
1702
1703 @retval EFI_SUCCESS The group address control block is added.
1704 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1705
1706 **/
1707 EFI_STATUS
1708 MnpGroupOpAddCtrlBlk (
1709 IN OUT MNP_INSTANCE_DATA *Instance,
1710 IN OUT MNP_GROUP_CONTROL_BLOCK *CtrlBlk,
1711 IN OUT MNP_GROUP_ADDRESS *GroupAddress OPTIONAL,
1712 IN EFI_MAC_ADDRESS *MacAddress,
1713 IN UINT32 HwAddressSize
1714 )
1715 {
1716 MNP_DEVICE_DATA *MnpDeviceData;
1717
1718 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1719
1720 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1721 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1722
1723 if (GroupAddress == NULL) {
1724 ASSERT (MacAddress != NULL);
1725
1726 //
1727 // Allocate a new GroupAddress to be added into MNP's GroupAddressList.
1728 //
1729 GroupAddress = AllocatePool (sizeof (MNP_GROUP_ADDRESS));
1730 if (GroupAddress == NULL) {
1731
1732 DEBUG ((EFI_D_ERROR, "MnpGroupOpFormCtrlBlk: Failed to allocate memory resource.\n"));
1733
1734 return EFI_OUT_OF_RESOURCES;
1735 }
1736
1737 CopyMem (&GroupAddress->Address, MacAddress, sizeof (GroupAddress->Address));
1738 GroupAddress->RefCnt = 0;
1739 InsertTailList (
1740 &MnpDeviceData->GroupAddressList,
1741 &GroupAddress->AddrEntry
1742 );
1743 MnpDeviceData->GroupAddressCount++;
1744 }
1745
1746 //
1747 // Increase the RefCnt.
1748 //
1749 GroupAddress->RefCnt++;
1750
1751 //
1752 // Add the CtrlBlk into the instance's GroupCtrlBlkList.
1753 //
1754 CtrlBlk->GroupAddress = GroupAddress;
1755 InsertTailList (&Instance->GroupCtrlBlkList, &CtrlBlk->CtrlBlkEntry);
1756
1757 return EFI_SUCCESS;
1758 }
1759
1760
1761 /**
1762 Delete a group control block from the instance. If the controlled group address's
1763 reference count reaches zero, the group address is removed too.
1764
1765 @param[in] Instance Pointer to the instance context data.
1766 @param[in] CtrlBlk Pointer to the group control block to delete.
1767
1768 @return The group address controlled by the control block is no longer used or not.
1769
1770 **/
1771 BOOLEAN
1772 MnpGroupOpDelCtrlBlk (
1773 IN MNP_INSTANCE_DATA *Instance,
1774 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk
1775 )
1776 {
1777 MNP_DEVICE_DATA *MnpDeviceData;
1778 MNP_GROUP_ADDRESS *GroupAddress;
1779
1780 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1781
1782 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1783 NET_CHECK_SIGNATURE (MnpDeviceData, MNP_DEVICE_DATA_SIGNATURE);
1784
1785 //
1786 // Remove and free the CtrlBlk.
1787 //
1788 GroupAddress = CtrlBlk->GroupAddress;
1789 RemoveEntryList (&CtrlBlk->CtrlBlkEntry);
1790 FreePool (CtrlBlk);
1791
1792 ASSERT (GroupAddress->RefCnt > 0);
1793
1794 //
1795 // Count down the RefCnt.
1796 //
1797 GroupAddress->RefCnt--;
1798
1799 if (GroupAddress->RefCnt == 0) {
1800 //
1801 // Free this GroupAddress entry if no instance uses it.
1802 //
1803 MnpDeviceData->GroupAddressCount--;
1804 RemoveEntryList (&GroupAddress->AddrEntry);
1805 FreePool (GroupAddress);
1806
1807 return TRUE;
1808 }
1809
1810 return FALSE;
1811 }
1812
1813
1814 /**
1815 Do the group operations for this instance.
1816
1817 @param[in, out] Instance Pointer to the instance context data.
1818 @param[in] JoinFlag Set to TRUE to join a group. Set to TRUE to
1819 leave a group/groups.
1820 @param[in] MacAddress Pointer to the group address to join or leave.
1821 @param[in] CtrlBlk Pointer to the group control block if JoinFlag
1822 is FALSE.
1823
1824 @retval EFI_SUCCESS The group operation finished.
1825 @retval EFI_OUT_OF_RESOURCES Failed due to lack of memory resources.
1826 @retval Others Other errors as indicated.
1827
1828 **/
1829 EFI_STATUS
1830 MnpGroupOp (
1831 IN OUT MNP_INSTANCE_DATA *Instance,
1832 IN BOOLEAN JoinFlag,
1833 IN EFI_MAC_ADDRESS *MacAddress OPTIONAL,
1834 IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL
1835 )
1836 {
1837 MNP_DEVICE_DATA *MnpDeviceData;
1838 LIST_ENTRY *Entry;
1839 LIST_ENTRY *NextEntry;
1840 MNP_GROUP_ADDRESS *GroupAddress;
1841 EFI_SIMPLE_NETWORK_MODE *SnpMode;
1842 MNP_GROUP_CONTROL_BLOCK *NewCtrlBlk;
1843 EFI_STATUS Status;
1844 BOOLEAN AddressExist;
1845 BOOLEAN NeedUpdate;
1846
1847 NET_CHECK_SIGNATURE (Instance, MNP_INSTANCE_DATA_SIGNATURE);
1848
1849 MnpDeviceData = Instance->MnpServiceData->MnpDeviceData;
1850 SnpMode = MnpDeviceData->Snp->Mode;
1851
1852 if (JoinFlag) {
1853 //
1854 // A new gropu address is to be added.
1855 //
1856 GroupAddress = NULL;
1857 AddressExist = FALSE;
1858
1859 //
1860 // Allocate memory for the control block.
1861 //
1862 NewCtrlBlk = AllocatePool (sizeof (MNP_GROUP_CONTROL_BLOCK));
1863 if (NewCtrlBlk == NULL) {
1864 DEBUG ((EFI_D_ERROR, "MnpGroupOp: Failed to allocate memory resource.\n"));
1865
1866 return EFI_OUT_OF_RESOURCES;
1867 }
1868
1869 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->GroupAddressList) {
1870 //
1871 // Check whether the MacAddress is already joined by other instances.
1872 //
1873 GroupAddress = NET_LIST_USER_STRUCT (Entry, MNP_GROUP_ADDRESS, AddrEntry);
1874 if (CompareMem (MacAddress, &GroupAddress->Address, SnpMode->HwAddressSize) == 0) {
1875 AddressExist = TRUE;
1876 break;
1877 }
1878 }
1879
1880 if (!AddressExist) {
1881 GroupAddress = NULL;
1882 }
1883
1884 //
1885 // Add the GroupAddress for this instance.
1886 //
1887 Status = MnpGroupOpAddCtrlBlk (
1888 Instance,
1889 NewCtrlBlk,
1890 GroupAddress,
1891 MacAddress,
1892 SnpMode->HwAddressSize
1893 );
1894 if (EFI_ERROR (Status)) {
1895 return Status;
1896 }
1897
1898 NeedUpdate = TRUE;
1899 } else {
1900 if (MacAddress != NULL) {
1901 ASSERT (CtrlBlk != NULL);
1902
1903 //
1904 // Leave the specific multicast mac address.
1905 //
1906 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, CtrlBlk);
1907 } else {
1908 //
1909 // Leave all multicast mac addresses.
1910 //
1911 NeedUpdate = FALSE;
1912
1913 NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Instance->GroupCtrlBlkList) {
1914
1915 NewCtrlBlk = NET_LIST_USER_STRUCT (
1916 Entry,
1917 MNP_GROUP_CONTROL_BLOCK,
1918 CtrlBlkEntry
1919 );
1920 //
1921 // Update is required if the group address left is no longer used
1922 // by other instances.
1923 //
1924 NeedUpdate = MnpGroupOpDelCtrlBlk (Instance, NewCtrlBlk);
1925 }
1926 }
1927 }
1928
1929 Status = EFI_SUCCESS;
1930
1931 if (NeedUpdate) {
1932 //
1933 // Reconfigure the receive filters if necessary.
1934 //
1935 Status = MnpConfigReceiveFilters (MnpDeviceData);
1936 }
1937
1938 return Status;
1939 }