From b2570da8b7d2154b2d1344f2eb25acac9e6b6578 Mon Sep 17 00:00:00 2001 From: vanjeff Date: Mon, 23 Jul 2007 09:18:27 +0000 Subject: [PATCH] Import Ip4Config module git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3406 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Network/Ip4ConfigDxe/ComponentName.c | 157 ++++ .../Network/Ip4ConfigDxe/Ip4Config.c | 755 ++++++++++++++++++ .../Network/Ip4ConfigDxe/Ip4Config.h | 132 +++ .../Network/Ip4ConfigDxe/Ip4ConfigDriver.c | 529 ++++++++++++ .../Network/Ip4ConfigDxe/Ip4ConfigDxe.inf | 64 ++ .../Network/Ip4ConfigDxe/Ip4ConfigDxe.msa | 77 ++ .../Network/Ip4ConfigDxe/NicIp4Variable.c | 383 +++++++++ .../Network/Ip4ConfigDxe/NicIp4Variable.h | 75 ++ 8 files changed, 2172 insertions(+) create mode 100644 MdeModulePkg/Universal/Network/Ip4ConfigDxe/ComponentName.c create mode 100644 MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c create mode 100644 MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.h create mode 100644 MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDriver.c create mode 100644 MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf create mode 100644 MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.msa create mode 100644 MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.c create mode 100644 MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.h 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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 @@ + + + Ip4Config + DXE_DRIVER + 26841BDE-920A-4e7a-9FBE-637F477143A6 + 1.0 + 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. + FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052 + + + IA32 X64 IPF EBC + false + Ip4Config + + + + DebugLib + + + UefiRuntimeServicesTableLib + + + UefiDriverEntryPoint + + + UefiBootServicesTableLib + + + UefiLib + + + + Ip4Config.c + NicIp4Variable.h + Ip4Config.h + Ip4ConfigDriver.c + NicIp4Variable.c + ComponentName.c + + + + + + + + gEfiDhcp4ProtocolGuid + + + gEfiManagedNetworkProtocolGuid + + + gEfiIp4ConfigProtocolGuid + + + gEfiManagedNetworkServiceBindingProtocolGuid + + + gEfiDhcp4ServiceBindingProtocolGuid + + + + EFI_SPECIFICATION_VERSION 0x00020000 + EDK_RELEASE_VERSION 0x00020000 + + Ip4ConfigDriverEntryPoint + + + \ 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 +#include +#include +#include +#include +#include + +#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 + +// +// 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