MdeModulePkg: Update Ip4Dxe driver to support Ip4Config2 protocol,
authorjiaxinwu <jiaxin.wu@intel.com>
Tue, 7 Jul 2015 08:19:55 +0000 (08:19 +0000)
committerjiaxinwu <jiaxinwu@Edk2>
Tue, 7 Jul 2015 08:19:55 +0000 (08:19 +0000)
and also add new UI configuration support in Ip4Dxe driver.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: jiaxinwu <jiaxin.wu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17853 6f19259b-4bc3-4df7-8a09-765794883524

20 files changed:
MdeModulePkg/Include/Guid/Ip4Config2Hii.h [new file with mode: 0644]
MdeModulePkg/MdeModulePkg.dec
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2.vfr [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Nv.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Nv.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4DxeStrings.uni [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.c
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Icmp.h
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.h
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.c
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Igmp.h
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.h
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4NvData.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Output.c

diff --git a/MdeModulePkg/Include/Guid/Ip4Config2Hii.h b/MdeModulePkg/Include/Guid/Ip4Config2Hii.h
new file mode 100644 (file)
index 0000000..b1b41b9
--- /dev/null
@@ -0,0 +1,25 @@
+/** @file\r
+  GUIDs used as HII FormSet and HII Package list GUID in Ip4Dxe driver. \r
+  \r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available under \r
+the terms and conditions of the BSD License that accompanies this distribution.  \r
+The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php.                                            \r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __IP4_CONFIG2_HII_GUID_H__\r
+#define __IP4_CONFIG2_HII_GUID_H__\r
+\r
+#define IP4_CONFIG2_NVDATA_GUID \\r
+  { \\r
+    0x9b942747, 0x154e, 0x4d29, { 0xa4, 0x36, 0xbf, 0x71, 0x0, 0xc8, 0xb5, 0x3b } \\r
+  }\r
+\r
+extern EFI_GUID gIp4Config2NvDataGuid;\r
+\r
+#endif\r
index 414b13e..c48669d 100644 (file)
   ## Include/Guid/Ip4ConfigHii.h\r
   gNicIp4ConfigNvDataGuid            = { 0x9d5b53f, 0xf4b0, 0x4f59, { 0xa0, 0xb1, 0x7b, 0x57, 0xd3, 0x5c, 0xe, 0x5 }}\r
 \r
+  ## Include/Guid/Ip4Config2Hii.h\r
+  gIp4Config2NvDataGuid              = { 0x9b942747, 0x154e, 0x4d29, { 0xa4, 0x36, 0xbf, 0x71, 0x0, 0xc8, 0xb5, 0x3b }}\r
+\r
   ## Include/Guid/VlanConfigHii.h\r
   gVlanConfigFormSetGuid             = { 0xd79df6b0, 0xef44, 0x43bd, { 0x97, 0x97, 0x43, 0xe9, 0x3b, 0xcf, 0x5f, 0xa8 }}\r
 \r
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2.vfr b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2.vfr
new file mode 100644 (file)
index 0000000..a18db22
--- /dev/null
@@ -0,0 +1,100 @@
+/** @file\r
+  Vfr file for IP4Dxe.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "Ip4NvData.h"\r
+\r
+#define EFI_NETWORK_DEVICE_CLASS  0x04\r
+\r
+formset\r
+  guid     = IP4_CONFIG2_NVDATA_GUID,\r
+  title    = STRING_TOKEN(STR_IP4_CONFIG2_FORM_TITLE),\r
+  help     = STRING_TOKEN(STR_IP4_CONFIG2_FORM_HELP),\r
+  class    = EFI_NETWORK_DEVICE_CLASS,\r
+  subclass = 0x03,\r
+\r
+  varstore IP4_CONFIG2_IFR_NVDATA,\r
+    name = IP4_CONFIG2_IFR_NVDATA,\r
+    guid = IP4_CONFIG2_NVDATA_GUID;\r
+\r
+  form formid = FORMID_MAIN_FORM,\r
+    title  = STRING_TOKEN(STR_IP4_DEVICE_FORM_TITLE);\r
+\r
+    checkbox varid = IP4_CONFIG2_IFR_NVDATA.Configure,\r
+            prompt = STRING_TOKEN(STR_IP4_CONFIGURE),\r
+            help   = STRING_TOKEN(STR_IP4_CONFIGURE),\r
+            flags  = INTERACTIVE,\r
+            key    = KEY_ENABLE,\r
+    endcheckbox;\r
+\r
+    suppressif ideqval IP4_CONFIG2_IFR_NVDATA.Configure == 0x00;\r
+\r
+      checkbox varid = IP4_CONFIG2_IFR_NVDATA.DhcpEnable,\r
+              prompt = STRING_TOKEN(STR_IP4_ENABLE_DHCP),\r
+              help   = STRING_TOKEN(STR_IP4_ENABLE_DHCP),\r
+              flags  = INTERACTIVE,\r
+              key    = KEY_DHCP_ENABLE,\r
+      endcheckbox;\r
+    endif;\r
+\r
+    suppressif ideqval IP4_CONFIG2_IFR_NVDATA.DhcpEnable == 0x01 OR ideqval IP4_CONFIG2_IFR_NVDATA.Configure == 0x00;\r
+\r
+      string  varid   = IP4_CONFIG2_IFR_NVDATA.StationAddress,\r
+              prompt  = STRING_TOKEN(STR_IP4_LOCAL_IP_ADDRESS),\r
+              help    = STRING_TOKEN(STR_IP4_IP_ADDRESS_HELP),\r
+              flags   = INTERACTIVE,\r
+              key     = KEY_LOCAL_IP,\r
+              minsize = IP_MIN_SIZE,\r
+              maxsize = IP_MAX_SIZE,\r
+      endstring;\r
+\r
+      string  varid   = IP4_CONFIG2_IFR_NVDATA.SubnetMask,\r
+              prompt  = STRING_TOKEN(STR_IP4_LOCAL_MASK),\r
+              help    = STRING_TOKEN(STR_IP4_MASK_HELP),\r
+              flags   = INTERACTIVE,\r
+              key     = KEY_SUBNET_MASK,\r
+              minsize = IP_MIN_SIZE,\r
+             maxsize = IP_MAX_SIZE,\r
+      endstring;\r
+\r
+      string  varid   = IP4_CONFIG2_IFR_NVDATA.GatewayAddress,\r
+              prompt  = STRING_TOKEN(STR_IP4_LOCAL_GATEWAY),\r
+              help    = STRING_TOKEN(STR_IP4_GATEWAY_HELP),\r
+              flags   = INTERACTIVE,\r
+              key     = KEY_GATE_WAY,\r
+              minsize = IP_MIN_SIZE,\r
+              maxsize = IP_MAX_SIZE,\r
+      endstring;\r
+\r
+      string  varid   = IP4_CONFIG2_IFR_NVDATA.DnsAddress,\r
+              prompt  = STRING_TOKEN(STR_IP4_LOCAL_DNS),\r
+              help    = STRING_TOKEN(STR_IP4_DNS_HELP),\r
+              flags   = INTERACTIVE,\r
+              key     = KEY_DNS,\r
+              minsize = IP_MIN_SIZE,\r
+              maxsize = ADDRESS_STR_MAX_SIZE,\r
+      endstring;\r
+\r
+    endif;\r
+\r
+    subtitle text = STRING_TOKEN(STR_NULL);\r
+    \r
+    text\r
+      help   = STRING_TOKEN(STR_SAVE_CHANGES),\r
+      text   = STRING_TOKEN(STR_SAVE_CHANGES),\r
+      flags  = INTERACTIVE,\r
+      key    = KEY_SAVE_CHANGES;\r
+      \r
+  endform;\r
+\r
+endformset;\r
+\r
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
new file mode 100644 (file)
index 0000000..2da4a51
--- /dev/null
@@ -0,0 +1,1969 @@
+/** @file\r
+  The implementation of EFI IPv4 Configuration II Protocol.\r
+\r
+  Copyright (c) 2015, Intel Corporation. All rights reserved.<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
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\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
+  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 successfull 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
+/**\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) {\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_NUM - 1; 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]  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
+\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_CONFIG2_INSTANCE   *Instance,\r
+  IN IP4_ADDR               StationAddress,\r
+  IN IP4_ADDR               SubnetMask\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  IP4_SERVICE               *IpSb;\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
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
+  IpIf = IpSb->DefaultInterface;\r
+  ASSERT (IpIf != NULL);\r
+\r
+  if ((IpIf->Ip == StationAddress) && (IpIf->SubnetMask == SubnetMask)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\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
+  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
+  Ip4AddRoute (\r
+    IpSb->DefaultRouteTable,\r
+    StationAddress,\r
+    SubnetMask,\r
+    IP4_ALLZERO_ADDRESS\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
+  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
+  Status = Ip4Config2SetDefaultAddr (Instance, 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
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\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
+/**\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
+\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
+    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 successfull 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
+\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
+  ASSERT_EFI_ERROR (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
+\r
+  if (Dhcp4Mode.State == Dhcp4Bound) {\r
+    Ip4Config2OnDhcp4Complete (NULL, Instance);\r
+    return EFI_SUCCESS;\r
+\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             = DHCP_TAG_PARA_LIST;\r
+  ParaList.Head.Length             = 2;\r
+  ParaList.Head.Data[0]            = DHCP_TAG_NETMASK;\r
+  ParaList.Route                   = DHCP_TAG_ROUTER;\r
+  OptionList[0]                    = &ParaList.Head;\r
+  Dhcp4Mode.ConfigData.OptionCount = 1;\r
+  Dhcp4Mode.ConfigData.OptionList  = OptionList;\r
+\r
+  Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);\r
+\r
+  if (EFI_ERROR (Status)) {\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
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
\r
+  IpSb->State     = IP4_SERVICE_STARTED;\r
+  DispatchDpc ();\r
+  return EFI_SUCCESS;\r
+\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
+\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
+    \r
+  } else {\r
+    if (NewPolicy == Ip4Config2PolicyDhcp) {\r
+      //\r
+      // The policy is changed from static to dhcp:\r
+      // Clean the ManualAddress, Gateway and DnsServers, shrink the variable\r
+      // 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
+    } 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
+      }\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
+Ip4Config2SetMaunualAddress (\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
+\r
+  ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY);\r
+\r
+  if (((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0) || (DataSize == 0)) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  if (Instance->Policy != Ip4Config2PolicyStatic) {\r
+    return EFI_WRITE_PROTECTED;\r
+  }\r
+\r
+  NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);\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
+  DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\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
+  StationAddress = EFI_NTOHL (NewAddress.Address);\r
+  SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
+\r
+  Status = Ip4Config2SetDefaultAddr (Instance, StationAddress, SubnetMask);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }  \r
+\r
+  DataItem->Status = EFI_SUCCESS;   \r
+\r
+ON_EXIT:\r
+  if (EFI_ERROR (DataItem->Status)) {\r
+    if (Ptr != NULL) {\r
+      FreePool (Ptr);\r
+    }\r
+    DataItem->Data.Ptr = NULL; \r
+  }\r
+\r
+  return EFI_SUCCESS;\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
+  if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {\r
+    return EFI_BAD_BUFFER_SIZE;\r
+  }\r
+\r
+  if (Instance->Policy != Ip4Config2PolicyStatic) {\r
+    return EFI_WRITE_PROTECTED;\r
+  }\r
+\r
+\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 (!NetIp4IsUnicast (NTOHL (Gateway), 0)) {\r
+\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
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
+  DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
+  OldGateway      = DataItem->Data.Gateway;\r
+  OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
+  OneRemoved      = FALSE;\r
+  OneAdded        = FALSE;\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 < OldGatewayCount; Index1++) {\r
+    //\r
+    // Remove this 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
+\r
+  for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\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
+\r
+  if (!OneRemoved && !OneAdded) {\r
+    DataItem->Status = EFI_SUCCESS;\r
+    return EFI_ABORTED;\r
+  } else {\r
+\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
+    return EFI_SUCCESS;\r
+  }\r
+\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
+  UINTN                 OldIndex;\r
+  UINTN                 NewIndex;\r
+  UINTN                 Index1;\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
+  if (Instance->Policy != Ip4Config2PolicyStatic) {\r
+    return EFI_WRITE_PROTECTED;\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
+\r
+    if (!NetIp4IsUnicast (NTOHL (DnsAddress), 0)) {\r
+      //\r
+      // The dns server address must be unicast.\r
+      //\r
+      FreePool (Tmp);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) {\r
+      if (EFI_IP4_EQUAL (NewDns + NewIndex, NewDns + Index1)) {\r
+        FreePool (Tmp);\r
+        return EFI_INVALID_PARAMETER;\r
+      }\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
+  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
+  IfInfo->Name[0] = L'e';\r
+  IfInfo->Name[1] = L't';\r
+  IfInfo->Name[2] = L'h';\r
+  IfInfo->Name[3] = (CHAR16) (L'0' + IpSb->Ip4Config2Instance.IfIndex);\r
+  IfInfo->Name[4] = 0;\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
+  The event handle routine when DHCPv4 process is finished or is updated.\r
+\r
+  @param[in]     Event         Not used.\r
+  @param[in]     Context       The pointer to the IP4 configuration instance data.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4Config2OnDhcp4Event (\r
+  IN EFI_EVENT  Event,\r
+  IN VOID       *Context\r
+  )\r
+{\r
+  return ;\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
+                                - Data is NULL.\r
+                                - One or more fields in Data do not match the requirement of the\r
+                                  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)) {\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   = Ip4Config2PolicyDhcp;\r
+  SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);\r
+\r
+  DataItem           = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
+  DataItem->SetData  = Ip4Config2SetMaunualAddress;\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
+  //\r
+  // Create the event used for DHCP.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  Ip4Config2OnDhcp4Event,\r
+                  Instance,\r
+                  &Instance->Dhcp4Event\r
+                  );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Instance->Configured  = TRUE;\r
+\r
+  //\r
+  // Try to read the config data from NV variable.\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
+  //\r
+  // Try to set the configured parameter.\r
+  //\r
+  for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {\r
+    DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];\r
+    if (DataItem->Data.Ptr != NULL) {\r
+      DataItem->SetData (\r
+                  &IpSb->Ip4Config2Instance,\r
+                  DataItem->DataSize,\r
+                  DataItem->Data.Ptr\r
+                  );\r
+    }\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
+  }\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
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.h
new file mode 100644 (file)
index 0000000..26e16a2
--- /dev/null
@@ -0,0 +1,252 @@
+/** @file\r
+  Definitions for EFI IPv4 Configuration II Protocol implementation.\r
+\r
+  Copyright (c) 2015, Intel Corporation. All rights reserved.<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
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef __IP4_CONFIG2_IMPL_H__\r
+#define __IP4_CONFIG2_IMPL_H__\r
+\r
+#define IP4_CONFIG2_INSTANCE_SIGNATURE    SIGNATURE_32 ('I', 'P', 'C', '2')\r
+#define IP4_FORM_CALLBACK_INFO_SIGNATURE  SIGNATURE_32 ('I', 'F', 'C', 'I')\r
+\r
+#define IP4_CONFIG2_VARIABLE_ATTRIBUTE    (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)\r
+\r
+#define DATA_ATTRIB_SIZE_FIXED              0x1\r
+#define DATA_ATTRIB_VOLATILE                0x2\r
+\r
+#define DHCP_TAG_PARA_LIST             55\r
+#define DHCP_TAG_NETMASK               1\r
+#define DHCP_TAG_ROUTER                3\r
+\r
+\r
+#define DATA_ATTRIB_SET(Attrib, Bits)       (BOOLEAN)((Attrib) & (Bits))\r
+#define SET_DATA_ATTRIB(Attrib, Bits)       ((Attrib) |= (Bits))\r
+\r
+typedef struct _IP4_CONFIG2_INSTANCE IP4_CONFIG2_INSTANCE;\r
+\r
+#define IP4_CONFIG2_INSTANCE_FROM_PROTOCOL(Proto) \\r
+  CR ((Proto), \\r
+      IP4_CONFIG2_INSTANCE, \\r
+      Ip4Config2, \\r
+      IP4_CONFIG2_INSTANCE_SIGNATURE \\r
+      )\r
+\r
+#define IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE(Instance) \\r
+  CR ((Instance), \\r
+      IP4_SERVICE, \\r
+      Ip4Config2Instance, \\r
+      IP4_SERVICE_SIGNATURE \\r
+      )\r
+\r
+#define IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Callback) \\r
+  CR ((Callback), \\r
+      IP4_CONFIG2_INSTANCE, \\r
+      CallbackInfo, \\r
+      IP4_CONFIG2_INSTANCE_SIGNATURE \\r
+      )\r
+\r
+#define IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(ConfigAccess) \\r
+  CR ((ConfigAccess), \\r
+      IP4_FORM_CALLBACK_INFO, \\r
+      HiiConfigAccessProtocol, \\r
+      IP4_FORM_CALLBACK_INFO_SIGNATURE \\r
+      )\r
+\r
+/**\r
+  The prototype of work function for EfiIp4Config2SetData().\r
+\r
+  @param[in]     Instance The pointer to the IP4 config2 instance data.\r
+  @param[in]     DataSize In bytes, the size of the buffer pointed to by Data.\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
+                               8 bytes.\r
+  @retval EFI_SUCCESS          The specified configuration data for the EFI IPv4\r
+                               network stack was set successfully.\r
+  \r
+**/\r
+typedef\r
+EFI_STATUS\r
+(*IP4_CONFIG2_SET_DATA) (\r
+  IN IP4_CONFIG2_INSTANCE *Instance,\r
+  IN UINTN                DataSize,\r
+  IN VOID                 *Data\r
+  );\r
+\r
+/**\r
+  The prototype of work function for EfiIp4Config2GetData().\r
+\r
+  @param[in]      Instance The 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 successfully.                               \r
+  \r
+**/\r
+typedef\r
+EFI_STATUS\r
+(*IP4_CONFIG2_GET_DATA) (\r
+  IN IP4_CONFIG2_INSTANCE *Instance,\r
+  IN OUT UINTN            *DataSize,\r
+  IN VOID                 *Data      OPTIONAL\r
+  );\r
+\r
+typedef union {\r
+  VOID                                      *Ptr;\r
+  EFI_IP4_CONFIG2_INTERFACE_INFO            *IfInfo;\r
+  EFI_IP4_CONFIG2_POLICY                    *Policy;\r
+  EFI_IP4_CONFIG2_MANUAL_ADDRESS            *ManualAddress;\r
+  EFI_IPv4_ADDRESS                          *Gateway;\r
+  EFI_IPv4_ADDRESS                          *DnsServers;\r
+} IP4_CONFIG2_DATA;\r
+\r
+typedef struct {\r
+  IP4_CONFIG2_SET_DATA SetData;\r
+  IP4_CONFIG2_GET_DATA GetData;\r
+  EFI_STATUS           Status;\r
+  UINT8                Attribute;\r
+  NET_MAP              EventMap;\r
+  IP4_CONFIG2_DATA     Data;\r
+  UINTN                DataSize;\r
+} IP4_CONFIG2_DATA_ITEM;\r
+\r
+typedef struct {\r
+  UINT16                    Offset;\r
+  UINT32                    DataSize;\r
+  EFI_IP4_CONFIG2_DATA_TYPE DataType;\r
+} IP4_CONFIG2_DATA_RECORD;\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// heap data that contains the data for each data record.\r
+//\r
+//  EFI_IP4_CONFIG2_POLICY                    Policy;\r
+//  UINT32                                    ManualaddressCount;\r
+//  UINT32                                    GatewayCount;\r
+//  UINT32                                    DnsServersCount;\r
+//  EFI_IP4_CONFIG2_MANUAL_ADDRESS            ManualAddress[];\r
+//  EFI_IPv4_ADDRESS                          Gateway[];\r
+//  EFI_IPv4_ADDRESS                          DnsServers[];\r
+//\r
+typedef struct {\r
+  UINT16                  Checksum;\r
+  UINT16                  DataRecordCount;\r
+  IP4_CONFIG2_DATA_RECORD DataRecord[1];\r
+} IP4_CONFIG2_VARIABLE;\r
+\r
+#pragma pack()\r
+\r
+typedef struct {\r
+  EFI_IP4_CONFIG2_POLICY                   Policy;               ///< manual or automatic  \r
+  EFI_IP4_CONFIG2_MANUAL_ADDRESS           *ManualAddress;       ///< IP addresses\r
+  UINT32                                   ManualAddressCount;   ///< IP addresses count\r
+  EFI_IPv4_ADDRESS                         *GatewayAddress;      ///< Gateway address\r
+  UINT32                                   GatewayAddressCount;  ///< Gateway address count\r
+  EFI_IPv4_ADDRESS                         *DnsAddress;          ///< DNS server address\r
+  UINT32                                   DnsAddressCount;      ///< DNS server address count\r
+} IP4_CONFIG2_NVDATA;\r
+\r
+typedef struct _IP4_FORM_CALLBACK_INFO {\r
+  UINT32                           Signature;\r
+  EFI_HANDLE                       ChildHandle;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL   HiiConfigAccessProtocol;\r
+  EFI_DEVICE_PATH_PROTOCOL         *HiiVendorDevicePath;\r
+  EFI_HII_HANDLE                   RegisteredHandle;\r
+} IP4_FORM_CALLBACK_INFO;\r
+\r
+struct _IP4_CONFIG2_INSTANCE {\r
+  UINT32                                    Signature;\r
+  BOOLEAN                                   Configured;\r
+  LIST_ENTRY                                Link;\r
+  UINT16                                    IfIndex;\r
+\r
+  EFI_IP4_CONFIG2_PROTOCOL                  Ip4Config2;\r
+\r
+  EFI_IP4_CONFIG2_INTERFACE_INFO            InterfaceInfo;\r
+  EFI_IP4_CONFIG2_POLICY                    Policy;  \r
+  IP4_CONFIG2_DATA_ITEM                     DataItem[Ip4Config2DataTypeMaximum];\r
+\r
+  EFI_EVENT                                 Dhcp4SbNotifyEvent;\r
+  VOID                                      *Registration;\r
+  EFI_HANDLE                                Dhcp4Handle;\r
+  EFI_DHCP4_PROTOCOL                        *Dhcp4;\r
+  BOOLEAN                                   DhcpSuccess;\r
+  BOOLEAN                                   OtherInfoOnly;\r
+  EFI_EVENT                                 Dhcp4Event;\r
+  UINT32                                    FailedIaAddressCount;\r
+  EFI_IPv4_ADDRESS                          *DeclineAddress;\r
+  UINT32                                    DeclineAddressCount;\r
+  \r
+  IP4_FORM_CALLBACK_INFO                    CallbackInfo;\r
+\r
+  IP4_CONFIG2_NVDATA                        Ip4NvData;\r
+};\r
+\r
+//\r
+// Configure the DHCP to request the routers and netmask\r
+// from server. The DHCP_TAG_NETMASK is included in Head.\r
+//\r
+#pragma pack(1)\r
+typedef struct {\r
+  EFI_DHCP4_PACKET_OPTION Head;\r
+  UINT8                   Route;\r
+} IP4_CONFIG2_DHCP4_OPTION;\r
+#pragma pack()\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
+/**\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
+/**\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
+#endif\r
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Nv.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Nv.c
new file mode 100644 (file)
index 0000000..27dae58
--- /dev/null
@@ -0,0 +1,1436 @@
+/** @file\r
+  Helper functions for configuring or getting the parameters relating to Ip4.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "Ip4Impl.h"\r
+\r
+CHAR16    mIp4Config2StorageName[]     = L"IP4_CONFIG2_IFR_NVDATA";\r
+\r
+/**\r
+  Calculate the prefix length of the IPv4 subnet mask.\r
+\r
+  @param[in]  SubnetMask The IPv4 subnet mask.\r
+\r
+  @return The prefix length of the subnet mask.\r
+  @retval 0 Other errors as indicated.\r
+  \r
+**/\r
+UINT8\r
+GetSubnetMaskPrefixLength (\r
+  IN EFI_IPv4_ADDRESS  *SubnetMask\r
+  )\r
+{\r
+  UINT8   Len;\r
+  UINT32  ReverseMask;\r
+\r
+  //\r
+  // The SubnetMask is in network byte order.\r
+  //\r
+  ReverseMask = SwapBytes32 (*(UINT32 *)&SubnetMask[0]);\r
+\r
+  //\r
+  // Reverse it.\r
+  //\r
+  ReverseMask = ~ReverseMask;\r
+\r
+  if ((ReverseMask & (ReverseMask + 1)) != 0) {\r
+    return 0;\r
+  }\r
+\r
+  Len = 0;\r
+\r
+  while (ReverseMask != 0) {\r
+    ReverseMask = ReverseMask >> 1;\r
+    Len++;\r
+  }\r
+\r
+  return (UINT8) (32 - Len);\r
+}\r
+\r
+/**\r
+  Convert the decimal dotted IPv4 address into the binary IPv4 address.\r
+\r
+  @param[in]   Str             The UNICODE string.\r
+  @param[out]  Ip              The storage to return the IPv4 address.\r
+\r
+  @retval EFI_SUCCESS           The binary IP address is returned in Ip.\r
+  @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
+  \r
+**/\r
+EFI_STATUS\r
+Ip4Config2StrToIp (\r
+  IN  CHAR16            *Str,\r
+  OUT EFI_IPv4_ADDRESS  *Ip\r
+  )\r
+{\r
+  UINTN Index;\r
+  UINTN Number;\r
+\r
+  Index = 0;\r
+\r
+  while (*Str != L'\0') {\r
+\r
+    if (Index > 3) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Number = 0;\r
+    while ((*Str >= L'0') && (*Str <= L'9')) {\r
+      Number = Number * 10 + (*Str - L'0');\r
+      Str++;\r
+    }\r
+\r
+    if (Number > 0xFF) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Ip->Addr[Index] = (UINT8) Number;\r
+\r
+    if ((*Str != L'\0') && (*Str != L'.')) {\r
+      //\r
+      // The current character should be either the NULL terminator or\r
+      // the dot delimiter.\r
+      //\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (*Str == L'.') {\r
+      //\r
+      // Skip the delimiter.\r
+      //\r
+      Str++;\r
+    }\r
+\r
+    Index++;\r
+  }\r
+\r
+  if (Index != 4) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert the decimal dotted IPv4 addresses separated by space into the binary IPv4 address list.\r
+\r
+  @param[in]   Str             The UNICODE string contains IPv4 addresses.\r
+  @param[out]  PtrIpList       The storage to return the IPv4 address list.\r
+  @param[out]  IpCount         The size of the IPv4 address list.\r
+\r
+  @retval EFI_SUCCESS           The binary IP address list is returned in PtrIpList.\r
+  @retval EFI_OUT_OF_RESOURCES  Error occurs in allocating memory.\r
+  @retval EFI_INVALID_PARAMETER The IP string is malformatted.\r
+  \r
+**/\r
+EFI_STATUS\r
+Ip4Config2StrToIpList (\r
+  IN  CHAR16            *Str,\r
+  OUT EFI_IPv4_ADDRESS  **PtrIpList,\r
+  OUT UINTN             *IpCount\r
+  )\r
+{\r
+  UINTN              BeginIndex;\r
+  UINTN              EndIndex; \r
+  UINTN              Index;\r
+  UINTN              IpIndex;\r
+  CHAR16             *StrTemp;\r
+  BOOLEAN            SpaceTag;\r
+  \r
+  BeginIndex = 0;\r
+  EndIndex   = BeginIndex;\r
+  Index      = 0;\r
+  IpIndex    = 0;\r
+  StrTemp    = NULL;\r
+  SpaceTag   = TRUE;\r
+  \r
+  *PtrIpList = NULL;\r
+  *IpCount   = 0;\r
+\r
+  if (Str == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get the number of Ip.\r
+  //\r
+  while (*(Str + Index) != L'\0') {\r
+    if (*(Str + Index) == L' ') {\r
+      SpaceTag = TRUE;\r
+    } else {\r
+      if (SpaceTag) {\r
+        (*IpCount)++;\r
+        SpaceTag = FALSE;\r
+      }\r
+    }\r
+     \r
+    Index++;\r
+  }\r
+\r
+  if (*IpCount == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  //\r
+  // Allocate buffer for IpList.\r
+  //\r
+  *PtrIpList = AllocateZeroPool(*IpCount * sizeof(EFI_IPv4_ADDRESS));\r
+  if (*PtrIpList == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Get IpList from Str.\r
+  //\r
+  Index = 0;\r
+  while (*(Str + Index) != L'\0') {\r
+    if (*(Str + Index) == L' ') {\r
+      if(!SpaceTag) {\r
+        StrTemp = AllocateZeroPool((EndIndex - BeginIndex + 1) * sizeof(CHAR16));\r
+        if (StrTemp == NULL) {\r
+          FreePool(*PtrIpList);\r
+          *PtrIpList = NULL;\r
+          *IpCount = 0;\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        \r
+        CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof(CHAR16));\r
+        *(StrTemp + (EndIndex - BeginIndex)) = L'\0';\r
+          \r
+        if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) {\r
+          FreePool(StrTemp);\r
+          FreePool(*PtrIpList);\r
+          *PtrIpList = NULL;\r
+          *IpCount = 0;\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+          \r
+        BeginIndex = EndIndex;\r
+        IpIndex++;\r
+\r
+        FreePool(StrTemp);\r
+      }\r
+\r
+      BeginIndex++;\r
+      EndIndex++;\r
+      SpaceTag = TRUE;\r
+    } else {\r
+      EndIndex++;\r
+      SpaceTag = FALSE;\r
+    }\r
+    \r
+    Index++;\r
+    \r
+    if (*(Str + Index) == L'\0') {\r
+      if (!SpaceTag) {\r
+        StrTemp = AllocateZeroPool((EndIndex - BeginIndex + 1) * sizeof(CHAR16));\r
+        if (StrTemp == NULL) {\r
+          FreePool(*PtrIpList);\r
+          *PtrIpList = NULL;\r
+          *IpCount = 0;\r
+          return EFI_OUT_OF_RESOURCES;\r
+        }\r
+        \r
+        CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof(CHAR16));\r
+        *(StrTemp + (EndIndex - BeginIndex)) = L'\0';\r
+        \r
+        if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) {\r
+          FreePool(StrTemp);\r
+          FreePool(*PtrIpList);\r
+          *PtrIpList = NULL;\r
+          *IpCount = 0;\r
+          return EFI_INVALID_PARAMETER;\r
+        }\r
+\r
+        FreePool(StrTemp);\r
+      }\r
+    }\r
+  } \r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Convert the IPv4 address into a dotted string.\r
+\r
+  @param[in]   Ip   The IPv4 address.\r
+  @param[out]  Str  The dotted IP string.\r
+  \r
+**/\r
+VOID\r
+Ip4Config2IpToStr (\r
+  IN  EFI_IPv4_ADDRESS  *Ip,\r
+  OUT CHAR16            *Str\r
+  )\r
+{\r
+  UnicodeSPrint (\r
+    Str,\r
+    2 * IP4_STR_MAX_SIZE, \r
+    L"%d.%d.%d.%d", \r
+    Ip->Addr[0],\r
+    Ip->Addr[1],\r
+    Ip->Addr[2],\r
+    Ip->Addr[3]\r
+    );\r
+}\r
+\r
+\r
+/**\r
+  Convert the IPv4 address list into string consists of several decimal \r
+  dotted IPv4 addresses separated by space.\r
+\r
+  @param[in]   Ip        The IPv4 address list.\r
+  @param[in]   IpCount   The size of IPv4 address list.\r
+  @param[out]  Str       The string contains several decimal dotted\r
+                         IPv4 addresses separated by space.       \r
+**/\r
+VOID\r
+Ip4Config2IpListToStr (\r
+  IN  EFI_IPv4_ADDRESS  *Ip,\r
+  IN  UINTN             IpCount,\r
+  OUT CHAR16            *Str\r
+  )\r
+{\r
+  UINTN            Index;\r
+  UINTN            TemIndex;\r
+  UINTN            StrIndex;\r
+  CHAR16           *TempStr;\r
+  EFI_IPv4_ADDRESS *TempIp;\r
+  \r
+  Index    = 0;\r
+  TemIndex = 0;\r
+  StrIndex = 0;\r
+  TempStr  = NULL;\r
+  TempIp   = NULL;\r
+\r
+  for (Index = 0; Index < IpCount; Index ++) {\r
+    TempIp = Ip + Index;\r
+    if (TempStr == NULL) {\r
+      TempStr = AllocateZeroPool(2 * IP4_STR_MAX_SIZE);\r
+      ASSERT(TempStr != NULL);\r
+    }\r
+\r
+    UnicodeSPrint (\r
+      TempStr, \r
+      2 * IP4_STR_MAX_SIZE, \r
+      L"%d.%d.%d.%d", \r
+      TempIp->Addr[0],\r
+      TempIp->Addr[1],\r
+      TempIp->Addr[2],\r
+      TempIp->Addr[3]\r
+      );\r
+\r
+    for (TemIndex = 0; TemIndex < IP4_STR_MAX_SIZE; TemIndex ++) {\r
+      if (*(TempStr + TemIndex) == L'\0') {\r
+        if (Index == IpCount - 1) {\r
+          Str[StrIndex++] = L'\0';\r
+        } else {\r
+          Str[StrIndex++] = L' ';\r
+        }  \r
+        break;\r
+      } else {\r
+        Str[StrIndex++] = *(TempStr + TemIndex);\r
+      }\r
+    }\r
+  }\r
+\r
+  if (TempStr != NULL) {\r
+    FreePool(TempStr);\r
+  }\r
+}\r
+\r
+/**\r
+  The notify function of create event when performing a manual configuration.\r
+\r
+  @param[in]    Event        The pointer of Event.\r
+  @param[in]    Context      The pointer of Context.\r
+  \r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4Config2ManualAddressNotify (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  *((BOOLEAN *) Context) = TRUE;\r
+}\r
+\r
+/**\r
+  Convert the network configuration data into the IFR data.\r
+\r
+  @param[in]       Instance          The IP4 config2 instance.\r
+  @param[in, out]  IfrNvData         The IFR nv data.\r
+\r
+  @retval EFI_SUCCESS            The configure parameter to IFR data was\r
+                                 set successfully.\r
+  @retval EFI_INVALID_PARAMETER  Source instance or target IFR data is not available.\r
+  @retval Others                 Other errors as indicated.\r
+  \r
+**/\r
+EFI_STATUS\r
+Ip4Config2ConvertConfigNvDataToIfrNvData (\r
+  IN     IP4_CONFIG2_INSTANCE       *Instance,\r
+  IN OUT IP4_CONFIG2_IFR_NVDATA     *IfrNvData\r
+  )\r
+{\r
+  IP4_SERVICE                                *IpSb;\r
+  EFI_IP4_CONFIG2_PROTOCOL                   *Ip4Config2;\r
+  EFI_IP4_CONFIG2_INTERFACE_INFO             *Ip4Info;\r
+  EFI_IP4_CONFIG2_POLICY                     Policy;\r
+  UINTN                                      DataSize;\r
+  UINTN                                      GatewaySize;\r
+  EFI_IPv4_ADDRESS                           GatewayAddress;\r
+  EFI_STATUS                                 Status;\r
+  UINTN                                      DnsSize;\r
+  UINTN                                      DnsCount;\r
+  EFI_IPv4_ADDRESS                           *DnsAddress;\r
+\r
+  Status      = EFI_SUCCESS;\r
+  Ip4Config2  = &Instance->Ip4Config2;\r
+  Ip4Info     = NULL;\r
+  DnsAddress  = NULL;\r
+  GatewaySize = sizeof (EFI_IPv4_ADDRESS);\r
+  \r
+  if ((IfrNvData == NULL) || (Instance == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  NET_CHECK_SIGNATURE (Instance, IP4_CONFIG2_INSTANCE_SIGNATURE);\r
+\r
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
+\r
+  if (IpSb->DefaultInterface->Configured) {\r
+    IfrNvData->Configure = 1;\r
+  } else {\r
+    IfrNvData->Configure = 0;\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Get the Policy info.\r
+  // \r
+  DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);\r
+  Status   = Ip4Config2->GetData (\r
+                           Ip4Config2,\r
+                           Ip4Config2DataTypePolicy,\r
+                           &DataSize,\r
+                           &Policy\r
+                           );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+  \r
+  if (Policy == Ip4Config2PolicyStatic) {\r
+    IfrNvData->DhcpEnable = FALSE;\r
+  } else if (Policy == Ip4Config2PolicyDhcp) {\r
+    IfrNvData->DhcpEnable = TRUE;\r
+    goto Exit;\r
+  }\r
+  \r
+  //\r
+  // Get the interface info.\r
+  //\r
+  DataSize    = 0;\r
+  Status = Ip4Config2->GetData (\r
+                         Ip4Config2,\r
+                         Ip4Config2DataTypeInterfaceInfo,\r
+                         &DataSize,\r
+                         NULL\r
+                         );\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return Status;\r
+  }\r
+  \r
+  Ip4Info = AllocateZeroPool (DataSize);\r
+  if (Ip4Info == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    return Status;\r
+  }\r
+\r
+  Status = Ip4Config2->GetData (\r
+                         Ip4Config2,\r
+                         Ip4Config2DataTypeInterfaceInfo,\r
+                         &DataSize,\r
+                         Ip4Info\r
+                         );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+  \r
+  //\r
+  // Get the Gateway info.\r
+  //\r
+  Status = Ip4Config2->GetData (\r
+                         Ip4Config2,\r
+                         Ip4Config2DataTypeGateway,\r
+                         &GatewaySize,\r
+                         &GatewayAddress\r
+                         );\r
+  if (EFI_ERROR (Status)) {\r
+    goto Exit;\r
+  }\r
+\r
+  //\r
+  // Get the Dns info.\r
+  //\r
+  DnsSize = 0;\r
+  Status = Ip4Config2->GetData (\r
+                         Ip4Config2,\r
+                         Ip4Config2DataTypeDnsServer,\r
+                         &DnsSize,\r
+                         NULL\r
+                         );\r
+  if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {\r
+    goto Exit;\r
+  }\r
+  \r
+  DnsCount = (UINT32) (DnsSize / sizeof (EFI_IPv4_ADDRESS));\r
+\r
+  if (DnsSize > 0) {\r
+    DnsAddress = AllocateZeroPool(DnsSize);\r
+    if (DnsAddress == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Exit;\r
+    }\r
+    \r
+    Status = Ip4Config2->GetData (\r
+                           Ip4Config2,\r
+                           Ip4Config2DataTypeDnsServer,\r
+                           &DnsSize,\r
+                           DnsAddress\r
+                           );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+  }\r
+\r
+  Ip4Config2IpToStr (&Ip4Info->StationAddress, IfrNvData->StationAddress);\r
+  Ip4Config2IpToStr (&Ip4Info->SubnetMask, IfrNvData->SubnetMask);\r
+  Ip4Config2IpToStr (&GatewayAddress, IfrNvData->GatewayAddress);\r
+  Ip4Config2IpListToStr (DnsAddress, DnsCount, IfrNvData->DnsAddress);\r
+\r
+Exit:\r
+\r
+  if (DnsAddress != NULL) {\r
+    FreePool(DnsAddress);\r
+  }\r
+\r
+  if (Ip4Info != NULL) {\r
+    FreePool(Ip4Info);\r
+  }\r
+  \r
+  return Status;\r
+}\r
+\r
+/**\r
+  Convert the IFR data into the network configuration data and set the IP\r
+  configure parameters for the NIC.\r
+\r
+  @param[in]       IfrFormNvData     The IFR NV data.\r
+  @param[in, out]  Instance          The IP4 config2 instance.\r
+\r
+  @retval EFI_SUCCESS            The configure parameter for this NIC was\r
+                                 set successfully.\r
+  @retval EFI_INVALID_PARAMETER  The address information for setting is invalid.\r
+  @retval Others                 Other errors as indicated.\r
+  \r
+**/\r
+EFI_STATUS\r
+Ip4Config2ConvertIfrNvDataToConfigNvData (\r
+  IN     IP4_CONFIG2_IFR_NVDATA     *IfrFormNvData,\r
+  IN OUT IP4_CONFIG2_INSTANCE       *Instance\r
+  )\r
+{\r
+  EFI_STATUS                       Status;  \r
+  EFI_IP4_CONFIG2_PROTOCOL         *Ip4Cfg2;\r
+  IP4_CONFIG2_NVDATA               *Ip4NvData; \r
+\r
+  EFI_IP_ADDRESS                   StationAddress;\r
+  EFI_IP_ADDRESS                   SubnetMask;\r
+  EFI_IP_ADDRESS                   Gateway;\r
+  IP4_ADDR                         Ip;\r
+  EFI_IPv4_ADDRESS                 *DnsAddress;\r
+  UINTN                            DnsCount;\r
+  UINTN                            Index;\r
+\r
+  EFI_EVENT                        TimeoutEvent;\r
+  EFI_EVENT                        SetAddressEvent;\r
+  BOOLEAN                          IsAddressOk;\r
+  UINTN                            DataSize;\r
+  EFI_INPUT_KEY                    Key;\r
+\r
+  Status          = EFI_SUCCESS;\r
+  Ip4Cfg2         = &Instance->Ip4Config2;\r
+  Ip4NvData       = &Instance->Ip4NvData;\r
+  \r
+  DnsCount        = 0;\r
+  DnsAddress      = NULL; \r
+  \r
+  TimeoutEvent    = NULL;\r
+  SetAddressEvent = NULL;\r
+\r
+\r
+  \r
+  if (Instance == NULL || IfrFormNvData == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (IfrFormNvData->Configure != TRUE) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
+  if (IfrFormNvData->DhcpEnable == TRUE) {\r
+    Ip4NvData->Policy = Ip4Config2PolicyDhcp;\r
+    \r
+    Status = Ip4Cfg2->SetData (\r
+                        Ip4Cfg2,\r
+                        Ip4Config2DataTypePolicy,\r
+                        sizeof (EFI_IP4_CONFIG2_POLICY),\r
+                        &Ip4NvData->Policy\r
+                        );\r
+    if (EFI_ERROR(Status)) {\r
+      return Status;\r
+    }\r
+  } else {\r
+    //\r
+    // Get Ip4NvData from IfrFormNvData if it is valid.\r
+    //\r
+    Ip4NvData->Policy = Ip4Config2PolicyStatic;\r
+\r
+    Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);\r
+    if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), 0)) {\r
+      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    \r
+    Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);\r
+    if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
+      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+    \r
+    Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);\r
+    if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
+      CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);\r
+    if (!EFI_ERROR (Status) && DnsCount > 0) {\r
+      for (Index = 0; Index < DnsCount; Index ++) {\r
+        CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));\r
+        if (!NetIp4IsUnicast (NTOHL (Ip), 0)) {\r
+          CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
+          FreePool(DnsAddress);\r
+          return EFI_INVALID_PARAMETER;\r
+        } \r
+      } \r
+    } else {\r
+      if (EFI_ERROR (Status)) {\r
+        CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
+      }\r
+    }\r
+    \r
+    if (Ip4NvData->ManualAddress != NULL) {\r
+      FreePool(Ip4NvData->ManualAddress); \r
+    }\r
+    Ip4NvData->ManualAddressCount = 1;\r
+    Ip4NvData->ManualAddress = AllocateZeroPool(sizeof(EFI_IP4_CONFIG2_MANUAL_ADDRESS));\r
+    if (Ip4NvData->ManualAddress == NULL) {\r
+      if (DnsAddress != NULL) {\r
+        FreePool(DnsAddress);\r
+      }\r
+      \r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem(&Ip4NvData->ManualAddress->Address, &StationAddress.v4, sizeof(EFI_IPv4_ADDRESS));\r
+    CopyMem(&Ip4NvData->ManualAddress->SubnetMask, &SubnetMask.v4, sizeof(EFI_IPv4_ADDRESS));\r
+    \r
+    if (Ip4NvData->GatewayAddress != NULL) {\r
+      FreePool(Ip4NvData->GatewayAddress); \r
+    }\r
+    Ip4NvData->GatewayAddressCount = 1;\r
+    Ip4NvData->GatewayAddress = AllocateZeroPool(sizeof(EFI_IPv4_ADDRESS));\r
+    if (Ip4NvData->GatewayAddress == NULL) {\r
+      if (DnsAddress != NULL) {\r
+        FreePool(DnsAddress);\r
+      }\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    CopyMem(Ip4NvData->GatewayAddress, &Gateway.v4, sizeof(EFI_IPv4_ADDRESS));\r
+    \r
+    if (Ip4NvData->DnsAddress != NULL) {\r
+      FreePool(Ip4NvData->DnsAddress); \r
+    }\r
+    Ip4NvData->DnsAddressCount = (UINT32) DnsCount;\r
+    Ip4NvData->DnsAddress      = DnsAddress;\r
+\r
+    //\r
+    // Setting Ip4NvData.\r
+    //\r
+    Status = Ip4Cfg2->SetData (\r
+                        Ip4Cfg2,\r
+                        Ip4Config2DataTypePolicy,\r
+                        sizeof (EFI_IP4_CONFIG2_POLICY),\r
+                        &Ip4NvData->Policy\r
+                        );\r
+    if (EFI_ERROR(Status)) {\r
+      return Status;\r
+    }\r
+\r
+    //\r
+    // Create events & timers for asynchronous settings.\r
+    //\r
+    Status = gBS->CreateEvent (\r
+                    EVT_TIMER,\r
+                    TPL_CALLBACK,\r
+                    NULL,\r
+                    NULL,\r
+                    &TimeoutEvent\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    Ip4Config2ManualAddressNotify,\r
+                    &IsAddressOk,\r
+                    &SetAddressEvent\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+\r
+    IsAddressOk = FALSE;\r
+    \r
+    Status = Ip4Cfg2->RegisterDataNotify (\r
+                        Ip4Cfg2,\r
+                        Ip4Config2DataTypeManualAddress,\r
+                        SetAddressEvent\r
+                        );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Set ManualAddress.\r
+    //\r
+    DataSize = Ip4NvData->ManualAddressCount * sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);\r
+    Status = Ip4Cfg2->SetData (\r
+                        Ip4Cfg2,\r
+                        Ip4Config2DataTypeManualAddress,\r
+                        DataSize,\r
+                        (VOID *) Ip4NvData->ManualAddress\r
+                        );\r
+\r
+    if (Status == EFI_NOT_READY) {\r
+      gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000);\r
+      while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {\r
+        if (IsAddressOk) {\r
+          Status = EFI_SUCCESS;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    Ip4Cfg2->UnregisterDataNotify (\r
+               Ip4Cfg2,\r
+               Ip4Config2DataTypeManualAddress,\r
+               SetAddressEvent\r
+               );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Set gateway.\r
+    //\r
+    DataSize = Ip4NvData->GatewayAddressCount * sizeof (EFI_IPv4_ADDRESS);\r
+    Status = Ip4Cfg2->SetData (\r
+                        Ip4Cfg2,\r
+                        Ip4Config2DataTypeGateway,\r
+                        DataSize,\r
+                        Ip4NvData->GatewayAddress\r
+                        );\r
+    if (EFI_ERROR (Status)) {\r
+      goto Exit;\r
+    }\r
+\r
+    //\r
+    // Set DNS addresses.\r
+    //\r
+    if (Ip4NvData->DnsAddressCount > 0 && Ip4NvData->DnsAddress != NULL) {\r
+      DataSize = Ip4NvData->DnsAddressCount * sizeof (EFI_IPv4_ADDRESS);\r
+      Status = Ip4Cfg2->SetData (\r
+                          Ip4Cfg2,\r
+                          Ip4Config2DataTypeDnsServer,\r
+                          DataSize,\r
+                          Ip4NvData->DnsAddress\r
+                          );\r
+      \r
+      if (EFI_ERROR (Status)) {\r
+        goto Exit;\r
+      } \r
+    } \r
+  } \r
+\r
+Exit:\r
+  if (SetAddressEvent != NULL) {\r
+    gBS->CloseEvent (SetAddressEvent);\r
+  }\r
+\r
+  if (TimeoutEvent != NULL) {\r
+    gBS->CloseEvent (TimeoutEvent);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function allows the caller to request the current\r
+  configuration for one or more named elements. The resulting\r
+  string is in <ConfigAltResp> format. Any and all alternative\r
+  configuration strings shall also be appended to the end of the\r
+  current configuration string. If they are, they must appear\r
+  after the current configuration. They must contain the same\r
+  routing (GUID, NAME, PATH) as the current configuration string.\r
+  They must have an additional description indicating the type of\r
+  alternative configuration the string represents,\r
+  "ALTCFG=<StringToken>". That <StringToken> (when\r
+  converted from Hex UNICODE to binary) is a reference to a\r
+  string in the associated string pack.\r
+\r
+  @param[in] This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in] Request    A null-terminated Unicode string in\r
+                        <ConfigRequest> format. Note that this\r
+                        includes the routing information as well as\r
+                        the configurable name / value pairs. It is\r
+                        invalid for this string to be in\r
+                        <MultiConfigRequest> format.\r
+  @param[out] Progress  On return, points to a character in the\r
+                        Request string. Points to the string's null\r
+                        terminator if request was successful. Points\r
+                        to the most recent "&" before the first\r
+                        failing name / value pair (or the beginning\r
+                        of the string if the failure is in the first\r
+                        name / value pair) if the request was not\r
+                        successful.\r
+  @param[out] Results   A null-terminated Unicode string in\r
+                        <ConfigAltResp> format which has all values\r
+                        filled in for the names in the Request string.\r
+                        String to be allocated by the called function.\r
+\r
+  @retval EFI_SUCCESS             The Results string is filled with the\r
+                                  values corresponding to all requested\r
+                                  names.\r
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the\r
+                                  parts of the results that must be\r
+                                  stored awaiting possible future\r
+                                  protocols.\r
+  @retval EFI_NOT_FOUND           Routing data doesn't match any\r
+                                  known driver. Progress set to the\r
+                                  first character in the routing header.\r
+                                  Note: There is no requirement that the\r
+                                  driver validate the routing data. It\r
+                                  must skip the <ConfigHdr> in order to\r
+                                  process the names.\r
+  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set\r
+                                  to most recent & before the\r
+                                  error or the beginning of the\r
+                                  string.\r
+  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points\r
+                                  to the & before the name in\r
+                                  question.Currently not implemented.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4FormExtractConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Request,\r
+  OUT EFI_STRING                             *Progress,\r
+  OUT EFI_STRING                             *Results\r
+  )\r
+{\r
+  EFI_STATUS                       Status;  \r
+  IP4_CONFIG2_INSTANCE             *Ip4Config2Instance;\r
+  IP4_FORM_CALLBACK_INFO           *Private;  \r
+  IP4_CONFIG2_IFR_NVDATA           *IfrFormNvData;\r
+  EFI_STRING                       ConfigRequestHdr;\r
+  EFI_STRING                       ConfigRequest;  \r
+  BOOLEAN                          AllocatedRequest;\r
+  EFI_STRING                       FormResult;\r
+  UINTN                            Size;\r
+  UINTN                            BufferSize;\r
+  \r
+  Status             = EFI_SUCCESS; \r
+  IfrFormNvData      = NULL;\r
+  ConfigRequest      = NULL;\r
+  FormResult         = NULL; \r
+  Size               = 0;\r
+  AllocatedRequest   = FALSE;    \r
+  ConfigRequest      = Request; \r
+  Private            = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
+  Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
+  BufferSize         = sizeof (IP4_CONFIG2_IFR_NVDATA);\r
+  *Progress          = Request;\r
+  \r
+  if (Progress == NULL || Results == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  //\r
+  // Check Request data in <ConfigHdr>.\r
+  //\r
+  if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
+    IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
+    if (IfrFormNvData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+    \r
+    Ip4Config2ConvertConfigNvDataToIfrNvData (Ip4Config2Instance, IfrFormNvData);\r
+    \r
+    if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {\r
+      //\r
+      // Request has no request element, construct full request string.\r
+      // Allocate and fill a buffer large enough to hold the <ConfigHdr> template\r
+      // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator\r
+      //\r
+      ConfigRequestHdr = HiiConstructConfigHdr (&gIp4Config2NvDataGuid, mIp4Config2StorageName, Private->ChildHandle);\r
+      Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);\r
+      ConfigRequest = AllocateZeroPool (Size);\r
+      ASSERT (ConfigRequest != NULL);\r
+      AllocatedRequest = TRUE;\r
+      \r
+      UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);\r
+      FreePool (ConfigRequestHdr);\r
+    }\r
+\r
+    //\r
+    // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+    //\r
+    Status = gHiiConfigRouting->BlockToConfig (\r
+                                  gHiiConfigRouting,\r
+                                  ConfigRequest,\r
+                                  (UINT8 *) IfrFormNvData,\r
+                                  BufferSize,\r
+                                  &FormResult,\r
+                                  Progress\r
+                                  );\r
+\r
+    FreePool (IfrFormNvData);\r
+    \r
+    //\r
+    // Free the allocated config request string.\r
+    //\r
+    if (AllocatedRequest) {\r
+      FreePool (ConfigRequest);\r
+      ConfigRequest = NULL;\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto Failure;\r
+    }\r
+  }\r
+  \r
+  if (Request == NULL || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
+    *Results = FormResult;\r
+  } else {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+Failure:\r
+  //\r
+  // Set Progress string to the original request string.\r
+  //\r
+  if (Request == NULL) {\r
+    *Progress = NULL;\r
+  } else if (StrStr (Request, L"OFFSET") == NULL) {\r
+    *Progress = Request + StrLen (Request);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  This function applies changes in a driver's configuration.\r
+  Input is a Configuration, which has the routing data for this\r
+  driver followed by name / value configuration pairs. The driver\r
+  must apply those pairs to its configurable storage. If the\r
+  driver's configuration is stored in a linear block of data\r
+  and the driver's name / value pairs are in <BlockConfig>\r
+  format, it may use the ConfigToBlock helper function (above) to\r
+  simplify the job. Currently not implemented.\r
+\r
+  @param[in]  This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]  Configuration  A null-terminated Unicode string in\r
+                             <ConfigString> format.\r
+  @param[out] Progress       A pointer to a string filled in with the\r
+                             offset of the most recent '&' before the\r
+                             first failing name / value pair (or the\r
+                             beginn ing of the string if the failure\r
+                             is in the first name / value pair) or\r
+                             the terminating NULL if all was\r
+                             successful.\r
+\r
+  @retval EFI_SUCCESS             The results have been distributed or are\r
+                                  awaiting distribution.\r
+  @retval EFI_OUT_OF_MEMORY       Not enough memory to store the\r
+                                  parts of the results that must be\r
+                                  stored awaiting possible future\r
+                                  protocols.\r
+  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the\r
+                                  Results parameter would result\r
+                                  in this type of error.\r
+  @retval EFI_NOT_FOUND           Target for the specified routing data\r
+                                  was not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4FormRouteConfig (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  CONST EFI_STRING                       Configuration,\r
+  OUT EFI_STRING                             *Progress\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINTN                            BufferSize;\r
+  IP4_CONFIG2_IFR_NVDATA           *IfrFormNvData;\r
+  IP4_CONFIG2_INSTANCE             *Ip4Config2Instance;\r
+  IP4_FORM_CALLBACK_INFO           *Private;\r
+\r
+  Status        = EFI_SUCCESS;\r
+  IfrFormNvData = NULL;\r
+\r
+  if (Configuration == NULL || Progress == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Progress = Configuration;\r
+\r
+  Private            = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
+  Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
+\r
+  //\r
+  // Check Routing data in <ConfigHdr>.\r
+  //\r
+  if (HiiIsConfigHdrMatch (Configuration, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) {\r
+    //\r
+    // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+    //\r
+    IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
+    if (IfrFormNvData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    BufferSize = 0;\r
+\r
+    Status = gHiiConfigRouting->ConfigToBlock (\r
+                                  gHiiConfigRouting,\r
+                                  Configuration,\r
+                                  (UINT8 *) IfrFormNvData,\r
+                                  &BufferSize,\r
+                                  Progress\r
+                                  );\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      return Status;\r
+    }\r
+\r
+    Status = gHiiConfigRouting->ConfigToBlock (\r
+                                  gHiiConfigRouting,\r
+                                  Configuration,\r
+                                  (UINT8 *) IfrFormNvData,\r
+                                  &BufferSize,\r
+                                  Progress\r
+                                  );\r
+    if (!EFI_ERROR (Status)) {\r
+      Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Ip4Config2Instance);\r
+    }\r
+\r
+    FreePool (IfrFormNvData);\r
+  } else {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  This function is called to provide results data to the driver.\r
+  This data consists of a unique key that is used to identify\r
+  which data is either being passed back or being asked for.\r
+\r
+  @param[in]  This               Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+  @param[in]  Action             Specifies the type of action taken by the browser.\r
+  @param[in]  QuestionId         A unique value which is sent to the original\r
+                                 exporting driver so that it can identify the type\r
+                                 of data to expect. The format of the data tends to\r
+                                 vary based on the opcode that enerated the callback.\r
+  @param[in]  Type               The type of value for the question.\r
+  @param[in]  Value              A pointer to the data being sent to the original\r
+                                 exporting driver.\r
+  @param[out] ActionRequest      On return, points to the action requested by the\r
+                                 callback function.\r
+\r
+  @retval EFI_SUCCESS            The callback successfully handled the action.\r
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the\r
+                                 variable and its data.\r
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.\r
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the\r
+                                 callback.Currently not implemented.\r
+  @retval EFI_INVALID_PARAMETERS Passing in wrong parameter.\r
+  @retval Others                 Other errors as indicated.\r
+  \r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4FormCallback (\r
+  IN  CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,\r
+  IN  EFI_BROWSER_ACTION                     Action,\r
+  IN  EFI_QUESTION_ID                        QuestionId,\r
+  IN  UINT8                                  Type,\r
+  IN  EFI_IFR_TYPE_VALUE                     *Value,\r
+  OUT EFI_BROWSER_ACTION_REQUEST             *ActionRequest\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  IP4_CONFIG2_INSTANCE      *Instance;\r
+  IP4_CONFIG2_IFR_NVDATA    *IfrFormNvData;\r
+  IP4_FORM_CALLBACK_INFO    *Private;\r
+  \r
+  EFI_IP_ADDRESS            StationAddress;\r
+  EFI_IP_ADDRESS            SubnetMask;\r
+  EFI_IP_ADDRESS            Gateway;\r
+  IP4_ADDR                  Ip;\r
+  EFI_IPv4_ADDRESS          *DnsAddress;\r
+  UINTN                     DnsCount;\r
+  UINTN                     Index;\r
+  EFI_INPUT_KEY             Key;\r
+  \r
+  IfrFormNvData = NULL;\r
+  DnsCount      = 0;\r
+  DnsAddress    = NULL; \r
+\r
+  if (Action == EFI_BROWSER_ACTION_CHANGED) {\r
+    Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS(This);\r
+    Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK(Private);\r
+    \r
+    IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA));\r
+    if (IfrFormNvData == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    //\r
+    // Retrive uncommitted data from Browser\r
+    //\r
+    if (!HiiGetBrowserData (&gIp4Config2NvDataGuid, mIp4Config2StorageName, sizeof (IP4_CONFIG2_IFR_NVDATA), (UINT8 *) IfrFormNvData)) {\r
+      FreePool (IfrFormNvData);\r
+      return EFI_NOT_FOUND;\r
+    }\r
+\r
+    Status = EFI_SUCCESS;\r
+\r
+    switch (QuestionId) {\r
+    case KEY_LOCAL_IP:\r
+      Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4);\r
+      if (EFI_ERROR (Status) || !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), 0)) {\r
+        CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL);\r
+        Status = EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+\r
+    case KEY_SUBNET_MASK:\r
+      Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4);\r
+      if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) {\r
+        CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL);\r
+        Status = EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+\r
+    case KEY_GATE_WAY:\r
+      Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4);\r
+      if (EFI_ERROR (Status) || ((Gateway.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), 0))) {\r
+        CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL);\r
+        Status = EFI_INVALID_PARAMETER;\r
+      }\r
+      break;\r
+    \r
+    case KEY_DNS:\r
+      Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount);\r
+      if (!EFI_ERROR (Status) && DnsCount > 0) {\r
+        for (Index = 0; Index < DnsCount; Index ++) {\r
+          CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR));\r
+          if (!NetIp4IsUnicast (NTOHL (Ip), 0)) {\r
+            CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
+            Status = EFI_INVALID_PARAMETER;\r
+            break;\r
+          } \r
+        }\r
+      } else {\r
+        if (EFI_ERROR (Status)) {\r
+          CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL);\r
+        }\r
+      }\r
+      \r
+      if(DnsAddress != NULL) {  \r
+        FreePool(DnsAddress);\r
+      }\r
+      break;\r
+      \r
+    case KEY_SAVE_CHANGES:\r
+      Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Instance);\r
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+      break;\r
+\r
+    default:\r
+      break;\r
+    }\r
+\r
+    FreePool (IfrFormNvData);\r
+\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // All other action return unsupported.\r
+  //\r
+  return EFI_UNSUPPORTED;\r
+}\r
+\r
+/**\r
+  Install HII Config Access protocol for network device and allocate resource.\r
+\r
+  @param[in, out]  Instance        The IP4 config2 Instance.\r
+\r
+  @retval EFI_SUCCESS              The HII Config Access protocol is installed.\r
+  @retval EFI_OUT_OF_RESOURCES     Failed to allocate memory.\r
+  @retval Others                   Other errors as indicated.\r
+  \r
+**/\r
+EFI_STATUS\r
+Ip4Config2FormInit (\r
+  IN OUT IP4_CONFIG2_INSTANCE     *Instance\r
+  )\r
+{\r
+  EFI_STATUS                     Status;\r
+  IP4_SERVICE                    *IpSb;\r
+  IP4_FORM_CALLBACK_INFO         *CallbackInfo;\r
+  EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess;\r
+  VENDOR_DEVICE_PATH             VendorDeviceNode;\r
+  EFI_SERVICE_BINDING_PROTOCOL   *MnpSb;\r
+  CHAR16                         *MacString;\r
+  CHAR16                         MenuString[128];\r
+  CHAR16                         PortString[128];\r
+  CHAR16                         *OldMenuString;\r
+  EFI_DEVICE_PATH_PROTOCOL       *ParentDevicePath;\r
+\r
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
+  ASSERT (IpSb != NULL);\r
+  \r
+  CallbackInfo = &Instance->CallbackInfo;\r
+  \r
+  CallbackInfo->Signature = IP4_FORM_CALLBACK_INFO_SIGNATURE;\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  IpSb->Controller,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  (VOID **) &ParentDevicePath\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Construct device path node for EFI HII Config Access protocol,\r
+  // which consists of controller physical device path and one hardware\r
+  // vendor guid node.\r
+  //\r
+  ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH));\r
+  VendorDeviceNode.Header.Type    = HARDWARE_DEVICE_PATH;\r
+  VendorDeviceNode.Header.SubType = HW_VENDOR_DP;\r
+\r
+  CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid);\r
+\r
+  SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH));\r
+  CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode (\r
+                                        ParentDevicePath,\r
+                                        (EFI_DEVICE_PATH_PROTOCOL *) &VendorDeviceNode\r
+                                        );\r
+  if (CallbackInfo->HiiVendorDevicePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  ConfigAccess                = &CallbackInfo->HiiConfigAccessProtocol;\r
+  ConfigAccess->ExtractConfig = Ip4FormExtractConfig;\r
+  ConfigAccess->RouteConfig   = Ip4FormRouteConfig;\r
+  ConfigAccess->Callback      = Ip4FormCallback;\r
+\r
+  //\r
+  // Install Device Path Protocol and Config Access protocol on new handle\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &CallbackInfo->ChildHandle,\r
+                  &gEfiDevicePathProtocolGuid,\r
+                  CallbackInfo->HiiVendorDevicePath,\r
+                  &gEfiHiiConfigAccessProtocolGuid,\r
+                  ConfigAccess,\r
+                  NULL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Open the Parent Handle for the child\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    IpSb->Controller,\r
+                    &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                    (VOID **) &MnpSb,\r
+                    IpSb->Image,\r
+                    CallbackInfo->ChildHandle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto Error;\r
+  }\r
+\r
+  //\r
+  // Publish our HII data\r
+  //\r
+  CallbackInfo->RegisteredHandle = HiiAddPackages (\r
+                                     &gIp4Config2NvDataGuid,\r
+                                     CallbackInfo->ChildHandle,\r
+                                     Ip4DxeStrings,\r
+                                     Ip4Config2Bin,\r
+                                     NULL\r
+                                     );\r
+  if (CallbackInfo->RegisteredHandle == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Error;\r
+  }\r
+\r
+  //\r
+  // Append MAC string in the menu help string and tile help string\r
+  //\r
+  Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString);\r
+  if (!EFI_ERROR (Status)) {\r
+    OldMenuString = HiiGetString (\r
+                      CallbackInfo->RegisteredHandle, \r
+                      STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP), \r
+                      NULL\r
+                      );\r
+    UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString);\r
+    HiiSetString (\r
+      CallbackInfo->RegisteredHandle, \r
+      STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP), \r
+      MenuString, \r
+      NULL\r
+      );\r
+\r
+    UnicodeSPrint (PortString, 128, L"MAC:%s", MacString);\r
+    HiiSetString (\r
+      CallbackInfo->RegisteredHandle,  \r
+      STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP), \r
+      PortString, \r
+      NULL\r
+      );\r
+    \r
+    FreePool (MacString);\r
+    FreePool (OldMenuString);\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+Error:\r
+  Ip4Config2FormUnload (Instance);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Uninstall the HII Config Access protocol for network devices and free up the resources.\r
+\r
+  @param[in, out]  Instance      The IP4 config2 instance to unload a form.\r
+\r
+**/\r
+VOID\r
+Ip4Config2FormUnload (\r
+  IN OUT IP4_CONFIG2_INSTANCE     *Instance\r
+  )\r
+{\r
+  IP4_SERVICE                    *IpSb;\r
+  IP4_FORM_CALLBACK_INFO         *CallbackInfo;\r
+  IP4_CONFIG2_NVDATA             *Ip4NvData;\r
+\r
+  IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
+  ASSERT (IpSb != NULL);\r
+\r
+  CallbackInfo = &Instance->CallbackInfo;\r
+\r
+  if (CallbackInfo->ChildHandle != NULL) {\r
+    //\r
+    // Close the child handle\r
+    //\r
+    gBS->CloseProtocol (\r
+           IpSb->Controller,\r
+           &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+           IpSb->Image,\r
+           CallbackInfo->ChildHandle\r
+           );\r
+    \r
+    //\r
+    // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL\r
+    //\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+           CallbackInfo->ChildHandle,\r
+           &gEfiDevicePathProtocolGuid,\r
+           CallbackInfo->HiiVendorDevicePath,\r
+           &gEfiHiiConfigAccessProtocolGuid,\r
+           &CallbackInfo->HiiConfigAccessProtocol,\r
+           NULL\r
+           );\r
+  }\r
+\r
+  if (CallbackInfo->HiiVendorDevicePath != NULL) {\r
+    FreePool (CallbackInfo->HiiVendorDevicePath);\r
+  }\r
+\r
+  if (CallbackInfo->RegisteredHandle != NULL) {\r
+    //\r
+    // Remove HII package list\r
+    //\r
+    HiiRemovePackages (CallbackInfo->RegisteredHandle);\r
+  }\r
+\r
+  Ip4NvData = &Instance->Ip4NvData;\r
+\r
+  if(Ip4NvData->ManualAddress != NULL) {\r
+    FreePool(Ip4NvData->ManualAddress);\r
+  }\r
+\r
+  if(Ip4NvData->GatewayAddress != NULL) {\r
+    FreePool(Ip4NvData->GatewayAddress);\r
+  }\r
+\r
+  if(Ip4NvData->DnsAddress != NULL) {\r
+    FreePool(Ip4NvData->DnsAddress);\r
+  }\r
+\r
+  Ip4NvData->ManualAddressCount  = 0;\r
+  Ip4NvData->GatewayAddressCount = 0;\r
+  Ip4NvData->DnsAddressCount     = 0;\r
+}\r
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Nv.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Nv.h
new file mode 100644 (file)
index 0000000..5a82e6d
--- /dev/null
@@ -0,0 +1,51 @@
+/** @file\r
+  The header file of IP4Config2Nv.c\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _IP4_CONFIG2NV_H_\r
+#define _IP4_CONFIG2NV_H_\r
+\r
+#include "Ip4Impl.h"\r
+\r
+extern UINT8  Ip4Config2Bin[];\r
+extern UINT8  Ip4DxeStrings[];\r
+\r
+#define NIC_ITEM_CONFIG_SIZE   (sizeof (IP4_CONFIG2_INSTANCE) + (sizeof (EFI_IPv4_ADDRESS) * MAX_IP4_CONFIG_DNS))\r
+\r
+/**\r
+  Install HII Config Access protocol for network device and allocate resource.\r
+\r
+  @param[in, out]  Instance         The IP4 config2 Instance.\r
+\r
+  @retval EFI_SUCCESS              The HII Config Access protocol is installed.\r
+  @retval EFI_OUT_OF_RESOURCES     Failed to allocate memory.\r
+  @retval Others                   Other errors as indicated.\r
+  \r
+**/\r
+EFI_STATUS\r
+Ip4Config2FormInit (\r
+  IN OUT IP4_CONFIG2_INSTANCE     *Instance\r
+  );\r
+\r
+/**\r
+  Uninstall the HII Config Access protocol for network devices and free up the resources.\r
+\r
+  @param[in, out]  Instance      The IP4 config2 instance to unload a form.\r
+\r
+**/\r
+VOID\r
+Ip4Config2FormUnload (\r
+  IN OUT IP4_CONFIG2_INSTANCE     *Instance\r
+  );\r
+\r
+#endif\r
index 4944113..101390c 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The driver binding and service binding protocol for IP4 driver.\r
 \r
-Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -121,7 +121,7 @@ Ip4DriverBindingSupported (
   destroyed, it is marked as that in case the destroy failed and\r
   being called again later.\r
 \r
-  @param[in]  IpSb               The IP4 serviceing binding instance to clean up\r
+  @param[in]  IpSb               The IP4 service binding instance to clean up\r
 \r
   @retval EFI_SUCCESS            The resource used by the instance are cleaned up\r
   @retval other                  Failed to clean up some of the resources.\r
@@ -166,7 +166,7 @@ Ip4CreateService (
   // empty resources, so if any thing goes wrong when allocating\r
   // resources, Ip4CleanService can be called to clean it up.\r
   //\r
-  IpSb = AllocatePool (sizeof (IP4_SERVICE));\r
+  IpSb = AllocateZeroPool (sizeof (IP4_SERVICE));\r
 \r
   if (IpSb == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -208,11 +208,7 @@ Ip4CreateService (
 \r
   ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
 \r
-  IpSb->Timer                       = NULL;\r
-  IpSb->Ip4Config                   = NULL;\r
-  IpSb->DoneEvent                   = NULL;\r
-  IpSb->ReconfigEvent               = NULL;\r
-  IpSb->ActiveEvent                 = NULL;\r
+  IpSb->Timer = NULL;\r
 \r
   //\r
   // Create various resources. First create the route table, timer\r
@@ -280,6 +276,13 @@ Ip4CreateService (
     goto ON_ERROR;\r
   }\r
 \r
+  IpSb->MacString = NULL;\r
+  Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);\r
 \r
   if (IpSb->DefaultInterface == NULL) {\r
@@ -289,6 +292,14 @@ Ip4CreateService (
 \r
   InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
 \r
+  ZeroMem (&IpSb->Ip4Config2Instance, sizeof (IP4_CONFIG2_INSTANCE));\r
+  \r
+  Status = Ip4Config2InitInstance (&IpSb->Ip4Config2Instance);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   IpSb->MaxPacketSize = IpSb->SnpMode.MaxPacketSize - sizeof (IP4_HEAD);\r
   if (NetLibGetVlanId (IpSb->Controller) != 0) {\r
     //\r
@@ -298,6 +309,7 @@ Ip4CreateService (
   }\r
   IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;\r
   *Service = IpSb;\r
+\r
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
@@ -315,7 +327,7 @@ ON_ERROR:
   destroyed, it is marked as that in case the destroy failed and\r
   being called again later.\r
 \r
-  @param[in]  IpSb               The IP4 serviceing binding instance to clean up\r
+  @param[in]  IpSb               The IP4 service binding instance to clean up\r
 \r
   @retval EFI_SUCCESS            The resource used by the instance are cleaned up\r
   @retval other                  Failed to clean up some of the resources.\r
@@ -374,22 +386,12 @@ Ip4CleanService (
     IpSb->Timer = NULL;\r
   }\r
 \r
-  if (IpSb->Ip4Config != NULL) {\r
-    IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
-\r
-    gBS->CloseProtocol (\r
-          IpSb->Controller,\r
-          &gEfiIp4ConfigProtocolGuid,\r
-          IpSb->Image,\r
-          IpSb->Controller\r
-          );\r
-\r
-    gBS->CloseEvent (IpSb->DoneEvent);\r
-    gBS->CloseEvent (IpSb->ReconfigEvent);\r
-    IpSb->ActiveEvent = NULL;\r
-    IpSb->Ip4Config = NULL;\r
+  if (IpSb->MacString != NULL) {\r
+    FreePool (IpSb->MacString);\r
   }\r
 \r
+  Ip4Config2CleanInstance (&IpSb->Ip4Config2Instance);\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -452,13 +454,13 @@ Ip4DestroyChildEntryInHandleBuffer (
 EFI_STATUS\r
 EFIAPI\r
 Ip4DriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
   )\r
-{\r
-  IP4_SERVICE               *IpSb;\r
-  EFI_STATUS                Status;\r
+{ \r
+  EFI_STATUS                    Status;\r
+  IP4_SERVICE                   *IpSb;\r
 \r
   //\r
   // Test for the Ip4 service binding protocol\r
@@ -475,12 +477,13 @@ Ip4DriverBindingStart (
   if (Status == EFI_SUCCESS) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
-\r
+  \r
   Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
-\r
+  \r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+  \r
   ASSERT (IpSb != NULL);\r
 \r
   //\r
@@ -490,19 +493,23 @@ Ip4DriverBindingStart (
                   &ControllerHandle,\r
                   &gEfiIp4ServiceBindingProtocolGuid,\r
                   &IpSb->ServiceBinding,\r
+                  &gEfiIp4Config2ProtocolGuid,\r
+                  &IpSb->Ip4Config2Instance.Ip4Config2,\r
                   NULL\r
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
     goto FREE_SERVICE;\r
   }\r
-\r
\r
   //\r
-  // ready to go: start the receiving and timer\r
+  // Ready to go: start the receiving and timer.\r
+  // Ip4Config2SetPolicy maybe call Ip4ReceiveFrame() to set the default interface's RecvRequest first after\r
+  // Ip4Config2 instance is initialized. So, EFI_ALREADY_STARTED is the allowed return status.\r
   //\r
   Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
 \r
-  if (EFI_ERROR (Status)) {\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
     goto UNINSTALL_PROTOCOL;\r
   }\r
 \r
@@ -529,7 +536,6 @@ UNINSTALL_PROTOCOL:
 FREE_SERVICE:\r
   Ip4CleanService (IpSb);\r
   FreePool (IpSb);\r
-\r
   return Status;\r
 }\r
 \r
@@ -571,90 +577,23 @@ Ip4DriverBindingStop (
   IP4_INTERFACE                            *IpIf;\r
   IP4_ROUTE_TABLE                          *RouteTable;\r
 \r
-  //\r
-  // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol\r
-  // by driver. So the ControllerHandle may be the MNP child handle, ARP child\r
-  // handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed\r
-  // in the NIC handle.\r
-  //\r
-  //\r
-  // First, check whether it is the IP4_CONFIG protocol being uninstalled.\r
-  // IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary\r
-  // to clean up the default configuration if IP4_CONFIG is being stopped.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  ControllerHandle,\r
-                  &gEfiIp4ConfigProtocolGuid,\r
-                  NULL,\r
-                  This->DriverBindingHandle,\r
-                  ControllerHandle,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                  );\r
-  if (Status == EFI_SUCCESS) {\r
-    //\r
-    // Retrieve the IP4 service binding protocol. If failed, it is\r
-    // likely that Ip4 ServiceBinding is uninstalled already. In this\r
-    // case, return immediately.\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    ControllerHandle,\r
-                    &gEfiIp4ServiceBindingProtocolGuid,\r
-                    (VOID **) &ServiceBinding,\r
-                    This->DriverBindingHandle,\r
-                    ControllerHandle,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-\r
-    IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
-    if (IpSb->Ip4Config != NULL && (IpSb->State != IP4_SERVICE_DESTROY)) {\r
-\r
-      IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
-\r
-      Status = gBS->CloseProtocol (\r
-                      ControllerHandle,\r
-                      &gEfiIp4ConfigProtocolGuid,\r
-                      IpSb->Image,\r
-                      ControllerHandle\r
-                      );\r
-      if (EFI_ERROR (Status)) {\r
-        return Status;\r
-      }\r
-\r
-      //\r
-      // If the auto configure hasn't complete, mark it as not started.\r
-      //\r
-      if (IpSb->State == IP4_SERVICE_STARTED) {\r
-        IpSb->State = IP4_SERVICE_UNSTARTED;\r
-      }\r
-\r
-      IpSb->Ip4Config = NULL;\r
-      gBS->CloseEvent (IpSb->DoneEvent);\r
-      gBS->CloseEvent (IpSb->ReconfigEvent);\r
-    }\r
-\r
-    return EFI_SUCCESS;\r
-  }\r
+  BOOLEAN                                  IsDhcp4;\r
 \r
-  //\r
-  // Either MNP or ARP protocol is being uninstalled. The controller\r
-  // handle is either the MNP child or ARP child. But, the IP4's\r
-  // service binding is installed on the NIC handle. So, need to open\r
-  // the protocol info to find the NIC handle.\r
-  //\r
+  IsDhcp4   = FALSE;\r
+   \r
   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
   if (NicHandle == NULL) {\r
     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
     if (NicHandle == NULL) {\r
-      return EFI_SUCCESS;\r
+      NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
+      if (NicHandle != NULL) {\r
+        IsDhcp4 = TRUE;  \r
+      } else {\r
+        return EFI_SUCCESS;\r
+      }\r
     }\r
   }\r
-\r
-  //\r
-  // Retrieve the IP4 service binding protocol\r
-  //\r
+   \r
   Status = gBS->OpenProtocol (\r
                   NicHandle,\r
                   &gEfiIp4ServiceBindingProtocolGuid,\r
@@ -666,9 +605,14 @@ Ip4DriverBindingStop (
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
+  \r
+  IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
 \r
-  IpSb   = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
-  if (NumberOfChildren != 0) {\r
+  if (IsDhcp4) {\r
+    Status = Ip4Config2DestroyDhcp4 (&IpSb->Ip4Config2Instance);\r
+    gBS->CloseEvent (IpSb->Ip4Config2Instance.Dhcp4Event);\r
+    IpSb->Ip4Config2Instance.Dhcp4Event = NULL;\r
+  } else if (NumberOfChildren != 0) {\r
     List = &IpSb->Children;\r
     Context.ServiceBinding    = ServiceBinding;\r
     Context.NumberOfChildren  = NumberOfChildren;\r
@@ -680,6 +624,7 @@ Ip4DriverBindingStop (
                NULL\r
                );\r
   } else if (IpSb->DefaultInterface->ArpHandle == ControllerHandle) {\r
+  \r
     //\r
     // The ARP protocol for the default interface is being uninstalled and all\r
     // its IP child handles should have been destroyed before. So, release the\r
@@ -704,10 +649,8 @@ Ip4DriverBindingStop (
     IpSb->DefaultRouteTable = RouteTable;\r
     Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
 \r
-    if (IpSb->Ip4Config != NULL && IpSb->State != IP4_SERVICE_DESTROY) {\r
-      IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
-    }\r
     IpSb->State = IP4_SERVICE_UNSTARTED;\r
+\r
   } else if (IsListEmpty (&IpSb->Children)) {\r
     State           = IpSb->State;\r
     IpSb->State     = IP4_SERVICE_DESTROY;\r
@@ -721,10 +664,13 @@ Ip4DriverBindingStop (
       goto ON_ERROR;\r
     }\r
 \r
-    gBS->UninstallProtocolInterface (\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
            NicHandle,\r
            &gEfiIp4ServiceBindingProtocolGuid,\r
-           ServiceBinding\r
+           ServiceBinding,\r
+           &gEfiIp4Config2ProtocolGuid,\r
+           &IpSb->Ip4Config2Instance.Ip4Config2,\r
+           NULL\r
            );\r
     \r
     if (gIp4ControllerNameTable != NULL) {\r
index 90fb83a..b93f2b7 100644 (file)
@@ -6,7 +6,7 @@
 #  subset of the Internet Control Message Protocol (ICMP) and may include support for\r
 #  the Internet Group Management Protocol (IGMP).\r
 #\r
-#  Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
+#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>\r
 #  This program and the accompanying materials\r
 #  are licensed and made available under the terms and conditions of the BSD License\r
 #  which accompanies this distribution. The full text of the license may be found at\r
   Ip4Route.c\r
   Ip4Icmp.h\r
   Ip4Input.c\r
+  Ip4Config2Impl.c\r
+  Ip4Config2Impl.h\r
+  Ip4Config2.vfr\r
+  Ip4DxeStrings.uni\r
+  Ip4NvData.h\r
+  Ip4Config2Nv.h\r
+  Ip4Config2Nv.c\r
 \r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
   MdeModulePkg/MdeModulePkg.dec\r
 \r
-\r
 [LibraryClasses]\r
   UefiLib\r
   BaseLib\r
   DebugLib\r
   NetLib\r
   DpcLib\r
+  HiiLib\r
+  PrintLib\r
+  DevicePathLib\r
+  UefiHiiServicesLib\r
 \r
 [Protocols]\r
   ## BY_START\r
   gEfiManagedNetworkServiceBindingProtocolGuid  ## TO_START\r
   gEfiManagedNetworkProtocolGuid                ## TO_START\r
   gEfiArpServiceBindingProtocolGuid             ## TO_START\r
-  gEfiIp4ConfigProtocolGuid                     ## TO_START\r
+  gEfiIp4Config2ProtocolGuid                    ## TO_START\r
   gEfiArpProtocolGuid                           ## TO_START\r
+  gEfiDhcp4ServiceBindingProtocolGuid           ## TO_START\r
+  gEfiDhcp4ProtocolGuid                         ## TO_START\r
   gEfiIpSec2ProtocolGuid                        ## SOMETIMES_CONSUMES\r
+  gEfiHiiConfigAccessProtocolGuid               ## BY_START\r
+  gEfiDevicePathProtocolGuid                    ## TO_START\r
+  \r
+[Guids]\r
+  ## SOMETIMES_CONSUMES ## GUID # HiiIsConfigHdrMatch   EFI_NIC_IP4_CONFIG_VARIABLE\r
+  ## SOMETIMES_PRODUCES ## GUID # HiiConstructConfigHdr EFI_NIC_IP4_CONFIG_VARIABLE\r
+  ## SOMETIMES_PRODUCES ## GUID # HiiGetBrowserData     EFI_NIC_IP4_CONFIG_VARIABLE\r
+  ## SOMETIMES_CONSUMES ## HII\r
+  gIp4Config2NvDataGuid\r
 \r
 [UserExtensions.TianoCore."ExtraFiles"]\r
   Ip4DxeExtra.uni\r
+\r
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4DxeStrings.uni b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4DxeStrings.uni
new file mode 100644 (file)
index 0000000..c940cf6
Binary files /dev/null and b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4DxeStrings.uni differ
index e5e2b98..b4b0864 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -158,9 +158,9 @@ Ip4ProcessIcmpRedirect (
   update call Ip4ProcessIcmpRedirect to update the IP instance's\r
   route cache, otherwise, deliver the packet to upper layer.\r
 \r
-  @param[in]  IpSb               The IP service that received the packet.\r
-  @param[in]  Head               The IP head of the ICMP error packet\r
-  @param[in]  Packet             The content of the ICMP error with IP head\r
+  @param[in]  IpSb               The IP4 service that received the packet.\r
+  @param[in]  Head               The IP4 head of the ICMP error packet\r
+  @param[in]  Packet             The content of the ICMP error with IP4 head\r
                                  removed.\r
 \r
   @retval EFI_SUCCESS            The ICMP error is processed successfully.\r
@@ -200,9 +200,9 @@ Ip4ProcessIcmpError (
 /**\r
   Replay an ICMP echo request.\r
 \r
-  @param[in]  IpSb               The IP service that receivd the packet\r
-  @param[in]  Head               The IP head of the ICMP error packet\r
-  @param[in]  Packet             The content of the ICMP error with IP head\r
+  @param[in]  IpSb               The IP4 service that receivd the packet\r
+  @param[in]  Head               The IP4 head of the ICMP error packet\r
+  @param[in]  Packet             The content of the ICMP error with IP4 head\r
                                  removed.\r
 \r
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource.\r
@@ -278,9 +278,9 @@ ON_EXIT:
   Process the ICMP query message. If it is an ICMP echo\r
   request, answer it. Otherwise deliver it to upper layer.\r
 \r
-  @param[in]  IpSb               The IP service that receivd the packet\r
-  @param[in]  Head               The IP head of the ICMP query packet\r
-  @param[in]  Packet             The content of the ICMP query with IP head\r
+  @param[in]  IpSb               The IP4 service that receivd the packet\r
+  @param[in]  Head               The IP4 head of the ICMP query packet\r
+  @param[in]  Packet             The content of the ICMP query with IP4 head\r
                                  removed.\r
 \r
   @retval EFI_INVALID_PARAMETER  The packet is invalid\r
@@ -317,9 +317,9 @@ Ip4ProcessIcmpQuery (
   then according to the message types, process it as query or\r
   error packet.\r
 \r
-  @param[in]  IpSb               The IP service that receivd the packet\r
-  @param[in]  Head               The IP head of the ICMP query packet\r
-  @param[in]  Packet             The content of the ICMP query with IP head\r
+  @param[in]  IpSb               The IP4 service that receivd the packet.\r
+  @param[in]  Head               The IP4 head of the ICMP query packet.\r
+  @param[in]  Packet             The content of the ICMP query with IP4 head\r
                                  removed.\r
 \r
   @retval EFI_INVALID_PARAMETER  The packet is malformated.\r
index 56488df..30199dc 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Header file for ICMP protocol.\r
   \r
-Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -84,9 +84,9 @@ extern EFI_IP4_ICMP_TYPE  mIp4SupportedIcmp[];
   then according to the message types, process it as query or\r
   error packet.\r
 \r
-  @param[in]  IpSb               The IP service that receivd the packet\r
-  @param[in]  Head               The IP head of the ICMP query packet\r
-  @param[in]  Packet             The content of the ICMP query with IP head\r
+  @param[in]  IpSb               The IP4 service that receivd the packet.\r
+  @param[in]  Head               The IP4 head of the ICMP query packet.\r
+  @param[in]  Packet             The content of the ICMP query with IP4 head\r
                                  removed.\r
 \r
   @retval EFI_INVALID_PARAMETER  The packet is malformated.\r
index a843150..669e041 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Implement IP4 pesudo interface.\r
   \r
-Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -423,12 +423,12 @@ Ip4CancelFrameArp (
   either queued on ARP queues or that have already been delivered to\r
   MNP and not yet recycled.\r
 \r
-  @param[in]  Interface         Interface to remove the frames from\r
+  @param[in]  Interface         Interface to remove the frames from.\r
   @param[in]  IoStatus          The transmit status returned to the frames'\r
-                                callback\r
+                                callback.\r
   @param[in]  FrameToCancel     Function to select the frame to cancel, NULL to\r
-                                select all\r
-  @param[in]  Context           Opaque parameters passed to FrameToCancel\r
+                                select all.\r
+  @param[in]  Context           Opaque parameters passed to FrameToCancel.\r
 \r
 **/\r
 VOID\r
@@ -476,10 +476,10 @@ Ip4CancelFrames (
   the interface is configured.\r
 \r
   @param[in]  Mnp               The shared MNP child of this IP4 service binding\r
-                                instance\r
+                                instance.\r
   @param[in]  Controller        The controller this IP4 service binding instance\r
                                 is installed. Most like the UNDI handle.\r
-  @param[in]  ImageHandle       This driver's image handle\r
+  @param[in]  ImageHandle       This driver's image handle.\r
 \r
   @return Point to the created IP4_INTERFACE, otherwise NULL.\r
 \r
@@ -542,9 +542,9 @@ Ip4CreateInterface (
   Set the interface's address, create and configure\r
   the ARP child if necessary.\r
 \r
-  @param  Interface         The interface to set the address\r
-  @param  IpAddr            The interface's IP address\r
-  @param  SubnetMask        The interface's netmask\r
+  @param  Interface         The interface to set the address.\r
+  @param  IpAddr            The interface's IP address.\r
+  @param  SubnetMask        The interface's netmask.\r
 \r
   @retval EFI_SUCCESS           The interface is configured with Ip/netmask pair,\r
                                 and a ARP is created for it.\r
@@ -566,8 +566,6 @@ Ip4SetAddress (
 \r
   NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
 \r
-  ASSERT (!Interface->Configured);\r
-\r
   //\r
   // Set the ip/netmask, then compute the subnet broadcast\r
   // and network broadcast for easy access. When computing\r
@@ -587,13 +585,35 @@ Ip4SetAddress (
   Netmask                   = gIp4AllMasks[MIN (Len, Type << 3)];\r
   Interface->NetBrdcast     = (IpAddr | ~Netmask);\r
 \r
+  //\r
+  // Do clean up for Arp child\r
+  //\r
+  if (Interface->ArpHandle != NULL) {\r
+    if (Interface->Arp != NULL) {\r
+      gBS->CloseProtocol (\r
+             Interface->ArpHandle,\r
+             &gEfiArpProtocolGuid,\r
+             Interface->Image,\r
+             Interface->Controller\r
+             );\r
+      \r
+      Interface->Arp = NULL;\r
+    }\r
+    \r
+    NetLibDestroyServiceChild (\r
+      Interface->Controller,\r
+      Interface->Image,\r
+      &gEfiArpServiceBindingProtocolGuid,\r
+      &Interface->ArpHandle\r
+      );\r
+\r
+    Interface->ArpHandle = NULL;\r
+  }\r
+\r
   //\r
   // If the address is NOT all zero, create then configure an ARP child.\r
   // Pay attention: DHCP configures its station address as 0.0.0.0/0\r
   //\r
-  Interface->Arp            = NULL;\r
-  Interface->ArpHandle      = NULL;\r
-\r
   if (IpAddr != IP4_ALLZERO_ADDRESS) {\r
     Status = NetLibCreateServiceChild (\r
                Interface->Controller,\r
@@ -603,7 +623,7 @@ Ip4SetAddress (
                );\r
 \r
     if (EFI_ERROR (Status)) {\r
-      return Status;;\r
+      return Status;\r
     }\r
 \r
     Status = gBS->OpenProtocol (\r
@@ -631,11 +651,11 @@ Ip4SetAddress (
 \r
     if (EFI_ERROR (Status)) {\r
       gBS->CloseProtocol (\r
-            Interface->ArpHandle,\r
-            &gEfiArpProtocolGuid,\r
-            Interface->Image,\r
-            Interface->Controller\r
-            );\r
+             Interface->ArpHandle,\r
+             &gEfiArpProtocolGuid,\r
+             Interface->Image,\r
+             Interface->Controller\r
+             );\r
 \r
       goto ON_ERROR;\r
     }\r
@@ -721,7 +741,7 @@ Ip4CancelReceive (
   Because the IpInstance is optional, the caller must remove\r
   IpInstance from the interface's instance list itself.\r
 \r
-  @param[in]  Interface         The interface used by the IpInstance\r
+  @param[in]  Interface         The interface used by the IpInstance.\r
   @param[in]  IpInstance        The Ip instance that free the interface. NULL if\r
                                 the Ip driver is releasing the default interface.\r
 \r
@@ -1197,14 +1217,14 @@ Ip4OnFrameReceived (
 /**\r
   Request to receive the packet from the interface.\r
 \r
-  @param[in]  Interface         The interface to receive the frames from\r
+  @param[in]  Interface         The interface to receive the frames from.\r
   @param[in]  IpInstance        The instance that requests the receive. NULL for\r
                                 the driver itself.\r
   @param[in]  CallBack          Function to call when receive finished.\r
-  @param[in]  Context           Opaque parameter to the callback\r
+  @param[in]  Context           Opaque parameter to the callback.\r
 \r
   @retval EFI_ALREADY_STARTED   There is already a pending receive request.\r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to receive\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to receive.\r
   @retval EFI_SUCCESS           The recieve request has been started.\r
   @retval other                 Other error occurs.\r
 \r
index 998fb25..6dada96 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Definition for IP4 pesudo interface structure.\r
   \r
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -192,10 +192,10 @@ struct _IP4_INTERFACE {
   the interface is configured.\r
 \r
   @param[in]  Mnp               The shared MNP child of this IP4 service binding\r
-                                instance\r
+                                instance.\r
   @param[in]  Controller        The controller this IP4 service binding instance\r
                                 is installed. Most like the UNDI handle.\r
-  @param[in]  ImageHandle       This driver's image handle\r
+  @param[in]  ImageHandle       This driver's image handle.\r
 \r
   @return Point to the created IP4_INTERFACE, otherwise NULL.\r
 \r
@@ -211,9 +211,9 @@ Ip4CreateInterface (
   Set the interface's address, create and configure\r
   the ARP child if necessary.\r
 \r
-  @param  Interface         The interface to set the address\r
-  @param  IpAddr            The interface's IP address\r
-  @param  SubnetMask        The interface's netmask\r
+  @param  Interface         The interface to set the address.\r
+  @param  IpAddr            The interface's IP address.\r
+  @param  SubnetMask        The interface's netmask.\r
 \r
   @retval EFI_SUCCESS           The interface is configured with Ip/netmask pair,\r
                                 and a ARP is created for it.\r
@@ -234,7 +234,7 @@ Ip4SetAddress (
   Because the IpInstance is optional, the caller must remove\r
   IpInstance from the interface's instance list itself.\r
 \r
-  @param[in]  Interface         The interface used by the IpInstance\r
+  @param[in]  Interface         The interface used by the IpInstance.\r
   @param[in]  IpInstance        The Ip instance that free the interface. NULL if\r
                                 the Ip driver is releasing the default interface.\r
 \r
@@ -284,12 +284,12 @@ Ip4SendFrame (
   either queued on ARP queues or that have already been delivered to\r
   MNP and not yet recycled.\r
 \r
-  @param[in]  Interface         Interface to remove the frames from\r
+  @param[in]  Interface         Interface to remove the frames from.\r
   @param[in]  IoStatus          The transmit status returned to the frames'\r
-                                callback\r
+                                callback.\r
   @param[in]  FrameToCancel     Function to select the frame to cancel, NULL to\r
-                                select all\r
-  @param[in]  Context           Opaque parameters passed to FrameToCancel\r
+                                select all.\r
+  @param[in]  Context           Opaque parameters passed to FrameToCancel.\r
 \r
 **/\r
 VOID\r
@@ -320,14 +320,14 @@ Ip4CancelReceive (
 /**\r
   Request to receive the packet from the interface.\r
 \r
-  @param[in]  Interface         The interface to receive the frames from\r
+  @param[in]  Interface         The interface to receive the frames from.\r
   @param[in]  IpInstance        The instance that requests the receive. NULL for\r
                                 the driver itself.\r
   @param[in]  CallBack          Function to call when receive finished.\r
-  @param[in]  Context           Opaque parameter to the callback\r
+  @param[in]  Context           Opaque parameter to the callback.\r
 \r
   @retval EFI_ALREADY_STARTED   There is already a pending receive request.\r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to receive\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to receive.\r
   @retval EFI_SUCCESS           The recieve request has been started.\r
   @retval other                 Other error occurs.\r
 \r
index c583d26..e0edc93 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   This file implements the RFC2236: IGMP v2.\r
   \r
-Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -85,8 +85,8 @@ ON_ERROR:
   Find the IGMP_GROUP structure which contains the status of multicast\r
   group Address in this IGMP control block\r
 \r
-  @param[in]  IgmpCtrl               The IGMP control block to search from\r
-  @param[in]  Address                The multicast address to search\r
+  @param[in]  IgmpCtrl               The IGMP control block to search from.\r
+  @param[in]  Address                The multicast address to search.\r
 \r
   @return NULL if the multicast address isn't in the IGMP control block. Otherwise\r
           the point to the IGMP_GROUP which contains the status of multicast group\r
@@ -119,8 +119,8 @@ Ip4FindGroup (
   same MAC address. Several IP4 multicast address may be mapped to\r
   the same MAC address.\r
 \r
-  @param[in]  IgmpCtrl               The IGMP control block to search in\r
-  @param[in]  Mac                    The MAC address to search\r
+  @param[in]  IgmpCtrl               The IGMP control block to search in.\r
+  @param[in]  Mac                    The MAC address to search.\r
 \r
   @return The number of the IP4 multicast group that mapped to the same\r
           multicast group Mac.\r
@@ -154,14 +154,14 @@ Ip4FindMac (
   Send an IGMP protocol message to the Dst, such as IGMP v1 membership report.\r
 \r
   @param[in]  IpSb               The IP4 service instance that requests the\r
-                                 transmission\r
-  @param[in]  Dst                The destinaton to send to\r
+                                 transmission.\r
+  @param[in]  Dst                The destinaton to send to.\r
   @param[in]  Type               The IGMP message type, such as IGMP v1 membership\r
-                                 report\r
+                                 report.\r
   @param[in]  Group              The group address in the IGMP message head.\r
 \r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory to build the message\r
-  @retval EFI_SUCCESS            The IGMP message is successfully send\r
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory to build the message.\r
+  @retval EFI_SUCCESS            The IGMP message is successfully send.\r
   @retval Others                 Failed to send the IGMP message.\r
 \r
 **/\r
@@ -229,10 +229,10 @@ Ip4SendIgmpMessage (
 \r
   @param[in]  IpSb               The IP4 service instance that requests the\r
                                  transmission.\r
-  @param[in]  Group              The group address to report\r
+  @param[in]  Group              The group address to report.\r
 \r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory to build the message\r
-  @retval EFI_SUCCESS            The IGMP report message is successfully send\r
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory to build the message.\r
+  @retval EFI_SUCCESS            The IGMP report message is successfully send.\r
   @retval Others                 Failed to send the report.\r
 \r
 **/\r
@@ -253,11 +253,11 @@ Ip4SendIgmpReport (
 /**\r
   Join the multicast group on behalf of this IP4 child\r
 \r
-  @param[in]  IpInstance         The IP4 child that wants to join the group\r
-  @param[in]  Address            The group to join\r
+  @param[in]  IpInstance         The IP4 child that wants to join the group.\r
+  @param[in]  Address            The group to join.\r
 \r
-  @retval EFI_SUCCESS            Successfully join the multicast group\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources\r
+  @retval EFI_SUCCESS            Successfully join the multicast group.\r
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.\r
   @retval Others                 Failed to join the multicast group.\r
 \r
 **/\r
@@ -334,10 +334,10 @@ ON_ERROR:
   Leave the IP4 multicast group on behalf of IpInstance.\r
 \r
   @param[in]  IpInstance         The IP4 child that wants to leave the group\r
-                                 address\r
-  @param[in]  Address            The group address to leave\r
+                                 address.\r
+  @param[in]  Address            The group address to leave.\r
 \r
-  @retval EFI_NOT_FOUND          The IP4 service instance isn't in the group\r
+  @retval EFI_NOT_FOUND          The IP4 service instance isn't in the group.\r
   @retval EFI_SUCCESS            Successfully leave the multicast group.\r
   @retval Others                 Failed to leave the multicast group.\r
 \r
@@ -403,9 +403,9 @@ Ip4LeaveGroup (
 /**\r
   Handle the received IGMP message for the IP4 service instance.\r
 \r
-  @param[in]  IpSb               The IP4 service instance that received the message\r
-  @param[in]  Head               The IP4 header of the received message\r
-  @param[in]  Packet             The IGMP message, without IP4 header\r
+  @param[in]  IpSb               The IP4 service instance that received the message.\r
+  @param[in]  Head               The IP4 header of the received message.\r
+  @param[in]  Packet             The IGMP message, without IP4 header.\r
 \r
   @retval EFI_INVALID_PARAMETER  The IGMP message is malformated.\r
   @retval EFI_SUCCESS            The IGMP message is successfully processed.\r
@@ -509,7 +509,7 @@ Ip4IgmpHandle (
   2. Decrease the report timer for each IGMP group in "delaying\r
      member" state.\r
 \r
-  @param[in]  IpSb                   The IP4 service instance that is ticking\r
+  @param[in]  IpSb                   The IP4 service instance that is ticking.\r
 \r
 **/\r
 VOID\r
@@ -553,9 +553,9 @@ Ip4IgmpTicking (
   assume the byte order of the both Source and Addr, the\r
   network byte order is used by the caller.\r
 \r
-  @param[in]  Source                 The array of group addresses to add to\r
-  @param[in]  Count                  The number of group addresses in the Source\r
-  @param[in]  Addr                   The IP4 multicast address to add\r
+  @param[in]  Source                 The array of group addresses to add to.\r
+  @param[in]  Count                  The number of group addresses in the Source.\r
+  @param[in]  Addr                   The IP4 multicast address to add.\r
 \r
   @return NULL if failed to allocate memory for the new groups,\r
           otherwise the new combined group addresses.\r
@@ -589,9 +589,9 @@ Ip4CombineGroups (
   both Groups and Addr, the network byte order is used by\r
   the caller.\r
 \r
-  @param  Groups            The array of group addresses to remove from\r
-  @param  Count             The number of group addresses in the Groups\r
-  @param  Addr              The IP4 multicast address to remove\r
+  @param  Groups            The array of group addresses to remove from.\r
+  @param  Count             The number of group addresses in the Groups.\r
+  @param  Addr              The IP4 multicast address to remove.\r
 \r
   @return The nubmer of group addresses in the Groups after remove.\r
           It is Count if the Addr isn't in the Groups.\r
index a11a915..756c697 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2005 - 2009, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -78,11 +78,11 @@ Ip4InitIgmp (
 /**\r
   Join the multicast group on behalf of this IP4 child\r
 \r
-  @param[in]  IpInstance         The IP4 child that wants to join the group\r
-  @param[in]  Address            The group to join\r
+  @param[in]  IpInstance         The IP4 child that wants to join the group.\r
+  @param[in]  Address            The group to join.\r
 \r
-  @retval EFI_SUCCESS            Successfully join the multicast group\r
-  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources\r
+  @retval EFI_SUCCESS            Successfully join the multicast group.\r
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.\r
   @retval Others                 Failed to join the multicast group.\r
 \r
 **/\r
@@ -96,10 +96,10 @@ Ip4JoinGroup (
   Leave the IP4 multicast group on behalf of IpInstance.\r
 \r
   @param[in]  IpInstance         The IP4 child that wants to leave the group\r
-                                 address\r
-  @param[in]  Address            The group address to leave\r
+                                 address.\r
+  @param[in]  Address            The group address to leave.\r
 \r
-  @retval EFI_NOT_FOUND          The IP4 service instance isn't in the group\r
+  @retval EFI_NOT_FOUND          The IP4 service instance isn't in the group.\r
   @retval EFI_SUCCESS            Successfully leave the multicast group.\r
   @retval Others                 Failed to leave the multicast group.\r
 \r
@@ -113,9 +113,9 @@ Ip4LeaveGroup (
 /**\r
   Handle the received IGMP message for the IP4 service instance.\r
 \r
-  @param[in]  IpSb               The IP4 service instance that received the message\r
-  @param[in]  Head               The IP4 header of the received message\r
-  @param[in]  Packet             The IGMP message, without IP4 header\r
+  @param[in]  IpSb               The IP4 service instance that received the message.\r
+  @param[in]  Head               The IP4 header of the received message.\r
+  @param[in]  Packet             The IGMP message, without IP4 header.\r
 \r
   @retval EFI_INVALID_PARAMETER  The IGMP message is malformated.\r
   @retval EFI_SUCCESS            The IGMP message is successfully processed.\r
@@ -136,7 +136,7 @@ Ip4IgmpHandle (
   2. Decrease the report timer for each IGMP group in "delaying\r
      member" state.\r
 \r
-  @param[in]  IpSb                   The IP4 service instance that is ticking\r
+  @param[in]  IpSb                   The IP4 service instance that is ticking.\r
 \r
 **/\r
 VOID\r
@@ -151,9 +151,9 @@ Ip4IgmpTicking (
   assume the byte order of the both Source and Addr, the\r
   network byte order is used by the caller.\r
 \r
-  @param[in]  Source                 The array of group addresses to add to\r
-  @param[in]  Count                  The number of group addresses in the Source\r
-  @param[in]  Addr                   The IP4 multicast address to add\r
+  @param[in]  Source                 The array of group addresses to add to.\r
+  @param[in]  Count                  The number of group addresses in the Source.\r
+  @param[in]  Addr                   The IP4 multicast address to add.\r
 \r
   @return NULL if failed to allocate memory for the new groups,\r
           otherwise the new combined group addresses.\r
@@ -172,9 +172,9 @@ Ip4CombineGroups (
   both Groups and Addr, the network byte order is used by\r
   the caller.\r
 \r
-  @param  Groups            The array of group addresses to remove from\r
-  @param  Count             The number of group addresses in the Groups\r
-  @param  Addr              The IP4 multicast address to remove\r
+  @param  Groups            The array of group addresses to remove from.\r
+  @param  Count             The number of group addresses in the Groups.\r
+  @param  Addr              The IP4 multicast address to remove.\r
 \r
   @return The nubmer of group addresses in the Groups after remove.\r
           It is Count if the Addr isn't in the Groups.\r
@@ -191,8 +191,8 @@ Ip4RemoveGroupAddr (
   Find the IGMP_GROUP structure which contains the status of multicast\r
   group Address in this IGMP control block\r
 \r
-  @param[in]  IgmpCtrl               The IGMP control block to search from\r
-  @param[in]  Address                The multicast address to search\r
+  @param[in]  IgmpCtrl               The IGMP control block to search from.\r
+  @param[in]  Address                The multicast address to search.\r
 \r
   @return NULL if the multicast address isn't in the IGMP control block. Otherwise\r
           the point to the IGMP_GROUP which contains the status of multicast group\r
index 06a56e1..b0f597f 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -530,303 +530,6 @@ Ip4ServiceConfigMnp (
 }\r
 \r
 \r
-/**\r
-  The event handle for IP4 auto configuration. If IP is asked\r
-  to reconfigure the default address. The original default\r
-  interface and route table are removed as the default. If there\r
-  is active IP children using the default address, the interface\r
-  will remain valid until all the children have freed their\r
-  references. If IP is signalled when auto configuration is done,\r
-  it will configure the default interface and default route table\r
-  with the configuration information retrieved by IP4_CONFIGURE.\r
-\r
-  @param[in]  Context                The IP4 service binding instance.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-Ip4AutoConfigCallBackDpc (\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  EFI_IP4_CONFIG_PROTOCOL   *Ip4Config;\r
-  EFI_IP4_IPCONFIG_DATA     *Data;\r
-  EFI_IP4_ROUTE_TABLE       *RouteEntry;\r
-  IP4_SERVICE               *IpSb;\r
-  IP4_ROUTE_TABLE           *RouteTable;\r
-  IP4_INTERFACE             *IpIf;\r
-  EFI_STATUS                Status;\r
-  UINTN                     Len;\r
-  UINT32                    Index;\r
-  IP4_ADDR                  StationAddress;\r
-  IP4_ADDR                  SubnetMask;\r
-  IP4_ADDR                  SubnetAddress;\r
-  IP4_ADDR                  GatewayAddress;\r
-  IP4_PROTOCOL              *Ip4Instance;\r
-  EFI_ARP_PROTOCOL          *Arp;\r
-  LIST_ENTRY                *Entry;\r
-\r
-  IpSb      = (IP4_SERVICE *) Context;\r
-  NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
-\r
-  Ip4Config = IpSb->Ip4Config;\r
-\r
-  //\r
-  // IP is asked to do the reconfiguration. If the default interface\r
-  // has been configured, release the default interface and route\r
-  // table, then create a new one. If there are some IP children\r
-  // using it, the interface won't be physically freed until all the\r
-  // children have released their reference to it. Also remember to\r
-  // restart the receive on the default address. IP4 driver only receive\r
-  // frames on the default address, and when the default interface is\r
-  // freed, Ip4AcceptFrame won't be informed.\r
-  //\r
-  if (IpSb->ActiveEvent == IpSb->ReconfigEvent) {\r
-\r
-    if (IpSb->DefaultInterface->Configured) {\r
-      IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
-\r
-      if (IpIf == NULL) {\r
-        return;\r
-      }\r
-\r
-      RouteTable = Ip4CreateRouteTable ();\r
-\r
-      if (RouteTable == NULL) {\r
-        Ip4FreeInterface (IpIf, NULL);\r
-        return;\r
-      }\r
-\r
-      Ip4CancelReceive (IpSb->DefaultInterface);\r
-      Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
-      Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
-\r
-      IpSb->DefaultInterface  = IpIf;\r
-      InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
-\r
-      IpSb->DefaultRouteTable = RouteTable;\r
-      Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
-    }\r
-\r
-    Ip4Config->Stop (Ip4Config);\r
-    Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent);\r
-    return ;\r
-  }\r
-\r
-  //\r
-  // Get the configure data in two steps: get the length then the data.\r
-  //\r
-  Len = 0;\r
-\r
-  if (Ip4Config->GetData (Ip4Config, &Len, NULL) != EFI_BUFFER_TOO_SMALL) {\r
-    return ;\r
-  }\r
-\r
-  Data = AllocatePool (Len);\r
-\r
-  if (Data == NULL) {\r
-    return ;\r
-  }\r
-\r
-  Status = Ip4Config->GetData (Ip4Config, &Len, Data);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  IpIf = IpSb->DefaultInterface;\r
-\r
-  //\r
-  // If the default address has been configured don't change it.\r
-  // This is unlikely to happen if EFI_IP4_CONFIG protocol has\r
-  // informed us to reconfigure each time it wants to change the\r
-  // configuration parameters.\r
-  //\r
-  if (IpIf->Configured) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Set the default interface's address, then add a directed\r
-  // route for it, that is, the route whose nexthop is zero.\r
-  //\r
-  StationAddress = EFI_NTOHL (Data->StationAddress);\r
-  SubnetMask = EFI_NTOHL (Data->SubnetMask);\r
-  Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask);\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\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
-        goto ON_EXIT;\r
-      }\r
-    }\r
-  }\r
-\r
-  Ip4AddRoute (\r
-    IpSb->DefaultRouteTable,\r
-    StationAddress,\r
-    SubnetMask,\r
-    IP4_ALLZERO_ADDRESS\r
-    );\r
-\r
-  //\r
-  // Add routes returned by EFI_IP4_CONFIG protocol.\r
-  //\r
-  for (Index = 0; Index < Data->RouteTableSize; Index++) {\r
-    RouteEntry = &Data->RouteTable[Index];\r
-\r
-    SubnetAddress = EFI_NTOHL (RouteEntry->SubnetAddress);\r
-    SubnetMask = EFI_NTOHL (RouteEntry->SubnetMask);\r
-    GatewayAddress = EFI_NTOHL (RouteEntry->GatewayAddress);\r
-    Ip4AddRoute (IpSb->DefaultRouteTable, SubnetAddress, SubnetMask, GatewayAddress);\r
-  }\r
-\r
-  IpSb->State = IP4_SERVICE_CONFIGED;\r
-\r
-ON_EXIT:\r
-  FreePool (Data);\r
-}\r
-\r
-/**\r
-  Request Ip4AutoConfigCallBackDpc 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
-Ip4AutoConfigCallBack (\r
-  IN EFI_EVENT              Event,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  IP4_SERVICE  *IpSb;\r
-\r
-  IpSb              = (IP4_SERVICE *) Context;\r
-  IpSb->ActiveEvent = Event;\r
-\r
-  //\r
-  // Request Ip4AutoConfigCallBackDpc as a DPC at TPL_CALLBACK\r
-  //\r
-  QueueDpc (TPL_CALLBACK, Ip4AutoConfigCallBackDpc, Context);\r
-}\r
-\r
-\r
-/**\r
-  Start the auto configuration for this IP service instance.\r
-  It will locates the EFI_IP4_CONFIG_PROTOCOL, then start the\r
-  auto configuration.\r
-\r
-  @param[in]  IpSb               The IP4 service instance to configure\r
-\r
-  @retval EFI_SUCCESS            The auto configuration is successfull started\r
-  @retval Others                 Failed to start auto configuration.\r
-\r
-**/\r
-EFI_STATUS\r
-Ip4StartAutoConfig (\r
-  IN IP4_SERVICE            *IpSb\r
-  )\r
-{\r
-  EFI_IP4_CONFIG_PROTOCOL   *Ip4Config;\r
-  EFI_STATUS                Status;\r
-\r
-  if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // Create the DoneEvent and ReconfigEvent to call EFI_IP4_CONFIG\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  Ip4AutoConfigCallBack,\r
-                  IpSb,\r
-                  &IpSb->DoneEvent\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  Ip4AutoConfigCallBack,\r
-                  IpSb,\r
-                  &IpSb->ReconfigEvent\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    goto CLOSE_DONE_EVENT;\r
-  }\r
-\r
-  //\r
-  // Open the EFI_IP4_CONFIG protocol then start auto configure\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  IpSb->Controller,\r
-                  &gEfiIp4ConfigProtocolGuid,\r
-                  (VOID **) &Ip4Config,\r
-                  IpSb->Image,\r
-                  IpSb->Controller,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    Status = EFI_UNSUPPORTED;\r
-    goto CLOSE_RECONFIG_EVENT;\r
-  }\r
-\r
-  Status = Ip4Config->Start (Ip4Config, IpSb->DoneEvent, IpSb->ReconfigEvent);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    gBS->CloseProtocol (\r
-           IpSb->Controller,\r
-           &gEfiIp4ConfigProtocolGuid,\r
-           IpSb->Image,\r
-           IpSb->Controller\r
-           );\r
-\r
-    goto CLOSE_RECONFIG_EVENT;\r
-  }\r
-\r
-  IpSb->Ip4Config = Ip4Config;\r
-  IpSb->State     = IP4_SERVICE_STARTED;\r
-  return Status;\r
-\r
-CLOSE_RECONFIG_EVENT:\r
-  gBS->CloseEvent (IpSb->ReconfigEvent);\r
-  IpSb->ReconfigEvent = NULL;\r
-\r
-CLOSE_DONE_EVENT:\r
-  gBS->CloseEvent (IpSb->DoneEvent);\r
-  IpSb->DoneEvent = NULL;\r
-\r
-  return Status;\r
-}\r
-\r
-\r
 /**\r
   Intiialize the IP4_PROTOCOL structure to the unconfigured states.\r
 \r
@@ -860,6 +563,7 @@ Ip4InitProtocol (
 }\r
 \r
 \r
+\r
 /**\r
   Configure the IP4 child. If the child is already configured,\r
   change the configuration parameter. Otherwise configure it\r
@@ -974,11 +678,8 @@ Ip4ConfigProtocol (
     // been started, start it.\r
     //\r
     if (IpSb->State == IP4_SERVICE_UNSTARTED) {\r
-      Status = Ip4StartAutoConfig (IpSb);\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        goto ON_ERROR;\r
-      }\r
+      Status = EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
     }\r
 \r
     IpIf = IpSb->DefaultInterface;\r
@@ -1038,8 +739,8 @@ ON_ERROR:
 \r
   @param[in]  IpInstance         The IP4 child to clean up.\r
 \r
-  @retval EFI_SUCCESS            The IP4 child is cleaned up\r
-  @retval EFI_DEVICE_ERROR       Some resources failed to be released\r
+  @retval EFI_SUCCESS            The IP4 child is cleaned up.\r
+  @retval EFI_DEVICE_ERROR       Some resources failed to be released.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -1112,11 +813,11 @@ Ip4CleanProtocol (
   address. Only continuous netmasks are supported. and check\r
   that StationAddress is a unicast address on the newtwork.\r
 \r
-  @param[in]  Ip                 The IP address to validate\r
-  @param[in]  Netmask            The netmaks of the IP\r
+  @param[in]  Ip                 The IP address to validate.\r
+  @param[in]  Netmask            The netmaks of the IP.\r
 \r
-  @retval TRUE                   The Ip/Netmask pair is valid\r
-  @retval FALSE                  The Ip/Netmask pair is invalid\r
+  @retval TRUE                   The Ip/Netmask pair is valid.\r
+  @retval FALSE                  The Ip/Netmask pair is invalid.\r
 \r
 **/\r
 BOOLEAN\r
@@ -1322,12 +1023,12 @@ ON_EXIT:
   should make sure that the parameters is valid.\r
 \r
   @param[in]  IpInstance             The IP4 child to change the setting.\r
-  @param[in]  JoinFlag               TRUE to join the group, otherwise leave it\r
-  @param[in]  GroupAddress           The target group address\r
+  @param[in]  JoinFlag               TRUE to join the group, otherwise leave it.\r
+  @param[in]  GroupAddress           The target group address.\r
 \r
-  @retval EFI_ALREADY_STARTED    Want to join the group, but already a member of it\r
+  @retval EFI_ALREADY_STARTED    Want to join the group, but already a member of it.\r
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate some resources.\r
-  @retval EFI_DEVICE_ERROR       Failed to set the group configuraton\r
+  @retval EFI_DEVICE_ERROR       Failed to set the group configuraton.\r
   @retval EFI_SUCCESS            Successfully updated the group setting.\r
   @retval EFI_NOT_FOUND          Try to leave the group which it isn't a member.\r
 \r
@@ -1624,10 +1325,10 @@ ON_EXIT:
 \r
   @param[in]  Map                    The container of either user's transmit or receive\r
                                      token.\r
-  @param[in]  Item                   Current item to check against\r
+  @param[in]  Item                   Current item to check against.\r
   @param[in]  Context                The Token to check againist.\r
 \r
-  @retval EFI_ACCESS_DENIED      The token or event has already been enqueued in IP\r
+  @retval EFI_ACCESS_DENIED      The token or event has already been enqueued in IP.\r
   @retval EFI_SUCCESS            The current item isn't the same token/event as the\r
                                  context.\r
 \r
@@ -1800,7 +1501,7 @@ Ip4TxTokenValid (
   are bound together. Check the comments in Ip4Output for information\r
   about IP fragmentation.\r
 \r
-  @param[in]  Context                The token's wrap\r
+  @param[in]  Context                The token's wrap.\r
 \r
 **/\r
 VOID\r
@@ -1848,9 +1549,9 @@ Ip4FreeTxToken (
   The callback function to Ip4Output to update the transmit status.\r
 \r
   @param  Ip4Instance            The Ip4Instance that request the transmit.\r
-  @param  Packet                 The user's transmit request\r
-  @param  IoStatus               The result of the transmission\r
-  @param  Flag                   Not used during transmission\r
+  @param  Packet                 The user's transmit request.\r
+  @param  IoStatus               The result of the transmission.\r
+  @param  Flag                   Not used during transmission.\r
   @param  Context                The token's wrap.\r
 \r
 **/\r
@@ -1911,7 +1612,7 @@ Ip4OnPacketSent (
   @retval  EFI_BAD_BUFFER_SIZE   The length of the IPv4 header + option length + total data length is\r
                                  greater than MTU (or greater than the maximum packet size if\r
                                  Token.Packet.TxData.OverrideData.\r
-                                 DoNotFragment is TRUE.)\r
+                                 DoNotFragment is TRUE).\r
 \r
 **/\r
 EFI_STATUS\r
@@ -2262,9 +1963,9 @@ ON_EXIT:
   Because Ip4CancelPacket and other functions are all called in\r
   line, so, after Ip4CancelPacket returns, the Item has been freed.\r
 \r
-  @param[in]  Map                    The IP4 child's transmit queue\r
-  @param[in]  Item                   The current transmitted packet to test.\r
-  @param[in]  Context                The user's token to cancel.\r
+  @param[in]  Map                The IP4 child's transmit queue.\r
+  @param[in]  Item               The current transmitted packet to test.\r
+  @param[in]  Context            The user's token to cancel.\r
 \r
   @retval EFI_SUCCESS            Continue to check the next Item.\r
   @retval EFI_ABORTED            The user's Token (Token != NULL) is cancelled.\r
@@ -2316,9 +2017,9 @@ Ip4CancelTxTokens (
   Cancel the receive request. This is quiet simple, because\r
   it is only enqueued in our local receive map.\r
 \r
-  @param[in]  Map                    The IP4 child's receive queue\r
-  @param[in]  Item                   Current receive request to cancel.\r
-  @param[in]  Context                The user's token to cancel\r
+  @param[in]  Map                The IP4 child's receive queue.\r
+  @param[in]  Item               Current receive request to cancel.\r
+  @param[in]  Context            The user's token to cancel.\r
 \r
   @retval EFI_SUCCESS            Continue to check the next receive request on the\r
                                  queue.\r
@@ -2361,13 +2062,13 @@ Ip4CancelRxTokens (
 /**\r
   Cancel the user's receive/transmit request.\r
 \r
-  @param[in]  IpInstance         The IP4 child\r
+  @param[in]  IpInstance         The IP4 child.\r
   @param[in]  Token              The token to cancel. If NULL, all token will be\r
                                  cancelled.\r
 \r
-  @retval EFI_SUCCESS            The token is cancelled\r
+  @retval EFI_SUCCESS            The token is cancelled.\r
   @retval EFI_NOT_FOUND          The token isn't found on either the\r
-                                 transmit/receive queue\r
+                                 transmit/receive queue.\r
   @retval EFI_DEVICE_ERROR       Not all token is cancelled when Token is NULL.\r
 \r
 **/\r
@@ -2563,10 +2264,10 @@ EfiIp4Poll (
   packets.\r
 \r
   @param[in]  Map                    The IP4 child's transmit map.\r
-  @param[in]  Item                   Current transmitted packet\r
+  @param[in]  Item                   Current transmitted packet.\r
   @param[in]  Context                Not used.\r
 \r
-  @retval EFI_SUCCESS            Always returns EFI_SUCCESS\r
+  @retval EFI_SUCCESS            Always returns EFI_SUCCESS.\r
 \r
 **/\r
 EFI_STATUS\r
index c49e013..84dfa80 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Ip4 internal functions and type defintions.\r
   \r
-Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -19,9 +19,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include <Protocol/IpSec.h>\r
 #include <Protocol/Ip4.h>\r
-#include <Protocol/Ip4Config.h>\r
+#include <Protocol/Ip4Config2.h>\r
 #include <Protocol/Arp.h>\r
 #include <Protocol/ManagedNetwork.h>\r
+#include <Protocol/Dhcp4.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
 \r
 #include <Library/DebugLib.h>\r
 #include <Library/UefiRuntimeServicesTableLib.h>\r
@@ -34,6 +37,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Library/MemoryAllocationLib.h>\r
 #include <Library/DpcLib.h>\r
 #include <Library/PrintLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/UefiHiiServicesLib.h>\r
 \r
 #include "Ip4Common.h"\r
 #include "Ip4Driver.h"\r
@@ -44,6 +50,9 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "Ip4Route.h"\r
 #include "Ip4Input.h"\r
 #include "Ip4Output.h"\r
+#include "Ip4Config2Impl.h"\r
+#include "Ip4Config2Nv.h"\r
+#include "Ip4NvData.h"\r
 \r
 #define IP4_PROTOCOL_SIGNATURE  SIGNATURE_32 ('I', 'P', '4', 'P')\r
 #define IP4_SERVICE_SIGNATURE   SIGNATURE_32 ('I', 'P', '4', 'S')\r
@@ -195,12 +204,11 @@ struct _IP4_SERVICE {
   EFI_EVENT                       Timer;\r
 \r
   //\r
-  // Auto configure staff\r
+  // IPv4 Configuration II Protocol instance\r
   //\r
-  EFI_IP4_CONFIG_PROTOCOL         *Ip4Config;\r
-  EFI_EVENT                       DoneEvent;\r
-  EFI_EVENT                       ReconfigEvent;\r
-  EFI_EVENT                       ActiveEvent;\r
+  IP4_CONFIG2_INSTANCE            Ip4Config2Instance;\r
+\r
+  CHAR16                          *MacString;\r
 \r
   UINT32                          MaxPacketSize;\r
   UINT32                          OldMaxPacketSize; ///< The MTU before IPsec enable.\r
@@ -212,6 +220,10 @@ struct _IP4_SERVICE {
 #define IP4_SERVICE_FROM_PROTOCOL(Sb)   \\r
           CR ((Sb), IP4_SERVICE, ServiceBinding, IP4_SERVICE_SIGNATURE)\r
 \r
+#define IP4_SERVICE_FROM_CONFIG2_INSTANCE(This) \\r
+  CR (This, IP4_SERVICE, Ip4Config2Instance, IP4_SERVICE_SIGNATURE)\r
+\r
+\r
 #define IP4_NO_MAPPING(IpInstance) (!(IpInstance)->Interface->Configured)\r
 \r
 extern EFI_IP4_PROTOCOL mEfiIp4ProtocolTemplete;\r
@@ -258,8 +270,8 @@ Ip4InitProtocol (
 \r
   @param[in]  IpInstance         The IP4 child to clean up.\r
 \r
-  @retval EFI_SUCCESS            The IP4 child is cleaned up\r
-  @retval EFI_DEVICE_ERROR       Some resources failed to be released\r
+  @retval EFI_SUCCESS            The IP4 child is cleaned up.\r
+  @retval EFI_DEVICE_ERROR       Some resources failed to be released.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -270,13 +282,13 @@ Ip4CleanProtocol (
 /**\r
   Cancel the user's receive/transmit request.\r
 \r
-  @param[in]  IpInstance         The IP4 child\r
+  @param[in]  IpInstance         The IP4 child.\r
   @param[in]  Token              The token to cancel. If NULL, all token will be\r
                                  cancelled.\r
 \r
-  @retval EFI_SUCCESS            The token is cancelled\r
+  @retval EFI_SUCCESS            The token is cancelled.\r
   @retval EFI_NOT_FOUND          The token isn't found on either the\r
-                                 transmit/receive queue\r
+                                 transmit/receive queue.\r
   @retval EFI_DEVICE_ERROR       Not all token is cancelled when Token is NULL.\r
 \r
 **/\r
@@ -333,10 +345,10 @@ Ip4TimerTicking (
   packets.\r
 \r
   @param[in]  Map                    The IP4 child's transmit map.\r
-  @param[in]  Item                   Current transmitted packet\r
+  @param[in]  Item                   Current transmitted packet.\r
   @param[in]  Context                Not used.\r
 \r
-  @retval EFI_SUCCESS            Always returns EFI_SUCCESS\r
+  @retval EFI_SUCCESS            Always returns EFI_SUCCESS.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -365,7 +377,7 @@ Ip4SentPacketTicking (
   are bound together. Check the comments in Ip4Output for information\r
   about IP fragmentation.\r
 \r
-  @param[in]  Context                The token's wrap\r
+  @param[in]  Context                The token's wrap.\r
 \r
 **/\r
 VOID\r
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4NvData.h b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4NvData.h
new file mode 100644 (file)
index 0000000..a02b331
--- /dev/null
@@ -0,0 +1,51 @@
+/** @file\r
+  Routines used to operate the Ip4Dxe.\r
+\r
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at<BR>\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _IP4_NV_DATA_H_\r
+#define _IP4_NV_DATA_H_\r
+\r
+#include <Guid/Ip4Config2Hii.h>\r
+\r
+#define FORMID_MAIN_FORM    1\r
+#define FORMID_DEVICE_FORM  2\r
+\r
+#define KEY_ENABLE                0x100\r
+#define KEY_DHCP_ENABLE           0x101\r
+#define KEY_LOCAL_IP              0x102\r
+#define KEY_SUBNET_MASK           0x103\r
+#define KEY_GATE_WAY              0x104\r
+#define KEY_DNS                   0x105\r
+#define KEY_SAVE_CHANGES          0x106\r
+\r
+#define IP_MIN_SIZE               7\r
+#define IP_MAX_SIZE               15\r
+#define IP4_STR_MAX_SIZE          16\r
+#define ADDRESS_STR_MAX_SIZE      255\r
+#define MAX_IP4_CONFIG_DNS        16\r
+\r
+///\r
+/// IP4_CONFIG2_IFR_NVDATA contains the IP4 configure\r
+/// parameters for that NIC.\r
+///\r
+typedef struct {\r
+  UINT8           Configure;                         ///< NIC configure status\r
+  UINT8           DhcpEnable;                        ///< Static or DHCP\r
+  CHAR16          StationAddress[IP4_STR_MAX_SIZE];  ///< IP addresses\r
+  CHAR16          SubnetMask[IP4_STR_MAX_SIZE];      ///< Subnet address\r
+  CHAR16          GatewayAddress[IP4_STR_MAX_SIZE];  ///< Gateway address\r
+  CHAR16          DnsAddress[ADDRESS_STR_MAX_SIZE];  ///< DNS server address\r
+} IP4_CONFIG2_IFR_NVDATA;\r
+\r
+#endif\r
+\r
index 370eaa6..68d1f09 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Transmit the IP4 packet.\r
   \r
-Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -312,6 +312,13 @@ Ip4Output (
       CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);\r
     } else {\r
       CacheEntry = Ip4Route (IpInstance->RouteTable, Head->Dst, Head->Src);\r
+      //\r
+      // If failed to route the packet by using the instance's route table,\r
+      // try to use the default route table.\r
+      //\r
+      if (CacheEntry == NULL) {\r
+        CacheEntry = Ip4Route (IpSb->DefaultRouteTable, Head->Dst, Head->Src);\r
+      }\r
     }\r
 \r
     if (CacheEntry == NULL) {\r