X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=NetworkPkg%2FIp6Dxe%2FIp6Driver.c;h=8a8cc8916afeb965adb5ef51168f507e66e811a7;hb=aa0f2bf7cc879dc732164d1ea003b53e244c2ff4;hp=388dadef8df8e9ebc1afb8e2908af15f229d199d;hpb=a3bcde70e6dc69000f85cc5deee98101d2ae200a;p=mirror_edk2.git diff --git a/NetworkPkg/Ip6Dxe/Ip6Driver.c b/NetworkPkg/Ip6Dxe/Ip6Driver.c index 388dadef8d..8a8cc8916a 100644 --- a/NetworkPkg/Ip6Dxe/Ip6Driver.c +++ b/NetworkPkg/Ip6Dxe/Ip6Driver.c @@ -1,7 +1,8 @@ /** @file The driver binding and service binding protocol for IP6 driver. - Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -24,6 +25,32 @@ EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding = { NULL }; +BOOLEAN mIpSec2Installed = FALSE; + +/** + Callback function for IpSec2 Protocol install. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context + +**/ +VOID +EFIAPI +IpSec2InstalledCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Close the event so it does not get called again. + // + gBS->CloseEvent (Event); + + mIpSec2Installed = TRUE; + + return; +} + /** This is the declaration of an EFI image entry point. This entry point is the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including @@ -46,6 +73,16 @@ Ip6DriverEntryPoint ( IN EFI_SYSTEM_TABLE *SystemTable ) { + VOID *Registration; + + EfiCreateProtocolNotifyEvent ( + &gEfiIpSec2ProtocolGuid, + TPL_CALLBACK, + IpSec2InstalledCallback, + NULL, + &Registration + ); + return EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, @@ -94,7 +131,7 @@ Ip6DriverBindingSupported ( Clean up an IP6 service binding instance. It releases all the resource allocated by the instance. The instance may be partly initialized, or partly destroyed. If a resource is - destroyed, it is marked as that in case the destory failed and + destroyed, it is marked as that in case the destroy failed and being called again later. @param[in] IpSb The IP6 service binding instance to clean up. @@ -112,16 +149,34 @@ Ip6CleanService ( EFI_IPv6_ADDRESS AllNodes; IP6_NEIGHBOR_ENTRY *NeighborCache; + IpSb->State = IP6_SERVICE_DESTROY; + + if (IpSb->Timer != NULL) { + gBS->SetTimer (IpSb->Timer, TimerCancel, 0); + gBS->CloseEvent (IpSb->Timer); + + IpSb->Timer = NULL; + } + + if (IpSb->FasterTimer != NULL) { + gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0); + gBS->CloseEvent (IpSb->FasterTimer); + + IpSb->FasterTimer = NULL; + } + Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance); - // - // Leave link-scope all-nodes multicast address (FF02::1) - // - Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes); + if (!IpSb->LinkLocalDadFail) { + // + // Leave link-scope all-nodes multicast address (FF02::1) + // + Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes); - Status = Ip6LeaveGroup (IpSb, &AllNodes); - if (EFI_ERROR (Status)) { - return Status; + Status = Ip6LeaveGroup (IpSb, &AllNodes); + if (EFI_ERROR (Status)) { + return Status; + } } if (IpSb->DefaultInterface != NULL) { @@ -175,19 +230,6 @@ Ip6CleanService ( gBS->CloseEvent (IpSb->RecvRequest.MnpToken.Event); } - if (IpSb->Timer != NULL) { - gBS->SetTimer (IpSb->Timer, TimerCancel, 0); - gBS->CloseEvent (IpSb->Timer); - - IpSb->Timer = NULL; - } - - if (IpSb->FasterTimer != NULL) { - gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0); - gBS->CloseEvent (IpSb->FasterTimer); - - IpSb->FasterTimer = NULL; - } // // Free the Neighbor Discovery resources // @@ -223,7 +265,6 @@ Ip6CreateService ( EFI_STATUS Status; EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken; EFI_MANAGED_NETWORK_CONFIG_DATA *Config; - IP6_CONFIG_DATA_ITEM *DataItem; ASSERT (Service != NULL); @@ -244,7 +285,6 @@ Ip6CreateService ( IpSb->ServiceBinding.CreateChild = Ip6ServiceBindingCreateChild; IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild; IpSb->State = IP6_SERVICE_UNSTARTED; - IpSb->InDestroy = FALSE; IpSb->NumChildren = 0; InitializeListHead (&IpSb->Children); @@ -411,22 +451,21 @@ Ip6CreateService ( goto ON_ERROR; } - // - // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds. - // - Status = gBS->SetTimer (IpSb->FasterTimer, TimerPeriodic, TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS); + Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString); if (EFI_ERROR (Status)) { goto ON_ERROR; } - // - // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds. - // - Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_MS * IP6_ONE_SECOND_IN_MS); + Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance); if (EFI_ERROR (Status)) { goto ON_ERROR; } + IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE); + if (IpSb->DefaultInterface == NULL) { + Status = EFI_DEVICE_ERROR; + goto ON_ERROR; + } Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, @@ -439,39 +478,6 @@ Ip6CreateService ( goto ON_ERROR; } - Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance); - if (EFI_ERROR (Status)) { - goto ON_ERROR; - } - - IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE); - if (IpSb->DefaultInterface == NULL) { - Status = EFI_DEVICE_ERROR; - goto ON_ERROR; - } - - // - // If there is any manual address, set it. - // - DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress]; - if (DataItem->Data.Ptr != NULL) { - DataItem->SetData ( - &IpSb->Ip6ConfigInstance, - DataItem->DataSize, - DataItem->Data.Ptr - ); - } - InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link); *Service = IpSb; @@ -507,6 +513,12 @@ Ip6DriverBindingStart ( { IP6_SERVICE *IpSb; EFI_STATUS Status; + EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg; + IP6_CONFIG_DATA_ITEM *DataItem; + + IpSb = NULL; + Ip6Cfg = NULL; + DataItem = NULL; // // Test for the Ip6 service binding protocol @@ -532,6 +544,8 @@ Ip6DriverBindingStart ( ASSERT (IpSb != NULL); + Ip6Cfg = &IpSb->Ip6ConfigInstance.Ip6Config; + // // Install the Ip6ServiceBinding Protocol onto ControlerHandle // @@ -540,26 +554,137 @@ Ip6DriverBindingStart ( &gEfiIp6ServiceBindingProtocolGuid, &IpSb->ServiceBinding, &gEfiIp6ConfigProtocolGuid, - &IpSb->Ip6ConfigInstance.Ip6Config, + Ip6Cfg, NULL ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + // + // Read the config data from NV variable again. + // The default data can be changed by other drivers. + // + Status = Ip6ConfigReadConfigData (IpSb->MacString, &IpSb->Ip6ConfigInstance); if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // If there is any default manual address, set it. + // + DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress]; + if (DataItem->Data.Ptr != NULL) { + Status = Ip6Cfg->SetData ( + Ip6Cfg, + Ip6ConfigDataTypeManualAddress, + DataItem->DataSize, + DataItem->Data.Ptr + ); + if (EFI_ERROR(Status) && Status != EFI_NOT_READY) { + goto ON_ERROR; + } + } - Ip6CleanService (IpSb); - FreePool (IpSb); - } else { - // - // Initialize the IP6 ID - // - mIp6Id = NET_RANDOM (NetRandomInitSeed ()); + // + // If there is any default gateway address, set it. + // + DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeGateway]; + if (DataItem->Data.Ptr != NULL) { + Status = Ip6Cfg->SetData ( + Ip6Cfg, + Ip6ConfigDataTypeGateway, + DataItem->DataSize, + DataItem->Data.Ptr + ); + if (EFI_ERROR(Status)) { + goto ON_ERROR; + } + } - Ip6SetVariableData (IpSb); + // + // ready to go: start the receiving and timer + // + Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb); + if (EFI_ERROR (Status)) { + goto ON_ERROR; } + // + // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds. + // + Status = gBS->SetTimer ( + IpSb->FasterTimer, + TimerPeriodic, + TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds. + // + Status = gBS->SetTimer ( + IpSb->Timer, + TimerPeriodic, + TICKS_PER_MS * IP6_ONE_SECOND_IN_MS + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Initialize the IP6 ID + // + mIp6Id = NET_RANDOM (NetRandomInitSeed ()); + + return EFI_SUCCESS; + +ON_ERROR: + Ip6CleanService (IpSb); + FreePool (IpSb); return Status; } +/** + Callback function which provided by user to remove one node in NetDestroyLinkList process. + + @param[in] Entry The entry to be removed. + @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList. + + @retval EFI_SUCCESS The entry has been removed successfully. + @retval Others Fail to remove the entry. + +**/ +EFI_STATUS +EFIAPI +Ip6DestroyChildEntryInHandleBuffer ( + IN LIST_ENTRY *Entry, + IN VOID *Context + ) +{ + IP6_PROTOCOL *IpInstance; + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + UINTN NumberOfChildren; + EFI_HANDLE *ChildHandleBuffer; + + if (Entry == NULL || Context == NULL) { + return EFI_INVALID_PARAMETER; + } + + IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE); + ServiceBinding = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding; + NumberOfChildren = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren; + ChildHandleBuffer = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer; + + if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) { + return EFI_SUCCESS; + } + + return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle); +} + /** Stop this driver on ControllerHandle. @@ -583,30 +708,23 @@ Ip6DriverBindingStop ( IN EFI_HANDLE *ChildHandleBuffer OPTIONAL ) { - EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; - IP6_SERVICE *IpSb; - IP6_PROTOCOL *IpInstance; - EFI_HANDLE NicHandle; - EFI_STATUS Status; - BOOLEAN IsDhcp6; - EFI_TPL OldTpl; - INTN State; + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + IP6_SERVICE *IpSb; + EFI_HANDLE NicHandle; + EFI_STATUS Status; + LIST_ENTRY *List; + INTN State; + BOOLEAN IsDhcp6; + IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; IsDhcp6 = FALSE; - NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid); - - if (NicHandle != NULL) { - // - // DriverBindingStop is triggered by the uninstallation of the EFI DHCPv6 - // Protocol used by Ip6Config. - // - IsDhcp6 = TRUE; - } else { - - NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid); - - if (NicHandle == NULL) { - return EFI_DEVICE_ERROR; + NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid); + if (NicHandle == NULL) { + NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid); + if (NicHandle != NULL) { + IsDhcp6 = TRUE; + } else { + return EFI_SUCCESS; } } @@ -624,29 +742,26 @@ Ip6DriverBindingStop ( IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding); - OldTpl = gBS->RaiseTPL (TPL_CALLBACK); - - if (IpSb->InDestroy) { - Status = EFI_SUCCESS; - goto Exit; - } - if (IsDhcp6) { - Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance); gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event); IpSb->Ip6ConfigInstance.Dhcp6Event = NULL; - } else if (NumberOfChildren == 0) { - - IpSb->InDestroy = TRUE; - State = IpSb->State; - IpSb->State = IP6_SERVICE_DESTROY; - + } else if (NumberOfChildren != 0) { // - // Clear the variable data. + // NumberOfChildren is not zero, destroy the IP6 children instances in ChildHandleBuffer. // - Ip6ClearVariableData (IpSb); - + List = &IpSb->Children; + Context.ServiceBinding = ServiceBinding; + Context.NumberOfChildren = NumberOfChildren; + Context.ChildHandleBuffer = ChildHandleBuffer; + Status = NetDestroyLinkList ( + List, + Ip6DestroyChildEntryInHandleBuffer, + &Context, + NULL + ); + } else if (IsListEmpty (&IpSb->Children)) { + State = IpSb->State; Status = Ip6CleanService (IpSb); if (EFI_ERROR (Status)) { IpSb->State = State; @@ -663,24 +778,10 @@ Ip6DriverBindingStop ( ); ASSERT_EFI_ERROR (Status); FreePool (IpSb); - } else { - // - // NumberOfChildren is not zero, destroy all IP6 children instances. - // - while (!IsListEmpty (&IpSb->Children)) { - IpInstance = NET_LIST_HEAD (&IpSb->Children, IP6_PROTOCOL, Link); - ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle); - } - - if (IpSb->NumChildren != 0) { - Status = EFI_DEVICE_ERROR; - } + Status = EFI_SUCCESS; } - + Exit: - - gBS->RestoreTPL (OldTpl); - return Status; } @@ -695,7 +796,7 @@ Exit: the existing child handle. @retval EFI_SUCCES The child handle was created with the I/O services. - @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create the child. @retval other The child handle was not created. @@ -800,7 +901,7 @@ ON_ERROR: handle. @retval EFI_UNSUPPORTED The child handle does not support the I/O services that are being removed. - @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle. + @retval EFI_INVALID_PARAMETER Child handle is NULL. @retval EFI_ACCESS_DENIED The child handle could not be destroyed because its I/O services are being used. @retval other The child handle was not destroyed. @@ -818,7 +919,6 @@ Ip6ServiceBindingDestroyChild ( IP6_PROTOCOL *IpInstance; EFI_IP6_PROTOCOL *Ip6; EFI_TPL OldTpl; - INTN State; if ((This == NULL) || (ChildHandle == NULL)) { return EFI_INVALID_PARAMETER; @@ -852,17 +952,16 @@ Ip6ServiceBindingDestroyChild ( // // A child can be destroyed more than once. For example, - // Ip6DriverBindingStop will destory all of its children. - // when UDP driver is being stopped, it will destory all + // Ip6DriverBindingStop will destroy all of its children. + // when UDP driver is being stopped, it will destroy all // the IP child it opens. // - if (IpInstance->State == IP6_STATE_DESTROY) { + if (IpInstance->InDestroy) { gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; } - State = IpInstance->State; - IpInstance->State = IP6_STATE_DESTROY; + IpInstance->InDestroy = TRUE; // // Close the Managed Network protocol. @@ -888,20 +987,18 @@ Ip6ServiceBindingDestroyChild ( // will be called back before preceeding. If any packets not recycled, // that means there is a resource leak. // + gBS->RestoreTPL (OldTpl); Status = gBS->UninstallProtocolInterface ( ChildHandle, &gEfiIp6ProtocolGuid, &IpInstance->Ip6Proto ); - + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = Ip6CleanProtocol (IpInstance); - - Ip6SetVariableData (IpSb); - if (EFI_ERROR (Status)) { gBS->InstallMultipleProtocolInterfaces ( &ChildHandle, @@ -923,7 +1020,6 @@ Ip6ServiceBindingDestroyChild ( return EFI_SUCCESS; ON_ERROR: - IpInstance->State = State; gBS->RestoreTPL (OldTpl); return Status;