]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Config2Impl.c
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
deleted file mode 100644 (file)
index 9dca48d..0000000
+++ /dev/null
@@ -1,2168 +0,0 @@
-/** @file\r
-  The implementation of EFI IPv4 Configuration II Protocol.\r
-\r
-  Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
-  (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
-\r
-  SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "Ip4Impl.h"\r
-\r
-LIST_ENTRY  mIp4Config2InstanceList = {&mIp4Config2InstanceList, &mIp4Config2InstanceList};\r
-\r
-/**\r
-  The event process routine when the DHCPv4 service binding protocol is installed\r
-  in the system.\r
-\r
-  @param[in]     Event         Not used.\r
-  @param[in]     Context       Pointer to the IP4 config2 instance data.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4Config2OnDhcp4SbInstalled (\r
-  IN EFI_EVENT  Event,\r
-  IN VOID       *Context\r
-  );\r
-\r
-/**\r
-  Destroy the Dhcp4 child in IP4_CONFIG2_INSTANCE and release the resources.\r
-\r
-  @param[in, out] Instance    The buffer of IP4 config2 instance to be freed.\r
-\r
-  @retval EFI_SUCCESS         The child was successfully destroyed.\r
-  @retval Others              Failed to destroy the child.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2DestroyDhcp4 (\r
-  IN OUT IP4_CONFIG2_INSTANCE  *Instance\r
-  )\r
-{\r
-  IP4_SERVICE                 *IpSb;\r
-  EFI_STATUS                  Status;\r
-  EFI_DHCP4_PROTOCOL          *Dhcp4;\r
-\r
-  Dhcp4 = Instance->Dhcp4;\r
-  ASSERT (Dhcp4 != NULL);\r
-\r
-  Dhcp4->Stop (Dhcp4);\r
-  Dhcp4->Configure (Dhcp4, NULL);\r
-  Instance->Dhcp4 = NULL;\r
-\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-\r
-  //\r
-  // Close DHCPv4 protocol and destroy the child.\r
-  //\r
-  Status = gBS->CloseProtocol (\r
-                  Instance->Dhcp4Handle,\r
-                  &gEfiDhcp4ProtocolGuid,\r
-                  IpSb->Image,\r
-                  IpSb->Controller\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = NetLibDestroyServiceChild (\r
-             IpSb->Controller,\r
-             IpSb->Image,\r
-             &gEfiDhcp4ServiceBindingProtocolGuid,\r
-             Instance->Dhcp4Handle\r
-             );\r
-\r
-  Instance->Dhcp4Handle = NULL;\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Update the current policy to NewPolicy. During the transition\r
-  period, the default router list\r
-  and address list in all interfaces will be released.\r
-\r
-  @param[in]  IpSb               The IP4 service binding instance.\r
-  @param[in]  NewPolicy          The new policy to be updated to.\r
-\r
-**/\r
-VOID\r
-Ip4Config2OnPolicyChanged (\r
-  IN IP4_SERVICE            *IpSb,\r
-  IN EFI_IP4_CONFIG2_POLICY NewPolicy\r
-  )\r
-{\r
-  IP4_INTERFACE   *IpIf;\r
-  IP4_ROUTE_TABLE *RouteTable;\r
-\r
-  //\r
-  // Currently there are only two policies: static and dhcp. Regardless of\r
-  // what transition is going on, i.e., static -> dhcp and dhcp ->\r
-  // static, we have to free default router table and all addresses.\r
-  //\r
-\r
-  if (IpSb->DefaultInterface != NULL) {\r
-    if (IpSb->DefaultRouteTable != NULL) {\r
-      Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
-      IpSb->DefaultRouteTable = NULL;\r
-    }\r
-\r
-    Ip4CancelReceive (IpSb->DefaultInterface);\r
-\r
-    Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
-    IpSb->DefaultInterface = NULL;\r
-  }\r
-\r
-  Ip4CleanAssembleTable (&IpSb->Assemble);\r
-\r
-  //\r
-  // Create new default interface and route table.\r
-  //\r
-  IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
-  if (IpIf == NULL) {\r
-    return ;\r
-  }\r
-\r
-  RouteTable = Ip4CreateRouteTable ();\r
-  if (RouteTable == NULL) {\r
-    Ip4FreeInterface (IpIf, NULL);\r
-    return ;\r
-  }\r
-\r
-  IpSb->DefaultInterface  = IpIf;\r
-  InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
-  IpSb->DefaultRouteTable = RouteTable;\r
-  Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
-\r
-  if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) {\r
-    IpSb->State = IP4_SERVICE_UNSTARTED;\r
-  }\r
-\r
-  //\r
-  // Start the dhcp configuration.\r
-  //\r
-  if (NewPolicy == Ip4Config2PolicyDhcp) {\r
-    Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
-  }\r
-\r
-}\r
-\r
-/**\r
-  Signal the registered event. It is the callback routine for NetMapIterate.\r
-\r
-  @param[in]  Map    Points to the list of registered event.\r
-  @param[in]  Item   The registered event.\r
-  @param[in]  Arg    Not used.\r
-\r
-  @retval EFI_SUCCESS           The event was signaled successfully.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-Ip4Config2SignalEvent (\r
-  IN NET_MAP                *Map,\r
-  IN NET_MAP_ITEM           *Item,\r
-  IN VOID                   *Arg\r
-  )\r
-{\r
-  gBS->SignalEvent ((EFI_EVENT) Item->Key);\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Read the configuration data from variable storage according to the VarName and\r
-  gEfiIp4Config2ProtocolGuid. It checks the integrity of variable data. If the\r
-  data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the\r
-  configuration data to IP4_CONFIG2_INSTANCE.\r
-\r
-  @param[in]      VarName       The pointer to the variable name\r
-  @param[in, out] Instance      The pointer to the IP4 config2 instance data.\r
-\r
-  @retval EFI_NOT_FOUND         The variable can not be found or already corrupted.\r
-  @retval EFI_OUT_OF_RESOURCES  Fail to allocate resource to complete the operation.\r
-  @retval EFI_SUCCESS           The configuration data was retrieved successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2ReadConfigData (\r
-  IN     CHAR16               *VarName,\r
-  IN OUT IP4_CONFIG2_INSTANCE *Instance\r
-  )\r
-{\r
-  EFI_STATUS              Status;\r
-  UINTN                   VarSize;\r
-  IP4_CONFIG2_VARIABLE    *Variable;\r
-  IP4_CONFIG2_DATA_ITEM   *DataItem;\r
-  UINTN                   Index;\r
-  IP4_CONFIG2_DATA_RECORD DataRecord;\r
-  CHAR8                   *Data;\r
-\r
-  //\r
-  // Try to read the configuration variable.\r
-  //\r
-  VarSize = 0;\r
-  Status  = gRT->GetVariable (\r
-                   VarName,\r
-                   &gEfiIp4Config2ProtocolGuid,\r
-                   NULL,\r
-                   &VarSize,\r
-                   NULL\r
-                   );\r
-\r
-  if (Status == EFI_BUFFER_TOO_SMALL) {\r
-    //\r
-    // Allocate buffer and read the config variable.\r
-    //\r
-    Variable = AllocatePool (VarSize);\r
-    if (Variable == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    Status = gRT->GetVariable (\r
-                    VarName,\r
-                    &gEfiIp4Config2ProtocolGuid,\r
-                    NULL,\r
-                    &VarSize,\r
-                    Variable\r
-                    );\r
-    if (EFI_ERROR (Status) || (UINT16) (~NetblockChecksum ((UINT8 *) Variable, (UINT32) VarSize)) != 0) {\r
-      //\r
-      // GetVariable still error or the variable is corrupted.\r
-      // Fall back to the default value.\r
-      //\r
-      FreePool (Variable);\r
-\r
-      //\r
-      // Remove the problematic variable and return EFI_NOT_FOUND, a new\r
-      // variable will be set again.\r
-      //\r
-      gRT->SetVariable (\r
-             VarName,\r
-             &gEfiIp4Config2ProtocolGuid,\r
-             IP4_CONFIG2_VARIABLE_ATTRIBUTE,\r
-             0,\r
-             NULL\r
-             );\r
-\r
-      return EFI_NOT_FOUND;\r
-    }\r
-\r
-\r
-    for (Index = 0; Index < Variable->DataRecordCount; Index++) {\r
-\r
-      CopyMem (&DataRecord, &Variable->DataRecord[Index], sizeof (DataRecord));\r
-\r
-      DataItem = &Instance->DataItem[DataRecord.DataType];\r
-      if (DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED) &&\r
-          (DataItem->DataSize != DataRecord.DataSize)\r
-          ) {\r
-        //\r
-        // Perhaps a corrupted data record...\r
-        //\r
-        continue;\r
-      }\r
-\r
-      if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) {\r
-        //\r
-        // This data item has variable length data.\r
-        //\r
-        DataItem->Data.Ptr = AllocatePool (DataRecord.DataSize);\r
-        if (DataItem->Data.Ptr == NULL) {\r
-          //\r
-          // no memory resource\r
-          //\r
-          continue;\r
-        }\r
-      }\r
-\r
-      Data = (CHAR8 *) Variable + DataRecord.Offset;\r
-      CopyMem (DataItem->Data.Ptr, Data, DataRecord.DataSize);\r
-\r
-      DataItem->DataSize = DataRecord.DataSize;\r
-      DataItem->Status   = EFI_SUCCESS;\r
-    }\r
-\r
-    FreePool (Variable);\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Write the configuration data from IP4_CONFIG2_INSTANCE to variable storage.\r
-\r
-  @param[in]      VarName       The pointer to the variable name.\r
-  @param[in]      Instance      The pointer to the IP4 config2 instance data.\r
-\r
-  @retval EFI_OUT_OF_RESOURCES  Fail to allocate resource to complete the operation.\r
-  @retval EFI_SUCCESS           The configuration data is written successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2WriteConfigData (\r
-  IN CHAR16               *VarName,\r
-  IN IP4_CONFIG2_INSTANCE *Instance\r
-  )\r
-{\r
-  UINTN                   Index;\r
-  UINTN                   VarSize;\r
-  IP4_CONFIG2_DATA_ITEM   *DataItem;\r
-  IP4_CONFIG2_VARIABLE    *Variable;\r
-  IP4_CONFIG2_DATA_RECORD *DataRecord;\r
-  CHAR8                   *Heap;\r
-  EFI_STATUS              Status;\r
-\r
-  VarSize = sizeof (IP4_CONFIG2_VARIABLE) - sizeof (IP4_CONFIG2_DATA_RECORD);\r
-\r
-  for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {\r
-\r
-    DataItem = &Instance->DataItem[Index];\r
-    if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) {\r
-\r
-      VarSize += sizeof (IP4_CONFIG2_DATA_RECORD) + DataItem->DataSize;\r
-    }\r
-  }\r
-\r
-  Variable = AllocatePool (VarSize);\r
-  if (Variable == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
-  }\r
-\r
-  Heap                      = (CHAR8 *) Variable + VarSize;\r
-  Variable->DataRecordCount = 0;\r
-\r
-  for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {\r
-\r
-    DataItem = &Instance->DataItem[Index];\r
-    if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_VOLATILE) && !EFI_ERROR (DataItem->Status)) {\r
-\r
-      Heap -= DataItem->DataSize;\r
-      CopyMem (Heap, DataItem->Data.Ptr, DataItem->DataSize);\r
-\r
-      DataRecord           = &Variable->DataRecord[Variable->DataRecordCount];\r
-      DataRecord->DataType = (EFI_IP4_CONFIG2_DATA_TYPE) Index;\r
-      DataRecord->DataSize = (UINT32) DataItem->DataSize;\r
-      DataRecord->Offset   = (UINT16) (Heap - (CHAR8 *) Variable);\r
-\r
-      Variable->DataRecordCount++;\r
-    }\r
-  }\r
-\r
-  Variable->Checksum = 0;\r
-  Variable->Checksum = (UINT16) ~NetblockChecksum ((UINT8 *) Variable, (UINT32) VarSize);\r
-\r
-  Status = gRT->SetVariable (\r
-                  VarName,\r
-                  &gEfiIp4Config2ProtocolGuid,\r
-                  IP4_CONFIG2_VARIABLE_ATTRIBUTE,\r
-                  VarSize,\r
-                  Variable\r
-                  );\r
-\r
-  FreePool (Variable);\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Build a EFI_IP4_ROUTE_TABLE to be returned to the caller of GetModeData.\r
-  The EFI_IP4_ROUTE_TABLE is clumsy to use in the internal operation of the\r
-  IP4 driver.\r
-\r
-  @param[in]   IpSb        The IP4 service binding instance.\r
-  @param[out]  Table       The built IP4 route table.\r
-\r
-  @retval EFI_SUCCESS           The route table is successfully build\r
-  @retval EFI_NOT_FOUND         Failed to allocate the memory for the rotue table.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2BuildDefaultRouteTable (\r
-  IN  IP4_SERVICE               *IpSb,\r
-  OUT EFI_IP4_ROUTE_TABLE       *Table\r
-  )\r
-{\r
-  LIST_ENTRY                *Entry;\r
-  IP4_ROUTE_ENTRY           *RtEntry;\r
-  UINT32                    Count;\r
-  INT32                     Index;\r
-\r
-  if (IpSb->DefaultRouteTable == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  Count = IpSb->DefaultRouteTable->TotalNum;\r
-\r
-  if (Count == 0) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  //\r
-  // Copy the route entry to EFI route table. Keep the order of\r
-  // route entry copied from most specific to default route. That\r
-  // is, interlevel the route entry from the instance's route area\r
-  // and those from the default route table's route area.\r
-  //\r
-  Count = 0;\r
-\r
-  for (Index = IP4_MASK_MAX; Index >= 0; Index--) {\r
-\r
-    NET_LIST_FOR_EACH (Entry, &(IpSb->DefaultRouteTable->RouteArea[Index])) {\r
-      RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);\r
-\r
-      EFI_IP4 (Table[Count].SubnetAddress)  = HTONL (RtEntry->Dest & RtEntry->Netmask);\r
-      EFI_IP4 (Table[Count].SubnetMask)     = HTONL (RtEntry->Netmask);\r
-      EFI_IP4 (Table[Count].GatewayAddress) = HTONL (RtEntry->NextHop);\r
-\r
-      Count++;\r
-    }\r
-\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  The event process routine when the DHCPv4 service binding protocol is installed\r
-  in the system.\r
-\r
-  @param[in]     Event         Not used.\r
-  @param[in]     Context       The pointer to the IP4 config2 instance data.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4Config2OnDhcp4SbInstalled (\r
-  IN EFI_EVENT  Event,\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  IP4_CONFIG2_INSTANCE  *Instance;\r
-\r
-  Instance = (IP4_CONFIG2_INSTANCE *) Context;\r
-\r
-  if ((Instance->Dhcp4Handle != NULL) || (Instance->Policy != Ip4Config2PolicyDhcp)) {\r
-    //\r
-    // The DHCP4 child is already created or the policy is no longer DHCP.\r
-    //\r
-    return ;\r
-  }\r
-\r
-  Ip4StartAutoConfig (Instance);\r
-}\r
-\r
-/**\r
-  Set the station address and subnetmask for the default interface.\r
-\r
-  @param[in]  IpSb               The pointer to the IP4 service binding instance.\r
-  @param[in]  StationAddress     Ip address to be set.\r
-  @param[in]  SubnetMask         Subnet to be set.\r
-\r
-  @retval EFI_SUCCESS   Set default address successful.\r
-  @retval Others        Some errors occur in setting.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2SetDefaultAddr (\r
-  IN IP4_SERVICE            *IpSb,\r
-  IN IP4_ADDR               StationAddress,\r
-  IN IP4_ADDR               SubnetMask\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  IP4_INTERFACE             *IpIf;\r
-  IP4_PROTOCOL              *Ip4Instance;\r
-  EFI_ARP_PROTOCOL          *Arp;\r
-  LIST_ENTRY                *Entry;\r
-  IP4_ADDR                  Subnet;\r
-  IP4_ROUTE_TABLE           *RouteTable;\r
-\r
-  IpIf = IpSb->DefaultInterface;\r
-  ASSERT (IpIf != NULL);\r
-\r
-  if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) {\r
-    IpSb->State = IP4_SERVICE_CONFIGED;\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if (IpSb->Reconfig) {\r
-    //\r
-    // The default address is changed, free the previous interface first.\r
-    //\r
-    if (IpSb->DefaultRouteTable != NULL) {\r
-      Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
-      IpSb->DefaultRouteTable = NULL;\r
-    }\r
-\r
-    Ip4CancelReceive (IpSb->DefaultInterface);\r
-    Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
-    IpSb->DefaultInterface = NULL;\r
-    //\r
-    // Create new default interface and route table.\r
-    //\r
-    IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
-    if (IpIf == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    RouteTable = Ip4CreateRouteTable ();\r
-    if (RouteTable == NULL) {\r
-      Ip4FreeInterface (IpIf, NULL);\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    IpSb->DefaultInterface  = IpIf;\r
-    InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
-    IpSb->DefaultRouteTable = RouteTable;\r
-    Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
-  }\r
-\r
-  if (IpSb->State == IP4_SERVICE_CONFIGED) {\r
-    IpSb->State = IP4_SERVICE_UNSTARTED;\r
-  }\r
-\r
-  Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (IpIf->Arp != NULL) {\r
-    //\r
-    // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address,\r
-    // but some IP children may have referenced the default interface before it is configured,\r
-    // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.\r
-    //\r
-    Arp = NULL;\r
-    NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {\r
-      Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE);\r
-      Status = gBS->OpenProtocol (\r
-                      IpIf->ArpHandle,\r
-                      &gEfiArpProtocolGuid,\r
-                      (VOID **) &Arp,\r
-                      gIp4DriverBinding.DriverBindingHandle,\r
-                      Ip4Instance->Handle,\r
-                      EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-                      );\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  // Add a route for the connected network.\r
-  //\r
-  Subnet = StationAddress & SubnetMask;\r
-\r
-  Ip4AddRoute (\r
-    IpSb->DefaultRouteTable,\r
-    Subnet,\r
-    SubnetMask,\r
-    IP4_ALLZERO_ADDRESS\r
-    );\r
-\r
-  IpSb->State = IP4_SERVICE_CONFIGED;\r
-  IpSb->Reconfig = FALSE;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Set the station address, subnetmask and gateway address for the default interface.\r
-\r
-  @param[in]  Instance         The pointer to the IP4 config2 instance data.\r
-  @param[in]  StationAddress   Ip address to be set.\r
-  @param[in]  SubnetMask       Subnet to be set.\r
-  @param[in]  GatewayAddress   Gateway to be set.\r
-\r
-  @retval EFI_SUCCESS     Set default If successful.\r
-  @retval Others          Errors occur as indicated.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2SetDefaultIf (\r
-  IN IP4_CONFIG2_INSTANCE   *Instance,\r
-  IN IP4_ADDR               StationAddress,\r
-  IN IP4_ADDR               SubnetMask,\r
-  IN IP4_ADDR               GatewayAddress\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-  IP4_SERVICE               *IpSb;\r
-\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-\r
-  //\r
-  // Check whether the StationAddress/SubnetMask pair is valid.\r
-  //\r
-  if (!Ip4StationAddressValid (StationAddress, SubnetMask)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Create a route if there is a default router.\r
-  //\r
-  if (GatewayAddress != IP4_ALLZERO_ADDRESS) {\r
-    Ip4AddRoute (\r
-      IpSb->DefaultRouteTable,\r
-      IP4_ALLZERO_ADDRESS,\r
-      IP4_ALLZERO_ADDRESS,\r
-      GatewayAddress\r
-      );\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Release all the DHCP related resources.\r
-\r
-  @param  Instance              The IP4 config2 instance.\r
-\r
-  @return None\r
-\r
-**/\r
-VOID\r
-Ip4Config2CleanDhcp4 (\r
-  IN IP4_CONFIG2_INSTANCE   *Instance\r
-  )\r
-{\r
-  IP4_SERVICE               *IpSb;\r
-\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-\r
-  if (Instance->Dhcp4 != NULL) {\r
-    Instance->Dhcp4->Stop (Instance->Dhcp4);\r
-\r
-    gBS->CloseProtocol (\r
-          Instance->Dhcp4Handle,\r
-          &gEfiDhcp4ProtocolGuid,\r
-          IpSb->Image,\r
-          IpSb->Controller\r
-          );\r
-\r
-    Instance->Dhcp4 = NULL;\r
-  }\r
-\r
-  if (Instance->Dhcp4Handle != NULL) {\r
-    NetLibDestroyServiceChild (\r
-      IpSb->Controller,\r
-      IpSb->Image,\r
-      &gEfiDhcp4ServiceBindingProtocolGuid,\r
-      Instance->Dhcp4Handle\r
-      );\r
-\r
-    Instance->Dhcp4Handle = NULL;\r
-  }\r
-\r
-  if (Instance->Dhcp4Event != NULL) {\r
-    gBS->CloseEvent (Instance->Dhcp4Event);\r
-    Instance->Dhcp4Event = NULL;\r
-  }\r
-}\r
-\r
-/**\r
-  This worker function sets the DNS server list for the EFI IPv4 network\r
-  stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL\r
-  manages. The DNS server addresses must be unicast IPv4 addresses.\r
-\r
-  @param[in]     Instance        The pointer to the IP4 config2 instance data.\r
-  @param[in]     DataSize        The size of the buffer pointed to by Data in bytes.\r
-  @param[in]     Data            The data buffer to set, points to an array of\r
-                                 EFI_IPv4_ADDRESS instances.\r
-\r
-  @retval EFI_BAD_BUFFER_SIZE    The DataSize does not match the size of the type.\r
-  @retval EFI_INVALID_PARAMETER  One or more fields in Data is invalid.\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources to complete the operation.\r
-  @retval EFI_ABORTED            The DNS server addresses to be set equal the current\r
-                                 configuration.\r
-  @retval EFI_SUCCESS            The specified configuration data for the EFI IPv4\r
-                                 network stack was set.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2SetDnsServerWorker (\r
-  IN IP4_CONFIG2_INSTANCE    *Instance,\r
-  IN UINTN                   DataSize,\r
-  IN VOID                    *Data\r
-  )\r
-{\r
-  UINTN                 OldIndex;\r
-  UINTN                 NewIndex;\r
-  EFI_IPv4_ADDRESS      *OldDns;\r
-  EFI_IPv4_ADDRESS      *NewDns;\r
-  UINTN                 OldDnsCount;\r
-  UINTN                 NewDnsCount;\r
-  IP4_CONFIG2_DATA_ITEM *Item;\r
-  BOOLEAN               OneAdded;\r
-  VOID                  *Tmp;\r
-  IP4_ADDR              DnsAddress;\r
-\r
-  if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {\r
-    return EFI_BAD_BUFFER_SIZE;\r
-  }\r
-\r
-  Item        = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
-  NewDns      = (EFI_IPv4_ADDRESS *) Data;\r
-  OldDns      = Item->Data.DnsServers;\r
-  NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
-  OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
-  OneAdded    = FALSE;\r
-\r
-  if (NewDnsCount != OldDnsCount) {\r
-    Tmp = AllocatePool (DataSize);\r
-    if (Tmp == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-  } else {\r
-    Tmp = NULL;\r
-  }\r
-\r
-  for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {\r
-    CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));\r
-    if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress))) {\r
-      //\r
-      // The dns server address must be unicast.\r
-      //\r
-      if (Tmp != NULL) {\r
-        FreePool (Tmp);\r
-      }\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    if (OneAdded) {\r
-      //\r
-      // If any address in the new setting is not in the old settings, skip the\r
-      // comparision below.\r
-      //\r
-      continue;\r
-    }\r
-\r
-    for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {\r
-      if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {\r
-        //\r
-        // If found break out.\r
-        //\r
-        break;\r
-      }\r
-    }\r
-\r
-    if (OldIndex == OldDnsCount) {\r
-      OneAdded = TRUE;\r
-    }\r
-  }\r
-\r
-  if (!OneAdded && (DataSize == Item->DataSize)) {\r
-    //\r
-    // No new item is added and the size is the same.\r
-    //\r
-    Item->Status = EFI_SUCCESS;\r
-    return EFI_ABORTED;\r
-  } else {\r
-    if (Tmp != NULL) {\r
-      if (Item->Data.Ptr != NULL) {\r
-        FreePool (Item->Data.Ptr);\r
-      }\r
-      Item->Data.Ptr = Tmp;\r
-    }\r
-\r
-    CopyMem (Item->Data.Ptr, Data, DataSize);\r
-    Item->DataSize = DataSize;\r
-    Item->Status   = EFI_SUCCESS;\r
-    return EFI_SUCCESS;\r
-  }\r
-}\r
-\r
-\r
-\r
-/**\r
-  Callback function when DHCP process finished. It will save the\r
-  retrieved IP configure parameter from DHCP to the NVRam.\r
-\r
-  @param  Event                  The callback event\r
-  @param  Context                Opaque context to the callback\r
-\r
-  @return None\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4Config2OnDhcp4Complete (\r
-  IN EFI_EVENT              Event,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  IP4_CONFIG2_INSTANCE      *Instance;\r
-  EFI_DHCP4_MODE_DATA       Dhcp4Mode;\r
-  EFI_STATUS                Status;\r
-  IP4_ADDR                  StationAddress;\r
-  IP4_ADDR                  SubnetMask;\r
-  IP4_ADDR                  GatewayAddress;\r
-  UINT32                    Index;\r
-  UINT32                    OptionCount;\r
-  EFI_DHCP4_PACKET_OPTION   **OptionList;\r
-\r
-  Instance = (IP4_CONFIG2_INSTANCE *) Context;\r
-  ASSERT (Instance->Dhcp4 != NULL);\r
-\r
-  //\r
-  // Get the DHCP retrieved parameters\r
-  //\r
-  Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto Exit;\r
-  }\r
-\r
-  if (Dhcp4Mode.State == Dhcp4Bound) {\r
-    StationAddress = EFI_NTOHL (Dhcp4Mode.ClientAddress);\r
-    SubnetMask = EFI_NTOHL (Dhcp4Mode.SubnetMask);\r
-    GatewayAddress = EFI_NTOHL (Dhcp4Mode.RouterAddress);\r
-\r
-    Status = Ip4Config2SetDefaultIf (Instance, StationAddress, SubnetMask, GatewayAddress);\r
-    if (EFI_ERROR (Status)) {\r
-      goto Exit;\r
-    }\r
-\r
-    //\r
-    // Parse the ACK to get required DNS server information.\r
-    //\r
-    OptionCount = 0;\r
-    OptionList  = NULL;\r
-\r
-    Status      = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);\r
-    if (Status != EFI_BUFFER_TOO_SMALL) {\r
-      goto Exit;\r
-    }\r
-\r
-    OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
-    if (OptionList == NULL) {\r
-      goto Exit;\r
-    }\r
-\r
-    Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);\r
-    if (EFI_ERROR (Status)) {\r
-      FreePool (OptionList);\r
-      goto Exit;\r
-    }\r
-\r
-    for (Index = 0; Index < OptionCount; Index++) {\r
-      //\r
-      // Look for DNS Server opcode (6).\r
-      //\r
-      if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) {\r
-        if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {\r
-          break;\r
-        }\r
-\r
-        Ip4Config2SetDnsServerWorker (Instance, OptionList[Index]->Length, &OptionList[Index]->Data[0]);\r
-        break;\r
-      }\r
-    }\r
-\r
-    FreePool (OptionList);\r
-\r
-    Instance->DhcpSuccess = TRUE;\r
-  }\r
-\r
-Exit:\r
-  Ip4Config2CleanDhcp4 (Instance);\r
-  DispatchDpc ();\r
-}\r
-\r
-\r
-/**\r
-  Start the DHCP configuration for this IP service instance.\r
-  It will locates the EFI_IP4_CONFIG2_PROTOCOL, then start the\r
-  DHCP configuration.\r
-\r
-  @param[in]  Instance           The IP4 config2 instance to configure\r
-\r
-  @retval EFI_SUCCESS            The auto configuration is successfully started\r
-  @retval Others                 Failed to start auto configuration.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4StartAutoConfig (\r
-  IN IP4_CONFIG2_INSTANCE   *Instance\r
-  )\r
-{\r
-  IP4_SERVICE                    *IpSb;\r
-  EFI_DHCP4_PROTOCOL             *Dhcp4;\r
-  EFI_DHCP4_MODE_DATA            Dhcp4Mode;\r
-  EFI_DHCP4_PACKET_OPTION        *OptionList[1];\r
-  IP4_CONFIG2_DHCP4_OPTION       ParaList;\r
-  EFI_STATUS                     Status;\r
-\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-\r
-  if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // A host must not invoke DHCP configuration if it is already\r
-  // participating in the DHCP configuraiton process.\r
-  //\r
-  if (Instance->Dhcp4Handle != NULL) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  Status = NetLibCreateServiceChild (\r
-             IpSb->Controller,\r
-             IpSb->Image,\r
-             &gEfiDhcp4ServiceBindingProtocolGuid,\r
-             &Instance->Dhcp4Handle\r
-             );\r
-\r
-  if (Status == EFI_UNSUPPORTED) {\r
-    //\r
-    // No DHCPv4 Service Binding protocol, register a notify.\r
-    //\r
-    if (Instance->Dhcp4SbNotifyEvent == NULL) {\r
-      Instance->Dhcp4SbNotifyEvent = EfiCreateProtocolNotifyEvent (\r
-                                       &gEfiDhcp4ServiceBindingProtocolGuid,\r
-                                       TPL_CALLBACK,\r
-                                       Ip4Config2OnDhcp4SbInstalled,\r
-                                       (VOID *) Instance,\r
-                                       &Instance->Registration\r
-                                       );\r
-    }\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (Instance->Dhcp4SbNotifyEvent != NULL) {\r
-    gBS->CloseEvent (Instance->Dhcp4SbNotifyEvent);\r
-  }\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  Instance->Dhcp4Handle,\r
-                  &gEfiDhcp4ProtocolGuid,\r
-                  (VOID **) &Instance->Dhcp4,\r
-                  IpSb->Image,\r
-                  IpSb->Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    NetLibDestroyServiceChild (\r
-      IpSb->Controller,\r
-      IpSb->Image,\r
-      &gEfiDhcp4ServiceBindingProtocolGuid,\r
-      Instance->Dhcp4Handle\r
-      );\r
-\r
-    Instance->Dhcp4Handle = NULL;\r
-\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Check the current DHCP status, if the DHCP process has\r
-  // already finished, return now.\r
-  //\r
-  Dhcp4  = Instance->Dhcp4;\r
-  Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);\r
-  if (Dhcp4Mode.State == Dhcp4Bound) {\r
-    Ip4Config2OnDhcp4Complete (NULL, Instance);\r
-\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // Try to start the DHCP process. Use most of the current\r
-  // DHCP configuration to avoid problems if some DHCP client\r
-  // yields the control of this DHCP service to us.\r
-  //\r
-  ParaList.Head.OpCode             = DHCP4_TAG_PARA_LIST;\r
-  ParaList.Head.Length             = 3;\r
-  ParaList.Head.Data[0]            = DHCP4_TAG_NETMASK;\r
-  ParaList.Route                   = DHCP4_TAG_ROUTER;\r
-  ParaList.Dns                     = DHCP4_TAG_DNS_SERVER;\r
-  OptionList[0]                    = &ParaList.Head;\r
-  Dhcp4Mode.ConfigData.OptionCount = 1;\r
-  Dhcp4Mode.ConfigData.OptionList  = OptionList;\r
-\r
-  Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);\r
-  if (EFI_ERROR (Status)) {\r
-    gBS->CloseProtocol (\r
-           Instance->Dhcp4Handle,\r
-           &gEfiDhcp4ProtocolGuid,\r
-           IpSb->Image,\r
-           IpSb->Controller\r
-           );\r
-\r
-    NetLibDestroyServiceChild (\r
-      IpSb->Controller,\r
-      IpSb->Image,\r
-      &gEfiDhcp4ServiceBindingProtocolGuid,\r
-      Instance->Dhcp4Handle\r
-      );\r
-\r
-    Instance->Dhcp4 = NULL;\r
-\r
-    Instance->Dhcp4Handle = NULL;\r
-\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Start the DHCP process\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  Ip4Config2OnDhcp4Complete,\r
-                  Instance,\r
-                  &Instance->Dhcp4Event\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    Ip4Config2DestroyDhcp4 (Instance);\r
-    return Status;\r
-  }\r
-\r
-  Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);\r
-  if (EFI_ERROR (Status)) {\r
-    Ip4Config2DestroyDhcp4 (Instance);\r
-    gBS->CloseEvent (Instance->Dhcp4Event);\r
-    Instance->Dhcp4Event = NULL;\r
-\r
-    return Status;\r
-  }\r
-\r
-  IpSb->State = IP4_SERVICE_STARTED;\r
-  DispatchDpc ();\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-\r
-/**\r
-  The work function is to get the interface information of the communication\r
-  device this IP4_CONFIG2_INSTANCE manages.\r
-\r
-  @param[in]      Instance Pointer to the IP4 config2 instance data.\r
-  @param[in, out] DataSize On input, in bytes, the size of Data. On output, in\r
-                           bytes, the size of buffer required to store the specified\r
-                           configuration data.\r
-  @param[in]      Data     The data buffer in which the configuration data is returned.\r
-                           Ignored if DataSize is ZERO.\r
-\r
-  @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified\r
-                               configuration data, and the required size is\r
-                               returned in DataSize.\r
-  @retval EFI_SUCCESS          The specified configuration data was obtained.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2GetIfInfo (\r
-  IN IP4_CONFIG2_INSTANCE *Instance,\r
-  IN OUT UINTN            *DataSize,\r
-  IN VOID                 *Data      OPTIONAL\r
-  )\r
-{\r
-  IP4_SERVICE                    *IpSb;\r
-  UINTN                          Length;\r
-  IP4_CONFIG2_DATA_ITEM          *Item;\r
-  EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;\r
-  IP4_ADDR                       Address;\r
-\r
-  IpSb   = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-  Length = sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO);\r
-\r
-  if (IpSb->DefaultRouteTable != NULL) {\r
-    Length += IpSb->DefaultRouteTable->TotalNum * sizeof (EFI_IP4_ROUTE_TABLE);\r
-  }\r
-\r
-  if (*DataSize < Length) {\r
-    *DataSize = Length;\r
-    return EFI_BUFFER_TOO_SMALL;\r
-  }\r
-\r
-  //\r
-  // Copy the fixed size part of the interface info.\r
-  //\r
-  Item = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo];\r
-  IfInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *) Data;\r
-  CopyMem (IfInfo, Item->Data.Ptr, sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO));\r
-\r
-  //\r
-  // Update the address info.\r
-  //\r
-  if (IpSb->DefaultInterface != NULL) {\r
-    Address = HTONL (IpSb->DefaultInterface->Ip);\r
-    CopyMem (&IfInfo->StationAddress, &Address, sizeof (EFI_IPv4_ADDRESS));\r
-    Address = HTONL (IpSb->DefaultInterface->SubnetMask);\r
-    CopyMem (&IfInfo->SubnetMask, &Address, sizeof (EFI_IPv4_ADDRESS));\r
-  }\r
-\r
-  if (IpSb->DefaultRouteTable != NULL) {\r
-    IfInfo->RouteTableSize = IpSb->DefaultRouteTable->TotalNum;\r
-    IfInfo->RouteTable   = (EFI_IP4_ROUTE_TABLE *) ((UINT8 *) Data + sizeof (EFI_IP4_CONFIG2_INTERFACE_INFO));\r
-\r
-    Ip4Config2BuildDefaultRouteTable (IpSb, IfInfo->RouteTable);\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  The work function is to set the general configuration policy for the EFI IPv4 network\r
-  stack that is running on the communication device managed by this IP4_CONFIG2_INSTANCE.\r
-  The policy will affect other configuration settings.\r
-\r
-  @param[in]     Instance Pointer to the IP4 config2 instance data.\r
-  @param[in]     DataSize Size of the buffer pointed to by Data in bytes.\r
-  @param[in]     Data     The data buffer to set.\r
-\r
-  @retval EFI_INVALID_PARAMETER The to be set policy is invalid.\r
-  @retval EFI_BAD_BUFFER_SIZE   The DataSize does not match the size of the type.\r
-  @retval EFI_ABORTED           The new policy equals the current policy.\r
-  @retval EFI_SUCCESS           The specified configuration data for the EFI IPv6\r
-                                network stack was set.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2SetPolicy (\r
-  IN IP4_CONFIG2_INSTANCE *Instance,\r
-  IN UINTN                DataSize,\r
-  IN VOID                 *Data\r
-  )\r
-{\r
-  EFI_IP4_CONFIG2_POLICY NewPolicy;\r
-  IP4_CONFIG2_DATA_ITEM  *DataItem;\r
-  IP4_SERVICE            *IpSb;\r
-\r
-  if (DataSize != sizeof (EFI_IP4_CONFIG2_POLICY)) {\r
-    return EFI_BAD_BUFFER_SIZE;\r
-  }\r
-\r
-  NewPolicy = *((EFI_IP4_CONFIG2_POLICY *) Data);\r
-\r
-  if (NewPolicy >= Ip4Config2PolicyMax) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (NewPolicy == Instance->Policy) {\r
-    if (NewPolicy != Ip4Config2PolicyDhcp || Instance->DhcpSuccess) {\r
-      return EFI_ABORTED;\r
-    }\r
-  } else {\r
-    //\r
-    // The policy is changed. Clean the ManualAddress, Gateway and DnsServers,\r
-    // shrink the variable data size, and fire up all the related events.\r
-    //\r
-    DataItem           = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
-    if (DataItem->Data.Ptr != NULL) {\r
-      FreePool (DataItem->Data.Ptr);\r
-    }\r
-    DataItem->Data.Ptr = NULL;\r
-    DataItem->DataSize = 0;\r
-    DataItem->Status   = EFI_NOT_FOUND;\r
-    NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
-\r
-    DataItem           = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
-    if (DataItem->Data.Ptr != NULL) {\r
-      FreePool (DataItem->Data.Ptr);\r
-    }\r
-    DataItem->Data.Ptr = NULL;\r
-    DataItem->DataSize = 0;\r
-    DataItem->Status   = EFI_NOT_FOUND;\r
-    NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
-\r
-    DataItem           = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
-    if (DataItem->Data.Ptr != NULL) {\r
-      FreePool (DataItem->Data.Ptr);\r
-    }\r
-    DataItem->Data.Ptr = NULL;\r
-    DataItem->DataSize = 0;\r
-    DataItem->Status   = EFI_NOT_FOUND;\r
-    NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
-\r
-    if (NewPolicy == Ip4Config2PolicyDhcp) {\r
-      SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_VOLATILE);\r
-    } else {\r
-      //\r
-      // The policy is changed from dhcp to static. Stop the DHCPv4 process\r
-      // and destroy the DHCPv4 child.\r
-      //\r
-      if (Instance->Dhcp4Handle != NULL) {\r
-        Ip4Config2DestroyDhcp4 (Instance);\r
-      }\r
-\r
-      //\r
-      // Close the event.\r
-      //\r
-      if (Instance->Dhcp4Event != NULL) {\r
-        gBS->CloseEvent (Instance->Dhcp4Event);\r
-        Instance->Dhcp4Event = NULL;\r
-      }\r
-    }\r
-  }\r
-\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-  Ip4Config2OnPolicyChanged (IpSb, NewPolicy);\r
-\r
-  Instance->Policy = NewPolicy;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  The work function is to set the station addresses manually for the EFI IPv4\r
-  network stack. It is only configurable when the policy is Ip4Config2PolicyStatic.\r
-\r
-  @param[in]     Instance Pointer to the IP4 config2 instance data.\r
-  @param[in]     DataSize Size of the buffer pointed to by Data in bytes.\r
-  @param[in]     Data     The data buffer to set.\r
-\r
-  @retval EFI_BAD_BUFFER_SIZE   The DataSize does not match the size of the type.\r
-  @retval EFI_WRITE_PROTECTED   The specified configuration data cannot be set\r
-                                under the current policy.\r
-  @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.\r
-  @retval EFI_OUT_OF_RESOURCES  Fail to allocate resource to complete the operation.\r
-  @retval EFI_NOT_READY         An asynchrous process is invoked to set the specified\r
-                                configuration data, and the process is not finished.\r
-  @retval EFI_ABORTED           The manual addresses to be set equal current\r
-                                configuration.\r
-  @retval EFI_SUCCESS           The specified configuration data for the EFI IPv6\r
-                                network stack was set.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2SetManualAddress (\r
-  IN IP4_CONFIG2_INSTANCE *Instance,\r
-  IN UINTN                DataSize,\r
-  IN VOID                 *Data\r
-  )\r
-{\r
-  EFI_IP4_CONFIG2_MANUAL_ADDRESS NewAddress;\r
-  IP4_CONFIG2_DATA_ITEM          *DataItem;\r
-  EFI_STATUS                     Status;\r
-  IP4_ADDR                       StationAddress;\r
-  IP4_ADDR                       SubnetMask;\r
-  VOID                           *Ptr;\r
-  IP4_SERVICE                    *IpSb;\r
-  IP4_INTERFACE                  *IpIf;\r
-  IP4_ROUTE_TABLE                *RouteTable;\r
-\r
-  DataItem   = NULL;\r
-  Status     = EFI_SUCCESS;\r
-  Ptr        = NULL;\r
-  IpIf       = NULL;\r
-  RouteTable = NULL;\r
-\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-\r
-  ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY);\r
-\r
-  if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0)) {\r
-    return EFI_BAD_BUFFER_SIZE;\r
-  }\r
-\r
-  if (Instance->Policy != Ip4Config2PolicyStatic) {\r
-    return EFI_WRITE_PROTECTED;\r
-  }\r
-\r
-  DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
-\r
-  if (Data != NULL && DataSize != 0) {\r
-    NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);\r
-\r
-    StationAddress = EFI_NTOHL (NewAddress.Address);\r
-    SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
-\r
-    //\r
-    // Check whether the StationAddress/SubnetMask pair is valid.\r
-    //\r
-    if (!Ip4StationAddressValid (StationAddress, SubnetMask)) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    //\r
-    // Store the new data, and init the DataItem status to EFI_NOT_READY because\r
-    // we may have an asynchronous configuration process.\r
-    //\r
-    Ptr = AllocateCopyPool (DataSize, Data);\r
-    if (Ptr == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    if (DataItem->Data.Ptr != NULL) {\r
-      FreePool (DataItem->Data.Ptr);\r
-    }\r
-\r
-    DataItem->Data.Ptr = Ptr;\r
-    DataItem->DataSize = DataSize;\r
-    DataItem->Status   = EFI_NOT_READY;\r
-\r
-    IpSb->Reconfig = TRUE;\r
-    Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);\r
-\r
-    DataItem->Status = Status;\r
-\r
-    if (EFI_ERROR (DataItem->Status) && DataItem->Status != EFI_NOT_READY) {\r
-      if (Ptr != NULL) {\r
-        FreePool (Ptr);\r
-      }\r
-      DataItem->Data.Ptr = NULL;\r
-    }\r
-  } else {\r
-    //\r
-    // DataSize is 0 and Data is NULL, clean up the manual address.\r
-    //\r
-    if (DataItem->Data.Ptr != NULL) {\r
-      FreePool (DataItem->Data.Ptr);\r
-    }\r
-    DataItem->Data.Ptr = NULL;\r
-    DataItem->DataSize = 0;\r
-    DataItem->Status   = EFI_NOT_FOUND;\r
-\r
-    //\r
-    // Free the default router table and Interface, clean up the assemble table.\r
-    //\r
-    if (IpSb->DefaultInterface != NULL) {\r
-      if (IpSb->DefaultRouteTable != NULL) {\r
-        Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
-        IpSb->DefaultRouteTable = NULL;\r
-      }\r
-\r
-      Ip4CancelReceive (IpSb->DefaultInterface);\r
-\r
-      Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
-      IpSb->DefaultInterface = NULL;\r
-    }\r
-\r
-    Ip4CleanAssembleTable (&IpSb->Assemble);\r
-\r
-    //\r
-    // Create new default interface and route table.\r
-    //\r
-    IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
-    if (IpIf == NULL) {\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    RouteTable = Ip4CreateRouteTable ();\r
-    if (RouteTable == NULL) {\r
-      Ip4FreeInterface (IpIf, NULL);\r
-      return EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-    IpSb->DefaultInterface  = IpIf;\r
-    InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
-    IpSb->DefaultRouteTable = RouteTable;\r
-    Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
-\r
-    //\r
-    // Reset the State to unstarted.\r
-    //\r
-    if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) {\r
-      IpSb->State = IP4_SERVICE_UNSTARTED;\r
-    }\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  The work function is to set the gateway addresses manually for the EFI IPv4\r
-  network stack that is running on the communication device that this EFI IPv4\r
-  Configuration Protocol manages. It is not configurable when the policy is\r
-  Ip4Config2PolicyDhcp. The gateway addresses must be unicast IPv4 addresses.\r
-\r
-  @param[in]     Instance The pointer to the IP4 config2 instance data.\r
-  @param[in]     DataSize The size of the buffer pointed to by Data in bytes.\r
-  @param[in]     Data     The data buffer to set. This points to an array of\r
-                          EFI_IPv6_ADDRESS instances.\r
-\r
-  @retval EFI_BAD_BUFFER_SIZE   The DataSize does not match the size of the type.\r
-  @retval EFI_WRITE_PROTECTED   The specified configuration data cannot be set\r
-                                under the current policy.\r
-  @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.\r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to complete the operation.\r
-  @retval EFI_ABORTED           The manual gateway addresses to be set equal the\r
-                                current configuration.\r
-  @retval EFI_SUCCESS           The specified configuration data for the EFI IPv6\r
-                                network stack was set.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2SetGateway (\r
-  IN IP4_CONFIG2_INSTANCE *Instance,\r
-  IN UINTN                DataSize,\r
-  IN VOID                 *Data\r
-  )\r
-{\r
-  IP4_SERVICE                    *IpSb;\r
-  IP4_CONFIG2_DATA_ITEM          *DataItem;\r
-  IP4_ADDR                       Gateway;\r
-\r
-  UINTN                 Index1;\r
-  UINTN                 Index2;\r
-  EFI_IPv4_ADDRESS      *OldGateway;\r
-  EFI_IPv4_ADDRESS      *NewGateway;\r
-  UINTN                 OldGatewayCount;\r
-  UINTN                 NewGatewayCount;\r
-  BOOLEAN               OneRemoved;\r
-  BOOLEAN               OneAdded;\r
-  VOID                  *Tmp;\r
-\r
-  OldGateway      = NULL;\r
-  NewGateway      = NULL;\r
-  OneRemoved      = FALSE;\r
-  OneAdded        = FALSE;\r
-  Tmp             = NULL;\r
-\r
-  if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv4_ADDRESS) != 0)) {\r
-    return EFI_BAD_BUFFER_SIZE;\r
-  }\r
-\r
-  if (Instance->Policy != Ip4Config2PolicyStatic) {\r
-    return EFI_WRITE_PROTECTED;\r
-  }\r
-\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-\r
-  DataItem        = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
-  OldGateway      = DataItem->Data.Gateway;\r
-  OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
-\r
-  for (Index1 = 0; Index1 < OldGatewayCount; Index1++) {\r
-    //\r
-    // Remove the old route entry.\r
-    //\r
-    CopyMem (&Gateway, OldGateway + Index1, sizeof (IP4_ADDR));\r
-    Ip4DelRoute (\r
-      IpSb->DefaultRouteTable,\r
-      IP4_ALLZERO_ADDRESS,\r
-      IP4_ALLZERO_ADDRESS,\r
-      NTOHL (Gateway)\r
-      );\r
-    OneRemoved = TRUE;\r
-  }\r
-\r
-  if (Data != NULL && DataSize != 0) {\r
-    NewGateway      = (EFI_IPv4_ADDRESS *) Data;\r
-    NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
-    for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
-      CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
-\r
-      if ((IpSb->DefaultInterface->SubnetMask != 0) &&\r
-          !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask)) {\r
-        return EFI_INVALID_PARAMETER;\r
-      }\r
-\r
-      for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {\r
-        if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) {\r
-          return EFI_INVALID_PARAMETER;\r
-        }\r
-      }\r
-    }\r
-\r
-    if (NewGatewayCount != OldGatewayCount) {\r
-      Tmp = AllocatePool (DataSize);\r
-      if (Tmp == NULL) {\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-    } else {\r
-      Tmp = NULL;\r
-    }\r
-\r
-    for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
-      //\r
-      // Add the new route entry.\r
-      //\r
-      CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
-      Ip4AddRoute (\r
-        IpSb->DefaultRouteTable,\r
-        IP4_ALLZERO_ADDRESS,\r
-        IP4_ALLZERO_ADDRESS,\r
-        NTOHL (Gateway)\r
-        );\r
-\r
-      OneAdded = TRUE;\r
-    }\r
-\r
-    if (!OneRemoved && !OneAdded) {\r
-      DataItem->Status = EFI_SUCCESS;\r
-      return EFI_ABORTED;\r
-    } else {\r
-      if (Tmp != NULL) {\r
-        if (DataItem->Data.Ptr != NULL) {\r
-          FreePool (DataItem->Data.Ptr);\r
-        }\r
-        DataItem->Data.Ptr = Tmp;\r
-      }\r
-\r
-      CopyMem (DataItem->Data.Ptr, Data, DataSize);\r
-      DataItem->DataSize = DataSize;\r
-      DataItem->Status   = EFI_SUCCESS;\r
-    }\r
-  } else {\r
-    //\r
-    // DataSize is 0 and Data is NULL, clean up the Gateway address.\r
-    //\r
-    if (DataItem->Data.Ptr != NULL) {\r
-      FreePool (DataItem->Data.Ptr);\r
-    }\r
-    DataItem->Data.Ptr = NULL;\r
-    DataItem->DataSize = 0;\r
-    DataItem->Status   = EFI_NOT_FOUND;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  The work function is to set the DNS server list for the EFI IPv4 network\r
-  stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL\r
-  manages. It is not configurable when the policy is Ip4Config2PolicyDhcp.\r
-  The DNS server addresses must be unicast IPv4 addresses.\r
-\r
-  @param[in]     Instance The pointer to the IP4 config2 instance data.\r
-  @param[in]     DataSize The size of the buffer pointed to by Data in bytes.\r
-  @param[in]     Data     The data buffer to set, points to an array of\r
-                          EFI_IPv4_ADDRESS instances.\r
-\r
-  @retval EFI_BAD_BUFFER_SIZE   The DataSize does not match the size of the type.\r
-  @retval EFI_WRITE_PROTECTED   The specified configuration data cannot be set\r
-                                under the current policy.\r
-  @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.\r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resources to complete the operation.\r
-  @retval EFI_ABORTED           The DNS server addresses to be set equal the current\r
-                                configuration.\r
-  @retval EFI_SUCCESS           The specified configuration data for the EFI IPv4\r
-                                network stack was set.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2SetDnsServer (\r
-  IN IP4_CONFIG2_INSTANCE *Instance,\r
-  IN UINTN                DataSize,\r
-  IN VOID                 *Data\r
-  )\r
-{\r
-  EFI_STATUS                     Status;\r
-  IP4_CONFIG2_DATA_ITEM          *Item;\r
-\r
-  Status = EFI_SUCCESS;\r
-  Item   = NULL;\r
-\r
-  if (Instance->Policy != Ip4Config2PolicyStatic) {\r
-    return EFI_WRITE_PROTECTED;\r
-  }\r
-\r
-  Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
-\r
-  if (DATA_ATTRIB_SET (Item->Attribute, DATA_ATTRIB_VOLATILE)) {\r
-    REMOVE_DATA_ATTRIB (Item->Attribute, DATA_ATTRIB_VOLATILE);\r
-  }\r
-\r
-  if (Data != NULL && DataSize != 0) {\r
-    Status = Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);\r
-  } else {\r
-    //\r
-    // DataSize is 0 and Data is NULL, clean up the DnsServer address.\r
-    //\r
-    if (Item->Data.Ptr != NULL) {\r
-      FreePool (Item->Data.Ptr);\r
-    }\r
-    Item->Data.Ptr = NULL;\r
-    Item->DataSize = 0;\r
-    Item->Status   = EFI_NOT_FOUND;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Generate the operational state of the interface this IP4 config2 instance manages\r
-  and output in EFI_IP4_CONFIG2_INTERFACE_INFO.\r
-\r
-  @param[in]      IpSb     The pointer to the IP4 service binding instance.\r
-  @param[out]     IfInfo   The pointer to the IP4 config2 interface information structure.\r
-\r
-**/\r
-VOID\r
-Ip4Config2InitIfInfo (\r
-  IN  IP4_SERVICE                    *IpSb,\r
-  OUT EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo\r
-  )\r
-{\r
-  UnicodeSPrint (\r
-    IfInfo->Name,\r
-    EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE,\r
-    L"eth%d",\r
-    IpSb->Ip4Config2Instance.IfIndex\r
-  );\r
-\r
-  IfInfo->IfType        = IpSb->SnpMode.IfType;\r
-  IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;\r
-  CopyMem (&IfInfo->HwAddress, &IpSb->SnpMode.CurrentAddress, IfInfo->HwAddressSize);\r
-}\r
-\r
-\r
-\r
-/**\r
-  Set the configuration for the EFI IPv4 network stack running on the communication\r
-  device this EFI_IP4_CONFIG2_PROTOCOL instance manages.\r
-\r
-  This function is used to set the configuration data of type DataType for the EFI\r
-  IPv4 network stack that is running on the communication device that this EFI IPv4\r
-  Configuration Protocol instance manages.\r
-\r
-  DataSize is used to calculate the count of structure instances in the Data for\r
-  a DataType in which multiple structure instances are allowed.\r
-\r
-  This function is always non-blocking. When setting some type of configuration data,\r
-  an asynchronous process is invoked to check the correctness of the data, such as\r
-  performing Duplicate Address Detection on the manually set local IPv4 addresses.\r
-  EFI_NOT_READY is returned immediately to indicate that such an asynchronous process\r
-  is invoked, and the process is not finished yet. The caller wanting to get the result\r
-  of the asynchronous process is required to call RegisterDataNotify() to register an\r
-  event on the specified configuration data. Once the event is signaled, the caller\r
-  can call GetData() to obtain the configuration data and know the result.\r
-  For other types of configuration data that do not require an asynchronous configuration\r
-  process, the result of the operation is immediately returned.\r
-\r
-  @param[in]     This           The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.\r
-  @param[in]     DataType       The type of data to set.\r
-  @param[in]     DataSize       Size of the buffer pointed to by Data in bytes.\r
-  @param[in]     Data           The data buffer to set. The type of the data buffer is\r
-                                associated with the DataType.\r
-\r
-  @retval EFI_SUCCESS           The specified configuration data for the EFI IPv6\r
-                                network stack was set successfully.\r
-  @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
-                                - This is NULL.\r
-                                - One or more fields in Data and DataSize do not match the\r
-                                  requirement of the data type indicated by DataType.\r
-  @retval EFI_WRITE_PROTECTED   The specified configuration data is read-only or the specified\r
-                                configuration data cannot be set under the current policy.\r
-  @retval EFI_ACCESS_DENIED     Another set operation on the specified configuration\r
-                                data is already in process.\r
-  @retval EFI_NOT_READY         An asynchronous process was invoked to set the specified\r
-                                configuration data, and the process is not finished yet.\r
-  @retval EFI_BAD_BUFFER_SIZE   The DataSize does not match the size of the type\r
-                                indicated by DataType.\r
-  @retval EFI_UNSUPPORTED       This DataType is not supported.\r
-  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
-  @retval EFI_DEVICE_ERROR      An unexpected system error or network error occurred.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EfiIp4Config2SetData (\r
-  IN EFI_IP4_CONFIG2_PROTOCOL   *This,\r
-  IN EFI_IP4_CONFIG2_DATA_TYPE  DataType,\r
-  IN UINTN                      DataSize,\r
-  IN VOID                       *Data\r
-  )\r
-{\r
-  EFI_TPL              OldTpl;\r
-  EFI_STATUS           Status;\r
-  IP4_CONFIG2_INSTANCE *Instance;\r
-  IP4_SERVICE          *IpSb;\r
-\r
-  if ((This == NULL) || (Data == NULL && DataSize != 0) || (Data != NULL && DataSize == 0)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (DataType >= Ip4Config2DataTypeMaximum) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);\r
-  IpSb     = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-  NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
-\r
-\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  Status = Instance->DataItem[DataType].Status;\r
-  if (Status != EFI_NOT_READY) {\r
-\r
-    if (Instance->DataItem[DataType].SetData == NULL) {\r
-      //\r
-      // This type of data is readonly.\r
-      //\r
-      Status = EFI_WRITE_PROTECTED;\r
-    } else {\r
-\r
-      Status = Instance->DataItem[DataType].SetData (Instance, DataSize, Data);\r
-      if (!EFI_ERROR (Status)) {\r
-        //\r
-        // Fire up the events registered with this type of data.\r
-        //\r
-        NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL);\r
-        Ip4Config2WriteConfigData (IpSb->MacString, Instance);\r
-      } else if (Status == EFI_ABORTED) {\r
-        //\r
-        // The SetData is aborted because the data to set is the same with\r
-        // the one maintained.\r
-        //\r
-        Status = EFI_SUCCESS;\r
-        NetMapIterate (&Instance->DataItem[DataType].EventMap, Ip4Config2SignalEvent, NULL);\r
-      }\r
-    }\r
-  } else {\r
-    //\r
-    // Another asynchornous process is on the way.\r
-    //\r
-    Status = EFI_ACCESS_DENIED;\r
-  }\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Get the configuration data for the EFI IPv4 network stack running on the communication\r
-  device that this EFI_IP4_CONFIG2_PROTOCOL instance manages.\r
-\r
-  This function returns the configuration data of type DataType for the EFI IPv4 network\r
-  stack running on the communication device that this EFI IPv4 Configuration Protocol instance\r
-  manages.\r
-\r
-  The caller is responsible for allocating the buffer used to return the specified\r
-  configuration data. The required size will be returned to the caller if the size of\r
-  the buffer is too small.\r
-\r
-  EFI_NOT_READY is returned if the specified configuration data is not ready due to an\r
-  asynchronous configuration process already in progress. The caller can call RegisterDataNotify()\r
-  to register an event on the specified configuration data. Once the asynchronous configuration\r
-  process is finished, the event will be signaled, and a subsequent GetData() call will return\r
-  the specified configuration data.\r
-\r
-  @param[in]      This           Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.\r
-  @param[in]      DataType       The type of data to get.\r
-  @param[in, out] DataSize       On input, in bytes, the size of Data. On output, in bytes, the\r
-                                 size of buffer required to store the specified configuration data.\r
-  @param[in]     Data            The data buffer in which the configuration data is returned. The\r
-                                 type of the data buffer is associated with the DataType.\r
-                                 This is an optional parameter that may be NULL.\r
-\r
-  @retval EFI_SUCCESS           The specified configuration data was obtained successfully.\r
-  @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:\r
-                                - This is NULL.\r
-                                - DataSize is NULL.\r
-                                - Data is NULL if *DataSize is not zero.\r
-  @retval EFI_BUFFER_TOO_SMALL  The size of Data is too small for the specified configuration data,\r
-                                and the required size is returned in DataSize.\r
-  @retval EFI_NOT_READY         The specified configuration data is not ready due to an\r
-                                asynchronous configuration process already in progress.\r
-  @retval EFI_NOT_FOUND         The specified configuration data is not found.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EfiIp4Config2GetData (\r
-  IN EFI_IP4_CONFIG2_PROTOCOL   *This,\r
-  IN EFI_IP4_CONFIG2_DATA_TYPE  DataType,\r
-  IN OUT UINTN                  *DataSize,\r
-  IN VOID                       *Data   OPTIONAL\r
-  )\r
-{\r
-  EFI_TPL               OldTpl;\r
-  EFI_STATUS            Status;\r
-  IP4_CONFIG2_INSTANCE  *Instance;\r
-  IP4_CONFIG2_DATA_ITEM *DataItem;\r
-\r
-  if ((This == NULL) || (DataSize == NULL) || ((*DataSize != 0) && (Data == NULL))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (DataType >= Ip4Config2DataTypeMaximum) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);\r
-  DataItem = &Instance->DataItem[DataType];\r
-\r
-  Status   = Instance->DataItem[DataType].Status;\r
-  if (!EFI_ERROR (Status)) {\r
-\r
-    if (DataItem->GetData != NULL) {\r
-\r
-      Status = DataItem->GetData (Instance, DataSize, Data);\r
-    } else if (*DataSize < Instance->DataItem[DataType].DataSize) {\r
-      //\r
-      // Update the buffer length.\r
-      //\r
-      *DataSize = Instance->DataItem[DataType].DataSize;\r
-      Status    = EFI_BUFFER_TOO_SMALL;\r
-    } else {\r
-\r
-      *DataSize = Instance->DataItem[DataType].DataSize;\r
-      CopyMem (Data, Instance->DataItem[DataType].Data.Ptr, *DataSize);\r
-    }\r
-  }\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Register an event that is signaled whenever a configuration process on the specified\r
-  configuration data is done.\r
-\r
-  This function registers an event that is to be signaled whenever a configuration\r
-  process on the specified configuration data is performed. An event can be registered\r
-  for a different DataType simultaneously. The caller is responsible for determining\r
-  which type of configuration data causes the signaling of the event in such an event.\r
-\r
-  @param[in]     This           Pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.\r
-  @param[in]     DataType       The type of data to unregister the event for.\r
-  @param[in]     Event          The event to register.\r
-\r
-  @retval EFI_SUCCESS           The notification event for the specified configuration data is\r
-                                registered.\r
-  @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.\r
-  @retval EFI_UNSUPPORTED       The configuration data type specified by DataType is not\r
-                                supported.\r
-  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
-  @retval EFI_ACCESS_DENIED     The Event is already registered for the DataType.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EfiIp4Config2RegisterDataNotify (\r
-  IN EFI_IP4_CONFIG2_PROTOCOL   *This,\r
-  IN EFI_IP4_CONFIG2_DATA_TYPE  DataType,\r
-  IN EFI_EVENT                  Event\r
-  )\r
-{\r
-  EFI_TPL              OldTpl;\r
-  EFI_STATUS           Status;\r
-  IP4_CONFIG2_INSTANCE *Instance;\r
-  NET_MAP              *EventMap;\r
-  NET_MAP_ITEM         *Item;\r
-\r
-  if ((This == NULL) || (Event == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (DataType >= Ip4Config2DataTypeMaximum) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
-\r
-  OldTpl    = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  Instance  = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);\r
-  EventMap  = &Instance->DataItem[DataType].EventMap;\r
-\r
-  //\r
-  // Check whether this event is already registered for this DataType.\r
-  //\r
-  Item = NetMapFindKey (EventMap, Event);\r
-  if (Item == NULL) {\r
-\r
-    Status = NetMapInsertTail (EventMap, Event, NULL);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-\r
-      Status = EFI_OUT_OF_RESOURCES;\r
-    }\r
-\r
-  } else {\r
-\r
-    Status = EFI_ACCESS_DENIED;\r
-  }\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Remove a previously registered event for the specified configuration data.\r
-\r
-  @param  This                   The pointer to the EFI_IP4_CONFIG2_PROTOCOL instance.\r
-  @param  DataType               The type of data to remove from the previously\r
-                                 registered event.\r
-  @param  Event                  The event to be unregistered.\r
-\r
-  @retval EFI_SUCCESS            The event registered for the specified\r
-                                 configuration data was removed.\r
-  @retval EFI_INVALID_PARAMETER  This is NULL or Event is NULL.\r
-  @retval EFI_NOT_FOUND          The Event has not been registered for the\r
-                                 specified DataType.\r
-\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-EfiIp4Config2UnregisterDataNotify (\r
-  IN EFI_IP4_CONFIG2_PROTOCOL   *This,\r
-  IN EFI_IP4_CONFIG2_DATA_TYPE  DataType,\r
-  IN EFI_EVENT                  Event\r
-  )\r
-{\r
-  EFI_TPL              OldTpl;\r
-  EFI_STATUS           Status;\r
-  IP4_CONFIG2_INSTANCE *Instance;\r
-  NET_MAP_ITEM         *Item;\r
-\r
-  if ((This == NULL) || (Event == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (DataType >= Ip4Config2DataTypeMaximum) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  Instance = IP4_CONFIG2_INSTANCE_FROM_PROTOCOL (This);\r
-\r
-  Item = NetMapFindKey (&Instance->DataItem[DataType].EventMap, Event);\r
-  if (Item != NULL) {\r
-\r
-    NetMapRemoveItem (&Instance->DataItem[DataType].EventMap, Item, NULL);\r
-    Status = EFI_SUCCESS;\r
-  } else {\r
-\r
-    Status = EFI_NOT_FOUND;\r
-  }\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Initialize an IP4_CONFIG2_INSTANCE.\r
-\r
-  @param[out]    Instance       The buffer of IP4_CONFIG2_INSTANCE to be initialized.\r
-\r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resources to complete the operation.\r
-  @retval EFI_SUCCESS           The IP4_CONFIG2_INSTANCE initialized successfully.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4Config2InitInstance (\r
-  OUT IP4_CONFIG2_INSTANCE  *Instance\r
-  )\r
-{\r
-  IP4_SERVICE           *IpSb;\r
-  IP4_CONFIG2_INSTANCE  *TmpInstance;\r
-  LIST_ENTRY            *Entry;\r
-  EFI_STATUS            Status;\r
-  UINTN                 Index;\r
-  UINT16                IfIndex;\r
-  IP4_CONFIG2_DATA_ITEM *DataItem;\r
-\r
-\r
-  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
-\r
-  Instance->Signature = IP4_CONFIG2_INSTANCE_SIGNATURE;\r
-\r
-\r
-  //\r
-  // Determine the index of this interface.\r
-  //\r
-  IfIndex = 0;\r
-  NET_LIST_FOR_EACH (Entry, &mIp4Config2InstanceList) {\r
-    TmpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_CONFIG2_INSTANCE, Link, IP4_CONFIG2_INSTANCE_SIGNATURE);\r
-\r
-    if (TmpInstance->IfIndex > IfIndex) {\r
-      //\r
-      // There is a sequence hole because some interface is down.\r
-      //\r
-      break;\r
-    }\r
-\r
-    IfIndex++;\r
-  }\r
-\r
-  Instance->IfIndex = IfIndex;\r
-  NetListInsertBefore (Entry, &Instance->Link);\r
-\r
-  for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {\r
-    //\r
-    // Initialize the event map for each data item.\r
-    //\r
-    NetMapInit (&Instance->DataItem[Index].EventMap);\r
-  }\r
-\r
-\r
-  //\r
-  // Initialize each data type: associate storage and set data size for the\r
-  // fixed size data types, hook the SetData function, set the data attribute.\r
-  //\r
-  DataItem           = &Instance->DataItem[Ip4Config2DataTypeInterfaceInfo];\r
-  DataItem->GetData  = Ip4Config2GetIfInfo;\r
-  DataItem->Data.Ptr = &Instance->InterfaceInfo;\r
-  DataItem->DataSize = sizeof (Instance->InterfaceInfo);\r
-  SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED | DATA_ATTRIB_VOLATILE);\r
-  Ip4Config2InitIfInfo (IpSb, &Instance->InterfaceInfo);\r
-\r
-  DataItem           = &Instance->DataItem[Ip4Config2DataTypePolicy];\r
-  DataItem->SetData  = Ip4Config2SetPolicy;\r
-  DataItem->Data.Ptr = &Instance->Policy;\r
-  DataItem->DataSize = sizeof (Instance->Policy);\r
-  Instance->Policy   = Ip4Config2PolicyStatic;\r
-  SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);\r
-\r
-  DataItem           = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
-  DataItem->SetData  = Ip4Config2SetManualAddress;\r
-  DataItem->Status   = EFI_NOT_FOUND;\r
-\r
-  DataItem           = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
-  DataItem->SetData  = Ip4Config2SetGateway;\r
-  DataItem->Status   = EFI_NOT_FOUND;\r
-\r
-  DataItem           = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
-  DataItem->SetData  = Ip4Config2SetDnsServer;\r
-  DataItem->Status   = EFI_NOT_FOUND;\r
-\r
-  Instance->Configured  = TRUE;\r
-\r
-  //\r
-  // Try to read the config data from NV variable.\r
-  // If not found, write initialized config data into NV variable\r
-  // as a default config data.\r
-  //\r
-  Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance);\r
-  if (Status == EFI_NOT_FOUND) {\r
-    Status = Ip4Config2WriteConfigData (IpSb->MacString, Instance);\r
-  }\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Instance->Ip4Config2.SetData              = EfiIp4Config2SetData;\r
-  Instance->Ip4Config2.GetData              = EfiIp4Config2GetData;\r
-  Instance->Ip4Config2.RegisterDataNotify   = EfiIp4Config2RegisterDataNotify;\r
-  Instance->Ip4Config2.UnregisterDataNotify = EfiIp4Config2UnregisterDataNotify;\r
-\r
-  //\r
-  // Publish the IP4 configuration form\r
-  //\r
-  return Ip4Config2FormInit (Instance);\r
-}\r
-\r
-\r
-/**\r
-  Release an IP4_CONFIG2_INSTANCE.\r
-\r
-  @param[in, out] Instance    The buffer of IP4_CONFIG2_INSTANCE to be freed.\r
-\r
-**/\r
-VOID\r
-Ip4Config2CleanInstance (\r
-  IN OUT IP4_CONFIG2_INSTANCE  *Instance\r
-  )\r
-{\r
-  UINTN                 Index;\r
-  IP4_CONFIG2_DATA_ITEM *DataItem;\r
-\r
-  if (Instance->DeclineAddress != NULL) {\r
-    FreePool (Instance->DeclineAddress);\r
-  }\r
-\r
-  if (!Instance->Configured) {\r
-    return ;\r
-  }\r
-\r
-  if (Instance->Dhcp4Handle != NULL) {\r
-\r
-    Ip4Config2DestroyDhcp4 (Instance);\r
-  }\r
-\r
-  //\r
-  // Close the event.\r
-  //\r
-  if (Instance->Dhcp4Event != NULL) {\r
-    gBS->CloseEvent (Instance->Dhcp4Event);\r
-    Instance->Dhcp4Event = NULL;\r
-  }\r
-\r
-  for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {\r
-\r
-    DataItem = &Instance->DataItem[Index];\r
-\r
-    if (!DATA_ATTRIB_SET (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED)) {\r
-      if (DataItem->Data.Ptr != NULL) {\r
-        FreePool (DataItem->Data.Ptr);\r
-      }\r
-      DataItem->Data.Ptr = NULL;\r
-      DataItem->DataSize = 0;\r
-    }\r
-\r
-    NetMapClean (&Instance->DataItem[Index].EventMap);\r
-  }\r
-\r
-  Ip4Config2FormUnload (Instance);\r
-\r
-  RemoveEntryList (&Instance->Link);\r
-}\r
-\r
-/**\r
-  The event handle for IP4 auto reconfiguration. The original default\r
-  interface and route table will be removed as the default.\r
-\r
-  @param[in]  Context                The IP4 service binding instance.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4AutoReconfigCallBackDpc (\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  IP4_SERVICE               *IpSb;\r
-\r
-  IpSb      = (IP4_SERVICE *) Context;\r
-  NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
-\r
-  if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
-    IpSb->State = IP4_SERVICE_UNSTARTED;\r
-  }\r
-\r
-  IpSb->Reconfig = TRUE;\r
-\r
-  Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
-\r
-  return ;\r
-}\r
-\r
-\r
-/**\r
-  Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.\r
-\r
-  @param Event     The event that is signalled.\r
-  @param Context   The IP4 service binding instance.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4AutoReconfigCallBack (\r
-  IN EFI_EVENT              Event,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  //\r
-  // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK\r
-  //\r
-  QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context);\r
-}\r
-\r