From 68fb05272b45b473fe030ac11dcb79d3f3c0aecd Mon Sep 17 00:00:00 2001 From: jcarsey Date: Fri, 25 Mar 2011 20:47:02 +0000 Subject: Add Network1 profile. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11423 6f19259b-4bc3-4df7-8a09-765794883524 --- .../UefiShellNetwork1CommandsLib/Ifconfig.c | 1746 ++++++++++++++++++++ 1 file changed, 1746 insertions(+) create mode 100644 ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c (limited to 'ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c') diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c new file mode 100644 index 0000000000..2e8a09fc33 --- /dev/null +++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c @@ -0,0 +1,1746 @@ +/** @file + The implementation for ifcommand shell command. + + Copyright (c) 2006 - 2011, 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. +**/ + +#include "UefiShellNetwork1CommandsLib.h" + +#define NIC_ITEM_CONFIG_SIZE (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE) +#define EFI_IP4_TO_U32(EfiIpAddr) (*(IP4_ADDR*)((EfiIpAddr).Addr)) + +BOOLEAN mIp4ConfigExist = FALSE; +STATIC EFI_HII_CONFIG_ROUTING_PROTOCOL *mHiiConfigRouting = NULL; + +STATIC CONST UINTN SEC_TO_NS = 10000000; +STATIC CONST CHAR16 DhcpString[5] = L"DHCP"; +STATIC CONST CHAR16 StaticString[7] = L"STATIC"; +STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT"; + +typedef struct { + LIST_ENTRY Link; + EFI_HANDLE Handle; + NIC_ADDR NicAddress; + CHAR16 Name[IP4_NIC_NAME_LENGTH]; + BOOLEAN MediaPresentSupported; + BOOLEAN MediaPresent; + EFI_IP4_CONFIG_PROTOCOL *Ip4Config; + NIC_IP4_CONFIG_INFO *ConfigInfo; +} NIC_INFO; + +typedef struct { + EFI_IP_ADDRESS DestIp; + EFI_MAC_ADDRESS DestMac; + EFI_IP_ADDRESS LocalIp; + EFI_MAC_ADDRESS LocalMac; + UINT8 MacLen; + EFI_EVENT OnResolved; + BOOLEAN Duplicate; +} ARP_REQUEST; + +STATIC CONST SHELL_PARAM_ITEM ParamList[] = { + {L"-c", TypeValue}, + {L"-l", TypeValue}, + {L"-s", TypeMaxValue}, + {NULL, TypeMax} + }; + +STATIC LIST_ENTRY NicInfoList; +STATIC BOOLEAN ArpResolved; +STATIC BOOLEAN mTimeout; + +/** + Count the space delimited items in a string. + + @param[in] String A pointer to the string to count. + + @return The number of space-delimited items. + @retval 0xFF an error occured. +**/ +UINT8 +EFIAPI +CountSubItems ( + IN CONST CHAR16 *String + ) +{ + CONST CHAR16 *Walker; + UINT8 Count; + + if (String == NULL || *String == CHAR_NULL) { + return (0xFF); + } + + for (Walker = String, Count = 0 ; Walker != NULL && *Walker != CHAR_NULL ; Walker = (StrStr(Walker, L" ")==NULL?NULL:StrStr(Walker, L" ")+1), Count++); + return (Count); +} + +/** + Find the NIC_INFO by the specified nic name. + + @param[in] Name The pointer to the string containing the NIC name. + + @return The pointer to the NIC_INFO if there is a NIC_INFO named by Name. + @retval NULL No NIC_INFO was found for Name. +**/ +NIC_INFO* +EFIAPI +IfconfigFindNicByName ( + IN CONST CHAR16 *Name + ) +{ + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + NIC_INFO *Info; + CHAR16 *TempString; + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) { + Info = BASE_CR (Entry, NIC_INFO, Link); + TempString = (CHAR16*)Info->Name; + + if (StringNoCaseCompare (&Name, &TempString) == 0) { + return Info; + } + } + + return NULL; +} + +/** + Tests whether a child handle is a child device of the controller. + + @param[in] ControllerHandle A handle for a (parent) controller to test. + @param[in] ChildHandle A child handle to test. + @param[in] ProtocolGuid Supplies the protocol that the child controller + opens on its parent controller. + + @retval EFI_SUCCESS ChildHandle is a child of the ControllerHandle. + @retval EFI_UNSUPPORTED ChildHandle is not a child of the ControllerHandle. +**/ +EFI_STATUS +EFIAPI +TestChildHandle ( + IN CONST EFI_HANDLE ControllerHandle, + IN CONST EFI_HANDLE ChildHandle, + IN CONST EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; + + ASSERT (ProtocolGuid != NULL); + + // + // Retrieve the list of agents that are consuming the specific protocol + // on ControllerHandle. + // + Status = gBS->OpenProtocolInformation ( + ControllerHandle, + (EFI_GUID *) ProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Inspect if ChildHandle is one of the agents. + // + Status = EFI_UNSUPPORTED; + for (Index = 0; Index < EntryCount; Index++) { + if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) && + (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + Status = EFI_SUCCESS; + break; + } + } + + FreePool (OpenInfoBuffer); + return Status; +} + +/** + Get the child handle of the NIC handle. + + @param[in] Controller Routing information: GUID. + @param[in] ChildHandle Returned child handle. + + @retval EFI_SUCCESS Successfully to get child handle. +**/ +EFI_STATUS +GetChildHandle ( + IN EFI_HANDLE Controller, + OUT EFI_HANDLE *ChildHandle + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN HandleCount; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *ChildDeviceDevicePath; + VENDOR_DEVICE_PATH *VendorDeviceNode; + + // + // Locate all EFI Hii Config Access protocols + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiHiiConfigAccessProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + if (EFI_ERROR (Status) || (HandleCount == 0)) { + return Status; + } + + Status = EFI_NOT_FOUND; + + for (Index = 0; Index < HandleCount; Index++) { + + Status = TestChildHandle (Controller, Handles[Index], &gEfiManagedNetworkServiceBindingProtocolGuid); + if (!EFI_ERROR (Status)) { + // + // Get device path on the child handle + // + Status = gBS->HandleProtocol ( + Handles[Index], + &gEfiDevicePathProtocolGuid, + (VOID **) &ChildDeviceDevicePath + ); + + if (!EFI_ERROR (Status)) { + while (!IsDevicePathEnd (ChildDeviceDevicePath)) { + ChildDeviceDevicePath = NextDevicePathNode (ChildDeviceDevicePath); + // + // Parse one instance + // + if (ChildDeviceDevicePath->Type == HARDWARE_DEVICE_PATH && + ChildDeviceDevicePath->SubType == HW_VENDOR_DP) { + VendorDeviceNode = (VENDOR_DEVICE_PATH *) ChildDeviceDevicePath; + if (CompareMem (&VendorDeviceNode->Guid, &gEfiNicIp4ConfigVariableGuid, sizeof (EFI_GUID)) == 0) { + // + // Found item matched gEfiNicIp4ConfigVariableGuid + // + *ChildHandle = Handles[Index]; + FreePool (Handles); + return EFI_SUCCESS; + } + } + } + } + } + } + + FreePool (Handles); + return Status; +} + +/** + Append OFFSET/WIDTH/VALUE items at the beginning of string. + + @param[in,out] String The pointer to the string to append onto. + @param[in] Offset Offset value. + @param[in] Width Width value. + @param[in] Block Point to data buffer. + + @return The count of unicode character that were appended. +**/ +UINTN +EFIAPI +AppendOffsetWidthValue ( + IN OUT CHAR16 *String, + IN UINTN Offset, + IN UINTN Width, + IN CONST UINT8 *Block + ) + +{ + CHAR16 *OriString; + + OriString = String; + + StrCpy (String, L"&OFFSET="); + String += StrLen (L"&OFFSET="); + String += UnicodeSPrint (String, 20, L"%x", Offset); + + StrCpy (String,L"&WIDTH="); + String += StrLen (L"&WIDTH="); + String += UnicodeSPrint (String, 20, L"%x", Width); + + if (Block != NULL) { + StrCpy (String,L"&VALUE="); + String += StrLen (L"&VALUE="); + while ((Width--) != 0) { + String += UnicodeSPrint (String, 20, L"%x", Block[Width]); + } + } + + return String - OriString; +} + +/** + Converts the unicode character of the string from uppercase to lowercase. + This is a internal function. + + @param ConfigString String to be converted +**/ +CHAR16* +EFIAPI +HiiToLower ( + IN CHAR16 *ConfigString + ) +{ + CHAR16 *String; + BOOLEAN Lower; + + // + // Convert all hex digits in range [A-F] in the configuration header to [a-f] + // + for (String = ConfigString, Lower = FALSE; String != NULL && *String != L'\0'; String++) { + if (*String == L'=') { + Lower = TRUE; + } else if (*String == L'&') { + Lower = FALSE; + } else if (Lower && *String >= L'A' && *String <= L'F') { + *String = (CHAR16) (*String - L'A' + L'a'); + } + } + + return (ConfigString); +} + + +/** + Construct using routing information GUID/NAME/PATH. + + @param[in] Guid Routing information: GUID. + @param[in] Name Routing information: NAME. + @param[in] DriverHandle Driver handle which contains the routing information: PATH. + + @retval NULL An error occured. + @return The pointer to configHdr string. +**/ +CHAR16 * +EFIAPI +ConstructConfigHdr ( + IN CONST EFI_GUID *Guid, + IN CONST CHAR16 *Name, + IN EFI_HANDLE DriverHandle + ) +{ + EFI_STATUS Status; + CHAR16 *ConfigHdr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + CHAR16 *String; + UINTN Index; + UINT8 *Buffer; + UINTN DevicePathLength; + UINTN NameLength; + + // + // Get the device path from handle installed EFI HII Config Access protocol + // + Status = gBS->HandleProtocol ( + DriverHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + DevicePathLength = GetDevicePathSize (DevicePath); + NameLength = StrLen (Name); + ConfigHdr = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathLength * 2 + 1) * sizeof (CHAR16)); + if (ConfigHdr == NULL) { + return NULL; + } + + String = ConfigHdr; + StrCpy (String, L"GUID="); + String += StrLen (L"GUID="); + + // + // Append Guid converted to 32 + // + for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) { + String += UnicodeSPrint (String, 6, L"%02x", *Buffer++); + } + + // + // Append L"&NAME=" + // + StrCpy (String, L"&NAME="); + String += StrLen (L"&NAME="); + for (Index = 0; Index < NameLength ; Index++) { + String += UnicodeSPrint (String, 10, L"00%x", Name[Index]); + } + + // + // Append L"&PATH=" + // + StrCpy (String, L"&PATH="); + String += StrLen (L"&PATH="); + for (Index = 0, Buffer = (UINT8 *) DevicePath; Index < DevicePathLength; Index++) { + String += UnicodeSPrint (String, 6, L"%02x", *Buffer++); + } + + return (HiiToLower(ConfigHdr)); +} + +/** + Get network physical device NIC information. + + @param[in] Handle The network physical device handle. + @param[out] NicAddr NIC information. + + @retval EFI_SUCCESS Get NIC information successfully. +**/ +EFI_STATUS +EFIAPI +IfConfigGetNicMacInfo ( + IN EFI_HANDLE Handle, + OUT NIC_ADDR *NicAddr + ) +{ + EFI_STATUS Status; + EFI_HANDLE MnpHandle; + EFI_SIMPLE_NETWORK_MODE SnpMode; + EFI_MANAGED_NETWORK_PROTOCOL *Mnp; + + MnpHandle = NULL; + Mnp = NULL; + + Status = NetLibCreateServiceChild ( + Handle, + gImageHandle, + &gEfiManagedNetworkServiceBindingProtocolGuid, + &MnpHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->HandleProtocol ( + MnpHandle, + &gEfiManagedNetworkProtocolGuid, + (VOID **) &Mnp + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + Status = Mnp->GetModeData (Mnp, NULL, &SnpMode); + if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) { + goto ON_ERROR; + } + + NicAddr->Type = (UINT16) SnpMode.IfType; + NicAddr->Len = (UINT8) SnpMode.HwAddressSize; + CopyMem (&NicAddr->MacAddr, &SnpMode.CurrentAddress, NicAddr->Len); + +ON_ERROR: + + NetLibDestroyServiceChild ( + Handle, + gImageHandle, + &gEfiManagedNetworkServiceBindingProtocolGuid, + MnpHandle + ); + + return Status; + +} + +/** + Get network physical device NIC information. + + @param[in] Handle The network physical device handle. + @param[out] MediaPresentSupported + Upon successful return, TRUE is media present + is supported. FALSE otherwise. + @param[out] MediaPresent Upon successful return, TRUE is media present + is enabled. FALSE otherwise. + + @retval EFI_SUCCESS The operation was successful. +**/ +EFI_STATUS +EFIAPI +IfConfigGetNicMediaStatus ( + IN EFI_HANDLE Handle, + OUT BOOLEAN *MediaPresentSupported, + OUT BOOLEAN *MediaPresent + ) + +{ + EFI_STATUS Status; + EFI_HANDLE MnpHandle; + EFI_SIMPLE_NETWORK_MODE SnpMode; + EFI_MANAGED_NETWORK_PROTOCOL *Mnp; + + MnpHandle = NULL; + Mnp = NULL; + + Status = NetLibCreateServiceChild ( + Handle, + gImageHandle, + &gEfiManagedNetworkServiceBindingProtocolGuid, + &MnpHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->HandleProtocol ( + MnpHandle, + &gEfiManagedNetworkProtocolGuid, + (VOID **) &Mnp + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + Status = Mnp->GetModeData (Mnp, NULL, &SnpMode); + if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) { + goto ON_ERROR; + } + + *MediaPresentSupported = SnpMode.MediaPresentSupported; + *MediaPresent = SnpMode.MediaPresent; + +ON_ERROR: + + NetLibDestroyServiceChild ( + Handle, + gImageHandle, + &gEfiManagedNetworkServiceBindingProtocolGuid, + MnpHandle + ); + + return Status; + +} + +/** + Get all Nic's information through HII service. + + @retval EFI_SUCCESS All the nic information is collected. +**/ +EFI_STATUS +EFIAPI +IfconfigGetAllNicInfoByHii ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE *Handles; + UINTN HandleCount; + CHAR16 *ConfigResp; + CHAR16 *ConfigHdr; + UINTN Index; + CHAR16 *AccessProgress; + CHAR16 *AccessResults; + UINTN BufferSize; + NIC_INFO *NicInfo; + NIC_IP4_CONFIG_INFO *NicConfigRequest; + NIC_IP4_CONFIG_INFO *NicConfig; + CHAR16 *String; + UINTN Length; + UINTN Offset; + EFI_HANDLE ChildHandle; + + AccessResults = NULL; + ConfigHdr = NULL; + ConfigResp = NULL; + NicConfigRequest = NULL; + NicInfo = NULL; + + InitializeListHead (&NicInfoList); + + // + // Check if HII Config Routing protocol available. + // + Status = gBS->LocateProtocol ( + &gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID**)&mHiiConfigRouting + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Locate all network device handles + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiManagedNetworkServiceBindingProtocolGuid, + NULL, + &HandleCount, + &Handles + ); + if (EFI_ERROR (Status) || (HandleCount == 0)) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = GetChildHandle (Handles[Index], &ChildHandle); + if (EFI_ERROR (Status)) { + // + // If failed to get Child handle, try NIC controller handle for back-compatibility. + // + ChildHandle = Handles[Index]; + } + // + // Construct configuration request string header + // + ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle); + Length = StrLen (ConfigHdr); + ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16)); + if (ConfigResp == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + StrCpy (ConfigResp, ConfigHdr); + + // + // Append OFFSET/WIDTH pair + // + String = ConfigResp + Length; + Offset = 0; + AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL); + + NicInfo = AllocateZeroPool (sizeof (NIC_INFO)); + if (NicInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + NicInfo->Handle = Handles[Index]; + + // + // Get network physical devcie MAC information + // + IfConfigGetNicMacInfo (Handles[Index], &NicInfo->NicAddress); + if (NicInfo->NicAddress.Type == NET_IFTYPE_ETHERNET) { + UnicodeSPrint (NicInfo->Name, IP4_NIC_NAME_LENGTH, L"eth%d", Index); + } else { + UnicodeSPrint (NicInfo->Name, IP4_NIC_NAME_LENGTH, L"unk%d", Index); + } + + // + // Get media status + // + IfConfigGetNicMediaStatus (Handles[Index], &NicInfo->MediaPresentSupported, &NicInfo->MediaPresent); + + NicConfigRequest = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE); + if (NicConfigRequest == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + + // + // Get network parameters by HII service + // + Status = mHiiConfigRouting->ExtractConfig ( + mHiiConfigRouting, + ConfigResp, + &AccessProgress, + &AccessResults + ); + if (!EFI_ERROR (Status)) { + BufferSize = NIC_ITEM_CONFIG_SIZE; + Status = mHiiConfigRouting->ConfigToBlock ( + mHiiConfigRouting, + AccessResults, + (UINT8 *) NicConfigRequest, + &BufferSize, + &AccessProgress + ); + if (!EFI_ERROR (Status)) { + BufferSize = sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * NicConfigRequest->Ip4Info.RouteTableSize; + NicConfig = AllocateZeroPool (BufferSize); + if (NicConfig == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_ERROR; + } + CopyMem (NicConfig, NicConfigRequest, BufferSize); + + // + // If succeeds to get NIC configuration, fix up routetable pointer. + // + NicConfig->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (&NicConfig->Ip4Info + 1); + NicInfo->ConfigInfo = NicConfig; + + } else { + NicInfo->ConfigInfo = NULL; + } + + FreePool (AccessResults); + + } else { + NicInfo->ConfigInfo = NULL; + } + + // + // Add the Nic's info to the global NicInfoList. + // + InsertTailList (&NicInfoList, &NicInfo->Link); + + FreePool (NicConfigRequest); + FreePool (ConfigResp); + FreePool (ConfigHdr); + } + + FreePool (Handles); + + return EFI_SUCCESS; + +ON_ERROR: + if (AccessResults != NULL) { + FreePool (AccessResults); + } + if (NicConfigRequest != NULL) { + FreePool (NicConfigRequest); + } + if (NicInfo != NULL) { + FreePool (NicInfo); + } + if (ConfigResp != NULL) { + FreePool (ConfigResp); + } + if (ConfigHdr != NULL) { + FreePool (ConfigHdr); + } + + FreePool (Handles); + + return Status; +} + +/** + Set the address for the specified nic by HII service. + + @param[in] NicInfo A pointer to the NIC_INFO of the Nic to be configured. + @param[in] Config The command line arguments for the set operation. + + @retval EFI_SUCCESS The address set operation is done. +**/ +SHELL_STATUS +EFIAPI +IfconfigSetNicAddrByHii ( + IN CONST NIC_INFO *NicInfo, + IN CONST NIC_IP4_CONFIG_INFO *Config + ) +{ + EFI_STATUS Status; + SHELL_STATUS ShellStatus; + NIC_IP4_CONFIG_INFO *NicConfig; + CHAR16 *ConfigResp; + CHAR16 *ConfigHdr; + CHAR16 *AccessProgress; + CHAR16 *AccessResults; + CHAR16 *String; + UINTN Length; + UINTN Offset; + EFI_HANDLE ChildHandle; + + AccessResults = NULL; + ConfigHdr = NULL; + ConfigResp = NULL; + NicConfig = NULL; + ShellStatus = SHELL_SUCCESS; + + Status = GetChildHandle (NicInfo->Handle, &ChildHandle); + if (EFI_ERROR (Status)) { + // + // If failed to get Child handle, try NIC controller handle for back-compatibility + // + ChildHandle = NicInfo->Handle; + } + // + // Construct config request string header + // + ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle); + + Length = StrLen (ConfigHdr); + ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16)); + StrCpy (ConfigResp, ConfigHdr); + + NicConfig = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE); + if (NicConfig == NULL) { + ShellStatus = SHELL_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + if (Config != NULL) { + CopyMem (NicConfig, Config, sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * Config->Ip4Info.RouteTableSize); + } + + // + // Append OFFSET/WIDTH pair + // + String = ConfigResp + Length; + Offset = 0; + AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL); + + // + // Call HII helper function to generate configuration string + // + Status = mHiiConfigRouting->BlockToConfig ( + mHiiConfigRouting, + ConfigResp, + (UINT8 *) NicConfig, + NIC_ITEM_CONFIG_SIZE, + &AccessResults, + &AccessProgress + ); + if (EFI_ERROR (Status)) { + ShellStatus = SHELL_NOT_FOUND; + goto ON_EXIT; + } + + // + // Set IP setting by HII servie + // + Status = mHiiConfigRouting->RouteConfig ( + mHiiConfigRouting, + AccessResults, + &AccessProgress + ); + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + } + +ON_EXIT: + SHELL_FREE_NON_NULL(AccessResults); + SHELL_FREE_NON_NULL(NicConfig); + SHELL_FREE_NON_NULL(ConfigResp); + SHELL_FREE_NON_NULL(ConfigHdr); + + return ShellStatus; +} + +/** + The callback function for the Arp address resolved event. + + @param[in] Event The event this function is registered to. + @param[in] Context The context registered to the event. +**/ +VOID +EFIAPI +IfconfigOnArpResolved ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + ARP_REQUEST *Request; + UINT8 Index; + + Request = (ARP_REQUEST *) Context; + ASSERT (Request != NULL); + + Request->Duplicate = FALSE; + + if (0 == CompareMem (&Request->LocalMac, &Request->DestMac, Request->MacLen)) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Already Configured", + (UINTN)Request->DestIp.v4.Addr[0], + (UINTN)Request->DestIp.v4.Addr[1], + (UINTN)Request->DestIp.v4.Addr[2], + (UINTN)Request->DestIp.v4.Addr[3] + ); + ArpResolved = TRUE; + return; + } + + for (Index = 0; Index < Request->MacLen; Index++) { + if (Request->DestMac.Addr[Index] != 0) { + Request->Duplicate = TRUE; + } + } + + if (Request->Duplicate) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_IFCONFIG_CONF_IP_ADDR), + gShellNetwork1HiiHandle, + (UINTN)Request->DestMac.Addr[0], + (UINTN)Request->DestMac.Addr[1], + (UINTN)Request->DestMac.Addr[2], + (UINTN)Request->DestMac.Addr[3], + (UINTN)Request->DestMac.Addr[4], + (UINTN)Request->DestMac.Addr[5] + ); + } + + ArpResolved = TRUE; + return ; +} + +/** + Check whether the address to be configured conflicts with other hosts. + + @param[in] NicInfo The pointer to the NIC_INFO of the Nic to be configured. + @param[in] IpAddr The IPv4 address to be configured to the Nic. + + @return TRUE Some other host already uses the IpAddr. + @return FALSE The address is unused. +**/ +BOOLEAN +EFIAPI +IfconfigIsIpDuplicate ( + IN NIC_INFO *NicInfo, + IN IP4_ADDR IpAddr + ) +{ + EFI_ARP_PROTOCOL *Arp; + EFI_ARP_CONFIG_DATA ArpCfgData; + EFI_HANDLE ArpHandle; + ARP_REQUEST Request; + EFI_STATUS Status; + + Arp = NULL; + ArpHandle = NULL; + ZeroMem (&Request, sizeof (ARP_REQUEST)); + + Status = NetLibCreateServiceChild ( + NicInfo->Handle, + gImageHandle, + &gEfiArpServiceBindingProtocolGuid, + &ArpHandle + ); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + Status = gBS->OpenProtocol ( + ArpHandle, + &gEfiArpProtocolGuid, + (VOID**)&Arp, + gImageHandle, + ArpHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // Set up the Arp requests + // + EFI_IP4_TO_U32 (Request.DestIp.v4) = IpAddr; + EFI_IP4_TO_U32 (Request.LocalIp.v4) = 0xffffffff; + Request.LocalMac = NicInfo->NicAddress.MacAddr; + Request.MacLen = NicInfo->NicAddress.Len; + + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + IfconfigOnArpResolved, + (VOID *) &Request, + &Request.OnResolved + ); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + ArpCfgData.SwAddressType = 0x0800; + ArpCfgData.SwAddressLength = 4; + ArpCfgData.StationAddress = &Request.LocalIp; + ArpCfgData.EntryTimeOut = 0; + ArpCfgData.RetryCount = 3; + ArpCfgData.RetryTimeOut = 0; + + Status = Arp->Configure (Arp, &ArpCfgData); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = Arp->Request ( + Arp, + &Request.DestIp, + Request.OnResolved, + &Request.DestMac + ); + + if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) { + goto ON_EXIT; + } + + while (!ArpResolved) { + + } + +ON_EXIT: + if (Request.OnResolved != NULL) { + gBS->CloseEvent (Request.OnResolved); + } + + NetLibDestroyServiceChild ( + NicInfo->Handle, + gImageHandle, + &gEfiArpServiceBindingProtocolGuid, + ArpHandle + ); + + return Request.Duplicate; +} + +/** + The callback function for the timer event used to get map. + + @param[in] Event The event this function is registered to. + @param[in] Context The context registered to the event. +**/ +VOID +EFIAPI +TimeoutToGetMap ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mTimeout = TRUE; + return ; +} + +/** + Create an IP child, use it to start the auto configuration, then destory it. + + @param[in] NicInfo The pointer to the NIC_INFO of the Nic to be configured. + + @retval EFI_SUCCESS The configuration is done. +**/ +EFI_STATUS +EFIAPI +IfconfigStartIp4( + IN NIC_INFO *NicInfo + ) +{ + EFI_IP4_PROTOCOL *Ip4; + EFI_HANDLE Ip4Handle; + EFI_HANDLE TimerToGetMap; + EFI_IP4_CONFIG_DATA Ip4ConfigData; + EFI_IP4_MODE_DATA Ip4Mode; + EFI_STATUS Status; + + // + // Get the Ip4ServiceBinding Protocol + // + Ip4Handle = NULL; + Ip4 = NULL; + TimerToGetMap = NULL; + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_START_SET_ADDR), gShellNetwork1HiiHandle); + + Status = NetLibCreateServiceChild ( + NicInfo->Handle, + gImageHandle, + &gEfiIp4ServiceBindingProtocolGuid, + &Ip4Handle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Ip4Handle, + &gEfiIp4ProtocolGuid, + (VOID **) &Ip4, + NicInfo->Handle, + gImageHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Ip4ConfigData.DefaultProtocol = EFI_IP_PROTO_ICMP; + Ip4ConfigData.AcceptAnyProtocol = FALSE; + Ip4ConfigData.AcceptIcmpErrors = FALSE; + Ip4ConfigData.AcceptBroadcast = FALSE; + Ip4ConfigData.AcceptPromiscuous = FALSE; + Ip4ConfigData.UseDefaultAddress = TRUE; + ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS)); + ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); + Ip4ConfigData.TypeOfService = 0; + Ip4ConfigData.TimeToLive = 1; + Ip4ConfigData.DoNotFragment = FALSE; + Ip4ConfigData.RawData = FALSE; + Ip4ConfigData.ReceiveTimeout = 0; + Ip4ConfigData.TransmitTimeout = 0; + + Status = Ip4->Configure (Ip4, &Ip4ConfigData); + + if (Status == EFI_NO_MAPPING) { + mTimeout = FALSE; + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL | EVT_TIMER, + TPL_CALLBACK - 1, + TimeoutToGetMap, + NULL, + &TimerToGetMap + ); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = gBS->SetTimer ( + TimerToGetMap, + TimerRelative, + MultU64x32 (SEC_TO_NS, 5) + ); + + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_WAIT_SET_DONE), gShellNetwork1HiiHandle); + + while (!mTimeout) { + Ip4->Poll (Ip4); + + if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) && + Ip4Mode.IsConfigured) { + break; + } + } + } + + Status = Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL); + + if ((Status == EFI_SUCCESS) && Ip4Mode.IsConfigured) { + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Default", + (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[0], + (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[1], + (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[2], + (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[3] + ); + } + +ON_EXIT: + + if (EFI_ERROR (Status)) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_DEF_ADDR_FAIL), gShellNetwork1HiiHandle); + } + + if (TimerToGetMap != NULL) { + gBS->SetTimer (TimerToGetMap, TimerCancel, 0); + gBS->CloseEvent (TimerToGetMap); + } + + NetLibDestroyServiceChild ( + NicInfo->Handle, + gImageHandle, + &gEfiIp4ServiceBindingProtocolGuid, + Ip4Handle + ); + + return Status; +} + +/** + Set the address for the nic specified by the params. + + @param[in] Argc The count of the passed in Params. + @param[in] Params The command line arguments for the set operation. + + @retval EFI_SUCCESS The address set operation is done. + @return Some error occurs. +**/ +SHELL_STATUS +EFIAPI +IfconfigSetNicAddr ( + IN UINTN Argc, + IN CONST CHAR16 *Params + ) +{ + NIC_IP4_CONFIG_INFO *Config; + NIC_IP4_CONFIG_INFO *OldConfig; + EFI_IP_ADDRESS Ip; + EFI_IP_ADDRESS Mask; + EFI_IP_ADDRESS Gateway; + NIC_INFO *Info; + BOOLEAN Permanent; + SHELL_STATUS ShellStatus; + CONST CHAR16 *Walker; + CHAR16 *Temp; + CONST CHAR16 *DhcpTemp; + CONST CHAR16 *StaticTemp; + CONST CHAR16 *PermTemp; + UINT32 NetworkBytes1; + UINT32 NetworkBytes2; + EFI_STATUS Status; + + Walker = Params; + Temp = NULL; + Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker); + Info = IfconfigFindNicByName (Temp); + + if (Info == NULL) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_NOT_FOUND), gShellNetwork1HiiHandle, Temp); + return SHELL_NOT_FOUND; + } + + Walker += StrLen(Temp) + 1; + FreePool(Temp); + Temp = NULL; + Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")==NULL?0:StrStr(Walker, L" ")-Walker); + + Config = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE)); + if (Config == NULL) { + return SHELL_OUT_OF_RESOURCES; + } + + Config->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Config + 1); + + OldConfig = Info->ConfigInfo; + Permanent = FALSE; + ShellStatus = SHELL_INVALID_PARAMETER; + + DhcpTemp = DhcpString; + StaticTemp = StaticString; + + if (StringNoCaseCompare(&Temp, &DhcpTemp) == 0) { + // + // Validate the parameter for DHCP, two valid forms: eth0 DHCP and eth0 DHCP perment + // + if ((Argc != 2) && (Argc!= 3)) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + if (Argc == 3) { + Walker += StrLen(Temp) + 1; + FreePool(Temp); + Temp = NULL; + Temp = StrnCatGrow(&Temp, NULL, Walker, 0); + + PermTemp = PermanentString; + if (StringNoCaseCompare(&Temp, &PermTemp) != 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing"); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + Permanent = TRUE; + } + + if ((OldConfig != NULL) && (OldConfig->Source == IP4_CONFIG_SOURCE_DHCP) && + (OldConfig->Perment == Permanent)) { + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_CONFIGURED), gShellNetwork1HiiHandle, Info->Name); + ShellStatus = SHELL_ALREADY_STARTED; + goto ON_EXIT; + } + + Config->Source = IP4_CONFIG_SOURCE_DHCP; + } else if (StringNoCaseCompare(&Temp, &StaticTemp) == 0) { + // + // validate the parameter, two forms: eth0 static IP NETMASK GATEWAY and + // eth0 static IP NETMASK GATEWAY perment + // + if ((Argc != 5) && (Argc != 6)) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + Walker += StrLen(Temp) + 1; + FreePool(Temp); + Temp = NULL; + Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker); + + if (EFI_ERROR (NetLibStrToIp4 (Temp, &Ip.v4))) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + Walker += StrLen(Temp) + 1; + FreePool(Temp); + Temp = NULL; + Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker); + if (EFI_ERROR (NetLibStrToIp4 (Temp, &Mask.v4))) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + Walker += StrLen(Temp) + 1; + FreePool(Temp); + Temp = NULL; + if (Argc == 6) { + Temp = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker); + } else { + Temp = StrnCatGrow(&Temp, NULL, Walker, 0); + } + if (EFI_ERROR (NetLibStrToIp4 (Temp, &Gateway.v4))) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + if (Argc == 6) { + Walker += StrLen(Temp) + 1; + FreePool(Temp); + Temp = NULL; + Temp = StrnCatGrow(&Temp, NULL, Walker, 0); + + PermTemp = PermanentString; + if (StringNoCaseCompare(&Temp, &PermTemp) != 0) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing"); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + Permanent = TRUE; + } + + NetworkBytes1 = NTOHL (Ip.Addr[0]); + NetworkBytes2 = NTOHL (Mask.Addr[0]); + if ((Ip.Addr[0] == 0) || (Mask.Addr[0] == 0) || + !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) { + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_ADDR_PAIR), gShellNetwork1HiiHandle); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + NetworkBytes1 = NTOHL (Gateway.Addr[0]); + if (!IP4_NET_EQUAL (Ip.Addr[0], Gateway.Addr[0], Mask.Addr[0]) || + !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) { + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_GATEWAY), gShellNetwork1HiiHandle); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + // + // Set the configuration up, two route table entries are added: + // one for the direct connected network, and another for the + // default gateway. Remember, some structure members are cleared + // by AllocateZeroPool + // + Config->Source = IP4_CONFIG_SOURCE_STATIC; + Config->Ip4Info.RouteTableSize = 2; + + CopyMem (&Config->Ip4Info.StationAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Config->Ip4Info.SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS)); + + Ip.Addr[0] = Ip.Addr[0] & Mask.Addr[0]; + + CopyMem (&Config->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Config->Ip4Info.RouteTable[0].SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS)); + CopyMem (&Config->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS)); + } else { + // neither static or DHCP. error. + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle); + ASSERT(ShellStatus == SHELL_INVALID_PARAMETER); + goto ON_EXIT; + } + + CopyMem (&Config->NicAddr, &Info->NicAddress, sizeof (NIC_ADDR)); + Config->Perment = Permanent; + + // + // Use HII service to set NIC address + // + ShellStatus = IfconfigSetNicAddrByHii (Info, Config); + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_SET_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT); + goto ON_EXIT; + } + + Status = IfconfigStartIp4 (Info); + if (EFI_ERROR(Status)) { + ShellStatus = SHELL_ACCESS_DENIED; + } + + if (ShellStatus != SHELL_SUCCESS) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_IP_CHILD_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT); + } + +ON_EXIT: + SHELL_FREE_NON_NULL(Config); + + return ShellStatus; +} + +/** + Show the address information for the nic specified. + + @param[in] Name A pointer to the string containg the nic's name, if NULL, + all nics' information is shown. +**/ +VOID +EFIAPI +IfconfigShowNicInfo ( + IN CONST CHAR16 *Name + ) +{ + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + NIC_INFO *NicInfo; + UINT32 Index; + EFI_IP4_IPCONFIG_DATA *Ip4Config; + EFI_IPv4_ADDRESS Gateway; + CONST CHAR16 *TempString; + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) { + NicInfo = BASE_CR (Entry, NIC_INFO, Link); + + TempString = (CHAR16*)NicInfo->Name; + if ((Name != NULL) && (StringNoCaseCompare (&Name, &TempString) != 0)) { + continue; + } + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NAME), gShellNetwork1HiiHandle, NicInfo->Name); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN(STR_IFCONFIG_SHOW_MAC_ADDR), + gShellNetwork1HiiHandle, + (UINTN)NicInfo->NicAddress.MacAddr.Addr[0], + (UINTN)NicInfo->NicAddress.MacAddr.Addr[1], + (UINTN)NicInfo->NicAddress.MacAddr.Addr[2], + (UINTN)NicInfo->NicAddress.MacAddr.Addr[3], + (UINTN)NicInfo->NicAddress.MacAddr.Addr[4], + (UINTN)NicInfo->NicAddress.MacAddr.Addr[5] + ); + + Print (L" Media State: %s\n", NicInfo->MediaPresent ? L"Media present" : L"Media disconnected"); + + if (NicInfo->ConfigInfo == NULL) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NOT_CONFIGURED), gShellNetwork1HiiHandle); + continue; + } + + if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_DHCP) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"DHCP"); + } else if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"STATIC"); + } else { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"Unknown"); + } + + ShellPrintHiiEx(-1, -1, NULL, + STRING_TOKEN (STR_IFCONFIG_PERMENT_STATUS), + gShellNetwork1HiiHandle, + (NicInfo->ConfigInfo->Perment? L"TRUE":L"FALSE") + ); + + Ip4Config = &NicInfo->ConfigInfo->Ip4Info; + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"IP address", + (UINTN)Ip4Config->StationAddress.Addr[0], + (UINTN)Ip4Config->StationAddress.Addr[1], + (UINTN)Ip4Config->StationAddress.Addr[2], + (UINTN)Ip4Config->StationAddress.Addr[3] + ); + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Mask", + (UINTN)Ip4Config->SubnetMask.Addr[0], + (UINTN)Ip4Config->SubnetMask.Addr[1], + (UINTN)Ip4Config->SubnetMask.Addr[2], + (UINTN)Ip4Config->SubnetMask.Addr[3] + ); + + ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS)); + + for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) { + if ((CompareMem (&Ip4Config->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) && + (CompareMem (&Ip4Config->RouteTable[Index].SubnetMask , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){ + CopyMem (&Gateway, &Ip4Config->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS)); + } + } + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Gateway", + (UINTN)Gateway.Addr[0], + (UINTN)Gateway.Addr[1], + (UINTN)Gateway.Addr[2], + (UINTN)Gateway.Addr[3] + ); + + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, Ip4Config->RouteTableSize); + + for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Subnet", + (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[0], + (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[1], + (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[2], + (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[3] + ); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Netmask", + (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[0], + (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[1], + (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[2], + (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[3] + ); + + ShellPrintHiiEx( + -1, + -1, + NULL, + STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), + gShellNetwork1HiiHandle, + L"Gateway", + (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[0], + (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[1], + (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[2], + (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[3] + ); + } + } + + return ; +} + +/** + Clear address configuration for the nic specified. + + @param[in] Name A pointer to the string containg the nic's name, + if NULL, all nics address configurations are cleared. + + @retval EFI_SUCCESS The address configuration is cleared. + @return Some error occurs. +**/ +EFI_STATUS +EFIAPI +IfconfigClearNicAddr ( + IN CONST CHAR16 *Name + ) +{ + LIST_ENTRY *Entry; + LIST_ENTRY *NextEntry; + NIC_INFO *Info; + EFI_STATUS Status; + + NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) { + Info = BASE_CR (Entry, NIC_INFO, Link); + + if ((Name != NULL) && (StrCmp (Name, Info->Name) != 0)) { + continue; + } + +// if (Info->NicIp4Config == NULL) { + Status = IfconfigSetNicAddrByHii (Info, NULL); +// } else { +// Status = Info->NicIp4Config->SetInfo (Info->NicIp4Config, NULL, TRUE); +// } + + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; + +} + +/** + Function for 'ifconfig' command. + + @param[in] ImageHandle Handle to the Image (NULL if Internal). + @param[in] SystemTable Pointer to the System Table (NULL if Internal). +**/ +SHELL_STATUS +EFIAPI +ShellCommandRunIfconfig ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + LIST_ENTRY *Package; + CHAR16 *ProblemParam; + SHELL_STATUS ShellStatus; + BOOLEAN ListOperation; + BOOLEAN ClearOperation; + BOOLEAN SetOperation; + CONST CHAR16 *Item; + LIST_ENTRY *Entry; + NIC_INFO *Info; + + InitializeListHead (&NicInfoList); + Status = EFI_INVALID_PARAMETER; + ShellStatus = SHELL_SUCCESS; + + // + // initialize the shell lib (we must be in non-auto-init...) + // + Status = ShellInitialize(); + ASSERT_EFI_ERROR(Status); + + // + // parse the command line + // + Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE); + if (EFI_ERROR(Status)) { + if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ProblemParam); + FreePool(ProblemParam); + ShellStatus = SHELL_INVALID_PARAMETER; + } else { + ASSERT(FALSE); + } + + goto Done; + } + + ClearOperation = ShellCommandLineGetFlag(Package, L"-c"); + ListOperation = ShellCommandLineGetFlag(Package, L"-l"); + SetOperation = ShellCommandLineGetFlag(Package, L"-s"); + + if (ClearOperation && ListOperation + ||SetOperation && ListOperation + ||ClearOperation && SetOperation + ) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } else if (!ClearOperation && !ListOperation && !SetOperation) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + + Status = IfconfigGetAllNicInfoByHii (); + if (EFI_ERROR (Status)) { + if (mIp4ConfigExist) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_NIC_FAIL), gShellNetwork1HiiHandle, Status); + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellNetwork1HiiHandle, L"gEfiIp4ConfigProtocolGuid", &gEfiIp4ConfigProtocolGuid); + } + + return SHELL_NOT_FOUND; + } + + if (ListOperation) { + Item = ShellCommandLineGetValue (Package, L"-l"); + + if (Item != NULL && CountSubItems(Item) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-l"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + // + // Show the configuration. + // + IfconfigShowNicInfo (Item); + } else if (SetOperation) { + Item = ShellCommandLineGetValue (Package, L"-s"); + + // + // The correct command line arguments for setting address are: + // IfConfig -s eth0 DHCP [perment] + // IfConfig -s eth0 static ip netmask gateway [perment] + // + if (Item == NULL || (CountSubItems(Item) < 2) || (CountSubItems(Item) > 6) || (CountSubItems(Item) == 4)) { + ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-s"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + ShellStatus = IfconfigSetNicAddr (CountSubItems(Item), Item); + } else if (ClearOperation) { + Item = ShellCommandLineGetValue (Package, L"-c"); + + if (Item != NULL && CountSubItems(Item) > 1) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-c"); + ShellStatus = SHELL_INVALID_PARAMETER; + goto Done; + } + + IfconfigClearNicAddr (Item); + } else { + ASSERT(FALSE); + } + +Done: + while (!IsListEmpty (&NicInfoList)) { + Entry = NicInfoList.ForwardLink; + Info = BASE_CR (Entry, NIC_INFO, Link); + + RemoveEntryList (Entry); + + if (Info->ConfigInfo != NULL) { + FreePool (Info->ConfigInfo); + } + + FreePool (Info); + } + + if (Package != NULL) { + ShellCommandLineFreeVarList(Package); + } + + return (ShellStatus); +} -- cgit v1.2.3