2011-03-25 21:47:02 +01:00
|
|
|
/** @file
|
|
|
|
The implementation for ifcommand shell command.
|
|
|
|
|
2015-02-04 23:25:01 +01:00
|
|
|
(C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
|
2015-06-30 05:18:31 +02:00
|
|
|
Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2011-04-05 22:55:45 +02:00
|
|
|
STATIC CONST UINTN SecondsToNanoSeconds = 10000000;
|
2011-03-25 21:47:02 +01:00
|
|
|
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.
|
2011-04-05 22:55:45 +02:00
|
|
|
@param[out] ChildHandle Returned child handle.
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
@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.
|
|
|
|
|
2011-09-02 10:05:34 +02:00
|
|
|
@param[in, out] String The pointer to the string to append onto.
|
2015-06-30 05:18:31 +02:00
|
|
|
@param[in] MaxLen The max number of UNICODE char in String
|
|
|
|
including the terminate NULL char.
|
2011-09-02 10:05:34 +02:00
|
|
|
@param[in] Offset Offset value.
|
|
|
|
@param[in] Width Width value.
|
|
|
|
@param[in] Block Point to data buffer.
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
@return The count of unicode character that were appended.
|
|
|
|
**/
|
|
|
|
UINTN
|
|
|
|
EFIAPI
|
|
|
|
AppendOffsetWidthValue (
|
|
|
|
IN OUT CHAR16 *String,
|
2015-06-30 05:18:31 +02:00
|
|
|
IN UINTN MaxLen,
|
2011-03-25 21:47:02 +01:00
|
|
|
IN UINTN Offset,
|
|
|
|
IN UINTN Width,
|
|
|
|
IN CONST UINT8 *Block
|
|
|
|
)
|
|
|
|
|
|
|
|
{
|
|
|
|
CHAR16 *OriString;
|
|
|
|
|
|
|
|
OriString = String;
|
|
|
|
|
2015-06-30 05:18:31 +02:00
|
|
|
StrnCpyS (String, MaxLen, L"&OFFSET=", 9);
|
2011-03-25 21:47:02 +01:00
|
|
|
String += StrLen (L"&OFFSET=");
|
|
|
|
String += UnicodeSPrint (String, 20, L"%x", Offset);
|
|
|
|
|
2015-06-30 05:18:31 +02:00
|
|
|
StrnCpyS (String, MaxLen, L"&WIDTH=", 8);
|
2011-03-25 21:47:02 +01:00
|
|
|
String += StrLen (L"&WIDTH=");
|
|
|
|
String += UnicodeSPrint (String, 20, L"%x", Width);
|
|
|
|
|
|
|
|
if (Block != NULL) {
|
2015-06-30 05:18:31 +02:00
|
|
|
StrnCpyS (String, MaxLen, L"&VALUE=", 8);
|
2011-03-25 21:47:02 +01:00
|
|
|
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;
|
2015-06-30 05:18:31 +02:00
|
|
|
UINTN ConfigHdrBufferSize;
|
2011-03-25 21:47:02 +01:00
|
|
|
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);
|
2015-06-30 05:18:31 +02:00
|
|
|
ConfigHdrBufferSize = (5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathLength * 2 + 1) * sizeof (CHAR16);
|
|
|
|
ConfigHdr = AllocateZeroPool (ConfigHdrBufferSize);
|
2011-03-25 21:47:02 +01:00
|
|
|
if (ConfigHdr == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
String = ConfigHdr;
|
2015-06-30 05:18:31 +02:00
|
|
|
StrnCpyS (String, ConfigHdrBufferSize/sizeof(CHAR16), L"GUID=", 6);
|
2011-03-25 21:47:02 +01:00
|
|
|
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="
|
|
|
|
//
|
2015-06-30 05:18:31 +02:00
|
|
|
StrnCpyS (String, ConfigHdrBufferSize/sizeof(CHAR16), L"&NAME=", 7);
|
2011-03-25 21:47:02 +01:00
|
|
|
String += StrLen (L"&NAME=");
|
|
|
|
for (Index = 0; Index < NameLength ; Index++) {
|
|
|
|
String += UnicodeSPrint (String, 10, L"00%x", Name[Index]);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Append L"&PATH="
|
|
|
|
//
|
2015-06-30 05:18:31 +02:00
|
|
|
StrnCpyS (String, ConfigHdrBufferSize/sizeof(CHAR16), L"&PATH=", 7);
|
2011-03-25 21:47:02 +01:00
|
|
|
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;
|
2015-06-30 05:18:31 +02:00
|
|
|
UINTN ConfigRespBufferSize;
|
2011-03-25 21:47:02 +01:00
|
|
|
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);
|
2011-03-30 21:33:03 +02:00
|
|
|
if (ConfigHdr != NULL) {
|
|
|
|
Length = StrLen (ConfigHdr);
|
|
|
|
} else {
|
|
|
|
Length = 0;
|
|
|
|
}
|
2015-06-30 05:18:31 +02:00
|
|
|
ConfigRespBufferSize = (Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16);
|
|
|
|
ConfigResp = AllocateZeroPool (ConfigRespBufferSize);
|
2011-03-25 21:47:02 +01:00
|
|
|
if (ConfigResp == NULL) {
|
|
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
|
|
goto ON_ERROR;
|
|
|
|
}
|
2011-03-30 21:33:03 +02:00
|
|
|
if (ConfigHdr != NULL) {
|
2015-06-30 05:18:31 +02:00
|
|
|
StrnCpyS (ConfigResp, ConfigRespBufferSize/sizeof(CHAR16), ConfigHdr, Length + NIC_ITEM_CONFIG_SIZE * 2 + 100 - 1);
|
2011-03-30 21:33:03 +02:00
|
|
|
}
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// Append OFFSET/WIDTH pair
|
|
|
|
//
|
|
|
|
String = ConfigResp + Length;
|
|
|
|
Offset = 0;
|
2015-06-30 05:18:31 +02:00
|
|
|
AppendOffsetWidthValue (String,
|
|
|
|
ConfigRespBufferSize/sizeof(CHAR16) - Length,
|
|
|
|
Offset,
|
|
|
|
NIC_ITEM_CONFIG_SIZE,
|
|
|
|
NULL
|
|
|
|
);
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
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;
|
2015-06-30 05:18:31 +02:00
|
|
|
UINTN ConfigRespBufferSize;
|
2011-03-25 21:47:02 +01:00
|
|
|
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);
|
2011-03-30 21:33:03 +02:00
|
|
|
if (ConfigHdr != NULL) {
|
|
|
|
Length = StrLen (ConfigHdr);
|
|
|
|
} else {
|
2011-04-02 00:16:01 +02:00
|
|
|
ShellStatus = SHELL_OUT_OF_RESOURCES;
|
|
|
|
goto ON_EXIT;
|
2011-03-30 21:33:03 +02:00
|
|
|
}
|
2015-06-30 05:18:31 +02:00
|
|
|
ConfigRespBufferSize = (Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16);
|
|
|
|
ConfigResp = AllocateZeroPool (ConfigRespBufferSize);
|
2011-04-02 00:16:01 +02:00
|
|
|
if (ConfigResp == NULL) {
|
|
|
|
ShellStatus = SHELL_OUT_OF_RESOURCES;
|
|
|
|
goto ON_EXIT;
|
|
|
|
}
|
2011-03-30 21:33:03 +02:00
|
|
|
if (ConfigHdr != NULL) {
|
2015-06-30 05:18:31 +02:00
|
|
|
StrnCpyS (ConfigResp, ConfigRespBufferSize/sizeof(CHAR16), ConfigHdr, Length + NIC_ITEM_CONFIG_SIZE * 2 + 100 - 1);
|
2011-03-30 21:33:03 +02:00
|
|
|
}
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
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;
|
2015-06-30 05:18:31 +02:00
|
|
|
AppendOffsetWidthValue (String,
|
|
|
|
ConfigRespBufferSize/sizeof(CHAR16) - Length,
|
|
|
|
Offset,
|
|
|
|
NIC_ITEM_CONFIG_SIZE,
|
|
|
|
NULL
|
|
|
|
);
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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 ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2012-10-17 10:23:41 +02:00
|
|
|
Create an IP child, use it to start the auto configuration, then destroy it.
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
@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,
|
2012-04-24 04:41:33 +02:00
|
|
|
TPL_CALLBACK,
|
2011-03-25 21:47:02 +01:00
|
|
|
TimeoutToGetMap,
|
|
|
|
NULL,
|
|
|
|
&TimerToGetMap
|
|
|
|
);
|
|
|
|
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
goto ON_EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = gBS->SetTimer (
|
|
|
|
TimerToGetMap,
|
|
|
|
TimerRelative,
|
2011-04-05 22:55:45 +02:00
|
|
|
MultU64x32 (SecondsToNanoSeconds, 5)
|
2011-03-25 21:47:02 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
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) {
|
|
|
|
//
|
2013-10-02 00:12:51 +02:00
|
|
|
// Validate the parameter for DHCP, two valid forms: eth0 DHCP and eth0 DHCP permanent
|
2011-03-25 21:47:02 +01:00
|
|
|
//
|
|
|
|
if ((Argc != 2) && (Argc!= 3)) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", Temp);
|
2011-03-25 21:47:02 +01:00
|
|
|
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) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, L"ifconfig", Temp, PermanentString, L"Nothing");
|
2011-03-25 21:47:02 +01:00
|
|
|
ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
|
|
|
|
goto ON_EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
Permanent = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((OldConfig != NULL) && (OldConfig->Source == IP4_CONFIG_SOURCE_DHCP) &&
|
2013-10-02 00:12:51 +02:00
|
|
|
(OldConfig->Permanent == Permanent)) {
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
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
|
2013-10-02 00:12:51 +02:00
|
|
|
// eth0 static IP NETMASK GATEWAY permanent
|
2011-03-25 21:47:02 +01:00
|
|
|
//
|
|
|
|
if ((Argc != 5) && (Argc != 6)) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", Temp);
|
2011-03-25 21:47:02 +01:00
|
|
|
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) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, L"ifconfig", Temp, PermanentString, L"Nothing");
|
2011-03-25 21:47:02 +01:00
|
|
|
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.
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ifconfig");
|
2011-03-25 21:47:02 +01:00
|
|
|
ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);
|
|
|
|
goto ON_EXIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyMem (&Config->NicAddr, &Info->NicAddress, sizeof (NIC_ADDR));
|
2013-10-04 17:38:38 +02:00
|
|
|
Config->Permanent = Permanent;
|
2011-03-25 21:47:02 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// 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,
|
2013-10-04 17:38:38 +02:00
|
|
|
STRING_TOKEN (STR_IFCONFIG_PERMANENT_STATUS),
|
2011-03-25 21:47:02 +01:00
|
|
|
gShellNetwork1HiiHandle,
|
2013-10-04 17:38:38 +02:00
|
|
|
(NicInfo->ConfigInfo->Permanent? L"TRUE":L"FALSE")
|
2011-03-25 21:47:02 +01:00
|
|
|
);
|
|
|
|
|
|
|
|
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) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam);
|
2011-03-25 21:47:02 +01:00
|
|
|
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");
|
|
|
|
|
2011-03-30 18:12:42 +02:00
|
|
|
if ((ClearOperation && ListOperation)
|
|
|
|
||(SetOperation && ListOperation)
|
|
|
|
||(ClearOperation && SetOperation)
|
2011-03-25 21:47:02 +01:00
|
|
|
) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig");
|
2011-03-25 21:47:02 +01:00
|
|
|
ShellStatus = SHELL_INVALID_PARAMETER;
|
|
|
|
goto Done;
|
|
|
|
} else if (!ClearOperation && !ListOperation && !SetOperation) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ifconfig");
|
2011-03-25 21:47:02 +01:00
|
|
|
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 {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellNetwork1HiiHandle, L"ifconfig", L"gEfiIp4ConfigProtocolGuid", &gEfiIp4ConfigProtocolGuid);
|
2011-03-25 21:47:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return SHELL_NOT_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ListOperation) {
|
|
|
|
Item = ShellCommandLineGetValue (Package, L"-l");
|
|
|
|
|
|
|
|
if (Item != NULL && CountSubItems(Item) > 1) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"ifconfig", Item, L"-l");
|
2011-03-25 21:47:02 +01:00
|
|
|
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:
|
2013-10-02 00:12:51 +02:00
|
|
|
// IfConfig -s eth0 DHCP [permanent]
|
|
|
|
// IfConfig -s eth0 static ip netmask gateway [permanent]
|
2011-03-25 21:47:02 +01:00
|
|
|
//
|
|
|
|
if (Item == NULL || (CountSubItems(Item) < 2) || (CountSubItems(Item) > 6) || (CountSubItems(Item) == 4)) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_NO_VALUE), gShellNetwork1HiiHandle, L"ifconfig", L"-s");
|
2011-03-25 21:47:02 +01:00
|
|
|
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) {
|
2015-02-03 22:27:55 +01:00
|
|
|
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"ifconfig", Item, L"-c");
|
2011-03-25 21:47:02 +01:00
|
|
|
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);
|
|
|
|
}
|