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