/** @file\r
The driver binding and service binding protocol for IP6 driver.\r
\r
- Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
NULL\r
};\r
\r
+BOOLEAN mIpSec2Installed = FALSE;\r
+\r
+/**\r
+ Callback function for IpSec2 Protocol install.\r
+\r
+ @param[in] Event Event whose notification function is being invoked\r
+ @param[in] Context Pointer to the notification function's context\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+IpSec2InstalledCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ //\r
+ // Test if protocol was even found.\r
+ // Notification function will be called at least once.\r
+ //\r
+ Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **)&mIpSec);\r
+ if (Status == EFI_SUCCESS && mIpSec != NULL) {\r
+ //\r
+ // Close the event so it does not get called again.\r
+ //\r
+ gBS->CloseEvent (Event);\r
+\r
+ mIpSec2Installed = TRUE;\r
+ }\r
+}\r
+\r
/**\r
This is the declaration of an EFI image entry point. This entry point is\r
the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
+ VOID *Registration;\r
+\r
+ EfiCreateProtocolNotifyEvent (\r
+ &gEfiIpSec2ProtocolGuid,\r
+ TPL_CALLBACK,\r
+ IpSec2InstalledCallback,\r
+ NULL,\r
+ &Registration\r
+ );\r
+\r
return EfiLibInstallDriverBindingComponentName2 (\r
ImageHandle,\r
SystemTable,\r
Clean up an IP6 service binding instance. It releases all\r
the resource allocated by the instance. The instance may be\r
partly initialized, or partly destroyed. If a resource is\r
- destroyed, it is marked as that in case the destory failed and\r
+ destroyed, it is marked as that in case the destroy failed and\r
being called again later.\r
\r
@param[in] IpSb The IP6 service binding instance to clean up.\r
EFI_IPv6_ADDRESS AllNodes;\r
IP6_NEIGHBOR_ENTRY *NeighborCache;\r
\r
+ IpSb->State = IP6_SERVICE_DESTROY;\r
+\r
+ if (IpSb->Timer != NULL) {\r
+ gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
+ gBS->CloseEvent (IpSb->Timer);\r
+\r
+ IpSb->Timer = NULL;\r
+ }\r
+\r
+ if (IpSb->FasterTimer != NULL) {\r
+ gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);\r
+ gBS->CloseEvent (IpSb->FasterTimer);\r
+\r
+ IpSb->FasterTimer = NULL;\r
+ }\r
+\r
Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance);\r
\r
- //\r
- // Leave link-scope all-nodes multicast address (FF02::1)\r
- //\r
- Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);\r
+ if (!IpSb->LinkLocalDadFail) {\r
+ //\r
+ // Leave link-scope all-nodes multicast address (FF02::1)\r
+ //\r
+ Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);\r
\r
- Status = Ip6LeaveGroup (IpSb, &AllNodes);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ Status = Ip6LeaveGroup (IpSb, &AllNodes);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
}\r
\r
if (IpSb->DefaultInterface != NULL) {\r
gBS->CloseEvent (IpSb->RecvRequest.MnpToken.Event);\r
}\r
\r
- if (IpSb->Timer != NULL) {\r
- gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
- gBS->CloseEvent (IpSb->Timer);\r
-\r
- IpSb->Timer = NULL;\r
- }\r
-\r
- if (IpSb->FasterTimer != NULL) {\r
- gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);\r
- gBS->CloseEvent (IpSb->FasterTimer);\r
-\r
- IpSb->FasterTimer = NULL;\r
- }\r
//\r
// Free the Neighbor Discovery resources\r
//\r
EFI_STATUS Status;\r
EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
EFI_MANAGED_NETWORK_CONFIG_DATA *Config;\r
- IP6_CONFIG_DATA_ITEM *DataItem;\r
\r
ASSERT (Service != NULL);\r
\r
IpSb->ServiceBinding.CreateChild = Ip6ServiceBindingCreateChild;\r
IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild;\r
IpSb->State = IP6_SERVICE_UNSTARTED;\r
- IpSb->InDestroy = FALSE;\r
\r
IpSb->NumChildren = 0;\r
InitializeListHead (&IpSb->Children);\r
goto ON_ERROR;\r
}\r
\r
- //\r
- // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.\r
- //\r
- Status = gBS->SetTimer (IpSb->FasterTimer, TimerPeriodic, TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS);\r
+ Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
\r
- //\r
- // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.\r
- //\r
- Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_MS * IP6_ONE_SECOND_IN_MS);\r
+ Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance);\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
\r
+ IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE);\r
+ if (IpSb->DefaultInterface == NULL) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_ERROR;\r
+ }\r
\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_SIGNAL,\r
goto ON_ERROR;\r
}\r
\r
- Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE);\r
- if (IpSb->DefaultInterface == NULL) {\r
- Status = EFI_DEVICE_ERROR;\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // If there is any manual address, set it.\r
- //\r
- DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress];\r
- if (DataItem->Data.Ptr != NULL) {\r
- DataItem->SetData (\r
- &IpSb->Ip6ConfigInstance,\r
- DataItem->DataSize,\r
- DataItem->Data.Ptr\r
- );\r
- }\r
-\r
InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
\r
*Service = IpSb;\r
{\r
IP6_SERVICE *IpSb;\r
EFI_STATUS Status;\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;\r
+ IP6_CONFIG_DATA_ITEM *DataItem;\r
+\r
+ IpSb = NULL;\r
+ Ip6Cfg = NULL;\r
+ DataItem = NULL;\r
\r
//\r
// Test for the Ip6 service binding protocol\r
\r
ASSERT (IpSb != NULL);\r
\r
+ Ip6Cfg = &IpSb->Ip6ConfigInstance.Ip6Config;\r
+\r
//\r
// Install the Ip6ServiceBinding Protocol onto ControlerHandle\r
//\r
&gEfiIp6ServiceBindingProtocolGuid,\r
&IpSb->ServiceBinding,\r
&gEfiIp6ConfigProtocolGuid,\r
- &IpSb->Ip6ConfigInstance.Ip6Config,\r
+ Ip6Cfg,\r
NULL\r
);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
+ //\r
+ // Read the config data from NV variable again.\r
+ // The default data can be changed by other drivers.\r
+ //\r
+ Status = Ip6ConfigReadConfigData (IpSb->MacString, &IpSb->Ip6ConfigInstance);\r
if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
- Ip6CleanService (IpSb);\r
- FreePool (IpSb);\r
- } else {\r
- //\r
- // Initialize the IP6 ID\r
- //\r
- mIp6Id = NET_RANDOM (NetRandomInitSeed ());\r
+ //\r
+ // If there is any default manual address, set it.\r
+ //\r
+ DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress];\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ Status = Ip6Cfg->SetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeManualAddress,\r
+ DataItem->DataSize,\r
+ DataItem->Data.Ptr\r
+ );\r
+ if (EFI_ERROR(Status) && Status != EFI_NOT_READY) {\r
+ goto ON_ERROR;\r
+ }\r
+ }\r
+\r
+ //\r
+ // If there is any default gateway address, set it.\r
+ //\r
+ DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeGateway];\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ Status = Ip6Cfg->SetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeGateway,\r
+ DataItem->DataSize,\r
+ DataItem->Data.Ptr\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ }\r
+\r
+ //\r
+ // ready to go: start the receiving and timer\r
+ //\r
+ Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
- Ip6SetVariableData (IpSb);\r
+ //\r
+ // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.\r
+ //\r
+ Status = gBS->SetTimer (\r
+ IpSb->FasterTimer,\r
+ TimerPeriodic,\r
+ TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
}\r
\r
+ //\r
+ // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.\r
+ //\r
+ Status = gBS->SetTimer (\r
+ IpSb->Timer,\r
+ TimerPeriodic,\r
+ TICKS_PER_MS * IP6_ONE_SECOND_IN_MS\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Initialize the IP6 ID\r
+ //\r
+ mIp6Id = NET_RANDOM (NetRandomInitSeed ());\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ Ip6CleanService (IpSb);\r
+ FreePool (IpSb);\r
return Status;\r
}\r
\r
+/**\r
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
+\r
+ @param[in] Entry The entry to be removed.\r
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
+\r
+ @retval EFI_SUCCESS The entry has been removed successfully.\r
+ @retval Others Fail to remove the entry.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ip6DestroyChildEntryInHandleBuffer (\r
+ IN LIST_ENTRY *Entry,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ IP6_PROTOCOL *IpInstance;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ UINTN NumberOfChildren;\r
+ EFI_HANDLE *ChildHandleBuffer;\r
+\r
+ if (Entry == NULL || Context == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);\r
+ ServiceBinding = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
+ NumberOfChildren = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
+ ChildHandleBuffer = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
+\r
+ if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
+}\r
+\r
/**\r
Stop this driver on ControllerHandle.\r
\r
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
)\r
{\r
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
- IP6_SERVICE *IpSb;\r
- IP6_PROTOCOL *IpInstance;\r
- EFI_HANDLE NicHandle;\r
- EFI_STATUS Status;\r
- BOOLEAN IsDhcp6;\r
- EFI_TPL OldTpl;\r
- INTN State;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ IP6_SERVICE *IpSb;\r
+ EFI_HANDLE NicHandle;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *List;\r
+ INTN State;\r
+ BOOLEAN IsDhcp6;\r
+ IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
\r
IsDhcp6 = FALSE;\r
- NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
-\r
- if (NicHandle != NULL) {\r
- //\r
- // DriverBindingStop is triggered by the uninstallation of the EFI DHCPv6\r
- // Protocol used by Ip6Config.\r
- //\r
- IsDhcp6 = TRUE;\r
- } else {\r
-\r
- NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
-\r
- if (NicHandle == NULL) {\r
- return EFI_DEVICE_ERROR;\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
+ if (NicHandle == NULL) {\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
+ if (NicHandle != NULL) {\r
+ IsDhcp6 = TRUE;\r
+ } else {\r
+ return EFI_SUCCESS;\r
}\r
}\r
\r
\r
IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- if (IpSb->InDestroy) {\r
- Status = EFI_SUCCESS;\r
- goto Exit;\r
- }\r
-\r
if (IsDhcp6) {\r
-\r
Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance);\r
gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event);\r
IpSb->Ip6ConfigInstance.Dhcp6Event = NULL;\r
- } else if (NumberOfChildren == 0) {\r
-\r
- IpSb->InDestroy = TRUE;\r
- State = IpSb->State;\r
- IpSb->State = IP6_SERVICE_DESTROY;\r
-\r
+ } else if (NumberOfChildren != 0) {\r
//\r
- // Clear the variable data.\r
+ // NumberOfChildren is not zero, destroy the IP6 children instances in ChildHandleBuffer.\r
//\r
- Ip6ClearVariableData (IpSb);\r
-\r
+ List = &IpSb->Children;\r
+ Context.ServiceBinding = ServiceBinding;\r
+ Context.NumberOfChildren = NumberOfChildren;\r
+ Context.ChildHandleBuffer = ChildHandleBuffer;\r
+ Status = NetDestroyLinkList (\r
+ List,\r
+ Ip6DestroyChildEntryInHandleBuffer,\r
+ &Context,\r
+ NULL\r
+ );\r
+ } else if (IsListEmpty (&IpSb->Children)) {\r
+ State = IpSb->State;\r
Status = Ip6CleanService (IpSb);\r
if (EFI_ERROR (Status)) {\r
IpSb->State = State;\r
);\r
ASSERT_EFI_ERROR (Status);\r
FreePool (IpSb);\r
- } else {\r
- //\r
- // NumberOfChildren is not zero, destroy all IP6 children instances.\r
- //\r
- while (!IsListEmpty (&IpSb->Children)) {\r
- IpInstance = NET_LIST_HEAD (&IpSb->Children, IP6_PROTOCOL, Link);\r
- ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
- }\r
-\r
- if (IpSb->NumChildren != 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
+ Status = EFI_SUCCESS;\r
}\r
\r
Exit:\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
return Status;\r
}\r
\r
the existing child handle.\r
\r
@retval EFI_SUCCES The child handle was created with the I/O services.\r
- @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create\r
the child.\r
@retval other The child handle was not created.\r
\r
handle.\r
@retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
that are being removed.\r
- @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
its I/O services are being used.\r
@retval other The child handle was not destroyed.\r
IP6_PROTOCOL *IpInstance;\r
EFI_IP6_PROTOCOL *Ip6;\r
EFI_TPL OldTpl;\r
- INTN State;\r
\r
if ((This == NULL) || (ChildHandle == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
\r
//\r
// A child can be destroyed more than once. For example,\r
- // Ip6DriverBindingStop will destory all of its children.\r
- // when UDP driver is being stopped, it will destory all\r
+ // Ip6DriverBindingStop will destroy all of its children.\r
+ // when UDP driver is being stopped, it will destroy all\r
// the IP child it opens.\r
//\r
- if (IpInstance->State == IP6_STATE_DESTROY) {\r
+ if (IpInstance->InDestroy) {\r
gBS->RestoreTPL (OldTpl);\r
return EFI_SUCCESS;\r
}\r
\r
- State = IpInstance->State;\r
- IpInstance->State = IP6_STATE_DESTROY;\r
+ IpInstance->InDestroy = TRUE;\r
\r
//\r
// Close the Managed Network protocol.\r
// will be called back before preceeding. If any packets not recycled,\r
// that means there is a resource leak.\r
//\r
+ gBS->RestoreTPL (OldTpl);\r
Status = gBS->UninstallProtocolInterface (\r
ChildHandle,\r
&gEfiIp6ProtocolGuid,\r
&IpInstance->Ip6Proto\r
);\r
-\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
\r
Status = Ip6CleanProtocol (IpInstance);\r
-\r
- Ip6SetVariableData (IpSb);\r
-\r
if (EFI_ERROR (Status)) {\r
gBS->InstallMultipleProtocolInterfaces (\r
&ChildHandle,\r
return EFI_SUCCESS;\r
\r
ON_ERROR:\r
- IpInstance->State = State;\r
gBS->RestoreTPL (OldTpl);\r
\r
return Status;\r