| /** @file | |
| The implementation for ifcommand shell command. | |
| Copyright (c) 2013 Hewlett-Packard Development Company, L.P. | |
| Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> | |
| 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 SecondsToNanoSeconds = 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[out] 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 <ConfigHdr> 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 <HexCh>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); | |
| if (ConfigHdr != NULL) { | |
| Length = StrLen (ConfigHdr); | |
| } else { | |
| Length = 0; | |
| } | |
| ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16)); | |
| if (ConfigResp == NULL) { | |
| Status = EFI_OUT_OF_RESOURCES; | |
| goto ON_ERROR; | |
| } | |
| if (ConfigHdr != NULL) { | |
| 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); | |
| if (ConfigHdr != NULL) { | |
| Length = StrLen (ConfigHdr); | |
| } else { | |
| ShellStatus = SHELL_OUT_OF_RESOURCES; | |
| goto ON_EXIT; | |
| } | |
| ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16)); | |
| if (ConfigResp == NULL) { | |
| ShellStatus = SHELL_OUT_OF_RESOURCES; | |
| goto ON_EXIT; | |
| } | |
| if (ConfigHdr != NULL) { | |
| 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 destroy 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, | |
| TimeoutToGetMap, | |
| NULL, | |
| &TimerToGetMap | |
| ); | |
| if (EFI_ERROR (Status)) { | |
| goto ON_EXIT; | |
| } | |
| Status = gBS->SetTimer ( | |
| TimerToGetMap, | |
| TimerRelative, | |
| MultU64x32 (SecondsToNanoSeconds, 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 permanent | |
| // | |
| 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->Permanent == 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 permanent | |
| // | |
| 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->Permanent = 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_PERMANENT_STATUS), | |
| gShellNetwork1HiiHandle, | |
| (NicInfo->ConfigInfo->Permanent? 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 [permanent] | |
| // IfConfig -s eth0 static ip netmask gateway [permanent] | |
| // | |
| 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); | |
| } |