TianoCore EDK2 master
Loading...
Searching...
No Matches
Ip6Driver.c
Go to the documentation of this file.
1
11#include "Ip6Impl.h"
12
13EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding = {
17 0xa,
18 NULL,
19 NULL
20};
21
22BOOLEAN mIpSec2Installed = FALSE;
23
31VOID
32EFIAPI
34 IN EFI_EVENT Event,
35 IN VOID *Context
36 )
37{
38 EFI_STATUS Status;
39
40 //
41 // Test if protocol was even found.
42 // Notification function will be called at least once.
43 //
44 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **)&mIpSec);
45 if ((Status == EFI_SUCCESS) && (mIpSec != NULL)) {
46 //
47 // Close the event so it does not get called again.
48 //
49 gBS->CloseEvent (Event);
50
51 mIpSec2Installed = TRUE;
52 }
53}
54
71EFIAPI
73 IN EFI_HANDLE ImageHandle,
74 IN EFI_SYSTEM_TABLE *SystemTable
75 )
76{
77 VOID *Registration;
78
80 &gEfiIpSec2ProtocolGuid,
81 TPL_CALLBACK,
83 NULL,
84 &Registration
85 );
86
88 ImageHandle,
89 SystemTable,
90 &gIp6DriverBinding,
91 ImageHandle,
92 &gIp6ComponentName,
93 &gIp6ComponentName2
94 );
95}
96
111EFIAPI
114 IN EFI_HANDLE ControllerHandle,
115 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
116 )
117{
118 //
119 // Test for the MNP service binding Protocol
120 //
121 return gBS->OpenProtocol (
122 ControllerHandle,
123 &gEfiManagedNetworkServiceBindingProtocolGuid,
124 NULL,
125 This->DriverBindingHandle,
126 ControllerHandle,
127 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
128 );
129}
130
146 IN IP6_SERVICE *IpSb
147 )
148{
149 EFI_STATUS Status;
150 EFI_IPv6_ADDRESS AllNodes;
151 IP6_NEIGHBOR_ENTRY *NeighborCache;
152
153 IpSb->State = IP6_SERVICE_DESTROY;
154
155 if (IpSb->Timer != NULL) {
156 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);
157 gBS->CloseEvent (IpSb->Timer);
158
159 IpSb->Timer = NULL;
160 }
161
162 if (IpSb->FasterTimer != NULL) {
163 gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);
164 gBS->CloseEvent (IpSb->FasterTimer);
165
166 IpSb->FasterTimer = NULL;
167 }
168
169 Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance);
170
171 if (!IpSb->LinkLocalDadFail) {
172 //
173 // Leave link-scope all-nodes multicast address (FF02::1)
174 //
175 Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);
176
177 Status = Ip6LeaveGroup (IpSb, &AllNodes);
178 if (EFI_ERROR (Status)) {
179 return Status;
180 }
181 }
182
183 if (IpSb->DefaultInterface != NULL) {
184 Ip6CleanInterface (IpSb->DefaultInterface, NULL);
185 IpSb->DefaultInterface = NULL;
186 }
187
189
190 Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);
191 Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);
192
193 if (IpSb->RouteTable != NULL) {
194 Ip6CleanRouteTable (IpSb->RouteTable);
195 IpSb->RouteTable = NULL;
196 }
197
198 if (IpSb->InterfaceId != NULL) {
199 FreePool (IpSb->InterfaceId);
200 }
201
202 IpSb->InterfaceId = NULL;
203
204 Ip6CleanAssembleTable (&IpSb->Assemble);
205
206 if (IpSb->MnpChildHandle != NULL) {
207 if (IpSb->Mnp != NULL) {
208 IpSb->Mnp->Cancel (IpSb->Mnp, NULL);
209 IpSb->Mnp->Configure (IpSb->Mnp, NULL);
210 gBS->CloseProtocol (
211 IpSb->MnpChildHandle,
212 &gEfiManagedNetworkProtocolGuid,
213 IpSb->Image,
214 IpSb->Controller
215 );
216
217 IpSb->Mnp = NULL;
218 }
219
221 IpSb->Controller,
222 IpSb->Image,
223 &gEfiManagedNetworkServiceBindingProtocolGuid,
224 IpSb->MnpChildHandle
225 );
226
227 IpSb->MnpChildHandle = NULL;
228 }
229
230 if (IpSb->RecvRequest.MnpToken.Event != NULL) {
231 gBS->CloseEvent (IpSb->RecvRequest.MnpToken.Event);
232 }
233
234 //
235 // Free the Neighbor Discovery resources
236 //
237 while (!IsListEmpty (&IpSb->NeighborTable)) {
238 NeighborCache = NET_LIST_HEAD (&IpSb->NeighborTable, IP6_NEIGHBOR_ENTRY, Link);
239 Ip6FreeNeighborEntry (IpSb, NeighborCache, FALSE, TRUE, EFI_SUCCESS, NULL, NULL);
240 }
241
242 return EFI_SUCCESS;
243}
244
260 IN EFI_HANDLE Controller,
261 IN EFI_HANDLE ImageHandle,
262 OUT IP6_SERVICE **Service
263 )
264{
265 IP6_SERVICE *IpSb;
266 EFI_STATUS Status;
269
270 ASSERT (Service != NULL);
271
272 *Service = NULL;
273
274 //
275 // allocate a service private data then initialize all the filed to
276 // empty resources, so if any thing goes wrong when allocating
277 // resources, Ip6CleanService can be called to clean it up.
278 //
279 IpSb = AllocateZeroPool (sizeof (IP6_SERVICE));
280
281 if (IpSb == NULL) {
282 return EFI_OUT_OF_RESOURCES;
283 }
284
285 IpSb->Signature = IP6_SERVICE_SIGNATURE;
286 IpSb->ServiceBinding.CreateChild = Ip6ServiceBindingCreateChild;
287 IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild;
288 IpSb->State = IP6_SERVICE_UNSTARTED;
289
290 IpSb->NumChildren = 0;
291 InitializeListHead (&IpSb->Children);
292
293 InitializeListHead (&IpSb->Interfaces);
294 IpSb->DefaultInterface = NULL;
295 IpSb->RouteTable = NULL;
296
297 IpSb->RecvRequest.Signature = IP6_LINK_RX_SIGNATURE;
298 IpSb->RecvRequest.CallBack = NULL;
299 IpSb->RecvRequest.Context = NULL;
300 MnpToken = &IpSb->RecvRequest.MnpToken;
301 MnpToken->Event = NULL;
302 MnpToken->Status = EFI_NOT_READY;
303 MnpToken->Packet.RxData = NULL;
304
305 Ip6CreateAssembleTable (&IpSb->Assemble);
306
307 IpSb->MldCtrl.Mldv1QuerySeen = 0;
308 InitializeListHead (&IpSb->MldCtrl.Groups);
309
310 ZeroMem (&IpSb->LinkLocalAddr, sizeof (EFI_IPv6_ADDRESS));
311 IpSb->LinkLocalOk = FALSE;
312 IpSb->LinkLocalDadFail = FALSE;
313 IpSb->Dhcp6NeedStart = FALSE;
314 IpSb->Dhcp6NeedInfoRequest = FALSE;
315
316 IpSb->CurHopLimit = IP6_HOP_LIMIT;
317 IpSb->LinkMTU = IP6_MIN_LINK_MTU;
318 IpSb->BaseReachableTime = IP6_REACHABLE_TIME;
319 Status = Ip6UpdateReachableTime (IpSb);
320 if (EFI_ERROR (Status)) {
321 goto ON_ERROR;
322 }
323
324 //
325 // RFC4861 RETRANS_TIMER: 1,000 milliseconds
326 //
327 IpSb->RetransTimer = IP6_RETRANS_TIMER;
328
329 IpSb->RoundRobin = 0;
330
331 InitializeListHead (&IpSb->NeighborTable);
332 InitializeListHead (&IpSb->DefaultRouterList);
333 InitializeListHead (&IpSb->OnlinkPrefix);
334 InitializeListHead (&IpSb->AutonomousPrefix);
335
336 IpSb->InterfaceIdLen = IP6_IF_ID_LEN;
337 IpSb->InterfaceId = NULL;
338
339 IpSb->RouterAdvertiseReceived = FALSE;
340 IpSb->SolicitTimer = IP6_MAX_RTR_SOLICITATIONS;
341 IpSb->Ticks = 0;
342
343 IpSb->Image = ImageHandle;
344 IpSb->Controller = Controller;
345
346 IpSb->MnpChildHandle = NULL;
347 IpSb->Mnp = NULL;
348
349 Config = &IpSb->MnpConfigData;
350 Config->ReceivedQueueTimeoutValue = 0;
351 Config->TransmitQueueTimeoutValue = 0;
352 Config->ProtocolTypeFilter = IP6_ETHER_PROTO;
353 Config->EnableUnicastReceive = TRUE;
357 Config->FlushQueuesOnReset = TRUE;
360
361 ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));
362
363 IpSb->Timer = NULL;
364 IpSb->FasterTimer = NULL;
365
366 ZeroMem (&IpSb->Ip6ConfigInstance, sizeof (IP6_CONFIG_INSTANCE));
367
368 IpSb->MacString = NULL;
369
370 //
371 // Create various resources. First create the route table, timer
372 // event, MNP token event and MNP child.
373 //
374
375 IpSb->RouteTable = Ip6CreateRouteTable ();
376 if (IpSb->RouteTable == NULL) {
377 Status = EFI_OUT_OF_RESOURCES;
378 goto ON_ERROR;
379 }
380
381 Status = gBS->CreateEvent (
382 EVT_NOTIFY_SIGNAL | EVT_TIMER,
383 TPL_CALLBACK,
385 IpSb,
386 &IpSb->Timer
387 );
388 if (EFI_ERROR (Status)) {
389 goto ON_ERROR;
390 }
391
392 Status = gBS->CreateEvent (
393 EVT_NOTIFY_SIGNAL | EVT_TIMER,
394 TPL_CALLBACK,
396 IpSb,
397 &IpSb->FasterTimer
398 );
399 if (EFI_ERROR (Status)) {
400 goto ON_ERROR;
401 }
402
403 Status = NetLibCreateServiceChild (
404 Controller,
405 ImageHandle,
406 &gEfiManagedNetworkServiceBindingProtocolGuid,
407 &IpSb->MnpChildHandle
408 );
409 if (EFI_ERROR (Status)) {
410 goto ON_ERROR;
411 }
412
413 Status = gBS->OpenProtocol (
414 IpSb->MnpChildHandle,
415 &gEfiManagedNetworkProtocolGuid,
416 (VOID **)(&IpSb->Mnp),
417 ImageHandle,
418 Controller,
419 EFI_OPEN_PROTOCOL_BY_DRIVER
420 );
421 if (EFI_ERROR (Status)) {
422 goto ON_ERROR;
423 }
424
425 Status = Ip6ServiceConfigMnp (IpSb, TRUE);
426 if (EFI_ERROR (Status)) {
427 goto ON_ERROR;
428 }
429
430 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);
431 if (EFI_ERROR (Status)) {
432 goto ON_ERROR;
433 }
434
435 IpSb->MaxPacketSize = IP6_MIN_LINK_MTU - sizeof (EFI_IP6_HEADER);
436 if (NetLibGetVlanId (IpSb->Controller) != 0) {
437 //
438 // This is a VLAN device, reduce MTU by VLAN tag length
439 //
440 IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;
441 }
442
443 IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;
444
445 //
446 // Currently only ETHERNET is supported in IPv6 stack, since
447 // link local address requires an IEEE 802 48-bit MACs for
448 // EUI-64 format interface identifier mapping.
449 //
450 if (IpSb->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
451 Status = EFI_UNSUPPORTED;
452 goto ON_ERROR;
453 }
454
455 Status = Ip6InitMld (IpSb);
456 if (EFI_ERROR (Status)) {
457 goto ON_ERROR;
458 }
459
460 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);
461 if (EFI_ERROR (Status)) {
462 goto ON_ERROR;
463 }
464
465 Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance);
466 if (EFI_ERROR (Status)) {
467 goto ON_ERROR;
468 }
469
470 IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE);
471 if (IpSb->DefaultInterface == NULL) {
472 Status = EFI_DEVICE_ERROR;
473 goto ON_ERROR;
474 }
475
476 Status = gBS->CreateEvent (
477 EVT_NOTIFY_SIGNAL,
478 TPL_NOTIFY,
480 &IpSb->RecvRequest,
481 &MnpToken->Event
482 );
483 if (EFI_ERROR (Status)) {
484 goto ON_ERROR;
485 }
486
487 InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);
488
489 *Service = IpSb;
490 return EFI_SUCCESS;
491
492ON_ERROR:
493 Ip6CleanService (IpSb);
494 FreePool (IpSb);
495 return Status;
496}
497
512EFIAPI
515 IN EFI_HANDLE ControllerHandle,
516 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
517 )
518{
519 IP6_SERVICE *IpSb;
520 EFI_STATUS Status;
522 IP6_CONFIG_DATA_ITEM *DataItem;
523 UINT32 Random;
524
525 IpSb = NULL;
526 Ip6Cfg = NULL;
527 DataItem = NULL;
528
529 Status = PseudoRandomU32 (&Random);
530 if (EFI_ERROR (Status)) {
531 DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
532 return Status;
533 }
534
535 //
536 // Test for the Ip6 service binding protocol
537 //
538 Status = gBS->OpenProtocol (
539 ControllerHandle,
540 &gEfiIp6ServiceBindingProtocolGuid,
541 NULL,
542 This->DriverBindingHandle,
543 ControllerHandle,
544 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
545 );
546
547 if (Status == EFI_SUCCESS) {
548 return EFI_ALREADY_STARTED;
549 }
550
551 Status = Ip6CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);
552
553 if (EFI_ERROR (Status)) {
554 return Status;
555 }
556
557 ASSERT (IpSb != NULL);
558
559 Ip6Cfg = &IpSb->Ip6ConfigInstance.Ip6Config;
560
561 //
562 // Install the Ip6ServiceBinding Protocol onto ControllerHandle
563 //
564 Status = gBS->InstallMultipleProtocolInterfaces (
565 &ControllerHandle,
566 &gEfiIp6ServiceBindingProtocolGuid,
567 &IpSb->ServiceBinding,
568 &gEfiIp6ConfigProtocolGuid,
569 Ip6Cfg,
570 NULL
571 );
572 if (EFI_ERROR (Status)) {
573 goto FREE_SERVICE;
574 }
575
576 //
577 // Read the config data from NV variable again.
578 // The default data can be changed by other drivers.
579 //
580 Status = Ip6ConfigReadConfigData (IpSb->MacString, &IpSb->Ip6ConfigInstance);
581 if (EFI_ERROR (Status)) {
582 goto UNINSTALL_PROTOCOL;
583 }
584
585 //
586 // If there is any default manual address, set it.
587 //
588 DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress];
589 if (DataItem->Data.Ptr != NULL) {
590 Status = Ip6Cfg->SetData (
591 Ip6Cfg,
593 DataItem->DataSize,
594 DataItem->Data.Ptr
595 );
596 if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_BAD_BUFFER_SIZE)) {
597 //
598 // Clean the invalid ManualAddress configuration.
599 //
600 Status = Ip6Cfg->SetData (
601 Ip6Cfg,
603 0,
604 NULL
605 );
606 DEBUG ((DEBUG_WARN, "Ip6DriverBindingStart: Clean the invalid ManualAddress configuration.\n"));
607 }
608 }
609
610 //
611 // If there is any default gateway address, set it.
612 //
613 DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeGateway];
614 if (DataItem->Data.Ptr != NULL) {
615 Status = Ip6Cfg->SetData (
616 Ip6Cfg,
618 DataItem->DataSize,
619 DataItem->Data.Ptr
620 );
621 if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_BAD_BUFFER_SIZE)) {
622 //
623 // Clean the invalid Gateway configuration.
624 //
625 Status = Ip6Cfg->SetData (
626 Ip6Cfg,
628 0,
629 NULL
630 );
631 DEBUG ((DEBUG_WARN, "Ip6DriverBindingStart: Clean the invalid Gateway configuration.\n"));
632 }
633 }
634
635 //
636 // ready to go: start the receiving and timer
637 //
638 Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);
639 if (EFI_ERROR (Status)) {
640 goto UNINSTALL_PROTOCOL;
641 }
642
643 //
644 // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.
645 //
646 Status = gBS->SetTimer (
647 IpSb->FasterTimer,
649 TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS
650 );
651 if (EFI_ERROR (Status)) {
652 goto UNINSTALL_PROTOCOL;
653 }
654
655 //
656 // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.
657 //
658 Status = gBS->SetTimer (
659 IpSb->Timer,
661 TICKS_PER_MS * IP6_ONE_SECOND_IN_MS
662 );
663 if (EFI_ERROR (Status)) {
664 goto UNINSTALL_PROTOCOL;
665 }
666
667 //
668 // Initialize the IP6 ID
669 //
670 mIp6Id = Random;
671
672 return EFI_SUCCESS;
673
674UNINSTALL_PROTOCOL:
675 gBS->UninstallMultipleProtocolInterfaces (
676 ControllerHandle,
677 &gEfiIp6ServiceBindingProtocolGuid,
678 &IpSb->ServiceBinding,
679 &gEfiIp6ConfigProtocolGuid,
680 Ip6Cfg,
681 NULL
682 );
683
684FREE_SERVICE:
685 Ip6CleanService (IpSb);
686 FreePool (IpSb);
687 return Status;
688}
689
701EFIAPI
703 IN LIST_ENTRY *Entry,
704 IN VOID *Context
705 )
706{
707 IP6_PROTOCOL *IpInstance;
708 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
709 UINTN NumberOfChildren;
710 EFI_HANDLE *ChildHandleBuffer;
711
712 if ((Entry == NULL) || (Context == NULL)) {
713 return EFI_INVALID_PARAMETER;
714 }
715
716 IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);
717 ServiceBinding = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ServiceBinding;
718 NumberOfChildren = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->NumberOfChildren;
719 ChildHandleBuffer = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ChildHandleBuffer;
720
721 if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {
722 return EFI_SUCCESS;
723 }
724
725 return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);
726}
727
743EFIAPI
746 IN EFI_HANDLE ControllerHandle,
747 IN UINTN NumberOfChildren,
748 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
749 )
750{
751 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
752 IP6_SERVICE *IpSb;
753 EFI_HANDLE NicHandle;
754 EFI_STATUS Status;
755 LIST_ENTRY *List;
756 INTN State;
757 BOOLEAN IsDhcp6;
759
760 IsDhcp6 = FALSE;
761 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
762 if (NicHandle == NULL) {
763 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);
764 if (NicHandle != NULL) {
765 IsDhcp6 = TRUE;
766 } else {
767 return EFI_SUCCESS;
768 }
769 }
770
771 Status = gBS->OpenProtocol (
772 NicHandle,
773 &gEfiIp6ServiceBindingProtocolGuid,
774 (VOID **)&ServiceBinding,
775 This->DriverBindingHandle,
776 NicHandle,
777 EFI_OPEN_PROTOCOL_GET_PROTOCOL
778 );
779 if (EFI_ERROR (Status)) {
780 return EFI_DEVICE_ERROR;
781 }
782
783 IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding);
784
785 if (IsDhcp6) {
786 Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance);
787 gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event);
788 IpSb->Ip6ConfigInstance.Dhcp6Event = NULL;
789 } else if (NumberOfChildren != 0) {
790 //
791 // NumberOfChildren is not zero, destroy the IP6 children instances in ChildHandleBuffer.
792 //
793 List = &IpSb->Children;
794 Context.ServiceBinding = ServiceBinding;
795 Context.NumberOfChildren = NumberOfChildren;
796 Context.ChildHandleBuffer = ChildHandleBuffer;
797 Status = NetDestroyLinkList (
798 List,
800 &Context,
801 NULL
802 );
803 } else if (IsListEmpty (&IpSb->Children)) {
804 State = IpSb->State;
805 Status = Ip6CleanService (IpSb);
806 if (EFI_ERROR (Status)) {
807 IpSb->State = State;
808 goto Exit;
809 }
810
811 Status = gBS->UninstallMultipleProtocolInterfaces (
812 NicHandle,
813 &gEfiIp6ServiceBindingProtocolGuid,
814 ServiceBinding,
815 &gEfiIp6ConfigProtocolGuid,
816 &IpSb->Ip6ConfigInstance.Ip6Config,
817 NULL
818 );
819 ASSERT_EFI_ERROR (Status);
820 FreePool (IpSb);
821 Status = EFI_SUCCESS;
822 }
823
824Exit:
825 return Status;
826}
827
844EFIAPI
847 IN EFI_HANDLE *ChildHandle
848 )
849{
850 IP6_SERVICE *IpSb;
851 IP6_PROTOCOL *IpInstance;
852 EFI_TPL OldTpl;
853 EFI_STATUS Status;
854 VOID *Mnp;
855
856 if ((This == NULL) || (ChildHandle == NULL)) {
857 return EFI_INVALID_PARAMETER;
858 }
859
860 IpSb = IP6_SERVICE_FROM_PROTOCOL (This);
861
862 if (IpSb->LinkLocalDadFail) {
863 return EFI_DEVICE_ERROR;
864 }
865
866 IpInstance = AllocatePool (sizeof (IP6_PROTOCOL));
867
868 if (IpInstance == NULL) {
869 return EFI_OUT_OF_RESOURCES;
870 }
871
872 Ip6InitProtocol (IpSb, IpInstance);
873
874 //
875 // Install Ip6 onto ChildHandle
876 //
877 Status = gBS->InstallMultipleProtocolInterfaces (
878 ChildHandle,
879 &gEfiIp6ProtocolGuid,
880 &IpInstance->Ip6Proto,
881 NULL
882 );
883 if (EFI_ERROR (Status)) {
884 goto ON_ERROR;
885 }
886
887 IpInstance->Handle = *ChildHandle;
888
889 //
890 // Open the Managed Network protocol BY_CHILD.
891 //
892 Status = gBS->OpenProtocol (
893 IpSb->MnpChildHandle,
894 &gEfiManagedNetworkProtocolGuid,
895 (VOID **)&Mnp,
896 gIp6DriverBinding.DriverBindingHandle,
897 IpInstance->Handle,
898 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
899 );
900 if (EFI_ERROR (Status)) {
901 gBS->UninstallMultipleProtocolInterfaces (
902 *ChildHandle,
903 &gEfiIp6ProtocolGuid,
904 &IpInstance->Ip6Proto,
905 NULL
906 );
907
908 goto ON_ERROR;
909 }
910
911 //
912 // Insert it into the service binding instance.
913 //
914 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
915
916 InsertTailList (&IpSb->Children, &IpInstance->Link);
917 IpSb->NumChildren++;
918
919 gBS->RestoreTPL (OldTpl);
920
921ON_ERROR:
922
923 if (EFI_ERROR (Status)) {
924 Ip6CleanProtocol (IpInstance);
925
926 FreePool (IpInstance);
927 }
928
929 return Status;
930}
931
949EFIAPI
952 IN EFI_HANDLE ChildHandle
953 )
954{
955 EFI_STATUS Status;
956 IP6_SERVICE *IpSb;
957 IP6_PROTOCOL *IpInstance;
958 EFI_IP6_PROTOCOL *Ip6;
959 EFI_TPL OldTpl;
960
961 if ((This == NULL) || (ChildHandle == NULL)) {
962 return EFI_INVALID_PARAMETER;
963 }
964
965 //
966 // Retrieve the private context data structures
967 //
968 IpSb = IP6_SERVICE_FROM_PROTOCOL (This);
969
970 Status = gBS->OpenProtocol (
971 ChildHandle,
972 &gEfiIp6ProtocolGuid,
973 (VOID **)&Ip6,
974 gIp6DriverBinding.DriverBindingHandle,
975 ChildHandle,
976 EFI_OPEN_PROTOCOL_GET_PROTOCOL
977 );
978
979 if (EFI_ERROR (Status)) {
980 return EFI_UNSUPPORTED;
981 }
982
983 IpInstance = IP6_INSTANCE_FROM_PROTOCOL (Ip6);
984
985 if (IpInstance->Service != IpSb) {
986 return EFI_INVALID_PARAMETER;
987 }
988
989 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
990
991 //
992 // A child can be destroyed more than once. For example,
993 // Ip6DriverBindingStop will destroy all of its children.
994 // when UDP driver is being stopped, it will destroy all
995 // the IP child it opens.
996 //
997 if (IpInstance->InDestroy) {
998 gBS->RestoreTPL (OldTpl);
999 return EFI_SUCCESS;
1000 }
1001
1002 IpInstance->InDestroy = TRUE;
1003
1004 //
1005 // Close the Managed Network protocol.
1006 //
1007 gBS->CloseProtocol (
1008 IpSb->MnpChildHandle,
1009 &gEfiManagedNetworkProtocolGuid,
1010 gIp6DriverBinding.DriverBindingHandle,
1011 ChildHandle
1012 );
1013
1014 //
1015 // Uninstall the IP6 protocol first. Many thing happens during
1016 // this:
1017 // 1. The consumer of the IP6 protocol will be stopped if it
1018 // opens the protocol BY_DRIVER. For example, if MNP driver is
1019 // stopped, IP driver's stop function will be called, and uninstall
1020 // EFI_IP6_PROTOCOL will trigger the UDP's stop function. This
1021 // makes it possible to create the network stack bottom up, and
1022 // stop it top down.
1023 // 2. the upper layer will recycle the received packet. The recycle
1024 // event's TPL is higher than this function. The recycle events
1025 // will be called back before preceding. If any packets not recycled,
1026 // that means there is a resource leak.
1027 //
1028 gBS->RestoreTPL (OldTpl);
1029 Status = gBS->UninstallProtocolInterface (
1030 ChildHandle,
1031 &gEfiIp6ProtocolGuid,
1032 &IpInstance->Ip6Proto
1033 );
1034 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1035 if (EFI_ERROR (Status)) {
1036 goto ON_ERROR;
1037 }
1038
1039 Status = Ip6CleanProtocol (IpInstance);
1040 if (EFI_ERROR (Status)) {
1041 gBS->InstallMultipleProtocolInterfaces (
1042 &ChildHandle,
1043 &gEfiIp6ProtocolGuid,
1044 Ip6,
1045 NULL
1046 );
1047
1048 goto ON_ERROR;
1049 }
1050
1051 RemoveEntryList (&IpInstance->Link);
1052 ASSERT (IpSb->NumChildren > 0);
1053 IpSb->NumChildren--;
1054
1055 gBS->RestoreTPL (OldTpl);
1056
1057 FreePool (IpInstance);
1058 return EFI_SUCCESS;
1059
1060ON_ERROR:
1061 gBS->RestoreTPL (OldTpl);
1062
1063 return Status;
1064}
UINT64 UINTN
INT64 INTN
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
struct _EFI_IP6_HEADER EFI_IP6_HEADER
EFI_STATUS Ip6SetToAllNodeMulticast(IN BOOLEAN Router, IN UINT8 Scope, OUT EFI_IPv6_ADDRESS *Ip6Addr)
Definition: Ip6Common.c:103
@ Ip6ConfigDataTypeGateway
Definition: Ip6Config.h:79
@ Ip6ConfigDataTypeManualAddress
Definition: Ip6Config.h:68
VOID Ip6ConfigCleanInstance(IN OUT IP6_CONFIG_INSTANCE *Instance)
EFI_STATUS Ip6ConfigInitInstance(OUT IP6_CONFIG_INSTANCE *Instance)
EFI_STATUS Ip6ConfigDestroyDhcp6(IN OUT IP6_CONFIG_INSTANCE *Instance)
EFI_STATUS Ip6ConfigReadConfigData(IN CHAR16 *VarName, IN OUT IP6_CONFIG_INSTANCE *Instance)
EFI_STATUS EFIAPI Ip6DriverEntryPoint(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: Ip6Driver.c:72
VOID EFIAPI IpSec2InstalledCallback(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip6Driver.c:33
EFI_STATUS EFIAPI Ip6DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL)
Definition: Ip6Driver.c:513
EFI_STATUS EFIAPI Ip6DestroyChildEntryInHandleBuffer(IN LIST_ENTRY *Entry, IN VOID *Context)
Definition: Ip6Driver.c:702
EFI_STATUS EFIAPI Ip6ServiceBindingDestroyChild(IN EFI_SERVICE_BINDING_PROTOCOL *This, IN EFI_HANDLE ChildHandle)
Definition: Ip6Driver.c:950
EFI_STATUS Ip6CreateService(IN EFI_HANDLE Controller, IN EFI_HANDLE ImageHandle, OUT IP6_SERVICE **Service)
Definition: Ip6Driver.c:259
EFI_STATUS EFIAPI Ip6ServiceBindingCreateChild(IN EFI_SERVICE_BINDING_PROTOCOL *This, IN EFI_HANDLE *ChildHandle)
Definition: Ip6Driver.c:845
EFI_STATUS Ip6CleanService(IN IP6_SERVICE *IpSb)
Definition: Ip6Driver.c:145
EFI_STATUS EFIAPI Ip6DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL)
Definition: Ip6Driver.c:112
EFI_STATUS EFIAPI Ip6DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer OPTIONAL)
Definition: Ip6Driver.c:744
EFI_STATUS Ip6ReceiveFrame(IN IP6_FRAME_CALLBACK CallBack, IN IP6_SERVICE *IpSb)
Definition: Ip6If.c:561
IP6_INTERFACE * Ip6CreateInterface(IN IP6_SERVICE *IpSb, IN BOOLEAN LinkLocal)
Definition: Ip6If.c:206
VOID EFIAPI Ip6TimerTicking(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip6If.c:785
VOID Ip6CleanInterface(IN IP6_INTERFACE *Interface, IN IP6_PROTOCOL *IpInstance OPTIONAL)
Definition: Ip6If.c:297
VOID EFIAPI Ip6OnFrameReceived(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip6If.c:538
EFI_STATUS Ip6CleanProtocol(IN OUT IP6_PROTOCOL *IpInstance)
Definition: Ip6Impl.c:444
EFI_STATUS Ip6ServiceConfigMnp(IN IP6_SERVICE *IpSb, IN BOOLEAN Force)
Definition: Ip6Impl.c:502
VOID Ip6InitProtocol(IN IP6_SERVICE *IpSb, IN OUT IP6_PROTOCOL *IpInstance)
Definition: Ip6Impl.c:299
VOID Ip6CleanAssembleTable(IN OUT IP6_ASSEMBLE_TABLE *Table)
Definition: Ip6Input.c:1136
VOID Ip6AcceptFrame(IN NET_BUF *Packet, IN EFI_STATUS IoStatus, IN UINT32 Flag, IN VOID *Context)
Definition: Ip6Input.c:976
VOID Ip6CreateAssembleTable(IN OUT IP6_ASSEMBLE_TABLE *Table)
Definition: Ip6Input.c:1117
EFI_STATUS Ip6LeaveGroup(IN IP6_SERVICE *IpSb, IN EFI_IPv6_ADDRESS *Address)
Definition: Ip6Mld.c:547
EFI_STATUS Ip6InitMld(IN IP6_SERVICE *IpSb)
Definition: Ip6Mld.c:334
VOID Ip6CleanDefaultRouterList(IN IP6_SERVICE *IpSb)
Definition: Ip6Nd.c:765
VOID Ip6CleanPrefixListTable(IN IP6_SERVICE *IpSb, IN LIST_ENTRY *ListHead)
Definition: Ip6Nd.c:391
EFI_STATUS Ip6UpdateReachableTime(IN OUT IP6_SERVICE *IpSb)
Definition: Ip6Nd.c:23
VOID EFIAPI Ip6NdFasterTimerTicking(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip6Nd.c:2797
EFI_STATUS Ip6FreeNeighborEntry(IN IP6_SERVICE *IpSb, IN IP6_NEIGHBOR_ENTRY *NeighborCache, IN BOOLEAN SendIcmpError, IN BOOLEAN FullFree, IN EFI_STATUS IoStatus, IN IP6_FRAME_TO_CANCEL FrameToCancel OPTIONAL, IN VOID *Context OPTIONAL)
Definition: Ip6Nd.c:613
VOID Ip6CleanRouteTable(IN OUT IP6_ROUTE_TABLE *RtTable)
Definition: Ip6Route.c:361
IP6_ROUTE_TABLE * Ip6CreateRouteTable(VOID)
Definition: Ip6Route.c:326
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
EFI_STATUS EFIAPI NetLibGetMacString(IN EFI_HANDLE ServiceHandle, IN EFI_HANDLE ImageHandle OPTIONAL, OUT CHAR16 **MacString)
Definition: DxeNetLib.c:2363
EFI_STATUS EFIAPI NetLibCreateServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN OUT EFI_HANDLE *ChildHandle)
Definition: DxeNetLib.c:1967
EFI_STATUS EFIAPI NetLibDestroyServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN EFI_HANDLE ChildHandle)
Definition: DxeNetLib.c:2020
BOOLEAN EFIAPI NetIsInHandleBuffer(IN EFI_HANDLE Handle, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer OPTIONAL)
Definition: DxeNetLib.c:1306
EFI_STATUS EFIAPI PseudoRandomU32(OUT UINT32 *Output)
Definition: DxeNetLib.c:1011
EFI_HANDLE EFIAPI NetLibGetNicHandle(IN EFI_HANDLE Controller, IN EFI_GUID *ProtocolGuid)
Definition: DxeNetLib.c:3019
EFI_STATUS EFIAPI NetDestroyLinkList(IN LIST_ENTRY *List, IN NET_DESTROY_LINK_LIST_CALLBACK CallBack, IN VOID *Context OPTIONAL, OUT UINTN *ListLength OPTIONAL)
Definition: DxeNetLib.c:1236
UINT16 EFIAPI NetLibGetVlanId(IN EFI_HANDLE ServiceHandle)
Definition: DxeNetLib.c:2140
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
VOID EFIAPI Exit(IN EFI_STATUS Status)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_EVENT EFIAPI EfiCreateProtocolNotifyEvent(IN EFI_GUID *ProtocolGuid, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext OPTIONAL, OUT VOID **Registration)
Definition: UefiLib.c:134
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
@ TimerCancel
Definition: UefiSpec.h:531
@ TimerPeriodic
Definition: UefiSpec.h:535
EFI_MANAGED_NETWORK_RECEIVE_DATA * RxData