/** @file | |
Helper functions for configuring or getting the parameters relating to Ip4. | |
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "Ip4Impl.h" | |
CHAR16 mIp4Config2StorageName[] = L"IP4_CONFIG2_IFR_NVDATA"; | |
/** | |
Calculate the prefix length of the IPv4 subnet mask. | |
@param[in] SubnetMask The IPv4 subnet mask. | |
@return The prefix length of the subnet mask. | |
@retval 0 Other errors as indicated. | |
**/ | |
UINT8 | |
GetSubnetMaskPrefixLength ( | |
IN EFI_IPv4_ADDRESS *SubnetMask | |
) | |
{ | |
UINT8 Len; | |
UINT32 ReverseMask; | |
// | |
// The SubnetMask is in network byte order. | |
// | |
ReverseMask = SwapBytes32 (*(UINT32 *)&SubnetMask[0]); | |
// | |
// Reverse it. | |
// | |
ReverseMask = ~ReverseMask; | |
if ((ReverseMask & (ReverseMask + 1)) != 0) { | |
return 0; | |
} | |
Len = 0; | |
while (ReverseMask != 0) { | |
ReverseMask = ReverseMask >> 1; | |
Len++; | |
} | |
return (UINT8)(32 - Len); | |
} | |
/** | |
Convert the decimal dotted IPv4 address into the binary IPv4 address. | |
@param[in] Str The UNICODE string. | |
@param[out] Ip The storage to return the IPv4 address. | |
@retval EFI_SUCCESS The binary IP address is returned in Ip. | |
@retval EFI_INVALID_PARAMETER The IP string is malformatted. | |
**/ | |
EFI_STATUS | |
Ip4Config2StrToIp ( | |
IN CHAR16 *Str, | |
OUT EFI_IPv4_ADDRESS *Ip | |
) | |
{ | |
UINTN Index; | |
UINTN Number; | |
Index = 0; | |
while (*Str != L'\0') { | |
if (Index > 3) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Number = 0; | |
while ((*Str >= L'0') && (*Str <= L'9')) { | |
Number = Number * 10 + (*Str - L'0'); | |
Str++; | |
} | |
if (Number > 0xFF) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Ip->Addr[Index] = (UINT8)Number; | |
if ((*Str != L'\0') && (*Str != L'.')) { | |
// | |
// The current character should be either the NULL terminator or | |
// the dot delimiter. | |
// | |
return EFI_INVALID_PARAMETER; | |
} | |
if (*Str == L'.') { | |
// | |
// Skip the delimiter. | |
// | |
Str++; | |
} | |
Index++; | |
} | |
if (Index != 4) { | |
return EFI_INVALID_PARAMETER; | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Convert the decimal dotted IPv4 addresses separated by space into the binary IPv4 address list. | |
@param[in] Str The UNICODE string contains IPv4 addresses. | |
@param[out] PtrIpList The storage to return the IPv4 address list. | |
@param[out] IpCount The size of the IPv4 address list. | |
@retval EFI_SUCCESS The binary IP address list is returned in PtrIpList. | |
@retval EFI_OUT_OF_RESOURCES Error occurs in allocating memory. | |
@retval EFI_INVALID_PARAMETER The IP string is malformatted. | |
**/ | |
EFI_STATUS | |
Ip4Config2StrToIpList ( | |
IN CHAR16 *Str, | |
OUT EFI_IPv4_ADDRESS **PtrIpList, | |
OUT UINTN *IpCount | |
) | |
{ | |
UINTN BeginIndex; | |
UINTN EndIndex; | |
UINTN Index; | |
UINTN IpIndex; | |
CHAR16 *StrTemp; | |
BOOLEAN SpaceTag; | |
BeginIndex = 0; | |
EndIndex = BeginIndex; | |
Index = 0; | |
IpIndex = 0; | |
StrTemp = NULL; | |
SpaceTag = TRUE; | |
*PtrIpList = NULL; | |
*IpCount = 0; | |
if (Str == NULL) { | |
return EFI_SUCCESS; | |
} | |
// | |
// Get the number of Ip. | |
// | |
while (*(Str + Index) != L'\0') { | |
if (*(Str + Index) == L' ') { | |
SpaceTag = TRUE; | |
} else { | |
if (SpaceTag) { | |
(*IpCount)++; | |
SpaceTag = FALSE; | |
} | |
} | |
Index++; | |
} | |
if (*IpCount == 0) { | |
return EFI_SUCCESS; | |
} | |
// | |
// Allocate buffer for IpList. | |
// | |
*PtrIpList = AllocateZeroPool (*IpCount * sizeof (EFI_IPv4_ADDRESS)); | |
if (*PtrIpList == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// Get IpList from Str. | |
// | |
Index = 0; | |
while (*(Str + Index) != L'\0') { | |
if (*(Str + Index) == L' ') { | |
if (!SpaceTag) { | |
StrTemp = AllocateZeroPool ((EndIndex - BeginIndex + 1) * sizeof (CHAR16)); | |
if (StrTemp == NULL) { | |
FreePool (*PtrIpList); | |
*PtrIpList = NULL; | |
*IpCount = 0; | |
return EFI_OUT_OF_RESOURCES; | |
} | |
CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof (CHAR16)); | |
*(StrTemp + (EndIndex - BeginIndex)) = L'\0'; | |
if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) { | |
FreePool (StrTemp); | |
FreePool (*PtrIpList); | |
*PtrIpList = NULL; | |
*IpCount = 0; | |
return EFI_INVALID_PARAMETER; | |
} | |
BeginIndex = EndIndex; | |
IpIndex++; | |
FreePool (StrTemp); | |
} | |
BeginIndex++; | |
EndIndex++; | |
SpaceTag = TRUE; | |
} else { | |
EndIndex++; | |
SpaceTag = FALSE; | |
} | |
Index++; | |
if (*(Str + Index) == L'\0') { | |
if (!SpaceTag) { | |
StrTemp = AllocateZeroPool ((EndIndex - BeginIndex + 1) * sizeof (CHAR16)); | |
if (StrTemp == NULL) { | |
FreePool (*PtrIpList); | |
*PtrIpList = NULL; | |
*IpCount = 0; | |
return EFI_OUT_OF_RESOURCES; | |
} | |
CopyMem (StrTemp, Str + BeginIndex, (EndIndex - BeginIndex) * sizeof (CHAR16)); | |
*(StrTemp + (EndIndex - BeginIndex)) = L'\0'; | |
if (Ip4Config2StrToIp (StrTemp, &((*PtrIpList)[IpIndex])) != EFI_SUCCESS) { | |
FreePool (StrTemp); | |
FreePool (*PtrIpList); | |
*PtrIpList = NULL; | |
*IpCount = 0; | |
return EFI_INVALID_PARAMETER; | |
} | |
FreePool (StrTemp); | |
} | |
} | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Convert the IPv4 address into a dotted string. | |
@param[in] Ip The IPv4 address. | |
@param[out] Str The dotted IP string. | |
**/ | |
VOID | |
Ip4Config2IpToStr ( | |
IN EFI_IPv4_ADDRESS *Ip, | |
OUT CHAR16 *Str | |
) | |
{ | |
UnicodeSPrint ( | |
Str, | |
2 * IP4_STR_MAX_SIZE, | |
L"%d.%d.%d.%d", | |
Ip->Addr[0], | |
Ip->Addr[1], | |
Ip->Addr[2], | |
Ip->Addr[3] | |
); | |
} | |
/** | |
Convert the IPv4 address list into string consists of several decimal | |
dotted IPv4 addresses separated by space. | |
@param[in] Ip The IPv4 address list. | |
@param[in] IpCount The size of IPv4 address list. | |
@param[out] Str The string contains several decimal dotted | |
IPv4 addresses separated by space. | |
@retval EFI_SUCCESS Operation is success. | |
@retval EFI_OUT_OF_RESOURCES Error occurs in allocating memory. | |
**/ | |
EFI_STATUS | |
Ip4Config2IpListToStr ( | |
IN EFI_IPv4_ADDRESS *Ip, | |
IN UINTN IpCount, | |
OUT CHAR16 *Str | |
) | |
{ | |
UINTN Index; | |
UINTN TemIndex; | |
UINTN StrIndex; | |
CHAR16 *TempStr; | |
EFI_IPv4_ADDRESS *TempIp; | |
Index = 0; | |
TemIndex = 0; | |
StrIndex = 0; | |
TempStr = NULL; | |
TempIp = NULL; | |
for (Index = 0; Index < IpCount; Index++) { | |
TempIp = Ip + Index; | |
if (TempStr == NULL) { | |
TempStr = AllocateZeroPool (2 * IP4_STR_MAX_SIZE); | |
if (TempStr == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
} | |
UnicodeSPrint ( | |
TempStr, | |
2 * IP4_STR_MAX_SIZE, | |
L"%d.%d.%d.%d", | |
TempIp->Addr[0], | |
TempIp->Addr[1], | |
TempIp->Addr[2], | |
TempIp->Addr[3] | |
); | |
for (TemIndex = 0; TemIndex < IP4_STR_MAX_SIZE; TemIndex++) { | |
if (*(TempStr + TemIndex) == L'\0') { | |
if (Index == IpCount - 1) { | |
Str[StrIndex++] = L'\0'; | |
} else { | |
Str[StrIndex++] = L' '; | |
} | |
break; | |
} else { | |
Str[StrIndex++] = *(TempStr + TemIndex); | |
} | |
} | |
} | |
if (TempStr != NULL) { | |
FreePool (TempStr); | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
The notify function of create event when performing a manual configuration. | |
@param[in] Event The pointer of Event. | |
@param[in] Context The pointer of Context. | |
**/ | |
VOID | |
EFIAPI | |
Ip4Config2ManualAddressNotify ( | |
IN EFI_EVENT Event, | |
IN VOID *Context | |
) | |
{ | |
*((BOOLEAN *)Context) = TRUE; | |
} | |
/** | |
Convert the network configuration data into the IFR data. | |
@param[in] Instance The IP4 config2 instance. | |
@param[in, out] IfrNvData The IFR nv data. | |
@retval EFI_SUCCESS The configure parameter to IFR data was | |
set successfully. | |
@retval EFI_INVALID_PARAMETER Source instance or target IFR data is not available. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
Ip4Config2ConvertConfigNvDataToIfrNvData ( | |
IN IP4_CONFIG2_INSTANCE *Instance, | |
IN OUT IP4_CONFIG2_IFR_NVDATA *IfrNvData | |
) | |
{ | |
IP4_SERVICE *IpSb; | |
EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; | |
EFI_IP4_CONFIG2_INTERFACE_INFO *Ip4Info; | |
EFI_IP4_CONFIG2_POLICY Policy; | |
UINTN DataSize; | |
UINTN GatewaySize; | |
EFI_IPv4_ADDRESS GatewayAddress; | |
EFI_STATUS Status; | |
UINTN DnsSize; | |
UINTN DnsCount; | |
EFI_IPv4_ADDRESS *DnsAddress; | |
Status = EFI_SUCCESS; | |
Ip4Config2 = &Instance->Ip4Config2; | |
Ip4Info = NULL; | |
DnsAddress = NULL; | |
GatewaySize = sizeof (EFI_IPv4_ADDRESS); | |
if ((IfrNvData == NULL) || (Instance == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
NET_CHECK_SIGNATURE (Instance, IP4_CONFIG2_INSTANCE_SIGNATURE); | |
IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); | |
if (IpSb->DefaultInterface->Configured) { | |
IfrNvData->Configure = 1; | |
} else { | |
IfrNvData->Configure = 0; | |
goto Exit; | |
} | |
// | |
// Get the Policy info. | |
// | |
DataSize = sizeof (EFI_IP4_CONFIG2_POLICY); | |
Status = Ip4Config2->GetData ( | |
Ip4Config2, | |
Ip4Config2DataTypePolicy, | |
&DataSize, | |
&Policy | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
if (Policy == Ip4Config2PolicyStatic) { | |
IfrNvData->DhcpEnable = FALSE; | |
} else if (Policy == Ip4Config2PolicyDhcp) { | |
IfrNvData->DhcpEnable = TRUE; | |
goto Exit; | |
} | |
// | |
// Get the interface info. | |
// | |
DataSize = 0; | |
Status = Ip4Config2->GetData ( | |
Ip4Config2, | |
Ip4Config2DataTypeInterfaceInfo, | |
&DataSize, | |
NULL | |
); | |
if (Status != EFI_BUFFER_TOO_SMALL) { | |
return Status; | |
} | |
Ip4Info = AllocateZeroPool (DataSize); | |
if (Ip4Info == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
return Status; | |
} | |
Status = Ip4Config2->GetData ( | |
Ip4Config2, | |
Ip4Config2DataTypeInterfaceInfo, | |
&DataSize, | |
Ip4Info | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// Get the Gateway info. | |
// | |
Status = Ip4Config2->GetData ( | |
Ip4Config2, | |
Ip4Config2DataTypeGateway, | |
&GatewaySize, | |
&GatewayAddress | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// Get the Dns info. | |
// | |
DnsSize = 0; | |
Status = Ip4Config2->GetData ( | |
Ip4Config2, | |
Ip4Config2DataTypeDnsServer, | |
&DnsSize, | |
NULL | |
); | |
if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) { | |
goto Exit; | |
} | |
DnsCount = (UINT32)(DnsSize / sizeof (EFI_IPv4_ADDRESS)); | |
if (DnsSize > 0) { | |
DnsAddress = AllocateZeroPool (DnsSize); | |
if (DnsAddress == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Exit; | |
} | |
Status = Ip4Config2->GetData ( | |
Ip4Config2, | |
Ip4Config2DataTypeDnsServer, | |
&DnsSize, | |
DnsAddress | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
} | |
Ip4Config2IpToStr (&Ip4Info->StationAddress, IfrNvData->StationAddress); | |
Ip4Config2IpToStr (&Ip4Info->SubnetMask, IfrNvData->SubnetMask); | |
Ip4Config2IpToStr (&GatewayAddress, IfrNvData->GatewayAddress); | |
Status = Ip4Config2IpListToStr (DnsAddress, DnsCount, IfrNvData->DnsAddress); | |
Exit: | |
if (DnsAddress != NULL) { | |
FreePool (DnsAddress); | |
} | |
if (Ip4Info != NULL) { | |
FreePool (Ip4Info); | |
} | |
return Status; | |
} | |
/** | |
Convert the IFR data into the network configuration data and set the IP | |
configure parameters for the NIC. | |
@param[in] IfrFormNvData The IFR NV data. | |
@param[in, out] Instance The IP4 config2 instance. | |
@retval EFI_SUCCESS The configure parameter for this NIC was | |
set successfully. | |
@retval EFI_INVALID_PARAMETER The address information for setting is invalid. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
Ip4Config2ConvertIfrNvDataToConfigNvData ( | |
IN IP4_CONFIG2_IFR_NVDATA *IfrFormNvData, | |
IN OUT IP4_CONFIG2_INSTANCE *Instance | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2; | |
IP4_CONFIG2_NVDATA *Ip4NvData; | |
EFI_IP_ADDRESS StationAddress; | |
EFI_IP_ADDRESS SubnetMask; | |
EFI_IP_ADDRESS Gateway; | |
IP4_ADDR Ip; | |
EFI_IPv4_ADDRESS *DnsAddress; | |
UINTN DnsCount; | |
UINTN Index; | |
EFI_EVENT TimeoutEvent; | |
EFI_EVENT SetAddressEvent; | |
BOOLEAN IsAddressOk; | |
UINTN DataSize; | |
EFI_INPUT_KEY Key; | |
Status = EFI_SUCCESS; | |
Ip4Cfg2 = &Instance->Ip4Config2; | |
Ip4NvData = &Instance->Ip4NvData; | |
DnsCount = 0; | |
DnsAddress = NULL; | |
TimeoutEvent = NULL; | |
SetAddressEvent = NULL; | |
if ((Instance == NULL) || (IfrFormNvData == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (IfrFormNvData->Configure != TRUE) { | |
if (Ip4NvData->DnsAddress != NULL) { | |
FreePool (Ip4NvData->DnsAddress); | |
Ip4NvData->DnsAddress = NULL; | |
Ip4NvData->DnsAddressCount = 0; | |
} | |
if (Ip4NvData->GatewayAddress != NULL) { | |
FreePool (Ip4NvData->GatewayAddress); | |
Ip4NvData->GatewayAddress = NULL; | |
Ip4NvData->GatewayAddressCount = 0; | |
} | |
if (Ip4NvData->ManualAddress != NULL) { | |
FreePool (Ip4NvData->ManualAddress); | |
Ip4NvData->ManualAddress = NULL; | |
Ip4NvData->ManualAddressCount = 0; | |
} | |
Ip4NvData->Policy = Ip4Config2PolicyDhcp; | |
Status = Ip4Cfg2->SetData ( | |
Ip4Cfg2, | |
Ip4Config2DataTypePolicy, | |
sizeof (EFI_IP4_CONFIG2_POLICY), | |
&Ip4NvData->Policy | |
); | |
return EFI_SUCCESS; | |
} | |
if (IfrFormNvData->DhcpEnable == TRUE) { | |
Ip4NvData->Policy = Ip4Config2PolicyDhcp; | |
Status = Ip4Cfg2->SetData ( | |
Ip4Cfg2, | |
Ip4Config2DataTypePolicy, | |
sizeof (EFI_IP4_CONFIG2_POLICY), | |
&Ip4NvData->Policy | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
} else { | |
// | |
// Get Ip4NvData from IfrFormNvData if it is valid. | |
// | |
Ip4NvData->Policy = Ip4Config2PolicyStatic; | |
Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4); | |
if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) { | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL); | |
return EFI_INVALID_PARAMETER; | |
} | |
Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4); | |
if (EFI_ERROR (Status) || | |
((SubnetMask.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) || | |
!Ip4StationAddressValid (NTOHL (StationAddress.Addr[0]), NTOHL (SubnetMask.Addr[0]))) | |
{ | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL); | |
return EFI_INVALID_PARAMETER; | |
} | |
Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4); | |
if (EFI_ERROR (Status) || | |
((Gateway.Addr[0] != 0) && (SubnetMask.Addr[0] != 0) && !NetIp4IsUnicast (NTOHL (Gateway.Addr[0]), NTOHL (SubnetMask.Addr[0])))) | |
{ | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL); | |
return EFI_INVALID_PARAMETER; | |
} | |
Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount); | |
if (!EFI_ERROR (Status) && (DnsCount > 0)) { | |
for (Index = 0; Index < DnsCount; Index++) { | |
CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR)); | |
if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) { | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL); | |
FreePool (DnsAddress); | |
return EFI_INVALID_PARAMETER; | |
} | |
} | |
} else { | |
if (EFI_ERROR (Status)) { | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL); | |
} | |
} | |
if (Ip4NvData->ManualAddress != NULL) { | |
FreePool (Ip4NvData->ManualAddress); | |
} | |
Ip4NvData->ManualAddressCount = 1; | |
Ip4NvData->ManualAddress = AllocateZeroPool (sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)); | |
if (Ip4NvData->ManualAddress == NULL) { | |
if (DnsAddress != NULL) { | |
FreePool (DnsAddress); | |
} | |
return EFI_OUT_OF_RESOURCES; | |
} | |
CopyMem (&Ip4NvData->ManualAddress->Address, &StationAddress.v4, sizeof (EFI_IPv4_ADDRESS)); | |
CopyMem (&Ip4NvData->ManualAddress->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS)); | |
if (Ip4NvData->GatewayAddress != NULL) { | |
FreePool (Ip4NvData->GatewayAddress); | |
} | |
Ip4NvData->GatewayAddressCount = 1; | |
Ip4NvData->GatewayAddress = AllocateZeroPool (sizeof (EFI_IPv4_ADDRESS)); | |
if (Ip4NvData->GatewayAddress == NULL) { | |
if (DnsAddress != NULL) { | |
FreePool (DnsAddress); | |
} | |
return EFI_OUT_OF_RESOURCES; | |
} | |
CopyMem (Ip4NvData->GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS)); | |
if (Ip4NvData->DnsAddress != NULL) { | |
FreePool (Ip4NvData->DnsAddress); | |
} | |
Ip4NvData->DnsAddressCount = (UINT32)DnsCount; | |
Ip4NvData->DnsAddress = DnsAddress; | |
// | |
// Setting Ip4NvData. | |
// | |
Status = Ip4Cfg2->SetData ( | |
Ip4Cfg2, | |
Ip4Config2DataTypePolicy, | |
sizeof (EFI_IP4_CONFIG2_POLICY), | |
&Ip4NvData->Policy | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Create events & timers for asynchronous settings. | |
// | |
Status = gBS->CreateEvent ( | |
EVT_TIMER, | |
TPL_CALLBACK, | |
NULL, | |
NULL, | |
&TimeoutEvent | |
); | |
if (EFI_ERROR (Status)) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Status = gBS->CreateEvent ( | |
EVT_NOTIFY_SIGNAL, | |
TPL_NOTIFY, | |
Ip4Config2ManualAddressNotify, | |
&IsAddressOk, | |
&SetAddressEvent | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
IsAddressOk = FALSE; | |
Status = Ip4Cfg2->RegisterDataNotify ( | |
Ip4Cfg2, | |
Ip4Config2DataTypeManualAddress, | |
SetAddressEvent | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// Set ManualAddress. | |
// | |
DataSize = Ip4NvData->ManualAddressCount * sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS); | |
Status = Ip4Cfg2->SetData ( | |
Ip4Cfg2, | |
Ip4Config2DataTypeManualAddress, | |
DataSize, | |
(VOID *)Ip4NvData->ManualAddress | |
); | |
if (Status == EFI_NOT_READY) { | |
gBS->SetTimer (TimeoutEvent, TimerRelative, 50000000); | |
while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { | |
if (IsAddressOk) { | |
Status = EFI_SUCCESS; | |
break; | |
} | |
} | |
} | |
Ip4Cfg2->UnregisterDataNotify ( | |
Ip4Cfg2, | |
Ip4Config2DataTypeManualAddress, | |
SetAddressEvent | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// Set gateway. | |
// | |
DataSize = Ip4NvData->GatewayAddressCount * sizeof (EFI_IPv4_ADDRESS); | |
Status = Ip4Cfg2->SetData ( | |
Ip4Cfg2, | |
Ip4Config2DataTypeGateway, | |
DataSize, | |
Ip4NvData->GatewayAddress | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
// | |
// Set DNS addresses. | |
// | |
if ((Ip4NvData->DnsAddressCount > 0) && (Ip4NvData->DnsAddress != NULL)) { | |
DataSize = Ip4NvData->DnsAddressCount * sizeof (EFI_IPv4_ADDRESS); | |
Status = Ip4Cfg2->SetData ( | |
Ip4Cfg2, | |
Ip4Config2DataTypeDnsServer, | |
DataSize, | |
Ip4NvData->DnsAddress | |
); | |
if (EFI_ERROR (Status)) { | |
goto Exit; | |
} | |
} | |
} | |
Exit: | |
if (SetAddressEvent != NULL) { | |
gBS->CloseEvent (SetAddressEvent); | |
} | |
if (TimeoutEvent != NULL) { | |
gBS->CloseEvent (TimeoutEvent); | |
} | |
return Status; | |
} | |
/** | |
This function allows the caller to request the current | |
configuration for one or more named elements. The resulting | |
string is in <ConfigAltResp> format. Any and all alternative | |
configuration strings shall also be appended to the end of the | |
current configuration string. If they are, they must appear | |
after the current configuration. They must contain the same | |
routing (GUID, NAME, PATH) as the current configuration string. | |
They must have an additional description indicating the type of | |
alternative configuration the string represents, | |
"ALTCFG=<StringToken>". That <StringToken> (when | |
converted from Hex UNICODE to binary) is a reference to a | |
string in the associated string pack. | |
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
@param[in] Request A null-terminated Unicode string in | |
<ConfigRequest> format. Note that this | |
includes the routing information as well as | |
the configurable name / value pairs. It is | |
invalid for this string to be in | |
<MultiConfigRequest> format. | |
@param[out] Progress On return, points to a character in the | |
Request string. Points to the string's null | |
terminator if request was successful. Points | |
to the most recent "&" before the first | |
failing name / value pair (or the beginning | |
of the string if the failure is in the first | |
name / value pair) if the request was not | |
successful. | |
@param[out] Results A null-terminated Unicode string in | |
<ConfigAltResp> format which has all values | |
filled in for the names in the Request string. | |
String to be allocated by the called function. | |
@retval EFI_SUCCESS The Results string is filled with the | |
values corresponding to all requested | |
names. | |
@retval EFI_OUT_OF_RESOURCES Not enough memory to store the | |
parts of the results that must be | |
stored awaiting possible future | |
protocols. | |
@retval EFI_NOT_FOUND Routing data doesn't match any | |
known driver. Progress set to the | |
first character in the routing header. | |
Note: There is no requirement that the | |
driver validate the routing data. It | |
must skip the <ConfigHdr> in order to | |
process the names. | |
@retval EFI_INVALID_PARAMETER Illegal syntax. Progress set | |
to most recent & before the | |
error or the beginning of the | |
string. | |
@retval EFI_INVALID_PARAMETER Unknown name. Progress points | |
to the & before the name in | |
question.Currently not implemented. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Ip4FormExtractConfig ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN CONST EFI_STRING Request, | |
OUT EFI_STRING *Progress, | |
OUT EFI_STRING *Results | |
) | |
{ | |
EFI_STATUS Status; | |
IP4_CONFIG2_INSTANCE *Ip4Config2Instance; | |
IP4_FORM_CALLBACK_INFO *Private; | |
IP4_CONFIG2_IFR_NVDATA *IfrFormNvData; | |
EFI_STRING ConfigRequestHdr; | |
EFI_STRING ConfigRequest; | |
BOOLEAN AllocatedRequest; | |
EFI_STRING FormResult; | |
UINTN Size; | |
UINTN BufferSize; | |
if ((Progress == NULL) || (Results == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Status = EFI_SUCCESS; | |
IfrFormNvData = NULL; | |
ConfigRequest = NULL; | |
FormResult = NULL; | |
Size = 0; | |
AllocatedRequest = FALSE; | |
ConfigRequest = Request; | |
Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This); | |
Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private); | |
BufferSize = sizeof (IP4_CONFIG2_IFR_NVDATA); | |
*Progress = Request; | |
// | |
// Check Request data in <ConfigHdr>. | |
// | |
if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) { | |
IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA)); | |
if (IfrFormNvData == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Ip4Config2ConvertConfigNvDataToIfrNvData (Ip4Config2Instance, IfrFormNvData); | |
if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { | |
// | |
// Request has no request element, construct full request string. | |
// Allocate and fill a buffer large enough to hold the <ConfigHdr> template | |
// followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator | |
// | |
ConfigRequestHdr = HiiConstructConfigHdr (&gIp4Config2NvDataGuid, mIp4Config2StorageName, Private->ChildHandle); | |
Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); | |
ConfigRequest = AllocateZeroPool (Size); | |
if (ConfigRequest == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Failure; | |
} | |
AllocatedRequest = TRUE; | |
UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); | |
FreePool (ConfigRequestHdr); | |
} | |
// | |
// Convert buffer data to <ConfigResp> by helper function BlockToConfig() | |
// | |
Status = gHiiConfigRouting->BlockToConfig ( | |
gHiiConfigRouting, | |
ConfigRequest, | |
(UINT8 *)IfrFormNvData, | |
BufferSize, | |
&FormResult, | |
Progress | |
); | |
FreePool (IfrFormNvData); | |
// | |
// Free the allocated config request string. | |
// | |
if (AllocatedRequest) { | |
FreePool (ConfigRequest); | |
ConfigRequest = NULL; | |
} | |
if (EFI_ERROR (Status)) { | |
goto Failure; | |
} | |
} | |
if ((Request == NULL) || HiiIsConfigHdrMatch (Request, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) { | |
*Results = FormResult; | |
} else { | |
return EFI_NOT_FOUND; | |
} | |
Failure: | |
// | |
// Set Progress string to the original request string. | |
// | |
if (Request == NULL) { | |
*Progress = NULL; | |
} else if (StrStr (Request, L"OFFSET") == NULL) { | |
*Progress = Request + StrLen (Request); | |
} | |
return Status; | |
} | |
/** | |
This function applies changes in a driver's configuration. | |
Input is a Configuration, which has the routing data for this | |
driver followed by name / value configuration pairs. The driver | |
must apply those pairs to its configurable storage. If the | |
driver's configuration is stored in a linear block of data | |
and the driver's name / value pairs are in <BlockConfig> | |
format, it may use the ConfigToBlock helper function (above) to | |
simplify the job. Currently not implemented. | |
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
@param[in] Configuration A null-terminated Unicode string in | |
<ConfigString> format. | |
@param[out] Progress A pointer to a string filled in with the | |
offset of the most recent '&' before the | |
first failing name / value pair (or the | |
beginning of the string if the failure | |
is in the first name / value pair) or | |
the terminating NULL if all was | |
successful. | |
@retval EFI_SUCCESS The results have been distributed or are | |
awaiting distribution. | |
@retval EFI_OUT_OF_MEMORY Not enough memory to store the | |
parts of the results that must be | |
stored awaiting possible future | |
protocols. | |
@retval EFI_INVALID_PARAMETERS Passing in a NULL for the | |
Results parameter would result | |
in this type of error. | |
@retval EFI_NOT_FOUND Target for the specified routing data | |
was not found. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Ip4FormRouteConfig ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN CONST EFI_STRING Configuration, | |
OUT EFI_STRING *Progress | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN BufferSize; | |
IP4_CONFIG2_IFR_NVDATA *IfrFormNvData; | |
IP4_CONFIG2_INSTANCE *Ip4Config2Instance; | |
IP4_FORM_CALLBACK_INFO *Private; | |
Status = EFI_SUCCESS; | |
IfrFormNvData = NULL; | |
if ((Configuration == NULL) || (Progress == NULL)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
*Progress = Configuration; | |
Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This); | |
Ip4Config2Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private); | |
// | |
// Check Routing data in <ConfigHdr>. | |
// | |
if (HiiIsConfigHdrMatch (Configuration, &gIp4Config2NvDataGuid, mIp4Config2StorageName)) { | |
// | |
// Convert buffer data to <ConfigResp> by helper function BlockToConfig() | |
// | |
IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA)); | |
if (IfrFormNvData == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
BufferSize = 0; | |
Status = gHiiConfigRouting->ConfigToBlock ( | |
gHiiConfigRouting, | |
Configuration, | |
(UINT8 *)IfrFormNvData, | |
&BufferSize, | |
Progress | |
); | |
if (Status != EFI_BUFFER_TOO_SMALL) { | |
return Status; | |
} | |
Status = gHiiConfigRouting->ConfigToBlock ( | |
gHiiConfigRouting, | |
Configuration, | |
(UINT8 *)IfrFormNvData, | |
&BufferSize, | |
Progress | |
); | |
if (!EFI_ERROR (Status)) { | |
Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Ip4Config2Instance); | |
} | |
FreePool (IfrFormNvData); | |
} else { | |
return EFI_NOT_FOUND; | |
} | |
return Status; | |
} | |
/** | |
This function is called to provide results data to the driver. | |
This data consists of a unique key that is used to identify | |
which data is either being passed back or being asked for. | |
@param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. | |
@param[in] Action Specifies the type of action taken by the browser. | |
@param[in] QuestionId A unique value which is sent to the original | |
exporting driver so that it can identify the type | |
of data to expect. The format of the data tends to | |
vary based on the opcode that enerated the callback. | |
@param[in] Type The type of value for the question. | |
@param[in] Value A pointer to the data being sent to the original | |
exporting driver. | |
@param[out] ActionRequest On return, points to the action requested by the | |
callback function. | |
@retval EFI_SUCCESS The callback successfully handled the action. | |
@retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the | |
variable and its data. | |
@retval EFI_DEVICE_ERROR The variable could not be saved. | |
@retval EFI_UNSUPPORTED The specified Action is not supported by the | |
callback. Currently not implemented. | |
@retval EFI_INVALID_PARAMETERS Passing in wrong parameter. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
Ip4FormCallback ( | |
IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, | |
IN EFI_BROWSER_ACTION Action, | |
IN EFI_QUESTION_ID QuestionId, | |
IN UINT8 Type, | |
IN EFI_IFR_TYPE_VALUE *Value, | |
OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest | |
) | |
{ | |
EFI_STATUS Status; | |
IP4_CONFIG2_INSTANCE *Instance; | |
IP4_CONFIG2_IFR_NVDATA *IfrFormNvData; | |
IP4_FORM_CALLBACK_INFO *Private; | |
EFI_IP_ADDRESS StationAddress; | |
EFI_IP_ADDRESS SubnetMask; | |
EFI_IP_ADDRESS Gateway; | |
IP4_ADDR Ip; | |
EFI_IPv4_ADDRESS *DnsAddress; | |
UINTN DnsCount; | |
UINTN Index; | |
EFI_INPUT_KEY Key; | |
IfrFormNvData = NULL; | |
DnsCount = 0; | |
DnsAddress = NULL; | |
if (Action == EFI_BROWSER_ACTION_CHANGED) { | |
Private = IP4_FORM_CALLBACK_INFO_FROM_CONFIG_ACCESS (This); | |
Instance = IP4_CONFIG2_INSTANCE_FROM_FORM_CALLBACK (Private); | |
IfrFormNvData = AllocateZeroPool (sizeof (IP4_CONFIG2_IFR_NVDATA)); | |
if (IfrFormNvData == NULL) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
// | |
// Retrieve uncommitted data from Browser | |
// | |
if (!HiiGetBrowserData (&gIp4Config2NvDataGuid, mIp4Config2StorageName, sizeof (IP4_CONFIG2_IFR_NVDATA), (UINT8 *)IfrFormNvData)) { | |
FreePool (IfrFormNvData); | |
return EFI_NOT_FOUND; | |
} | |
Status = EFI_SUCCESS; | |
switch (QuestionId) { | |
case KEY_LOCAL_IP: | |
Status = Ip4Config2StrToIp (IfrFormNvData->StationAddress, &StationAddress.v4); | |
if (EFI_ERROR (Status) || IP4_IS_UNSPECIFIED (NTOHL (StationAddress.Addr[0])) || IP4_IS_LOCAL_BROADCAST (NTOHL (StationAddress.Addr[0]))) { | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid IP address!", NULL); | |
Status = EFI_INVALID_PARAMETER; | |
} | |
break; | |
case KEY_SUBNET_MASK: | |
Status = Ip4Config2StrToIp (IfrFormNvData->SubnetMask, &SubnetMask.v4); | |
if (EFI_ERROR (Status) || ((SubnetMask.Addr[0] != 0) && (GetSubnetMaskPrefixLength (&SubnetMask.v4) == 0))) { | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Subnet Mask!", NULL); | |
Status = EFI_INVALID_PARAMETER; | |
} | |
break; | |
case KEY_GATE_WAY: | |
Status = Ip4Config2StrToIp (IfrFormNvData->GatewayAddress, &Gateway.v4); | |
if (EFI_ERROR (Status) || IP4_IS_LOCAL_BROADCAST (NTOHL (Gateway.Addr[0]))) { | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Gateway!", NULL); | |
Status = EFI_INVALID_PARAMETER; | |
} | |
break; | |
case KEY_DNS: | |
Status = Ip4Config2StrToIpList (IfrFormNvData->DnsAddress, &DnsAddress, &DnsCount); | |
if (!EFI_ERROR (Status) && (DnsCount > 0)) { | |
for (Index = 0; Index < DnsCount; Index++) { | |
CopyMem (&Ip, &DnsAddress[Index], sizeof (IP4_ADDR)); | |
if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) { | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL); | |
Status = EFI_INVALID_PARAMETER; | |
break; | |
} | |
} | |
} else { | |
if (EFI_ERROR (Status)) { | |
CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Invalid Dns Server!", NULL); | |
} | |
} | |
if (DnsAddress != NULL) { | |
FreePool (DnsAddress); | |
} | |
break; | |
case KEY_SAVE_CHANGES: | |
Status = Ip4Config2ConvertIfrNvDataToConfigNvData (IfrFormNvData, Instance); | |
*ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; | |
break; | |
default: | |
break; | |
} | |
FreePool (IfrFormNvData); | |
return Status; | |
} | |
// | |
// All other action return unsupported. | |
// | |
return EFI_UNSUPPORTED; | |
} | |
/** | |
Install HII Config Access protocol for network device and allocate resource. | |
@param[in, out] Instance The IP4 config2 Instance. | |
@retval EFI_SUCCESS The HII Config Access protocol is installed. | |
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory. | |
@retval Others Other errors as indicated. | |
**/ | |
EFI_STATUS | |
Ip4Config2FormInit ( | |
IN OUT IP4_CONFIG2_INSTANCE *Instance | |
) | |
{ | |
EFI_STATUS Status; | |
IP4_SERVICE *IpSb; | |
IP4_FORM_CALLBACK_INFO *CallbackInfo; | |
EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; | |
VENDOR_DEVICE_PATH VendorDeviceNode; | |
EFI_SERVICE_BINDING_PROTOCOL *MnpSb; | |
CHAR16 *MacString; | |
CHAR16 MenuString[128]; | |
CHAR16 PortString[128]; | |
CHAR16 *OldMenuString; | |
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; | |
IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); | |
ASSERT (IpSb != NULL); | |
CallbackInfo = &Instance->CallbackInfo; | |
CallbackInfo->Signature = IP4_FORM_CALLBACK_INFO_SIGNATURE; | |
Status = gBS->HandleProtocol ( | |
IpSb->Controller, | |
&gEfiDevicePathProtocolGuid, | |
(VOID **)&ParentDevicePath | |
); | |
if (EFI_ERROR (Status)) { | |
return Status; | |
} | |
// | |
// Construct device path node for EFI HII Config Access protocol, | |
// which consists of controller physical device path and one hardware | |
// vendor guid node. | |
// | |
ZeroMem (&VendorDeviceNode, sizeof (VENDOR_DEVICE_PATH)); | |
VendorDeviceNode.Header.Type = HARDWARE_DEVICE_PATH; | |
VendorDeviceNode.Header.SubType = HW_VENDOR_DP; | |
CopyGuid (&VendorDeviceNode.Guid, &gEfiCallerIdGuid); | |
SetDevicePathNodeLength (&VendorDeviceNode.Header, sizeof (VENDOR_DEVICE_PATH)); | |
CallbackInfo->HiiVendorDevicePath = AppendDevicePathNode ( | |
ParentDevicePath, | |
(EFI_DEVICE_PATH_PROTOCOL *)&VendorDeviceNode | |
); | |
if (CallbackInfo->HiiVendorDevicePath == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Error; | |
} | |
ConfigAccess = &CallbackInfo->HiiConfigAccessProtocol; | |
ConfigAccess->ExtractConfig = Ip4FormExtractConfig; | |
ConfigAccess->RouteConfig = Ip4FormRouteConfig; | |
ConfigAccess->Callback = Ip4FormCallback; | |
// | |
// Install Device Path Protocol and Config Access protocol on new handle | |
// | |
Status = gBS->InstallMultipleProtocolInterfaces ( | |
&CallbackInfo->ChildHandle, | |
&gEfiDevicePathProtocolGuid, | |
CallbackInfo->HiiVendorDevicePath, | |
&gEfiHiiConfigAccessProtocolGuid, | |
ConfigAccess, | |
NULL | |
); | |
if (!EFI_ERROR (Status)) { | |
// | |
// Open the Parent Handle for the child | |
// | |
Status = gBS->OpenProtocol ( | |
IpSb->Controller, | |
&gEfiManagedNetworkServiceBindingProtocolGuid, | |
(VOID **)&MnpSb, | |
IpSb->Image, | |
CallbackInfo->ChildHandle, | |
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER | |
); | |
} | |
if (EFI_ERROR (Status)) { | |
goto Error; | |
} | |
// | |
// Publish our HII data | |
// | |
CallbackInfo->RegisteredHandle = HiiAddPackages ( | |
&gIp4Config2NvDataGuid, | |
CallbackInfo->ChildHandle, | |
Ip4DxeStrings, | |
Ip4Config2Bin, | |
NULL | |
); | |
if (CallbackInfo->RegisteredHandle == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Error; | |
} | |
// | |
// Append MAC string in the menu help string and tile help string | |
// | |
Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &MacString); | |
if (!EFI_ERROR (Status)) { | |
OldMenuString = HiiGetString ( | |
CallbackInfo->RegisteredHandle, | |
STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP), | |
NULL | |
); | |
UnicodeSPrint (MenuString, 128, L"%s (MAC:%s)", OldMenuString, MacString); | |
HiiSetString ( | |
CallbackInfo->RegisteredHandle, | |
STRING_TOKEN (STR_IP4_CONFIG2_FORM_HELP), | |
MenuString, | |
NULL | |
); | |
UnicodeSPrint (PortString, 128, L"MAC:%s", MacString); | |
HiiSetString ( | |
CallbackInfo->RegisteredHandle, | |
STRING_TOKEN (STR_IP4_DEVICE_FORM_HELP), | |
PortString, | |
NULL | |
); | |
FreePool (MacString); | |
FreePool (OldMenuString); | |
return EFI_SUCCESS; | |
} | |
Error: | |
Ip4Config2FormUnload (Instance); | |
return Status; | |
} | |
/** | |
Uninstall the HII Config Access protocol for network devices and free up the resources. | |
@param[in, out] Instance The IP4 config2 instance to unload a form. | |
**/ | |
VOID | |
Ip4Config2FormUnload ( | |
IN OUT IP4_CONFIG2_INSTANCE *Instance | |
) | |
{ | |
IP4_SERVICE *IpSb; | |
IP4_FORM_CALLBACK_INFO *CallbackInfo; | |
IP4_CONFIG2_NVDATA *Ip4NvData; | |
IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance); | |
ASSERT (IpSb != NULL); | |
CallbackInfo = &Instance->CallbackInfo; | |
if (CallbackInfo->ChildHandle != NULL) { | |
// | |
// Close the child handle | |
// | |
gBS->CloseProtocol ( | |
IpSb->Controller, | |
&gEfiManagedNetworkServiceBindingProtocolGuid, | |
IpSb->Image, | |
CallbackInfo->ChildHandle | |
); | |
// | |
// Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL | |
// | |
gBS->UninstallMultipleProtocolInterfaces ( | |
CallbackInfo->ChildHandle, | |
&gEfiDevicePathProtocolGuid, | |
CallbackInfo->HiiVendorDevicePath, | |
&gEfiHiiConfigAccessProtocolGuid, | |
&CallbackInfo->HiiConfigAccessProtocol, | |
NULL | |
); | |
} | |
if (CallbackInfo->HiiVendorDevicePath != NULL) { | |
FreePool (CallbackInfo->HiiVendorDevicePath); | |
} | |
if (CallbackInfo->RegisteredHandle != NULL) { | |
// | |
// Remove HII package list | |
// | |
HiiRemovePackages (CallbackInfo->RegisteredHandle); | |
} | |
Ip4NvData = &Instance->Ip4NvData; | |
if (Ip4NvData->ManualAddress != NULL) { | |
FreePool (Ip4NvData->ManualAddress); | |
} | |
if (Ip4NvData->GatewayAddress != NULL) { | |
FreePool (Ip4NvData->GatewayAddress); | |
} | |
if (Ip4NvData->DnsAddress != NULL) { | |
FreePool (Ip4NvData->DnsAddress); | |
} | |
Ip4NvData->ManualAddressCount = 0; | |
Ip4NvData->GatewayAddressCount = 0; | |
Ip4NvData->DnsAddressCount = 0; | |
} |