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