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