Import Ip4Config module
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 23 Jul 2007 09:18:27 +0000 (09:18 +0000)
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 23 Jul 2007 09:18:27 +0000 (09:18 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3406 6f19259b-4bc3-4df7-8a09-765794883524

MdeModulePkg/Universal/Network/Ip4ConfigDxe/ComponentName.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.msa [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.c [new file with mode: 0644]
MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.h [new file with mode: 0644]

diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/ComponentName.c b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/ComponentName.c
new file mode 100644 (file)
index 0000000..1be21a1
--- /dev/null
@@ -0,0 +1,157 @@
+/** @file\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. 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
+Module Name:\r
+\r
+  ComponentName.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+\r
+#include "Ip4Config.h"\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4ConfigComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4ConfigComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL                     *This,\r
+  IN  EFI_HANDLE                                      ControllerHandle,\r
+  IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,\r
+  IN  CHAR8                                           *Language,\r
+  OUT CHAR16                                          **ControllerName\r
+  );\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+EFI_COMPONENT_NAME_PROTOCOL     gIp4ConfigComponentName = {\r
+  Ip4ConfigComponentNameGetDriverName,\r
+  Ip4ConfigComponentNameGetControllerName,\r
+  "eng"\r
+};\r
+\r
+STATIC\r
+EFI_UNICODE_STRING_TABLE mIp4ConfigDriverNameTable[] = {\r
+  {"eng", L"IP4 CONFIG Network Service Driver"},\r
+  {NULL, NULL}\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4ConfigComponentNameGetDriverName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **DriverName\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves a Unicode string that is the user readable name of the EFI Driver.\r
+\r
+  Arguments:\r
+    This       - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+    Language   - A pointer to a three character ISO 639-2 language identifier.\r
+                 This is the language of the driver name that that the caller\r
+                 is requesting, and it must match one of the languages specified\r
+                 in SupportedLanguages.  The number of languages supported by a\r
+                 driver is up to the driver writer.\r
+    DriverName - A pointer to the Unicode string to return.  This Unicode string\r
+                 is the name of the driver specified by This in the language\r
+                 specified by Language.\r
+\r
+  Returns:\r
+    EFI_SUCCES            - The Unicode string for the Driver specified by This\r
+                            and the language specified by Language was returned\r
+                            in DriverName.\r
+    EFI_INVALID_PARAMETER - Language is NULL.\r
+    EFI_INVALID_PARAMETER - DriverName is NULL.\r
+    EFI_UNSUPPORTED       - The driver specified by This does not support the\r
+                            language specified by Language.\r
+\r
+--*/\r
+{\r
+  return LookupUnicodeString (\r
+           Language,\r
+           gIp4ConfigComponentName.SupportedLanguages,\r
+           mIp4ConfigDriverNameTable,\r
+           DriverName\r
+           );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4ConfigComponentNameGetControllerName (\r
+  IN  EFI_COMPONENT_NAME_PROTOCOL  *This,\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  EFI_HANDLE                   ChildHandle        OPTIONAL,\r
+  IN  CHAR8                        *Language,\r
+  OUT CHAR16                       **ControllerName\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Retrieves a Unicode string that is the user readable name of the controller\r
+    that is being managed by an EFI Driver.\r
+\r
+  Arguments:\r
+    This             - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+    ControllerHandle - The handle of a controller that the driver specified by\r
+                       This is managing.  This handle specifies the controller\r
+                       whose name is to be returned.\r
+    ChildHandle      - The handle of the child controller to retrieve the name\r
+                       of.  This is an optional parameter that may be NULL.  It\r
+                       will be NULL for device drivers.  It will also be NULL\r
+                       for a bus drivers that wish to retrieve the name of the\r
+                       bus controller.  It will not be NULL for a bus driver\r
+                       that wishes to retrieve the name of a child controller.\r
+    Language         - A pointer to a three character ISO 639-2 language\r
+                       identifier.  This is the language of the controller name\r
+                       that that the caller is requesting, and it must match one\r
+                       of the languages specified in SupportedLanguages.  The\r
+                       number of languages supported by a driver is up to the\r
+                       driver writer.\r
+    ControllerName   - A pointer to the Unicode string to return.  This Unicode\r
+                       string is the name of the controller specified by\r
+                       ControllerHandle and ChildHandle in the language specified\r
+                       by Language from the point of view of the driver specified\r
+                       by This.\r
+\r
+  Returns:\r
+    EFI_SUCCESS           - The Unicode string for the user readable name in the\r
+                            language specified by Language for the driver\r
+                            specified by This was returned in DriverName.\r
+    EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.\r
+    EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.\r
+    EFI_INVALID_PARAMETER - Language is NULL.\r
+    EFI_INVALID_PARAMETER - ControllerName is NULL.\r
+    EFI_UNSUPPORTED       - The driver specified by This is not currently managing\r
+                            the controller specified by ControllerHandle and\r
+                            ChildHandle.\r
+    EFI_UNSUPPORTED       - The driver specified by This does not support the\r
+                            language specified by Language.\r
+\r
+--*/\r
+{\r
+  return EFI_UNSUPPORTED;\r
+}\r
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c
new file mode 100644 (file)
index 0000000..c0cc15f
--- /dev/null
@@ -0,0 +1,755 @@
+/** @file\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. 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
+Module Name:\r
+\r
+  Ip4Config.c\r
+\r
+Abstract:\r
+\r
+  This code implements the IP4Config and NicIp4Config protocols.\r
+\r
+\r
+**/\r
+\r
+#include "Ip4Config.h"\r
+\r
+IP4_CONFIG_INSTANCE *mIp4ConfigNicList[MAX_IP4_CONFIG_IN_VARIABLE];\r
+\r
+VOID\r
+EFIAPI\r
+Ip4ConfigOnDhcp4Complete (\r
+  IN EFI_EVENT                  Event,\r
+  IN VOID                       *Context\r
+  );\r
+\r
+\r
+/**\r
+  Return the name and MAC address for the NIC. The Name, if not NULL,\r
+  has at least IP4_NIC_NAME_LENGTH bytes.\r
+\r
+  @param  This                   The NIC IP4 CONFIG protocol\r
+  @param  Name                   The buffer to return the name\r
+  @param  NicAddr                The buffer to return the MAC addr\r
+\r
+  @retval EFI_INVALID_PARAMETER  This is NULL\r
+  @retval EFI_SUCCESS            The name or address of the NIC are returned.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiNicIp4ConfigGetName (\r
+  IN  EFI_NIC_IP4_CONFIG_PROTOCOL *This,\r
+  IN  UINT16                      *Name,          OPTIONAL\r
+  IN  NIC_ADDR                    *NicAddr       OPTIONAL\r
+  )\r
+{\r
+  IP4_CONFIG_INSTANCE       *Instance;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Instance = IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This);\r
+\r
+  if (Name != NULL) {\r
+    NetCopyMem (Name, Instance->NicName, IP4_NIC_NAME_LENGTH);\r
+  }\r
+\r
+  if (NicAddr != NULL) {\r
+    *NicAddr = Instance->NicAddr;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Get the NIC's configure information from the IP4 configure  variable.\r
+  It will remove the invalid variable.\r
+\r
+  @param  NicAddr                The NIC to check\r
+\r
+  @return NULL if no configure for the NIC in the variable, or it is invalid.\r
+  @return Otherwise the NIC's IP configure parameter.\r
+\r
+**/\r
+NIC_IP4_CONFIG_INFO *\r
+Ip4ConfigGetNicInfo (\r
+  IN  NIC_ADDR              *NicAddr\r
+  )\r
+{\r
+  IP4_CONFIG_VARIABLE       *Variable;\r
+  IP4_CONFIG_VARIABLE       *NewVariable;\r
+  NIC_IP4_CONFIG_INFO       *Config;\r
+\r
+  //\r
+  // Read the configuration parameter for this NicAddr from\r
+  // the EFI variable\r
+  //\r
+  Variable = Ip4ConfigReadVariable ();\r
+\r
+  if (Variable == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Config = Ip4ConfigFindNicVariable (Variable, NicAddr);\r
+\r
+  if (Config == NULL) {\r
+    NetFreePool (Variable);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Validate the configuration, if the configuration is invalid,\r
+  // remove it from the variable.\r
+  //\r
+  if (!Ip4ConfigIsValid (Config)) {\r
+    NewVariable = Ip4ConfigModifyVariable (Variable, &Config->NicAddr, NULL);\r
+    Ip4ConfigWriteVariable (NewVariable);\r
+\r
+    if (NewVariable != NULL) {\r
+      NetFreePool (NewVariable);\r
+    };\r
+\r
+    NetFreePool (Config);\r
+    Config = NULL;\r
+  }\r
+\r
+  NetFreePool (Variable);\r
+  return Config;\r
+}\r
+\r
+\r
+/**\r
+  Get the configure parameter for this NIC.\r
+\r
+  @param  This                   The NIC IP4 CONFIG protocol\r
+  @param  ConfigLen              The length of the NicConfig buffer.\r
+  @param  NicConfig              The buffer to receive the NIC's configure\r
+                                 parameter.\r
+\r
+  @retval EFI_INVALID_PARAMETER  This or ConfigLen is NULL\r
+  @retval EFI_NOT_FOUND          There is no configure parameter for the NIC in\r
+                                 NVRam.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiNicIp4ConfigGetInfo (\r
+  IN  EFI_NIC_IP4_CONFIG_PROTOCOL *This,\r
+  IN OUT  UINTN                   *ConfigLen,\r
+  OUT NIC_IP4_CONFIG_INFO         *NicConfig\r
+  )\r
+{\r
+  IP4_CONFIG_INSTANCE *Instance;\r
+  NIC_IP4_CONFIG_INFO *Config;\r
+  EFI_STATUS          Status;\r
+  UINTN               Len;\r
+\r
+  if ((This == NULL) || (ConfigLen == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // Read the Nic's configuration parameter from variable\r
+  //\r
+  Instance  = IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This);\r
+  Config    = Ip4ConfigGetNicInfo (&Instance->NicAddr);\r
+\r
+  if (Config == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // Copy the data to user's buffer\r
+  //\r
+  Len = SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
+\r
+  if ((*ConfigLen < Len) || (NicConfig == NULL)) {\r
+    Status = EFI_BUFFER_TOO_SMALL;\r
+  } else {\r
+    Status = EFI_SUCCESS;\r
+    NetCopyMem (NicConfig, Config, Len);\r
+  }\r
+\r
+  *ConfigLen = Len;\r
+\r
+  NetFreePool (Config);\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Set the IP configure parameters for this NIC. If Reconfig is TRUE,\r
+  the IP driver will be informed to discard current auto configure\r
+  parameter and restart the auto configuration process. If current\r
+  there is a pending auto configuration, EFI_ALREADY_STARTED is\r
+  returned. You can only change the configure setting when either\r
+  the configure has finished or not started yet. If NicConfig, the\r
+  NIC's configure parameter is removed from the variable.\r
+\r
+  @param  This                   The NIC IP4 CONFIG protocol\r
+  @param  NicConfig              The new NIC IP4 configure parameter\r
+  @param  Reconfig               Inform the IP4 driver to restart the auto\r
+                                 configuration\r
+\r
+  @retval EFI_INVALID_PARAMETER  This is NULL or the configure parameter is\r
+                                 invalid.\r
+  @retval EFI_ALREADY_STARTED    There is a pending auto configuration.\r
+  @retval EFI_NOT_FOUND          No auto configure parameter is found\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiNicIp4ConfigSetInfo (\r
+  IN EFI_NIC_IP4_CONFIG_PROTOCOL  *This,\r
+  IN NIC_IP4_CONFIG_INFO          *NicConfig,     OPTIONAL\r
+  IN BOOLEAN                      Reconfig\r
+  )\r
+{\r
+  IP4_CONFIG_INSTANCE *Instance;\r
+  IP4_CONFIG_VARIABLE *Variable;\r
+  IP4_CONFIG_VARIABLE *NewVariable;\r
+  EFI_STATUS          Status;\r
+\r
+  //\r
+  // Validate the parameters\r
+  //\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Instance = IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This);\r
+\r
+  if ((NicConfig != NULL) && (!Ip4ConfigIsValid (NicConfig) ||\r
+      !NIC_ADDR_EQUAL (&NicConfig->NicAddr, &Instance->NicAddr))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Instance->State == IP4_CONFIG_STATE_STARTED) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  //\r
+  // Update the parameter in the configure variable\r
+  //\r
+  Variable = Ip4ConfigReadVariable ();\r
+\r
+  if ((Variable == NULL) && (NicConfig == NULL)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  NewVariable = Ip4ConfigModifyVariable (Variable, &Instance->NicAddr, NicConfig);\r
+  Status      = Ip4ConfigWriteVariable (NewVariable);\r
+\r
+  if (NewVariable != NULL) {\r
+    NetFreePool (NewVariable);\r
+  }\r
+\r
+  //\r
+  // Variable is NULL when saving the first configure parameter\r
+  //\r
+  if (Variable != NULL) {\r
+    NetFreePool (Variable);\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Signal the IP4 to run the auto configuration again\r
+  //\r
+  if (Reconfig && (Instance->ReconfigEvent != NULL)) {\r
+    Status = gBS->SignalEvent (Instance->ReconfigEvent);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start the auto configuration process.\r
+\r
+  @param  This                   The IP4 configure protocol\r
+  @param  DoneEvent              The event to signal when auto configure is done\r
+  @param  ReconfigEvent          The event to signal when reconfigure is necessary.\r
+\r
+  @retval EFI_INVALID_PARAMETER  One of the function parameters is NULL.\r
+  @retval EFI_ALREADY_STARTED    The auto configuration has already started.\r
+  @retval EFI_SUCCESS            The auto configure is successfully started.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIp4ConfigStart (\r
+  IN EFI_IP4_CONFIG_PROTOCOL  *This,\r
+  IN EFI_EVENT                DoneEvent,\r
+  IN EFI_EVENT                ReconfigEvent\r
+  )\r
+{\r
+  IP4_CONFIG_INSTANCE       *Instance;\r
+  EFI_DHCP4_PROTOCOL        *Dhcp4;\r
+  EFI_DHCP4_MODE_DATA       Dhcp4Mode;\r
+  EFI_DHCP4_PACKET_OPTION   *OptionList[1];\r
+  IP4_CONFIG_DHCP4_OPTION   ParaList;\r
+  EFI_STATUS                Status;\r
+  UINT32                    Source;\r
+  EFI_TPL                   OldTpl;\r
+\r
+  if ((This == NULL) || (DoneEvent == NULL) || (ReconfigEvent == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
+\r
+  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+\r
+  if (Instance->State != IP4_CONFIG_STATE_IDLE) {\r
+    Status = EFI_ALREADY_STARTED;\r
+\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Instance->DoneEvent     = DoneEvent;\r
+  Instance->ReconfigEvent = ReconfigEvent;\r
+\r
+  Instance->NicConfig     = Ip4ConfigGetNicInfo (&Instance->NicAddr);\r
+\r
+  if (Instance->NicConfig == NULL) {\r
+    Source = IP4_CONFIG_SOURCE_DHCP;\r
+  } else {\r
+    Source = Instance->NicConfig->Source;\r
+  }\r
+\r
+  //\r
+  // If the source is static, the auto configuration is done.\r
+  // return now.\r
+  //\r
+  if (Source == IP4_CONFIG_SOURCE_STATIC) {\r
+    Instance->State  = IP4_CONFIG_STATE_CONFIGURED;\r
+    Instance->Result = EFI_SUCCESS;\r
+\r
+    gBS->SignalEvent (Instance->DoneEvent);\r
+    Status = EFI_SUCCESS;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Start the dhcp process\r
+  //\r
+  ASSERT ((Source == IP4_CONFIG_SOURCE_DHCP) && (Instance->Dhcp4 == NULL));\r
+\r
+  Status = NetLibCreateServiceChild (\r
+             Instance->Controller,\r
+             Instance->Image,\r
+             &gEfiDhcp4ServiceBindingProtocolGuid,\r
+             &Instance->Dhcp4Handle\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  Instance->Dhcp4Handle,\r
+                  &gEfiDhcp4ProtocolGuid,\r
+                  (VOID **) &Instance->Dhcp4,\r
+                  Instance->Image,\r
+                  Instance->Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\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 (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  if (Dhcp4Mode.State == Dhcp4Bound) {\r
+    Ip4ConfigOnDhcp4Complete (NULL, Instance);\r
+\r
+    goto ON_EXIT;\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
+    goto ON_ERROR;\r
+  }\r
+\r
+  //\r
+  // Start the DHCP process\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  NET_TPL_EVENT,\r
+                  Ip4ConfigOnDhcp4Complete,\r
+                  Instance,\r
+                  &Instance->Dhcp4Event\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Instance->State  = IP4_CONFIG_STATE_STARTED;\r
+  Instance->Result = EFI_NOT_READY;\r
+\r
+ON_ERROR:\r
+  if (EFI_ERROR (Status)) {\r
+    Ip4ConfigCleanConfig (Instance);\r
+  }\r
+\r
+ON_EXIT:\r
+  NET_RESTORE_TPL (OldTpl);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop the current auto configuration\r
+\r
+  @param  This                   The IP4 CONFIG protocol\r
+\r
+  @retval EFI_INVALID_PARAMETER  This is NULL.\r
+  @retval EFI_NOT_STARTED        The auto configuration hasn't been started.\r
+  @retval EFI_SUCCESS            The auto configuration has been stopped.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIp4ConfigStop (\r
+  IN EFI_IP4_CONFIG_PROTOCOL  *This\r
+  )\r
+{\r
+  IP4_CONFIG_INSTANCE  *Instance;\r
+  EFI_STATUS           Status;\r
+  EFI_TPL              OldTpl;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
+\r
+  Status = EFI_SUCCESS;\r
+  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+\r
+  if (Instance->State == IP4_CONFIG_STATE_IDLE) {\r
+    Status = EFI_NOT_STARTED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Release all the configure parameters. Don't signal the user\r
+  // event. The user wants to abort the configuration, this isn't\r
+  // the configuration done or reconfiguration.\r
+  //\r
+  Ip4ConfigCleanConfig (Instance);\r
+\r
+ON_EXIT:\r
+  NET_RESTORE_TPL (OldTpl);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Get the current outcome of the auto configuration process\r
+\r
+  @param  This                   The IP4 CONFIG protocol\r
+  @param  ConfigDataSize         The size of the configure data\r
+  @param  ConfigData             The buffer to save the configure data\r
+\r
+  @retval EFI_INVALID_PARAMETER  This or ConfigDataSize is NULL\r
+  @retval EFI_BUFFER_TOO_SMALL   The buffer is too small. The needed size is\r
+                                 returned in the ConfigDataSize.\r
+  @retval EFI_SUCCESS            The configure data is put in the buffer\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIp4ConfigGetData (\r
+  IN  EFI_IP4_CONFIG_PROTOCOL *This,\r
+  IN  OUT  UINTN              *ConfigDataSize,\r
+  OUT EFI_IP4_IPCONFIG_DATA   *ConfigData           OPTIONAL\r
+  )\r
+{\r
+  IP4_CONFIG_INSTANCE       *Instance;\r
+  NIC_IP4_CONFIG_INFO       *NicConfig;\r
+  EFI_STATUS                Status;\r
+  EFI_TPL                   OldTpl;\r
+  UINTN                     Len;\r
+\r
+  if ((This == NULL) || (ConfigDataSize == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Instance  = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);\r
+\r
+  Status = EFI_SUCCESS;\r
+  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+\r
+  if (Instance->State == IP4_CONFIG_STATE_IDLE) {\r
+    Status = EFI_NOT_STARTED;\r
+  } else if (Instance->State == IP4_CONFIG_STATE_STARTED) {\r
+    Status = EFI_NOT_READY;\r
+  }\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Copy the configure data if auto configuration succeeds.\r
+  //\r
+  Status = Instance->Result;\r
+\r
+  if (Status == EFI_SUCCESS) {\r
+    ASSERT (Instance->NicConfig != NULL);\r
+\r
+    NicConfig = Instance->NicConfig;\r
+    Len       = SIZEOF_IP4_CONFIG_INFO (&NicConfig->Ip4Info);\r
+\r
+    if ((*ConfigDataSize < Len) || (ConfigData == NULL)) {\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+    } else {\r
+      NetCopyMem (ConfigData, &NicConfig->Ip4Info, Len);\r
+    }\r
+\r
+    *ConfigDataSize = Len;\r
+  }\r
+\r
+ON_EXIT:\r
+  NET_RESTORE_TPL (OldTpl);\r
+\r
+  return Status;\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
+Ip4ConfigOnDhcp4Complete (\r
+  IN EFI_EVENT              Event,\r
+  IN VOID                   *Context\r
+  )\r
+{\r
+  IP4_CONFIG_INSTANCE       *Instance;\r
+  EFI_DHCP4_MODE_DATA       Dhcp4Mode;\r
+  EFI_IP4_IPCONFIG_DATA     *Ip4Config;\r
+  EFI_STATUS                Status;\r
+  BOOLEAN                   Perment;\r
+  IP4_ADDR                  Subnet;\r
+\r
+  Instance = (IP4_CONFIG_INSTANCE *) Context;\r
+  ASSERT (Instance->Dhcp4 != NULL);\r
+\r
+  Instance->State   = IP4_CONFIG_STATE_CONFIGURED;\r
+  Instance->Result  = EFI_TIMEOUT;\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 ON_EXIT;\r
+  }\r
+\r
+  if (Dhcp4Mode.State == Dhcp4Bound) {\r
+    //\r
+    // Save the new configuration retrieved by DHCP both in\r
+    // the instance and to NVRam. So, both the IP4 driver and\r
+    // other user can get that address.\r
+    //\r
+    Perment = FALSE;\r
+\r
+    if (Instance->NicConfig != NULL) {\r
+      ASSERT (Instance->NicConfig->Source == IP4_CONFIG_SOURCE_DHCP);\r
+      Perment = Instance->NicConfig->Perment;\r
+      NetFreePool (Instance->NicConfig);\r
+    }\r
+\r
+    Instance->NicConfig = NetAllocatePool (sizeof (NIC_IP4_CONFIG_INFO) +\r
+                                           sizeof (EFI_IP4_ROUTE_TABLE));\r
+\r
+    if (Instance->NicConfig == NULL) {\r
+      Instance->Result = EFI_OUT_OF_RESOURCES;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    Instance->NicConfig->NicAddr = Instance->NicAddr;\r
+    Instance->NicConfig->Source  = IP4_CONFIG_SOURCE_DHCP;\r
+    Instance->NicConfig->Perment = Perment;\r
+\r
+    Ip4Config                    = &Instance->NicConfig->Ip4Info;\r
+    Ip4Config->StationAddress    = Dhcp4Mode.ClientAddress;\r
+    Ip4Config->SubnetMask        = Dhcp4Mode.SubnetMask;\r
+\r
+    //\r
+    // Create a route for the connected network\r
+    //\r
+    Ip4Config->RouteTableSize    = 1;\r
+\r
+    Subnet = EFI_NTOHL (Dhcp4Mode.ClientAddress) & EFI_NTOHL (Dhcp4Mode.SubnetMask);\r
+\r
+    EFI_IP4 (Ip4Config->RouteTable[0].SubnetAddress)  = HTONL (Subnet);\r
+    Ip4Config->RouteTable[0].SubnetMask               = Dhcp4Mode.SubnetMask;\r
+    EFI_IP4 (Ip4Config->RouteTable[0].GatewayAddress) = 0;\r
+\r
+    //\r
+    // Create a route if there is a default router.\r
+    //\r
+    if (EFI_IP4 (Dhcp4Mode.RouterAddress) != 0) {\r
+      Ip4Config->RouteTableSize                         = 2;\r
+      EFI_IP4 (Ip4Config->RouteTable[1].SubnetAddress)  = 0;\r
+      EFI_IP4 (Ip4Config->RouteTable[1].SubnetMask)     = 0;\r
+      Ip4Config->RouteTable[1].GatewayAddress           = Dhcp4Mode.RouterAddress;\r
+    }\r
+\r
+    Instance->Result = EFI_SUCCESS;\r
+\r
+    //\r
+    // ignore the return status of EfiNicIp4ConfigSetInfo. Network\r
+    // stack can operate even that failed.\r
+    //\r
+    EfiNicIp4ConfigSetInfo (&Instance->NicIp4Protocol, Instance->NicConfig, FALSE);\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->SignalEvent (Instance->DoneEvent);\r
+  Ip4ConfigCleanDhcp4 (Instance);\r
+  return ;\r
+}\r
+\r
+\r
+/**\r
+  Release all the DHCP related resources.\r
+\r
+  @param  This                   The IP4 configure instance\r
+\r
+  @return None\r
+\r
+**/\r
+VOID\r
+Ip4ConfigCleanDhcp4 (\r
+  IN IP4_CONFIG_INSTANCE    *This\r
+  )\r
+{\r
+  if (This->Dhcp4 != NULL) {\r
+    This->Dhcp4->Stop (This->Dhcp4);\r
+\r
+    gBS->CloseProtocol (\r
+          This->Dhcp4Handle,\r
+          &gEfiDhcp4ProtocolGuid,\r
+          This->Image,\r
+          This->Controller\r
+          );\r
+\r
+    This->Dhcp4 = NULL;\r
+  }\r
+\r
+  if (This->Dhcp4Handle != NULL) {\r
+    NetLibDestroyServiceChild (\r
+      This->Controller,\r
+      This->Image,\r
+      &gEfiDhcp4ServiceBindingProtocolGuid,\r
+      This->Dhcp4Handle\r
+      );\r
+\r
+    This->Dhcp4Handle = NULL;\r
+  }\r
+\r
+  if (This->Dhcp4Event == NULL) {\r
+    gBS->CloseEvent (This->Dhcp4Event);\r
+    This->Dhcp4Event = NULL;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Clean up all the configuration parameters\r
+\r
+  @param  Instance               The IP4 configure instance\r
+\r
+  @return None\r
+\r
+**/\r
+VOID\r
+Ip4ConfigCleanConfig (\r
+  IN IP4_CONFIG_INSTANCE        *Instance\r
+  )\r
+{\r
+  if (Instance->NicConfig != NULL) {\r
+    NetFreePool (Instance->NicConfig);\r
+    Instance->NicConfig = NULL;\r
+  }\r
+\r
+  Instance->State         = IP4_CONFIG_STATE_IDLE;\r
+  Instance->DoneEvent     = NULL;\r
+  Instance->ReconfigEvent = NULL;\r
+\r
+  Ip4ConfigCleanDhcp4 (Instance);\r
+}\r
+\r
+EFI_IP4_CONFIG_PROTOCOL     mIp4ConfigProtocolTemplate = {\r
+  EfiIp4ConfigStart,\r
+  EfiIp4ConfigStop,\r
+  EfiIp4ConfigGetData\r
+};\r
+\r
+EFI_NIC_IP4_CONFIG_PROTOCOL mNicIp4ConfigProtocolTemplate = {\r
+  EfiNicIp4ConfigGetName,\r
+  EfiNicIp4ConfigGetInfo,\r
+  EfiNicIp4ConfigSetInfo\r
+};\r
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h
new file mode 100644 (file)
index 0000000..90e5599
--- /dev/null
@@ -0,0 +1,132 @@
+/** @file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+  Ip4Config.h
+
+Abstract:
+
+  Header file for IP4Config driver.
+
+
+**/
+
+#ifndef __EFI_IP4CONFIG_H__
+#define __EFI_IP4CONFIG_H__
+
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Dhcp4.h>\r
+#include <Protocol/IP4Config.h>\r
+#include <Protocol/ManagedNetwork.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/NetLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>
+
+#include "NicIp4Variable.h"
+
+typedef struct _IP4_CONFIG_INSTANCE IP4_CONFIG_INSTANCE;
+
+enum {
+  IP4_CONFIG_STATE_IDLE         = 0,
+  IP4_CONFIG_STATE_STARTED,
+  IP4_CONFIG_STATE_CONFIGURED,
+
+  IP4_PROTO_ICMP                = 0x01,
+  IP4_CONFIG_INSTANCE_SIGNATURE = EFI_SIGNATURE_32 ('I', 'P', '4', 'C'),
+
+  DHCP_TAG_PARA_LIST            = 55,
+  DHCP_TAG_NETMASK              = 1,
+  DHCP_TAG_ROUTER               = 3,
+};
+
+//
+// Configure the DHCP to request the routers and netmask
+// from server. The DHCP_TAG_NETMASK is included in Head.
+//
+#pragma pack(1)
+typedef struct {
+  EFI_DHCP4_PACKET_OPTION Head;
+  UINT8                   Route;
+} IP4_CONFIG_DHCP4_OPTION;
+#pragma pack()
+
+typedef struct _IP4_CONFIG_INSTANCE {
+  UINT32                        Signature;
+  EFI_HANDLE                    Controller;
+  EFI_HANDLE                    Image;
+
+  EFI_IP4_CONFIG_PROTOCOL       Ip4ConfigProtocol;
+  EFI_NIC_IP4_CONFIG_PROTOCOL   NicIp4Protocol;
+
+  //
+  // NicConfig's state, such as IP4_CONFIG_STATE_IDLE
+  //
+  INTN                          State;
+
+  //
+  // Mnp child to keep the connection with MNP.
+  //
+  EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;
+  EFI_HANDLE                    MnpHandle;
+
+  //
+  // User's requests data
+  //
+  EFI_EVENT                     DoneEvent;
+  EFI_EVENT                     ReconfigEvent;
+  EFI_STATUS                    Result;
+
+  //
+  // Identity of this interface and some configuration info.
+  //
+  NIC_ADDR                      NicAddr;
+  UINT16                        NicName[IP4_NIC_NAME_LENGTH];
+  UINT32                        NicIndex;
+  NIC_IP4_CONFIG_INFO           *NicConfig;
+
+  //
+  // DHCP handles to access DHCP
+  //
+  EFI_DHCP4_PROTOCOL            *Dhcp4;
+  EFI_HANDLE                    Dhcp4Handle;
+  EFI_EVENT                     Dhcp4Event;
+};
+
+#define IP4_CONFIG_INSTANCE_FROM_IP4CONFIG(this) \
+  CR (this, IP4_CONFIG_INSTANCE, Ip4ConfigProtocol, IP4_CONFIG_INSTANCE_SIGNATURE)
+
+#define IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG(this) \
+  CR (this, IP4_CONFIG_INSTANCE, NicIp4Protocol, IP4_CONFIG_INSTANCE_SIGNATURE)
+
+extern EFI_DRIVER_BINDING_PROTOCOL  gIp4ConfigDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL  gIp4ConfigComponentName;
+extern IP4_CONFIG_INSTANCE          *mIp4ConfigNicList[MAX_IP4_CONFIG_IN_VARIABLE];
+extern EFI_IP4_CONFIG_PROTOCOL      mIp4ConfigProtocolTemplate;
+extern EFI_NIC_IP4_CONFIG_PROTOCOL  mNicIp4ConfigProtocolTemplate;
+
+VOID
+Ip4ConfigCleanDhcp4 (
+  IN IP4_CONFIG_INSTANCE        *This
+  );
+
+VOID
+Ip4ConfigCleanConfig (
+  IN IP4_CONFIG_INSTANCE        *Instance
+  );
+#endif
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c
new file mode 100644 (file)
index 0000000..342b7d9
--- /dev/null
@@ -0,0 +1,529 @@
+/** @file\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. 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
+Module Name:\r
+\r
+  Ip4ConfigDriver.c\r
+\r
+Abstract:\r
+\r
+  The driver binding for IP4 CONFIG protocol.\r
+\r
+\r
+**/\r
+\r
+\r
+#include "Ip4Config.h"\r
+\r
+\r
+/**\r
+  Stop all the auto configuration when the IP4 configure driver is\r
+  being unloaded.\r
+\r
+  @param  ImageHandle          The driver that is being unloaded\r
+\r
+  @retval EFI_SUCCESS          The driver has been ready for unload.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiIp4ConfigUnload (\r
+  IN EFI_HANDLE             ImageHandle\r
+  )\r
+{\r
+  UINT32      Index;\r
+\r
+  //\r
+  //  Stop all the IP4_CONFIG instances\r
+  //\r
+  for (Index = 0; Index < MAX_IP4_CONFIG_IN_VARIABLE; Index++) {\r
+    if (mIp4ConfigNicList[Index] == NULL) {\r
+      continue;\r
+    }\r
+\r
+    gIp4ConfigDriverBinding.Stop (\r
+                              &gIp4ConfigDriverBinding,\r
+                              mIp4ConfigNicList[Index]->MnpHandle,\r
+                              0,\r
+                              NULL\r
+                              );\r
+  }\r
+\r
+  return NetLibDefaultUnload (ImageHandle);\r
+}\r
+\r
+//@MT: EFI_DRIVER_ENTRY_POINT (Ip4ConfigDriverEntryPoint)\r
+\r
+EFI_STATUS\r
+Ip4ConfigDriverEntryPoint (\r
+  IN EFI_HANDLE             ImageHandle,\r
+  IN EFI_SYSTEM_TABLE       *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The entry point for IP4 config driver which install the driver\r
+  binding and component name protocol on its image.\r
+\r
+Arguments:\r
+\r
+  ImageHandle - The Image handle of the driver\r
+  SystemTable - The system table\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - All the related protocols are installed on the driver\r
+  Others      - Failed to install the protocol\r
+\r
+--*/\r
+{\r
+  return NetLibInstallAllDriverProtocolsWithUnload (\r
+           ImageHandle,\r
+           SystemTable,\r
+           &gIp4ConfigDriverBinding,\r
+           ImageHandle,\r
+           &gIp4ConfigComponentName,\r
+           NULL,\r
+           NULL,\r
+           EfiIp4ConfigUnload\r
+           );\r
+}\r
+\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  ControllerHandle     Handle of device to test\r
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
+                               device to start.\r
+\r
+  @retval EFI_SUCCES           This driver supports this device\r
+  @retval EFI_ALREADY_STARTED  This driver is already running on this device\r
+  @retval other                This driver does not support this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4ConfigDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath  OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start this driver on ControllerHandle.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  ControllerHandle     Handle of device to bind driver to\r
+  @param  RemainingDevicePath  Optional parameter use to pick a specific child\r
+                               device to start.\r
+\r
+  @retval EFI_SUCCES           This driver is added to ControllerHandle\r
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle\r
+  @retval other                This driver does not support this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4ConfigDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  EFI_IP4_CONFIG_PROTOCOL       *Ip4Config;\r
+  EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;\r
+  EFI_HANDLE                    MnpHandle;\r
+  IP4_CONFIG_INSTANCE           *Instance;\r
+  EFI_SIMPLE_NETWORK_MODE       SnpMode;\r
+  IP4_CONFIG_VARIABLE           *Variable;\r
+  NIC_IP4_CONFIG_INFO           *NicConfig;\r
+  IP4_CONFIG_VARIABLE           *NewVariable;\r
+  EFI_STATUS                    Status;\r
+  UINT32                        Index;\r
+\r
+  //\r
+  // Check for multiple start.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiIp4ConfigProtocolGuid,\r
+                  &Ip4Config,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (!EFI_ERROR (Status)) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  //\r
+  // Create a MNP child\r
+  //\r
+  Mnp       = NULL;\r
+  MnpHandle = NULL;\r
+  Instance  = NULL;\r
+\r
+  Status    = NetLibCreateServiceChild (\r
+                ControllerHandle,\r
+                This->DriverBindingHandle,\r
+                &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                &MnpHandle\r
+                );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = gBS->OpenProtocol (\r
+                  MnpHandle,\r
+                  &gEfiManagedNetworkProtocolGuid,\r
+                  (VOID **) &Mnp,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  //\r
+  // Allocate an instance then initialize it\r
+  //\r
+  Instance = NetAllocatePool (sizeof (IP4_CONFIG_INSTANCE));\r
+\r
+  if (Instance == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Instance->Signature         = IP4_CONFIG_INSTANCE_SIGNATURE;\r
+  Instance->Controller        = ControllerHandle;\r
+  Instance->Image             = This->DriverBindingHandle;\r
+\r
+  Instance->Ip4ConfigProtocol = mIp4ConfigProtocolTemplate;\r
+  Instance->NicIp4Protocol    = mNicIp4ConfigProtocolTemplate;\r
+\r
+  Instance->State             = IP4_CONFIG_STATE_IDLE;\r
+  Instance->Mnp               = Mnp;\r
+  Instance->MnpHandle         = MnpHandle;\r
+\r
+  Instance->DoneEvent         = NULL;\r
+  Instance->ReconfigEvent     = NULL;\r
+  Instance->Result            = EFI_NOT_READY;\r
+  Instance->NicConfig         = NULL;\r
+\r
+  Instance->Dhcp4             = NULL;\r
+  Instance->Dhcp4Handle       = NULL;\r
+  Instance->Dhcp4Event        = NULL;\r
+\r
+  Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);\r
+\r
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Instance->NicAddr.Type    = (UINT16) SnpMode.IfType;\r
+  Instance->NicAddr.Len     = (UINT8) SnpMode.HwAddressSize;\r
+  Instance->NicAddr.MacAddr = SnpMode.CurrentAddress;\r
+\r
+  //\r
+  // Add it to the global list, and compose the name\r
+  //\r
+  for (Index = 0; Index < MAX_IP4_CONFIG_IN_VARIABLE; Index++) {\r
+    if (mIp4ConfigNicList[Index] == NULL) {\r
+      mIp4ConfigNicList[Index]  = Instance;\r
+      Instance->NicIndex        = Index;\r
+\r
+      if (Instance->NicAddr.Type == NET_IFTYPE_ETHERNET) {\r
+        Instance->NicName[0]  = 'e';\r
+        Instance->NicName[1]  = 't';\r
+        Instance->NicName[2]  = 'h';\r
+        Instance->NicName[3]  = (UINT16) ('0' + Index);\r
+        Instance->NicName[4]  = 0;\r
+      } else {\r
+        Instance->NicName[0]  = 'u';\r
+        Instance->NicName[1]  = 'n';\r
+        Instance->NicName[2]  = 'k';\r
+        Instance->NicName[3]  = (UINT16) ('0' + Index);\r
+        Instance->NicName[4]  = 0;\r
+      }\r
+\r
+      break;\r
+    }\r
+  }\r
+\r
+  if (Index == MAX_IP4_CONFIG_IN_VARIABLE) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  //\r
+  // Install the IP4_CONFIG and NIC_IP4CONFIG protocols\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &ControllerHandle,\r
+                  &gEfiIp4ConfigProtocolGuid,\r
+                  &Instance->Ip4ConfigProtocol,\r
+                  &gEfiNicIp4ConfigProtocolGuid,\r
+                  &Instance->NicIp4Protocol,\r
+                  NULL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    mIp4ConfigNicList[Index] = NULL;\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  //\r
+  // Get the previous configure parameters. If an error happend here,\r
+  // just ignore it because the driver should be able to operate.\r
+  //\r
+  Variable = Ip4ConfigReadVariable ();\r
+\r
+  if (Variable == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  NicConfig = Ip4ConfigFindNicVariable (Variable, &Instance->NicAddr);\r
+\r
+  if (NicConfig == NULL) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Don't modify the permant static configuration\r
+  //\r
+  if (NicConfig->Perment && (NicConfig->Source == IP4_CONFIG_SOURCE_STATIC)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Delete the non-permant configuration and remove the previous\r
+  // acquired DHCP parameters. Only doing DHCP itself is permant\r
+  //\r
+  NewVariable = NULL;\r
+\r
+  if (!NicConfig->Perment) {\r
+    NewVariable = Ip4ConfigModifyVariable (Variable, &Instance->NicAddr, NULL);\r
+\r
+  } else if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {\r
+    NetZeroMem (&NicConfig->Ip4Info, sizeof (EFI_IP4_IPCONFIG_DATA));\r
+    NewVariable = Ip4ConfigModifyVariable (Variable, &Instance->NicAddr, NicConfig);\r
+\r
+  }\r
+\r
+  Ip4ConfigWriteVariable (NewVariable);\r
+\r
+  if (NewVariable != NULL) {\r
+    NetFreePool (NewVariable);\r
+  }\r
+\r
+ON_EXIT:\r
+  NetFreePool (Variable);\r
+\r
+  if (NicConfig != NULL) {\r
+    NetFreePool (NicConfig);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+  if (Instance != NULL) {\r
+    NetFreePool (Instance);\r
+  }\r
+\r
+  if (Mnp != NULL) {\r
+    gBS->CloseProtocol (\r
+          MnpHandle,\r
+          &gEfiManagedNetworkProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          ControllerHandle\r
+          );\r
+  }\r
+\r
+  NetLibDestroyServiceChild (\r
+    ControllerHandle,\r
+    This->DriverBindingHandle,\r
+    &gEfiManagedNetworkProtocolGuid,\r
+    MnpHandle\r
+    );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop this driver on ControllerHandle.\r
+\r
+  @param  This                 Protocol instance pointer.\r
+  @param  ControllerHandle     Handle of device to stop driver on\r
+  @param  NumberOfChildren     Number of Handles in ChildHandleBuffer. If number of\r
+                                children is zero stop the entire bus driver.\r
+  @param  ChildHandleBuffer    List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCES           This driver is removed ControllerHandle\r
+  @retval other                This driver was not removed from this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ip4ConfigDriverBindingStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  IP4_CONFIG_INSTANCE       *Instance;\r
+  EFI_IP4_CONFIG_PROTOCOL   *Ip4Config;\r
+  EFI_HANDLE                NicHandle;\r
+  EFI_STATUS                Status;\r
+\r
+  //\r
+  // IP4_CONFIG instance opens an MNP child. It may also create and open\r
+  // a DHCP child. If this is the DHCP handle, stop the DHCP process. If\r
+  // it is the MNP child, stop the whole driver.\r
+  //\r
+  //\r
+  NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
+\r
+  if (NicHandle != NULL) {\r
+    //\r
+    // Get our context back then clean the DHCP up. Notify the user if necessary.\r
+    //\r
+    Status = gBS->OpenProtocol (\r
+                    NicHandle,\r
+                    &gEfiIp4ConfigProtocolGuid,\r
+                    (VOID **) &Ip4Config,\r
+                    This->DriverBindingHandle,\r
+                    ControllerHandle,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (Ip4Config);\r
+    ASSERT (ControllerHandle == Instance->Dhcp4Handle);\r
+\r
+    Ip4ConfigCleanDhcp4 (Instance);\r
+\r
+    Instance->State   = IP4_CONFIG_STATE_CONFIGURED;\r
+    Instance->Result  = EFI_DEVICE_ERROR;\r
+\r
+    if (Instance->DoneEvent != NULL) {\r
+      gBS->SignalEvent (Instance->DoneEvent);\r
+    }\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // This is a MNP handle, stop the whole driver\r
+  //\r
+  NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
+\r
+  if (NicHandle == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get our context back.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  NicHandle,\r
+                  &gEfiIp4ConfigProtocolGuid,\r
+                  (VOID **) &Ip4Config,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (Ip4Config);\r
+\r
+  //\r
+  // Unload the protocols first to inform the top drivers\r
+  //\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                  NicHandle,\r
+                  &gEfiIp4ConfigProtocolGuid,\r
+                  &Instance->Ip4ConfigProtocol,\r
+                  &gEfiNicIp4ConfigProtocolGuid,\r
+                  &Instance->NicIp4Protocol,\r
+                  NULL\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Release all the resources\r
+  //\r
+  if (Instance->MnpHandle != NULL) {\r
+    gBS->CloseProtocol (\r
+          Instance->MnpHandle,\r
+          &gEfiManagedNetworkProtocolGuid,\r
+          This->DriverBindingHandle,\r
+          NicHandle\r
+          );\r
+\r
+    NetLibDestroyServiceChild (\r
+      NicHandle,\r
+      Instance->Image,\r
+      &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+      Instance->MnpHandle\r
+      );\r
+\r
+    Instance->Mnp       = NULL;\r
+    Instance->MnpHandle = NULL;\r
+  }\r
+\r
+  Ip4ConfigCleanConfig (Instance);\r
+  mIp4ConfigNicList[Instance->NicIndex] = NULL;\r
+  NetFreePool (Instance);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gIp4ConfigDriverBinding = {\r
+  Ip4ConfigDriverBindingSupported,\r
+  Ip4ConfigDriverBindingStart,\r
+  Ip4ConfigDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
new file mode 100644 (file)
index 0000000..2fc16ef
--- /dev/null
@@ -0,0 +1,64 @@
+#/** @file\r
+# Component name for module Ip4Config\r
+#\r
+# FIX ME!\r
+# Copyright (c) 2006, Intel Corporation. All right reserved.\r
+#\r
+#  All rights reserved. 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
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010005\r
+  BASE_NAME                      = Ip4ConfigDxe\r
+  FILE_GUID                      = 26841BDE-920A-4e7a-9FBE-637F477143A6\r
+  MODULE_TYPE                    = DXE_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  EDK_RELEASE_VERSION            = 0x00020000\r
+  EFI_SPECIFICATION_VERSION      = 0x00020000\r
+\r
+  ENTRY_POINT                    = Ip4ConfigDriverEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+  ComponentName.c\r
+  NicIp4Variable.c\r
+  Ip4ConfigDriver.c\r
+  Ip4Config.h\r
+  NicIp4Variable.h\r
+  Ip4Config.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+  UefiLib\r
+  UefiBootServicesTableLib\r
+  UefiDriverEntryPoint\r
+  UefiRuntimeServicesTableLib\r
+  DebugLib\r
+  NetLib\r
+\r
+\r
+[Protocols]\r
+  gEfiDhcp4ServiceBindingProtocolGuid           # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiManagedNetworkServiceBindingProtocolGuid  # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiIp4ConfigProtocolGuid                     # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiManagedNetworkProtocolGuid                # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiDhcp4ProtocolGuid                         # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiNicIp4ConfigVariableGuid                  # PROTOCOL ALWAYS_CONSUMED\r
+  gEfiNicIp4ConfigProtocolGuid                  # PROTOCOL ALWAYS_CONSUMED
\ No newline at end of file
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.msa b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.msa
new file mode 100644 (file)
index 0000000..94eb98e
--- /dev/null
@@ -0,0 +1,77 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+  <MsaHeader>\r
+    <ModuleName>Ip4Config</ModuleName>\r
+    <ModuleType>DXE_DRIVER</ModuleType>\r
+    <GuidValue>26841BDE-920A-4e7a-9FBE-637F477143A6</GuidValue>\r
+    <Version>1.0</Version>\r
+    <Abstract>Component name for module Ip4Config</Abstract>\r
+    <Description>FIX ME!</Description>\r
+    <Copyright>Copyright (c) 2006, Intel Corporation. All right reserved.</Copyright>\r
+    <License>All rights reserved. This program and the accompanying materials                          
+      are licensed and made available under the terms and conditions of the BSD License         
+      which accompanies this distribution.  The full text of the license may be found at        
+      http://opensource.org/licenses/bsd-license.php                                            
+      
+      THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+      WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+    <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION   0x00000052</Specification>\r
+  </MsaHeader>\r
+  <ModuleDefinitions>\r
+    <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+    <BinaryModule>false</BinaryModule>\r
+    <OutputFileBasename>Ip4Config</OutputFileBasename>\r
+  </ModuleDefinitions>\r
+  <LibraryClassDefinitions>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>DebugLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiRuntimeServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiDriverEntryPoint</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiBootServicesTableLib</Keyword>\r
+    </LibraryClass>\r
+    <LibraryClass Usage="ALWAYS_CONSUMED">\r
+      <Keyword>UefiLib</Keyword>\r
+    </LibraryClass>\r
+  </LibraryClassDefinitions>\r
+  <SourceFiles>\r
+    <Filename>Ip4Config.c</Filename>\r
+    <Filename>NicIp4Variable.h</Filename>\r
+    <Filename>Ip4Config.h</Filename>\r
+    <Filename>Ip4ConfigDriver.c</Filename>\r
+    <Filename>NicIp4Variable.c</Filename>\r
+    <Filename>ComponentName.c</Filename>\r
+  </SourceFiles>\r
+  <PackageDependencies>\r
+    <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+    <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+  </PackageDependencies>\r
+  <Protocols>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDhcp4ProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiManagedNetworkProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiIp4ConfigProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiManagedNetworkServiceBindingProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+    <Protocol Usage="ALWAYS_CONSUMED">\r
+      <ProtocolCName>gEfiDhcp4ServiceBindingProtocolGuid</ProtocolCName>\r
+    </Protocol>\r
+  </Protocols>\r
+  <Externs>\r
+    <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+    <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+    <Extern>\r
+      <ModuleEntryPoint>Ip4ConfigDriverEntryPoint</ModuleEntryPoint>\r
+    </Extern>\r
+  </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.c b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.c
new file mode 100644 (file)
index 0000000..ac5283f
--- /dev/null
@@ -0,0 +1,383 @@
+/** @file\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. 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
+Module Name:\r
+\r
+  NicIp4Variable.c\r
+\r
+Abstract:\r
+\r
+  Routines used to operate the Ip4 configure variable\r
+\r
+\r
+**/\r
+\r
+\r
+#include <Library/NetLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+\r
+#include "NicIp4Variable.h"\r
+\r
+\r
+/**\r
+  Check whether the configure parameter is valid.\r
+\r
+  @param  NicConfig    The configure parameter to check\r
+\r
+  @return TRUE if the parameter is valid for the interface, otherwise FALSE.\r
+\r
+**/\r
+BOOLEAN\r
+Ip4ConfigIsValid (\r
+  IN NIC_IP4_CONFIG_INFO    *NicConfig\r
+  )\r
+{\r
+  EFI_IP4_IPCONFIG_DATA     *IpConfig;\r
+  IP4_ADDR                  Station;\r
+  IP4_ADDR                  Netmask;\r
+  IP4_ADDR                  Gateway;\r
+  UINT32                    Index;\r
+\r
+  IpConfig = &NicConfig->Ip4Info;\r
+\r
+  if (NicConfig->Source == IP4_CONFIG_SOURCE_STATIC) {\r
+    //\r
+    // Validate that the addresses are unicast and mask\r
+    // is properly formated\r
+    //\r
+    Station = EFI_NTOHL (IpConfig->StationAddress);\r
+    Netmask = EFI_NTOHL (IpConfig->SubnetMask);\r
+\r
+    if ((Netmask == 0) || !IP4_IS_VALID_NETMASK (Netmask) ||\r
+        (Station == 0) || !Ip4IsUnicast (Station, Netmask)) {\r
+      return FALSE;\r
+    }\r
+\r
+    //\r
+    // Validate that the next hops are on the connected network\r
+    // or that is a direct route (Gateway == 0).\r
+    //\r
+    for (Index = 0; Index < IpConfig->RouteTableSize; Index++) {\r
+      Gateway = EFI_NTOHL (IpConfig->RouteTable[Index].GatewayAddress);\r
+\r
+      if ((Gateway != 0) && (!IP4_NET_EQUAL (Station, Gateway, Netmask) ||\r
+          !Ip4IsUnicast (Gateway, Netmask))) {\r
+        return FALSE;\r
+      }\r
+    }\r
+\r
+    return TRUE;\r
+  }\r
+\r
+  //\r
+  // return false if it is an unkown configure source. Valid\r
+  // sources are static and dhcp.\r
+  //\r
+  return (BOOLEAN) (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP);\r
+}\r
+\r
+\r
+\r
+/**\r
+  Read the ip4 configure variable from the EFI variable\r
+\r
+  None\r
+\r
+  @return The IP4 configure read if it is there and is valid, otherwise NULL\r
+\r
+**/\r
+IP4_CONFIG_VARIABLE *\r
+Ip4ConfigReadVariable (\r
+  VOID\r
+  )\r
+{\r
+  IP4_CONFIG_VARIABLE       *Variable;\r
+  EFI_STATUS                Status;\r
+  UINTN                     Size;\r
+  UINT16                    CheckSum;\r
+\r
+  //\r
+  // Get the size of variable, then allocate a buffer to read the variable.\r
+  //\r
+  Size     = 0;\r
+  Variable = NULL;\r
+  Status   = gRT->GetVariable (\r
+                    EFI_NIC_IP4_CONFIG_VARIABLE,\r
+                    &gEfiNicIp4ConfigVariableGuid,\r
+                    NULL,\r
+                    &Size,\r
+                    NULL\r
+                    );\r
+\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    return NULL;\r
+  }\r
+\r
+  if (Size < sizeof (IP4_CONFIG_VARIABLE)) {\r
+    goto REMOVE_VARIABLE;\r
+  }\r
+\r
+  Variable = NetAllocatePool (Size);\r
+\r
+  if (Variable == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Status = gRT->GetVariable (\r
+                  EFI_NIC_IP4_CONFIG_VARIABLE,\r
+                  &gEfiNicIp4ConfigVariableGuid,\r
+                  NULL,\r
+                  &Size,\r
+                  Variable\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  //\r
+  // Verify the checksum, variable size and count\r
+  //\r
+  CheckSum = ~NetblockChecksum ((UINT8 *) Variable, (UINT32)Size);\r
+\r
+  if ((CheckSum != 0) || (Size != Variable->Len)) {\r
+    goto REMOVE_VARIABLE;\r
+  }\r
+\r
+  if ((Variable->Count < 1) || (Variable->Count > MAX_IP4_CONFIG_IN_VARIABLE)) {\r
+    goto REMOVE_VARIABLE;\r
+  }\r
+\r
+  return Variable;\r
+\r
+REMOVE_VARIABLE:\r
+  Ip4ConfigWriteVariable (NULL);\r
+\r
+ON_ERROR:\r
+  if (Variable != NULL) {\r
+    NetFreePool (Variable);\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  Write the IP4 configure variable to the NVRAM. If Config\r
+  is NULL, remove the variable.\r
+\r
+  @param  Config       The IP4 configure data to write\r
+\r
+  @retval EFI_SUCCESS  The variable is written to the NVRam\r
+  @retval Others       Failed to write the variable.\r
+\r
+**/\r
+EFI_STATUS\r
+Ip4ConfigWriteVariable (\r
+  IN IP4_CONFIG_VARIABLE    * Config        OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  Status = gRT->SetVariable (\r
+                  EFI_NIC_IP4_CONFIG_VARIABLE,\r
+                  &gEfiNicIp4ConfigVariableGuid,\r
+                  IP4_CONFIG_VARIABLE_ATTRIBUTES,\r
+                  (Config == NULL) ? 0 : Config->Len,\r
+                  Config\r
+                  );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Locate the IP4 configure parameters from the variable.If a\r
+  configuration is found, copy it to a newly allocated block\r
+  of memory to avoid the alignment problem. Caller should\r
+  release the memory after use.\r
+\r
+  @param  Variable     The IP4 configure variable to search in\r
+  @param  NicAddr      The interface address to check\r
+\r
+  @return The point to the NIC's IP4 configure info if it is found\r
+  @return in the IP4 variable, otherwise NULL.\r
+\r
+**/\r
+NIC_IP4_CONFIG_INFO *\r
+Ip4ConfigFindNicVariable (\r
+  IN IP4_CONFIG_VARIABLE    *Variable,\r
+  IN NIC_ADDR               *NicAddr\r
+  )\r
+{\r
+  NIC_IP4_CONFIG_INFO       Temp;\r
+  NIC_IP4_CONFIG_INFO       *Config;\r
+  UINT32                    Index;\r
+  UINT8                     *Cur;\r
+  UINT32                    Len;\r
+\r
+  Cur = (UINT8*)&Variable->ConfigInfo;\r
+\r
+  for (Index = 0; Index < Variable->Count; Index++) {\r
+    //\r
+    // Copy the data to Temp to avoid the alignment problems\r
+    //\r
+    NetCopyMem (&Temp, Cur, sizeof (NIC_IP4_CONFIG_INFO));\r
+    Len = SIZEOF_NIC_IP4_CONFIG_INFO (&Temp);\r
+\r
+    //\r
+    // Found the matching configuration parameters, allocate\r
+    // a block of memory then copy it out.\r
+    //\r
+    if (NIC_ADDR_EQUAL (&Temp.NicAddr, NicAddr)) {\r
+      Config = NetAllocatePool (Len);\r
+\r
+      if (Config == NULL) {\r
+        return NULL;\r
+      }\r
+\r
+      NetCopyMem (Config, Cur, Len);\r
+      return Config;\r
+    }\r
+\r
+    Cur += Len;\r
+  }\r
+\r
+  return NULL;\r
+}\r
+\r
+\r
+/**\r
+  Modify the configuration parameter for the NIC in the variable.\r
+  If Config is NULL, old configuration will be remove from the new\r
+  variable. Otherwise, append it or replace the old one.\r
+\r
+  @param  Variable     The IP4 variable to change\r
+  @param  NicAddr      The interface to search\r
+  @param  Config       The new configuration parameter (NULL to remove the old)\r
+\r
+  @return The new IP4_CONFIG_VARIABLE variable if the new variable has at\r
+  @return least one NIC configure and no EFI_OUT_OF_RESOURCES failure.\r
+  @return Return NULL either because failed to locate memory for new variable\r
+  @return or the only NIC configure is removed from the Variable.\r
+\r
+**/\r
+IP4_CONFIG_VARIABLE *\r
+Ip4ConfigModifyVariable (\r
+  IN IP4_CONFIG_VARIABLE    *Variable,    OPTIONAL\r
+  IN NIC_ADDR               *NicAddr,\r
+  IN NIC_IP4_CONFIG_INFO    *Config       OPTIONAL\r
+  )\r
+{\r
+  NIC_IP4_CONFIG_INFO       Temp;\r
+  NIC_IP4_CONFIG_INFO       *Old;\r
+  IP4_CONFIG_VARIABLE       *NewVar;\r
+  UINT32                    Len;\r
+  UINT32                    TotalLen;\r
+  UINT32                    Count;\r
+  UINT8                     *Next;\r
+  UINT8                     *Cur;\r
+  UINT32                    Index;\r
+\r
+  ASSERT ((Variable != NULL) || (Config != NULL));\r
+\r
+  //\r
+  // Compute the total length\r
+  //\r
+  if (Variable != NULL) {\r
+    //\r
+    // Variable != NULL, then Config can be NULL or not.  and so is\r
+    // the Old. If old configure exists, it is removed from the\r
+    // Variable. New configure is append to the variable.\r
+    //\r
+    //\r
+    Count     = Variable->Count;\r
+    Cur       = (UINT8 *)&Variable->ConfigInfo;\r
+    TotalLen  = Variable->Len;\r
+\r
+    Old       = Ip4ConfigFindNicVariable (Variable, NicAddr);\r
+\r
+    if (Old != NULL) {\r
+      TotalLen -= SIZEOF_NIC_IP4_CONFIG_INFO (Old);\r
+      NetFreePool (Old);\r
+    }\r
+\r
+    if (Config != NULL) {\r
+      TotalLen += SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
+    }\r
+\r
+    //\r
+    // Return NULL if the only NIC_IP4_CONFIG_INFO is being removed.\r
+    //\r
+    if (TotalLen < sizeof (IP4_CONFIG_VARIABLE)) {\r
+      return NULL;\r
+    }\r
+\r
+  } else {\r
+    //\r
+    // Variable == NULL and Config != NULL, Create a new variable with\r
+    // this NIC configure.\r
+    //\r
+    Count     = 0;\r
+    Cur       = NULL;\r
+    TotalLen  = sizeof (IP4_CONFIG_VARIABLE) - sizeof (NIC_IP4_CONFIG_INFO)\r
+                + SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
+  }\r
+\r
+  ASSERT (TotalLen >= sizeof (IP4_CONFIG_VARIABLE));\r
+\r
+  NewVar = NetAllocateZeroPool (TotalLen);\r
+\r
+  if (NewVar == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  NewVar->Len = TotalLen;\r
+\r
+  //\r
+  // Copy the other configure parameters from the old variable\r
+  //\r
+  Next = (UINT8 *)&NewVar->ConfigInfo;\r
+\r
+  for (Index = 0; Index < Count; Index++) {\r
+    NetCopyMem (&Temp, Cur, sizeof (NIC_IP4_CONFIG_INFO));\r
+    Len = SIZEOF_NIC_IP4_CONFIG_INFO (&Temp);\r
+\r
+    if (!NIC_ADDR_EQUAL (&Temp.NicAddr, NicAddr)) {\r
+      NetCopyMem (Next, Cur, Len);\r
+      Next += Len;\r
+      NewVar->Count++;\r
+    }\r
+\r
+    Cur += Len;\r
+  }\r
+\r
+  //\r
+  // Append the new configure if it isn't NULL.\r
+  //\r
+  Len = 0;\r
+\r
+  if (Config != NULL) {\r
+    Len = SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
+\r
+    NetCopyMem (Next, Config, Len);\r
+    NewVar->Count++;\r
+  }\r
+\r
+  ASSERT (Next + Len == (UINT8 *) NewVar + TotalLen);\r
+\r
+  NewVar->CheckSum = ~NetblockChecksum ((UINT8 *) NewVar, TotalLen);\r
+  return NewVar;\r
+}\r
diff --git a/MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.h b/MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.h
new file mode 100644 (file)
index 0000000..74d1660
--- /dev/null
@@ -0,0 +1,75 @@
+/** @file
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+  NicIp4Variable.h
+
+Abstract:
+
+  Routines used to operate the Ip4 configure variable
+
+
+**/
+
+#ifndef _NIC_IP4_VARIABLE_H_
+#define _NIC_IP4_VARIABLE_H_
+
+
+#include <Protocol/NicIp4Config.h>
+
+//
+// Return the size of NIC_IP4_CONFIG_INFO and EFI_IP4_IPCONFIG_DATA.
+// They are of variable size
+//
+#define SIZEOF_IP4_CONFIG_INFO(Ip4Config) \
+  (sizeof (EFI_IP4_IPCONFIG_DATA) + \
+   sizeof (EFI_IP4_ROUTE_TABLE) * (NET_MAX (1, (Ip4Config)->RouteTableSize) - 1))
+
+#define SIZEOF_NIC_IP4_CONFIG_INFO(NicConfig) \
+  (sizeof (NIC_IP4_CONFIG_INFO) + \
+   sizeof (EFI_IP4_ROUTE_TABLE) * (NET_MAX (1, (NicConfig)->Ip4Info.RouteTableSize) - 1))
+
+//
+// Compare whether two NIC address are equal includes their type and length.
+//
+#define NIC_ADDR_EQUAL(Nic1, Nic2) \
+  (((Nic1)->Type == (Nic2)->Type) && ((Nic1)->Len == (Nic2)->Len) && \
+   NET_MAC_EQUAL (&(Nic1)->MacAddr, &(Nic2)->MacAddr, (Nic1)->Len))
+
+BOOLEAN
+Ip4ConfigIsValid (
+  IN NIC_IP4_CONFIG_INFO    *NicConfig
+  );
+
+IP4_CONFIG_VARIABLE *
+Ip4ConfigReadVariable (
+  VOID
+  );
+
+EFI_STATUS
+Ip4ConfigWriteVariable (
+  IN IP4_CONFIG_VARIABLE    *Config       OPTIONAL
+  );
+
+NIC_IP4_CONFIG_INFO *
+Ip4ConfigFindNicVariable (
+  IN IP4_CONFIG_VARIABLE    *Variable,
+  IN NIC_ADDR               *NicAddr
+  );
+
+IP4_CONFIG_VARIABLE *
+Ip4ConfigModifyVariable (
+  IN IP4_CONFIG_VARIABLE    *Variable,    OPTIONAL
+  IN NIC_ADDR               *NicAddr,
+  IN NIC_IP4_CONFIG_INFO    *Config       OPTIONAL
+  );
+#endif