summaryrefslogtreecommitdiff
path: root/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
diff options
context:
space:
mode:
authorjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2011-03-25 20:47:02 +0000
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>2011-03-25 20:47:02 +0000
commit68fb05272b45b473fe030ac11dcb79d3f3c0aecd (patch)
tree8390e8e6f3ac6c3ff0bedd19a36cc92db93750d1 /ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
parent9586a3512789e7fe5e4b883a2591c6bd07ac863c (diff)
downloadedk2-platforms-68fb05272b45b473fe030ac11dcb79d3f3c0aecd.tar.xz
Add Network1 profile.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11423 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c')
-rw-r--r--ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c1746
1 files changed, 1746 insertions, 0 deletions
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.<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 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 <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);
+ 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);
+}